Compare commits
2 Commits
4cba2af670
...
5cbb657666
| Author | SHA1 | Date | |
|---|---|---|---|
| 5cbb657666 | |||
| b8a024a4b9 |
12
doc/TODO.txt
12
doc/TODO.txt
@ -1,17 +1,9 @@
|
||||
TODO: auto-timestamps
|
||||
- SaveXyz should set created_at and updated_at; shouldn't touch is_deleted or deleted_at
|
||||
TODO: soft-deletion
|
||||
- enable soft-deletion if table has `is_deleted` and `deleted_at` fields
|
||||
- if soft delete is enabled, DeleteXyz should do update (not delete) and set is_deleted and deleted_at
|
||||
- ...and DeleteXyz should have pointer receiver for soft-delete
|
||||
- SaveXyz shouldn't set created_at in the do-update branch
|
||||
- GetXyzByID should include `ErrItemIsDeleted` if item is soft-deleted
|
||||
|
||||
TODO: modified-timestamps
|
||||
- set updated_at and created_at in SaveXYZ
|
||||
- soft delete option
|
||||
|
||||
TODO: generator-foreign-keys
|
||||
- add auto-foreign-key checking blocks to SaveXyz
|
||||
|
||||
TODO: migration-structs
|
||||
- Right now, migrations are strings. Could be a struct with "name", "up" and "down" fields
|
||||
- Adding a "down" operation enables handling newer DB versions with "down instead of error-out" for development (perhaps a flag)
|
||||
|
||||
@ -27,14 +27,6 @@ func SQLFieldsConstIdent(tbl schema.Table) *ast.Ident {
|
||||
return ast.NewIdent(strings.ToLower(tbl.GoTypeName) + "SQLFields")
|
||||
}
|
||||
|
||||
func fkFieldName(col schema.Column) string {
|
||||
if col.IsNonCodeTableForeignKey() {
|
||||
return textutils.SnakeToCamel(strings.TrimSuffix(col.Name, "_id")) + "ID"
|
||||
} else {
|
||||
return textutils.SnakeToCamel(col.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------
|
||||
// Generators
|
||||
// ---------------
|
||||
@ -66,31 +58,12 @@ func GenerateModelAST(table schema.Table) *ast.GenDecl {
|
||||
default:
|
||||
if col.IsNonCodeTableForeignKey() {
|
||||
fields = append(fields, &ast.Field{
|
||||
Names: []*ast.Ident{ast.NewIdent(fkFieldName(col))},
|
||||
Names: []*ast.Ident{ast.NewIdent(col.GoFieldName())},
|
||||
Type: ast.NewIdent(schema.TypenameFromTablename(col.ForeignKeyTargetTable) + "ID"),
|
||||
Tag: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("`db:\"%s\" json:\"%s\"`", col.Name, col.Name)},
|
||||
})
|
||||
} else {
|
||||
typeName := "string"
|
||||
switch col.Type {
|
||||
case "integer", "int":
|
||||
if strings.HasPrefix(col.Name, "is_") || strings.HasPrefix(col.Name, "has_") {
|
||||
typeName = "bool"
|
||||
} else if strings.HasSuffix(col.Name, "_at") {
|
||||
typeName = "Timestamp"
|
||||
} else {
|
||||
typeName = "int"
|
||||
}
|
||||
case "text":
|
||||
typeName = "string"
|
||||
case "real":
|
||||
typeName = "float32"
|
||||
case "blob":
|
||||
typeName = "[]byte"
|
||||
default:
|
||||
panic("Unrecognized sqlite column type: " + col.Type)
|
||||
}
|
||||
|
||||
typeName := col.GoType()
|
||||
fields = append(fields, &ast.Field{
|
||||
Names: []*ast.Ident{ast.NewIdent(textutils.SnakeToCamel(col.Name))},
|
||||
Type: ast.NewIdent(typeName),
|
||||
@ -170,7 +143,7 @@ func GenerateSaveItemFunc(tbl schema.Table) *ast.FuncDecl {
|
||||
}
|
||||
hasFks = true
|
||||
|
||||
structFieldName := fkFieldName(col)
|
||||
structFieldName := col.GoFieldName()
|
||||
structField := &ast.SelectorExpr{X: ast.NewIdent(tbl.VarName), Sel: ast.NewIdent(structFieldName)}
|
||||
|
||||
if col.IsNonCodeTableForeignKey() {
|
||||
|
||||
@ -305,7 +305,7 @@ func GenerateModelTestAST(tbl schema.Table, gomodName string) *ast.File {
|
||||
Lhs: []ast.Expr{
|
||||
&ast.SelectorExpr{
|
||||
X: ast.NewIdent(tbl.VarName),
|
||||
Sel: ast.NewIdent(fkFieldName(col)),
|
||||
Sel: ast.NewIdent(col.GoFieldName()),
|
||||
},
|
||||
},
|
||||
Tok: token.ASSIGN,
|
||||
@ -346,11 +346,11 @@ func GenerateModelTestAST(tbl schema.Table, gomodName string) *ast.File {
|
||||
ast.NewIdent("err"),
|
||||
&ast.BasicLit{
|
||||
Kind: token.STRING,
|
||||
Value: fmt.Sprintf("%q", fkFieldName(col)),
|
||||
Value: fmt.Sprintf("%q", col.GoFieldName()),
|
||||
},
|
||||
&ast.SelectorExpr{
|
||||
X: ast.NewIdent(tbl.VarName),
|
||||
Sel: ast.NewIdent(fkFieldName(col)),
|
||||
Sel: ast.NewIdent(col.GoFieldName()),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
package schema
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.offline-twitter.com/offline-labs/gas-stack/pkg/textutils"
|
||||
)
|
||||
|
||||
// Column represents a single column in a table.
|
||||
type Column struct {
|
||||
@ -26,6 +30,39 @@ func (c Column) IsNonCodeTableForeignKey() bool {
|
||||
return c.IsForeignKey && strings.HasSuffix(c.Name, "_id")
|
||||
}
|
||||
|
||||
func (c Column) GoFieldName() string {
|
||||
if c.Name == "rowid" {
|
||||
return "ID"
|
||||
}
|
||||
if c.IsNonCodeTableForeignKey() {
|
||||
return textutils.SnakeToCamel(strings.TrimSuffix(c.Name, "_id")) + "ID"
|
||||
}
|
||||
return textutils.SnakeToCamel(c.Name)
|
||||
}
|
||||
|
||||
func (c Column) GoType() string {
|
||||
if c.IsNonCodeTableForeignKey() {
|
||||
return TypenameFromTablename(c.ForeignKeyTargetTable) + "ID"
|
||||
}
|
||||
switch c.Type {
|
||||
case "integer", "int":
|
||||
if strings.HasPrefix(c.Name, "is_") || strings.HasPrefix(c.Name, "has_") {
|
||||
return "bool"
|
||||
} else if strings.HasSuffix(c.Name, "_at") {
|
||||
return "Timestamp"
|
||||
}
|
||||
return "int"
|
||||
case "text":
|
||||
return "string"
|
||||
case "real":
|
||||
return "float32"
|
||||
case "blob":
|
||||
return "[]byte"
|
||||
default:
|
||||
panic("Unrecognized sqlite column type: " + c.Type)
|
||||
}
|
||||
}
|
||||
|
||||
// Table is a single SQLite table.
|
||||
type Table struct {
|
||||
TableName string `db:"name"`
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user