Merge branch 'master' into ui

This commit is contained in:
Dan Sosedoff 2014-10-11 22:39:27 -05:00
commit d579819946
4 changed files with 80 additions and 33 deletions

29
API.md
View File

@ -1,25 +1,20 @@
## API
# API
Get current database tables:
Current endpoint:
```
GET /tables
GET /info
GET /tables
GET /tables/:table
GET /tables/:table/indexes
GET /query
POST /query
GET /explain
POST /explain
GET /history
```
Get table details:
```
GET /tables/:name
```
Execute select query:
```
POST /select?query=SQL
GET /select?query=SQL
```
### Response formats
# Query Response
Successful response:

24
api.go
View File

@ -22,6 +22,17 @@ func API_RunQuery(c *gin.Context) {
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) {
names, err := dbClient.Tables()
@ -34,7 +45,7 @@ func API_GetTables(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 {
c.JSON(400, NewError(err))
@ -59,6 +70,17 @@ func API_Info(c *gin.Context) {
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) {
result, err := dbClient.Query(query)

View File

@ -9,9 +9,10 @@ import (
)
const (
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_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_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_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 {
@ -38,6 +39,10 @@ func NewClient() (*Client, error) {
return &Client{db: db}, nil
}
func (client *Client) Test() error {
return client.db.Ping()
}
func (client *Client) recordQuery(query string) {
client.history = append(client.history, query)
}
@ -58,6 +63,16 @@ func (client *Client) Tables() ([]string, error) {
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) {
rows, err := client.db.Queryx(query)

39
main.go
View File

@ -10,16 +10,21 @@ import (
var options struct {
Url string `long:"url" description:"Database connection string"`
Host string `short:"h" long:"host" description:"Server hostname or IP" default:"localhost"`
Port int `short:"p" long:"port" description:"Server port" default:"5432"`
User string `short:"u" long:"user" description:"Database user" default:"postgres"`
DbName string `short:"d" long:"db" description:"Database name" default:"postgres"`
Host string `long:"host" description:"Server hostname or IP" default:"localhost"`
Port int `long:"port" description:"Server port" default:"5432"`
User string `long:"user" description:"Database user" default:"postgres"`
DbName string `long:"db" description:"Database name" default:"postgres"`
Ssl string `long:"ssl" description:"SSL option" default:"disable"`
Static string `short:"s" description:"Path to static assets" default:"./static"`
}
var dbClient *Client
func exitWithMessage(message string) {
fmt.Println("Error:", message)
os.Exit(1)
}
func getConnectionString() string {
if options.Url != "" {
return options.Url
@ -34,17 +39,24 @@ func getConnectionString() string {
func initClient() {
client, err := NewClient()
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
exitWithMessage(err.Error())
}
_, err = client.Query(SQL_INFO)
fmt.Println("Connecting to server...")
err = client.Test()
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
exitWithMessage(err.Error())
}
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
@ -68,9 +80,12 @@ func main() {
router.GET("/info", API_Info)
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.POST("/query", API_RunQuery)
router.GET("/explain", API_ExplainQuery)
router.POST("/explain", API_ExplainQuery)
router.GET("/history", API_History)
router.Static("/app", options.Static)