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

Commit 83cadb0

Browse files
authored
Merge pull request #55 from tarantool/custom-unflattener
Allow to use custom unflattener
2 parents d293f35 + 20b3c1a commit 83cadb0

File tree

6 files changed

+398
-34
lines changed

6 files changed

+398
-34
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ default:
44
.PHONY: lint
55
lint:
66
luacheck graphql/*.lua test/local/*.lua test/testdata/*.lua \
7-
test/common/*test.lua test/common/lua/*.lua \
7+
test/common/*.test.lua test/common/lua/*.lua \
88
--no-redefined --no-unused-args
99

1010
.PHONY: test

graphql/accessor_general.lua

+34-21
Original file line numberDiff line numberDiff line change
@@ -574,13 +574,6 @@ end
574574
--- Nothing returned, but after necessary count of invokes `state.objs` will
575575
--- hold list of resulting objects.
576576
local function process_tuple(state, tuple, opts)
577-
local function maybe_unflatten(model, tuple, obj)
578-
local ok, obj = model.unflatten(tuple)
579-
assert(ok, 'cannot unflat tuple: ' .. tostring(obj))
580-
return obj
581-
end
582-
583-
local model = opts.model
584577
local limit = opts.limit
585578
local filter = opts.filter
586579
local do_filter = opts.do_filter
@@ -594,18 +587,19 @@ local function process_tuple(state, tuple, opts)
594587
'(`fetched_object_cnt_max` in accessor)'):format(
595588
qstats.fetched_object_cnt, fetched_object_cnt_max))
596589

590+
-- convert tuple -> object
591+
local obj = opts.unflatten_tuple(opts.collection_name, tuple,
592+
opts.default_unflatten_tuple)
593+
597594
-- skip all items before pivot (the item pointed by offset)
598-
local obj = nil
599595
if not state.pivot_found and pivot_filter then
600-
obj = maybe_unflatten(model, tuple, obj)
601596
local match = utils.is_subtable(obj, pivot_filter)
602597
if not match then return true end
603598
state.pivot_found = true
604599
return true -- skip pivot item too
605600
end
606601

607-
-- convert tuple -> object, then filter out or continue
608-
obj = maybe_unflatten(model, tuple, obj)
602+
-- filter out non-matching objects
609603
local match = utils.is_subtable(obj, filter)
610604
if do_filter then
611605
if not match then return true end
@@ -698,13 +692,13 @@ local function select_internal(self, collection_name, from, filter, args, extra)
698692
index_name, collection_name))
699693
end
700694

701-
-- lookup compiled schema for unflattening (model)
695+
-- lookup functions for unflattening
702696
local schema_name = collection.schema_name
703697
assert(type(schema_name) == 'string',
704698
'schema_name must be a string, got ' .. type(schema_name))
705-
local model = self.models[schema_name]
706-
assert(model ~= nil,
707-
('cannot find model for collection "%s"'):format(
699+
local default_unflatten_tuple = self.default_unflatten_tuple[schema_name]
700+
assert(default_unflatten_tuple ~= nil,
701+
('cannot find default_unflatten_tuple for collection "%s"'):format(
708702
collection_name))
709703

710704
-- read-write variables for process_tuple
@@ -717,13 +711,15 @@ local function select_internal(self, collection_name, from, filter, args, extra)
717711

718712
-- read only process_tuple options
719713
local select_opts = {
720-
model = model,
721714
limit = args.limit,
722715
filter = filter,
723716
do_filter = not full_match,
724717
pivot_filter = nil, -- filled later if needed
725718
resulting_object_cnt_max = self.settings.resulting_object_cnt_max,
726-
fetched_object_cnt_max = self.settings.fetched_object_cnt_max
719+
fetched_object_cnt_max = self.settings.fetched_object_cnt_max,
720+
collection_name = collection_name,
721+
unflatten_tuple = self.funcs.unflatten_tuple,
722+
default_unflatten_tuple = default_unflatten_tuple,
727723
}
728724

729725
if index == nil then
@@ -803,6 +799,9 @@ local function validate_funcs(funcs)
803799
assert(type(funcs.get_primary_index) == 'function',
804800
'funcs.get_primary_index must be a function, got ' ..
805801
type(funcs.get_primary_index))
802+
assert(type(funcs.unflatten_tuple) == 'function',
803+
'funcs.unflatten_tuple must be a function, got ' ..
804+
type(funcs.unflatten_tuple))
806805
end
807806

808807
--- Create a new data accessor.
@@ -818,10 +817,10 @@ end
818817
--- value is 10,000)_
819818
---
820819
--- @tparam table funcs set of functions (`is_collection_exists`, `get_index`,
821-
--- `get_primary_index`) allows this abstract data accessor behaves in the
822-
--- certain way (say, like space data accessor or shard data accessor);
823-
--- consider the `accessor_space` and the `accessor_shard` modules documentation
824-
--- for this functions description
820+
--- `get_primary_index`, `unflatten_tuple`) allows this abstract data accessor
821+
--- behaves in the certain way (say, like space data accessor or shard data
822+
--- accessor); consider the `accessor_space` and the `accessor_shard` modules
823+
--- documentation for this functions description
825824
---
826825
--- For examples of `opts.schemas` and `opts.collections` consider the
827826
--- @{tarantool_graphql.new} function description.
@@ -885,6 +884,19 @@ function accessor_general.new(opts, funcs)
885884
validate_collections(collections, schemas, indexes)
886885
local index_cache = build_index_cache(indexes, collections)
887886

887+
-- create default unflatten functions, that can be called from
888+
-- funcs.unflatten_tuple when an additional pre/postprocessing is not
889+
-- needed
890+
local default_unflatten_tuple = {}
891+
for schema_name, model in pairs(models) do
892+
default_unflatten_tuple[schema_name] =
893+
function(_, tuple)
894+
local ok, obj = model.unflatten(tuple)
895+
assert(ok, 'cannot unflat tuple: ' .. tostring(obj))
896+
return obj
897+
end
898+
end
899+
888900
validate_funcs(funcs)
889901

890902
return setmetatable({
@@ -893,6 +905,7 @@ function accessor_general.new(opts, funcs)
893905
service_fields = service_fields,
894906
indexes = indexes,
895907
models = models,
908+
default_unflatten_tuple = default_unflatten_tuple,
896909
index_cache = index_cache,
897910
funcs = funcs,
898911
settings = {

graphql/accessor_shard.lua

+33-6
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,41 @@ local function get_primary_index(collection_name)
8080
return get_index(collection_name, 0)
8181
end
8282

83+
--- Convert a tuple to an object.
84+
---
85+
--- @tparam string collection_name
86+
--- @tparam cdata/table tuple
87+
--- @tparam function default unflatten action, call it in the following way:
88+
---
89+
--- ```
90+
--- return default(collection_name, tuple)
91+
--- ```
92+
local function unflatten_tuple(collection_name, tuple, default)
93+
return default(collection_name, tuple)
94+
end
95+
8396
--- Create a new shard data accessor instance.
84-
function accessor_shard.new(opts)
85-
local funcs = {
86-
is_collection_exists = is_collection_exists,
87-
get_index = get_index,
88-
get_primary_index = get_primary_index,
97+
function accessor_shard.new(opts, funcs)
98+
local funcs = funcs or {}
99+
assert(type(funcs) == 'table',
100+
'funcs must be nil or a table, got ' .. type(funcs))
101+
102+
for k, v in pairs(funcs) do
103+
assert(type(k) == 'string',
104+
'funcs keys must be strings, got ' .. type(k))
105+
assert(type(v) == 'table',
106+
'funcs values must be functions, got ' .. type(v))
107+
end
108+
109+
local res_funcs = {
110+
is_collection_exists = funcs.is_collection_exists or
111+
is_collection_exists,
112+
get_index = funcs.get_index or get_index,
113+
get_primary_index = funcs.get_primary_index or get_primary_index,
114+
unflatten_tuple = funcs.unflatten_tuple or unflatten_tuple,
89115
}
90-
return accessor_general.new(opts, funcs)
116+
117+
return accessor_general.new(opts, res_funcs)
91118
end
92119

93120
return accessor_shard

graphql/accessor_space.lua

+33-6
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,41 @@ local function get_primary_index(collection_name)
2222
return box.space[collection_name].index[0]
2323
end
2424

25+
--- Convert a tuple to an object.
26+
---
27+
--- @tparam string collection_name
28+
--- @tparam cdata/table tuple
29+
--- @tparam function default unflatten action, call it in the following way:
30+
---
31+
--- ```
32+
--- return default(collection_name, tuple)
33+
--- ```
34+
local function unflatten_tuple(collection_name, tuple, default)
35+
return default(collection_name, tuple)
36+
end
37+
2538
--- Create a new space data accessor instance.
26-
function accessor_space.new(opts)
27-
local funcs = {
28-
is_collection_exists = is_collection_exists,
29-
get_index = get_index,
30-
get_primary_index = get_primary_index,
39+
function accessor_space.new(opts, funcs)
40+
local funcs = funcs or {}
41+
assert(type(funcs) == 'table',
42+
'funcs must be nil or a table, got ' .. type(funcs))
43+
44+
for k, v in pairs(funcs) do
45+
assert(type(k) == 'string',
46+
'funcs keys must be strings, got ' .. type(k))
47+
assert(type(v) == 'function',
48+
'funcs values must be functions, got ' .. type(v))
49+
end
50+
51+
local res_funcs = {
52+
is_collection_exists = funcs.is_collection_exists or
53+
is_collection_exists,
54+
get_index = funcs.get_index or get_index,
55+
get_primary_index = funcs.get_primary_index or get_primary_index,
56+
unflatten_tuple = funcs.unflatten_tuple or unflatten_tuple,
3157
}
32-
return accessor_general.new(opts, funcs)
58+
59+
return accessor_general.new(opts, res_funcs)
3360
end
3461

3562
return accessor_space

0 commit comments

Comments
 (0)