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

Commit 8e43896

Browse files
committed
Disable mutations for avro-schema-2* by default
Added `enable_mutations` option to forcely enable it.
1 parent 5201812 commit 8e43896

File tree

6 files changed

+126
-34
lines changed

6 files changed

+126
-34
lines changed

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ local result = compiled_query:execute(variables)
126126

127127
### Mutations
128128

129+
Mutations are disabled for avro-schema-2\*, because it can work incorrectly for
130+
schemas with nullable types (ones whose marked with asterisk). Mutations still
131+
can be enabled with the `enable_mutations = true` option, but use it with
132+
caution. Don't enable this option with schemas involve nullable types.
133+
129134
#### Insert
130135

131136
Example with an object passed from a variable:

graphql/accessor_general.lua

+46-24
Original file line numberDiff line numberDiff line change
@@ -1403,29 +1403,23 @@ end
14031403
--- Provided `funcs` argument determines certain functions for retrieving
14041404
--- tuples.
14051405
---
1406-
--- @tparam table opts `schemas`, `collections`, `service_fields`, `indexes` and
1407-
--- `collection_use_tomap` ({[collection_name] = whether objects in collection
1408-
--- collection_name intended to be unflattened using tuple:tomap({names_only = true})
1409-
--- method instead of compiled_avro_schema.unflatten(tuple), ...})
1410-
--- to give the data accessor all needed meta-information re data; the format is
1411-
--- shown below; additional attributes `resulting_object_cnt_max` and
1412-
--- `fetched_object_cnt_max` are optional positive numbers which help to control
1413-
--- query behaviour in case it requires more resources than expected _(default
1414-
--- value is 10,000)_; `timeout_ms` _(default is 1000)_
1415-
---
1416-
--- @tparam table funcs set of functions:
1417-
---
1418-
--- * `is_collection_exists`,
1419-
--- * `get_index`,
1420-
--- * `get_primary_index`,
1421-
--- * `unflatten_tuple`,
1422-
--- * `flatten_object`,
1423-
--- * `insert_tuple`.
1424-
---
1425-
--- They allows this abstract data accessor behaves in the certain way (say,
1426-
--- like space data accessor or shard data accessor); consider the
1427-
--- `accessor_space` and the `accessor_shard` modules documentation for these
1428-
--- functions description.
1406+
--- @tparam table opts set of options:
1407+
---
1408+
--- * `schemas`,
1409+
--- * `collections`,
1410+
--- * `service_fields`,
1411+
--- * `indexes`,
1412+
--- * `collection_use_tomap`: ({[collection_name] = whether objects in
1413+
--- collection `collection_name` intended to be unflattened using
1414+
--- `tuple:tomap({names_only = true}` method instead of
1415+
--- `compiled_avro_schema.unflatten(tuple), ...}`),
1416+
--- * `resulting_object_cnt_max` and `fetched_object_cnt_max` are optional
1417+
--- positive numbers which help to control query behaviour in case it
1418+
--- requires more resources than expected _(default value is 10,000 for
1419+
--- both)_,
1420+
--- * `timeout_ms` _(default is 1000)_,
1421+
--- * `enable_mutations`: boolean flag _(default is `false` for avro-schema-2*
1422+
--- and `true` for avro-schema-3*)_.
14291423
---
14301424
--- For examples of `opts.schemas` and `opts.collections` consider the
14311425
--- @{tarantool_graphql.new} function description.
@@ -1452,6 +1446,20 @@ end
14521446
--- ...
14531447
--- }
14541448
---
1449+
--- @tparam table funcs set of functions:
1450+
---
1451+
--- * `is_collection_exists`,
1452+
--- * `get_index`,
1453+
--- * `get_primary_index`,
1454+
--- * `unflatten_tuple`,
1455+
--- * `flatten_object`,
1456+
--- * `insert_tuple`.
1457+
---
1458+
--- They allows this abstract data accessor behaves in the certain way (say,
1459+
--- like space data accessor or shard data accessor); consider the
1460+
--- `accessor_space` and the `accessor_shard` modules documentation for these
1461+
--- functions description.
1462+
---
14551463
--- @treturn table data accessor instance, a table with the two methods
14561464
--- (`select` and `arguments`) as described in the @{tarantool_graphql.new}
14571465
--- function description.
@@ -1471,6 +1479,14 @@ function accessor_general.new(opts, funcs)
14711479
DEF_FETCHED_OBJECT_CNT_MAX
14721480
-- TODO: move this setting to `tgql.compile` after #59
14731481
local timeout_ms = opts.timeout_ms or DEF_TIMEOUT_MS
1482+
-- Mutations are disabled for avro-schema-2*, because it can work
1483+
-- incorrectly for schemas with nullable types.
1484+
local enable_mutations
1485+
if opts.enable_mutations == nil then
1486+
enable_mutations = avro_helpers.major_avro_schema_version() == 3
1487+
else
1488+
enable_mutations = opts.enable_mutations
1489+
end
14741490

