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

Commit 29a5126

Browse files
committed
Use gql_type to create top level collections
The commmit introduces the idea that the `Query` object is just a collection. If so, it is natural to add this type to GraphQL using the same procedure as for other types. This is important change, because it not only deletes current code duplication, but allows to not repeat yourself during further coding.
1 parent b046ce8 commit 29a5126

File tree

2 files changed

+52
-44
lines changed

2 files changed

+52
-44
lines changed

graphql/accessor_general.lua

+6-6
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ end
206206
--- function will search through
207207
---
208208
--- @tparam table from information about a connection bring executor to select
209-
--- from a current collection; it is nil when the executor selecting top-level
210-
--- objects, but has the following structure for nested collections:
209+
--- from a current collection; its `collection_name` is 'Query' selecting
210+
--- top-level objects;it has the following structure:
211211
---
212212
--- {
213213
--- collection_name = <...> (string),
@@ -267,7 +267,7 @@ local get_index_name = function(self, collection_name, from, filter, args)
267267
-- If an offset is set we return it as `pivot.filter`. So, select will be
268268
-- performed by an index from the connection, then the result will be
269269
-- postprocessed using `pivot`.
270-
if from ~= nil then
270+
if from.collection_name ~= 'Query' then
271271
local connection_index =
272272
connection_indexes[collection_name][from.connection_name]
273273
local index_name = connection_index.index_name
@@ -631,8 +631,8 @@ end
631631
---
632632
--- @tparam string collection_name name of collection to perform select
633633
---
634-
--- @tparam table from collection and connection names we arrive from/by or nil
635-
--- as defined in the `tarantool_graphql.new` function description
634+
--- @tparam table from collection and connection names we arrive from/by as
635+
--- defined in the `tarantool_graphql.new` function description
636636
---
637637
--- @tparam table filter subset of object fields with values by which we want
638638
--- to find full object(s)
@@ -685,7 +685,7 @@ local function select_internal(self, collection_name, from, filter, args, extra)
685685
assert(self.funcs.is_collection_exists(collection_name),
686686
('cannot find collection "%s"'):format(collection_name))
687687
local index = self.funcs.get_index(collection_name, index_name)
688-
if from ~= nil then
688+
if from.collection_name ~= 'Query' then
689689
-- allow fullscan only for a top-level object
690690
assert(index ~= nil,
691691
('cannot find index "%s" in space "%s"'):format(

graphql/tarantool_graphql.lua

+46-38
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,45 @@ gql_type = function(state, avro_schema, collection, collection_name)
443443
end
444444
end
445445

446+
--- Create virtual root collection `Query`, which has connections to any
447+
--- collection.
448+
---
449+
--- Actually, each GQL query starts its execution from the `Query` collection.
450+
--- That is why it shoult contain connections to any collection.
451+
---
452+
--- @tparam table state dictionary which contains all information about the
453+
--- schema, arguments, types...
454+
local function create_root_collection(state)
455+
local root_connections = {}
456+
-- The fake connections have 1:N mechanics.
457+
-- Create one connection for each collection.
458+
for collection_name, collection in pairs(state.collections) do
459+
table.insert(root_connections, {
460+
parts = {},
461+
name = collection_name,
462+
destination_collection = collection_name,
463+
type = "1:N"
464+
})
465+
end
466+
local root_schema = {
467+
type = "record",
468+
name = "Query",
469+
-- The fake root has no fields.
470+
fields = {}
471+
}
472+
local root_collection = {
473+
name = "Query",
474+
connections = root_connections
475+
}
476+
477+
-- `gql_type` is designed to create GQL type corresponding to a real schema
478+
-- and connections. However it also works with the fake schema.
479+
local root_type = gql_type(state, root_schema, root_collection, "Query")
480+
state.schema = schema.create({
481+
query = root_type
482+
})
483+
end
484+
446485
local function parse_cfg(cfg)
447486
local state = {}
448487
state.types = utils.gen_booking_table({})
@@ -461,8 +500,11 @@ local function parse_cfg(cfg)
461500
local collections = table.copy(cfg.collections)
462501
state.collections = collections
463502

464-
local fields = {}
465-
503+
-- Prepare types which represents:
504+
-- - Avro schemas (collections)
505+
-- - scalar field arguments (used to filter objects by value stored in it's
506+
-- field)
507+
-- - list arguments (offset, limit...)
466508
for collection_name, collection in pairs(state.collections) do
467509
collection.name = collection_name
468510
assert(collection.schema_name ~= nil,
@@ -495,43 +537,9 @@ local function parse_cfg(cfg)
495537
state.list_arguments[collection_name] = list_args
496538
state.all_arguments[collection_name] = args
497539

498-
-- create entry points from collection names
499-
fields[collection_name] = {
500-
kind = types.nonNull(types.list(state.types[collection_name])),
501-
arguments = state.all_arguments[collection_name],
502-
resolve = function(rootValue, args_instance, info)
503-
local object_args_instance = {} -- passed to 'filter'
504-
local list_args_instance = {} -- passed to 'args'
505-
for k, v in pairs(args_instance) do
506-
if list_args[k] ~= nil then
507-
list_args_instance[k] = v
508-
elseif state.object_arguments[k] ~= nil then
509-
object_args_instance[k] = v
510-
else
511-
error(('cannot found "%s" field ("%s" value) ' ..
512-
'within allowed fields'):format(tostring(k),
513-
tostring(v)))
514-
end
515-
end
516-
local from = nil
517-
518-
local extra = {
519-
qcontext = info.qcontext
520-
}
521-
return accessor:select(rootValue, collection_name, from,
522-
object_args_instance, list_args_instance, extra)
523-
end,
524-
}
525540
end
526-
527-
local schema = schema.create({
528-
query = types.object({
529-
name = 'Query',
530-
fields = fields,
531-
})
532-
})
533-
state.schema = schema
534-
541+
-- create fake root `Query` collection
542+
create_root_collection(state)
535543
return state
536544
end
537545

0 commit comments

Comments
 (0)