Skip to content

Commit

Permalink
box: expose box.schema before box.cfg
Browse files Browse the repository at this point in the history
box.schema has a number of constants, e.g. IDs of system spaces,
which may be useful for the user. Let's allow to access box.schema
before box.cfg is called.

It is used in checking names, as we need to know, which snapshot spaces
to scan.

Needed for #8978

NO_DOC=minor change
  • Loading branch information
Serpentian authored and sergepetrenko committed Oct 27, 2023
1 parent 145af72 commit e7ca37b
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 0 deletions.
3 changes: 3 additions & 0 deletions changelogs/unreleased/box-schema-before-cfg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## feature/core

* box.schema can now be accessed before box.cfg().
5 changes: 5 additions & 0 deletions src/box/lua/call.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "box/box.h"
#include "box/lua/call.h"
#include "box/call.h"
#include "box/error.h"
Expand Down Expand Up @@ -946,6 +947,8 @@ static struct func_vtab func_persistent_lua_vtab = {
static int
lbox_module_reload(lua_State *L)
{
if (box_check_configured() != 0)
return luaT_error(L);
const char *name = luaL_checkstring(L, 1);
if (box_module_reload(name) != 0)
return luaT_error(L);
Expand All @@ -955,6 +958,8 @@ lbox_module_reload(lua_State *L)
int
lbox_func_call(struct lua_State *L)
{
if (box_check_configured() != 0)
return luaT_error(L);
if (lua_gettop(L) < 1 || !lua_isstring(L, 1))
return luaL_error(L, "Use func:call(...)");

Expand Down
1 change: 1 addition & 0 deletions src/box/lua/load_cfg.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,7 @@ local box_cfg_guard_whitelist = {
info = true;
iproto = true;
priv = true;
schema = true;
};

-- List of box members that requires full box loading.
Expand Down
4 changes: 4 additions & 0 deletions src/box/lua/schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2744,6 +2744,7 @@ local function wrap_schema_object_mt(name)
end

function box.schema.space.bless(space)
utils.box_check_configured()
local index_mt_name
if space.engine == 'vinyl' then
index_mt_name = 'vinyl_index_mt'
Expand Down Expand Up @@ -2798,6 +2799,7 @@ box.sequence = {}
box.schema.sequence = {}

function box.schema.sequence.bless(seq)
utils.box_check_configured()
setmetatable(seq, {__index = sequence_mt})
end

Expand Down Expand Up @@ -3238,6 +3240,7 @@ func_mt.call = function(func, args)
end

function box.schema.func.bless(func)
utils.box_check_configured()
setmetatable(func, {__index = func_mt})
end

Expand Down Expand Up @@ -3311,6 +3314,7 @@ end
box.schema.user = {}

box.schema.user.password = function(password)
utils.box_check_configured()
return internal.prepare_auth(box.cfg.auth_type, password)
end

Expand Down
2 changes: 2 additions & 0 deletions src/box/lua/upgrade.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,7 @@ end
-- Runs the given function with the permission to execute DDL operations
-- with an old schema. Used by upgrade/downgrade scripts.
local function run_upgrade(func, ...)
utils.box_check_configured()
if builtin.box_schema_upgrade_begin() ~= 0 then
box.error()
end
Expand Down Expand Up @@ -2110,6 +2111,7 @@ local downgrade_versions = {
-- In case of downgrade check for issues is done before making any changes.
-- If any issue is found then downgrade is failed and no any changes are done.
local function downgrade_impl(version_str, dry_run)
utils.box_check_configured()
utils.check_param(version_str, 'version_str', 'string')
local version = mkversion.parse(version_str)
if fun.index(version_str, downgrade_versions) == nil then
Expand Down
7 changes: 7 additions & 0 deletions src/lua/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,11 @@ else
utils.memory_region_is_poisoned = function() return false end
end

--[[ Throw an error, if box is unconfigured. --]]
function utils.box_check_configured()
if type(box.cfg) == 'function' then
box.error(box.error.UNCONFIGURED)
end
end

return utils
72 changes: 72 additions & 0 deletions test/box-luatest/box_schema_before_box_cfg_test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
local t = require('luatest')
local treegen = require('test.treegen')
local justrun = require('test.justrun')

local g = t.group()

g.test_box_schema_before_box_cfg = function()
treegen.init(g)
local dir = treegen.prepare_directory(g, {}, {})
treegen.write_script(dir, 'main.lua', [[
local t = require('luatest')
local schema = box.schema
-- Allowed to call the following functions before box.cfg
t.assert_equals(pcall(schema.downgrade_versions), true)
-- Test, that it's impossible to invoke all other box.schema.*.
local msg = 'Please call box.cfg{} first'
-- t.assert_error_msg_contains(msg, schema.create_space, 'test')
t.assert_error_msg_contains(msg, schema.upgrade)
t.assert_error_msg_contains(msg, schema.downgrade, '3.0.0')
t.assert_error_msg_contains(msg, schema.downgrade_issues, '3.0.0')
t.assert_error_msg_contains(msg, schema.func.bless, {})
t.assert_error_msg_contains(msg, schema.func.call, 'f')
t.assert_error_msg_contains(msg, schema.func.create, 'f')
t.assert_error_msg_contains(msg, schema.func.drop, 'f')
t.assert_error_msg_contains(msg, schema.func.exists, 'f')
t.assert_error_msg_contains(msg, schema.func.reload, 'f')
t.assert_error_msg_contains(msg, schema.index.alter)
t.assert_error_msg_contains(msg, schema.index.create)
t.assert_error_msg_contains(msg, schema.index.drop)
t.assert_error_msg_contains(msg, schema.index.rename, 1, 1, 'n')
t.assert_error_msg_contains(msg, schema.role.create)
t.assert_error_msg_contains(msg, schema.role.drop)
t.assert_error_msg_contains(msg, schema.role.exists)
t.assert_error_msg_contains(msg, schema.role.grant)
t.assert_error_msg_contains(msg, schema.role.info)
t.assert_error_msg_contains(msg, schema.role.revoke)
t.assert_error_msg_contains(msg, schema.sequence.bless, {})
t.assert_error_msg_contains(msg, schema.sequence.alter)
t.assert_error_msg_contains(msg, schema.sequence.create, 'n')
t.assert_error_msg_contains(msg, schema.sequence.drop, 'n')
t.assert_error_msg_contains(msg, schema.space.alter, 's')
t.assert_error_msg_contains(msg, schema.space.bless, {})
t.assert_error_msg_contains(msg, schema.space.create, 's')
t.assert_error_msg_contains(msg, schema.space.drop, 's')
t.assert_error_msg_contains(msg, schema.space.format, 's')
t.assert_error_msg_contains(msg, schema.space.rename, 1, 's')
t.assert_error_msg_contains(msg, schema.user.create)
t.assert_error_msg_contains(msg, schema.user.disable)
t.assert_error_msg_contains(msg, schema.user.drop)
t.assert_error_msg_contains(msg, schema.user.enable)
t.assert_error_msg_contains(msg, schema.user.exists)
t.assert_error_msg_contains(msg, schema.user.grant)
t.assert_error_msg_contains(msg, schema.user.info)
t.assert_error_msg_contains(msg, schema.user.passwd, 's', 's')
t.assert_error_msg_contains(msg, schema.user.password)
t.assert_error_msg_contains(msg, schema.user.revoke)
]])

local opts = {nojson = true, stderr = true}
local res = justrun.tarantool(dir, {}, {'main.lua'}, opts)
t.assert_equals(res.stderr, "")
t.assert_equals(res.exit_code, 0)
end

0 comments on commit e7ca37b

Please sign in to comment.