diff --git a/cmd/subcmd_generate_models.go b/cmd/subcmd_generate_models.go index dab7543..2b9f10d 100644 --- a/cmd/subcmd_generate_models.go +++ b/cmd/subcmd_generate_models.go @@ -82,8 +82,14 @@ var generate_model = &cobra.Command{ // Skip indexes on other tables continue } - if index.IsUnique && len(index.Columns) == 1 { + if len(index.Columns) != 1 || index.Columns[0] == "" { + // Skip multi-column and expression indexes + continue + } + if index.IsUnique { decls = append(decls, modelgenerate.GenerateGetItemByUniqColFunc(table, table.GetColumnByName(index.Columns[0]))) + } else { + decls = append(decls, modelgenerate.GenerateGetItemsByColFunc(table, table.GetColumnByName(index.Columns[0]))) } } decls = append(decls, modelgenerate.GenerateGetAllItemsFunc(table)) diff --git a/ops/test.sh b/ops/test.sh new file mode 100644 index 0000000..f841a41 --- /dev/null +++ b/ops/test.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +go test -tags fts5 ./... diff --git a/pkg/codegen/modelgenerate/generate_model.go b/pkg/codegen/modelgenerate/generate_model.go index b4dca52..24dd660 100644 --- a/pkg/codegen/modelgenerate/generate_model.go +++ b/pkg/codegen/modelgenerate/generate_model.go @@ -680,6 +680,49 @@ func GenerateGetItemByUniqColFunc(tbl schema.Table, col schema.Column) *ast.Func } } +// GenerateGetItemsByColFunc produces an AST for the `GetXyzsByCol()` function, for a non-unique +// index on a single column. +// E.g., a table with `table.TableName = "foods"` and a non-unique index on "category" will +// produce a "GetFoodsByCategory(category string) []Food" function. +func GenerateGetItemsByColFunc(tbl schema.Table, col schema.Column) *ast.FuncDecl { + // Use the xyzSQLFields constant in the select query + selectExpr := &ast.BinaryExpr{ + X: &ast.BinaryExpr{ + X: &ast.BasicLit{Kind: token.STRING, Value: "`\n\t select `"}, + Op: token.ADD, + Y: SQLFieldsConstIdent(tbl), + }, + Op: token.ADD, + Y: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("`\n\t from %s\n\t where %s = ?\n\t`", tbl.TableName, col.Name)}, + } + + param := ast.NewIdent(col.GoVarName()) + + selectCall := doCall(&ast.CallExpr{ + Fun: &ast.SelectorExpr{X: dbDB, Sel: ast.NewIdent("Select")}, + Args: []ast.Expr{&ast.UnaryExpr{Op: token.AND, X: ast.NewIdent("ret")}, selectExpr, param}, + }) + + return &ast.FuncDecl{ + Recv: dbRecv, + Name: ast.NewIdent("Get" + inflection.Plural(schema.TypenameFromTablename(tbl.TableName)) + "By" + col.GoFieldName()), + Type: &ast.FuncType{ + Params: &ast.FieldList{List: []*ast.Field{ + {Names: []*ast.Ident{param}, Type: GoTypeForColumn(col)}, + }}, + Results: &ast.FieldList{List: []*ast.Field{ + {Names: []*ast.Ident{ast.NewIdent("ret")}, Type: &ast.ArrayType{Elt: ast.NewIdent(tbl.GoTypeName)}}, + }}, + }, + Body: &ast.BlockStmt{ + List: []ast.Stmt{ + &ast.ExprStmt{X: selectCall}, + &ast.ReturnStmt{}, + }, + }, + } +} + // GenerateGetAllItemsFunc produces an AST for the `GetAllXyzs()` function. // E.g., a table with `table.TypeName = "foods"` will produce a "GetAllFoods()" function. func GenerateGetAllItemsFunc(tbl schema.Table) *ast.FuncDecl { diff --git a/pkg/codegen/modelgenerate/generate_testfile.go b/pkg/codegen/modelgenerate/generate_testfile.go index 93ccf9a..314411e 100644 --- a/pkg/codegen/modelgenerate/generate_testfile.go +++ b/pkg/codegen/modelgenerate/generate_testfile.go @@ -432,8 +432,12 @@ func GenerateModelTestAST(tbl pkgschema.Table, schema pkgschema.Schema, gomodNam // Skip indexes on other tables continue } - if index.IsUnique && len(index.Columns) == 1 { - col := tbl.GetColumnByName(index.Columns[0]) + if len(index.Columns) != 1 || index.Columns[0] == "" { + // Skip multi-column and expression indexes + continue + } + col := tbl.GetColumnByName(index.Columns[0]) + if index.IsUnique { indexGets = append(indexGets, []ast.Stmt{ // assert.Equal(t, item2, TestDB.GetItemByXYZ(...)) &ast.ExprStmt{X: &ast.CallExpr{ // TODO: what if just delete the "ExprStmt" wrapper? @@ -450,9 +454,25 @@ func GenerateModelTestAST(tbl pkgschema.Table, schema pkgschema.Schema, gomodNam }, }}, }...) - // decls = append(decls, modelgenerate.GenerateGetItemByUniqColFunc(table, table.GetColumnByName(index.Columns[0]))) - hasIndexedGets = true + } else { + indexGets = append(indexGets, []ast.Stmt{ + // assert.Contains(t, TestDB.GetItemsByXYZ(...), item2) + &ast.ExprStmt{X: &ast.CallExpr{ + Fun: &ast.SelectorExpr{X: ast.NewIdent("assert"), Sel: ast.NewIdent("Contains")}, + Args: []ast.Expr{ + ast.NewIdent("t"), + &ast.CallExpr{ + Fun: &ast.SelectorExpr{X: testDB, Sel: ast.NewIdent( + "Get" + inflection.Plural(pkgschema.TypenameFromTablename(tbl.TableName)) + "By" + col.GoFieldName(), + )}, + Args: []ast.Expr{&ast.SelectorExpr{X: testObj2, Sel: ast.NewIdent(col.GoFieldName())}}, + }, + testObj2, + }, + }}, + }...) } + hasIndexedGets = true } if hasIndexedGets {