Add json tags and fix smaller issues

main
Jonas Letzbor 2024-04-09 19:10:16 +02:00
parent 9eea116536
commit 07465cfafe
Signed by: RPJosh
GPG Key ID: 43ACB900522EA740
6 changed files with 69 additions and 21 deletions

11
go.mod
View File

@ -2,11 +2,14 @@ module git.rpjosh.de/RPJosh/go-ddl-parser
go 1.22.1 go 1.22.1
require (
git.rpjosh.de/RPJosh/go-logger v1.3.2
github.com/davecgh/go-spew v1.1.1
github.com/go-sql-driver/mysql v1.8.1
github.com/google/go-cmp v0.6.0
)
require ( require (
filippo.io/edwards25519 v1.1.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect
git.rpjosh.de/RPJosh/go-logger v1.3.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/google/go-cmp v0.6.0 // indirect
golang.org/x/sys v0.19.0 // indirect golang.org/x/sys v0.19.0 // indirect
) )

View File

@ -70,7 +70,7 @@ func (s *Mariadb) GetTable(schema, name string) (*Table, error) {
c.IS_NULLABLE, c.IS_NULLABLE,
c.DATA_TYPE, c.DATA_TYPE,
c.COLUMN_TYPE, c.COLUMN_TYPE,
COALESCE(c.CHARACTER_MAXIMUM_LENGTH, c.NUMERIC_PRECISION, c.DATETIME_PRECISION), COALESCE(c.CHARACTER_MAXIMUM_LENGTH, c.NUMERIC_PRECISION, c.DATETIME_PRECISION, 0),
c.COLUMN_KEY, c.COLUMN_KEY,
c.COLUMN_COMMENT, c.COLUMN_COMMENT,
c.extra, c.extra,
@ -142,6 +142,7 @@ func (s *Mariadb) GetTables(schema string) ([]*Table, error) {
t.TABLE_NAME t.TABLE_NAME
FROM information_schema.tables t FROM information_schema.tables t
WHERE t.table_schema = ? WHERE t.table_schema = ?
ORDER BY t.TABLE_NAME ASC
` `
rows, err := s.db.Query(sql, schema) rows, err := s.db.Query(sql, schema)
if err != nil { if err != nil {

View File

@ -1,3 +0,0 @@
package ddl
// @TODO hier table -> struct

View File

@ -4,9 +4,12 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"os/exec"
"regexp" "regexp"
"sort" "sort"
"strings" "strings"
"unicode"
"unicode/utf8"
"git.rpjosh.de/RPJosh/go-ddl-parser" "git.rpjosh.de/RPJosh/go-ddl-parser"
@ -114,6 +117,13 @@ func CreateStructs(conf *StructConfig, tables []*ddl.Table) error {
return fmt.Errorf("failed to write file %q: %s", tblConfig.Path, err) return fmt.Errorf("failed to write file %q: %s", tblConfig.Path, err)
} }
f.Close() f.Close()
// Lint go file
cmd := exec.Command("go", "fmt", tblConfig.Path)
if err := cmd.Run(); err != nil {
logger.Warning("Failed to run go fmt: %s", err)
}
cmd.Wait()
} }
return nil return nil
@ -144,6 +154,24 @@ func GetFieldName(fieldName string) string {
return rtc return rtc
} }
// GetJsonName returns the json key value for the provided fildName of
// the database.
// The json keys are CamelCased
func GetJsonName(fieldName string) string {
structField := GetFieldName(fieldName)
// Lowercase the first character for json
r, size := utf8.DecodeRuneInString(structField)
if r == utf8.RuneError && size <= 1 {
return structField
}
lc := unicode.ToLower(r)
if r == lc {
return structField
}
return string(lc) + structField[size:]
}
// findTableConfig returns a specific table configuration for the table // findTableConfig returns a specific table configuration for the table
// or an empty configuration struct if no one was provided // or an empty configuration struct if no one was provided
func (c *constructor) findTableConfig(tbl *ddl.Table) *TableConfig { func (c *constructor) findTableConfig(tbl *ddl.Table) *TableConfig {
@ -215,7 +243,8 @@ func (c *constructor) getGoFile(existingContent string, tbl *ddl.Table, tblConfi
} }
fieldName := GetFieldName(col.Name) fieldName := GetFieldName(col.Name)
rtc += fmt.Sprintf("\t%s %s `%s:\"%s\"`\n", fieldName, dataType, ColumnTagId, tags.ToTag()) jsonName := GetJsonName(col.Name)
rtc += fmt.Sprintf("\t%s %s `json:\"%s\" %s:\"%s\"`\n", fieldName, dataType, jsonName, ColumnTagId, tags.ToTag())
columns += fmt.Sprintf("\t %s_%s string = \"%s\"\n", tableName, fieldName, fieldName) columns += fmt.Sprintf("\t %s_%s string = \"%s\"\n", tableName, fieldName, fieldName)
} }
@ -235,7 +264,7 @@ func (c *constructor) getGoFile(existingContent string, tbl *ddl.Table, tblConfi
Schema: tbl.Schema, Schema: tbl.Schema,
Table: tbl.Name, Table: tbl.Name,
} }
rtc += fmt.Sprintf("\t%s any `%s:\"%s\"`\n", MetadataFieldName, MetadataTagId, metaData.ToTag()) rtc += fmt.Sprintf("\t%s any `json:\"-\" %s:\"%s\"`\n", MetadataFieldName, MetadataTagId, metaData.ToTag())
// Add closing line // Add closing line
rtc += "}\n" rtc += "}\n"
@ -243,7 +272,7 @@ func (c *constructor) getGoFile(existingContent string, tbl *ddl.Table, tblConfi
// Add package header if no file exists already // Add package header if no file exists already
if existingContent == "" { if existingContent == "" {
header := fmt.Sprintf("package %s\n", tblConfig.PackageName) header := fmt.Sprintf("package %s\n\n", tblConfig.PackageName)
importStr := "" importStr := ""
if len(imports) != 0 { if len(imports) != 0 {
importStr = "import (\n" importStr = "import (\n"
@ -253,9 +282,9 @@ func (c *constructor) getGoFile(existingContent string, tbl *ddl.Table, tblConfi
importStr += ")\n" importStr += ")\n"
} }
rtc = header + importStr + rtc + columns rtc = header + importStr + "\n" + rtc + columns
} else { } else {
// @TODO merge file... rtc = c.patchFile(existingContent, rtc+columns, tbl, tblConfig, imports)
} }
return rtc return rtc
@ -277,9 +306,9 @@ func (c *constructor) getDataType(column *ddl.Column, tblConfig *TableConfig, ta
case ddl.StringType: case ddl.StringType:
return "sql.NullString", "database/sql" return "sql.NullString", "database/sql"
case ddl.IntType: case ddl.IntType:
return "sql.NullInt", "database/sql" return "sql.NullInt64", "database/sql"
case ddl.DoubleType: case ddl.DoubleType:
return "sql.NullFloat", "database/sql" return "sql.NullFloat64", "database/sql"
case ddl.DateType: case ddl.DateType:
return "sql.NullTime", "database/sql" return "sql.NullTime", "database/sql"
} }
@ -291,7 +320,7 @@ func (c *constructor) getDataType(column *ddl.Column, tblConfig *TableConfig, ta
case ddl.IntType: case ddl.IntType:
return "int", "" return "int", ""
case ddl.DoubleType: case ddl.DoubleType:
return "float", "" return "float64", ""
case ddl.DateType: case ddl.DateType:
return "time.Time", "time" return "time.Time", "time"
} }
@ -397,7 +426,7 @@ func (c *constructor) patchFile(existingContent string, newStruct string, tbl *d
if reg.MatchString(existingContent) { if reg.MatchString(existingContent) {
// Replace content // Replace content
return reg.ReplaceAllString(existingContent, newStruct+"\n") return reg.ReplaceAllString(existingContent, newStruct)
} else { } else {
// Append content // Append content
return existingContent + "\n" + newStruct return existingContent + "\n" + newStruct
@ -413,11 +442,12 @@ func (c *constructor) patchImports(existingContent string, imports map[string]bo
reg := regexp.MustCompile(`"([^"]+)"`) reg := regexp.MustCompile(`"([^"]+)"`)
var importStart, importEnd int var importStart, importEnd int
importFound := true
// Find any existing import clause within the first 5 lines // Find any existing import clause within the first 5 lines
for i, line := range strings.Split(existingContent, "\n") { for i, line := range strings.Split(existingContent, "\n") {
// No import found // No import found
if i > 5 && importStart == 0 { if i > 5 && importStart == 0 {
return existingContent, nil importFound = false
} }
// Trim any whitespace for import // Trim any whitespace for import
@ -480,6 +510,22 @@ func (c *constructor) patchImports(existingContent string, imports map[string]bo
} }
newImport += ")" newImport += ")"
// We didn't found an existing import statment yet that we could replace
if !importFound {
lines := strings.Split(existingContent, "\n")
// Only a single line -> add it directly below
if len(lines) <= 1 {
lines = append(lines, "")
lines = append(lines, strings.Split(newImport, "\n")...)
} else {
// Insert it into existing, empty line
return replaceLines(existingContent, 1, 1, strings.Split("\n"+newImport, "\n")), nil
}
return strings.Join(lines, "\n"), nil
}
// Replace import string // Replace import string
return replaceLines(existingContent, importStart, importEnd, strings.Split(newImport, "\n")), nil return replaceLines(existingContent, importStart, importEnd, strings.Split(newImport, "\n")), nil
} }

View File

@ -393,6 +393,7 @@ func TestPatchFilePatchSelf(t *testing.T) {
// Replace a single column ID to test some change. // Replace a single column ID to test some change.
// WithUnder -> ReplacedColumn // WithUnder -> ReplacedColumn
expected = strings.ReplaceAll(expected, "WithUnder", "ReplacedColumn") expected = strings.ReplaceAll(expected, "WithUnder", "ReplacedColumn")
expected = strings.ReplaceAll(expected, "withUnder", "replacedColumn")
expected = strings.ReplaceAll(expected, "with_under", "replaced_column") expected = strings.ReplaceAll(expected, "with_under", "replaced_column")
tbl.Columns[1].Name = "replaced_column" tbl.Columns[1].Name = "replaced_column"
@ -429,13 +430,13 @@ func replaceWhitespaces(val string) string {
// getStructTag returns the tag for a struct to append to. // getStructTag returns the tag for a struct to append to.
// We already tested the struct tags in another test! // We already tested the struct tags in another test!
func getStructTag(col *ddl.Column) string { func getStructTag(col *ddl.Column) string {
tagStart := "`" + ColumnTagId + ":\"" tagStart := "`json:\"" + GetJsonName(col.Name) + "\" " + ColumnTagId + ":\""
tagEnd := "\"`" tagEnd := "\"`"
return tagStart + GetColumnTag(col).ToTag() + tagEnd return tagStart + GetColumnTag(col).ToTag() + tagEnd
} }
func getMetadataTag(tbl *ddl.Table) string { func getMetadataTag(tbl *ddl.Table) string {
tagStart := "`" + MetadataTagId + ":\"" tagStart := "`json:\"-\" " + MetadataTagId + ":\""
tagEnd := "\"`" tagEnd := "\"`"
m := &MetadataTag{ m := &MetadataTag{