-
Notifications
You must be signed in to change notification settings - Fork 3
Add creation of avro-schema from query with multi-head connections, Unions, Maps and directives #201
Conversation
a1808e0
to
e951857
Compare
e951857
to
ed13524
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments for maps generation.
graphql/query_to_avro.lua
Outdated
@@ -29,7 +33,9 @@ local gql_scalar_to_avro_index = { | |||
|
|||
local function gql_scalar_to_avro(fieldType) | |||
assert(fieldType.__type == "Scalar", "GraphQL scalar field expected") | |||
assert(fieldType.name ~= "Map", "Map type is not supported") | |||
if (fieldType.subtype == "Map") then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant parenthesis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, fixed.
graphql/convert_schema/types.lua
Outdated
|
||
local res = core_types.map | ||
local res = core_types.map({values = converted_values, name = map_name }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code style: no whitespace after '{' and whitespace before '}' (I prefer to avoid these whitespaces.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed to 'no whitespaces'
graphql/convert_schema/types.lua
Outdated
local converted_values = types.convert(state, avro_schema.values, | ||
{context = context}) | ||
|
||
local true_values_type = converted_values |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use core_types.nullable().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, why do you need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, suggest to use 'bare' or 'nullable' name depending of what do you need. The functions named in the same way are in 'core.types'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed with core_types.nullable() and 'nullable_values_type'.
We need this to name Map type properly. Previously we have single Map
type which has no info about values
type. Now we have ValuesType_Map
GraphQL type for each avro-schema map type. Like this:
{"type": "map", "values": "string"} -> String_Map
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After verbal discussion we decided not to name Map types like ValuesType_Map
and use context.path .. Map
names instead.
graphql/convert_schema/union.lua
Outdated
@@ -38,6 +38,9 @@ local function box_type(type_to_box, box_field_name, opts) | |||
-- for the argument type to avoid 'Encountered multiple types' error. See | |||
-- also the comment in @{types.box_collection_type}. | |||
local box_name = (gql_true_type.name or gql_true_type.__type) .. '_box' | |||
if (gql_true_type.__type == "Scalar" and gql_true_type.subtype == 'Map') then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are use two types of quotation marks in the one line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, redundant parenthesis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, fixed.
graphql/core/types.lua
Outdated
end, | ||
}) | ||
function types.map(config) | ||
local instance = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 spaces indent in this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
'we should not go here') | ||
end, | ||
}) | ||
function types.map(config) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add nonNull into the instance (see types.inputMap
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we use another mechanism for setting nullability.
Like this:
local res = core_types.map({values = converted_values, name = map_name})
return avro_t == 'map' and core_types.nonNull(res) or res
We do like this with records, arrays, etc. Why we may want to handle maps different way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don’t, but I propose to support it in the type object for unification with other type objects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, okay, 'for unification' is a valid argument for me.
graphql/query_to_avro.lua
Outdated
--- The function converts a GraphQL Map type to avro-schema map type. | ||
map_to_avro = function(mapType) | ||
assert(mapType.values ~= nil, "GraphQL Map type must have 'values' field") | ||
return { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double whitespace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
graphql/convert_schema/union.lua
Outdated
@@ -38,6 +38,9 @@ local function box_type(type_to_box, box_field_name, opts) | |||
-- for the argument type to avoid 'Encountered multiple types' error. See | |||
-- also the comment in @{types.box_collection_type}. | |||
local box_name = (gql_true_type.name or gql_true_type.__type) .. '_box' | |||
if (gql_true_type.__type == "Scalar" and gql_true_type.subtype == 'Map') then | |||
box_name = 'Map_box' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it for compatibility? For cases when a map is inside a union?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly. Previously we created box_name = ScalarType.name .. '_box'
and this covered Map
type case as well.
But now Map
type has some custom name, not 'Map', so we have to manually name box_type
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, please, let short comment here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that base_name
below does thw work and that if is not needed here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. Removed that if
graphql/query_to_avro.lua
Outdated
assert(mapType.values ~= nil, "GraphQL Map type must have 'values' field") | ||
return { | ||
type = "map", | ||
values = gql_type_to_avro(mapType.values), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double whitespace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
78b75ed
to
5cfae83
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit more comments re 'Maps' commit.
graphql/convert_schema/types.lua
Outdated
|
||
local res = core_types.map | ||
local map_name = helpers.full_name("Map", context) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for nitpicking: single quotes is used in this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. Consistency is good
graphql/convert_schema/types.lua
Outdated
@@ -448,10 +448,11 @@ function types.convert(state, avro_schema, opts) | |||
'got %s (avro_schema %s)'):format(type(avro_schema.values), | |||
json.encode(avro_schema))) | |||
|
|||
-- validate avro schema format inside 'values' | |||
types.convert(state, avro_schema.values, {context = context}) | |||
local converted_values = types.convert(state, avro_schema.values, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add 'Map' to path
before converting and remove after. It does not matter in context of name clashes (I think), but would be consistent with the other converting code: we add type names to path
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, done.
graphql/convert_schema/union.lua
Outdated
@@ -38,6 +38,9 @@ local function box_type(type_to_box, box_field_name, opts) | |||
-- for the argument type to avoid 'Encountered multiple types' error. See | |||
-- also the comment in @{types.box_collection_type}. | |||
local box_name = (gql_true_type.name or gql_true_type.__type) .. '_box' | |||
if (gql_true_type.__type == "Scalar" and gql_true_type.subtype == 'Map') then | |||
box_name = 'Map_box' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, please, let short comment here.
@@ -29,7 +30,9 @@ local gql_scalar_to_avro_index = { | |||
|
|||
local function gql_scalar_to_avro(fieldType) | |||
assert(fieldType.__type == "Scalar", "GraphQL scalar field expected") | |||
assert(fieldType.name ~= "Map", "Map type is not supported") | |||
if fieldType.subtype == "Map" then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: here double quotes is used accross the file, so it is okay. The inconsistency btw file is because of different origin authors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
graphql/convert_schema/union.lua
Outdated
@@ -38,6 +38,9 @@ local function box_type(type_to_box, box_field_name, opts) | |||
-- for the argument type to avoid 'Encountered multiple types' error. See | |||
-- also the comment in @{types.box_collection_type}. | |||
local box_name = (gql_true_type.name or gql_true_type.__type) .. '_box' | |||
if (gql_true_type.__type == "Scalar" and gql_true_type.subtype == 'Map') then | |||
box_name = 'Map_box' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that base_name
below does thw work and that if is not needed here.
5cfae83
to
45f6c0e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments for null multi-head connections.
graphql/convert_schema/resolve.lua
Outdated
@@ -190,6 +190,25 @@ function resolve.gen_resolve_function_multihead(collection_name, connection, | |||
end | |||
|
|||
return function(parent, _, info) | |||
-- If parent object does not have all source_fields (for any of | |||
-- variants) non-nill then we do not resolve variant and just return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typos:
- non-nill → non-null
- parent object → a parent object
- source_fields → source fields (because it is not the name of a field)
- started with uppercase letter, but does not end with a period.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, fixed.
graphql/convert_schema/resolve.lua
Outdated
@@ -190,6 +190,25 @@ function resolve.gen_resolve_function_multihead(collection_name, connection, | |||
end | |||
|
|||
return function(parent, _, info) | |||
-- If parent object does not have all source_fields (for any of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should allow to omit a variant determination only when source fields for all variants are null.
It would be good to have it described explicitly in README. Like so:
Multi-head connections
A parent object is matching against a multi-head connection variants in the order of the variants. The parent object should match with a determinant of at least one variant except the following case. When source fields of all variants are null the multi-head connection obligated to give
null
object as the result. In this case the parent object is allowed to don’t match any variant. One can use this feature to avoid to set any specific determinant value when a multi-head connection is known to have no connected object.
Ideally, we should have description of the entire multi-head connection feature (but it of course is not part of this set of issues).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you propose to add this short paragraph to README now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should allow to omit a variant determination only when source fields for all variants are null.
Ok, done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, to README.
graphql/convert_schema/resolve.lua
Outdated
-- variants) non-nill then we do not resolve variant and just return | ||
-- box.NULL | ||
for _, variant in ipairs(c.variants) do | ||
for _, p in ipairs(variant.parts) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that it would be good to use are_all_parts_null
function we already have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really not sure. This function has an assertion inside:
assert(ok,
'FULL MATCH constraint was failed: connection ' ..
'key parts must be all non-nulls or all nulls; ' ..
'object: ' .. json.encode(parent))
Consider the case: collection has three fields: 1, 2 and 3. Fields 1 and 2 are used as source fields for connection 1, while fields 2 and 3 are used as source fields for connection 2.
And some collection object has fields 1 and 2 not null and field 3 null. This is ok in general, but would met assertion condition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After discussion in chat we decided to add opts argument to are_all_parts_null
which would suppress assert and use this function.
@@ -0,0 +1,456 @@ | |||
local tap = require('tap') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Maybe briefly describe why it is needed and where differs from multihead_conn_testdata.lua? Maybe also it worth to link the issue here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- multihead_conn_testdata_with_nulls.lua → multihead_conn_with_nulls_testdata.lua
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Added brief description. Link to the issue seems inappropriate here from my point of view.
- Fixed.
end | ||
|
||
function multihead_conn_testdata.run_queries(gql_wrapper) | ||
local test = tap.test('multihead_conn_null') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
multihead_conn_null → multihead_conn_with_nulls
For the sake of consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
]]):strip()) | ||
test:is_deeply(result_1_2.data, exp_result_1_2, '1_2') | ||
|
||
local variables_1_3 = {hero_id = 'hero_id_3'} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, comment this case and link with the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
45f6c0e
to
f918558
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments for 'small refactor'. BTW, code style fixes is not a refactorng.
graphql/query_to_avro.lua
Outdated
@@ -176,19 +176,19 @@ union_to_avro = function(fieldType, subSelections, context) | |||
if box_sub_selections.selectionSet.selections[1].selectionSet ~= nil then | |||
-- Object GraphQL type case. | |||
type_sub_selections = | |||
box_sub_selections.selectionSet.selections[1].selectionSet.selections | |||
box_sub_selections.selectionSet.selections[1].selectionSet.selections |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don’t break indent. Carry like so:
aaaaa = xxxxxxx.yyyyyyyy
.zzzzzzz
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be merged with 'Make small clean up'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, done.
graphql/query_to_avro.lua
Outdated
else | ||
-- Scalar GraphQL type case. | ||
type_sub_selections = box_sub_selections.selectionSet.selections[1] | ||
end | ||
|
||
if is_multihead then | ||
local avro_type = gql_type_to_avro(type.kind, | ||
type_sub_selections, context, {is_nullable = true}) | ||
type_sub_selections, context, {is_nullable = true}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your wrote it within the PR in the commit re unions. Merge it into that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
graphql/query_to_avro.lua
Outdated
table.insert(result.fields, {name = type.name, type = avro_type}) | ||
else | ||
table.insert(result, gql_type_to_avro(type.kind, | ||
type_sub_selections, context)) | ||
type_sub_selections, context)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your wrote it within the PR in the commit re unions. Merge it into that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
graphql/query_to_avro.lua
Outdated
@@ -224,7 +224,7 @@ local function field_to_avro(object_type, fields, context) | |||
assert(d.kind == "directive") | |||
check(d.name.value, "directive.name.value", "string") | |||
assert(d.name.value == "include" or d.name.value == "skip", | |||
"Only 'include' and 'skip' directives are supported for now") | |||
"Only 'include' and 'skip' directives are supported for now") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your wrote it within the PR in the commit re directives. Merge it into that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
test/test_utils.lua
Outdated
|
||
-- Converts map recursively into array. If an array with maps is | ||
-- encountered then all this maps will be converted too. | ||
function test_utils.convert_table_to_array(map) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
function recursively_map_to_array(t)
if type(t) == 'table' and not utils.is_array(t) do
local res = {}
for k, v in pairs(t) do
assert(type(k) == 'string')
table.insert(res, {k, v})
end
table.sort(res, function(a, b) return a[1] < b[1] end)
return res
end
return t
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t test it. Just propose a bit simper variant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pairs
would give us numbers (1, 2, 3) as well, wouldn't it?
So assert(type(k)) == 'string'
should fail.
And we may have maps inside arrays as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, forget about recursion. It should like so I guess:
function recursively_map_to_array(t)
if type(t) == 'table' and not utils.is_array(t) then
local res = {}
for k, v in pairs(t) do
assert(type(k) == 'string')
table.insert(res, {k, recursively_map_to_array(v)})
end
table.sort(res, function(a, b) return a[1] < b[1] end)
return res
elseif type(t) == 'table' then
local res = {}
for _, v in ipairs(t) do
table.insert(res, recursively_map_to_array(v))
end
return res
end
return t
end
But as discussed verbally field order in arrays are changed sporadically too and it is hard to simply sort it, because elements can be tables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Several months later even you himself will have difficulties with saying for what it was. Comment it in the commit message, add usage in introspection.test.lua.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments re unions.
graphql/query_to_avro.lua
Outdated
@@ -97,6 +113,88 @@ map_to_avro = function(mapType) | |||
} | |||
end | |||
|
|||
--- The function converts a GraphQL Union type to avro-schema type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'The function' is redundant. Just 'Convert …'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, fixed.
graphql/query_to_avro.lua
Outdated
--- avro-schema records. Each field represents one union variant. Variant type | ||
--- name is taken as a field name. Such records must have all fields nullable. | ||
--- | ||
--- We convert multi-head Unions to records instead of unions because in case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
multi-head Unions → multi-head connections?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think writing 'multi-head connections' here is a little bit wrong, because we are talking in this comment not about multi-head connections, but about their implementation - Unions.
Changed like this:
multi-head Unions → Unions implementing multi-head connections
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are going to be too formal :) I’m okay.
graphql/query_to_avro.lua
Outdated
--- We convert multi-head Unions to records instead of unions because in case | ||
--- of 1:N connections we would not have valid avro-schema (if use unions). | ||
--- This is because according to avro-schema standard unions may not contain | ||
--- more than one schema with the same type (in case of 1:N multi-head |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose to reuse standard wording here:
Unions may not contain more than one schema with the same type, except for the named types record, fixed and enum.
Note for 'except for' part.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
graphql/query_to_avro.lua
Outdated
--- of 1:N connections we would not have valid avro-schema (if use unions). | ||
--- This is because according to avro-schema standard unions may not contain | ||
--- more than one schema with the same type (in case of 1:N multi-head | ||
--- connections we would have more than one 'array' in union) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No period at the end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
graphql/query_to_avro.lua
Outdated
assert(utils.table_size(box_type.fields) == 1, 'Box Object must ' .. | ||
'have exactly one field') | ||
local type = | ||
box_type.fields[utils.get_keys(box_type.fields)[1]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local type = select(2, next(box_type.fields))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, I would prefer name field_name
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed with select.
field_name
seems to be a wrong naming since type
is actually a type. Latter we use type.name
and type.kind
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
graphql/query_to_avro.lua
Outdated
|
||
if is_multihead then | ||
local avro_type = gql_type_to_avro(type.kind, | ||
type_sub_selections, context, {is_nullable = true}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is avro_helpers.make_avro_type_nullable
, so you don’t need to introduce the new option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, option removed.
graphql/query_to_avro.lua
Outdated
assert(fieldType.types ~= nil, "GraphQL Union must have 'types' field") | ||
check(fieldType.types, "fieldType.types", "table") | ||
local is_multihead = (fieldType.resolveType == nil) | ||
local result = {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case of is_multihead the table ({}
) is always replaced with the new one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it was my intention. I thought this previous construction is clearer then:
if is_multihead then
check(fieldType.name, "fieldType.name", "string")
result = {
type = 'record',
name = fieldType.name,
fields = {}
}
else
result = {}
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it is clearer in some way, maybe doesn’t. I would prefer to avoid it, because don’t sure how such empty objects can affect gc.
graphql/query_to_avro.lua
Outdated
type_sub_selections, context, {is_nullable = true}) | ||
table.insert(result.fields, {name = type.name, type = avro_type}) | ||
else | ||
table.insert(result, gql_type_to_avro(type.kind, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to add 'null' depending of whether the GraphQL Union is nullable. I think it is already handled somewhere with avro_helpers.make_avro_type_nullable
. Is it so?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is. We do it in gql_type_to_avro()
before returning result in case of 'natural' Unions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to be correct. Thanks.
local meta = testdata.get_test_metadata() | ||
testdata.fill_test_data(box.space, meta) | ||
|
||
local accessor = graphql.accessor_space.new({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use just graphql.new, I want to deprecate explicit use of built-in accessors at some time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
]] | ||
|
||
local expected_avro_schema = [[ | ||
type: record |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments for directives support.
The test is really huge, thanks!
graphql/query_to_avro.lua
Outdated
assert(d.name.value == "include" or d.name.value == "skip", | ||
"Only 'include' and 'skip' directives are supported for now") | ||
end | ||
if type(fieldTypeAvro) == "string" then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just use avro_helpers.make_avro_type_nullable
.
local yaml = require('yaml') | ||
local avro = require('avro_schema') | ||
local test = require('tap').test('to avro schema') | ||
local common_testdata = require('test.testdata.common_testdata') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Place relative imports after package.path updating.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
]] | ||
|
||
local expected_avro_schema = [[ | ||
type: record |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, add indent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, done.
user_id = 'user_id_1', | ||
include_description = false, | ||
skip_discount = true, | ||
include_user = true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you intend to invert boolean values comparing to variables_1
? If so, you missed include_user
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, there was no such intention. I wanted to test nested directives. Like this:
user_connection(user_id: "user_id_1") @include(if: $include_user) {
user_id
first_name @include(if: $include_user_first_name)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay.
]] | ||
|
||
local expected_avro_schema = [[ | ||
type: record |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same as above: indent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fxd.
|
||
local ok, err = avro.validate(compiled_schema, result_2) | ||
assert(ok, tostring(err)) | ||
test:is(ok, true, 'query response validation by avro - union 2') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test:ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fxd.
]]) | ||
|
||
test:is_deeply(result_2, result_expected_2, | ||
'comparision between expected and actual query response - multihead 2') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fxd.
local union_meta = union_testdata.get_test_metadata() | ||
union_testdata.fill_test_data(box.space, union_meta) | ||
|
||
local accessor = graphql.accessor_space.new({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same as above: please, use graphql.new w/o separate accessor creating.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fxd.
local multihead_meta = multihead_testdata.get_test_metadata() | ||
multihead_testdata.fill_test_data(box.space, multihead_meta) | ||
|
||
local accessor = graphql.accessor_space.new({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same: proposed to move accessor’s arguments to the graphql.new
call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fxd.
local common_meta = common_testdata.get_test_metadata() | ||
common_testdata.fill_test_data(box.space, common_meta) | ||
|
||
local accessor = graphql.accessor_space.new({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is better to use graphql.new
in new tests and maybe deprecate separate usage of build-in accessors in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fxd.
f918558
to
2f7dafc
Compare
2f7dafc
to
312b47c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Some minor comments are below.
hero_type: human | ||
hero_connection: | ||
human_collection: | ||
name: Luke |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indent for yaml seems to be 2 spaces everywhere (because of yaml.encode dump it so), but here there are several places with 4 spaces indent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
testdata.fill_test_data() | ||
local meta = testdata.get_test_metadata() | ||
|
||
local accessor = graphql.accessor_space.new({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proposed to move the options to graphql.new
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
]] | ||
|
||
local expected_avro_schema = [[ | ||
type: record |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
banking_type: credit | ||
hero_banking_connection: | ||
credit_account_collection: | ||
- account_id: credit_account_id_1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4 spaces indent instead of 2 spaces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
banking_type: dublon | ||
hero_banking_connection: | ||
dublon_account_collection: | ||
- account_id: dublon_account_id_1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4 spaces indent instead of 2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
312b47c
to
286cb8d
Compare
Also changed GraphQL Map type: now it has subType = Map and name = values.type .. '_Map'
(Example: 'String_Map') This is to avoid name clash.
Сloses #200 #198 #197 #85 #84