Skip to content

Instantly share code, notes, and snippets.

@fuzzy
Created September 23, 2015 20:52
Show Gist options
  • Save fuzzy/58607148fa18cc085aae to your computer and use it in GitHub Desktop.
Save fuzzy/58607148fa18cc085aae to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"reflect"
)
type ApiKey struct {
Key string
Enabled bool
Admin bool
}
func main() {
// iterate through the attributes of a Data Model instance
data := ApiKey{Key: "blahblahblah", Enabled: true, Admin: false}
err := createTable(&data)
if err != nil {
fmt.Println(err)
}
err = deleteRow(&data)
if err != nil {
fmt.Println(err)
}
err = updateRow(&data)
if err != nil {
fmt.Println(err)
}
err = insertRow(&data)
if err != nil {
fmt.Println(err)
}
err = dropTable(&data)
if err != nil {
fmt.Println(err)
}
}
func dump(f interface{}) (string, []string, []interface{}) {
var columns []string
var fields []interface{}
val := reflect.ValueOf(f).Elem()
typ := reflect.TypeOf(f)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
table := typ.Name()
for i := 0; i < val.NumField(); i++ {
vF := val.Field(i)
tF := val.Type().Field(i)
iF := vF.Interface()
// TODO: Handle nested structs here
// can do this by checking the type of iF
// and calling ourselves recursively I think.
columns = append(columns, tF.Name)
fields = append(fields, iF)
}
return table, columns, fields
}
func sqlize(f interface{}) string {
switch x := f.(type) {
case bool:
return fmt.Sprint(x)
case int:
return fmt.Sprint(x)
default:
return fmt.Sprintf("'%s'", fmt.Sprint(x))
}
}
func sqltype(f interface{}) string {
switch f.(type) {
case bool:
return fmt.Sprint("BOOL")
case int:
return fmt.Sprint("INT")
default:
return fmt.Sprint("VARCHAR")
}
}
func Save(f interface{}) error {
return nil
}
func dropTable(f interface{}) error {
table, _, _ := dump(f)
sql := fmt.Sprintf("DROP TABLE %s IF EXISTS", table)
fmt.Printf("DEBUG: %s\n", sql)
return nil
}
func createTable(f interface{}) error {
table, cols, rows := dump(f)
sql := fmt.Sprintf("CREATE TABLE %s (", table)
for i := 0; i < len(cols); i++ {
sql = fmt.Sprintf("%s%s %s, ", sql, cols[i], sqltype(rows[i]))
}
sql = fmt.Sprintf("%s)", sql[:(len(sql)-2)])
fmt.Printf("DEBUG: %s\n", sql)
return nil
}
func selectRows(f interface{}) error {
return nil
}
func deleteRow(f interface{}) error {
sql := "DELETE FROM "
table, cols, rows := dump(f)
// TODO:
// fix this so that a select is done before hand, and if more than
// one row exists, error should be returned
sql = fmt.Sprintf("%s%s WHERE %s = %s", sql, table, cols[0], sqlize(rows[0]))
fmt.Printf("DEBUG: %s\n", sql)
return nil
}
func updateRow(f interface{}) error {
sql := "UPDATE "
table, cols, rows := dump(f)
sql = fmt.Sprintf("%s%s SET ", sql, table)
for i := 1; i < len(cols); i++ {
sql = fmt.Sprintf("%s%s = %s, ", sql, cols[i], sqlize(rows[i]))
}
sql = fmt.Sprintf("%s WHERE %s = %s", sql[:(len(sql)-2)], cols[0], sqlize(rows[0]))
fmt.Printf("DEBUG: %s\n", sql)
return nil
}
func insertRow(f interface{}) error {
table, cols, rows := dump(f)
retv := fmt.Sprintf("INSERT INTO %s (", table)
for _, k := range cols {
retv = fmt.Sprintf("%s%s, ", retv, k)
}
retv = fmt.Sprintf("%s) VALUES (", retv[:(len(retv)-2)])
for _, v := range rows {
retv = fmt.Sprintf("%s%s, ", retv, sqlize(v))
}
retv = fmt.Sprintf("%s)", retv[:(len(retv)-2)])
fmt.Printf("DEBUG: %s\n", retv)
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment