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

Support avro-unions #115

Merged
merged 1 commit into from
Apr 13, 2018
Merged

Support avro-unions #115

merged 1 commit into from
Apr 13, 2018

Conversation

SudoBobo
Copy link
Contributor

@SudoBobo SudoBobo commented Apr 9, 2018

Closes #109 (but there is blocking problem described here tarantool/avro-schema#64)

--- The function 'boxes' given GraphQL type so it can be used in GraphQL unions.
--- By specification GraphQL may contain only objects. As we want to use scalar
--- types as unions' variants, we 'box' (or wrap) them into object types with
--- one field - _boxes. GraphQL objects are boxed for unification.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main reason is type determinant form in avro-schema.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed and clarified comment.

check(gql_type, 'gql_type', 'table')

local box_name, box_fields
local gql_true_type = nullable(gql_type)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to know true type to perform proper logic later. Refactored this part a bit.

--require('pl.pretty').dump(avro_schema)

for _, type in ipairs(avro_schema) do
if type == 'null' then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach to represent unions with null need to be commented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented.

@SudoBobo SudoBobo force-pushed the sb/avro-union branch 2 times, most recently from 550cd80 to aa89196 Compare April 12, 2018 19:09
@SudoBobo SudoBobo changed the title WIP PR Support avro-unions Apr 12, 2018
@SudoBobo SudoBobo force-pushed the sb/avro-union branch 3 times, most recently from f491502 to 777a607 Compare April 13, 2018 12:39
Copy link
Member

@Totktonada Totktonada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, consider comments below. Some of them can be outdated after our chat discussions.

@@ -64,6 +64,8 @@ local function avro_type(avro_schema)
return 'record*'
elseif utils.is_array(avro_schema) then
return 'union'
elseif utils.is_array(avro_schema.type) then
return 'union'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above utils.is_array(avro_schema) branch seems to be dead code? If so, it need to be removed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it seems to be more consistent if we’ll use this function only for avro types and never for record fields. So, it wuold be good to fix problems with using the above utils.is_array(avro_schema) branch.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now fixed.

name = field.name,
kind = gql_type(state, field.type),
}
-- union case
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, move the comment into the corresponding if branch.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No more actual.

if utils.is_array(field.type) then
res[field.name] = {
name = field.name,
kind = gql_type(state, {name = field.name, type = field.type}),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No more actual.

@@ -204,4 +204,13 @@ function utils.table_size(t)
return count
end

function utils.is_in_array(key, array)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

key → value

I have the same function in the another project named value_in. Maybe it worth to reuse such names. Up to you.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. Fxd.

--- 'Boxes' is a part of this specific form.
---
--- @tparam table gql_type GraphQL type to be boxed
--- @param avro_schema table or string ... necessary for right names for boxed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avro_schema → avro_name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, forgot to finish comment. Now it is finished.

if i ~= j then
assert(avro_type(type) ~= avro_type(another_type),
'Unions may not contain more than one schema with ' ..
'the same type except for the named types ' ..
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

colon need to be after 'named types'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fxd.

if type.name == nil then
for j, another_type in ipairs(avro_schema) do
if i ~= j then
assert(avro_type(type) ~= avro_type(another_type),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two records with different names are allowed by an avro-schema, but will not pass this check? Ok for postpone to backlog.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two records will pass this check as their type.name is not nil.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even when names are the same?

end
error(('result objects "%s" has no determinant field matching ' ..
'determinants for this union "%s"'):format(yaml.encode(result),
yaml.encode(field_to_type)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, it is better to use json module for inline objects or use yaml and place multilne objects on its own line(s) after an error message.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer second variant as it is seems easier to read. Fxd.

}
}

local USER_ID = 2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

USER_ID → USER_ID_FN or USER_ID_FIELD

print('Validating results with initial avro-schema')
local _, schema = avro_schema.create(schemas.user_collection)
for _, r in ipairs(result.user_collection) do
local ok, err = avro_schema.validate(schema, r)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is okay for this test, but in the future we need to support converting unions to avro-schema. Don’t sure there are an issue (likely not).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean from GraphQL Union to avro union?

Copy link
Member

@Totktonada Totktonada Apr 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not exactly. We need to convert a query (in context of a graphql schema we can generate from some avro-schema) to avro-schema back. A part of this convertion is unions. They will be pass the way avro → graphql → avro :)

@@ -688,7 +836,7 @@ end
--- XXX As it is not clear now what to do with complex types inside arrays
--- (just pass to results or allow to use filters), only scalar arrays
--- is allowed for now. Note: map is considered scalar.
gql_type = function(state, avro_schema, collection, collection_name)
gql_type = function(state, avro_schema, collection, collection_name, field_name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ldoc need to be updated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to state explicitly that it wil be used only for an union generation, because avro-schema union has no any name in it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fxd.

@SudoBobo SudoBobo force-pushed the sb/avro-union branch 4 times, most recently from f5bd594 to bf5f2a5 Compare April 13, 2018 17:11
--- 1) GraphQL Union types may contain only GraphQL Objects. GraphQL Scalar
--- types may be put inside Union only if they are 'boxed' inside an Object.
--- 2) GraphQL Union types must have specific form, described in @{create_gql_union}.
--- 'Boxes' is a part of this specific form.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

specific form
described in

Common words and the link. It is not good problem statement. Before the last change you stated explicitly that the problem is in avro-schema union, but mistakely use the term 'initial avro-schema' (you have no one, see the comment below). Now you don’t state any problem here (in point 2). Please, give back the old comment and ask me if you have problems with check correctness of the wording.

Copy link
Contributor Author

@SudoBobo SudoBobo Apr 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved problem description to comments to create_gql_union()

@Totktonada
Copy link
Member

LGTM.

I wait you will clarify some points in comments, but going to leave you face-to-face with fighting with wording :)

@SudoBobo SudoBobo force-pushed the sb/avro-union branch 3 times, most recently from 1ba583b to 0a4a7dd Compare April 13, 2018 18:59
@SudoBobo SudoBobo merged commit e08cb5c into master Apr 13, 2018
@SudoBobo SudoBobo deleted the sb/avro-union branch May 26, 2018 18:07
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants