evalEdge evaluates has-edge and has-edge-with calls.
(name string, exprs ...entql.Expr)
| 241 | |
| 242 | // evalEdge evaluates has-edge and has-edge-with calls. |
| 243 | func (e *state) evalEdge(name string, exprs ...entql.Expr) *sql.Predicate { |
| 244 | edge, ok := e.context.Edges[name] |
| 245 | expect(ok, "edge %q was not found for node %q", name, e.context.Type) |
| 246 | var fromC, toC string |
| 247 | switch { |
| 248 | case edge.To.ID != nil: |
| 249 | toC = edge.To.ID.Column |
| 250 | // Edge-owner points to its edge schema. |
| 251 | case edge.To.CompositeID != nil && !edge.Spec.Inverse: |
| 252 | toC = edge.To.CompositeID[0].Column |
| 253 | // Edge-backref points to its edge schema. |
| 254 | case edge.To.CompositeID != nil && edge.Spec.Inverse: |
| 255 | toC = edge.To.CompositeID[1].Column |
| 256 | default: |
| 257 | panic(evalError{fmt.Sprintf("expect id definition for edge %q", name)}) |
| 258 | } |
| 259 | switch { |
| 260 | case e.context.ID != nil: |
| 261 | fromC = e.context.ID.Column |
| 262 | case e.context.CompositeID != nil && (edge.Spec.Rel == M2O || (edge.Spec.Rel == O2O && edge.Spec.Inverse)): |
| 263 | // An edge-schema with a composite id can query |
| 264 | // only edges that it owns (holds the foreign-key). |
| 265 | default: |
| 266 | panic(evalError{fmt.Sprintf("unexpected edge-query from an edge-schema %q", e.context.Type)}) |
| 267 | } |
| 268 | step := NewStep( |
| 269 | From(e.context.Table, fromC), |
| 270 | To(edge.To.Table, toC), |
| 271 | Edge(edge.Spec.Rel, edge.Spec.Inverse, edge.Spec.Table, edge.Spec.Columns...), |
| 272 | ) |
| 273 | selector := e.selector.Clone().SetP(nil) |
| 274 | selector.SetTotal(e.Total()) |
| 275 | if len(exprs) == 0 { |
| 276 | HasNeighbors(selector, step) |
| 277 | return selector.P() |
| 278 | } |
| 279 | HasNeighborsWith(selector, step, func(s *sql.Selector) { |
| 280 | for _, expr := range exprs { |
| 281 | if cx, ok := expr.(*entql.CallExpr); ok && cx.Func == FuncSelector { |
| 282 | expect(len(cx.Args) == 1, "invalid number of arguments for %s", FuncSelector) |
| 283 | wrapped, ok := cx.Args[0].(wrappedFunc) |
| 284 | expect(ok, "invalid argument for %s: %T", FuncSelector, cx.Args[0]) |
| 285 | wrapped.Func(s) |
| 286 | } else { |
| 287 | p, err := evalExpr(edge.To, s, expr) |
| 288 | expect(err == nil, "edge evaluation failed for %s->%s: %s", e.context.Type, name, err) |
| 289 | s.Where(p) |
| 290 | } |
| 291 | } |
| 292 | }) |
| 293 | return selector.P() |
| 294 | } |
| 295 | |
| 296 | func (e *state) field(f *entql.Field) string { |
| 297 | _, ok := e.context.Fields[f.Name] |
no test coverage detected