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
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 (
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
)

View File

@ -70,7 +70,7 @@ func (s *Mariadb) GetTable(schema, name string) (*Table, error) {
c.IS_NULLABLE,
c.DATA_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_COMMENT,
c.extra,
@ -142,6 +142,7 @@ func (s *Mariadb) GetTables(schema string) ([]*Table, error) {
t.TABLE_NAME
FROM information_schema.tables t
WHERE t.table_schema = ?
ORDER BY t.TABLE_NAME ASC
`
rows, err := s.db.Query(sql, schema)
if err != nil {

View File

@ -280,7 +280,7 @@ func ConnectToMariadb(t *testing.T) *sql.DB {
}
// createMariadbTable creates a table with the provided column configuration
// in statementand returns the created table name
// in statement and returns the created table name
func createMariadbTable(db *sql.DB, statement string) (string, error) {
name, _ := GenerateRandomString(8)
name = "ddl_test_" + name

View File

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

View File

@ -4,9 +4,12 @@ import (
"errors"
"fmt"
"os"
"os/exec"
"regexp"
"sort"
"strings"
"unicode"
"unicode/utf8"
"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)
}
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
@ -144,6 +154,24 @@ func GetFieldName(fieldName string) string {
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
// or an empty configuration struct if no one was provided
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)
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)
}
@ -235,7 +264,7 @@ func (c *constructor) getGoFile(existingContent string, tbl *ddl.Table, tblConfi
Schema: tbl.Schema,
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
rtc += "}\n"
@ -243,7 +272,7 @@ func (c *constructor) getGoFile(existingContent string, tbl *ddl.Table, tblConfi
// Add package header if no file exists already
if existingContent == "" {
header := fmt.Sprintf("package %s\n", tblConfig.PackageName)
header := fmt.Sprintf("package %s\n\n", tblConfig.PackageName)
importStr := ""
if len(imports) != 0 {
importStr = "import (\n"
@ -253,9 +282,9 @@ func (c *constructor) getGoFile(existingContent string, tbl *ddl.Table, tblConfi
importStr += ")\n"
}
rtc = header + importStr + rtc + columns
rtc = header + importStr + "\n" + rtc + columns
} else {
// @TODO merge file...
rtc = c.patchFile(existingContent, rtc+columns, tbl, tblConfig, imports)
}
return rtc
@ -277,9 +306,9 @@ func (c *constructor) getDataType(column *ddl.Column, tblConfig *TableConfig, ta
case ddl.StringType:
return "sql.NullString", "database/sql"
case ddl.IntType:
return "sql.NullInt", "database/sql"
return "sql.NullInt64", "database/sql"
case ddl.DoubleType:
return "sql.NullFloat", "database/sql"
return "sql.NullFloat64", "database/sql"
case ddl.DateType:
return "sql.NullTime", "database/sql"
}
@ -291,7 +320,7 @@ func (c *constructor) getDataType(column *ddl.Column, tblConfig *TableConfig, ta
case ddl.IntType:
return "int", ""
case ddl.DoubleType:
return "float", ""
return "float64", ""
case ddl.DateType:
return "time.Time", "time"
}
@ -397,7 +426,7 @@ func (c *constructor) patchFile(existingContent string, newStruct string, tbl *d
if reg.MatchString(existingContent) {
// Replace content
return reg.ReplaceAllString(existingContent, newStruct+"\n")
return reg.ReplaceAllString(existingContent, newStruct)
} else {
// Append content
return existingContent + "\n" + newStruct
@ -413,11 +442,12 @@ func (c *constructor) patchImports(existingContent string, imports map[string]bo
reg := regexp.MustCompile(`"([^"]+)"`)
var importStart, importEnd int
importFound := true
// Find any existing import clause within the first 5 lines
for i, line := range strings.Split(existingContent, "\n") {
// No import found
if i > 5 && importStart == 0 {
return existingContent, nil
importFound = false
}
// Trim any whitespace for import
@ -480,6 +510,22 @@ func (c *constructor) patchImports(existingContent string, imports map[string]bo
}
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
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.
// WithUnder -> ReplacedColumn
expected = strings.ReplaceAll(expected, "WithUnder", "ReplacedColumn")
expected = strings.ReplaceAll(expected, "withUnder", "replacedColumn")
expected = strings.ReplaceAll(expected, "with_under", "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.
// We already tested the struct tags in another test!
func getStructTag(col *ddl.Column) string {
tagStart := "`" + ColumnTagId + ":\""
tagStart := "`json:\"" + GetJsonName(col.Name) + "\" " + ColumnTagId + ":\""
tagEnd := "\"`"
return tagStart + GetColumnTag(col).ToTag() + tagEnd
}
func getMetadataTag(tbl *ddl.Table) string {
tagStart := "`" + MetadataTagId + ":\""
tagStart := "`json:\"-\" " + MetadataTagId + ":\""
tagEnd := "\"`"
m := &MetadataTag{