Skip to content

Commit

Permalink
Move mysql logic into seperate utils_mysql file. #2
Browse files Browse the repository at this point in the history
  • Loading branch information
Shelnutt2 committed Jun 16, 2016
1 parent 2838a5a commit 48b398a
Show file tree
Hide file tree
Showing 3 changed files with 233 additions and 205 deletions.
46 changes: 6 additions & 40 deletions db2struct/main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"database/sql"
"fmt"
"os"
"strconv"
Expand Down Expand Up @@ -81,60 +80,27 @@ func main() {
return
}

var err error
var db *sql.DB
if mariadbPassword != nil {
db, err = sql.Open("mysql", *mariadbUser+":"+*mariadbPassword+"@tcp("+mariadbHost+":"+strconv.Itoa(*mariadbPort)+")/"+*mariadbDatabase+"?&parseTime=True")
} else {
db, err = sql.Open("mysql", *mariadbUser+"@tcp("+mariadbHost+":"+strconv.Itoa(*mariadbPort)+")/"+*mariadbDatabase+"?&parseTime=True")
}
defer db.Close()
columnDataTypes, err := db2struct.GetColumnsFromMysqlTable(*mariadbUser, *mariadbPassword, mariadbHost, *mariadbPort, *mariadbDatabase, *mariadbTable)

// Check for error in db, note this does not check connectivity but does check uri
if err != nil {
fmt.Println("Error opening mysql db: " + err.Error())
fmt.Println("Error in selecting column data information from mysql information schema")
return
}

// Store colum as map of maps
columnDataTypes := make(map[string]map[string]string)
// Select columnd data from INFORMATION_SCHEMA
columnDataTypeQuery := "SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = ? AND table_name = ?"

if *verbose {
fmt.Println("running: " + columnDataTypeQuery)
}

rows, err := db.Query(columnDataTypeQuery, *mariadbDatabase, *mariadbTable)

if err != nil {
fmt.Println("Error selecting from db: " + err.Error())
return
}
if db != nil {
defer rows.Close()
}

for rows.Next() {
var column string
var dataType string
var nullable string
rows.Scan(&column, &dataType, &nullable)

columnDataTypes[column] = map[string]string{"value": dataType, "nullable": nullable}
}

// If structName is not set we need to default it
if structName == nil || *structName == "" {
*structName = "newstruct"
}
// If packageName is not set we need to default it
if packageName == nil || *packageName == "" {
*packageName = "newpackage"
}
// Generate struct string based on columnDataTypes
struc, err := db2struct.Generate(columnDataTypes, *mariadbTable, *structName, *packageName, *jsonAnnotation, *gormAnnotation, *gureguTypes)
struc, err := db2struct.Generate(*columnDataTypes, *mariadbTable, *structName, *packageName, *jsonAnnotation, *gormAnnotation, *gureguTypes)

if err != nil {
fmt.Println("Error in creating struct from json: " + err.Error())
return
}

