Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.

Commit 8d96b82

Browse files
committed
Give an empty multihead connection as null
This commit changes behaviour in the following cases: 1. When a union variant to which a connected object belongs is not appear in a query, the library returns box.NULL w/o any wrappers. 2. When no connected object is found, the library returns box.NULL as well even if all-nulls check before fails (typically because of disable_dangling_check option, but also it is possible because of using different source fields across multihead connection variants). The first case is tested with to_avro_multihead.test.lua. The latter one does not tested. In these cases we could receive `{"collection_name": null}` as a result instead of just `null`. Only `null` is valid result for a avro-schema union. Both variant however are valid by our avro-schema generated for a query, because a multi-head connection represented as an object with nullable fields. There is a reason for that, see the comment for the union_to_avro() function in graphql/query_to_avro.lua. Fixes #253.
1 parent cab19ec commit 8d96b82

File tree

3 files changed

+35
-11
lines changed

3 files changed

+35
-11
lines changed

graphql/bfs_executor.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ local function filter_object(object, object_type, selections, context, opts)
575575
qcontext = qcontext,
576576
schema = context.schema,
577577
parentObject = object_type,
578+
fieldASTs = {selection},
578579
}
579580
end
580581

graphql/convert_schema/resolve.lua

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,8 @@ function resolve.gen_resolve_function_multihead(collection_name, connection,
254254
local is_hidden = opts.is_hidden or false
255255
check(is_hidden, 'is_hidden', 'boolean')
256256

257-
-- If a parent object does not have all source fields (for any of
258-
-- variants) non-null then we do not resolve variant and just return
259-
-- box.NULL.
257+
-- If a parent object has all source fields null (for all variants)
258+
-- then we do not resolve variant and just return box.NULL.
260259
local is_source_fields_found = false
261260
for _, variant in ipairs(c.variants) do
262261
is_source_fields_found =
@@ -280,6 +279,29 @@ function resolve.gen_resolve_function_multihead(collection_name, connection,
280279
local v, variant_num, box_field_name = resolve_variant(parent)
281280
local destination_type = union_types[variant_num]
282281

282+
-- check whether destination type is in requested types
283+
local is_variant_requested = false
284+
for _, s in ipairs(info.fieldASTs[1].selectionSet.selections) do
285+
local requested_type_name = s.typeCondition.name.value
286+
if destination_type.name == requested_type_name then
287+
is_variant_requested = true
288+
break
289+
end
290+
end
291+
292+
-- If the variant the object match is not requested in a query, just
293+
-- return box.NULL, w/o the wrapper.
294+
if not is_variant_requested then
295+
if gen_prepare then
296+
return {
297+
is_calculated = true,
298+
objs = box.NULL,
299+
}
300+
else
301+
return box.NULL, nil
302+
end
303+
end
304+
283305
local quazi_connection = {
284306
type = c.type,
285307
parts = v.parts,
@@ -300,14 +322,20 @@ function resolve.gen_resolve_function_multihead(collection_name, connection,
300322
result.connection = quazi_connection
301323
result.invoke = function(prepared_resolve)
302324
local result = invoke_resolve(prepared_resolve)
303-
-- see comment below
325+
-- see comments below
326+
if result == nil then return box.NULL, nil end
304327
return {[box_field_name] = result}, destination_type
305328
end
306329
return result
307330
else
308331
local result = resolve.gen_resolve_function(collection_name,
309332
quazi_connection, destination_type, {}, accessor, gen_opts)(
310333
parent, {}, info, opts)
334+
-- If a connected object was not found, return just box.NULL w/o
335+
-- wrapping. It is possible here when different source fields are
336+
-- set for variants or when the disable_dangling_check options is
337+
-- set.
338+
if result == nil then return box.NULL, nil end
311339
-- This 'wrapping' is needed because we use 'select' on 'collection'
312340
-- GraphQL type and the result of the resolve function must be in
313341
-- {'collection_name': {result}} format to be avro-valid.

test/extra/to_avro_multihead.test.lua

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,6 @@ local ok, err = avro.validate(compiled_schema_heroes, result_1.data)
268268
test:ok(ok, 'query 1 response validation (obtainHeroes)', {err = err})
269269

270270
-- humans
271-
result_expected_1.hero_collection[1].hero_connection.starship_collection = nil
272-
result_expected_1.hero_collection[1].hero_banking_connection
273-
.dublon_account_collection = nil
274271
local result_1 = gql_query:execute(variables_1, 'obtainHumans')
275272
test:is_deeply(result_1.data, result_expected_1,
276273
'query 1 response (obtainHumans)')
@@ -307,11 +304,9 @@ local ok, err = avro.validate(compiled_schema_heroes, result_2.data)
307304
test:ok(ok, 'query 2 response validation (obtainHeroes)', {err = err})
308305

309306
-- humans
310-
result_expected_2.hero_collection[1].hero_connection.starship_collection = nil
311-
result_expected_2.hero_collection[1].hero_banking_connection
312-
.dublon_account_collection = nil
307+
result_expected_2.hero_collection[1].hero_connection = nil
308+
result_expected_2.hero_collection[1].hero_banking_connection = nil
313309
local result_2 = gql_query:execute(variables_2, 'obtainHumans')
314-
print(yaml.encode(result_2.data))
315310
test:is_deeply(result_2.data, result_expected_2,
316311
'query 2 response (obtainHumans)')
317312
local ok, err = avro.validate(compiled_schema_humans, result_2.data)

0 commit comments

Comments
 (0)