(at *AttributeExpr, vat *NamedAttributeExpr, view string, seen map[string]*AttributeExpr)
| 363 | } |
| 364 | |
| 365 | func projectRecursive(at *AttributeExpr, vat *NamedAttributeExpr, view string, seen map[string]*AttributeExpr) (*AttributeExpr, error) { |
| 366 | if att, ok := seen[hashAttrAndView(at, view)]; ok { |
| 367 | return att, nil |
| 368 | } |
| 369 | at = DupAtt(at) |
| 370 | |
| 371 | if rt, ok := at.Type.(*ResultTypeExpr); ok { |
| 372 | vatt := vat.Attribute |
| 373 | view, ok := vatt.Meta.Last(ViewMetaKey) |
| 374 | if !ok { |
| 375 | if v, ok := at.Meta.Last(ViewMetaKey); ok { |
| 376 | view = v |
| 377 | } else { |
| 378 | view = DefaultView |
| 379 | } |
| 380 | } |
| 381 | seen[hashAttrAndView(at, view)] = at |
| 382 | pr, err := project(rt, view, seen) |
| 383 | if err != nil { |
| 384 | return nil, fmt.Errorf("view %#v on field %#v cannot be computed: %w", view, vat.Name, err) |
| 385 | } |
| 386 | at.Type = pr |
| 387 | return at, nil |
| 388 | } |
| 389 | |
| 390 | if _, ok := at.Type.(*UserTypeExpr); ok { |
| 391 | seen[hashAttrAndView(at, view)] = at |
| 392 | } |
| 393 | |
| 394 | if obj := AsObject(at.Type); obj != nil { |
| 395 | vobj := AsObject(vat.Attribute.Type) |
| 396 | if vobj == nil { |
| 397 | return at, nil |
| 398 | } |
| 399 | for _, cnat := range *obj { |
| 400 | var cvnat *NamedAttributeExpr |
| 401 | for _, nnat := range *vobj { |
| 402 | if nnat.Name == cnat.Name { |
| 403 | cvnat = nnat |
| 404 | break |
| 405 | } |
| 406 | } |
| 407 | if cvnat == nil { |
| 408 | continue |
| 409 | } |
| 410 | pat, err := projectRecursive(cnat.Attribute, cvnat, view, seen) |
| 411 | if err != nil { |
| 412 | return nil, err |
| 413 | } |
| 414 | cnat.Attribute = pat |
| 415 | } |
| 416 | return at, nil |
| 417 | } |
| 418 | |
| 419 | if ar := AsArray(at.Type); ar != nil { |
| 420 | pat, err := projectRecursive(ar.ElemType, vat, view, seen) |
| 421 | if err != nil { |
| 422 | return nil, err |
no test coverage detected