fmt.Println(string(struc))
Expand Down
171 changes: 6 additions & 165 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package db2struct
import (
"fmt"
"go/format"
"sort"
"strconv"
"strings"
"unicode"
Expand Down Expand Up @@ -59,13 +58,18 @@ var intToWordMap = []string{
"nine",
}

//Debug level logging
var Debug = false

// Generate Given a Column map with datatypes and a name structName,
// attempts to generate a struct definition
func Generate(columnTypes map[string]map[string]string, tableName string, structName string, pkgName string, jsonAnnotation bool, gormAnnotation bool, gureguTypes bool) ([]byte, error) {
var dbTypes string
dbTypes = generateMysqlTypes(columnTypes, 0, jsonAnnotation, gormAnnotation, gureguTypes)
src := fmt.Sprintf("package %s\ntype %s %s}",
pkgName,
structName,
generateTypes(columnTypes, 0, jsonAnnotation, gormAnnotation, gureguTypes))
dbTypes)
if gormAnnotation == true {
tableNameFunc := "// TableName sets the insert table name for this struct type\n" +
"func (" + strings.ToLower(string(structName[0])) + " *" + structName + ") TableName() string {\n" +
Expand All @@ -80,55 +84,6 @@ func Generate(columnTypes map[string]map[string]string, tableName string, struct
return formatted, err
}

// Generate go struct entries for a map[string]interface{} structure
func generateTypes(obj map[string]map[string]string, depth int, jsonAnnotation bool, gormAnnotation bool, gureguTypes bool) string {
structure := "struct {"

keys := make([]string, 0, len(obj))
for key := range obj {
keys = append(keys, key)
}
sort.Strings(keys)

for _, key := range keys {
mysqlType := obj[key]
nullable := false
if mysqlType["nullable"] == "YES" {
nullable = true
}

// Get the corresponding go value type for this mysql type
var valueType string
// If the guregu (https://github.com/guregu/null) CLI option is passed use its types, otherwise use go's sql.NullX
if gureguTypes == true {
valueType = mysqlTypeToGureguType(mysqlType["value"], nullable)
} else {
valueType = mysqlTypeToGoType(mysqlType["value"], nullable)
}

fieldName := fmtFieldName(stringifyFirstChar(key))
var annotations []string
if gormAnnotation == true {
annotations = append(annotations, fmt.Sprintf("gorm:\"column:%s\"", key))
}
if jsonAnnotation == true {
annotations = append(annotations, fmt.Sprintf("json:\"%s\"", key))
}
if len(annotations) > 0 {
structure += fmt.Sprintf("\n%s %s `%s`",
fieldName,
valueType,
strings.Join(annotations, " "))

} else {
structure += fmt.Sprintf("\n%s %s",
fieldName,
valueType)
}
}
return structure
}

// fmtFieldName formats a string as a struct key
//
// Example:
Expand Down Expand Up @@ -237,117 +192,3 @@ func stringifyFirstChar(str string) string {

return intToWordMap[i] + "_" + str[1:]
}

// mysqlTypeToGoType converts the mysql types to go compatible sql.Nullable (https://golang.org/pkg/database/sql/) types
func mysqlTypeToGoType(mysqlType string, nullable bool) string {
switch mysqlType {
case "tinyint":
if nullable {
return "sql.NullInt64"
}
return "int"
case "int":
if nullable {
return "sql.NullInt64"
}
return "int"
case "bigint":
if nullable {
return "sql.NullInt64"
}
return "int64"
case "varchar":
if nullable {
return "sql.NullString"
}
return "string"
case "datetime":
return "time.Time"
case "date":
return "time.Time"
case "time":
return "time.Time"
case "timestamp":
return "time.Time"
case "decimal":
if nullable {
return "sql.NullFloat64"
}
return "float64"
case "float":
if nullable {
return "sql.NullFloat64"
}
return "float32"
case "double":
if nullable {
return "sql.NullFloat64"
}
return "float64"
}

return ""
}

// mysqlTypeToGureguType converts the mysql types to go compatible guregu (https://github.com/guregu/null) types
func mysqlTypeToGureguType(mysqlType string, nullable bool) string {
switch mysqlType {
case "tinyint":
if nullable {
return "null.Int"
}
return "int"
case "int":
if nullable {
return "null.Int"
}
return "int"
case "bigint":
if nullable {
return "null.Int"
}
return "int64"
case "varchar":
if nullable {
return "null.String"
}
return "string"
case "datetime":
if nullable {
return "null.Time"
}
return "time.Time"
case "date":
if nullable {
return "null.Time"
}
return "time.Time"
case "time":
if nullable {
return "null.Time"
}
return "time.Time"
case "timestamp":
if nullable {
return "null.Time"
}
return "time.Time"
case "decimal":
if nullable {
return "null.Float"
}
return "float64"
case "float":
if nullable {
return "null.Float"
}
return "float32"
case "double":
if nullable {
return "null.Float"
}
return "float64"
}

return ""
}
Loading

0 comments on commit 48b398a

Please sign in to comment.