-
Notifications
You must be signed in to change notification settings - Fork 3
Conversation
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.
Questions and comments for the code are attached. Answers for such questions can be good basis for proper documentation and code comments.
Please, give attention to my expectation to have backlog trackerized once the feature will be implemented in the current state (see related comment).
@@ -41,23 +84,74 @@ testdata.meta = { | |||
"order_collection": { | |||
"schema_name": "order", | |||
"connections": [ | |||
{ | |||
"type": "1:N", | |||
"name": "order__order_item", |
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.
Having schema/collection name as part of connection makes understanding of a query harder.
-- - id | ||
-- - first_name | ||
-- - last_name | ||
-- - order: Orders of users. |
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 clarify (comment here) that order is a shopping cart to better understanding the example.
local item_id_max = #items | ||
for _, item in ipairs(items) do | ||
virtbox.item_collection:replace( | ||
{item.id, item.description, item.name, item.price} |
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.
Broken indent.
order_item_cnt = order_item_cnt + 1 | ||
local item_id = order_item_cnt % item_id_max + 1 | ||
virtbox.order_item_collection:replace( | ||
{ |
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.
Broken indent.
graphql/query_to_avro.lua
Outdated
return result | ||
end | ||
error('Unknown type "' .. fieldTypeName .. '" for field "' .. | ||
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.
luacheck output:
graphql/query_to_avro.lua:62:13: accessing undefined variable field
graphql/query_to_avro.lua
Outdated
end | ||
|
||
if fieldTypeName == 'Scalar' or fieldTypeName == 'Enum' then | ||
return fieldType.serialize(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.
Can you describe what is going on here? We have no any value to serialize… Also it is unexpected to see scalars here, as you process it separatelly.
graphql/query_to_avro.lua
Outdated
return result | ||
--return collection_to_avro(fieldType, result, subSelections, context) | ||
elseif fieldTypeName == 'Interface' or fieldTypeName == 'Union' then | ||
local objectType = fieldType.resolveType(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.
We trying to resolve union to a certain type based on what information? We have no values here to choose one of variants. Can you describe it, please?
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.
My mistake. It should not work properly, but I did not know what to do with unions. 1. They are not implemented. 2. They are represented in different ways in gql and tarantool. A suttose at this point we should assert here.
graphql/query_to_avro.lua
Outdated
elseif fieldTypeName == 'Interface' or fieldTypeName == 'Union' then | ||
local objectType = fieldType.resolveType(result) | ||
result.type = collection_to_avro(objectType, result, | ||
subSelections, 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.
Python-style indent.
graphql/query_to_avro.lua
Outdated
return result | ||
end | ||
|
||
collection_to_avro = function(objectType, object, 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.
Maybe 'object_to_avro' is better name? I think about a case with inner record within a collection object or with an object within an array.
graphql/query_to_avro.lua
Outdated
return result | ||
end | ||
|
||
if fieldTypeName == 'Scalar' or fieldTypeName == 'Enum' 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.
I don’t know how to receive 'scalar' from our avro-schemas. Maybe we should ban it?
We have no enum / union support for now (and maybe interfaces too). I think we need to test it or stated explicitly that it need to be tested once will be available. So, I expect that you will file bunch of issues to support various types in AST or at least add notes re query schemas to existing issues for supporting of such features.
(is not for offend) If you don’t sure current implementation will work properly, maybe it is better to remove it for now to keep code compact and readable?
Added @SudoBobo as optional reviewer. |
fe69468
to
49de748
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.
I think it is good enough (there was worse code from me). Despite that I leave some comments to grow our feeling of a 'healthy code'.
graphql/query_to_avro.lua
Outdated
--- | ||
--- @treturn table `avro_schema` avro schema for any `query:execute()` result. | ||
function query_to_avro.convert(query) | ||
local state = query.state |
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.
Optional: it is good to catch compiled_query.avro_schema()
(period instead of colon) calls and produce a meaningfull message in the case. Just assert that the query
parameter is a table.
graphql/query_to_avro.lua
Outdated
-- The function converts avro type to nullable. | ||
-- In current tarantool/avro-schema implementation we simply add '*' | ||
-- to the end of type name. | ||
-- The function do not copy the resulting type but changes it in place. |
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 changes and returns changed object both. Personally I prefer to implement one of that approaches to decrease possible area to misuse a function (one can expect that it does not change the parameter, because it returns the new 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.
@Khatskevich You just ignored the comment. So I don’t know your point and I have mine preferences. I’ll fix it according to what I know — mine preferences.
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 prefer here to leave it both return and change an input in place, because of immutability of strings in Lua.
graphql/query_to_avro.lua
Outdated
-- @tparam table avro schema node to be converted to nullable | ||
-- | ||
-- @tresult table schema node; basically it is the passed schema node, | ||
-- however in nullable type implementation through unions it can be different |
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 get you in two ways:
- As I see we always return the same table (but with change field).
- What is
nullable type implementation through unions
? The above statement says that nulable type is implemented via '*'. Maybe more context 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.
@Khatskevich You just ignored the comment. I’ll fix it according to mine preferences.
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.
Removed confusing part about an union.
graphql/query_to_avro.lua
Outdated
avro.type = make_avro_type_nullable(avro.type) | ||
return avro | ||
end | ||
assert(false, "Avro type should be a string or table") |
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 good to have "got " .. type_type
at the end (saves some time at debug).
graphql/query_to_avro.lua
Outdated
return result | ||
end | ||
|
||
-- The function converts avro type to 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.
The function cannot be applied to its result, yep? We need to check wheter passed type is nullable or stated non-self-applicability explicitly in the comment.
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.
Assert on nullable types is worse option then self-applicability, IMO, but ok, you fixed it.
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.
Reworked to allow nulllable type as an input.
graphql/query_to_avro.lua
Outdated
local innerType = fieldType.ofType | ||
-- Steal type from virtual object. | ||
-- This is necessary because in case of arrays type should be | ||
-- "completed" into results `items` field, but in case of 1:1 relations |
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 oppose an array (List) vs a record (Object) and a scalar (Scalar). That is exactly what this part of the code doing. When you say about 1:1 connection it at least yield the question what is going with nested/top-level records and scalars.
graphql/query_to_avro.lua
Outdated
--- root to the current object | ||
--- | ||
--- @treturn table corresponding Avro schema | ||
object_to_avro = function(object_type, selections, context, 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.
Unused and undocumented parameter 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.
We have --no-unused-args
in luacheck, because it is too restricting in some cases. Say, when you don’t use self
parameter of a function.
graphql/query_to_avro.lua
Outdated
context.namespace_parts = {} | ||
local rootType = state.schema[context.operation.operation] | ||
local selections = context.operation.selectionSet.selections | ||
return object_to_avro(rootType, selections, context, false) |
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.
If you’ll remove nullable
parameter, don’t miss to remove it here.
graphql/query_to_avro.lua
Outdated
NonNull) | ||
local fieldTypeName = fieldType.__type | ||
if fieldTypeName == 'NonNull' then | ||
-- In case the field is NonNull, the real type is in ofType attibute. |
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.
attibute → attribute
graphql/query_to_avro.lua
Outdated
local function complete_field_to_avro(fieldType, result, subSelections, context, | ||
NonNull) | ||
local fieldTypeName = fieldType.__type | ||
if fieldTypeName == 'NonNull' 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.
This if
is… hmm… hard to read. Let’s look over with me:
- The
fieldTypeName == 'NonNull'
branch.- Here we see renaming that works like recursion, but expressed via fall-through.
- By the way, it cannot process several nested NonNull’s.
NonNull ~= true
branch.- Never use
x ~= true
. Your reader does not want to normalize the code in the brain. - Here we use recursion and don’t use fall-through.
- Never use
How to make the code readable? Options I see:
- Save
is_nonnull
oris_nullable
flag. Process fieldType/fieldType.ofType and save the result. Make it nullable in dependence of the flag. Return the result. - Save
is_nonnull
oris_nullable
flag. In case of NonNull resursively call the function, but pass the flag in a parameter. Process result. Make it nullable in dependence of the flag. Return the result.
I appeal you to leave it as is if you comfortable with your approach, but I think that it is good to share argued opinions between us.
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.
@Khatskevich You just ignored the comment. I’ll fix it according to mine preferences.
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.
Reworked according to the first option. Make it returning a result using return
instead of the mutable table parameter.
The changes are debatable, but I'm trying to improve code readability as stated in the comments to [1]. [1]: tarantool/graphql#58
Add goods (item) and order_item relation.
This patch is important for graphql query -> avro schema convertor implementation, because both executor and convertor walks over query AST. Part of #7
Extend query object: add `avro_schema` method, which produces Avro schema which can be used to verify or flatten any `query_exequte` result. Closes #7
The changes are debatable, but I'm trying to improve code readability as stated in the comments to [1]. [1]: tarantool/graphql#58
The changes are debatable, but I'm trying to improve code readability as stated in the comments to [1]. [1]: tarantool/graphql#58
No description provided.