Skip to content

Commit

Permalink
box: support space and index names in IPROTO requests
Browse files Browse the repository at this point in the history
Add support for accepting IPROTO requests with space or index name instead
of identifier (identifier is preferred over name): remove `space_id` key
from mandatory keys and delay resolution of space identifier until request
gets to transaction thread.

Add support for sending CRUD requests from net.box connection objects with
disabled schema fetching by manually specifying space or index name or
identifier: when schema fetching is disabled, the space and index tables of
connections return wrapper tables that store necessary context (space or
index name or identifier, determined by type, connection object and space
for indexes) for performing requests.

Closes tarantool#8146

@TarantoolBot document
Title: Space and index name in IPROTO requests

Refer to design document for details:
https://www.notion.so/tarantool/Schemafull-IPROTO-cc315ad6bdd641dea66ad854992d8cbf?pvs=4#f4d4b3fa2b3646f1949319866428b6c0
  • Loading branch information
CuriousGeorgiy committed Apr 16, 2023
1 parent 442ee72 commit ddd1901
Show file tree
Hide file tree
Showing 16 changed files with 257 additions and 47 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## feature/box

* Added support for accepting IPROTO requests with space or index name instead
of identifier (gh-8146).

## feature/net.box

* Added support for sending CRUD requests from connection objects with disabled
schema fetching by manually specifying space or index name or identifier
(gh-8146).
37 changes: 37 additions & 0 deletions src/box/iproto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2138,6 +2138,39 @@ tx_process_rollback(struct cmsg *m)
tx_end_msg(msg, &header);
}

/*
* In case the request does not contain a space or identifier but contains a
* corresponding name, tries to resolve the name.
* A space identifier is mandatory for a CRUD request, so in case the space
* identifier is not present in the request and we fail to get an identifier
* from the space name (or the space name is missing), we must return with an
* error, setting a missing request field diagnostic, just as it was done in
* `xrow_decode_dml` before space names in IPROTO requests were introduced.
*/
static int
tx_resolve_space_and_index_name(struct request *dml)
{
if (dml->space_id == 0 && dml->space_name != NULL) {
uint32_t space_id = box_space_id_by_name(dml->space_name,
dml->space_name_len);
if (space_id != BOX_ID_NIL)
dml->space_id = space_id;
}
if (dml->space_id == 0) {
diag_set(ClientError, ER_MISSING_REQUEST_FIELD,
iproto_key_name(IPROTO_SPACE_ID));
return -1;
}
if (dml->index_id == 0 && dml->index_name != NULL) {
uint32_t index_id = box_index_id_by_name(dml->space_id,
dml->index_name,
dml->index_name_len);
if (index_id != BOX_ID_NIL)
dml->index_id = index_id;
}
return 0;
}

