gas-stack/cmd/subcmd_generate_models.go
~wispem-wantex 1bc7f9111f
Some checks failed
CI / build-docker (push) Successful in 6s
CI / build-docker-bootstrap (push) Has been skipped
CI / release-test (push) Failing after 16s
codegen: implement "without rowid" tables
2026-03-18 10:39:38 -07:00

109 lines
3.1 KiB
Go

package main
import (
"errors"
"fmt"
"go/ast"
"go/token"
"os"
"github.com/spf13/cobra"
"git.offline-twitter.com/offline-labs/gas-stack/pkg/codegen/modelgenerate"
. "git.offline-twitter.com/offline-labs/gas-stack/pkg/flowutils"
"git.offline-twitter.com/offline-labs/gas-stack/pkg/schema"
)
var ErrNoSuchTable = errors.New("no such table")
var generate_model = &cobra.Command{
Use: "generate <model_name>",
Short: "Generate a model type",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
path := Must(cmd.Flags().GetString("schema"))
modname := Must(cmd.Flags().GetString("modname"))
sql, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("reading path %s: %w", path, err)
}
db := schema.InitDB(string(sql))
schema := schema.SchemaFromDB(db)
table, isOk := schema.Tables[args[0]]
if !isOk {
return ErrNoSuchTable
}
if Must(cmd.Flags().GetBool("test")) {
file2 := modelgenerate.GenerateModelTestAST(table, schema, modname)
PanicIf(modelgenerate.FprintWithComments(os.Stdout, file2))
} else {
decls := []ast.Decl{
&ast.GenDecl{
Tok: token.IMPORT,
Specs: []ast.Spec{
&ast.ImportSpec{Path: &ast.BasicLit{Kind: token.STRING, Value: `"database/sql"`}},
&ast.ImportSpec{Path: &ast.BasicLit{Kind: token.STRING, Value: `"errors"`}},
&ast.ImportSpec{
Name: ast.NewIdent("."),
Path: &ast.BasicLit{Kind: token.STRING, Value: `"git.offline-twitter.com/offline-labs/gas-stack/pkg/db"`},
},
&ast.ImportSpec{
Name: ast.NewIdent("."),
Path: &ast.BasicLit{
Kind: token.STRING,
Value: `"git.offline-twitter.com/offline-labs/gas-stack/pkg/flowutils"`,
},
},
},
},
}
if !table.IsWithoutRowid {
decls = append(decls, modelgenerate.GenerateIDType(table))
}
decls = append(decls,
modelgenerate.GenerateModelAST(table),
modelgenerate.GenerateSQLFieldsConst(table),
modelgenerate.GenerateSaveItemFunc(table),
modelgenerate.GenerateDeleteItemFunc(table),
)
if table.IsWithoutRowid {
decls = append(decls,
modelgenerate.GenerateGetItemBy(table, table.PrimaryKeyColumns()),
)
} else {
decls = append(decls,
modelgenerate.GenerateGetItemByIDFunc(table),
)
}
for _, index := range schema.Indexes {
if index.TableName != table.TableName {
// Skip indexes on other tables
continue
}
if index.IsUnique && len(index.Columns) == 1 {
decls = append(decls, modelgenerate.GenerateGetItemByUniqColFunc(table, table.GetColumnByName(index.Columns[0])))
}
}
decls = append(decls, modelgenerate.GenerateGetAllItemsFunc(table))
file := &ast.File{
Name: ast.NewIdent("db"), // TODO: parameterize
Decls: decls,
}
PanicIf(modelgenerate.FprintWithComments(os.Stdout, file))
}
return nil
},
}
func init() {
generate_model.Flags().String("schema", "pkg/db/schema.sql", "Path to SQL schema file")
generate_model.Flags().String("modname", "mymodule", "Name of project's Go module (TODO: detect automatically)")
generate_model.Flags().Bool("test", false, "Generate test file instead of regular file")
}