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

Commit 1db1c02

Browse files
committed
WIP: support avro-schema references (to records)
Related to #116.
1 parent 7c13a3a commit 1db1c02

File tree

1 file changed

+71
-34
lines changed

1 file changed

+71
-34
lines changed

graphql/tarantool_graphql.lua

Lines changed: 71 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -56,36 +56,61 @@ local default_instance
5656
-- forward declarations
5757
local gql_type
5858

59-
local function avro_type(avro_schema)
59+
local function is_scalar_type(avro_schema_type)
60+
check(avro_schema_type, 'avro_schema_type', 'string')
61+
62+
local scalar_types = {
63+
['int'] = true,
64+
['int*'] = true,
65+
['long'] = true,
66+
['long*'] = true,
67+
--[[
68+
['float'] = true,
69+
['float*'] = true,
70+
['double'] = true,
71+
['double*'] = true,
72+
['boolean'] = true,
73+
['boolean*'] = true,
74+
]]--
75+
['string'] = true,
76+
['string*'] = true,
77+
}
78+
79+
return scalar_types[avro_schema_type] or false
80+
end
81+
82+
local function is_compound_type(avro_schema_type)
83+
check(avro_schema_type, 'avro_schema_type', 'string')
84+
85+
local compound_types = {
86+
['record'] = true,
87+
['record*'] = true,
88+
['array'] = true,
89+
['array*'] = true,
90+
['map'] = true,
91+
['map*'] = true,
92+
}
93+
94+
return compound_types[avro_schema_type] or false
95+
end
96+
97+
local function avro_type(avro_schema, opts)
98+
local opts = opts or {}
99+
local allow_references = opts.allow_references or false
100+
60101
if type(avro_schema) == 'table' then
61-
if avro_schema.type == 'record' then
62-
return 'record'
63-
elseif avro_schema.type == 'record*' then
64-
return 'record*'
102+
if is_compound_type(avro_schema.type) then
103+
return avro_schema.type
65104
elseif utils.is_array(avro_schema) then
66105
return 'union'
67-
elseif avro_schema.type == 'array' then
68-
return 'array'
69-
elseif avro_schema.type == 'array*' then
70-
return 'array*'
71-
elseif avro_schema.type == 'map' then
72-
return 'map'
73-
elseif avro_schema.type == 'map*' then
74-
return 'map*'
106+
elseif allow_references then
107+
return avro_schema
75108
end
76109
elseif type(avro_schema) == 'string' then
77-
if avro_schema == 'int' then
78-
return 'int'
79-
elseif avro_schema == 'int*' then
80-
return 'int*'
81-
elseif avro_schema == 'long' then
82-
return 'long'
83-
elseif avro_schema == 'long*' then
84-
return 'long*'
85-
elseif avro_schema == 'string' then
86-
return 'string'
87-
elseif avro_schema == 'string*' then
88-
return 'string*'
110+
if is_scalar_type(avro_schema) then
111+
return avro_schema
112+
elseif allow_references then
113+
return avro_schema
89114
end
90115
end
91116
error('unrecognized avro-schema type: ' .. json.encode(avro_schema))
@@ -245,14 +270,13 @@ local function convert_record_fields_to_args(fields, opts)
245270
assert(type(field.name) == 'string',
246271
('field.name must be a string, got %s (schema %s)')
247272
:format(type(field.name), json.encode(field)))
248-
249-
-- records, arrays (gql lists) and maps can't be arguments, so these
250-
-- graphql types are to be skipped
251-
local avro_t = avro_type(field.type)
252-
if not skip_compound or (
253-
avro_t ~= 'record' and avro_t ~= 'record*' and
254-
avro_t ~= 'array' and avro_t ~= 'array*' and
255-
avro_t ~= 'map' and avro_t ~= 'map*') then
273+
-- records, arrays (gql lists), maps and unions can't be arguments, so
274+
-- these graphql types are to be skipped;
275+
-- skip_compound == false is the trick for accessor_general-provided
276+
-- record; we don't expect map, array or union here as well as we don't
277+
-- expect avro-schema reference.
278+
local avro_t = avro_type(field.type, {allow_references = true})
279+
if not skip_compound or is_scalar_type(avro_t) then
256280
local gql_class = gql_argument_type(field.type)
257281
args[field.name] = nullable(gql_class)
258282
end
@@ -711,7 +735,7 @@ gql_type = function(state, avro_schema, collection, collection_name)
711735
'state.accessor.list_args must not be nil')
712736

713737
-- type of the top element in the avro-schema
714-
local avro_t = avro_type(avro_schema)
738+
local avro_t = avro_type(avro_schema, {allow_references = true})
715739

716740
if avro_t == 'record' or avro_t == 'record*' then
717741
assert(type(avro_schema.name) == 'string',
@@ -735,6 +759,8 @@ gql_type = function(state, avro_schema, collection, collection_name)
735759
avro_schema.name,
736760
fields = fields,
737761
})
762+
state.declarations[avro_schema.name] = types.nonNull(res)
763+
state.declarations[avro_schema.name .. '*'] = res
738764
return avro_t == 'record' and types.nonNull(res) or res
739765
elseif avro_t == 'enum' then
740766
error('enums not implemented yet') -- XXX
@@ -764,6 +790,14 @@ gql_type = function(state, avro_schema, collection, collection_name)
764790
local gql_map = types_map
765791
return avro_t == 'map' and types.nonNull(gql_map) or gql_map
766792
else
793+
require('log').info('aaaa: ' .. json.encode(avro_schema))
794+
-- XXX: prevent name clash using namespaces
795+
if type(avro_schema) == 'string' then
796+
if state.declarations[avro_schema] ~= nil then
797+
return state.declarations[avro_schema]
798+
end
799+
end
800+
767801
local res = convert_scalar_type(avro_schema, {raise = false})
768802
if res == nil then
769803
error('unrecognized avro-schema type: ' ..
@@ -903,6 +937,9 @@ local function parse_cfg(cfg)
903937
state.list_arguments = utils.gen_booking_table({})
904938
state.all_arguments = utils.gen_booking_table({})
905939

940+
-- map from avro-schema names to graphql types
941+
state.declarations = {}
942+
906943
local accessor = cfg.accessor
907944
assert(accessor ~= nil, 'cfg.accessor must not be nil')
908945
assert(accessor.select ~= nil, 'cfg.accessor.select must not be nil')

0 commit comments

Comments
 (0)