Merge branch 'master' into ui
This commit is contained in:
commit
d579819946
27
API.md
27
API.md
@ -1,25 +1,20 @@
|
|||||||
## API
|
# API
|
||||||
|
|
||||||
Get current database tables:
|
Current endpoint:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
GET /info
|
||||||
GET /tables
|
GET /tables
|
||||||
|
GET /tables/:table
|
||||||
|
GET /tables/:table/indexes
|
||||||
|
GET /query
|
||||||
|
POST /query
|
||||||
|
GET /explain
|
||||||
|
POST /explain
|
||||||
|
GET /history
|
||||||
```
|
```
|
||||||
|
|
||||||
Get table details:
|
# Query Response
|
||||||
|
|
||||||
```
|
|
||||||
GET /tables/:name
|
|
||||||
```
|
|
||||||
|
|
||||||
Execute select query:
|
|
||||||
|
|
||||||
```
|
|
||||||
POST /select?query=SQL
|
|
||||||
GET /select?query=SQL
|
|
||||||
```
|
|
||||||
|
|
||||||
### Response formats
|
|
||||||
|
|
||||||
Successful response:
|
Successful response:
|
||||||
|
|
||||||
|
24
api.go
24
api.go
@ -22,6 +22,17 @@ func API_RunQuery(c *gin.Context) {
|
|||||||
API_HandleQuery(query, c)
|
API_HandleQuery(query, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func API_ExplainQuery(c *gin.Context) {
|
||||||
|
query := strings.TrimSpace(c.Request.FormValue("query"))
|
||||||
|
|
||||||
|
if query == "" {
|
||||||
|
c.JSON(400, errors.New("Query parameter is missing"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
API_HandleQuery(fmt.Sprintf("EXPLAIN %s", query), c)
|
||||||
|
}
|
||||||
|
|
||||||
func API_GetTables(c *gin.Context) {
|
func API_GetTables(c *gin.Context) {
|
||||||
names, err := dbClient.Tables()
|
names, err := dbClient.Tables()
|
||||||
|
|
||||||
@ -34,7 +45,7 @@ func API_GetTables(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func API_GetTable(c *gin.Context) {
|
func API_GetTable(c *gin.Context) {
|
||||||
res, err := dbClient.Query(fmt.Sprintf(SQL_TABLE_SCHEMA, c.Params.ByName("name")))
|
res, err := dbClient.Query(fmt.Sprintf(SQL_TABLE_SCHEMA, c.Params.ByName("table")))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(400, NewError(err))
|
c.JSON(400, NewError(err))
|
||||||
@ -59,6 +70,17 @@ func API_Info(c *gin.Context) {
|
|||||||
c.JSON(200, res.Format()[0])
|
c.JSON(200, res.Format()[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func API_TableIndexes(c *gin.Context) {
|
||||||
|
res, err := dbClient.TableIndexes(c.Params.ByName("table"))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(400, NewError(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(200, res)
|
||||||
|
}
|
||||||
|
|
||||||
func API_HandleQuery(query string, c *gin.Context) {
|
func API_HandleQuery(query string, c *gin.Context) {
|
||||||
result, err := dbClient.Query(query)
|
result, err := dbClient.Query(query)
|
||||||
|
|
||||||
|
15
client.go
15
client.go
@ -12,6 +12,7 @@ const (
|
|||||||
SQL_INFO = "SELECT version(), user, current_database(), inet_client_addr(), inet_client_port(), inet_server_addr(), inet_server_port()"
|
SQL_INFO = "SELECT version(), user, current_database(), inet_client_addr(), inet_client_port(), inet_server_addr(), inet_server_port()"
|
||||||
SQL_TABLES = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_schema,table_name;"
|
SQL_TABLES = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_schema,table_name;"
|
||||||
SQL_TABLE_SCHEMA = "SELECT column_name, data_type, is_nullable, character_maximum_length, character_set_catalog, column_default FROM information_schema.columns where table_name = '%s';"
|
SQL_TABLE_SCHEMA = "SELECT column_name, data_type, is_nullable, character_maximum_length, character_set_catalog, column_default FROM information_schema.columns where table_name = '%s';"
|
||||||
|
SQL_TABLE_INDEXES = "SELECT indexname, indexdef FROM pg_indexes WHERE tablename = '%s';"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
@ -38,6 +39,10 @@ func NewClient() (*Client, error) {
|
|||||||
return &Client{db: db}, nil
|
return &Client{db: db}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *Client) Test() error {
|
||||||
|
return client.db.Ping()
|
||||||
|
}
|
||||||
|
|
||||||
func (client *Client) recordQuery(query string) {
|
func (client *Client) recordQuery(query string) {
|
||||||
client.history = append(client.history, query)
|
client.history = append(client.history, query)
|
||||||
}
|
}
|
||||||
@ -58,6 +63,16 @@ func (client *Client) Tables() ([]string, error) {
|
|||||||
return tables, nil
|
return tables, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *Client) TableIndexes(table string) (*Result, error) {
|
||||||
|
res, err := client.Query(fmt.Sprintf(SQL_TABLE_INDEXES, table))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
func (client *Client) Query(query string) (*Result, error) {
|
func (client *Client) Query(query string) (*Result, error) {
|
||||||
rows, err := client.db.Queryx(query)
|
rows, err := client.db.Queryx(query)
|
||||||
|
|
||||||
|
39
main.go
39
main.go
@ -10,16 +10,21 @@ import (
|
|||||||
|
|
||||||
var options struct {
|
var options struct {
|
||||||
Url string `long:"url" description:"Database connection string"`
|
Url string `long:"url" description:"Database connection string"`
|
||||||
Host string `short:"h" long:"host" description:"Server hostname or IP" default:"localhost"`
|
Host string `long:"host" description:"Server hostname or IP" default:"localhost"`
|
||||||
Port int `short:"p" long:"port" description:"Server port" default:"5432"`
|
Port int `long:"port" description:"Server port" default:"5432"`
|
||||||
User string `short:"u" long:"user" description:"Database user" default:"postgres"`
|
User string `long:"user" description:"Database user" default:"postgres"`
|
||||||
DbName string `short:"d" long:"db" description:"Database name" default:"postgres"`
|
DbName string `long:"db" description:"Database name" default:"postgres"`
|
||||||
Ssl string `long:"ssl" description:"SSL option" default:"disable"`
|
Ssl string `long:"ssl" description:"SSL option" default:"disable"`
|
||||||
Static string `short:"s" description:"Path to static assets" default:"./static"`
|
Static string `short:"s" description:"Path to static assets" default:"./static"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var dbClient *Client
|
var dbClient *Client
|
||||||
|
|
||||||
|
func exitWithMessage(message string) {
|
||||||
|
fmt.Println("Error:", message)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
func getConnectionString() string {
|
func getConnectionString() string {
|
||||||
if options.Url != "" {
|
if options.Url != "" {
|
||||||
return options.Url
|
return options.Url
|
||||||
@ -34,17 +39,24 @@ func getConnectionString() string {
|
|||||||
|
|
||||||
func initClient() {
|
func initClient() {
|
||||||
client, err := NewClient()
|
client, err := NewClient()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error:", err)
|
exitWithMessage(err.Error())
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = client.Query(SQL_INFO)
|
fmt.Println("Connecting to server...")
|
||||||
|
err = client.Test()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error:", err)
|
exitWithMessage(err.Error())
|
||||||
os.Exit(1)
|
}
|
||||||
|
|
||||||
|
fmt.Println("Checking tables...")
|
||||||
|
tables, err := client.Tables()
|
||||||
|
if err != nil {
|
||||||
|
exitWithMessage(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(tables) == 0 {
|
||||||
|
exitWithMessage("Database does not have any tables")
|
||||||
}
|
}
|
||||||
|
|
||||||
dbClient = client
|
dbClient = client
|
||||||
@ -68,9 +80,12 @@ func main() {
|
|||||||
|
|
||||||
router.GET("/info", API_Info)
|
router.GET("/info", API_Info)
|
||||||
router.GET("/tables", API_GetTables)
|
router.GET("/tables", API_GetTables)
|
||||||
router.GET("/tables/:name", API_GetTable)
|
router.GET("/tables/:table", API_GetTable)
|
||||||
|
router.GET("/tables/:table/indexes", API_TableIndexes)
|
||||||
router.GET("/query", API_RunQuery)
|
router.GET("/query", API_RunQuery)
|
||||||
router.POST("/query", API_RunQuery)
|
router.POST("/query", API_RunQuery)
|
||||||
|
router.GET("/explain", API_ExplainQuery)
|
||||||
|
router.POST("/explain", API_ExplainQuery)
|
||||||
router.GET("/history", API_History)
|
router.GET("/history", API_History)
|
||||||
router.Static("/app", options.Static)
|
router.Static("/app", options.Static)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user