diff --git a/changelogs/unreleased/gh-7858-net-box-space-sequence.md b/changelogs/unreleased/gh-7858-net-box-space-sequence.md new file mode 100644 index 0000000000000000000000000000000000000000..87e607766825c64411007bea204ae213887cf291 --- /dev/null +++ b/changelogs/unreleased/gh-7858-net-box-space-sequence.md @@ -0,0 +1,4 @@ +## bugfix/core + +* Added information about the sequence used by a remote space to net.box + connection (gh-7858). diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c index 3eb19d6c3e8cd1b828723d6a026d2a1dc3637501..307057f12ca1bf60ac524a718fe4a4d21f75734b 100644 --- a/src/box/lua/net_box.c +++ b/src/box/lua/net_box.c @@ -2685,8 +2685,8 @@ netbox_transport_fetch_schema(struct netbox_transport *transport, transport->state = NETBOX_FETCH_SCHEMA; netbox_transport_on_state_change(transport, L); uint32_t peer_version_id = transport->greeting.version_id; - /* _vcollation view was added in 2.2.0-389-g3e3ef182f */ bool peer_has_vcollation = peer_version_id >= version_id(2, 2, 1); + bool peer_has_vspace_sequence = peer_version_id >= version_id(2, 10, 5); restart: lua_newtable(L); int schema_table_idx = lua_gettop(L); @@ -2700,9 +2700,15 @@ netbox_transport_fetch_schema(struct netbox_transport *transport, if (peer_has_vcollation) netbox_encode_select_all(L, &transport->send_buf, vcollation_sync, BOX_VCOLLATION_ID); + uint64_t vspace_sequence_sync = transport->next_sync++; + if (peer_has_vspace_sequence) + netbox_encode_select_all(L, &transport->send_buf, + vspace_sequence_sync, + BOX_VSPACE_SEQUENCE_ID); bool got_vspace = false; bool got_vindex = false; bool got_vcollation = false; + bool got_vspace_sequence = false; schema_version = 0; do { struct xrow_header hdr; @@ -2710,20 +2716,22 @@ netbox_transport_fetch_schema(struct netbox_transport *transport, luaT_error(L); if (hdr.sync != vspace_sync && hdr.sync != vindex_sync && - hdr.sync != vcollation_sync) { + hdr.sync != vcollation_sync && + hdr.sync != vspace_sequence_sync) { netbox_transport_dispatch_response(transport, L, &hdr); continue; } if (iproto_type_is_error(hdr.type)) { uint32_t errcode = hdr.type & (IPROTO_TYPE_ERROR - 1); - if (errcode == ER_NO_SUCH_SPACE && - hdr.sync == vcollation_sync) { - /* - * No _vcollation space - * (server has old schema version). - */ - peer_has_vcollation = false; - continue; + if (errcode == ER_NO_SUCH_SPACE) { + /* Server may have old dd version. */ + if (hdr.sync == vcollation_sync) { + peer_has_vcollation = false; + continue; + } else if (hdr.sync == vspace_sequence_sync) { + peer_has_vspace_sequence = false; + continue; + } } xrow_decode_error(&hdr); luaT_error(L); @@ -2750,6 +2758,9 @@ netbox_transport_fetch_schema(struct netbox_transport *transport, } else if (hdr.sync == vcollation_sync) { key = BOX_VCOLLATION_ID; got_vcollation = true; + } else if (hdr.sync == vspace_sequence_sync) { + key = BOX_VSPACE_SEQUENCE_ID; + got_vspace_sequence = true; } else { unreachable(); } @@ -2757,7 +2768,8 @@ netbox_transport_fetch_schema(struct netbox_transport *transport, tuple_format_runtime); lua_rawseti(L, schema_table_idx, key); } while (!(got_vspace && got_vindex && - (got_vcollation || !peer_has_vcollation))); + (got_vcollation || !peer_has_vcollation) && + (got_vspace_sequence || !peer_has_vspace_sequence))); /* Invoke the 'did_fetch_schema' callback. */ lua_rawgeti(L, LUA_REGISTRYINDEX, transport->opts.callback_ref); lua_pushliteral(L, "did_fetch_schema"); @@ -2765,7 +2777,8 @@ netbox_transport_fetch_schema(struct netbox_transport *transport, lua_rawgeti(L, schema_table_idx, BOX_VSPACE_ID); lua_rawgeti(L, schema_table_idx, BOX_VINDEX_ID); lua_rawgeti(L, schema_table_idx, BOX_VCOLLATION_ID); - lua_call(L, 5, 0); + lua_rawgeti(L, schema_table_idx, BOX_VSPACE_SEQUENCE_ID); + lua_call(L, 6, 0); /* Pop the schema table. */ lua_pop(L, 1); return schema_version; diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua index 5f4d4e5b24624e4084ef1710050e8998a7940abf..c74156081adaa8fd698dd0546ee710af803c9b51 100644 --- a/src/box/lua/net_box.lua +++ b/src/box/lua/net_box.lua @@ -936,7 +936,7 @@ function remote_methods:wait_state(state, timeout) end function remote_methods:_install_schema(schema_version, spaces, indices, - collations) + collations, space_sequences) local sl, space_mt, index_mt = {}, self._space_mt, self._index_mt for _, space in pairs(spaces) do local name = space[3] @@ -977,6 +977,13 @@ function remote_methods:_install_schema(schema_version, spaces, indices, sl[name] = s end + local seql = {} + if space_sequences ~= nil then + for _, seq in ipairs(space_sequences) do + seql[seq[1]] = seq + end + end + for _, index in pairs(indices) do local idx = { space = index[1], @@ -1033,6 +1040,17 @@ function remote_methods:_install_schema(schema_version, spaces, indices, idx.unique = not not index[OPTS].unique end + if idx.id == 0 then + local seq = seql[idx.space] + if seq ~= nil then + idx.sequence_id = seq[2] + idx.sequence_fieldno = seq[4] + 1 + if seq[5] ~= '' then + idx.sequence_path = seq[5] + end + end + end + if sl[idx.space] ~= nil then sl[idx.space].index[idx.id] = idx sl[idx.space].index[idx.name] = idx diff --git a/test/box-luatest/gh_7858_net_box_space_sequence_test.lua b/test/box-luatest/gh_7858_net_box_space_sequence_test.lua new file mode 100644 index 0000000000000000000000000000000000000000..3c50555cc84c5e19c194e2cdc6d5374ec73a5386 --- /dev/null +++ b/test/box-luatest/gh_7858_net_box_space_sequence_test.lua @@ -0,0 +1,114 @@ +local server = require('luatest.server') +local t = require('luatest') + +local g = t.group('gh_7858_net_box_space_sequence') + +g.before_all(function(cg) + cg.server = server:new({alias = 'default'}) + cg.server:start() +end) + +g.after_all(function(cg) + cg.server:drop() +end) + +g.after_test('test_net_box_space_sequence', function(cg) + cg.server:exec(function() + if box.space.test1 ~= nil then + box.space.test1:drop() + end + if box.space.test2 ~= nil then + box.space.test2:drop() + end + if box.space.test3 ~= nil then + box.space.test3:drop() + end + if box.sequence.test ~= nil then + box.sequence.test:drop() + end + end) +end) + +g.test_net_box_space_sequence = function(cg) + cg.server:exec(function() + local t = require('luatest') + local net = require('net.box') + box.schema.sequence.create('test') + box.schema.create_space('test1') + box.space.test1:create_index('pk') + box.space.test1:create_index('sk', {parts = {2, 'unsigned'}}) + box.schema.create_space('test2') + box.space.test2:create_index('pk', {sequence = true}) + box.space.test2:create_index('sk', {parts = {2, 'unsigned'}}) + box.schema.create_space('test3') + box.space.test3:create_index('pk', { + parts = {{'[2].foo.bar', 'unsigned'}}, + sequence = box.sequence.test.id, + }) + box.space.test3:create_index('sk', {parts = {1, 'unsigned'}}) + local conn = net.connect(box.cfg.listen) + t.assert_equals(conn.space.test1.index.pk.sequence_id, nil) + t.assert_equals(conn.space.test1.index.pk.sequence_fieldno, nil) + t.assert_equals(conn.space.test1.index.pk.sequence_path, nil) + t.assert_equals(conn.space.test1.index.sk.sequence_id, nil) + t.assert_equals(conn.space.test1.index.sk.sequence_fieldno, nil) + t.assert_equals(conn.space.test1.index.sk.sequence_path, nil) + t.assert_equals(conn.space.test2.index.pk.sequence_id, + box.sequence.test2_seq.id) + t.assert_equals(conn.space.test2.index.pk.sequence_fieldno, 1) + t.assert_equals(conn.space.test2.index.pk.sequence_path, nil) + t.assert_equals(conn.space.test2.index.sk.sequence_id, nil) + t.assert_equals(conn.space.test2.index.sk.sequence_fieldno, nil) + t.assert_equals(conn.space.test2.index.sk.sequence_path, nil) + t.assert_equals(conn.space.test3.index.pk.sequence_id, + box.sequence.test.id) + t.assert_equals(conn.space.test3.index.pk.sequence_fieldno, 2) + t.assert_equals(conn.space.test3.index.pk.sequence_path, '.foo.bar') + t.assert_equals(conn.space.test3.index.sk.sequence_id, nil) + t.assert_equals(conn.space.test3.index.sk.sequence_fieldno, nil) + t.assert_equals(conn.space.test3.index.sk.sequence_path, nil) + conn:close() + end) +end + +local g_old_schema = t.group('gh_7858_net_box_space_sequence.old_schema') + +g_old_schema.before_test('test_net_box_space_sequence', function(cg) + t.tarantool.skip_if_not_debug() + cg.server = server:new({ + alias = 'default', + datadir = 'test/box-luatest/upgrade/2.10.4', + env = {ERRINJ_AUTO_UPGRADE = 'true'}, + }) + cg.server:start() +end) + +g_old_schema.after_test('test_net_box_space_sequence', function(cg) + cg.server:drop() +end) + +g_old_schema.test_net_box_space_sequence = function(cg) + cg.server:exec(function() + local t = require('luatest') + local net = require('net.box') + t.assert_not_equals(box.space.gh_7858, nil) + t.assert_not_equals(box.sequence.gh_7858_seq, nil) + t.assert_equals(box.space.gh_7858.index.pk.sequence_id, + box.sequence.gh_7858_seq.id) + t.assert_equals(box.space.gh_7858.index.pk.sequence_fieldno, 2) + t.assert_equals(box.space.gh_7858.index.pk.sequence_path, '[3]') + local conn = net.connect(box.cfg.listen) + t.assert_equals(conn.error, nil) + t.assert_not_equals(conn.space.gh_7858, nil) + t.assert_equals(conn.space.gh_7858.index.pk.sequence_id, nil) + t.assert_equals(conn.space.gh_7858.index.pk.sequence_fieldno, nil) + t.assert_equals(conn.space.gh_7858.index.pk.sequence_path, nil) + box.schema.upgrade() + t.assert_equals(conn:ping(), true) + t.assert_equals(conn.space.gh_7858.index.pk.sequence_id, + box.sequence.gh_7858_seq.id) + t.assert_equals(conn.space.gh_7858.index.pk.sequence_fieldno, 2) + t.assert_equals(conn.space.gh_7858.index.pk.sequence_path, '[3]') + conn:close() + end) +end diff --git a/test/box-luatest/upgrade/2.10.4/00000000000000000009.snap b/test/box-luatest/upgrade/2.10.4/00000000000000000009.snap deleted file mode 100644 index d21bba921962fc4a1602f651e9af35e1d361bebb..0000000000000000000000000000000000000000 Binary files a/test/box-luatest/upgrade/2.10.4/00000000000000000009.snap and /dev/null differ diff --git a/test/box-luatest/upgrade/2.10.4/00000000000000000014.snap b/test/box-luatest/upgrade/2.10.4/00000000000000000014.snap new file mode 100644 index 0000000000000000000000000000000000000000..9b3148317f2a10a22a9228164b7de0547d4dac38 Binary files /dev/null and b/test/box-luatest/upgrade/2.10.4/00000000000000000014.snap differ diff --git a/test/box-luatest/upgrade/2.10.4/gen.lua b/test/box-luatest/upgrade/2.10.4/gen.lua new file mode 100644 index 0000000000000000000000000000000000000000..409fb03743d346fb239a866f6bb4d6a9e602db51 --- /dev/null +++ b/test/box-luatest/upgrade/2.10.4/gen.lua @@ -0,0 +1,15 @@ +box.cfg{} + +box.schema.user.create('eve') +box.schema.user.create('bob', {password = 'secret'}) +box.schema.role.create('test') + +box.schema.create_space('gh_7858') +box.space.gh_7858:create_index('pk', { + parts = {{'[2][3]', 'unsigned'}}, + sequence = true, +}) + +box.snapshot() + +os.exit(0) diff --git a/test/box/net.box_iproto_transactions_over_streams.result b/test/box/net.box_iproto_transactions_over_streams.result index 31ca1bed254a30d72c43e47527070f3032418237..16086b60d451050eb878068c4107e833796fba7f 100644 --- a/test/box/net.box_iproto_transactions_over_streams.result +++ b/test/box/net.box_iproto_transactions_over_streams.result @@ -219,16 +219,13 @@ IPROTO_AUTH = 7 IPROTO_STREAM_ID = 0x0a --- ... -next_request_id = 10 ---- -... test_run:cmd("setopt delimiter ';'") --- - true ... header = msgpack.encode({ [IPROTO_REQUEST_TYPE] = IPROTO_AUTH, - [IPROTO_SYNC] = next_request_id, + [IPROTO_SYNC] = conn:_next_sync(), [IPROTO_STREAM_ID] = 1, }); --- diff --git a/test/box/net.box_iproto_transactions_over_streams.test.lua b/test/box/net.box_iproto_transactions_over_streams.test.lua index 4013d9c5b20a31282a7c099cd04d68d4b1569d06..c6683574c6114c8522964fbef7a3638e33dc0ab0 100644 --- a/test/box/net.box_iproto_transactions_over_streams.test.lua +++ b/test/box/net.box_iproto_transactions_over_streams.test.lua @@ -120,11 +120,10 @@ IPROTO_REQUEST_TYPE = 0x00 IPROTO_SYNC = 0x01 IPROTO_AUTH = 7 IPROTO_STREAM_ID = 0x0a -next_request_id = 10 test_run:cmd("setopt delimiter ';'") header = msgpack.encode({ [IPROTO_REQUEST_TYPE] = IPROTO_AUTH, - [IPROTO_SYNC] = next_request_id, + [IPROTO_SYNC] = conn:_next_sync(), [IPROTO_STREAM_ID] = 1, }); body = msgpack.encode({nil});