[PATCH 4/4] schema: explicitly forbid setting sequence for json path key part

Vladimir Davydov vdavydov.dev at gmail.com
Wed May 15 13:33:49 MSK 2019


When a space has a sequence, we substitute NULL in the corresponding
primary index part with the next value generated by the sequence. We do
this by patching raw msgpack, see request_handle_sequence. The problem
is we can't do it easily if the field is nested. For example, consider
field [1].a.b. In Lua it is impossible to create tuple {{a = {b = nil}}}
so we would need to restore the whole path from an empty tuple. This
isn't trivial to do. Let's forbid it for now as nobody has requested
this feature yet.

See #4210

@TarantoolBot document
Title: Document that a sequence can't be used with json path key part

This will result in index create/alter error:

```
box.schema.space.create('test')
box.space.test:create_index('primary', {
    parts = {{'[1][1]', 'unsigned'}},
    sequence = true
})
```

One can set a sequence for a plain part of a json path index though,
i.e. this is okay:

```
box.schema.space.create('test')
box.space.test:create_index('primary', {
    parts = {{'[1][1]', 'unsigned'}, {2, 'unsigned}},
    sequence = true, sequence_part = 2
})
```
---
 src/box/alter.cc           |  8 +++++-
 src/box/lua/schema.lua     |  4 +++
 test/box/sequence.result   | 69 ++++++++++++++++++++++++++++++++++++++++++++++
 test/box/sequence.test.lua | 20 ++++++++++++++
 4 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/src/box/alter.cc b/src/box/alter.cc
index 2d43a9d2..a07a0845 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -131,7 +131,13 @@ index_def_check_sequence(struct index_def *index_def, uint32_t sequence_part,
 		tnt_raise(ClientError, ER_MODIFY_INDEX, index_def->name,
 			  space_name, "sequence part is out of bounds");
 	}