14751491
assert(type(schemas) == 'table',
14761492
'schemas must be a table, got ' .. type(schemas))
@@ -1492,6 +1508,7 @@ function accessor_general.new(opts, funcs)
14921508
assert(timeout_ms <= TIMEOUT_INFINITY,
14931509
('timeouts more then graphql.TIMEOUT_INFINITY (%s) ' ..
14941510
'do not supported'):format(tostring(TIMEOUT_INFINITY)))
1511+
check(enable_mutations, 'enable_mutations', 'boolean')
14951512

14961513
local models, service_fields_defaults = compile_schemas(schemas,
14971514
service_fields)
@@ -1521,7 +1538,8 @@ function accessor_general.new(opts, funcs)
15211538
settings = {
15221539
resulting_object_cnt_max = resulting_object_cnt_max,
15231540
fetched_object_cnt_max = fetched_object_cnt_max,
1524-
timeout_ms = timeout_ms
1541+
timeout_ms = timeout_ms,
1542+
enable_mutations = enable_mutations,
15251543
}
15261544
}, {
15271545
__index = {
@@ -1567,6 +1585,10 @@ function accessor_general.new(opts, funcs)
15671585
}
15681586
end,
15691587
extra_args = function(self, collection_name)
1588+
if not self.settings.enable_mutations then
1589+
return {}, {}
1590+
end
1591+
15701592
local collection = self.collections[collection_name]
15711593
local schema_name = collection.schema_name
15721594

graphql/avro_helpers.lua

+10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
--- The module us collection of helpers to simplify avro-schema related tasks.
22

33
local json = require('json')
4+
local avro_schema = require('avro_schema')
45

56
local avro_helpers = {}
67

@@ -71,4 +72,13 @@ function avro_helpers.make_avro_type_nullable(avro, opts)
7172
error("avro should be a string or a table, got " .. value_type)
7273
end
7374

75+
--- XXX
76+
function avro_helpers.major_avro_schema_version()
77+
local ok, handle = avro_schema.create('boolean')
78+
assert(ok, tostring(handle))
79+
local ok, model = avro_schema.compile(handle)
80+
assert(ok, tostring(model))
81+
return model.get_types == nil and 2 or 3
82+
end
83+
7484
return avro_helpers

graphql/tarantool_graphql.lua

+2
Original file line numberDiff line numberDiff line change
@@ -1624,6 +1624,7 @@ local function create_default_accessor(cfg)
16241624
resulting_object_cnt_max = cfg.resulting_object_cnt_max,
16251625
fetched_object_cnt_max = cfg.fetched_object_cnt_max,
16261626
timeout_ms = cfg.timeout_ms,
1627+
enable_mutations = cfg.enable_mutations,
16271628
}, cfg.accessor_funcs)
16281629
end
16291630

@@ -1637,6 +1638,7 @@ local function create_default_accessor(cfg)
16371638
resulting_object_cnt_max = cfg.resulting_object_cnt_max,
16381639
fetched_object_cnt_max = cfg.fetched_object_cnt_max,
16391640
timeout_ms = cfg.timeout_ms,
1641+
enable_mutations = cfg.enable_mutations,
16401642
}, cfg.accessor_funcs);
16411643
end
16421644
end

test/common/mutation.test.lua

