Move license from MIT to Apache 2.0. Add Makefile
This commit is contained in:
@ -1,3 +1,4 @@
|
||||
//nolint:errcheck
|
||||
package psql
|
||||
|
||||
import (
|
||||
|
@ -27,8 +27,11 @@ func TestMain(m *testing.M) {
|
||||
"token",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
qcompile.AddRole("user", "product", qcode.TRConfig{
|
||||
err = qcompile.AddRole("user", "product", qcode.TRConfig{
|
||||
Query: qcode.QueryConfig{
|
||||
Columns: []string{"id", "name", "price", "users", "customers"},
|
||||
Filters: []string{
|
||||
@ -54,27 +57,39 @@ func TestMain(m *testing.M) {
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
qcompile.AddRole("anon", "product", qcode.TRConfig{
|
||||
err = qcompile.AddRole("anon", "product", qcode.TRConfig{
|
||||
Query: qcode.QueryConfig{
|
||||
Columns: []string{"id", "name"},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
qcompile.AddRole("anon1", "product", qcode.TRConfig{
|
||||
err = qcompile.AddRole("anon1", "product", qcode.TRConfig{
|
||||
Query: qcode.QueryConfig{
|
||||
Columns: []string{"id", "name", "price"},
|
||||
DisableFunctions: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
qcompile.AddRole("user", "users", qcode.TRConfig{
|
||||
err = qcompile.AddRole("user", "users", qcode.TRConfig{
|
||||
Query: qcode.QueryConfig{
|
||||
Columns: []string{"id", "full_name", "avatar", "email", "products"},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
qcompile.AddRole("bad_dude", "users", qcode.TRConfig{
|
||||
err = qcompile.AddRole("bad_dude", "users", qcode.TRConfig{
|
||||
Query: qcode.QueryConfig{
|
||||
Filters: []string{"false"},
|
||||
DisableFunctions: true,
|
||||
@ -86,8 +101,11 @@ func TestMain(m *testing.M) {
|
||||
Filters: []string{"false"},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
qcompile.AddRole("user", "mes", qcode.TRConfig{
|
||||
err = qcompile.AddRole("user", "mes", qcode.TRConfig{
|
||||
Query: qcode.QueryConfig{
|
||||
Columns: []string{"id", "full_name", "avatar"},
|
||||
Filters: []string{
|
||||
@ -95,8 +113,11 @@ func TestMain(m *testing.M) {
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
qcompile.AddRole("user", "customers", qcode.TRConfig{
|
||||
err = qcompile.AddRole("user", "customers", qcode.TRConfig{
|
||||
Query: qcode.QueryConfig{
|
||||
Columns: []string{"id", "email", "full_name", "products"},
|
||||
},
|
||||
@ -167,7 +188,9 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
for i, t := range tables {
|
||||
schema.updateSchema(t, columns[i], aliases)
|
||||
if err := schema.updateSchema(t, columns[i], aliases); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
vars := NewVariables(map[string]string{
|
||||
|
@ -1,3 +1,4 @@
|
||||
//nolint:errcheck
|
||||
package psql
|
||||
|
||||
import (
|
||||
@ -6,10 +7,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/cespare/xxhash/v2"
|
||||
"github.com/dosco/super-graph/qcode"
|
||||
"github.com/dosco/super-graph/util"
|
||||
)
|
||||
@ -249,7 +248,7 @@ func (c *compilerContext) renderSelect(sel *qcode.Select, ti *DBTableInfo) (uint
|
||||
hasOrder := len(sel.OrderBy) != 0
|
||||
|
||||
// SELECT
|
||||
if ti.Singular == false {
|
||||
if !ti.Singular {
|
||||
//fmt.Fprintf(w, `SELECT coalesce(json_agg("%s"`, c.sel.Table)
|
||||
io.WriteString(c.w, `SELECT coalesce(json_agg("`)
|
||||
io.WriteString(c.w, "json_")
|
||||
@ -351,7 +350,7 @@ func (c *compilerContext) renderSelectClose(sel *qcode.Select, ti *DBTableInfo)
|
||||
io.WriteString(c.w, `') :: integer`)
|
||||
}
|
||||
|
||||
if ti.Singular == false {
|
||||
if !ti.Singular {
|
||||
//fmt.Fprintf(w, `) AS "json_agg_%d"`, c.sel.ID)
|
||||
io.WriteString(c.w, `)`)
|
||||
aliasWithID(c.w, "json_agg", sel.ID)
|
||||
@ -417,7 +416,7 @@ func (c *compilerContext) renderColumns(sel *qcode.Select, ti *DBTableInfo) {
|
||||
for _, col := range sel.Cols {
|
||||
n := funcPrefixLen(col.Name)
|
||||
if n != 0 {
|
||||
if sel.Functions == false {
|
||||
if !sel.Functions {
|
||||
continue
|
||||
}
|
||||
if len(sel.Allowed) != 0 {
|
||||
@ -956,7 +955,7 @@ func (c *compilerContext) renderOp(ex *qcode.Exp, sel *qcode.Select, ti *DBTable
|
||||
if len(ti.TSVCol) == 0 {
|
||||
return fmt.Errorf("no tsv column defined for %s", ti.Name)
|
||||
}
|
||||
if col, ok = ti.Columns[ti.TSVCol]; !ok {
|
||||
if _, ok = ti.Columns[ti.TSVCol]; !ok {
|
||||
return fmt.Errorf("no tsv column '%s' found ", ti.TSVCol)
|
||||
}
|
||||
//fmt.Fprintf(w, `(("%s") @@ to_tsquery('%s'))`, c.ti.TSVCol, val.Val)
|
||||
@ -1139,22 +1138,6 @@ func aliasWithIDSuffix(w io.Writer, alias string, id int32, suffix string) {
|
||||
io.WriteString(w, `"`)
|
||||
}
|
||||
|
||||
func colWithAlias(w io.Writer, col, alias string) {
|
||||
io.WriteString(w, `"`)
|
||||
io.WriteString(w, col)
|
||||
io.WriteString(w, `" AS "`)
|
||||
io.WriteString(w, alias)
|
||||
io.WriteString(w, `"`)
|
||||
}
|
||||
|
||||
func tableWithAlias(w io.Writer, table, alias string) {
|
||||
io.WriteString(w, `"`)
|
||||
io.WriteString(w, table)
|
||||
io.WriteString(w, `" AS "`)
|
||||
io.WriteString(w, alias)
|
||||
io.WriteString(w, `"`)
|
||||
}
|
||||
|
||||
func colWithTable(w io.Writer, table, col string) {
|
||||
io.WriteString(w, `"`)
|
||||
io.WriteString(w, table)
|
||||
@ -1185,20 +1168,6 @@ func colWithTableIDAlias(w io.Writer, table string, id int32, col, alias string)
|
||||
io.WriteString(w, `"`)
|
||||
}
|
||||
|
||||
func colWithTableIDSuffixAlias(w io.Writer, table string, id int32,
|
||||
suffix, col, alias string) {
|
||||
io.WriteString(w, `"`)
|
||||
io.WriteString(w, table)
|
||||
io.WriteString(w, `_`)
|
||||
int2string(w, id)
|
||||
io.WriteString(w, suffix)
|
||||
io.WriteString(w, `"."`)
|
||||
io.WriteString(w, col)
|
||||
io.WriteString(w, `" AS "`)
|
||||
io.WriteString(w, alias)
|
||||
io.WriteString(w, `"`)
|
||||
}
|
||||
|
||||
func tableIDColSuffix(w io.Writer, table string, id int32, col, suffix string) {
|
||||
io.WriteString(w, `"`)
|
||||
io.WriteString(w, table)
|
||||
@ -1223,7 +1192,7 @@ func int2string(w io.Writer, val int32) {
|
||||
for val2 > 0 {
|
||||
temp *= 10
|
||||
temp += val2 % 10
|
||||
val2 = int32(math.Floor(float64(val2 / 10)))
|
||||
val2 = int32(float64(val2 / 10))
|
||||
}
|
||||
|
||||
val3 := temp
|
||||
@ -1233,11 +1202,3 @@ func int2string(w io.Writer, val int32) {
|
||||
w.Write([]byte{charset[d]})
|
||||
}
|
||||
}
|
||||
|
||||
func relID(h *xxhash.Digest, child, parent string) uint64 {
|
||||
h.WriteString(child)
|
||||
h.WriteString(parent)
|
||||
v := h.Sum64()
|
||||
h.Reset()
|
||||
return v
|
||||
}
|
||||
|
@ -199,7 +199,9 @@ func NewDBSchema(db *pgxpool.Pool, aliases map[string][]string) (*DBSchema, erro
|
||||
return nil, err
|
||||
}
|
||||
|
||||
schema.updateSchema(t, cols, aliases)
|
||||
if err := schema.updateSchema(t, cols, aliases); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return schema, nil
|
||||
@ -208,7 +210,7 @@ func NewDBSchema(db *pgxpool.Pool, aliases map[string][]string) (*DBSchema, erro
|
||||
func (s *DBSchema) updateSchema(
|
||||
t *DBTable,
|
||||
cols []*DBColumn,
|
||||
aliases map[string][]string) {
|
||||
aliases map[string][]string) error {
|
||||
|
||||
// Foreign key columns in current table
|
||||
colByID := make(map[int16]*DBColumn)
|
||||
@ -281,12 +283,16 @@ func (s *DBSchema) updateSchema(
|
||||
// Belongs-to relation between current table and the
|
||||
// table in the foreign key
|
||||
rel1 := &DBRel{RelBelongTo, "", "", c.Name, fc.Name}
|
||||
s.SetRel(ct, ft, rel1)
|
||||
if err := s.SetRel(ct, ft, rel1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// One-to-many relation between the foreign key table and the
|
||||
// the current table
|
||||
rel2 := &DBRel{RelOneToMany, "", "", fc.Name, c.Name}
|
||||
s.SetRel(ft, ct, rel2)
|
||||
if err := s.SetRel(ft, ct, rel2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jcols = append(jcols, c)
|
||||
}
|
||||
@ -301,42 +307,54 @@ func (s *DBSchema) updateSchema(
|
||||
if len(jcols) > 1 {
|
||||
for i := range jcols {
|
||||
for n := range jcols {
|
||||
if n != i {
|
||||
s.updateSchemaOTMT(ct, jcols[i], jcols[n], colByID)
|
||||
if n == i {
|
||||
continue
|
||||
}
|
||||
err := s.updateSchemaOTMT(ct, jcols[i], jcols[n], colByID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *DBSchema) updateSchemaOTMT(
|
||||
ct string,
|
||||
col1, col2 *DBColumn,
|
||||
colByID map[int16]*DBColumn) {
|
||||
colByID map[int16]*DBColumn) error {
|
||||
|
||||
t1 := strings.ToLower(col1.FKeyTable)
|
||||
t2 := strings.ToLower(col2.FKeyTable)
|
||||
|
||||
fc1, ok := colByID[col1.FKeyColID[0]]
|
||||
if !ok {
|
||||
return
|
||||
return fmt.Errorf("expected column id '%d' not found", col1.FKeyColID[0])
|
||||
}
|
||||
fc2, ok := colByID[col2.FKeyColID[0]]
|
||||
if !ok {
|
||||
return
|
||||
return fmt.Errorf("expected column id '%d' not found", col2.FKeyColID[0])
|
||||
}
|
||||
|
||||
// One-to-many-through relation between 1nd foreign key table and the
|
||||
// 2nd foreign key table
|
||||
//rel1 := &DBRel{RelOneToManyThrough, ct, fc1.Name, col1.Name}
|
||||
rel1 := &DBRel{RelOneToManyThrough, ct, col2.Name, fc2.Name, col1.Name}
|
||||
s.SetRel(t1, t2, rel1)
|
||||
if err := s.SetRel(t1, t2, rel1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 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.SetRel(t2, t1, rel2)
|
||||
if err := s.SetRel(t2, t1, rel2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *DBSchema) GetTable(table string) (*DBTableInfo, error) {
|
||||
|
Reference in New Issue
Block a user