From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> To: tarantool-patches@freelists.org Cc: vdavydov.dev@gmail.com, aleclarson <alec.stanford.larson@gmail.com> Subject: [PATCH 1/2] schema: expose space_mt and index_mt on `box.schema` table Date: Fri, 23 Mar 2018 16:07:08 +0300 [thread overview] Message-ID: <39d1b0b99479563fadd0d9701702ae7c782b18db.1521810303.git.v.shpilevoy@tarantool.org> (raw) In-Reply-To: <cover.1521810303.git.v.shpilevoy@tarantool.org> In-Reply-To: <cover.1521810303.git.v.shpilevoy@tarantool.org> From: aleclarson <alec.stanford.larson@gmail.com> This commit allows userland to extend the space and index metatables with their own functions or even metamethods. Reducing barriers for this kind of experimentation is vital for user contribution toward the improvement of Tarantool's API. Also, this commit reuses functions between all spaces/indexes. The metatables are exposed on `box` to make them simple to discover. The suggested alternatives were `box.internal` and `box.schema`. In a future commit, we should look into "freezing" the built-in methods so the user cannot accidentally override them. This is especially important when updating Tarantool. Closes #3204 --- src/box/lua/schema.lua | 639 ++++++++++++++++++++-------------------- test/box-tap/schema_mt.test.lua | 74 +++++ 2 files changed, 398 insertions(+), 315 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..3fb626efd 100644 --- a/src/box/lua/schema.lua +++ b/src/box/lua/schema.lua @@ -1074,218 +1074,348 @@ 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 - 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); +local space_mt = {} +space_mt.__index = space_mt +box.schema.space_mt = 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 - 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 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 - 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 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 - 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 builtin.space_bsize(s) +end + +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 - 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 + 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 - index_mt.get_luac = function(index, key) - check_index_arg(index, 'get') - key = keify(key) - return internal.get(index.space_id, index.id, key) + 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 - 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 +local index_mt = {} +index_mt.__index = index_mt +box.schema.index_mt = 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.__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 +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); +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 +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); +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 +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); - 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 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 - local port = ffi.cast('struct port *', port_tuple) +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 +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) +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 +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) - 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(index.space_id, index.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) + 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.rename = function(index, name) - check_index_arg(index, 'rename') - return box.schema.index.rename(index.space_id, index.id, name) + builtin.port_destroy(port); + return ret +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 + +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 + +index_mt.info = function(index) + return internal.info(index.space_id, index.id); +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) +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 - 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) + return box.schema.index.alter(index.space_id, index.id, options) +end + +index_mt.__pairs = index_mt.pairs -- Lua 5.2 compatibility +index_mt.__ipairs = index_mt.pairs -- Lua 5.2 compatibility + +function box.schema.space.bless(space) + local index_mt = {} + index_mt.__index = function(index, key) + return index_mt[key] or box.schema.index_mt[key] end -- true if reading operations may yield @@ -1294,136 +1424,15 @@ function box.schema.space.bless(space) for _, op in ipairs(read_ops) do if read_yields then -- use Lua/C implmenetation - index_mt[op] = index_mt[op .. "_luac"] + index_mt[op] = box.schema.index_mt[op .. "_luac"] else -- use FFI implementation - index_mt[op] = index_mt[op .. "_ffi"] + index_mt[op] = box.schema.index_mt[op .. "_ffi"] end 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) + setmetatable(space, box.schema.space_mt) if type(space.index) == 'table' and space.enabled then for j, index in pairs(space.index) do if type(j) == 'number' 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..7e531dd01 --- /dev/null +++ b/test/box-tap/schema_mt.test.lua @@ -0,0 +1,74 @@ +#!/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() +os.exit(0) -- 2.14.3 (Apple Git-98)
next prev parent reply other threads:[~2018-03-23 13:07 UTC|newest] Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-03-23 13:07 [PATCH 0/2] schema: expose space_mt and index_mt on table Vladislav Shpilevoy 2018-03-23 13:07 ` Vladislav Shpilevoy [this message] 2018-03-23 13:07 ` [PATCH 2/2] schema: review fixes for box.schema.space/index metatables Vladislav Shpilevoy 2018-03-29 10:54 ` [PATCH 0/2] schema: expose space_mt and index_mt on table Vladimir Davydov 2018-03-29 14:31 ` [PATCH v2 0/2] schema: expose space_mt and index_mt on box.schema table Vladislav Shpilevoy 2018-03-29 14:31 ` [PATCH v2 1/2] schema: move space_mt and index_mt definition out of space bless Vladislav Shpilevoy 2018-04-01 9:33 ` Vladimir Davydov 2018-04-01 11:02 ` [PATCH 0/2] schema: expose space_mt and index_mt on box.schema table Vladislav Shpilevoy 2018-04-01 11:02 ` [PATCH 1/2] schema: move space_mt and index_mt definition out of space bless Vladislav Shpilevoy 2018-04-01 11:02 ` [PATCH 2/2] schema: expose space_mt and index_mt on `box.schema` table Vladislav Shpilevoy 2018-04-02 11:28 ` Vladimir Davydov 2018-04-03 16:50 ` [PATCH v2 0/3] schema: expose space_mt and index_mt on box.schema table Vladislav Shpilevoy 2018-04-03 16:50 ` [PATCH v2 1/3] schema: move space_mt and index_mt definition out of space bless Vladislav Shpilevoy 2018-04-03 16:50 ` [PATCH v2 2/3] schema: inherit vinyl/memtx_index_mt from base index mt Vladislav Shpilevoy 2018-04-03 16:50 ` [PATCH v2 3/3] schema: expose space_mt and index_mt on box.schema table Vladislav Shpilevoy 2018-05-05 12:47 ` [tarantool-patches] " Vladislav Shpilevoy 2018-05-08 16:48 ` Konstantin Osipov 2018-05-08 17:33 ` Vladislav Shpilevoy 2018-03-29 14:31 ` [PATCH v2 2/2] schema: expose space_mt and index_mt on `box.schema` table Vladislav Shpilevoy 2018-04-01 9:37 ` [PATCH v2 0/2] schema: expose space_mt and index_mt on box.schema table Vladimir Davydov
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=39d1b0b99479563fadd0d9701702ae7c782b18db.1521810303.git.v.shpilevoy@tarantool.org \ --to=v.shpilevoy@tarantool.org \ --cc=alec.stanford.larson@gmail.com \ --cc=tarantool-patches@freelists.org \ --cc=vdavydov.dev@gmail.com \ --subject='Re: [PATCH 1/2] schema: expose space_mt and index_mt on `box.schema` table' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox