Skip to content

Commit

Permalink
0.1.1 release
Browse files Browse the repository at this point in the history
  • Loading branch information
Crystal Qian committed Jul 1, 2015
1 parent be727ea commit 1191400
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 65 deletions.
129 changes: 129 additions & 0 deletions README.md
Expand Up @@ -10,3 +10,132 @@ Modules:

1. structs: currently hardcoded details on each table in the to_development database. Need to write a script to dynamically generate this file.
2. sqlToJson: two methods in this, one to return rows from a sql database, another to make a json byte array from a dict of rows. Not sure if I should just combine into one method.

#GoTo (Golang Traffic Ops)

GoTo is a web API that returns JSON formatting for SQL database tables (specifically, the Comcast [Traffic Ops](http://traffic-control-cdn.net/docs/latest/development/traffic_ops.html) database).

## Releases
* 0.2.0 (Upcoming)
* Clean up output JSON formatting and object naming
* Generate struct handler with OK/404 for URLs (should solve .favicon issue)
* Return JSON format via curl, displayed as .json output in browser
* 0.1.1 (7/1/2015)
Documentation is updated and code is cleaned up.
* [0.1.0](https://github.com/cjqian/jsonserver/commit/be727ea8bb4597126c3171d9f809a0437833b9a5) (6/30/2015)
Basic packages are sketched out and incorporated with the main server; everything
works, kind of. See the demo [here.](https://www.dropbox.com/s/7u48ihlxkuytmxn/demo_presentation.pdf?dl=0)

## Known Issues
* Favicon.ico responses are breaking the program.
* Inaccurate JSON formatting.

## Packages
### Main.go

This is the main Go program that starts the web service and listens for requests.

Requests are in the form:
```go
url/[table_in_database]
//for example,
http://localhost:8000/deliveryservice
```

Which will return the JSON for the "deliveryservice" table in the database.

The program takes in three parameters: the username, password and database.

To build/run:
```go
go build main.go
./main [username] [password] [database]
```

### SQL Parser

This package (sqlParser) contains the following public methods for i
interacting with the database. Also, I'm using the [SQLX library](http://jmoiron.github.io/sqlx/).

```go
// connects to and returns a pointer to the database
func ConnectToDatabase(username string, password string, environment string) sqlx.DB;

//returns an array of table name strings from queried database
func GetTableNames(db sqlx.DB) []string;

//returns *Rows from given table (name) from queried database
func GetRows(db sqlx.DB, tableName string) *sqlx.Rows;

//returns array of column names from table (name) in database
func GetColumnNames(db sqlx.DB, tableName string) []string;
```

### Struct Constructor

This package (structConstructor) contructs the following package (see Structs)
by generating three .go files. Main.go runs the construction whenever the server is started.

```go
//writes struct, interface, and map files to structs package
func MakeStructFiles(db sqlx.DB);

//writes the struct file, which has an object for each database table,
//with each table field as a member variable
func MakeStructs(db sqlx.DB);

//writes structInterface.go, which has functions that take in *Rows and
//return the byte array JSON format for each table in the database
func MakeStructInterface(db sqlx.DB);

//writes structMap.go, which has one function that maps each tableName string
//to its respective function in structInterface.go`
func MakeStructMap(db sqlx.DB);

//writes string str to fileName, helper function for the above three
func WriteFile(str string, fileName string);
```

### Structs

This package (structs) is dynamically generated on server start from Struct Constructor (see above).
There are three files:
* structs.go
```go
type [TableName] struct{
[Table Field] [Field Type]
...
}
```

* structInterface.go
```go
func ByteArrayFrom[Table Name](rows *sqlx.Rows) []byte{
var tStr []byte

//creates a new [Table Name] object (defined in Structs) and scans
//contents of given rows into its fields. appends the JSON
//representation to a tStr byte array representing the entire table
t := [Table Name]{}
for rows.Next() {
rows.StructScan(&t)
tmpStr, _ := json.MarshalIndent(t, "", " ")
tStr = append(tStr[:], tmpStr[:]...)
}

return tStr
}
```

* structMap.go
```go
func MapTableToJson(tableName string, rows *sqlx.Rows) []byte{
if tableName == [Table Name]{
tStr := ByteArrayFromAsn(row)
return tStr
}
...
}
```


49 changes: 0 additions & 49 deletions jsonFormatter/jsonFormatter.go

This file was deleted.

9 changes: 4 additions & 5 deletions main.go
@@ -1,6 +1,6 @@
//takes in username, password, and database
//currently prints each instance in table to commnand line as
//json struct
//main.go
//takes in username, password, and database arguments
//runs server that handles url table searches

package main

Expand Down Expand Up @@ -28,7 +28,6 @@ var (
//prints JSON of argument table name in database
func generateHandler(w http.ResponseWriter, r *http.Request) {
tableName := r.URL.Path[len("/"):]
// tableName := "deliveryservice"
fmt.Print(tableName)
rows := sqlParser.GetRows(db, tableName)
fmt.Printf("%s", structs.MapTableToJson(tableName, rows))
Expand All @@ -39,7 +38,6 @@ func main() {
structConstructor.MakeStructFiles(db)

flag.Parse()

http.HandleFunc("/", generateHandler)

if *addr {
Expand All @@ -56,5 +54,6 @@ func main() {
s.Serve(l)
return
}

http.ListenAndServe(":8080", nil)
}
6 changes: 3 additions & 3 deletions sqlParser/sqlParser.go
Expand Up @@ -11,14 +11,15 @@ func check(e error) {
}
}

//connects to and returns a pointer to the database
func ConnectToDatabase(username string, password string, environment string) sqlx.DB {
db, err := sqlx.Open("mysql", username+":"+password+"@tcp(localhost:3306)/"+environment)
check(err)

return *db
}

//returns array of table names from queried database
//returns array of table name strings from queried database
func GetTableNames(db sqlx.DB) []string {
var tableNames []string

Expand All @@ -40,7 +41,7 @@ func GetTableNames(db sqlx.DB) []string {
return tableNames
}

//returns *Rows from queried database
//returns *Rows from given table (name) from queried database
func GetRows(db sqlx.DB, tableName string) *sqlx.Rows {
rows, err := db.Queryx("SELECT * from " + tableName)
check(err)
Expand All @@ -49,7 +50,6 @@ func GetRows(db sqlx.DB, tableName string) *sqlx.Rows {
}

//returns array of column names from table in database
//returns array of table names from queried database
func GetColumnNames(db sqlx.DB, tableName string) []string {
var colNames []string

Expand Down
30 changes: 22 additions & 8 deletions structConstructor/structConstructor.go
@@ -1,3 +1,5 @@
//structConstructor.go
//generates 'structs' package
package structConstructor

import (
Expand All @@ -14,20 +16,20 @@ func check(e error) {
}
}

//makes structs and struct interfaces
//writes struct, interface, and map files to structs package
func MakeStructFiles(db sqlx.DB) {
MakeStructs(db)
MakeStructInterface(db)
MakeStructToJson(db)
MakeStructMap(db)
}

//makes structures from database
//writes the struct file (structs.go), which has an object for each
//database table, ith each table field as a member variable
func MakeStructs(db sqlx.DB) {
structStr := "package structs\n"
tableList := sqlParser.GetTableNames(db)

//add a struct for each table
//writes in relation to home directory
for _, table := range tableList {
structStr += "type " + strings.Title(table) + " struct {\n"
columnList := sqlParser.GetColumnNames(db, table)
Expand All @@ -38,24 +40,30 @@ func MakeStructs(db sqlx.DB) {

structStr += "}\n"
}

//writes in relation to home directory
WriteFile(structStr, "./structs/structs.go")
}

//adds rows into a struct
//writes structInterface.go, which has a function that takes in *Rows and
//returns the byte array JSON format for each table in the database
func MakeStructInterface(db sqlx.DB) {
//header, imports
structInterface := "package structs\n"
structInterface += "import (\n"
structInterface += "\t\"github.com/jmoiron/sqlx\"\n"
structInterface += "\t\"encoding/json\"\n"
structInterface += ")\n"

//makes a function for each object
tableList := sqlParser.GetTableNames(db)
for _, table := range tableList {
//function declaration
structInterface += "func ByteArrayFrom" + strings.Title(table) + "(rows *sqlx.Rows) []byte {\n"
structInterface += "\tvar tStr []byte\n"
//make new instance
structInterface += "\tt := " + strings.Title(table) + "{}\n"
//loops through all columns
//loops through all columns and translates to JSON
structInterface += "\tfor rows.Next() {\n"
structInterface += "\t\t rows.StructScan(&t)\n"
structInterface += "\t\t tmpStr, _ := json.MarshalIndent(t, \"\", \" \")\n"
Expand All @@ -69,12 +77,15 @@ func MakeStructInterface(db sqlx.DB) {
WriteFile(structInterface, "./structs/structInterface.go")
}

//maps each string to a function
func MakeStructToJson(db sqlx.DB) {
//writes structMap.go, which has a function that maps each tableName string to
//its respective function in structInterface.go
func MakeStructMap(db sqlx.DB) {
//declaration, imports
structMap := "package structs\n"
structMap += "import \"github.com/jmoiron/sqlx\"\n"
structMap += "func MapTableToJson(tableName string, rows *sqlx.Rows) []byte{\n"

//each table has a case mapping name with structInterface function
tableList := sqlParser.GetTableNames(db)
for _, table := range tableList {
structMap += "\tif tableName == \"" + table + "\"{\n"
Expand All @@ -83,8 +94,11 @@ func MakeStructToJson(db sqlx.DB) {
structMap += "\t}\n"
}

//if invalid table, returns error
structMap += "return []byte(\"ERROR: TABLE NOT FOUND\")\n"
structMap += "}\n"

//writes in relation to home directory
WriteFile(structMap, "./structs/structMap.go")
}

Expand Down

0 comments on commit 1191400

Please sign in to comment.