70 lines
1.8 KiB
Go
70 lines
1.8 KiB
Go
package schema
|
|
|
|
import (
|
|
_ "embed"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/jinzhu/inflection"
|
|
"github.com/jmoiron/sqlx"
|
|
_ "github.com/mattn/go-sqlite3"
|
|
|
|
"git.offline-twitter.com/offline-labs/gas-stack/pkg/textutils"
|
|
)
|
|
|
|
//go:embed views.sql
|
|
var create_views string
|
|
|
|
// InitDB creates an in-memory DB from a given schema string.
|
|
func InitDB(sql_schema string) *sqlx.DB {
|
|
db := sqlx.MustOpen("sqlite3", ":memory:")
|
|
db.MustExec(sql_schema)
|
|
db.MustExec(create_views)
|
|
return db
|
|
}
|
|
|
|
func SchemaFromSQLFile(filepath string) (Schema, error) {
|
|
sqlBytes, err := os.ReadFile(filepath)
|
|
if err != nil {
|
|
return Schema{}, fmt.Errorf("failed to read SQL file: %w", err)
|
|
}
|
|
return SchemaFromDB(InitDB(string(sqlBytes))), nil
|
|
}
|
|
|
|
// SchemaFromDB takes a DB connection, checks its schema metadata tables, and returns a Schema.
|
|
func SchemaFromDB(db *sqlx.DB) Schema {
|
|
ret := Schema{Tables: map[string]Table{}, Indexes: map[string]Index{}}
|
|
|
|
var tables []Table
|
|
err := db.Select(&tables, `select name, is_strict, is_without_rowid from tables`)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
for _, tbl := range tables {
|
|
tbl.TypeName = textutils.SnakeToCamel(inflection.Singular(tbl.TableName))
|
|
tbl.TypeIDName = tbl.TypeName + "ID"
|
|
tbl.VarName = strings.ToLower(string(tbl.TableName[0]))
|
|
|
|
err = db.Select(&tbl.Columns, `select * from columns where table_name = ?`, tbl.TableName)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
ret.Tables[tbl.TableName] = tbl
|
|
}
|
|
|
|
var indexes []Index
|
|
err = db.Select(&indexes, `select index_name, table_name, is_unique from indexes`)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
for _, idx := range indexes {
|
|
err = db.Select(&idx.Columns, `select column_name from index_columns where index_name = ? order by rank`, idx.Name)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
ret.Indexes[idx.Name] = idx
|
|
}
|
|
return ret
|
|
}
|