[PATCH v2 1/2] schema: move space_mt and index_mt definition out of space bless

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Thu Mar 29 17:31:44 MSK 2018


From: aleclarson <alec.stanford.larson at gmail.com>

Space_mt and index_mt are created individually for each space
inside a giant space.bless function. It makes impossible to
implement #3204: exposing space and index metatables to a user,
because for this they must be global and shared between all
spaces and indexes.

Lets move their definition out of space.bless function, and do
their duplicate inside.

Needed #3204
---
 src/box/lua/schema.lua          | 608 +++++++++++++++++++---------------------
 test/box-tap/schema_mt.test.lua |  79 ++++++
 2 files changed, 373 insertions(+), 314 deletions(-)
 create mode 100755 test/box-tap/schema_mt.test.lua

diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index 5a0f71559..ff89c8e58 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -1074,221 +1074,321 @@ end
 
 internal.check_iterator_type = check_iterator_type -- export for net.box
 
-function box.schema.space.bless(space)
-    local index_mt = {}
-    -- __len and __index
-    index_mt.len = function(index)
-        check_index_arg(index, 'len')
-        local ret = builtin.box_index_len(index.space_id, index.id)
-        if ret == -1 then
-            box.error()
-        end
-        return tonumber(ret)
-    end
-    -- index.bsize
-    index_mt.bsize = function(index)
-        check_index_arg(index, 'bsize')
-        local ret = builtin.box_index_bsize(index.space_id, index.id)
-        if ret == -1 then
-            box.error()
-        end
-        return tonumber(ret)
-    end
-    index_mt.__len = index_mt.len -- Lua 5.2 compatibility
-    index_mt.__newindex = function(table, index)
-        return error('Attempt to modify a read-only table') end
-    index_mt.__index = index_mt
-    -- min and max
-    index_mt.min_ffi = function(index, key)
-        check_index_arg(index, 'min')
-        local pkey, pkey_end = tuple_encode(key)
-        if builtin.box_index_min(index.space_id, index.id,
-                                 pkey, pkey_end, ptuple) ~= 0 then
-            box.error() -- error
-        elseif ptuple[0] ~= nil then
-            return tuple_bless(ptuple[0])
-        else
-            return
-        end
+local space_mt = {}
+space_mt.__index = space_mt
+box.schema.space_mt = space_mt
+
+function space_mt:len()
+    check_space_arg(self, 'len')
+    local pk = self.index[0]
+    if pk == nil then
+        return 0 -- empty space without indexes, return 0
     end
-    index_mt.min_luac = function(index, key)
-        check_index_arg(index, 'min')
-        key = keify(key)
-        return internal.min(index.space_id, index.id, key);
+    return self.index[0]:len()
+end
+function space_mt:count(key, opts)
+    check_space_arg(self, 'count')
+    local pk = self.index[0]
+    if pk == nil then
+        return 0 -- empty space without indexes, return 0
     end
-    index_mt.max_ffi = function(index, key)
-        check_index_arg(index, 'max')
-        local pkey, pkey_end = tuple_encode(key)
-        if builtin.box_index_max(index.space_id, index.id,
-                                 pkey, pkey_end, ptuple) ~= 0 then
-            box.error() -- error
-        elseif ptuple[0] ~= nil then
-            return tuple_bless(ptuple[0])
-        else
-            return
-        end
+    return pk:count(key, opts)
+end
+function space_mt:bsize()
+    check_space_arg(self, 'bsize')
+    local s = builtin.space_by_id(self.id)
+    if s == nil then
+        box.error(box.error.NO_SUCH_SPACE, self.name)
     end
