sqlboiler/bdb/interface.go

124 lines
3.3 KiB
Go
Raw Normal View History

// Package bdb supplies the sql(b)oiler (d)ata(b)ase abstractions.
package bdb
import "github.com/pkg/errors"
2016-04-03 09:15:35 +02:00
2016-03-23 05:25:57 +01:00
// Interface for a database driver. Functionality required to support a specific
// database type (eg, MySQL, Postgres etc.)
type Interface interface {
2016-09-09 07:41:57 +02:00
TableNames(schema string, whitelist, blacklist []string) ([]string, error)
Columns(schema, tableName string) ([]Column, error)
PrimaryKeyInfo(schema, tableName string) (*PrimaryKey, error)
ForeignKeyInfo(schema, tableName string) ([]ForeignKey, error)
2016-03-23 05:25:57 +01:00
2016-04-03 09:15:35 +02:00
// TranslateColumnType takes a Database column type and returns a go column type.
TranslateColumnType(Column) Column
2016-08-14 01:27:34 +02:00
// UseLastInsertID should return true if the driver is capable of using
// the sql.Exec result's LastInsertId
UseLastInsertID() bool
// Open the database connection
Open() error
// Close the database connection
Close()
2016-09-09 19:14:18 +02:00
// Dialect helpers, these provide the values that will go into
// a boil.Dialect, so the query builder knows how to support
// your database driver properly.
2016-09-09 19:30:46 +02:00
LeftQuote() byte
RightQuote() byte
2016-09-09 19:14:18 +02:00
IndexPlaceholders() bool
}
2016-08-16 12:38:31 +02:00
// Tables returns the metadata for all tables, minus the tables
2016-09-09 07:41:57 +02:00
// specified in the blacklist.
func Tables(db Interface, schema string, whitelist, blacklist []string) ([]Table, error) {
2016-04-03 09:15:35 +02:00
var err error
2016-08-15 14:42:40 +02:00
2016-09-09 07:41:57 +02:00
names, err := db.TableNames(schema, whitelist, blacklist)
2016-08-15 14:42:40 +02:00
if err != nil {
return nil, errors.Wrap(err, "unable to get table names")
2016-04-03 09:15:35 +02:00
}
var tables []Table
for _, name := range names {
t := Table{
Name: name,
}
2016-04-03 09:15:35 +02:00
if t.Columns, err = db.Columns(schema, name); err != nil {
return nil, errors.Wrapf(err, "unable to fetch table column info (%s)", name)
2016-04-03 09:15:35 +02:00
}
for i, c := range t.Columns {
t.Columns[i] = db.TranslateColumnType(c)
}
if t.PKey, err = db.PrimaryKeyInfo(schema, name); err != nil {
return nil, errors.Wrapf(err, "unable to fetch table pkey info (%s)", name)
2016-04-03 09:15:35 +02:00
}
if t.FKeys, err = db.ForeignKeyInfo(schema, name); err != nil {
return nil, errors.Wrapf(err, "unable to fetch table fkey info (%s)", name)
2016-04-03 09:15:35 +02:00
}
setIsJoinTable(&t)
tables = append(tables, t)
}
// Relationships have a dependency on foreign key nullability.
for i := range tables {
tbl := &tables[i]
2016-07-15 21:09:32 +02:00
setForeignKeyConstraints(tbl, tables)
}
for i := range tables {
tbl := &tables[i]
setRelationships(tbl, tables)
}
2016-04-03 09:15:35 +02:00
return tables, nil
}
// setIsJoinTable if there are:
// A composite primary key involving two columns
2016-04-03 10:02:41 +02:00
// Both primary key columns are also foreign keys
2016-04-03 09:15:35 +02:00
func setIsJoinTable(t *Table) {
2016-04-03 10:02:41 +02:00
if t.PKey == nil || len(t.PKey.Columns) != 2 || len(t.FKeys) < 2 {
2016-04-03 09:15:35 +02:00
return
}
for _, c := range t.PKey.Columns {
found := false
for _, f := range t.FKeys {
if c == f.Column {
found = true
break
}
}
if !found {
return
}
}
t.IsJoinTable = true
}
2016-07-15 21:09:32 +02:00
func setForeignKeyConstraints(t *Table, tables []Table) {
for i, fkey := range t.FKeys {
localColumn := t.GetColumn(fkey.Column)
foreignTable := GetTable(tables, fkey.ForeignTable)
foreignColumn := foreignTable.GetColumn(fkey.ForeignColumn)
t.FKeys[i].Nullable = localColumn.Nullable
2016-07-15 21:09:32 +02:00
t.FKeys[i].Unique = localColumn.Unique
t.FKeys[i].ForeignColumnNullable = foreignColumn.Nullable
2016-07-15 21:09:32 +02:00
t.FKeys[i].ForeignColumnUnique = foreignColumn.Unique
}
}
func setRelationships(t *Table, tables []Table) {
t.ToManyRelationships = toManyRelationships(*t, tables)
}