From 3e6393d5adfee5ef3ce8e801aa1e35e3e934db4e Mon Sep 17 00:00:00 2001 From: Ilya Verbin <iverbin@tarantool.org> Date: Tue, 11 Oct 2022 15:50:37 +0300 Subject: [PATCH] box: use dd_version_id instead of _schema.version in get_version By default a user might not have privileges to access the _schema space, that will cause an error during schema_needs_upgrade(), which calls get_version(). Fix this by using C variable dd_version_id, which is updated in the _schema.version replace trigger. There's a special case for upgrade() during bootstrap() - triggers are disabled during bootstrap, that's why dd_version_id is not being updated. Handle this by passing _initial_version=1.7.5 to the upgrade function. Part of #7149 NO_DOC=internal NO_CHANGELOG=internal --- extra/exports | 1 + src/box/lua/upgrade.lua | 18 +++++++-------- src/box/schema.cc | 7 +++++- src/box/schema.h | 5 ++++ ...rbid_ddl_until_box_schema_upgrade_test.lua | 23 +++++++++++++++++++ test/box/stat.result | 16 ++++++------- 6 files changed, 52 insertions(+), 18 deletions(-) create mode 100644 test/box-luatest/gh_7149_forbid_ddl_until_box_schema_upgrade_test.lua diff --git a/extra/exports b/extra/exports index 0b7d2e579d..f30e7bbfe9 100644 --- a/extra/exports +++ b/extra/exports @@ -12,6 +12,7 @@ base64_bufsize base64_decode base64_encode +box_dd_version_id box_decimal_abs box_decimal_add box_decimal_compare diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua index a077e8210f..12078fc218 100644 --- a/src/box/lua/upgrade.lua +++ b/src/box/lua/upgrade.lua @@ -3,6 +3,9 @@ local bit = require('bit') local json = require('json') local fio = require('fio') local xlog = require('xlog') +local ffi = require('ffi') + +ffi.cdef('uint32_t box_dd_version_id(void);') -- Guest user id - the default user local GUEST = 0 @@ -1288,13 +1291,10 @@ local handlers = { -- Schema version of the snapshot. local function get_version() - local version = box.space._schema:get{'version'} - if version == nil then - error('Missing "version" in box.space._schema') - end - local major = version[2] - local minor = version[3] - local patch = version[4] or 0 + local version = ffi.C.box_dd_version_id() + local major = bit.band(bit.rshift(version, 16), 0xff) + local minor = bit.band(bit.rshift(version, 8), 0xff) + local patch = bit.band(version, 0xff) return mkversion(major, minor, patch), string.format("%s.%s.%s", major, minor, patch) @@ -1398,7 +1398,7 @@ local function upgrade(options) options = options or {} setmetatable(options, {__index = {auto = false}}) - local version = get_version() + local version = options._initial_version or get_version() if version < mkversion(1, 6, 8) then log.warn('can upgrade from 1.6.8 only') return @@ -1432,7 +1432,7 @@ local function bootstrap() -- insert initial schema initial_1_7_5() -- upgrade schema to the latest version - upgrade() + upgrade{_initial_version = mkversion(1, 7, 5)} set_system_triggers(true) diff --git a/src/box/schema.cc b/src/box/schema.cc index 79cdaf2103..4ca145397e 100644 --- a/src/box/schema.cc +++ b/src/box/schema.cc @@ -69,13 +69,18 @@ struct rlist on_alter_func = RLIST_HEAD_INITIALIZER(on_alter_func); struct entity_access entity_access; -/** Return current schema version */ uint32_t box_schema_version(void) { return schema_version; } +uint32_t +box_dd_version_id(void) +{ + return dd_version_id; +} + static int on_replace_dd_system_space(struct trigger *trigger, void *event) { diff --git a/src/box/schema.h b/src/box/schema.h index b5c0c13bdb..a3c505c9be 100644 --- a/src/box/schema.h +++ b/src/box/schema.h @@ -49,9 +49,14 @@ extern uint32_t dd_version_id; /** Triggers invoked after schema initialization. */ extern struct rlist on_schema_init; +/** Return current monotonic schema version. */ uint32_t box_schema_version(void); +/** Return current persistent schema version. */ +uint32_t +box_dd_version_id(void); + /** * Try to look up object name by id and type of object. * diff --git a/test/box-luatest/gh_7149_forbid_ddl_until_box_schema_upgrade_test.lua b/test/box-luatest/gh_7149_forbid_ddl_until_box_schema_upgrade_test.lua new file mode 100644 index 0000000000..6956ce6a92 --- /dev/null +++ b/test/box-luatest/gh_7149_forbid_ddl_until_box_schema_upgrade_test.lua @@ -0,0 +1,23 @@ +local t = require('luatest') +local g = t.group('gh-7149') +local server = require('test.luatest_helpers.server') + +g.after_each(function() + g.server:drop() +end) + +g.before_test('test_schema_access', function() + g.server = server:new{alias = 'master'} + g.server:start() +end) + +-- Check that get_version() from upgrade.lua can be executed by any user without +-- getting an error: Read access to space '_schema' is denied for user 'user'. +g.test_schema_access = function() + g.server:exec(function() + box.cfg() + box.schema.user.create('user') + box.session.su('user') + box.schema.upgrade() + end) +end diff --git a/test/box/stat.result b/test/box/stat.result index 1ed2434107..915902c666 100644 --- a/test/box/stat.result +++ b/test/box/stat.result @@ -24,7 +24,7 @@ box.stat.REPLACE.total ... box.stat.SELECT.total --- -- 2 +- 0 ... box.stat.ERROR.total --- @@ -59,7 +59,7 @@ box.stat.REPLACE.total ... box.stat.SELECT.total --- -- 6 +- 4 ... -- check exceptions space:get('Impossible value') @@ -77,14 +77,14 @@ space:get(1) ... box.stat.SELECT.total --- -- 7 +- 5 ... space:get(11) --- ... box.stat.SELECT.total --- -- 8 +- 6 ... space:select(5) --- @@ -92,7 +92,7 @@ space:select(5) ... box.stat.SELECT.total --- -- 9 +- 7 ... space:select(15) --- @@ -100,14 +100,14 @@ space:select(15) ... box.stat.SELECT.total --- -- 10 +- 8 ... for _ in space:pairs() do end --- ... box.stat.SELECT.total --- -- 11 +- 9 ... -- reset box.stat.reset() @@ -157,7 +157,7 @@ box.stat.REPLACE.total ... box.stat.SELECT.total --- -- 2 +- 0 ... box.stat.ERROR.total --- -- GitLab