139 lines
3.1 KiB
Go
139 lines
3.1 KiB
Go
package schema
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"git.secnex.io/secnex/pgson/utils"
|
|
)
|
|
|
|
type Table struct {
|
|
Name string `json:"table"`
|
|
PrimaryKey string `json:"primary_key"`
|
|
Schema []Field `json:"schema"`
|
|
}
|
|
|
|
type Field struct {
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
Nullable *bool `json:"nullable"`
|
|
Default *string `json:"default"`
|
|
Unique *bool `json:"unique"`
|
|
Primary *bool `json:"primary"`
|
|
Comment *string `json:"comment"`
|
|
References *Reference `json:"references"`
|
|
Algorithm *string `json:"algorithm"`
|
|
}
|
|
|
|
type Reference struct {
|
|
Table string `json:"table"`
|
|
Column string `json:"column"`
|
|
OnDelete string `json:"on_delete"`
|
|
OnUpdate string `json:"on_update"`
|
|
}
|
|
|
|
var fieldTypeToSQLType = map[string]string{
|
|
"string": "VARCHAR",
|
|
"int": "INTEGER",
|
|
"float": "FLOAT",
|
|
"bool": "BOOLEAN",
|
|
"date": "DATE",
|
|
"time": "TIME",
|
|
"datetime": "TIMESTAMP",
|
|
"uuid": "UUID",
|
|
"json": "JSONB",
|
|
"hash": "VARCHAR",
|
|
}
|
|
|
|
func NewTable(data []byte) (*Table, error) {
|
|
var table Table
|
|
err := json.Unmarshal(data, &table)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &table, nil
|
|
}
|
|
|
|
func (t *Table) JSON() ([]byte, error) {
|
|
return json.Marshal(t)
|
|
}
|
|
|
|
func (f *Field) SQL() string {
|
|
if !utils.IsValidIdentifier(f.Name) {
|
|
return ""
|
|
}
|
|
|
|
sqlType := fieldTypeToSQLType[f.Type]
|
|
if sqlType == "" {
|
|
return ""
|
|
}
|
|
|
|
quotedName := utils.SQLQuoteIdent(f.Name)
|
|
sql := fmt.Sprintf("%s %s", quotedName, sqlType)
|
|
|
|
if f.Nullable != nil && !*f.Nullable {
|
|
sql += " NOT NULL"
|
|
}
|
|
|
|
if f.Primary != nil && *f.Primary {
|
|
sql += " PRIMARY KEY"
|
|
if f.Default == nil && f.Type == "uuid" {
|
|
sql += " DEFAULT uuid_generate_v4()"
|
|
}
|
|
}
|
|
|
|
if f.Unique != nil && *f.Unique {
|
|
sql += " UNIQUE"
|
|
}
|
|
|
|
if f.Default != nil && f.Primary == nil {
|
|
def := *f.Default
|
|
if utils.IsValidDefault(def) {
|
|
switch {
|
|
case utils.IsValidDefault(def):
|
|
if utils.IsValidDefault(def) && (def == "CURRENT_TIMESTAMP" || def == "now()" || def == "uuid_generate_v4()") {
|
|
sql += fmt.Sprintf(" DEFAULT %s", def)
|
|
} else {
|
|
sql += fmt.Sprintf(" DEFAULT %s", utils.SQLQuoteValue(def))
|
|
}
|
|
}
|
|
} else {
|
|
return ""
|
|
}
|
|
}
|
|
if f.References != nil {
|
|
ref := f.References
|
|
if !utils.IsValidIdentifier(ref.Table) || !utils.IsValidIdentifier(ref.Column) {
|
|
return ""
|
|
}
|
|
sql += fmt.Sprintf(" REFERENCES %s(%s)", utils.SQLQuoteIdent(ref.Table), utils.SQLQuoteIdent(ref.Column))
|
|
if ref.OnDelete != "" {
|
|
action, err := utils.SanitizeOnAction(ref.OnDelete)
|
|
if err == nil && action != "" {
|
|
sql += fmt.Sprintf(" ON DELETE %s", action)
|
|
}
|
|
}
|
|
if ref.OnUpdate != "" {
|
|
action, err := utils.SanitizeOnAction(ref.OnUpdate)
|
|
if err == nil && action != "" {
|
|
sql += fmt.Sprintf(" ON UPDATE %s", action)
|
|
}
|
|
}
|
|
}
|
|
|
|
return sql
|
|
}
|
|
|
|
func (f *Field) SQLReferences() string {
|
|
if f.References == nil {
|
|
return ""
|
|
}
|
|
ref := f.References
|
|
|
|
if !utils.IsValidIdentifier(ref.Table) || !utils.IsValidIdentifier(ref.Column) {
|
|
return ""
|
|
}
|
|
|
|
return fmt.Sprintf(" REFERENCES %s(%s)", utils.SQLQuoteIdent(ref.Table), utils.SQLQuoteIdent(ref.Column))
|
|
}
|