TMP: codetables
This commit is contained in:
111
pkg/codegen/modelgenerate/generate_codetable_type.go
Normal file
111
pkg/codegen/modelgenerate/generate_codetable_type.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package modelgenerate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
|
||||
"git.offline-twitter.com/offline-labs/gas-stack/pkg/schema"
|
||||
"git.offline-twitter.com/offline-labs/gas-stack/pkg/textutils"
|
||||
)
|
||||
|
||||
func GenerateCodetableType(table schema.Table) *ast.GenDecl {
|
||||
return &ast.GenDecl{
|
||||
Tok: token.TYPE,
|
||||
Specs: []ast.Spec{&ast.TypeSpec{Name: &ast.Ident{Name: table.GoTypeName}, Type: &ast.Ident{Name: "int"}}},
|
||||
}
|
||||
}
|
||||
|
||||
func GenerateCodetableEnum(table schema.Table, vals []string) *ast.GenDecl {
|
||||
getConstName := func(s string) string {
|
||||
return table.GoTypeName + textutils.KebabToPascal(s)
|
||||
}
|
||||
|
||||
constSpecs := []ast.Spec{}
|
||||
for i, val := range vals {
|
||||
spec := &ast.ValueSpec{
|
||||
Names: []*ast.Ident{{Name: getConstName(val)}},
|
||||
}
|
||||
// Only the first one needs `iota`
|
||||
if i == 0 {
|
||||
spec.Type = &ast.Ident{Name: table.GoTypeName}
|
||||
spec.Values = []ast.Expr{&ast.BinaryExpr{
|
||||
X: &ast.Ident{Name: "iota"},
|
||||
Op: token.ADD,
|
||||
Y: &ast.BasicLit{Kind: token.INT, Value: "1"},
|
||||
}}
|
||||
}
|
||||
constSpecs = append(constSpecs, spec)
|
||||
}
|
||||
|
||||
return &ast.GenDecl{Tok: token.CONST, Specs: constSpecs}
|
||||
}
|
||||
|
||||
// GenerateCodetableStringerFunc implements the `Stringer` interface by defining a `String() string` function.
|
||||
func GenerateCodetableStringerFunc(table schema.Table, vals []string) *ast.FuncDecl {
|
||||
objIdent := ast.NewIdent(table.VarName)
|
||||
return &ast.FuncDecl{
|
||||
Recv: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{objIdent}, Type: &ast.Ident{Name: table.GoTypeName}}}},
|
||||
Name: &ast.Ident{Name: "String"},
|
||||
Type: &ast.FuncType{Params: &ast.FieldList{}, Results: &ast.FieldList{List: []*ast.Field{{Type: &ast.Ident{Name: "string"}}}}},
|
||||
Body: &ast.BlockStmt{
|
||||
List: []ast.Stmt{
|
||||
// names := []string{ ... }
|
||||
&ast.AssignStmt{
|
||||
Lhs: []ast.Expr{&ast.Ident{Name: "names"}},
|
||||
Tok: token.DEFINE,
|
||||
Rhs: []ast.Expr{
|
||||
&ast.CompositeLit{
|
||||
Type: &ast.ArrayType{Elt: &ast.Ident{Name: "string"}},
|
||||
Elts: func() []ast.Expr {
|
||||
ret := []ast.Expr{
|
||||
&ast.BasicLit{Kind: token.STRING, Value: `""`},
|
||||
}
|
||||
for _, val := range vals {
|
||||
ret = append(ret, &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("%q", val)})
|
||||
}
|
||||
return ret
|
||||
}(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// if int(c) < 1 || int(c) >= len(names) { return "invalid" }
|
||||
&ast.IfStmt{
|
||||
Cond: &ast.BinaryExpr{
|
||||
X: &ast.BinaryExpr{
|
||||
X: &ast.CallExpr{Fun: &ast.Ident{Name: "int"}, Args: []ast.Expr{objIdent}},
|
||||
Op: token.LSS,
|
||||
Y: &ast.BasicLit{Kind: token.INT, Value: "1"},
|
||||
},
|
||||
Op: token.LOR,
|
||||
Y: &ast.BinaryExpr{
|
||||
X: &ast.CallExpr{Fun: &ast.Ident{Name: "int"}, Args: []ast.Expr{objIdent}},
|
||||
Op: token.GEQ,
|
||||
Y: &ast.CallExpr{Fun: &ast.Ident{Name: "len"}, Args: []ast.Expr{&ast.Ident{Name: "names"}}},
|
||||
},
|
||||
},
|
||||
Body: &ast.BlockStmt{
|
||||
List: []ast.Stmt{
|
||||
&ast.ReturnStmt{Results: []ast.Expr{
|
||||
&ast.CallExpr{Fun: &ast.SelectorExpr{X: ast.NewIdent("fmt"), Sel: ast.NewIdent("Sprintf")}, Args: []ast.Expr{
|
||||
&ast.BasicLit{Kind: token.STRING, Value: `"<%d=invalid>"`},
|
||||
objIdent,
|
||||
}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
// return names[c]
|
||||
&ast.ReturnStmt{
|
||||
Results: []ast.Expr{
|
||||
&ast.IndexExpr{
|
||||
X: &ast.Ident{Name: "names"},
|
||||
Index: objIdent,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,15 @@ import (
|
||||
|
||||
// Column represents a single column in a table.
|
||||
type Column struct {
|
||||
TableName string `db:"table_name"`
|
||||
Name string `db:"column_name"`
|
||||
Type string `db:"column_type"`
|
||||
// TableName is the name of the SQLite table this column belongs to.
|
||||
TableName string `db:"table_name"`
|
||||
|
||||
// Name is the SQLite column name.
|
||||
Name string `db:"column_name"`
|
||||
|
||||
// Type is the SQLite type this column contains.
|
||||
Type string `db:"column_type"`
|
||||
|
||||
IsNotNull bool `db:"notnull"`
|
||||
HasDefaultValue bool `db:"has_default_value"`
|
||||
DefaultValue string `db:"dflt_value"`
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"sort"
|
||||
|
||||
"git.offline-twitter.com/offline-labs/gas-stack/pkg/flowutils"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
// Table is a single SQLite table.
|
||||
@@ -61,3 +66,11 @@ func (t Table) HasAutoTimestamps() (hasCreatedAt bool, hasUpdatedAt bool) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t Table) GetCodeTableValues(db *sqlx.DB) (ret []string) {
|
||||
if !slices.ContainsFunc(t.Columns, func(c Column) bool { return c.Name == "name" }) {
|
||||
panic("not a code table")
|
||||
}
|
||||
flowutils.PanicIf(db.Select(&ret, fmt.Sprintf("select name from %s", t.TableName)))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -10,6 +10,16 @@ func SnakeToCamel(s string) string {
|
||||
return strings.Join(parts, "")
|
||||
}
|
||||
|
||||
func KebabToPascal(s string) string {
|
||||
parts := strings.Split(s, "-")
|
||||
for i, part := range parts {
|
||||
if len(part) > 0 {
|
||||
parts[i] = strings.ToUpper(part[:1]) + part[1:]
|
||||
}
|
||||
}
|
||||
return strings.Join(parts, "")
|
||||
}
|
||||
|
||||
func CamelToPascal(s string) string {
|
||||
return strings.ToLower(s)[0:1] + s[1:]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user