// processClause retrives the triples for the provided triple given the // information available. func (p *queryPlan) processClause(cls *semantic.GraphClause, lo *storage.LookupOptions) error { // This method decides how to process the clause based on the current // list of bindings solved and data available. exist, total := 0, 0 for _, b := range cls.Bindings() { total++ if p.tbl.HasBinding(b) { exist++ } } if exist == 0 { // Data is new. tbl, err := simpleFetch(p.grfs, cls, lo) if err != nil { return err } if len(p.tbl.Bindings()) > 0 { return p.tbl.DotProduct(tbl) } return p.tbl.AppendTable(tbl) } if exist > 0 && exist < total { // Data is partially binded, retrieve data either extends the row with the // new bindings or filters it out if now new bindings are available. return p.specifyClauseWithTable(cls, lo) } if exist > 0 && exist == total { // Since all bindings in the clause are already solved, the clause becomes a // fully specified triple. If the triple does not exist the row will be // deleted. return p.filterOnExistance(cls, lo) } // Somethign is wrong with the code. return fmt.Errorf("queryPlan.processClause(%v) should have never failed to resolve the clause", cls) }
// processClause retrives the triples for the provided triple given the // information available. func (p *queryPlan) processClause(cls *semantic.GraphClause) error { // This method decides how to process the clause based on the current // list of bindings solved and data available. exist, total := 0, 0 for _, b := range cls.Bindings() { total++ if p.tbl.HasBinding(b) { exist++ } } if exist == 0 { // Data is new. // TODO(xllora): Fetch the data. if len(p.tbl.Bindings()) > 0 { // TODO(xllora): The data should be added using the dot product. return nil } // TODO(xllora): Data should be added directly. return nil } if exist > 0 && exist < total { // TODO(xllora): Data is partially binded, retrieve data either extends // the row with the new bindings or filters it out if now new bindings // are available. return nil } if exist > 0 && exist == total { // TODO(xllora): Since all bindings in the clause are already solved, // the clause becomes a fully specified triple. If the triple does not // exist the row will be deleted. return nil } // Somethign is wrong with the code. return fmt.Errorf("queryPlan.processClause(%v) should have never failed to resolve the clause", cls) }
// simpleFetch returns a table containing the data specified by the graph // clause by querying the provided stora. Will return an error if it had poblems // retrieveing the data. func simpleFetch(gs []storage.Graph, cls *semantic.GraphClause) (*table.Table, error) { tbl, err := table.New(cls.Bindings()) if err != nil { return nil, err } if cls.S != nil && cls.P != nil && cls.O != nil { // Fully qualified triple. // TODO(xllora): Implement. return nil, nil } if cls.S != nil && cls.P != nil && cls.O == nil { // SP request. // TODO(xllora): Implement. return nil, nil } if cls.S != nil && cls.P == nil && cls.O != nil { // SO request. // TODO(xllora): Implement. return nil, nil } if cls.S == nil && cls.P != nil && cls.O != nil { // PO request. // TODO(xllora): Implement. return nil, nil } if cls.S != nil && cls.P == nil && cls.O == nil { // S request. // TODO(xllora): Implement. return nil, nil } if cls.S == nil && cls.P != nil && cls.O == nil { // P request. // TODO(xllora): Implement. return nil, nil } if cls.S == nil && cls.P == nil && cls.O != nil { // O request. // TODO(xllora): Implement. return nil, nil } if cls.S == nil && cls.P == nil && cls.O == nil { // Full data request. for _, g := range gs { ts, err := g.Triples() if err != nil { return nil, err } if err := addTriples(ts, cls, tbl); err != nil { return nil, err } } return tbl, nil } return nil, fmt.Errorf("planner.simpleFetch could not recognize request in clause %v", cls) }
// simpleExist returns true if the triple exist. Return the unfeasible state, // the table and the error if present. func simpleExist(gs []storage.Graph, cls *semantic.GraphClause, t *triple.Triple) (bool, *table.Table, error) { unfeasible := true tbl, err := table.New(cls.Bindings()) if err != nil { return true, nil, err } for _, g := range gs { b, err := g.Exist(t) if err != nil { return true, nil, err } if b { unfeasible = false ts := make(chan *triple.Triple, 1) ts <- t close(ts) if err := addTriples(ts, cls, tbl); err != nil { return true, nil, err } } } return unfeasible, tbl, nil }
// simpleFetch returns a table containing the data specified by the graph // clause by querying the provided stora. Will return an error if it had poblems // retrieveing the data. func simpleFetch(gs []storage.Graph, cls *semantic.GraphClause, lo *storage.LookupOptions) (*table.Table, error) { s, p, o := cls.S, cls.P, cls.O lo = updateTimeBounds(lo, cls) tbl, err := table.New(cls.Bindings()) if err != nil { return nil, err } if s != nil && p != nil && o != nil { // Fully qualified triple. t, err := triple.New(s, p, o) if err != nil { return nil, err } for _, g := range gs { b, err := g.Exist(t) if err != nil { return nil, err } if b { ts := make(chan *triple.Triple, 1) ts <- t close(ts) if err := addTriples(ts, cls, tbl); err != nil { return nil, err } } } return tbl, nil } if s != nil && p != nil && o == nil { // SP request. for _, g := range gs { os, err := g.Objects(s, p, lo) if err != nil { return nil, err } var ros []*triple.Object for o := range os { ros = append(ros, o) } ts := make(chan *triple.Triple, len(ros)) for _, o := range ros { t, err := triple.New(s, p, o) if err != nil { return nil, err } ts <- t } close(ts) if err := addTriples(ts, cls, tbl); err != nil { return nil, err } } return tbl, nil } if s != nil && p == nil && o != nil { // SO request. for _, g := range gs { ps, err := g.PredicatesForSubjectAndObject(s, o, lo) if err != nil { return nil, err } var rps []*predicate.Predicate for p := range ps { rps = append(rps, p) } ts := make(chan *triple.Triple, len(rps)) for _, p := range rps { t, err := triple.New(s, p, o) if err != nil { return nil, err } ts <- t } close(ts) if err := addTriples(ts, cls, tbl); err != nil { return nil, err } } return tbl, nil } if s == nil && p != nil && o != nil { // PO request. for _, g := range gs { ss, err := g.Subjects(p, o, lo) if err != nil { return nil, err } var rss []*node.Node for s := range ss { rss = append(rss, s) } ts := make(chan *triple.Triple, len(rss)) for _, s := range rss { t, err := triple.New(s, p, o) if err != nil { return nil, err } ts <- t } close(ts) if err := addTriples(ts, cls, tbl); err != nil { return nil, err } } return tbl, nil } if s != nil && p == nil && o == nil { // S request. for _, g := range gs { ts, err := g.TriplesForSubject(s, lo) if err != nil { return nil, err } if err := addTriples(ts, cls, tbl); err != nil { return nil, err } } return tbl, nil } if s == nil && p != nil && o == nil { // P request. for _, g := range gs { ts, err := g.TriplesForPredicate(p, lo) if err != nil { return nil, err } if err := addTriples(ts, cls, tbl); err != nil { return nil, err } } return tbl, nil } if s == nil && p == nil && o != nil { // O request. for _, g := range gs { ts, err := g.TriplesForObject(o, lo) if err != nil { return nil, err } if err := addTriples(ts, cls, tbl); err != nil { return nil, err } } return tbl, nil } if s == nil && p == nil && o == nil { // Full data request. for _, g := range gs { ts, err := g.Triples() if err != nil { return nil, err } if err := addTriples(ts, cls, tbl); err != nil { return nil, err } } return tbl, nil } return nil, fmt.Errorf("planner.simpleFetch could not recognize request in clause %v", cls) }
// simpleFetch returns a table containing the data specified by the graph // clause by querying the provided stora. Will return an error if it had poblems // retrieveing the data. func simpleFetch(ctx context.Context, gs []storage.Graph, cls *semantic.GraphClause, lo *storage.LookupOptions, chanSize int) (*table.Table, error) { s, p, o := cls.S, cls.P, cls.O lo = updateTimeBounds(lo, cls) tbl, err := table.New(cls.Bindings()) if err != nil { return nil, err } if s != nil && p != nil && o != nil { // Fully qualified triple. t, err := triple.New(s, p, o) if err != nil { return nil, err } for _, g := range gs { b, err := g.Exist(ctx, t) if err != nil { return nil, err } if b { ts := make(chan *triple.Triple, 1) ts <- t close(ts) if err := addTriples(ts, cls, tbl); err != nil { return nil, err } } } return tbl, nil } if s != nil && p != nil && o == nil { // SP request. for _, g := range gs { var ( oErr error aErr error lErr error wg sync.WaitGroup ) wg.Add(2) os := make(chan *triple.Object, chanSize) go func() { defer wg.Done() oErr = g.Objects(ctx, s, p, lo, os) }() ts := make(chan *triple.Triple, chanSize) go func() { defer wg.Done() aErr = addTriples(ts, cls, tbl) }() for o := range os { if lErr != nil { // Drain the channel to avoid leaking goroutines. continue } t, err := triple.New(s, p, o) if err != nil { lErr = err continue } ts <- t } close(ts) wg.Wait() if oErr != nil { return nil, oErr } if aErr != nil { return nil, aErr } if lErr != nil { return nil, lErr } } return tbl, nil } if s != nil && p == nil && o != nil { // SO request. for _, g := range gs { var ( pErr error aErr error lErr error wg sync.WaitGroup ) wg.Add(2) ps := make(chan *predicate.Predicate, chanSize) go func() { defer wg.Done() pErr = g.PredicatesForSubjectAndObject(ctx, s, o, lo, ps) }() ts := make(chan *triple.Triple, chanSize) go func() { defer wg.Done() aErr = addTriples(ts, cls, tbl) }() for p := range ps { if lErr != nil { // Drain the channel to avoid leaking goroutines. continue } t, err := triple.New(s, p, o) if err != nil { lErr = err continue } ts <- t } close(ts) wg.Wait() if pErr != nil { return nil, pErr } if aErr != nil { return nil, aErr } if lErr != nil { return nil, lErr } } return tbl, nil } if s == nil && p != nil && o != nil { // PO request. for _, g := range gs { var ( pErr error aErr error lErr error wg sync.WaitGroup ) wg.Add(2) ss := make(chan *node.Node, chanSize) go func() { defer wg.Done() pErr = g.Subjects(ctx, p, o, lo, ss) }() ts := make(chan *triple.Triple, chanSize) go func() { defer wg.Done() aErr = addTriples(ts, cls, tbl) }() for s := range ss { if lErr != nil { // Drain the channel to avoid leaking goroutines. continue } t, err := triple.New(s, p, o) if err != nil { lErr = err continue } ts <- t } close(ts) wg.Wait() if pErr != nil { return nil, pErr } if aErr != nil { return nil, aErr } if lErr != nil { return nil, lErr } } return tbl, nil } if s != nil && p == nil && o == nil { // S request. for _, g := range gs { var ( tErr error aErr error wg sync.WaitGroup ) ts := make(chan *triple.Triple, chanSize) wg.Add(1) go func() { defer wg.Done() tErr = g.TriplesForSubject(ctx, s, lo, ts) }() aErr = addTriples(ts, cls, tbl) wg.Wait() if tErr != nil { return nil, tErr } if aErr != nil { return nil, aErr } } return tbl, nil } if s == nil && p != nil && o == nil { // P request. for _, g := range gs { var ( tErr error aErr error wg sync.WaitGroup ) ts := make(chan *triple.Triple, chanSize) wg.Add(1) go func() { defer wg.Done() tErr = g.TriplesForPredicate(ctx, p, lo, ts) }() aErr = addTriples(ts, cls, tbl) wg.Wait() if tErr != nil { return nil, tErr } if aErr != nil { return nil, aErr } } return tbl, nil } if s == nil && p == nil && o != nil { // O request. for _, g := range gs { var ( tErr error wg sync.WaitGroup ) ts := make(chan *triple.Triple, chanSize) wg.Add(1) go func() { defer wg.Done() tErr = g.TriplesForObject(ctx, o, lo, ts) }() aErr := addTriples(ts, cls, tbl) wg.Wait() if tErr != nil { return nil, tErr } if aErr != nil { return nil, aErr } } return tbl, nil } if s == nil && p == nil && o == nil { // Full data request. for _, g := range gs { var ( tErr error aErr error wg sync.WaitGroup ) ts := make(chan *triple.Triple, chanSize) wg.Add(1) go func() { defer wg.Done() tErr = g.Triples(ctx, ts) }() aErr = addTriples(ts, cls, tbl) wg.Wait() if tErr != nil { return nil, tErr } if aErr != nil { return nil, aErr } } return tbl, nil } return nil, fmt.Errorf("planner.simpleFetch could not recognize request in clause %v", cls) }