-    index_mt.max_luac = function(index, key)
-        check_index_arg(index, 'max')
-        key = keify(key)
-        return internal.max(index.space_id, index.id, key);
+    return builtin.space_bsize(s)
+end
+function space_mt:get(key)
+    check_space_arg(self, 'get')
+    return check_primary_index(self):get(key)
+end
+function space_mt:select(key, opts)
+    check_space_arg(self, 'select')
+    return check_primary_index(self):select(key, opts)
+end
+function space_mt:insert(tuple)
+    check_space_arg(self, 'insert')
+    return internal.insert(self.id, tuple)
+end
+function space_mt:replace(tuple)
+    check_space_arg(self, 'replace')
+    return internal.replace(self.id, tuple)
+end
+space_mt.put = space_mt.replace -- put is an alias for replace
+function space_mt:update(key, ops)
+    check_space_arg(self, 'update')
+    return check_primary_index(self):update(key, ops)
+end
+function space_mt:upsert(tuple_key, ops, deprecated)
+    check_space_arg(self, 'upsert')
+    if deprecated ~= nil then
+        local msg = "Error: extra argument in upsert call: "
+        msg = msg .. tostring(deprecated)
+        msg = msg .. ". Usage :upsert(tuple, operations)"
+        box.error(box.error.PROC_LUA, msg)
     end
-    index_mt.random_ffi = function(index, rnd)
-        check_index_arg(index, 'random')
-        rnd = rnd or math.random()
-        if builtin.box_index_random(index.space_id, index.id, rnd,
-                                    ptuple) ~= 0 then
-            box.error() -- error
-        elseif ptuple[0] ~= nil then
-            return tuple_bless(ptuple[0])
-        else
-            return
-        end
+    return internal.upsert(self.id, tuple_key, ops)
+end
+function space_mt:delete(key)
+    check_space_arg(self, 'delete')
+    return check_primary_index(self):delete(key)
+end
+-- Assumes that spaceno has a TREE (NUM) primary key
+-- inserts a tuple after getting the next value of the
+-- primary key and returns it back to the user
+function space_mt:auto_increment(tuple)
+    check_space_arg(self, 'auto_increment')
+    local max_tuple = check_primary_index(self):max()
+    local max = 0
+    if max_tuple ~= nil then
+        max = max_tuple[1]
+    end
+    table.insert(tuple, 1, max + 1)
+    return self:insert(tuple)
+end
+function space_mt:pairs(key, opts)
+    check_space_arg(self, 'pairs')
+    local pk = self.index[0]
+    if pk == nil then
+        -- empty space without indexes, return empty iterator
+        return fun.iter({})
+    end
+    return pk:pairs(key, opts)
+end
+space_mt.__pairs = space_mt.pairs -- Lua 5.2 compatibility
+space_mt.__ipairs = space_mt.pairs -- Lua 5.2 compatibility
+function space_mt:truncate()
+    check_space_arg(self, 'truncate')
+    return internal.truncate(self.id)
+end
+function space_mt:format(format)
+    check_space_arg(self, 'format')
+    return box.schema.space.format(self.id, format)
+end
+function space_mt:drop()
+    check_space_arg(self, 'drop')
+    check_space_exists(self)
+    return box.schema.space.drop(self.id, self.name)
+end
+function space_mt:rename(name)
+    check_space_arg(self, 'rename')
+    check_space_exists(self)
+    return box.schema.space.rename(self.id, name)
+end
+function space_mt:create_index(name, options)
+    check_space_arg(self, 'create_index')
+    check_space_exists(self)
+    return box.schema.index.create(self.id, name, options)
+end
+function space_mt:run_triggers(yesno)
+    check_space_arg(self, 'run_triggers')
+    local s = builtin.space_by_id(self.id)
+    if s == nil then
+        box.error(box.error.NO_SUCH_SPACE, self.name)
     end
