Skip to content

Instantly share code, notes, and snippets.

@dmitrymomot
Created February 28, 2018 23:37
Show Gist options
  • Save dmitrymomot/f25e0b599e1b88a9789cc0cd8483a01f to your computer and use it in GitHub Desktop.
Save dmitrymomot/f25e0b599e1b88a9789cc0cd8483a01f to your computer and use it in GitHub Desktop.
package main
import (
"encoding/json"
"fmt"
// init mysql
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"github.com/mitchellh/mapstructure"
)
const (
driver = "mysql"
connStr = "user:password@tcp(localhost:3306)/flxbase?charset=utf8&parseTime=True&loc=Local"
)
// Test struct
type Test struct {
gorm.Model
String string
Integer int
Boolean bool
AnotherField uint64
}
func main() {
db, err := gorm.Open(driver, connStr)
checkErr(err)
defer db.Close()
db.LogMode(true)
if !db.HasTable(&Test{}) {
checkErr(db.CreateTable(&Test{}).Error)
}
db.AutoMigrate(&Test{})
table, err := TableSchema(db, "tests")
checkErr(err)
jsonData, err := json.Marshal(table)
checkErr(err)
fmt.Println(string(jsonData))
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
// TableField struct
type TableField struct {
Collation string
Comment string
Default string
Extra string
Field string
Key string
Null string
Privileges string
Type string
}
// MapToStruct converts map to structure
func MapToStruct(data map[string]interface{}, output interface{}) error {
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
TagName: "json",
Metadata: nil,
Result: output,
})
if err != nil {
return err
}
if err := decoder.Decode(data); err != nil {
return err
}
return nil
}
// TableSchema returns table schema
func TableSchema(db *gorm.DB, table string) ([]*TableField, error) {
rows, err := db.Raw("SHOW FULL COLUMNS FROM " + table).Rows()
if err != nil {
return nil, err
}
columns, err := rows.Columns()
if err != nil {
return nil, err
}
count := len(columns)
tableData := make([]*TableField, 0)
values := make([]interface{}, count)
valuePtrs := make([]interface{}, count)
for rows.Next() {
for i := 0; i < count; i++ {
valuePtrs[i] = &values[i]
}
rows.Scan(valuePtrs...)
entry := make(map[string]interface{})
for i, col := range columns {
var v interface{}
val := values[i]
b, ok := val.([]byte)
if ok {
v = string(b)
} else {
v = val
}
entry[col] = v
}
tf := &TableField{}
if err := MapToStruct(entry, tf); err != nil {
return nil, err
}
tableData = append(tableData, tf)
}
return tableData, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment