diff --git a/doc/sphinx/book/box/box_index.rst b/doc/sphinx/book/box/box_index.rst index 46967180ec9ca3e1754518f03613bb262478c4d3..4c07a6134e8ffbf7286bce03b9a58740d705780b 100644 --- a/doc/sphinx/book/box/box_index.rst +++ b/doc/sphinx/book/box/box_index.rst @@ -470,6 +470,33 @@ API is a direct binding to corresponding methods of index objects of type | :codenormal:`- 1` | :codenormal:`...` + .. function:: update(key, {{operator, field_no, value}, ...}) + + Update a tuple. + + Same as :func:`box.space...update() <space_object.update>`, + but key is searched in this index instead of primary key. + This index ought to be unique. + + :param lua-value key: key to be matched against the index key + :param table {operator, field_no, value}: update opearations (see: func:`box.space...update() <space_object.update>`) + + :return: the updated tuple. + :rtype: tuple + + .. function:: delete(key) + + Delete a tuple identified by a key. + + Same as :func:`box.space...delete() <space_object.delete>`, + but key is searched in this index instead of primary key. + This index ought to be unique. + + :param lua-value key: key to be matched against the index key + + :return: the deleted tuple. + :rtype: tuple + .. function:: alter({options}) Alter an index. diff --git a/src/box/request.cc b/src/box/request.cc index 719d76bdcdae272f5a7359a5d8e59cf4d139247d..57321ed88b840d72dff13e593bba195a536bde4d 100644 --- a/src/box/request.cc +++ b/src/box/request.cc @@ -80,8 +80,10 @@ execute_update(struct request *request, struct port *port) struct txn *txn = txn_begin_stmt(request, space); access_check_space(space, PRIV_W); - Index *pk = index_find(space, 0); - /* Try to find the tuple by primary key. */ + /* Try to find the tuple by unique key. */ + Index *pk = index_find(space, request->index_id); + if (!pk->key_def->is_unique) + tnt_raise(ClientError, ER_MORE_THAN_ONE_TUPLE); const char *key = request->key; uint32_t part_count = mp_decode_array(&key); primary_key_validate(pk->key_def, key, part_count); @@ -122,8 +124,10 @@ execute_delete(struct request *request, struct port *port) access_check_space(space, PRIV_W); - /* Try to find tuple by primary key */ - Index *pk = index_find(space, 0); + /* Try to find the tuple by unique key. */ + Index *pk = index_find(space, request->index_id); + if (!pk->key_def->is_unique) + tnt_raise(ClientError, ER_MORE_THAN_ONE_TUPLE); const char *key = request->key; uint32_t part_count = mp_decode_array(&key); primary_key_validate(pk->key_def, key, part_count); diff --git a/src/lua/net_box.lua b/src/lua/net_box.lua index 6f4231dc4193afd9d2505dd29b3d5ef73985e4a3..1c6e99ec2dadca5ba8e297c4af6fa730f00f3cae 100644 --- a/src/lua/net_box.lua +++ b/src/lua/net_box.lua @@ -157,19 +157,19 @@ local proto = { end, -- delete - delete = function(sync, spaceno, key) + delete = function(sync, spaceno, key, index_id) return request( { [SYNC] = sync, [TYPE] = DELETE }, - { [SPACE_ID] = spaceno, [KEY] = keyfy(key) } + { [SPACE_ID] = spaceno, [INDEX_ID] = index_id, [KEY] = keyfy(key) } ) end, -- update - update = function(sync, spaceno, key, oplist) + update = function(sync, spaceno, key, oplist, index_id) return request( { [SYNC] = sync, [TYPE] = UPDATE }, { [KEY] = keyfy(key), [INDEX_BASE] = 1 , [TUPLE] = oplist, - [SPACE_ID] = spaceno } + [SPACE_ID] = spaceno, [INDEX_ID] = index_id } ) end, @@ -256,12 +256,12 @@ local function space_metatable(self) delete = function(space, key) check_if_space(space) - return self:_delete(space.id, key) + return self:_delete(space.id, key, 0) end, update = function(space, key, oplist) check_if_space(space) - return self:_update(space.id, key, oplist) + return self:_update(space.id, key, oplist, 0) end, get = function(space, key) @@ -334,7 +334,18 @@ local function index_metatable(self) if #res > 0 then return res[1][1] end - end + end, + + delete = function(idx, key) + check_if_index(idx) + return self:_delete(idx.space.id, key, idx.id) + end, + + update = function(idx, key, oplist) + check_if_index(idx) + return self:_update(idx.space.id, key, oplist, idx.id) + end, + } } end @@ -1041,13 +1052,13 @@ local remote_methods = { return one_tuple(res.body[DATA]) end, - _delete = function(self, spaceno, key) - local res = self:_request('delete', true, spaceno, key) + _delete = function(self, spaceno, key, index_id) + local res = self:_request('delete', true, spaceno, key, index_id) return one_tuple(res.body[DATA]) end, - _update = function(self, spaceno, key, oplist) - local res = self:_request('update', true, spaceno, key, oplist) + _update = function(self, spaceno, key, oplist, index_id) + local res = self:_request('update', true, spaceno, key, oplist, index_id) return one_tuple(res.body[DATA]) end } diff --git a/test/box/sql.result b/test/box/sql.result index 4c48ce6ba5420205c4cb5a970639f786d0ba64f3..19eddef048b3a48ec5ce47db9a9686643cbc372f 100644 --- a/test/box/sql.result +++ b/test/box/sql.result @@ -4,6 +4,9 @@ net_box = require('net.box') s = box.schema.space.create('test', { id = 0 }) --- ... +_ = box.schema.space.create('test1', { id = 555 }) +--- +... box.schema.user.create('test', { password = 'test' }) --- ... @@ -19,6 +22,12 @@ space = conn.space.test index = box.space.test:create_index('primary', { type = 'hash' }) --- ... +_ = box.space.test1:create_index('primary', { type = 'hash' }) +--- +... +_ = box.space.test1:create_index('secondary', { type = 'hash', parts = {2, 'str'}}) +--- +... conn:ping() --- - true @@ -178,6 +187,19 @@ space:select{4294967295} --- - [] ... +-- check update delete be secondary index +conn.space.test1:insert{0, "hello", 1} +--- +- [0, 'hello', 1] +... +conn.space.test1.index.secondary:update("hello", {{'=', 3, 2}}) +--- +- [0, 'hello', 2] +... +conn.space.test1.index.secondary:delete("hello") +--- +- [0, 'hello', 2] +... -- cleanup space:delete(0) --- @@ -189,6 +211,9 @@ space:delete(4294967295) box.space.test:drop() --- ... +box.space.test1:drop() +--- +... box.schema.user.drop('test') --- ... diff --git a/test/box/sql.test.lua b/test/box/sql.test.lua index ba9240ba537f61e1eeadb5d747f926c88a39cdbe..bad89b7c2b87cf6b1f13ec592731610cf8d68dc9 100644 --- a/test/box/sql.test.lua +++ b/test/box/sql.test.lua @@ -1,6 +1,7 @@ net_box = require('net.box') s = box.schema.space.create('test', { id = 0 }) +_ = box.schema.space.create('test1', { id = 555 }) box.schema.user.create('test', { password = 'test' }) box.schema.user.grant('test', 'execute,read,write', 'universe') @@ -8,6 +9,8 @@ conn = net_box:new('test:test@' .. box.cfg.listen) space = conn.space.test index = box.space.test:create_index('primary', { type = 'hash' }) +_ = box.space.test1:create_index('primary', { type = 'hash' }) +_ = box.space.test1:create_index('secondary', { type = 'hash', parts = {2, 'str'}}) conn:ping() -- xxx: bug currently selects no rows @@ -72,9 +75,15 @@ space:insert{0} space:select{0} space:select{4294967295} +-- check update delete be secondary index +conn.space.test1:insert{0, "hello", 1} +conn.space.test1.index.secondary:update("hello", {{'=', 3, 2}}) +conn.space.test1.index.secondary:delete("hello") + -- cleanup space:delete(0) space:delete(4294967295) box.space.test:drop() +box.space.test1:drop() box.schema.user.drop('test') space = nil