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

Commit 82c0bad

Browse files
committed
design & code style fixes after review
1 parent 275f03c commit 82c0bad

15 files changed

+373
-340
lines changed

graphql/accessor_general.lua

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ local function process_tuple(state, tuple, opts)
827827

828828
-- convert tuple -> object
829829
local obj = opts.unflatten_tuple(collection_name, tuple,
830-
opts.default_unflatten_tuple, opts.is_collection_formatted)
830+
{ has_space_format = opts.has_space_format }, opts.default_unflatten_tuple)
831831

832832
-- skip all items before pivot (the item pointed by offset)
833833
if not state.pivot_found and pivot_filter then
@@ -975,7 +975,7 @@ local function select_internal(self, collection_name, from, filter, args, extra)
975975
fetched_object_cnt_max = self.settings.fetched_object_cnt_max,
976976
collection_name = collection_name,
977977
unflatten_tuple = self.funcs.unflatten_tuple,
978-
is_collection_formatted = self.formatted_collections[collection_name] or false,
978+
has_space_format = self.has_space_format[collection_name] or false,
979979
default_unflatten_tuple = default_unflatten_tuple,
980980
pcre = args.pcre,
981981
resolveField = extra.resolveField,
@@ -1233,7 +1233,6 @@ function accessor_general.new(opts, funcs)
12331233
assert(type(funcs) == 'table',
12341234
'funcs must be a table, got ' .. type(funcs))
12351235

1236-
--todo assertions for opt.formatted_collections
12371236
local schemas = opts.schemas
12381237
local collections = opts.collections
12391238
local service_fields = opts.service_fields
@@ -1288,7 +1287,7 @@ function accessor_general.new(opts, funcs)
12881287
indexes = indexes,
12891288
models = models,
12901289
default_unflatten_tuple = default_unflatten_tuple,
1291-
formatted_collections = opts.formatted_collections,
1290+
has_space_format = opts.has_space_format or {},
12921291
index_cache = index_cache,
12931292
funcs = funcs,
12941293
settings = {

graphql/accessor_shard.lua

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,19 @@ end
8484
---
8585
--- @tparam string collection_name
8686
--- @tparam cdata/table tuple
87+
--- @tparam table opts
88+
--- * `has_space_format` (boolean, if collection 'collection_name' generated
89+
--- from space:format() or not).
8790
--- @tparam function default unflatten action, call it in the following way:
8891
---
8992
--- ```
9093
--- return default(collection_name, tuple)
9194
--- ```
92-
local function unflatten_tuple(collection_name, tuple, default)
95+
local function unflatten_tuple(collection_name, tuple, opts, default)
96+
if opts.has_space_format then
97+
return tuple:tomap({ names_only = true })
98+
end
99+
93100
return default(collection_name, tuple)
94101
end
95102

graphql/accessor_space.lua

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,17 @@ end
2626
---
2727
--- @tparam string collection_name
2828
--- @tparam cdata/table tuple
29+
--- @tparam table opts
30+
--- * `has_space_format` (boolean, if collection 'collection_name' generated
31+
--- from space:format() or not).
2932
--- @tparam function default unflatten action, call it in the following way:
3033
---
3134
--- ```
3235
--- return default(collection_name, tuple)
3336
--- ```
34-
local function unflatten_tuple(collection_name, tuple, default, is_collection_formatted)
35-
if is_collection_formatted then
36-
return tuple:tomap()
37+
local function unflatten_tuple(collection_name, tuple, opts, default)
38+
if opts.has_space_format then
39+
return tuple:tomap({ names_only = true })
3740
end
3841
return default(collection_name, tuple)
3942
end
@@ -51,8 +54,6 @@ function accessor_space.new(opts, funcs)
5154
'funcs values must be functions, got ' .. type(v))
5255
end
5356

