sqlite_lint: add support for FTS5 and virtual tables
This commit is contained in:
parent
d70cbc1913
commit
0371fb4144
3
ops/compile.sh
Executable file
3
ops/compile.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
go build -tags fts5 -o gas ./cmd
|
||||||
@ -13,7 +13,8 @@ cd "$(dirname "${BASH_SOURCE[0]}")/.."
|
|||||||
|
|
||||||
# Compile `gas`
|
# Compile `gas`
|
||||||
gas="/tmp/gas"
|
gas="/tmp/gas"
|
||||||
go build -o $gas ./cmd
|
ops/compile.sh
|
||||||
|
mv gas $gas
|
||||||
|
|
||||||
test_project="/memory/test_gasproj"
|
test_project="/memory/test_gasproj"
|
||||||
if [[ -e $test_project ]]; then
|
if [[ -e $test_project ]]; then
|
||||||
|
|||||||
@ -13,7 +13,8 @@ cd "$(dirname "${BASH_SOURCE[0]}")/.."
|
|||||||
|
|
||||||
# Compile `gas`
|
# Compile `gas`
|
||||||
gas="/tmp/gas"
|
gas="/tmp/gas"
|
||||||
go build -o $gas ./cmd
|
ops/compile.sh
|
||||||
|
mv gas $gas
|
||||||
|
|
||||||
test_schema_dir="pkg/schema/lint/test_schemas"
|
test_schema_dir="pkg/schema/lint/test_schemas"
|
||||||
|
|
||||||
|
|||||||
@ -76,7 +76,7 @@ func GenerateModelAST(table schema.Table) *ast.GenDecl {
|
|||||||
return &ast.GenDecl{
|
return &ast.GenDecl{
|
||||||
Tok: token.TYPE,
|
Tok: token.TYPE,
|
||||||
Specs: []ast.Spec{&ast.TypeSpec{
|
Specs: []ast.Spec{&ast.TypeSpec{
|
||||||
Name: ast.NewIdent(table.TypeName),
|
Name: ast.NewIdent(table.GoTypeName),
|
||||||
Type: &ast.StructType{Fields: &ast.FieldList{List: fields}},
|
Type: &ast.StructType{Fields: &ast.FieldList{List: fields}},
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
@ -171,7 +171,7 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
|||||||
Op: token.NEQ,
|
Op: token.NEQ,
|
||||||
Y: &ast.BasicLit{Kind: token.INT, Value: "1"},
|
Y: &ast.BasicLit{Kind: token.INT, Value: "1"},
|
||||||
},
|
},
|
||||||
Body: &ast.BlockStmt{List: []ast.Stmt{&ast.ExprStmt{X: &ast.CallExpr{Fun: ast.NewIdent("panic"), Args: []ast.Expr{&ast.CallExpr{Fun: ast.NewIdent("fmt.Errorf"), Args: []ast.Expr{&ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"got %s with ID (%%d), so attempted update, but it doesn't exist\"", strings.ToLower(tbl.TypeName))}, &ast.SelectorExpr{X: ast.NewIdent(tbl.VarName), Sel: ast.NewIdent("ID")}}}}}}}},
|
Body: &ast.BlockStmt{List: []ast.Stmt{&ast.ExprStmt{X: &ast.CallExpr{Fun: ast.NewIdent("panic"), Args: []ast.Expr{&ast.CallExpr{Fun: ast.NewIdent("fmt.Errorf"), Args: []ast.Expr{&ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"got %s with ID (%%d), so attempted update, but it doesn't exist\"", strings.ToLower(tbl.GoTypeName))}, &ast.SelectorExpr{X: ast.NewIdent(tbl.VarName), Sel: ast.NewIdent("ID")}}}}}}}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -181,9 +181,9 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
|||||||
|
|
||||||
funcDecl := &ast.FuncDecl{
|
funcDecl := &ast.FuncDecl{
|
||||||
Recv: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent("db")}, Type: ast.NewIdent("DB")}}},
|
Recv: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent("db")}, Type: ast.NewIdent("DB")}}},
|
||||||
Name: ast.NewIdent("Save" + tbl.TypeName),
|
Name: ast.NewIdent("Save" + tbl.GoTypeName),
|
||||||
Type: &ast.FuncType{
|
Type: &ast.FuncType{
|
||||||
Params: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent(tbl.VarName)}, Type: &ast.StarExpr{X: ast.NewIdent(tbl.TypeName)}}}},
|
Params: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent(tbl.VarName)}, Type: &ast.StarExpr{X: ast.NewIdent(tbl.GoTypeName)}}}},
|
||||||
Results: nil,
|
Results: nil,
|
||||||
},
|
},
|
||||||
Body: funcBody,
|
Body: funcBody,
|
||||||
@ -194,11 +194,11 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
|||||||
// GenerateGetItemByIDFunc produces an AST for the `GetXyzByID()` function.
|
// GenerateGetItemByIDFunc produces an AST for the `GetXyzByID()` function.
|
||||||
// E.g., a table with `table.TypeName = "foods"` will produce a "GetFoodByID()" function.
|
// E.g., a table with `table.TypeName = "foods"` will produce a "GetFoodByID()" function.
|
||||||
func GenerateGetItemByIDFunc(tbl schema.Table) *ast.FuncDecl {
|
func GenerateGetItemByIDFunc(tbl schema.Table) *ast.FuncDecl {
|
||||||
funcName := "Get" + tbl.TypeName + "ByID"
|
funcName := "Get" + tbl.GoTypeName + "ByID"
|
||||||
|
|
||||||
recv := &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent("db")}, Type: ast.NewIdent("DB")}}}
|
recv := &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent("db")}, Type: ast.NewIdent("DB")}}}
|
||||||
arg := &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent("id")}, Type: ast.NewIdent(tbl.TypeIDName)}}}
|
arg := &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent("id")}, Type: ast.NewIdent(tbl.TypeIDName)}}}
|
||||||
result := &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent("ret")}, Type: ast.NewIdent(tbl.TypeName)}, {Names: []*ast.Ident{ast.NewIdent("err")}, Type: ast.NewIdent("error")}}}
|
result := &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent("ret")}, Type: ast.NewIdent(tbl.GoTypeName)}, {Names: []*ast.Ident{ast.NewIdent("err")}, Type: ast.NewIdent("error")}}}
|
||||||
|
|
||||||
// Use the xyzSQLFields constant in the select query
|
// Use the xyzSQLFields constant in the select query
|
||||||
selectExpr := &ast.BinaryExpr{
|
selectExpr := &ast.BinaryExpr{
|
||||||
@ -220,7 +220,7 @@ func GenerateGetItemByIDFunc(tbl schema.Table) *ast.FuncDecl {
|
|||||||
},
|
},
|
||||||
&ast.IfStmt{
|
&ast.IfStmt{
|
||||||
Cond: &ast.CallExpr{Fun: &ast.SelectorExpr{X: ast.NewIdent("errors"), Sel: ast.NewIdent("Is")}, Args: []ast.Expr{ast.NewIdent("err"), &ast.SelectorExpr{X: ast.NewIdent("sql"), Sel: ast.NewIdent("ErrNoRows")}}},
|
Cond: &ast.CallExpr{Fun: &ast.SelectorExpr{X: ast.NewIdent("errors"), Sel: ast.NewIdent("Is")}, Args: []ast.Expr{ast.NewIdent("err"), &ast.SelectorExpr{X: ast.NewIdent("sql"), Sel: ast.NewIdent("ErrNoRows")}}},
|
||||||
Body: &ast.BlockStmt{List: []ast.Stmt{&ast.ReturnStmt{Results: []ast.Expr{&ast.CompositeLit{Type: ast.NewIdent(tbl.TypeName)}, ast.NewIdent("ErrNotInDB")}}}},
|
Body: &ast.BlockStmt{List: []ast.Stmt{&ast.ReturnStmt{Results: []ast.Expr{&ast.CompositeLit{Type: ast.NewIdent(tbl.GoTypeName)}, ast.NewIdent("ErrNotInDB")}}}},
|
||||||
},
|
},
|
||||||
&ast.ReturnStmt{},
|
&ast.ReturnStmt{},
|
||||||
},
|
},
|
||||||
@ -238,12 +238,12 @@ func GenerateGetItemByIDFunc(tbl schema.Table) *ast.FuncDecl {
|
|||||||
// GenerateGetAllItemsFunc produces an AST for the `GetAllXyzs()` function.
|
// GenerateGetAllItemsFunc produces an AST for the `GetAllXyzs()` function.
|
||||||
// E.g., a table with `table.TypeName = "foods"` will produce a "GetAllFoods()" function.
|
// E.g., a table with `table.TypeName = "foods"` will produce a "GetAllFoods()" function.
|
||||||
func GenerateGetAllItemsFunc(tbl schema.Table) *ast.FuncDecl {
|
func GenerateGetAllItemsFunc(tbl schema.Table) *ast.FuncDecl {
|
||||||
funcName := "GetAll" + inflection.Plural(tbl.TypeName)
|
funcName := "GetAll" + inflection.Plural(tbl.GoTypeName)
|
||||||
recv := &ast.FieldList{List: []*ast.Field{
|
recv := &ast.FieldList{List: []*ast.Field{
|
||||||
{Names: []*ast.Ident{ast.NewIdent("db")}, Type: ast.NewIdent("DB")},
|
{Names: []*ast.Ident{ast.NewIdent("db")}, Type: ast.NewIdent("DB")},
|
||||||
}}
|
}}
|
||||||
result := &ast.FieldList{List: []*ast.Field{
|
result := &ast.FieldList{List: []*ast.Field{
|
||||||
{Names: []*ast.Ident{ast.NewIdent("ret")}, Type: &ast.ArrayType{Elt: ast.NewIdent(tbl.TypeName)}},
|
{Names: []*ast.Ident{ast.NewIdent("ret")}, Type: &ast.ArrayType{Elt: ast.NewIdent(tbl.GoTypeName)}},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
selectCall := &ast.CallExpr{
|
selectCall := &ast.CallExpr{
|
||||||
@ -291,9 +291,9 @@ func GenerateGetAllItemsFunc(tbl schema.Table) *ast.FuncDecl {
|
|||||||
// GenerateDeleteItemFunc produces an AST for the `DeleteXyz()` function.
|
// GenerateDeleteItemFunc produces an AST for the `DeleteXyz()` function.
|
||||||
// E.g., a table with `table.TypeName = "foods"` will produce a "DeleteFood()" function.
|
// E.g., a table with `table.TypeName = "foods"` will produce a "DeleteFood()" function.
|
||||||
func GenerateDeleteItemFunc(tbl schema.Table) *ast.FuncDecl {
|
func GenerateDeleteItemFunc(tbl schema.Table) *ast.FuncDecl {
|
||||||
funcName := "Delete" + tbl.TypeName
|
funcName := "Delete" + tbl.GoTypeName
|
||||||
recv := &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent("db")}, Type: ast.NewIdent("DB")}}}
|
recv := &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent("db")}, Type: ast.NewIdent("DB")}}}
|
||||||
arg := &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent(tbl.VarName)}, Type: ast.NewIdent(tbl.TypeName)}}}
|
arg := &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{ast.NewIdent(tbl.VarName)}, Type: ast.NewIdent(tbl.GoTypeName)}}}
|
||||||
|
|
||||||
funcBody := &ast.BlockStmt{
|
funcBody := &ast.BlockStmt{
|
||||||
List: []ast.Stmt{
|
List: []ast.Stmt{
|
||||||
@ -328,7 +328,7 @@ func GenerateDeleteItemFunc(tbl schema.Table) *ast.FuncDecl {
|
|||||||
Args: []ast.Expr{&ast.CallExpr{
|
Args: []ast.Expr{&ast.CallExpr{
|
||||||
Fun: ast.NewIdent("fmt.Errorf"),
|
Fun: ast.NewIdent("fmt.Errorf"),
|
||||||
Args: []ast.Expr{
|
Args: []ast.Expr{
|
||||||
&ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"tried to delete %s with ID (%%d) but it doesn't exist\"", strings.ToLower(tbl.TypeName))},
|
&ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"tried to delete %s with ID (%%d) but it doesn't exist\"", strings.ToLower(tbl.GoTypeName))},
|
||||||
&ast.SelectorExpr{X: ast.NewIdent(tbl.VarName), Sel: ast.NewIdent("ID")},
|
&ast.SelectorExpr{X: ast.NewIdent(tbl.VarName), Sel: ast.NewIdent("ID")},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -372,5 +372,5 @@ func GenerateSQLFieldsConst(tbl schema.Table) *ast.GenDecl {
|
|||||||
// ---------------
|
// ---------------
|
||||||
|
|
||||||
func SQLFieldsConstIdent(tbl schema.Table) *ast.Ident {
|
func SQLFieldsConstIdent(tbl schema.Table) *ast.Ident {
|
||||||
return ast.NewIdent(strings.ToLower(tbl.TypeName) + "SQLFields")
|
return ast.NewIdent(strings.ToLower(tbl.GoTypeName) + "SQLFields")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,7 +90,7 @@ func GenerateModelTestAST(tbl schema.Table, gomodName string) *ast.File {
|
|||||||
description2 := `"a big item"`
|
description2 := `"a big item"`
|
||||||
|
|
||||||
testCreateUpdateDelete := &ast.FuncDecl{
|
testCreateUpdateDelete := &ast.FuncDecl{
|
||||||
Name: ast.NewIdent("TestCreateUpdateDelete" + tbl.TypeName),
|
Name: ast.NewIdent("TestCreateUpdateDelete" + tbl.GoTypeName),
|
||||||
Type: &ast.FuncType{
|
Type: &ast.FuncType{
|
||||||
Params: &ast.FieldList{
|
Params: &ast.FieldList{
|
||||||
List: []*ast.Field{{
|
List: []*ast.Field{{
|
||||||
@ -106,7 +106,7 @@ func GenerateModelTestAST(tbl schema.Table, gomodName string) *ast.File {
|
|||||||
Lhs: []ast.Expr{testObj},
|
Lhs: []ast.Expr{testObj},
|
||||||
Tok: token.DEFINE,
|
Tok: token.DEFINE,
|
||||||
Rhs: []ast.Expr{&ast.CompositeLit{
|
Rhs: []ast.Expr{&ast.CompositeLit{
|
||||||
Type: ast.NewIdent(tbl.TypeName),
|
Type: ast.NewIdent(tbl.GoTypeName),
|
||||||
Elts: []ast.Expr{
|
Elts: []ast.Expr{
|
||||||
&ast.KeyValueExpr{
|
&ast.KeyValueExpr{
|
||||||
Key: fieldName,
|
Key: fieldName,
|
||||||
@ -118,7 +118,7 @@ func GenerateModelTestAST(tbl schema.Table, gomodName string) *ast.File {
|
|||||||
|
|
||||||
// TestDB.SaveItem(&item)
|
// TestDB.SaveItem(&item)
|
||||||
&ast.ExprStmt{X: &ast.CallExpr{
|
&ast.ExprStmt{X: &ast.CallExpr{
|
||||||
Fun: ast.NewIdent("TestDB.Save" + tbl.TypeName),
|
Fun: ast.NewIdent("TestDB.Save" + tbl.GoTypeName),
|
||||||
Args: []ast.Expr{&ast.UnaryExpr{Op: token.AND, X: testObj}},
|
Args: []ast.Expr{&ast.UnaryExpr{Op: token.AND, X: testObj}},
|
||||||
}},
|
}},
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ func GenerateModelTestAST(tbl schema.Table, gomodName string) *ast.File {
|
|||||||
Rhs: []ast.Expr{&ast.CallExpr{
|
Rhs: []ast.Expr{&ast.CallExpr{
|
||||||
Fun: ast.NewIdent("Must"),
|
Fun: ast.NewIdent("Must"),
|
||||||
Args: []ast.Expr{&ast.CallExpr{
|
Args: []ast.Expr{&ast.CallExpr{
|
||||||
Fun: ast.NewIdent("TestDB.Get" + tbl.TypeName + "ByID"),
|
Fun: ast.NewIdent("TestDB.Get" + tbl.GoTypeName + "ByID"),
|
||||||
Args: []ast.Expr{&ast.SelectorExpr{X: testObj, Sel: ast.NewIdent("ID")}},
|
Args: []ast.Expr{&ast.SelectorExpr{X: testObj, Sel: ast.NewIdent("ID")}},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
@ -160,7 +160,7 @@ func GenerateModelTestAST(tbl schema.Table, gomodName string) *ast.File {
|
|||||||
|
|
||||||
// TestDB.SaveItem(&item)
|
// TestDB.SaveItem(&item)
|
||||||
&ast.ExprStmt{X: &ast.CallExpr{
|
&ast.ExprStmt{X: &ast.CallExpr{
|
||||||
Fun: ast.NewIdent("TestDB.Save" + tbl.TypeName),
|
Fun: ast.NewIdent("TestDB.Save" + tbl.GoTypeName),
|
||||||
Args: []ast.Expr{&ast.UnaryExpr{Op: token.AND, X: testObj}},
|
Args: []ast.Expr{&ast.UnaryExpr{Op: token.AND, X: testObj}},
|
||||||
}},
|
}},
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ func GenerateModelTestAST(tbl schema.Table, gomodName string) *ast.File {
|
|||||||
Rhs: []ast.Expr{&ast.CallExpr{
|
Rhs: []ast.Expr{&ast.CallExpr{
|
||||||
Fun: ast.NewIdent("Must"),
|
Fun: ast.NewIdent("Must"),
|
||||||
Args: []ast.Expr{&ast.CallExpr{
|
Args: []ast.Expr{&ast.CallExpr{
|
||||||
Fun: ast.NewIdent("TestDB.Get" + tbl.TypeName + "ByID"),
|
Fun: ast.NewIdent("TestDB.Get" + tbl.GoTypeName + "ByID"),
|
||||||
Args: []ast.Expr{&ast.SelectorExpr{X: testObj, Sel: ast.NewIdent("ID")}},
|
Args: []ast.Expr{&ast.SelectorExpr{X: testObj, Sel: ast.NewIdent("ID")}},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
@ -189,7 +189,7 @@ func GenerateModelTestAST(tbl schema.Table, gomodName string) *ast.File {
|
|||||||
|
|
||||||
// TestDB.DeleteItem(item)
|
// TestDB.DeleteItem(item)
|
||||||
&ast.ExprStmt{X: &ast.CallExpr{
|
&ast.ExprStmt{X: &ast.CallExpr{
|
||||||
Fun: ast.NewIdent("TestDB.Delete" + tbl.TypeName),
|
Fun: ast.NewIdent("TestDB.Delete" + tbl.GoTypeName),
|
||||||
Args: []ast.Expr{testObj},
|
Args: []ast.Expr{testObj},
|
||||||
}},
|
}},
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ func GenerateModelTestAST(tbl schema.Table, gomodName string) *ast.File {
|
|||||||
Lhs: []ast.Expr{ast.NewIdent("_"), ast.NewIdent("err")},
|
Lhs: []ast.Expr{ast.NewIdent("_"), ast.NewIdent("err")},
|
||||||
Tok: token.DEFINE,
|
Tok: token.DEFINE,
|
||||||
Rhs: []ast.Expr{&ast.CallExpr{
|
Rhs: []ast.Expr{&ast.CallExpr{
|
||||||
Fun: ast.NewIdent("TestDB.Get" + tbl.TypeName + "ByID"),
|
Fun: ast.NewIdent("TestDB.Get" + tbl.GoTypeName + "ByID"),
|
||||||
Args: []ast.Expr{&ast.SelectorExpr{X: testObj, Sel: ast.NewIdent("ID")}},
|
Args: []ast.Expr{&ast.SelectorExpr{X: testObj, Sel: ast.NewIdent("ID")}},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -217,7 +217,7 @@ func GenerateModelTestAST(tbl schema.Table, gomodName string) *ast.File {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testGetAll := &ast.FuncDecl{
|
testGetAll := &ast.FuncDecl{
|
||||||
Name: ast.NewIdent("TestGetAll" + inflection.Plural(tbl.TypeName)),
|
Name: ast.NewIdent("TestGetAll" + inflection.Plural(tbl.GoTypeName)),
|
||||||
Type: &ast.FuncType{Params: &ast.FieldList{List: []*ast.Field{
|
Type: &ast.FuncType{Params: &ast.FieldList{List: []*ast.Field{
|
||||||
{Names: []*ast.Ident{ast.NewIdent("t")}, Type: &ast.StarExpr{X: ast.NewIdent("testing.T")}},
|
{Names: []*ast.Ident{ast.NewIdent("t")}, Type: &ast.StarExpr{X: ast.NewIdent("testing.T")}},
|
||||||
}}, Results: nil},
|
}}, Results: nil},
|
||||||
@ -229,7 +229,7 @@ func GenerateModelTestAST(tbl schema.Table, gomodName string) *ast.File {
|
|||||||
Rhs: []ast.Expr{&ast.CallExpr{
|
Rhs: []ast.Expr{&ast.CallExpr{
|
||||||
Fun: &ast.SelectorExpr{
|
Fun: &ast.SelectorExpr{
|
||||||
X: ast.NewIdent("TestDB"),
|
X: ast.NewIdent("TestDB"),
|
||||||
Sel: ast.NewIdent("GetAll" + inflection.Plural(tbl.TypeName)),
|
Sel: ast.NewIdent("GetAll" + inflection.Plural(tbl.GoTypeName)),
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -23,7 +23,10 @@ var Checks = []Check{
|
|||||||
Explanation: "All columns should be marked as `not null` unless they are foreign keys. (Primary keys are\n" +
|
Explanation: "All columns should be marked as `not null` unless they are foreign keys. (Primary keys are\n" +
|
||||||
"automatically not-null, and don't need to be specified.)",
|
"automatically not-null, and don't need to be specified.)",
|
||||||
Execute: func(s schema.Schema) (ret []CheckResult) {
|
Execute: func(s schema.Schema) (ret []CheckResult) {
|
||||||
for tablename := range s.Tables {
|
for tablename, tbl := range s.Tables {
|
||||||
|
if tbl.TableType != "table" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
for _, column := range s.Tables[tablename].Columns {
|
for _, column := range s.Tables[tablename].Columns {
|
||||||
if !column.IsNotNull && !column.IsForeignKey && !column.IsPrimaryKey {
|
if !column.IsNotNull && !column.IsForeignKey && !column.IsPrimaryKey {
|
||||||
ret = append(ret, CheckResult{
|
ret = append(ret, CheckResult{
|
||||||
@ -43,7 +46,10 @@ var Checks = []Check{
|
|||||||
"integer, real, text, blob or any). This disallows all 'date' and 'time' column types.\n" +
|
"integer, real, text, blob or any). This disallows all 'date' and 'time' column types.\n" +
|
||||||
"See more: https://www.sqlite.org/stricttables.html",
|
"See more: https://www.sqlite.org/stricttables.html",
|
||||||
Execute: func(s schema.Schema) (ret []CheckResult) {
|
Execute: func(s schema.Schema) (ret []CheckResult) {
|
||||||
for tablename := range s.Tables {
|
for tablename, tbl := range s.Tables {
|
||||||
|
if tbl.TableType != "table" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if !s.Tables[tablename].IsStrict {
|
if !s.Tables[tablename].IsStrict {
|
||||||
ret = append(ret, CheckResult{
|
ret = append(ret, CheckResult{
|
||||||
ErrorMsg: "Table should be marked \"strict\"",
|
ErrorMsg: "Table should be marked \"strict\"",
|
||||||
@ -78,7 +84,10 @@ var Checks = []Check{
|
|||||||
Explanation: "All tables must have a primary key. If it's rowid, it has to be named explicitly.",
|
Explanation: "All tables must have a primary key. If it's rowid, it has to be named explicitly.",
|
||||||
Execute: func(s schema.Schema) (ret []CheckResult) {
|
Execute: func(s schema.Schema) (ret []CheckResult) {
|
||||||
tableloop:
|
tableloop:
|
||||||
for tablename := range s.Tables {
|
for tablename, tbl := range s.Tables {
|
||||||
|
if tbl.TableType != "table" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
for _, column := range s.Tables[tablename].Columns {
|
for _, column := range s.Tables[tablename].Columns {
|
||||||
if column.IsPrimaryKey {
|
if column.IsPrimaryKey {
|
||||||
continue tableloop
|
continue tableloop
|
||||||
@ -161,6 +170,9 @@ var Checks = []Check{
|
|||||||
Execute: func(s schema.Schema) (ret []CheckResult) {
|
Execute: func(s schema.Schema) (ret []CheckResult) {
|
||||||
tbl_loop:
|
tbl_loop:
|
||||||
for tblName, tbl := range s.Tables {
|
for tblName, tbl := range s.Tables {
|
||||||
|
if tbl.TableType != "table" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if tbl.IsWithoutRowid {
|
if tbl.IsWithoutRowid {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,14 @@ create table stuff (
|
|||||||
) strict;
|
) strict;
|
||||||
create index index_stuff_amount on stuff (amount);
|
create index index_stuff_amount on stuff (amount);
|
||||||
|
|
||||||
|
create virtual table stuff_fts using fts5(
|
||||||
|
data,
|
||||||
|
content='stuff',
|
||||||
|
content_rowid='rowid',
|
||||||
|
tokenize='trigram'
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
create table stuff2 (
|
create table stuff2 (
|
||||||
weird_pk integer primary key,
|
weird_pk integer primary key,
|
||||||
label text not null unique,
|
label text not null unique,
|
||||||
|
|||||||
@ -38,10 +38,10 @@ func SchemaFromDB(db *sqlx.DB) Schema {
|
|||||||
ret := Schema{Tables: map[string]Table{}, Indexes: map[string]Index{}}
|
ret := Schema{Tables: map[string]Table{}, Indexes: map[string]Index{}}
|
||||||
|
|
||||||
var tables []Table
|
var tables []Table
|
||||||
PanicIf(db.Select(&tables, `select name, is_strict, is_without_rowid from tables`))
|
PanicIf(db.Select(&tables, `select name, table_type, is_strict, is_without_rowid from tables`))
|
||||||
for _, tbl := range tables {
|
for _, tbl := range tables {
|
||||||
tbl.TypeName = TypenameFromTablename(tbl.TableName)
|
tbl.GoTypeName = TypenameFromTablename(tbl.TableName)
|
||||||
tbl.TypeIDName = tbl.TypeName + "ID"
|
tbl.TypeIDName = tbl.GoTypeName + "ID"
|
||||||
tbl.VarName = strings.ToLower(string(tbl.TableName[0]))
|
tbl.VarName = strings.ToLower(string(tbl.TableName[0]))
|
||||||
|
|
||||||
PanicIf(db.Select(&tbl.Columns, `select * from columns where table_name = ?`, tbl.TableName))
|
PanicIf(db.Select(&tbl.Columns, `select * from columns where table_name = ?`, tbl.TableName))
|
||||||
|
|||||||
@ -25,7 +25,7 @@ func TestParseSchema(t *testing.T) {
|
|||||||
|
|
||||||
foods := schema.Tables["foods"]
|
foods := schema.Tables["foods"]
|
||||||
assert.Equal(foods.TableName, "foods")
|
assert.Equal(foods.TableName, "foods")
|
||||||
assert.Equal(foods.TypeName, "Food")
|
assert.Equal(foods.GoTypeName, "Food")
|
||||||
assert.Equal(foods.TypeIDName, "FoodID")
|
assert.Equal(foods.TypeIDName, "FoodID")
|
||||||
assert.Equal(foods.IsStrict, true)
|
assert.Equal(foods.IsStrict, true)
|
||||||
assert.Len(foods.Columns, 20)
|
assert.Len(foods.Columns, 20)
|
||||||
|
|||||||
@ -22,15 +22,22 @@ func (c Column) IsNullableForeignKey() bool {
|
|||||||
|
|
||||||
// Table is a single SQLite table.
|
// Table is a single SQLite table.
|
||||||
type Table struct {
|
type Table struct {
|
||||||
TableName string `db:"name"`
|
TableName string `db:"name"`
|
||||||
|
|
||||||
|
// One of "table", "view", "shadow", or "virtual"
|
||||||
|
TableType string `db:"table_type"`
|
||||||
IsStrict bool `db:"is_strict"`
|
IsStrict bool `db:"is_strict"`
|
||||||
IsWithoutRowid bool `db:"is_without_rowid"`
|
IsWithoutRowid bool `db:"is_without_rowid"`
|
||||||
|
|
||||||
Columns []Column
|
Columns []Column
|
||||||
|
|
||||||
TypeIDName string
|
TypeIDName string
|
||||||
VarName string
|
|
||||||
TypeName string
|
// Default variable name for variables of this type to use when generating Go code
|
||||||
|
VarName string
|
||||||
|
|
||||||
|
// Name of corresponding model type to be generated
|
||||||
|
GoTypeName string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Index struct {
|
type Index struct {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
create temporary view tables as
|
create temporary view tables as
|
||||||
select l.schema,
|
select l.schema,
|
||||||
l.name,
|
l.name,
|
||||||
l.type,
|
l.type as table_type,
|
||||||
l.wr as is_without_rowid,
|
l.wr as is_without_rowid,
|
||||||
l.strict as is_strict
|
l.strict as is_strict
|
||||||
from sqlite_schema s
|
from sqlite_schema s
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user