diff --git a/src/box/memtx_space.c b/src/box/memtx_space.c index 304e7fda3e3bcf307e19ffca86f82e3402e96bef..c0b8c9011a1849871079e7d1c59fc6f00b2debe1 100644 --- a/src/box/memtx_space.c +++ b/src/box/memtx_space.c @@ -532,6 +532,69 @@ memtx_space_execute_upsert(struct space *space, struct txn *txn, return 0; } +/** + * This function simply creates new memtx tuple, refs it and calls space's + * replace function. In constrast to original memtx_space_execute_replace(), it + * doesn't handle any transaction routine. + * Ephemeral spaces shouldn't be involved in transaction routine, since + * they are used only for internal purposes. Moreover, ephemeral spaces + * can be created and destroyed within one transaction and rollback of already + * destroyed space may lead to undefined behaviour. For this reason it + * doesn't take txn as an argument. + */ +static int +memtx_space_ephemeral_replace(struct space *space, const char *tuple, + const char *tuple_end) +{ + struct memtx_space *memtx_space = (struct memtx_space *)space; + struct tuple *new_tuple = memtx_tuple_new(space->format, tuple, + tuple_end); + if (new_tuple == NULL) + return -1; + tuple_ref(new_tuple); + struct tuple *old_tuple = NULL; + if (memtx_space->replace(space, old_tuple, new_tuple, + DUP_REPLACE_OR_INSERT, &old_tuple) != 0) { + tuple_unref(new_tuple); + return -1; + } + if (old_tuple != NULL) + tuple_unref(old_tuple); + return 0; +} + +/** + * Delete tuple with given key from primary index. Tuple checking is omitted + * due to the ability of ephemeral spaces to hold nulls in primary key. + * Generally speaking, it is not correct behaviour owing to ambiguity when + * fetching/deleting tuple from space with several tuples containing + * nulls in PK. On the other hand, ephemeral spaces are used only for internal + * needs, so if it is guaranteed that no such situation occur + * (when several tuples with nulls in PK exist), it is OK to allow + * insertion nulls in PK. + * + * Similarly to ephemeral replace function, + * it isn't involved in any transaction routine. + */ +static int +memtx_space_ephemeral_delete(struct space *space, const char *key) +{ + struct memtx_space *memtx_space = (struct memtx_space *)space; + struct index *primary_index = space_index(space, 0 /* primary index*/); + if (primary_index == NULL) + return -1; + uint32_t part_count = mp_decode_array(&key); + struct tuple *old_tuple; + if (index_get(primary_index, key, part_count, &old_tuple) != 0) + return -1; + if (old_tuple != NULL && + memtx_space->replace(space, old_tuple, NULL, + DUP_REPLACE, &old_tuple) != 0) + return -1; + tuple_unref(old_tuple); + return 0; +} + /* }}} DML */ /* {{{ DDL */ @@ -922,6 +985,8 @@ static const struct space_vtab memtx_space_vtab = { /* .execute_delete = */ memtx_space_execute_delete, /* .execute_update = */ memtx_space_execute_update, /* .execute_upsert = */ memtx_space_execute_upsert, + /* .ephemeral_replace = */ memtx_space_ephemeral_replace, + /* .ephemeral_delete = */ memtx_space_ephemeral_delete, /* .init_system_space = */ memtx_init_system_space, /* .init_ephemeral_space = */ memtx_init_ephemeral_space, /* .check_index_def = */ memtx_space_check_index_def, diff --git a/src/box/space.h b/src/box/space.h index b3d2cde98633da8dba4ecf76f6dbfb30d77168a3..1844690550d36618ab8e378a24fbbf46f37eab0f 100644 --- a/src/box/space.h +++ b/src/box/space.h @@ -66,6 +66,10 @@ struct space_vtab { struct request *, struct tuple **result); int (*execute_upsert)(struct space *, struct txn *, struct request *); + int (*ephemeral_replace)(struct space *, const char *, const char *); + + int (*ephemeral_delete)(struct space *, const char *); + void (*init_system_space)(struct space *); /** * Initialize an ephemeral space instance. @@ -334,6 +338,20 @@ int space_execute_upsert(struct space *space, struct txn *txn, struct request *request); + +static inline int +space_ephemeral_replace(struct space *space, const char *tuple, + const char *tuple_end) +{ + return space->vtab->ephemeral_replace(space, tuple, tuple_end); +} + +static inline int +space_ephemeral_delete(struct space *space, const char *key) +{ + return space->vtab->ephemeral_delete(space, key); +} + static inline void init_system_space(struct space *space) { diff --git a/src/box/sysview_engine.c b/src/box/sysview_engine.c index 556a7e14855c69ba9eb24b000853f66c33b84a1a..817b86355b156a97f5d7ccd16a6ad7e161e38068 100644 --- a/src/box/sysview_engine.c +++ b/src/box/sysview_engine.c @@ -99,6 +99,26 @@ sysview_space_execute_upsert(struct space *space, struct txn *txn, return -1; } +static int +sysview_space_ephemeral_replace(struct space *space, const char *tuple, + const char *tuple_end) +{ + (void)space; + (void)tuple; + (void)tuple_end; + unreachable(); + return -1; +} + +static int +sysview_space_ephemeral_delete(struct space *space, const char *key) +{ + (void)key; + (void)space; + unreachable(); + return -1; +} + static void sysview_init_system_space(struct space *space) { @@ -200,6 +220,8 @@ static const struct space_vtab sysview_space_vtab = { /* .execute_delete = */ sysview_space_execute_delete, /* .execute_update = */ sysview_space_execute_update, /* .execute_upsert = */ sysview_space_execute_upsert, + /* .ephemeral_replace = */ sysview_space_ephemeral_replace, + /* .ephemeral_delete = */ sysview_space_ephemeral_delete, /* .init_system_space = */ sysview_init_system_space, /* .init_ephemeral_space = */ sysview_init_ephemeral_space, /* .check_index_def = */ sysview_space_check_index_def, diff --git a/src/box/vinyl.c b/src/box/vinyl.c index 4c670f3cddc2e6ff8e3860a9a6ab829922e45a73..0541ebe1488e592f2d4fcb2ed3ae0403616c80ff 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -2362,6 +2362,26 @@ vinyl_space_execute_upsert(struct space *space, struct txn *txn, return vy_upsert(env, tx, stmt, space, request); } +static int +vinyl_space_ephemeral_replace(struct space *space, const char *tuple, + const char *tuple_end) +{ + (void)space; + (void)tuple; + (void)tuple_end; + unreachable(); + return -1; +} + +static int +vinyl_space_ephemeral_delete(struct space *space, const char *key) +{ + (void)space; + (void)key; + unreachable(); + return -1; +} + static inline void txn_stmt_unref_tuples(struct txn_stmt *stmt) { @@ -4013,6 +4033,8 @@ static const struct space_vtab vinyl_space_vtab = { /* .execute_delete = */ vinyl_space_execute_delete, /* .execute_update = */ vinyl_space_execute_update, /* .execute_upsert = */ vinyl_space_execute_upsert, + /* .ephemeral_replace = */ vinyl_space_ephemeral_replace, + /* .ephemeral_delete = */ vinyl_space_ephemeral_delete, /* .init_system_space = */ vinyl_init_system_space, /* .init_ephemeral_space = */ vinyl_init_ephemeral_space, /* .check_index_def = */ vinyl_space_check_index_def,