-    index_mt.random_luac = function(index, rnd)
-        check_index_arg(index, 'random')
-        rnd = rnd or math.random()
-        return internal.random(index.space_id, index.id, rnd);
-    end
-    -- iteration
-    index_mt.pairs_ffi = function(index, key, opts)
-        check_index_arg(index, 'pairs')
-        local pkey, pkey_end = tuple_encode(key)
-        local itype = check_iterator_type(opts, pkey + 1 >= pkey_end);
-
-        local keybuf = ffi.string(pkey, pkey_end - pkey)
-        local pkeybuf = ffi.cast('const char *', keybuf)
-        local cdata = builtin.box_index_iterator(index.space_id, index.id,
-            itype, pkeybuf, pkeybuf + #keybuf);
-        if cdata == nil then
-            box.error()
-        end
-        return fun.wrap(iterator_gen, keybuf,
-            ffi.gc(cdata, builtin.box_iterator_free))
-    end
-    index_mt.pairs_luac = function(index, key, opts)
-        check_index_arg(index, 'pairs')
-        key = keify(key)
-        local itype = check_iterator_type(opts, #key == 0);
-        local keymp = msgpack.encode(key)
-        local keybuf = ffi.string(keymp, #keymp)
-        local cdata = internal.iterator(index.space_id, index.id, itype, keymp);
-        return fun.wrap(iterator_gen_luac, keybuf,
-            ffi.gc(cdata, builtin.box_iterator_free))
-    end
-
-    -- index subtree size
-    index_mt.count_ffi = function(index, key, opts)
-        check_index_arg(index, 'count')
-        local pkey, pkey_end = tuple_encode(key)
-        local itype = check_iterator_type(opts, pkey + 1 >= pkey_end);
-        local count = builtin.box_index_count(index.space_id, index.id,
-            itype, pkey, pkey_end);
-        if count == -1 then
-            box.error()
-        end
-        return tonumber(count)
-    end
-    index_mt.count_luac = function(index, key, opts)
-        check_index_arg(index, 'count')
-        key = keify(key)
-        local itype = check_iterator_type(opts, #key == 0);
-        return internal.count(index.space_id, index.id, itype, key);
-    end
-
-    index_mt.get_ffi = function(index, key)
-        check_index_arg(index, 'get')
-        local key, key_end = tuple_encode(key)
-        if builtin.box_index_get(index.space_id, index.id,
-                                 key, key_end, ptuple) ~= 0 then
-            return box.error() -- error
-        elseif ptuple[0] ~= nil then
-            return tuple_bless(ptuple[0])
-        else
-            return
-        end
+    builtin.space_run_triggers(s, yesno)
+end
+
+local index_mt = {}
+index_mt.__index = index_mt
+box.schema.index_mt = index_mt
+
+function index_mt:len()
+    check_index_arg(self, 'len')
+    local ret = builtin.box_index_len(self.space_id, self.id)
+    if ret == -1 then
+        box.error()
     end
-    index_mt.get_luac = function(index, key)
-        check_index_arg(index, 'get')
-        key = keify(key)
-        return internal.get(index.space_id, index.id, key)
+    return tonumber(ret)
+end
+function index_mt:bsize()
+    check_index_arg(self, 'bsize')
+    local ret = builtin.box_index_bsize(self.space_id, self.id)
+    if ret == -1 then
+        box.error()
     end
-
-    local function check_select_opts(opts, key_is_nil)
-        local offset = 0
-        local limit = 4294967295
-        local iterator = check_iterator_type(opts, key_is_nil)
-        if opts ~= nil then
-            if opts.offset ~= nil then
-                offset = opts.offset
-            end
-            if opts.limit ~= nil then
-                limit = opts.limit
-            end
-        end
-        return iterator, offset, limit
+    return tonumber(ret)
+end
+index_mt.__len = index_mt.len -- Lua 5.2 compatibility
+index_mt.__index = index_mt
+function index_mt:min_ffi(key)
+    check_index_arg(self, 'min')
+    local pkey, pkey_end = tuple_encode(key)
+    if builtin.box_index_min(self.space_id, self.id,
+                             pkey, pkey_end, ptuple) ~= 0 then
+        box.error()
+    elseif ptuple[0] ~= nil then
+        return tuple_bless(ptuple[0])
     end
+end
+function index_mt:min_luac(key)
+    check_index_arg(self, 'min')
+    key = keify(key)
+    return internal.min(self.space_id, self.id, key)
+end
+function index_mt:max_ffi(key)
+    check_index_arg(self, 'max')
+    local pkey, pkey_end = tuple_encode(key)
+    if builtin.box_index_max(self.space_id, self.id,
+                             pkey, pkey_end, ptuple) ~= 0 then
+        box.error()
+    elseif ptuple[0] ~= nil then
+        return tuple_bless(ptuple[0])
+    end
+end
+function index_mt:max_luac(key)
+    check_index_arg(self, 'max')
+    key = keify(key)
+    return internal.max(self.space_id, self.id, key)
+end
+function index_mt:random_ffi(rnd)
+    check_index_arg(self, 'random')
+    rnd = rnd or math.random()
+    if builtin.box_index_random(self.space_id, self.id, rnd, ptuple) ~= 0 then
+        box.error()
+    elseif ptuple[0] ~= nil then
+        return tuple_bless(ptuple[0])
+    end
+end
+function index_mt:random_luac(rnd)
+    check_index_arg(self, 'random')
+    rnd = rnd or math.random()
+    return internal.random(self.space_id, self.id, rnd)
+end
+function index_mt:pairs_ffi(key, opts)
+    check_index_arg(self, 'pairs')
+    local pkey, pkey_end = tuple_encode(key)
+    local itype = check_iterator_type(opts, pkey + 1 >= pkey_end)
 
-    index_mt.select_ffi = function(index, key, opts)
-        check_index_arg(index, 'select')
-        local key, key_end = tuple_encode(key)
-        local iterator, offset, limit = check_select_opts(opts, key + 1 >= key_end)
-
-        local port = ffi.cast('struct port *', port_tuple)
+    local keybuf = ffi.string(pkey, pkey_end - pkey)
+    local pkeybuf = ffi.cast('const char *', keybuf)
+    local cdata = builtin.box_index_iterator(self.space_id, self.id, itype,
+                                             pkeybuf, pkeybuf + #keybuf)
+    if cdata == nil then
+        box.error()
+    end
+    return fun.wrap(iterator_gen, keybuf,
+                    ffi.gc(cdata, builtin.box_iterator_free))
+end
+function index_mt:pairs_luac(key, opts)
+    check_index_arg(self, 'pairs')
+    key = keify(key)
+    local itype = check_iterator_type(opts, #key == 0)
+    local keymp = msgpack.encode(key)
+    local keybuf = ffi.string(keymp, #keymp)
+    local cdata = internal.iterator(self.space_id, self.id, itype, keymp)
+    return fun.wrap(iterator_gen_luac, keybuf,
+                    ffi.gc(cdata, builtin.box_iterator_free))
+end
+function index_mt:count_ffi(key, opts)
+    check_index_arg(self, 'count')
+    local pkey, pkey_end = tuple_encode(key)
+    local itype = check_iterator_type(opts, pkey + 1 >= pkey_end)
+    local count = builtin.box_index_count(self.space_id, self.id, itype, pkey,
+                                          pkey_end)
+    if count == -1 then
+        box.error()
+    end
+    return tonumber(count)
+end
+function index_mt:count_luac(key, opts)
+    check_index_arg(self, 'count')
+    key = keify(key)
+    local itype = check_iterator_type(opts, #key == 0)
+    return internal.count(self.space_id, self.id, itype, key)
+end
+function index_mt:get_ffi(key)
+    check_index_arg(self, 'get')
+    local key, key_end = tuple_encode(key)
+    if builtin.box_index_get(self.space_id, self.id, key, key_end,
+                             ptuple) ~= 0 then
+        return box.error()
+    elseif ptuple[0] ~= nil then
+        return tuple_bless(ptuple[0])
+    end
+end
+function index_mt:get_luac(key)
+    check_index_arg(self, 'get')
+    key = keify(key)
+    return internal.get(self.space_id, self.id, key)
+end
 
-        if builtin.box_select(index.space_id, index.id,
-            iterator, offset, limit, key, key_end, port) ~= 0 then
-            return box.error()
+local function check_select_opts(opts, key_is_nil)
+    local offset = 0
+    local limit = 4294967295
+    local iterator = check_iterator_type(opts, key_is_nil)
+    if opts ~= nil then
+        if opts.offset ~= nil then
+            offset = opts.offset
         end
-
-        local ret = {}
-        local entry = port_tuple.first
-        for i=1,tonumber(port_tuple.size),1 do
-            ret[i] = tuple_bless(entry.tuple)
-            entry = entry.next
+        if opts.limit ~= nil then
+            limit = opts.limit
         end
-        builtin.port_destroy(port);
-        return ret
     end
+    return iterator, offset, limit
+end
 
-    index_mt.select_luac = function(index, key, opts)
-        check_index_arg(index, 'select')
-        local key = keify(key)
-        local iterator, offset, limit = check_select_opts(opts, #key == 0)
-        return internal.select(index.space_id, index.id, iterator,
-            offset, limit, key)
-    end
+function index_mt:select_ffi(key, opts)
+    check_index_arg(self, 'select')
+    local key, key_end = tuple_encode(key)
+    local iterator, offset, limit = check_select_opts(opts, key + 1 >= key_end)
 
-    index_mt.update = function(index, key, ops)
-        check_index_arg(index, 'update')
-        return internal.update(index.space_id, index.id, keify(key), ops);
-    end
-    index_mt.delete = function(index, key)
-        check_index_arg(index, 'delete')
-        return internal.delete(index.space_id, index.id, keify(key));
-    end
+    local port = ffi.cast('struct port *', port_tuple)
 
-    index_mt.info = function(index)
-        return internal.info(index.space_id, index.id);
+    if builtin.box_select(self.space_id, self.id, iterator, offset, limit, key,
+                          key_end, port) ~= 0 then
+        return box.error()
     end
 
-    index_mt.drop = function(index)
-        check_index_arg(index, 'drop')
-        return box.schema.index.drop(index.space_id, index.id)
-    end
-    index_mt.rename = function(index, name)
-        check_index_arg(index, 'rename')
-        return box.schema.index.rename(index.space_id, index.id, name)
+    local ret = {}
+    local entry = port_tuple.first
+    for i=1,tonumber(port_tuple.size),1 do
+        ret[i] = tuple_bless(entry.tuple)
+        entry = entry.next
     end
-    index_mt.alter = function(index, options)
-        check_index_arg(index, 'alter')
-        if index.id == nil or index.space_id == nil then
-            box.error(box.error.PROC_LUA, "Usage: index:alter{opts}")
-        end
-        return box.schema.index.alter(index.space_id, index.id, options)
+    builtin.port_destroy(port)
+    return ret
+end
+function index_mt:select_luac(key, opts)
+    check_index_arg(self, 'select')
+    local key = keify(key)
+    local iterator, offset, limit = check_select_opts(opts, #key == 0)
+    return internal.select(self.space_id, self.id, iterator, offset, limit, key)
+end
+function index_mt:update(key, ops)
+    check_index_arg(self, 'update')
+    return internal.update(self.space_id, self.id, keify(key), ops)
+end
+function index_mt:delete(key)
+    check_index_arg(self, 'delete')
+    return internal.delete(self.space_id, self.id, keify(key))
+end
+function index_mt:info()
+    return internal.info(self.space_id, self.id)
+end
+function index_mt:drop()
+    check_index_arg(self, 'drop')
+    return box.schema.index.drop(self.space_id, self.id)
+end
+function index_mt:rename(name)
+    check_index_arg(self, 'rename')
+    return box.schema.index.rename(self.space_id, self.id, name)
+end
+function index_mt:alter(options)
+    check_index_arg(self, 'alter')
+    if self.id == nil or self.space_id == nil then
+        box.error(box.error.PROC_LUA, "Usage: index:alter{opts}")
     end
+    return box.schema.index.alter(self.space_id, self.id, options)
+end
 
-    -- true if reading operations may yield
+function box.schema.space.bless(space)
+    local space_mt = table.deepcopy(space_mt)
+    local index_mt = table.deepcopy(index_mt)
     local read_yields = space.engine == 'vinyl'
     local read_ops = {'select', 'get', 'min', 'max', 'count', 'random', 'pairs'}
     for _, op in ipairs(read_ops) do
@@ -1302,126 +1402,6 @@ function box.schema.space.bless(space)
     end
     index_mt.__pairs = index_mt.pairs -- Lua 5.2 compatibility
     index_mt.__ipairs = index_mt.pairs -- Lua 5.2 compatibility
-    --
-    local space_mt = {}
-    space_mt.len = function(space)
-        check_space_arg(space, 'len')
-        local pk = space.index[0]
-        if pk == nil then
-            return 0 -- empty space without indexes, return 0
-        end
-        return space.index[0]:len()
-    end
-    space_mt.count = function(space, key, opts)
-        check_space_arg(space, 'count')
-        local pk = space.index[0]
-        if pk == nil then
-            return 0 -- empty space without indexes, return 0
-        end
-        return pk:count(key, opts)
-    end
-    space_mt.bsize = function(space)
-        check_space_arg(space, 'bsize')
-        local s = builtin.space_by_id(space.id)
-        if s == nil then
-            box.error(box.error.NO_SUCH_SPACE, space.name)
-        end
-        return builtin.space_bsize(s)
-    end
-    space_mt.__newindex = index_mt.__newindex
-
-    space_mt.get = function(space, key)
-        check_space_arg(space, 'get')
-        return check_primary_index(space):get(key)
-    end
-    space_mt.select = function(space, key, opts)
-        check_space_arg(space, 'select')
-        return check_primary_index(space):select(key, opts)
-    end
-    space_mt.insert = function(space, tuple)
-        check_space_arg(space, 'insert')
-        return internal.insert(space.id, tuple);
-    end
-    space_mt.replace = function(space, tuple)
-        check_space_arg(space, 'replace')
-        return internal.replace(space.id, tuple);
-    end
-    space_mt.put = space_mt.replace; -- put is an alias for replace
-    space_mt.update = function(space, key, ops)
-        check_space_arg(space, 'update')
-        return check_primary_index(space):update(key, ops)
-    end
-    space_mt.upsert = function(space, tuple_key, ops, deprecated)
-        check_space_arg(space, 'upsert')
-        if deprecated ~= nil then
-            local msg = "Error: extra argument in upsert call: "
-            msg = msg .. tostring(deprecated)
-            msg = msg .. ". Usage :upsert(tuple, operations)"
-            box.error(box.error.PROC_LUA, msg)
-        end
-        return internal.upsert(space.id, tuple_key, ops);
-    end
-    space_mt.delete = function(space, key)
-        check_space_arg(space, 'delete')
-        return check_primary_index(space):delete(key)
-    end
--- Assumes that spaceno has a TREE (NUM) primary key
--- inserts a tuple after getting the next value of the
--- primary key and returns it back to the user
-    space_mt.auto_increment = function(space, tuple)
-        check_space_arg(space, 'auto_increment')
-        local max_tuple = check_primary_index(space):max()
-        local max = 0
-        if max_tuple ~= nil then
-            max = max_tuple[1]
-        end
-        table.insert(tuple, 1, max + 1)
-        return space:insert(tuple)
-    end
-
-    space_mt.pairs = function(space, key, opts)
-        check_space_arg(space, 'pairs')
-        local pk = space.index[0]
-        if pk == nil then
-            -- empty space without indexes, return empty iterator
-            return fun.iter({})
-        end
-        return pk:pairs(key, opts)
-    end
-    space_mt.__pairs = space_mt.pairs -- Lua 5.2 compatibility
-    space_mt.__ipairs = space_mt.pairs -- Lua 5.2 compatibility
-    space_mt.truncate = function(space)
-        check_space_arg(space, 'truncate')
-        return internal.truncate(space.id)
-    end
-    space_mt.format = function(space, format)
-        check_space_arg(space, 'format')
-        return box.schema.space.format(space.id, format)
-    end
-    space_mt.drop = function(space)
-        check_space_arg(space, 'drop')
-        check_space_exists(space)
-        return box.schema.space.drop(space.id, space.name)
-    end
-    space_mt.rename = function(space, name)
-        check_space_arg(space, 'rename')
-        check_space_exists(space)
-        return box.schema.space.rename(space.id, name)
-    end
-    space_mt.create_index = function(space, name, options)
-        check_space_arg(space, 'create_index')
-        check_space_exists(space)
-        return box.schema.index.create(space.id, name, options)
-    end
-    space_mt.run_triggers = function(space, yesno)
-        check_space_arg(space, 'run_triggers')
-        local s = builtin.space_by_id(space.id)
-        if s == nil then
-            box.error(box.error.NO_SUCH_SPACE, space.name)
-        end
-        builtin.space_run_triggers(s, yesno)
-    end
-    space_mt.__index = space_mt
 
     setmetatable(space, space_mt)
     if type(space.index) == 'table' and space.enabled then
diff --git a/test/box-tap/schema_mt.test.lua b/test/box-tap/schema_mt.test.lua
new file mode 100755
index 000000000..096c4ad60
--- /dev/null
+++ b/test/box-tap/schema_mt.test.lua
@@ -0,0 +1,79 @@
+#!/usr/bin/env tarantool
+--
+-- pr-3204: expose space_mt, index_mt into box.schema.
+--
+
+local tap = require('tap')
+local test = tap.test('schema_mt')
+
+test:plan(7)
+
+box.cfg{
+  log="tarantool.log",
+}
+
+local sp1 = box.schema.space.create('test')
+local sp2 = box.schema.space.create('test2')
+
+test:is(
+  getmetatable(sp1),
+  getmetatable(sp2),
+  'all spaces use the same metatable'
+)
+
+local idx1 = sp1:create_index('primary')
+local idx2 = sp2:create_index('primary')
+
+test:isnt(
+  getmetatable(idx1),
+  getmetatable(idx2),
+  'all indexes have their own metatable'
+)
+
+test:is(
+  idx1.get,
+  idx2.get,
+  'memtx indexes share read methods'
+)
+
+local sp3 = box.schema.space.create('test3', {engine='vinyl'})
+local sp4 = box.schema.space.create('test4', {engine='vinyl'})
+
+local idx3 = sp3:create_index('primary')
+local idx4 = sp4:create_index('primary')
+
+test:is(
+  idx3.get,
+  idx4.get,
+  'vinyl indexes share read methods'
+)
+
+test:isnt(
+  idx1.get,
+  idx3.get,
+  'memtx and vinyl indexes have separate read methods'
+)
+
+function box.schema.space_mt.foo() end
+
+test:is(
+  sp1.foo,
+  box.schema.space_mt.foo,
+  'box.schema.space_mt is mutable'
+)
+
+function box.schema.index_mt.foo() end
+
+test:is(
+  idx1.foo,
+  box.schema.index_mt.foo,
+  'box.schema.index_mt is mutable'
+)
+
+test:check()
+
+sp1:drop()
+sp2:drop()
+sp3:drop()
+sp4:drop()
+os.exit(0)
-- 
2.14.3 (Apple Git-98)




More information about the Tarantool-patches mailing list