Example #1
0
// 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)
	})
}