+49-3
Original file line numberDiff line numberDiff line change
@@ -672,8 +672,54 @@ local function run_queries(gql_wrapper, virtbox, meta)
672672
assert(test:check(), 'check plan')
673673
end
674674

675-
test_utils.run_testdata(testdata, {
676-
run_queries = run_queries,
677-
})
675+
-- Mutations are disabled for avro-schema-2* by default, but can be enabled by
676+
-- the option.
677+
local function run_queries_avro_schema_2(test, enable_mutations, gql_wrapper,
678+
virtbox, meta)
679+
local mutation_insert = [[
680+
mutation insert_user($user: user_collection_insert) {
681+
user_collection(insert: $user) {
682+
user_id
683+
first_name
684+
last_name
685+
}
686+
}
687+
]]
688+
local ok, err = pcall(gql_wrapper.compile, gql_wrapper, mutation_insert)
689+
690+
if enable_mutations then
691+
test:ok(ok, 'mutations are enabled with the enable_mutations flag')
692+
else
693+
local err_exp = 'Variable specifies unknown type ' ..
694+
'"user_collection_insert"'
695+
test:is_deeply({ok, test_utils.strip_error(err)}, {false, err_exp},
696+
'mutations are forbidden for avro-schema-2*')
697+
end
698+
end
699+
700+
if test_utils.major_avro_schema_version() == 3 then
701+
test_utils.run_testdata(testdata, {
702+
run_queries = run_queries,
703+
})
704+
else
705+
local test = tap.test('mutation')
706+
test:plan(2)
707+
local function workload(_, shard)
708+
local virtbox = shard or box.space
709+
local meta = testdata.meta or testdata.get_test_metadata()
710+
testdata.fill_test_data(virtbox, meta)
711+
-- test mutations are disabled on avro-schema-2* by default
712+
local gql_wrapper = test_utils.graphql_from_testdata(testdata, shard)
713+
run_queries_avro_schema_2(test, false, gql_wrapper, virtbox, meta)
714+
-- test mutations can be enabled on avro-schema-2* by the option
715+
local gql_wrapper = test_utils.graphql_from_testdata(testdata, shard,
716+
{enable_mutations = true})
717+
run_queries_avro_schema_2(test, true, gql_wrapper, virtbox, meta)
718+
end
719+
test_utils.run_testdata(testdata, {
720+
workload = workload,
721+
})
722+
assert(test:check(), 'check plan')
723+
end
678724

679725
os.exit()

test/utils.lua

+14-7
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ end
121121
function utils.run_testdata(testdata, opts)
122122
local opts = opts or {}
123123
local run_queries = opts.run_queries or testdata.run_queries
124+
-- custom workload for, say, test different options on several graphql
125+
-- instances
126+
local workload = opts.workload or nil
124127

125128
-- allow to run under tarantool on 'space' configuration w/o test-run
126129
local conf_name = test_run and test_run:get_cfg('conf') or 'space'
@@ -130,13 +133,17 @@ function utils.run_testdata(testdata, opts)
130133
init_function = testdata.init_spaces,
131134
init_function_params = {utils.major_avro_schema_version()},
132135
cleanup_function = testdata.drop_spaces,
133-
workload = function(_, shard)
134-
local virtbox = shard or box.space
135-
local meta = testdata.meta or testdata.get_test_metadata()
136-
testdata.fill_test_data(virtbox, meta)
137-
local gql_wrapper = utils.graphql_from_testdata(testdata, shard,
138-
opts.graphql_opts)
139-
run_queries(gql_wrapper, virtbox, meta)
136+
workload = function(conf_name, shard)
137+
if workload then
138+
workload(conf_name, shard)
139+
else
140+
local virtbox = shard or box.space
141+
local meta = testdata.meta or testdata.get_test_metadata()
142+
testdata.fill_test_data(virtbox, meta)
143+
local gql_wrapper = utils.graphql_from_testdata(testdata, shard,
144+
opts.graphql_opts)
145+
run_queries(gql_wrapper, virtbox, meta)
146+
end
140147
models_cache = nil -- clear models cache
141148
end,
142149
servers = {'shard1', 'shard2', 'shard3', 'shard4'},

0 commit comments

Comments
 (0)