Fix role filters and nested where bugs

This commit is contained in:
Vikram Rangnekar 2020-01-13 09:34:15 -05:00
parent 1e31e33707
commit 7c02226016
5 changed files with 45 additions and 25 deletions

View File

@ -814,11 +814,15 @@ func (c *compilerContext) renderRelationshipByName(table, parent string, id int3
} }
func (c *compilerContext) renderWhere(sel *qcode.Select, ti *DBTableInfo) error { func (c *compilerContext) renderWhere(sel *qcode.Select, ti *DBTableInfo) error {
st := util.NewStack()
if sel.Where != nil { if sel.Where != nil {
st.Push(sel.Where) return c.renderExp(sel.Where, ti, false)
} }
return nil
}
func (c *compilerContext) renderExp(ex *qcode.Exp, ti *DBTableInfo, skipNested bool) error {
st := util.NewStack()
st.Push(ex)
for { for {
if st.Len() == 0 { if st.Len() == 0 {
@ -873,16 +877,16 @@ func (c *compilerContext) renderWhere(sel *qcode.Select, ti *DBTableInfo) error
qcode.FreeExp(val) qcode.FreeExp(val)
default: default:
if len(val.NestedCols) != 0 { if !skipNested && len(val.NestedCols) != 0 {
io.WriteString(c.w, `EXISTS `) io.WriteString(c.w, `EXISTS `)
if err := c.renderNestedWhere(val, sel, ti); err != nil { if err := c.renderNestedWhere(val, ti); err != nil {
return err return err
} }
} else { } else {
//fmt.Fprintf(w, `(("%s"."%s") `, c.sel.Name, val.Col) //fmt.Fprintf(w, `(("%s"."%s") `, c.sel.Name, val.Col)
if err := c.renderOp(val, sel, ti); err != nil { if err := c.renderOp(val, ti); err != nil {
return err return err
} }
qcode.FreeExp(val) qcode.FreeExp(val)
@ -898,7 +902,7 @@ func (c *compilerContext) renderWhere(sel *qcode.Select, ti *DBTableInfo) error
return nil return nil
} }
func (c *compilerContext) renderNestedWhere(ex *qcode.Exp, sel *qcode.Select, ti *DBTableInfo) error { func (c *compilerContext) renderNestedWhere(ex *qcode.Exp, ti *DBTableInfo) error {
for i := 0; i < len(ex.NestedCols)-1; i++ { for i := 0; i < len(ex.NestedCols)-1; i++ {
cti, err := c.schema.GetTable(ex.NestedCols[i]) cti, err := c.schema.GetTable(ex.NestedCols[i])
if err != nil { if err != nil {
@ -922,6 +926,15 @@ func (c *compilerContext) renderNestedWhere(ex *qcode.Exp, sel *qcode.Select, ti
return err return err
} }
io.WriteString(c.w, ` AND (`)
if err := c.renderExp(ex, cti, true); err != nil {
return err
}
//fmt.Println(">", ex)
io.WriteString(c.w, `)`)
} }
for i := 0; i < len(ex.NestedCols)-1; i++ { for i := 0; i < len(ex.NestedCols)-1; i++ {
@ -931,7 +944,7 @@ func (c *compilerContext) renderNestedWhere(ex *qcode.Exp, sel *qcode.Select, ti
return nil return nil
} }
func (c *compilerContext) renderOp(ex *qcode.Exp, sel *qcode.Select, ti *DBTableInfo) error { func (c *compilerContext) renderOp(ex *qcode.Exp, ti *DBTableInfo) error {
var col *DBColumn var col *DBColumn
var ok bool var ok bool
@ -1029,10 +1042,9 @@ func (c *compilerContext) renderOp(ex *qcode.Exp, sel *qcode.Select, ti *DBTable
if ex.Type == qcode.ValList { if ex.Type == qcode.ValList {
c.renderList(ex) c.renderList(ex)
} else if col == nil {
return errors.New("no column found for expression value")
} else { } else {
if col == nil {
return errors.New("no column found for expression value")
}
c.renderVal(ex, c.vars, col) c.renderVal(ex, c.vars, col)
} }

View File

@ -409,7 +409,7 @@ func withWhereOnRelations(t *testing.T) {
users(where: { users(where: {
not: { not: {
products: { products: {
price: { gt: 3 } price: { gt: 3 }
} }
} }
}) { }) {
@ -418,7 +418,7 @@ func withWhereOnRelations(t *testing.T) {
} }
}` }`
sql := `SELECT json_object_agg('users', json_0) FROM (SELECT coalesce(json_agg("json_0"), '[]') AS "json_0" FROM (SELECT row_to_json((SELECT "json_row_0" FROM (SELECT "users_0"."id" AS "id", "users_0"."email" AS "email") AS "json_row_0")) AS "json_0" FROM (SELECT "users"."id", "users"."email" FROM "users" WHERE (NOT EXISTS (SELECT 1 FROM products WHERE (("products"."user_id") = ("users"."id")))) LIMIT ('20') :: integer) AS "users_0" LIMIT ('20') :: integer) AS "json_agg_0") AS "sel_0"` sql := `SELECT json_object_agg('users', json_0) FROM (SELECT coalesce(json_agg("json_0"), '[]') AS "json_0" FROM (SELECT row_to_json((SELECT "json_row_0" FROM (SELECT "users_0"."id" AS "id", "users_0"."email" AS "email") AS "json_row_0")) AS "json_0" FROM (SELECT "users"."id", "users"."email" FROM "users" WHERE (NOT EXISTS (SELECT 1 FROM products WHERE (("products"."user_id") = ("users"."id")) AND ((("products"."price") > 3)))) LIMIT ('20') :: integer) AS "users_0" LIMIT ('20') :: integer) AS "json_agg_0") AS "sel_0"`
resSQL, err := compileGQLToPSQL(gql, nil, "user") resSQL, err := compileGQLToPSQL(gql, nil, "user")
if err != nil { if err != nil {

View File

@ -80,7 +80,7 @@ func (trv *trval) allowedColumns(qt QType) map[string]struct{} {
case QTUpdate: case QTUpdate:
return trv.update.cols return trv.update.cols
case QTDelete: case QTDelete:
return trv.insert.cols return trv.delete.cols
case QTUpsert: case QTUpsert:
return trv.insert.cols return trv.insert.cols
} }

View File

@ -940,10 +940,13 @@ func setWhereColName(ex *Exp, node *Node) {
list = append([]string{k}, list...) list = append([]string{k}, list...)
} }
} }
if len(list) == 1 { listlen := len(list)
if listlen == 1 {
ex.Col = list[0] ex.Col = list[0]
} else if len(list) > 1 { } else if listlen > 1 {
ex.NestedCols = list ex.Col = list[listlen-1]
ex.NestedCols = list[:listlen]
} }
} }
@ -996,6 +999,11 @@ func compileFilter(filter []string) (*Exp, error) {
return nil, err return nil, err
} }
// TODO: Invalid table names in nested where causes fail silently
// returning a nil 'f' this needs to be fixed
// TODO: Invalid where clauses such as missing op (eg. eq) also fail silently
if fl == nil { if fl == nil {
fl = f fl = f
} else { } else {

View File

@ -80,26 +80,26 @@ func addRole(qc *qcode.Compiler, r configRole, t configRoleTable) error {
Presets: t.Insert.Presets, Presets: t.Insert.Presets,
} }
if t.Query.Block { if t.Insert.Block {
insert.Filters = blockFilter insert.Filters = blockFilter
} }
update := qcode.UpdateConfig{ update := qcode.UpdateConfig{
Filters: t.Insert.Filters, Filters: t.Update.Filters,
Columns: t.Insert.Columns, Columns: t.Update.Columns,
Presets: t.Insert.Presets, Presets: t.Update.Presets,
} }
if t.Query.Block { if t.Update.Block {
update.Filters = blockFilter update.Filters = blockFilter
} }
delete := qcode.DeleteConfig{ delete := qcode.DeleteConfig{
Filters: t.Insert.Filters, Filters: t.Delete.Filters,
Columns: t.Insert.Columns, Columns: t.Delete.Columns,
} }
if t.Query.Block { if t.Delete.Block {
delete.Filters = blockFilter delete.Filters = blockFilter
} }