mirror of
https://github.com/neilotoole/sq.git
synced 2024-12-22 15:41:35 +03:00
2898a92983
* Refactor sqlmodel pkg
128 lines
3.3 KiB
Go
128 lines
3.3 KiB
Go
// Package schema provides functionality for modeling SQL constructs.
|
|
package schema
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/neilotoole/sq/libsq/core/errz"
|
|
"github.com/neilotoole/sq/libsq/core/kind"
|
|
)
|
|
|
|
// Table models a database table definition.
|
|
type Table struct {
|
|
// Name is the table name.
|
|
Name string `json:"name"`
|
|
|
|
// PKColName is the name of the primary key column, or empty.
|
|
//
|
|
// REVISIT: this construct does not allow for composite PK.
|
|
PKColName string `json:"primary_key,omitempty"`
|
|
|
|
// AutoIncrement, if true, indicates that a PK column
|
|
// should autoincrement.
|
|
//
|
|
// REVISIT: this construct does not allow for composite PK.
|
|
AutoIncrement bool `json:"auto_increment"`
|
|
|
|
// Cols is the table's column definitions.
|
|
Cols []*Column `json:"cols"`
|
|
}
|
|
|
|
// NewTable is a convenience constructor for creating
|
|
// a simple table definition.
|
|
func NewTable(tblName string, colNames []string, colKinds []kind.Kind) *Table {
|
|
tblDef := &Table{Name: tblName}
|
|
cols := make([]*Column, len(colNames))
|
|
|
|
for i := range colNames {
|
|
cols[i] = &Column{Table: tblDef, Name: colNames[i], Kind: colKinds[i]}
|
|
}
|
|
|
|
tblDef.Cols = cols
|
|
return tblDef
|
|
}
|
|
|
|
// ColNames returns a new slice containing the names
|
|
// of t's columns.
|
|
func (t *Table) ColNames() []string {
|
|
names := make([]string, len(t.Cols))
|
|
for i, col := range t.Cols {
|
|
names[i] = col.Name
|
|
}
|
|
return names
|
|
}
|
|
|
|
// ColKinds returns a new slice containing the kinds
|
|
// of t's columns.
|
|
func (t *Table) ColKinds() []kind.Kind {
|
|
kinds := make([]kind.Kind, len(t.Cols))
|
|
for i, col := range t.Cols {
|
|
kinds[i] = col.Kind
|
|
}
|
|
return kinds
|
|
}
|
|
|
|
func (t *Table) String() string {
|
|
return t.Name + "(" + strings.Join(t.ColNames(), ",") + ")"
|
|
}
|
|
|
|
// ColsByName returns the ColDefs for each named column, or an error if any column
|
|
// is not matched.
|
|
func (t *Table) ColsByName(cols []string) ([]*Column, error) {
|
|
defs := make([]*Column, len(cols))
|
|
|
|
for i, name := range cols {
|
|
found := false
|
|
for _, def := range t.Cols {
|
|
if def.Name == name {
|
|
defs[i] = def
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
return nil, errz.Errorf("could not find column definition {%s} in table {%s}", name, t.Name)
|
|
}
|
|
}
|
|
return defs, nil
|
|
}
|
|
|
|
// FindCol returns the named Column or nil if not found.
|
|
func (t *Table) FindCol(name string) (*Column, error) {
|
|
for _, col := range t.Cols {
|
|
if col.Name == name {
|
|
return col, nil
|
|
}
|
|
}
|
|
return nil, errz.Errorf("could not find column definition {%s} in table {%s}", name, t.Name)
|
|
}
|
|
|
|
// Column models a table column definition.
|
|
type Column struct {
|
|
Name string `json:"name"`
|
|
Table *Table `json:"-"`
|
|
Kind kind.Kind `json:"kind"`
|
|
|
|
NotNull bool `json:"not_null"`
|
|
HasDefault bool `json:"has_default"`
|
|
|
|
// Size typically applies to text fields, e.g. VARCHAR(255).
|
|
Size int `json:"size"`
|
|
|
|
Unique bool `json:"unique"`
|
|
ForeignKey *FKConstraint `json:"foreign_key,omitempty"`
|
|
}
|
|
|
|
// FKConstraint models a foreign key constraint.
|
|
type FKConstraint struct {
|
|
// RefTable is the name of the referenced parent table.
|
|
RefTable string `json:"ref_table"`
|
|
// RefCol is the name of the referenced col in the parent table.
|
|
RefCol string `json:"ref_col"`
|
|
// OnDelete is one of CASCADE or SET_NULL, defaults to CASCADE.
|
|
OnDelete string `json:"on_delete"`
|
|
// OnUpdate is one of CASCADE or SET_NULL, defaults to CASCADE.
|
|
OnUpdate string `json:"on_update"`
|
|
}
|