111 lines
2.8 KiB
Go
111 lines
2.8 KiB
Go
package schema
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"git.offline-twitter.com/offline-labs/gas-stack/pkg/textutils"
|
|
)
|
|
|
|
// 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"`
|
|
IsNotNull bool `db:"notnull"`
|
|
HasDefaultValue bool `db:"has_default_value"`
|
|
DefaultValue string `db:"dflt_value"`
|
|
IsPrimaryKey bool `db:"is_primary_key"`
|
|
PrimaryKeyRank uint `db:"primary_key_rank"`
|
|
IsForeignKey bool `db:"is_foreign_key"`
|
|
ForeignKeyTargetTable string `db:"fk_target_table"`
|
|
ForeignKeyTargetColumn string `db:"fk_target_column"`
|
|
}
|
|
|
|
// IsNullableForeignKey is a helper function.
|
|
func (c Column) IsNullableForeignKey() bool {
|
|
return !c.IsNotNull && !c.IsPrimaryKey && c.IsForeignKey
|
|
}
|
|
|
|
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"`
|
|
|
|
// One of "table", "view", "shadow", or "virtual"
|
|
TableType string `db:"table_type"`
|
|
IsStrict bool `db:"is_strict"`
|
|
IsWithoutRowid bool `db:"is_without_rowid"`
|
|
|
|
Columns []Column
|
|
|
|
TypeIDName 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
|
|
}
|
|
|
|
func (t Table) HasAutoTimestamps() (hasCreatedAt bool, hasUpdatedAt bool) {
|
|
for _, c := range t.Columns {
|
|
if c.Name == "created_at" && c.Type == "integer" {
|
|
hasCreatedAt = true
|
|
}
|
|
if c.Name == "updated_at" && c.Type == "integer" {
|
|
hasUpdatedAt = true
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
type Index struct {
|
|
Name string `db:"index_name"`
|
|
TableName string `db:"table_name"`
|
|
Columns []string
|
|
IsUnique bool `db:"is_unique"`
|
|
// TODO: `where ...` for partial indexes
|
|
// TODO: identify columns that are expressions
|
|
}
|
|
|
|
type Schema struct {
|
|
Tables map[string]Table
|
|
Indexes map[string]Index
|
|
}
|