Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
aarondl committed Sep 25, 2016
2 parents 0cf3939 + 32290d9 commit 05d9018
Show file tree
Hide file tree
Showing 33 changed files with 800 additions and 519 deletions.
2 changes: 1 addition & 1 deletion bdb/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func Tables(db Interface, schema string, whitelist, blacklist []string) ([]Table
// A composite primary key involving two columns
// Both primary key columns are also foreign keys
func setIsJoinTable(t *Table) {
if t.PKey == nil || len(t.PKey.Columns) != 2 || len(t.FKeys) < 2 {
if t.PKey == nil || len(t.PKey.Columns) != 2 || len(t.FKeys) < 2 || len(t.Columns) > 2 {
return
}

Expand Down
35 changes: 1 addition & 34 deletions bdb/keys.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
package bdb

import (
"fmt"
"regexp"
"strings"
)

var rgxAutoIncColumn = regexp.MustCompile(`^nextval\(.*\)`)
import "fmt"

// PrimaryKey represents a primary key constraint in a database
type PrimaryKey struct {
Expand Down Expand Up @@ -80,30 +74,3 @@ func SQLColDefinitions(cols []Column, names []string) SQLColumnDefs {

return ret
}

// AutoIncPrimaryKey returns the auto-increment primary key column name or an
// empty string. Primary key columns with default values are presumed
// to be auto-increment, because pkeys need to be unique and a static
// default value would cause collisions.
func AutoIncPrimaryKey(cols []Column, pkey *PrimaryKey) *Column {
if pkey == nil {
return nil
}

for _, pkeyColumn := range pkey.Columns {
for _, c := range cols {
if c.Name != pkeyColumn {
continue
}

if c.Default != "auto_increment" || c.Nullable ||
!(strings.HasPrefix(c.Type, "int") || strings.HasPrefix(c.Type, "uint")) {
continue
}

return &c
}
}

return nil
}
47 changes: 23 additions & 24 deletions bdb/relationships.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func toManyRelationships(table Table, tables []Table) []ToManyRelationship {

for _, t := range tables {
for _, f := range t.FKeys {
if f.ForeignTable == table.Name && !f.Unique {
if f.ForeignTable == table.Name && (t.IsJoinTable || !f.Unique) {
relationships = append(relationships, buildToManyRelationship(table, f, t, tables))
}
}
Expand All @@ -101,12 +101,11 @@ func buildToOneRelationship(localTable Table, foreignKey ForeignKey, foreignTabl

func buildToManyRelationship(localTable Table, foreignKey ForeignKey, foreignTable Table, tables []Table) ToManyRelationship {
if !foreignTable.IsJoinTable {
col := localTable.GetColumn(foreignKey.ForeignColumn)
return ToManyRelationship{
Table: localTable.Name,
Column: foreignKey.ForeignColumn,
Nullable: col.Nullable,
Unique: col.Unique,
Nullable: foreignKey.ForeignColumnNullable,
Unique: foreignKey.ForeignColumnUnique,
ForeignTable: foreignTable.Name,
ForeignColumn: foreignKey.Column,
ForeignColumnNullable: foreignKey.Nullable,
Expand All @@ -115,33 +114,33 @@ func buildToManyRelationship(localTable Table, foreignKey ForeignKey, foreignTab
}
}

col := foreignTable.GetColumn(foreignKey.Column)
relationship := ToManyRelationship{
Table: localTable.Name,
Column: foreignKey.ForeignColumn,
Nullable: col.Nullable,
Unique: col.Unique,
Table: localTable.Name,
Column: foreignKey.ForeignColumn,
Nullable: foreignKey.ForeignColumnNullable,
Unique: foreignKey.ForeignColumnUnique,

ToJoinTable: true,
JoinTable: foreignTable.Name,

JoinLocalColumn: foreignKey.Column,
JoinLocalColumnNullable: foreignKey.Nullable,
JoinLocalColumnUnique: foreignKey.Unique,
}

for _, fk := range foreignTable.FKeys {
if fk.ForeignTable != localTable.Name {
relationship.JoinForeignColumn = fk.Column
relationship.JoinForeignColumnNullable = fk.Nullable
relationship.JoinForeignColumnUnique = fk.Unique

foreignTable := GetTable(tables, fk.ForeignTable)
foreignCol := foreignTable.GetColumn(fk.ForeignColumn)
relationship.ForeignTable = fk.ForeignTable
relationship.ForeignColumn = fk.ForeignColumn
relationship.ForeignColumnNullable = foreignCol.Nullable
relationship.ForeignColumnUnique = foreignCol.Unique
} else {
relationship.JoinLocalColumn = fk.Column
relationship.JoinLocalColumnNullable = fk.Nullable
relationship.JoinLocalColumnUnique = fk.Unique
if fk.Name == foreignKey.Name {
continue
}

relationship.JoinForeignColumn = fk.Column
relationship.JoinForeignColumnNullable = fk.Nullable
relationship.JoinForeignColumnUnique = fk.Unique

relationship.ForeignTable = fk.ForeignTable
relationship.ForeignColumn = fk.ForeignColumn
relationship.ForeignColumnNullable = fk.ForeignColumnNullable
relationship.ForeignColumnUnique = fk.ForeignColumnUnique
}

return relationship
Expand Down
10 changes: 5 additions & 5 deletions bdb/relationships_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,15 +213,15 @@ func TestToManyRelationshipsNull(t *testing.T) {
Name: "jets",
Columns: []Column{{Name: "id", Nullable: true}, {Name: "pilot_id", Nullable: true}, {Name: "airport_id", Nullable: true}},
FKeys: []ForeignKey{
{Name: "jets_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true},
{Name: "jets_airport_id_fk", Column: "airport_id", ForeignTable: "airports", ForeignColumn: "id", Nullable: true},
{Name: "jets_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true, ForeignColumnNullable: true},
{Name: "jets_airport_id_fk", Column: "airport_id", ForeignTable: "airports", ForeignColumn: "id", Nullable: true, ForeignColumnNullable: true},
},
},
{
Name: "licenses",
Columns: []Column{{Name: "id", Nullable: true}, {Name: "pilot_id", Nullable: true}},
FKeys: []ForeignKey{
{Name: "licenses_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true},
{Name: "licenses_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true, ForeignColumnNullable: true},
},
},
{
Expand All @@ -237,8 +237,8 @@ func TestToManyRelationshipsNull(t *testing.T) {
IsJoinTable: true,
Columns: []Column{{Name: "pilot_id", Nullable: true}, {Name: "language_id", Nullable: true}},
FKeys: []ForeignKey{
{Name: "pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true},
{Name: "language_id_fk", Column: "language_id", ForeignTable: "languages", ForeignColumn: "id", Nullable: true},
{Name: "pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true, ForeignColumnNullable: true},
{Name: "language_id_fk", Column: "language_id", ForeignTable: "languages", ForeignColumn: "id", Nullable: true, ForeignColumnNullable: true},
},
},
}
Expand Down
24 changes: 24 additions & 0 deletions bdb/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,27 @@ func (t Table) GetColumn(name string) (col Column) {

panic(fmt.Sprintf("could not find column name: %s", name))
}

// CanLastInsertID checks the following:
// 1. Is there only one primary key?
// 2. Does the primary key column have a default value?
// 3. Is the primary key column type one of uintX/intX?
// If the above is all true, this table can use LastInsertId
func (t Table) CanLastInsertID() bool {
if t.PKey == nil || len(t.PKey.Columns) != 1 {
return false
}

col := t.GetColumn(t.PKey.Columns[0])
if len(col.Default) == 0 {
return false
}

switch col.Type {
case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64":
default:
return false
}

return true
}
53 changes: 53 additions & 0 deletions bdb/table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,56 @@ func TestGetColumnMissing(t *testing.T) {

table.GetColumn("missing")
}

func TestCanLastInsertID(t *testing.T) {
t.Parallel()

tests := []struct {
Can bool
PKeys []Column
}{
{true, []Column{
{Name: "id", Type: "int64", Default: "a"},
}},
{true, []Column{
{Name: "id", Type: "uint64", Default: "a"},
}},
{true, []Column{
{Name: "id", Type: "int", Default: "a"},
}},
{true, []Column{
{Name: "id", Type: "uint", Default: "a"},
}},
{true, []Column{
{Name: "id", Type: "uint", Default: "a"},
}},
{false, []Column{
{Name: "id", Type: "uint", Default: "a"},
{Name: "id2", Type: "uint", Default: "a"},
}},
{false, []Column{
{Name: "id", Type: "string", Default: "a"},
}},
{false, []Column{
{Name: "id", Type: "int", Default: ""},
}},
{false, nil},
}

for i, test := range tests {
table := Table{
Columns: test.PKeys,
PKey: &PrimaryKey{},
}

var pkeyNames []string
for _, pk := range test.PKeys {
pkeyNames = append(pkeyNames, pk.Name)
}
table.PKey.Columns = pkeyNames

if got := table.CanLastInsertID(); got != test.Can {
t.Errorf("%d) wrong: %t", i, got)
}
}
}
Loading

0 comments on commit 05d9018

Please sign in to comment.