Use hash's as ids for table relationships

This commit is contained in:
Vikram Rangnekar
2019-05-14 22:32:12 -04:00
parent e1d3bb9055
commit 58408eadc1
7 changed files with 116 additions and 41 deletions

View File

@ -30,7 +30,7 @@ func NewCompiler(conf Config) *Compiler {
return &Compiler{conf.Schema, conf.Vars, conf.TableMap}
}
func (c *Compiler) AddRelationship(key TTKey, val *DBRel) {
func (c *Compiler) AddRelationship(key uint64, val *DBRel) {
c.schema.RelMap[key] = val
}
@ -139,9 +139,8 @@ func (v *selectBlock) processChildren() (uint32, []*qcode.Column) {
for _, id := range v.sel.Children {
child := &v.qc.Query.Selects[id]
k := TTKey{child.Table, v.sel.Table}
rel, ok := v.schema.RelMap[k]
rel, ok := v.schema.RelMap[child.RelID]
if !ok {
skipped |= (1 << uint(id))
continue
@ -290,8 +289,7 @@ func (v *joinClose) render(w io.Writer) error {
}
func (v *selectBlock) renderJoinTable(w io.Writer) {
k := TTKey{v.sel.Table, v.parent.Table}
rel, ok := v.schema.RelMap[k]
rel, ok := v.schema.RelMap[v.sel.RelID]
if !ok {
panic(errors.New("no relationship found"))
}
@ -315,14 +313,12 @@ func (v *selectBlock) renderColumns(w io.Writer) {
}
func (v *selectBlock) renderRemoteRelColumns(w io.Writer) {
k := TTKey{Table2: v.sel.Table}
i := 0
for _, id := range v.sel.Children {
child := &v.qc.Query.Selects[id]
k.Table1 = child.Table
rel, ok := v.schema.RelMap[k]
rel, ok := v.schema.RelMap[child.RelID]
if !ok || rel.Type != RelRemote {
continue
}
@ -489,8 +485,7 @@ func (v *selectBlock) renderOrderByColumns(w io.Writer) {
}
func (v *selectBlock) renderRelationship(w io.Writer) {
k := TTKey{v.sel.Table, v.parent.Table}
rel, ok := v.schema.RelMap[k]
rel, ok := v.schema.RelMap[v.sel.RelID]
if !ok {
panic(errors.New("no relationship found"))
}

View File

@ -100,7 +100,7 @@ func TestMain(m *testing.M) {
schema := &DBSchema{
Tables: make(map[string]*DBTableInfo),
RelMap: make(map[TTKey]*DBRel),
RelMap: make(map[uint64]*DBRel),
}
for i, t := range tables {

View File

@ -4,20 +4,13 @@ import (
"fmt"
"strings"
"github.com/cespare/xxhash/v2"
"github.com/go-pg/pg"
)
type TCKey struct {
Table, Column string
}
type TTKey struct {
Table1, Table2 string
}
type DBSchema struct {
Tables map[string]*DBTableInfo
RelMap map[TTKey]*DBRel
RelMap map[uint64]*DBRel
}
type DBTableInfo struct {
@ -47,7 +40,7 @@ type DBRel struct {
func NewDBSchema(db *pg.DB) (*DBSchema, error) {
schema := &DBSchema{
Tables: make(map[string]*DBTableInfo),
RelMap: make(map[TTKey]*DBRel),
RelMap: make(map[uint64]*DBRel),
}
tables, err := GetTables(db)
@ -87,6 +80,8 @@ func (s *DBSchema) updateSchema(t *DBTable, cols []*DBColumn) {
ct := strings.ToLower(t.Name)
s.Tables[ct] = ti
h := xxhash.New()
for _, c := range cols {
switch {
case c.Type == "tsvector":
@ -110,12 +105,12 @@ func (s *DBSchema) updateSchema(t *DBTable, cols []*DBColumn) {
// Belongs-to relation between current table and the
// table in the foreign key
rel1 := &DBRel{RelBelongTo, "", "", c.Name, fc.Name}
s.RelMap[TTKey{ct, ft}] = rel1
s.RelMap[relID(h, ct, ft)] = rel1
// One-to-many relation between the foreign key table and the
// the current table
rel2 := &DBRel{RelOneToMany, "", "", fc.Name, c.Name}
s.RelMap[TTKey{ft, ct}] = rel2
s.RelMap[relID(h, ft, ct)] = rel2
jcols = append(jcols, c)
}
@ -131,7 +126,7 @@ func (s *DBSchema) updateSchema(t *DBTable, cols []*DBColumn) {
for i := range jcols {
for n := range jcols {
if n != i {
s.updateSchemaOTMT(ct, jcols[i], jcols[n], colByID)
s.updateSchemaOTMT(h, ct, jcols[i], jcols[n], colByID)
}
}
}
@ -139,7 +134,10 @@ func (s *DBSchema) updateSchema(t *DBTable, cols []*DBColumn) {
}
func (s *DBSchema) updateSchemaOTMT(
ct string, col1, col2 *DBColumn, colByID map[int]*DBColumn) {
h *xxhash.Digest,
ct string,
col1, col2 *DBColumn,
colByID map[int]*DBColumn) {
t1 := strings.ToLower(col1.FKeyTable)
t2 := strings.ToLower(col2.FKeyTable)
@ -157,13 +155,13 @@ func (s *DBSchema) updateSchemaOTMT(
// 2nd foreign key table
//rel1 := &DBRel{RelOneToManyThrough, ct, fc1.Name, col1.Name}
rel1 := &DBRel{RelOneToManyThrough, ct, col2.Name, fc2.Name, col1.Name}
s.RelMap[TTKey{t1, t2}] = rel1
s.RelMap[relID(h, t1, t2)] = rel1
// One-to-many-through relation between 2nd foreign key table and the
// 1nd foreign key table
//rel2 := &DBRel{RelOneToManyThrough, ct, col2.Name, fc2.Name}
rel2 := &DBRel{RelOneToManyThrough, ct, col1.Name, fc1.Name, col2.Name}
s.RelMap[TTKey{t2, t1}] = rel2
s.RelMap[relID(h, t2, t1)] = rel2
}
type DBTable struct {
@ -264,3 +262,11 @@ func (s *DBSchema) GetTable(table string) (*DBTableInfo, error) {
}
return t, nil
}
func relID(h *xxhash.Digest, child, parent string) uint64 {
h.WriteString(child)
h.WriteString(parent)
v := h.Sum64()
h.Reset()
return v
}