-	enum field_type type = index_def->key_def->parts[sequence_part].type;
+	struct key_part *part = &index_def->key_def->parts[sequence_part];
+	if (part->path != NULL) {
+		tnt_raise(ClientError, ER_MODIFY_INDEX, index_def->name,
+			  space_name, "sequence cannot be used with "
+			  "a json path key");
+	}
+	enum field_type type = part->type;
 	if (type != FIELD_TYPE_UNSIGNED && type != FIELD_TYPE_INTEGER) {
 		tnt_raise(ClientError, ER_MODIFY_INDEX, index_def->name,
 			  space_name, "sequence cannot be used with "
diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index 91900395..8f54f444 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -755,6 +755,10 @@ local function check_sequence_part(parts, sequence_part,
                   "sequence part is out of bounds")
     end
     sequence_part = parts[sequence_part]
+    if sequence_part.path ~= nil then
+        box.error(box.error.MODIFY_INDEX, index_name, space_name,
+                  "sequence cannot be used with a json path key")
+    end
     local sequence_part_type = sequence_part.type or sequence_part[2]
     if sequence_part_type ~= 'integer' and sequence_part_type ~= 'unsigned' then
         box.error(box.error.MODIFY_INDEX, index_name, space_name,
diff --git a/test/box/sequence.result b/test/box/sequence.result
index 4f962347..5d2d8a4f 100644
--- a/test/box/sequence.result
+++ b/test/box/sequence.result
@@ -2033,3 +2033,72 @@ s:insert{'d', box.null, 1001}
 s:drop()
 ---
 ...
+--
+-- gh-4210: sequence cannot be used with json path indexes.
+--
+sq = box.schema.sequence.create('test')
+---
+...
+s = box.schema.space.create('test')
+---
+...
+s:create_index('pk', {parts = {{'[1][1]', 'unsigned'}}, sequence = true}) -- error
+---
+- error: 'Can''t create or modify index ''pk'' in space ''test'': sequence cannot
+    be used with a json path key'
+...
+s:create_index('pk', {parts = {{1, 'unsigned', path = '[1]'}}, sequence = true}) -- error
+---
+- error: 'Can''t create or modify index ''pk'' in space ''test'': sequence cannot
+    be used with a json path key'
+...
+_ = s:create_index('pk', {parts = {{1, 'unsigned'}, {'[2][1]', 'unsigned'}}, sequence = true}) -- ok
+---
+...
+s.index.pk:alter{sequence_part = 2} -- error
+---
+- error: 'Can''t create or modify index ''pk'' in space ''test'': sequence cannot
+    be used with a json path key'
+...
+box.space._space_sequence:update(s.id, {{'=', 4, 1}}) -- error
+---
+- error: 'Can''t create or modify index ''pk'' in space ''test'': sequence cannot
+    be used with a json path key'
+...
+s.index.pk:alter{parts = {{'[1][1]', 'unsigned'}}} -- error
+---
+- error: 'Can''t create or modify index ''pk'' in space ''test'': sequence cannot
+    be used with a json path key'
+...
+s.index.pk:alter{parts = {{1, 'unsigned', path = '[1]'}}} -- error
+---
+- error: 'Can''t create or modify index ''pk'' in space ''test'': sequence cannot
+    be used with a json path key'
+...
+box.space._index:update({s.id, 0}, {{'=', 6, {{field = 1, type = 'unsigned', path = '[1]'}}}}) -- error
+---
+- error: 'Can''t create or modify index ''pk'' in space ''test'': sequence cannot
+    be used with a json path key'
+...
+s.index.pk:alter{sequence = false} -- ok
+---
+...
+s.index.pk:alter{sequence = true, sequence_part = 2} -- error
+---
+- error: 'Can''t create or modify index ''pk'' in space ''test'': sequence cannot
+    be used with a json path key'
+...
+box.space._space_sequence:insert{s.id, sq.id, false, 1} -- error
+---
+- error: 'Can''t create or modify index ''pk'' in space ''test'': sequence cannot
+    be used with a json path key'
+...
+s.index.pk:alter{sequence = true} -- ok
+---
+...
+s:drop()
+---
+...
+sq:drop()
+---
+...
diff --git a/test/box/sequence.test.lua b/test/box/sequence.test.lua
index d419e369..3fa0bef7 100644
--- a/test/box/sequence.test.lua
+++ b/test/box/sequence.test.lua
@@ -685,3 +685,23 @@ s.index.pk.sequence_id == sequence_id
 s:insert{'d', 1000, 1000}
 s:insert{'d', box.null, 1001}
 s:drop()
+
+--
+-- gh-4210: sequence cannot be used with json path indexes.
+--
+sq = box.schema.sequence.create('test')
+s = box.schema.space.create('test')
+s:create_index('pk', {parts = {{'[1][1]', 'unsigned'}}, sequence = true}) -- error
+s:create_index('pk', {parts = {{1, 'unsigned', path = '[1]'}}, sequence = true}) -- error
+_ = s:create_index('pk', {parts = {{1, 'unsigned'}, {'[2][1]', 'unsigned'}}, sequence = true}) -- ok
+s.index.pk:alter{sequence_part = 2} -- error
+box.space._space_sequence:update(s.id, {{'=', 4, 1}}) -- error
+s.index.pk:alter{parts = {{'[1][1]', 'unsigned'}}} -- error
+s.index.pk:alter{parts = {{1, 'unsigned', path = '[1]'}}} -- error
+box.space._index:update({s.id, 0}, {{'=', 6, {{field = 1, type = 'unsigned', path = '[1]'}}}}) -- error
+s.index.pk:alter{sequence = false} -- ok
+s.index.pk:alter{sequence = true, sequence_part = 2} -- error
+box.space._space_sequence:insert{s.id, sq.id, false, 1} -- error
+s.index.pk:alter{sequence = true} -- ok
+s:drop()
+sq:drop()
-- 
2.11.0




More information about the Tarantool-patches mailing list