54-
-- todo add some note in comments that funcs.unflatten_tuple must
55-
-- manage our tuple:tomap or unflatten issue
5657
local res_funcs = {
5758
is_collection_exists = funcs.is_collection_exists or
5859
is_collection_exists,

graphql/config_complement.lua

Lines changed: 125 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1+
--- Config complement module provide an ability to complement user-defined config
2+
--- (in a simplified format) to a fully specified format.
3+
---
4+
------ Notes:
5+
---
6+
--- * Currently the module complements only connections (cfg.connections),
7+
-- see @{complement_connections}.
8+
9+
local json = require('json')
110
local utils = require('graphql.utils')
2-
local at = utils.assert_type
11+
local check = utils.check
12+
local get_spaces_formats = require('graphql.simple_config').get_spaces_formats
313

414
local config_complement = {}
515

6-
--- The function determines connection type by fully qualified connection.parts
7-
--- and source collection space format
8-
--- Items in parts must be sorted by destination_field to match field order
9-
--- in connection's index
10-
local function determine_connection_type(connection_parts, index, source_format)
16+
--- The function determines connection type by connection.parts
17+
--- and source collection space format.
18+
local function determine_connection_type(connection_parts, index, source_space_format)
1119
local type
1220

1321
if #connection_parts < #(index.fields) then
@@ -22,142 +30,189 @@ local function determine_connection_type(connection_parts, index, source_format)
2230
end
2331
end
2432

25-
-- todo still not clear how to handle nullables
33+
local is_all_nullable = true
34+
local is_all_not_nullable = true
35+
36+
for _, connection_part in pairs(connection_parts) do
37+
for _,field_format in ipairs(source_space_format) do
38+
if connection_part.source_field == field_format.name then
39+
if field_format.is_nullable == true then
40+
is_all_not_nullable = false
41+
else
42+
is_all_nullable = false
43+
end
44+
end
45+
end
46+
end
47+
48+
if is_all_nullable == is_all_not_nullable then
49+
error('source_fields in connection_parts must be all nullable or ' ..
50+
'not nullable at the same time')
51+
end
52+
53+
if is_all_nullable then
54+
type = type .. '*'
55+
end
56+
2657
return type
2758
end
2859

29-
--- XXX Currently if connections_parts have destination_fields that do not
30-
--- exist in connection's index the assertion is raised. Maybe it is not a
31-
--- desirable behavior. Consider the following case: you have working
32-
--- tarantool_graphql, then you try to change configuration a bit and
33-
--- tarantool_graphql crushes.
3460
local function sort_parts(connection_parts, index_fields)
3561
local sorted_parts = {}
62+
63+
-- check if fields in connection_parts exist in index_fields
3664
for _, part in pairs(connection_parts) do
3765
local is_found = false
3866
for i, index_field in ipairs(index_fields) do
3967
if part.destination_field == index_field then
40-
sorted_parts[i] = part
4168
is_found = true
4269
end
4370
end
4471
assert(is_found, ('part.destination_field %s was not found in ' ..
45-
'connection index'):format(part.destination_field))
72+
'connection index %s'):format(part.destination_field,
73+
json.encode(index_fields)))
4674
end
47-
return sorted_parts;
75+
76+
-- sort parts and check that sorted_parts form index prefix
77+
-- (including index itself)
78+
for i = 1, utils.size(connection_parts) do
79+
local index_field = index_fields[i]
80+
for _, part in pairs(connection_parts) do
81+
if part.destination_field == index_field then
82+
sorted_parts[i] = index_field
83+
break
84+
end
85+
-- no match found
86+
error(('given parts %s does not form an index or an index ' ..
87+
'prefix %s'):format(json.encode(connection_parts),
88+
json.encode(index_fields)))
89+
end
90+
end
91+
return sorted_parts
4892
end
4993

