// TableBuilder provides a simple sql parser func TableBuilder(op, specs *parser.OPFactory) flux.Reactor { return adaptors.QueryAdaptor(func(r flux.Reactor, gs ds.Graphs) { mo, err := adaptors.DFGraph(gs) if err != nil { r.ReplyError(err) return } recordSize := gs.Length() _ = recordSize var tables Tables for mo.Next() == nil { uo := mo.Node().(*parser.ParseNode) //create a table for this record table := &Table{ Key: uo.Key, Name: uo.Name(), Parent: uo.Parent, PKey: uo.PKey, Attrs: uo.Attr.All(), Node: uo, Graph: gs, } tables = append(tables, table) rules := uo.Rules if table.Parent != "" { if !rules.Has(relationKey) { r.ReplyError(fmt.Errorf("Query for '%s' is a subroot/child of '%s' and needs a '%s(with: [childkey parentkey])' in its conditions for proper evaluation e.g '%s(with: [user_id id])'", table.Name, table.Parent, table.Name, table.Name)) // col := parser.NewCondition("with") // col.Set("value", []string{fmt.Sprintf("%s_id", strings.ToLower(table.Parent)), "id"}) // rules.Set(relationKey, []parser.Collector{col}) return } } for _, val := range specialKeys { if !rules.Has(val) { continue } co, err := rules.Get(val) if err != nil && len(co) <= 0 { return } cod := co[0] // table.Keys[val] = co[0].Get("value") if kos, err := specs.Process(val, val, cod); err == nil { table.Conditions = append(table.Conditions, kos...) } rules.Remove(val) } rules.EachCondition(func(name string, c parser.Collector, stop func()) { co, err := op.Process(c.Get("type").(string), name, c) if err != nil { r.ReplyError(err) stop() } table.Conditions = append(table.Conditions, co...) }) records := uo.Records //add the record to the column list table.Columns = append(table.Columns, records.Keys()...) //process the records constraints records.EachCondition(func(name string, c parser.Collector, stop func()) { co, err := op.Process(c.Get("type").(string), name, c) if err != nil { r.ReplyError(err) stop() } table.Conditions = append(table.Conditions, co...) }) } //deliver the table for building r.Reply(tables) }) }