static void
tx_process1(struct cmsg *m)
{
Expand All @@ -2149,6 +2182,8 @@ tx_process1(struct cmsg *m)
struct obuf_svp svp;
struct obuf *out;
tx_inject_delay();
if (tx_resolve_space_and_index_name(&msg->dml) != 0)
goto error;
if (box_process1(&msg->dml, &tuple) != 0)
goto error;
out = msg->connection->tx.p_obuf;
Expand Down Expand Up @@ -2185,6 +2220,8 @@ tx_process_select(struct cmsg *m)
goto error;

tx_inject_delay();
if (tx_resolve_space_and_index_name(&msg->dml) != 0)
goto error;
packed_pos = req->after_position;
packed_pos_end = req->after_position_end;
if (packed_pos != NULL) {
Expand Down
14 changes: 8 additions & 6 deletions src/box/iproto_constants.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ const unsigned char iproto_key_type[IPROTO_KEY_MAX] =
/* 0x59 */ MP_UINT, /* IPROTO_TXN_ISOLATION */
/* 0x5a */ MP_UINT, /* IPROTO_VCLOCK_SYNC */
/* 0x5b */ MP_STR, /* IPROTO_AUTH_TYPE */
/* 0x5c */ MP_STR, /* IPROTO_SPACE_NAME */
/* 0x5d */ MP_STR, /* IPROTO_INDEX_NAME */
/* }}} */
};

Expand Down Expand Up @@ -179,15 +181,15 @@ const char *iproto_type_strs[] =
#define bit(c) (1ULL<<IPROTO_##c)
const uint64_t iproto_body_key_map[IPROTO_TYPE_STAT_MAX] = {
0, /* unused */
bit(SPACE_ID) | bit(LIMIT) | bit(KEY), /* SELECT */
bit(SPACE_ID) | bit(TUPLE), /* INSERT */
bit(SPACE_ID) | bit(TUPLE), /* REPLACE */
bit(SPACE_ID) | bit(KEY) | bit(TUPLE), /* UPDATE */
bit(SPACE_ID) | bit(KEY), /* DELETE */
bit(LIMIT) | bit(KEY), /* SELECT */
bit(TUPLE), /* INSERT */
bit(TUPLE), /* REPLACE */
bit(KEY) | bit(TUPLE), /* UPDATE */
bit(KEY), /* DELETE */
0, /* CALL_16 */
0, /* AUTH */
0, /* EVAL */
bit(SPACE_ID) | bit(OPS) | bit(TUPLE), /* UPSERT */
bit(OPS) | bit(TUPLE), /* UPSERT */
0, /* CALL */
0, /* EXECUTE */
0, /* NOP */
Expand Down
11 changes: 11 additions & 0 deletions src/box/iproto_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,17 @@ enum iproto_key {
* authentication method.
*/
IPROTO_AUTH_TYPE = 0x5b,
/**
* Space name used instead of identifier (IPROTO_SPACE_ID) in CRUD
* requests. Ignored when identifier is present.
*/
IPROTO_SPACE_NAME = 0x5c,
/**
* Index name used instead of identifier (IPROTO_INDEX_ID) in
* IPROTO_SELECT and IPROTO_DELETE requests. Ignored when identifier is
* present.
*/
IPROTO_INDEX_NAME = 0x5d,
/*
* Be careful to not extend iproto_key values over 0x7f.
* iproto_keys are encoded in msgpack as positive fixnum, which ends at
Expand Down
2 changes: 2 additions & 0 deletions src/box/iproto_features.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,6 @@ iproto_features_init(void)
IPROTO_FEATURE_WATCHERS);
iproto_features_set(&IPROTO_CURRENT_FEATURES,
IPROTO_FEATURE_PAGINATION);
iproto_features_set(&IPROTO_CURRENT_FEATURES,
IPROTO_FEATURE_SPACE_AND_INDEX_NAMES);
}
10 changes: 9 additions & 1 deletion src/box/iproto_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ enum iproto_feature_id {
* request fields and IPROTO_POSITION response field.
*/
IPROTO_FEATURE_PAGINATION = 4,
/**
* Using space [index] names instead of identifiers support:
* IPROTO_SPACE_NAME and IPROTO_INDEX_NAME fields in IPROTO_SELECT and
* IPROTO_DELETE request body;
* IPROTO_SPACE_NAME field in IPROTO_INSERT, IPROTO_REPLACE,
* IPROTO_UPDATE and IPROTO_UPSERT request body.
*/
IPROTO_FEATURE_SPACE_AND_INDEX_NAMES = 5,
iproto_feature_id_MAX,
};

Expand All @@ -69,7 +77,7 @@ struct iproto_features {
* `box.iproto.protocol_version` needs to be updated correspondingly.
*/
enum {
IPROTO_CURRENT_VERSION = 4,
IPROTO_CURRENT_VERSION = 5,
};

/**
Expand Down
3 changes: 3 additions & 0 deletions src/box/lua/iproto.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ push_iproto_key_enum(struct lua_State *L)
{"EVENT_DATA", IPROTO_EVENT_DATA},
{"TXN_ISOLATION", IPROTO_TXN_ISOLATION},
{"VCLOCK_SYNC", IPROTO_VCLOCK_SYNC},
{"SPACE_NAME", IPROTO_SPACE_NAME},
{"INDEX_NAME", IPROTO_INDEX_NAME},
};
push_iproto_constant_subnamespace(L, "key", keys, lengthof(keys));
for (size_t i = 0; i < lengthof(keys); ++i) {
Expand Down Expand Up @@ -293,6 +295,7 @@ push_iproto_protocol_features(struct lua_State *L)
{"error_extension", IPROTO_FEATURE_ERROR_EXTENSION},
{"watchers", IPROTO_FEATURE_WATCHERS},
{"pagination", IPROTO_FEATURE_PAGINATION},
{"space_and_index_names", IPROTO_FEATURE_SPACE_AND_INDEX_NAMES},
};

lua_createtable(L, 0, lengthof(features));
Expand Down
80 changes: 48 additions & 32 deletions src/box/lua/net_box.c
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,44 @@ netbox_encode_eval(lua_State *L, int idx, struct mpstream *stream,
netbox_end_encode(stream, svp);
}

/*
* Depending on the type of the 'id' argument (see also net.box space metatable)
* encode either a space identifier or a space name.
*/
static void
netbox_encode_space_id_or_name(lua_State *L, int idx, struct mpstream *stream)
{
if (lua_type(L, idx) == LUA_TNUMBER) {
uint32_t space_id = lua_tonumber(L, idx);
mpstream_encode_uint(stream, IPROTO_SPACE_ID);
mpstream_encode_uint(stream, space_id);
} else {
size_t len;
const char *space_name = lua_tolstring(L, idx, &len);
mpstream_encode_uint(stream, IPROTO_SPACE_NAME);
mpstream_encode_strn(stream, space_name, len);
}
}

/*
* Depending on the type of the 'id' argument (see also net.box index metatable)
* encode either a index identifier or an index name.
*/
static void
netbox_encode_index_id_or_name(lua_State *L, int idx, struct mpstream *stream)
{
if (lua_type(L, idx) == LUA_TNUMBER) {
uint32_t space_id = lua_tonumber(L, idx);
mpstream_encode_uint(stream, IPROTO_INDEX_ID);
mpstream_encode_uint(stream, space_id);
} else {
size_t len;
const char *space_name = lua_tolstring(L, idx, &len);
mpstream_encode_uint(stream, IPROTO_INDEX_NAME);
mpstream_encode_strn(stream, space_name, len);
}
}

/* Encode select request. */
static void
netbox_encode_select(lua_State *L, int idx, struct mpstream *stream,
Expand All @@ -817,19 +855,13 @@ netbox_encode_select(lua_State *L, int idx, struct mpstream *stream,
if (fetch_pos)
map_size++;
mpstream_encode_map(stream, map_size);
uint32_t space_id = lua_tonumber(L, idx);
uint32_t index_id = lua_tonumber(L, idx + 1);
int iterator = lua_tointeger(L, idx + 2);
uint32_t offset = lua_tonumber(L, idx + 3);
uint32_t limit = lua_tonumber(L, idx + 4);

/* encode space_id */
mpstream_encode_uint(stream, IPROTO_SPACE_ID);
mpstream_encode_uint(stream, space_id);
netbox_encode_space_id_or_name(L, idx, stream);

/* encode index_id */
mpstream_encode_uint(stream, IPROTO_INDEX_ID);
mpstream_encode_uint(stream, index_id);
netbox_encode_index_id_or_name(L, idx + 1, stream);

/* encode iterator */
mpstream_encode_uint(stream, IPROTO_ITERATOR);
Expand Down Expand Up @@ -881,10 +913,7 @@ netbox_encode_insert_or_replace(lua_State *L, int idx, struct mpstream *stream,

mpstream_encode_map(stream, 2);

/* encode space_id */
uint32_t space_id = lua_tonumber(L, idx);
mpstream_encode_uint(stream, IPROTO_SPACE_ID);
mpstream_encode_uint(stream, space_id);
netbox_encode_space_id_or_name(L, idx, stream);

/* encode args */
mpstream_encode_uint(stream, IPROTO_TUPLE);
Expand Down Expand Up @@ -919,15 +948,9 @@ netbox_encode_delete(lua_State *L, int idx, struct mpstream *stream,

mpstream_encode_map(stream, 3);

/* encode space_id */
uint32_t space_id = lua_tonumber(L, idx);
mpstream_encode_uint(stream, IPROTO_SPACE_ID);
mpstream_encode_uint(stream, space_id);
netbox_encode_space_id_or_name(L, idx, stream);

/* encode space_id */
uint32_t index_id = lua_tonumber(L, idx + 1);
mpstream_encode_uint(stream, IPROTO_INDEX_ID);
mpstream_encode_uint(stream, index_id);
netbox_encode_index_id_or_name(L, idx + 1, stream);

/* encode key */
mpstream_encode_uint(stream, IPROTO_KEY);
Expand All @@ -946,15 +969,9 @@ netbox_encode_update(lua_State *L, int idx, struct mpstream *stream,

mpstream_encode_map(stream, 5);

/* encode space_id */
uint32_t space_id = lua_tonumber(L, idx);
mpstream_encode_uint(stream, IPROTO_SPACE_ID);
mpstream_encode_uint(stream, space_id);
netbox_encode_space_id_or_name(L, idx, stream);

/* encode index_id */
uint32_t index_id = lua_tonumber(L, idx + 1);
mpstream_encode_uint(stream, IPROTO_INDEX_ID);
mpstream_encode_uint(stream, index_id);
netbox_encode_index_id_or_name(L, idx + 1, stream);

/* encode index_id */
mpstream_encode_uint(stream, IPROTO_INDEX_BASE);
Expand All @@ -981,10 +998,7 @@ netbox_encode_upsert(lua_State *L, int idx, struct mpstream *stream,

mpstream_encode_map(stream, 4);

/* encode space_id */
uint32_t space_id = lua_tonumber(L, idx);
mpstream_encode_uint(stream, IPROTO_SPACE_ID);
mpstream_encode_uint(stream, space_id);
netbox_encode_space_id_or_name(L, idx, stream);

/* encode index_base */
mpstream_encode_uint(stream, IPROTO_INDEX_BASE);
Expand Down Expand Up @@ -3000,6 +3014,8 @@ luaopen_net_box(struct lua_State *L)
IPROTO_FEATURE_WATCHERS);
iproto_features_set(&NETBOX_IPROTO_FEATURES,
IPROTO_FEATURE_PAGINATION);
iproto_features_set(&NETBOX_IPROTO_FEATURES,
IPROTO_FEATURE_SPACE_AND_INDEX_NAMES);

lua_pushcfunction(L, luaT_netbox_request_iterator_next);
luaT_netbox_request_iterator_next_ref = luaL_ref(L, LUA_REGISTRYINDEX);
Expand Down
16 changes: 16 additions & 0 deletions src/box/lua/net_box.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ local IPROTO_FEATURE_NAMES = {
[2] = 'error_extension',
[3] = 'watchers',
[4] = 'pagination',
[5] = 'space_and_index_names',
}

local REQUEST_OPTION_TYPES = {
Expand Down Expand Up @@ -390,6 +391,21 @@ local function new_sm(uri, opts)
})
end
end
if not opts.fetch_schema and features.space_and_index_names then
remote.space = setmetatable({_remote = remote}, {
__index = function(self, key)
local space = {id = key, name = key, _remote = self._remote,
_format_cdata = box.internal.new_tuple_format()}
space.index = setmetatable({space = space, _remote = remote}, {
__index = function(self, key)
return setmetatable({id = key, name = key,
space = self.space,
_remote = self._remote},
self._remote._index_mt)
end})
return setmetatable(space, self._remote._space_mt)
end})
end
elseif what == 'did_fetch_schema' then
remote:_install_schema(...)
elseif what == 'event' then
Expand Down
8 changes: 8 additions & 0 deletions src/box/xrow.c
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,14 @@ xrow_decode_dml(struct xrow_header *row, struct request *request,
request->after_tuple = value;
request->after_tuple_end = data;
break;
case IPROTO_SPACE_NAME:
request->space_name =
mp_decode_str(&value, &request->space_name_len);
break;
case IPROTO_INDEX_NAME:
request->index_name =
mp_decode_str(&value, &request->index_name_len);
break;
default:
break;
}
Expand Down
8 changes: 8 additions & 0 deletions src/box/xrow.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,14 @@ struct request {
int index_base;
/** Send position of last selected tuple in response if true. */
bool fetch_position;
/** Name of requested space, points to the request's input buffer. */
const char *space_name;
/** Length of @space_name. */
uint32_t space_name_len;
/** Name of requested index, points to the request's input buffer. */
const char *index_name;
/** Length of @index_name. */
uint32_t index_name_len;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ local reference_table = {
EVENT_DATA = 0x58,
TXN_ISOLATION = 0x59,
VCLOCK_SYNC = 0x5a,
SPACE_NAME = 0x5c,
INDEX_NAME = 0x5d,
},

-- `iproto_metadata_key` enumeration.
Expand Down Expand Up @@ -157,7 +159,7 @@ local reference_table = {
},

-- `IPROTO_CURRENT_VERSION` constant
protocol_version = 4,
protocol_version = 5,

-- `feature_id` enumeration
protocol_features = {
Expand All @@ -166,13 +168,15 @@ local reference_table = {
error_extension = true,
watchers = true,
pagination = true,
space_and_index_names = true,
},
feature = {
streams = 0,
transactions = 1,
error_extension = 2,
watchers = 3,
pagination = 4,
space_and_index_names = 5,
},
}

Expand Down

0 comments on commit ddd1901

Please sign in to comment.