@@ -23,6 +23,10 @@ type Resource interface {
23
23
24
24
// Validator returns the schema.Validator associated with the resource.
25
25
Validator () schema.Validator
26
+
27
+ // Path returns the full path of the resource composed of names of each
28
+ // intermediate resources separated by dots (i.e.: res1.res2.res3).
29
+ Path () string
26
30
}
27
31
28
32
// Eval evaluate the projection on the given payload with the help of the
@@ -31,10 +35,10 @@ type Resource interface {
31
35
func (p Projection ) Eval (ctx context.Context , payload map [string ]interface {}, rsc Resource ) (map [string ]interface {}, error ) {
32
36
rbr := & referenceBatchResolver {}
33
37
validator := rsc .Validator ()
34
- payload , err := evalProjection (ctx , p , payload , validator , rbr )
38
+ payload , err := evalProjection (ctx , p , payload , validator , rbr , rsc )
35
39
if err == nil {
36
40
// Execute the batched reference resolutions.
37
- err = rbr .execute (ctx , rsc )
41
+ err = rbr .execute (ctx )
38
42
}
39
43
return payload , err
40
44
}
@@ -80,7 +84,7 @@ func prepareProjection(p Projection, payload map[string]interface{}) (Projection
80
84
return proj , nil
81
85
}
82
86
83
- func evalProjectionArray (ctx context.Context , pf ProjectionField , payload []interface {}, def * schema.Field , rbr * referenceBatchResolver ) (* []interface {}, error ) {
87
+ func evalProjectionArray (ctx context.Context , pf ProjectionField , payload []interface {}, def * schema.Field , rbr * referenceBatchResolver , rsc Resource ) (* []interface {}, error ) {
84
88
res := make ([]interface {}, 0 , len (payload ))
85
89
// Return pointer to res, because it may be populated after this function ends, by referenceBatchResolver
86
90
// in `schema.Reference` case
@@ -102,11 +106,15 @@ func evalProjectionArray(ctx context.Context, pf ProjectionField, payload []inte
102
106
Projection : pf .Children ,
103
107
Predicate : Predicate {e },
104
108
}
105
- rbr .request (fieldType .Path , q , func (payloads []map [string ]interface {}, validator schema.Validator ) error {
109
+ subRsc , err := rsc .SubResource (ctx , fieldType .Path )
110
+ if err != nil {
111
+ return nil , err
112
+ }
113
+ rbr .request (subRsc , q , func (payloads []map [string ]interface {}, validator schema.Validator , rsc Resource ) error {
106
114
var v interface {}
107
115
var err error
108
116
for i := range payloads {
109
- if payloads [i ], err = evalProjection (ctx , pf .Children , payloads [i ], validator , rbr ); err != nil {
117
+ if payloads [i ], err = evalProjection (ctx , pf .Children , payloads [i ], validator , rbr , rsc ); err != nil {
110
118
return fmt .Errorf ("%s: error applying projection on sub-field item #%d: %v" , pf .Name , i , err )
111
119
}
112
120
}
@@ -127,7 +135,7 @@ func evalProjectionArray(ctx context.Context, pf ProjectionField, payload []inte
127
135
if subval , ok := val .([]interface {}); ok {
128
136
var err error
129
137
var subvalp * []interface {}
130
- if subvalp , err = evalProjectionArray (ctx , pf , subval , & fieldType .Values , rbr ); err != nil {
138
+ if subvalp , err = evalProjectionArray (ctx , pf , subval , & fieldType .Values , rbr , rsc ); err != nil {
131
139
return nil , fmt .Errorf ("%s: error applying projection on array item #%d: %v" , pf .Name , i , err )
132
140
}
133
141
var v interface {}
@@ -146,7 +154,7 @@ func evalProjectionArray(ctx context.Context, pf ProjectionField, payload []inte
146
154
return nil , fmt .Errorf ("%s: invalid value: not a dict/object" , pf .Name )
147
155
}
148
156
var err error
149
- if subval , err = evalProjection (ctx , pf .Children , subval , fieldType , rbr ); err != nil {
157
+ if subval , err = evalProjection (ctx , pf .Children , subval , fieldType , rbr , rsc ); err != nil {
150
158
return nil , fmt .Errorf ("%s.%v" , pf .Name , err )
151
159
}
152
160
var v interface {}
@@ -162,7 +170,7 @@ func evalProjectionArray(ctx context.Context, pf ProjectionField, payload []inte
162
170
return resp , nil
163
171
}
164
172
165
- func evalProjection (ctx context.Context , p Projection , payload map [string ]interface {}, fg schema.FieldGetter , rbr * referenceBatchResolver ) (map [string ]interface {}, error ) {
173
+ func evalProjection (ctx context.Context , p Projection , payload map [string ]interface {}, fg schema.FieldGetter , rbr * referenceBatchResolver , rsc Resource ) (map [string ]interface {}, error ) {
166
174
res := map [string ]interface {}{}
167
175
resMu := sync.Mutex {}
168
176
var err error
@@ -191,7 +199,7 @@ func evalProjection(ctx context.Context, p Projection, payload map[string]interf
191
199
return nil , fmt .Errorf ("%s: invalid value: not a dict" , pf .Name )
192
200
}
193
201
var err error
194
- if subval , err = evalProjection (ctx , pf .Children , subval , def .Schema , rbr ); err != nil {
202
+ if subval , err = evalProjection (ctx , pf .Children , subval , def .Schema , rbr , rsc ); err != nil {
195
203
return nil , fmt .Errorf ("%s.%v" , pf .Name , err )
196
204
}
197
205
if res [name ], err = resolveFieldHandler (ctx , pf , def , subval ); err != nil {
@@ -203,10 +211,14 @@ func evalProjection(ctx context.Context, p Projection, payload map[string]interf
203
211
Projection : pf .Children ,
204
212
Predicate : Predicate {& Equal {Field : "id" , Value : val }},
205
213
}
206
- rbr .request (ref .Path , q , func (payloads []map [string ]interface {}, validator schema.Validator ) error {
214
+ subRsc , err := rsc .SubResource (ctx , ref .Path )
215
+ if err != nil {
216
+ return nil , err
217
+ }
218
+ rbr .request (subRsc , q , func (payloads []map [string ]interface {}, validator schema.Validator , rsc Resource ) error {
207
219
var v interface {}
208
220
if len (payloads ) == 1 {
209
- payload , err := evalProjection (ctx , pf .Children , payloads [0 ], validator , rbr )
221
+ payload , err := evalProjection (ctx , pf .Children , payloads [0 ], validator , rbr , rsc )
210
222
if err != nil {
211
223
return fmt .Errorf ("%s: error applying Projection on sub-field: %v" , name , err )
212
224
}
@@ -223,7 +235,7 @@ func evalProjection(ctx context.Context, p Projection, payload map[string]interf
223
235
if payload , ok := val .([]interface {}); ok {
224
236
var err error
225
237
var subvalp * []interface {}
226
- if subvalp , err = evalProjectionArray (ctx , pf , payload , & array .Values , rbr ); err != nil {
238
+ if subvalp , err = evalProjectionArray (ctx , pf , payload , & array .Values , rbr , rsc ); err != nil {
227
239
return nil , fmt .Errorf ("%s: error applying projection on array item #%d: %v" , pf .Name , i , err )
228
240
}
229
241
if res [name ], err = resolveFieldHandler (ctx , pf , & array .Values , subvalp ); err != nil {
@@ -238,7 +250,7 @@ func evalProjection(ctx context.Context, p Projection, payload map[string]interf
238
250
return nil , fmt .Errorf ("%s: invalid value: not a dict" , pf .Name )
239
251
}
240
252
var err error
241
- if subval , err = evalProjection (ctx , pf .Children , subval , fg , rbr ); err != nil {
253
+ if subval , err = evalProjection (ctx , pf .Children , subval , fg , rbr , rsc ); err != nil {
242
254
return nil , fmt .Errorf ("%s.%v" , pf .Name , err )
243
255
}
244
256
if res [name ], err = resolveFieldHandler (ctx , pf , def , subval ); err != nil {
@@ -264,9 +276,13 @@ func evalProjection(ctx context.Context, p Projection, payload map[string]interf
264
276
if err != nil {
265
277
return nil , err
266
278
}
267
- rbr .request (ref .Path , q , func (payloads []map [string ]interface {}, validator schema.Validator ) (err error ) {
279
+ subRsc , err := rsc .SubResource (ctx , ref .Path )
280
+ if err != nil {
281
+ return nil , err
282
+ }
283
+ rbr .request (subRsc , q , func (payloads []map [string ]interface {}, validator schema.Validator , rsc Resource ) (err error ) {
268
284
for i := range payloads {
269
- if payloads [i ], err = evalProjection (ctx , pf .Children , payloads [i ], validator , rbr ); err != nil {
285
+ if payloads [i ], err = evalProjection (ctx , pf .Children , payloads [i ], validator , rbr , rsc ); err != nil {
270
286
return fmt .Errorf ("%s: error applying projection on sub-resource item #%d: %v" , pf .Name , i , err )
271
287
}
272
288
}
0 commit comments