50-
--- The functions determines fully qualified connection's parts based on
51-
--- connection's index and incompletely qualified connection's part given by user
52-
--- @tparam table parts incompletely qualified connection's part given by user
53-
--- @tparam table index connection index (cfg.indexes[collection][index_name]
94+
--- The functions determines fully defined connection's parts based on
95+
--- connection's index and partially defined connection's part given by user.
96+
--- @tparam table parts partially defined connection's part given by user
97+
--- @tparam table index connection index (cfg.indexes[collection][index_name])
5498
--- order of items in index.fields must be the same as in index format
5599
local function determine_connection_parts(parts, index)
56-
at(parts, 'parts', 'nil', 'number', 'table')
100+
check(parts, 'parts', 'nil', 'number', 'table')
57101
local result_parts = {}
58102

59-
-- full index case
103+
-- User defined no parts of the connection. All connection's index fields
104+
-- are taken as 'parts'
60105
if type(parts) == 'nil' then
61106
for i, v in ipairs(index.fields) do
62107
result_parts[i] = {source_field = v, destination_field = v}
63108
end
64109
end
65110

66-
-- index prefix case
111+
-- User defined a number of fields of index which must form index prefix.
112+
-- First 'number' index fields are taken as 'parts'
67113
if type(parts) == 'number' then
68114
for i = 1, parts do
69115
local v = index.fields[i]
70116
result_parts[i] = {source_field = v, destination_field = v}
71117
end
72118
end
73119

74-
-- fully qualified parts case
120+
-- User defined parts as pairs of {source_field: foo_field,
121+
-- destination_field: boo_field}. These 'parts' may correspond either to full
122+
-- index or index prefix
75123
if type(parts) == 'table' then
76-
local sorted_parts = sort_parts(parts, index.fields)
77-
for i, v in ipairs(sorted_parts) do
78-
result_parts[i] = {source_field = v, destination_field = v}
79-
end
124+
-- sorting parts is necessary to check if user defined part form an
125+
-- index or an index prefix
126+
result_parts = sort_parts(parts, index.fields)
80127
end
81128

82129
return result_parts
83130
end
84131

85-
---
86132
--- The function complements collections' connections, described in simplified
87133
--- format, to connections in a fully specified format. Connection's
88134
--- collection determined on source_collection. Type determined on index type.
89135
--- Notice an example:
90136
---
91-
--- "connections" : [
92-
--- {
93-
--- "name": "order_connection",
94-
--- "source_collection": "user_collection",
95-
--- "destination_collection": "order_collection"
96-
--- "index_name": "user_id_index",
97-
--- "parts" : nil | number | table (destination fields can be omitted)
98-
--- },
99-
--- ...
100-
--- ]
101-
--- will produce following complement in 'user_collection' :
137+
--- "connections" : [
138+
--- {
139+
--- "name": "order_connection",
140+
--- "source_collection": "user_collection",
141+
--- "destination_collection": "order_collection"
142+
--- "index_name": "user_id_index",
143+
--- "parts" : nil | number | table (destination fields can be omitted)
144+
--- in case of 'table' expected format is:
145+
--- "parts": [
146+
--- {"source_field": "user_id", "destination_field": "user_id"},
147+
--- ...
148+
--- ]
149+
--- },
150+
--- ...
151+
--- ]
102152
---
103-
--- "user_collection": {
104-
--- "schema_name": "user",
105-
--- "connections": [
106-
--- {
107-
--- "type": "1:N",
108-
--- "name": "order_connection",
109-
--- "destination_collection": "order_collection",
110-
--- "parts": [
111-
--- { "source_field": "user_id", "destination_field": "user_id" }
112-
--- ],
113-
--- "index_name": "user_id_index"
114-
--- },
153+
--- will produce following complement in 'user_collection' :
115154
---
116-
--- ]
117-
--- }
155+
--- "user_collection": {
156+
--- "schema_name": "user",
157+
--- "connections": [
158+
--- {
159+
--- "type": "1:N",
160+
--- "name": "order_connection",
161+
--- "destination_collection": "order_collection",
162+
--- "parts": [
163+
--- { "source_field": "user_id", "destination_field": "user_id" }
164+
--- ],
165+
--- "index_name": "user_id_index"
166+
--- },
167+
--- ]
168+
--- }
118169
---
119170
--- @tparam table collections cfg.collections
120171
--- @tparam table connections cfg.connections - user-defined collections
121-
--- @tparam table indexes cfg.indexes - {collection_name = collection_indexes}
172+
--- @tparam table indexes cfg.indexes - {[collection_name] = collection_indexes, ...}
122173
local function complement_connections(collections, connections, indexes, schemas)
123174
if connections == nil then
124175
return collections
125176
end
126177

127-
at(collections, 'collections', 'table')
128-
at(connections, 'connections', 'table')
178+
check(collections, 'collections', 'table')
179+
check(connections, 'connections', 'table')
180+
181+
local spaces_formats = get_spaces_formats()
129182

130183
for _, c in pairs(connections) do
131-
at(c.name, 'connection.name', 'string')
132-
at(c.source_collection, 'connection.source_collection', 'string')
133-
at(c.destination_collection, 'connection.destination_collection',
134-
'string')
135-
at(c.index_name, 'connection.index_name', 'string')
136-
at(c.parts, 'connection.parts', 'string', 'table', 'nil')
184+
check(c.name, 'connection.name', 'string')
185+
check(c.source_collection, 'connection.source_collection', 'string')
186+
check(c.destination_collection, 'connection.destination_collection',
187+
'string')
188+
check(c.index_name, 'connection.index_name', 'string')
189+
check(c.parts, 'connection.parts', 'string', 'table', 'nil')
137190

138191
local index = indexes[c.source_collection][c.index_name]
139192
assert(index.unique ~= nil, 'index.unique must not be nil ' ..
140193
'during connections complementing')
141194

142195
local result_c = {}
196+
result_c.source_collection = c.source_collection
197+
result_c.destination_collection = c.destination_collection
143198
result_c.parts = determine_connection_parts(c.parts, index)
144-
result_c.type = determine_connection_type(result_c.parts, index)
199+
200+
local source_space_format = spaces_formats[result_c.source_collection]
201+
202+
result_c.type = determine_connection_type(result_c.parts, index,
203+
source_space_format)
145204
result_c.index_name = c.index_name
146-
result_c.destination_collection = c.destination_collection
147205
result_c.name = c.name
148206

149207
local collection_connections = collections[c.source_collection].
150-
connections
151-
if collection_connections == nil then
152-
collection_connections = {}
153-
end
208+
connections or {}
154209
collection_connections[#collection_connections + 1] = result_c
155210
end
156-
157211
return collections
158212
end
159213

160-
--- The function complements
214+
--- The function complements cfg.collection.connections using given
215+
--- cfg.connections. See @{complement_connections} for details.
161216
function config_complement.complement_cfg(cfg)
162217
cfg.collections = complement_connections(cfg.collections, cfg.connections,
163218
cfg.indexes)

0 commit comments

Comments
 (0)