[tarantool-patches] [PATCH v2 3/7] box: create new methods for ephemeral spaces

imeevma at tarantool.org imeevma at tarantool.org
Tue Jul 17 17:55:24 MSK 2018


Up to this patch any space had two additional methods
that were methods of ephemeral spaces. In this patch
these methods deleted from vtab and from now on
ephemeral spaces are spaces with special vtab.

Part of #3375.
---
Branch: https://github.com/tarantool/tarantool/compare/imeevma/gh-3375-lua-expose-ephemeral-spaces
Issue: https://github.com/tarantool/tarantool/issues/3375

 src/box/box.cc           | 155 +++++++++++++++++-----
 src/box/box.h            |  94 +++++++++++++
 src/box/memtx_space.c    | 333 ++++++++++++++++++++++++++++++-----------------
 src/box/space.h          |  17 ---
 src/box/sql.c            |  33 ++++-
 src/box/sysview_engine.c |  22 ----
 src/box/vinyl.c          |  22 ----
 7 files changed, 459 insertions(+), 217 deletions(-)

diff --git a/src/box/box.cc b/src/box/box.cc
index 1dcbfbf..9d9f6f0 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -872,6 +872,52 @@ box_set_net_msg_max(void)
 /* }}} configuration bindings */
 
 /**
+ * Fill up request according to given
+ * operation type. For all cases but
+ * UPSERT argument name match names of
+ * fields of struct request. For UPSERT
+ * arguments key and key_end are fields
+ * ops and ops_end.
+ */
+static inline void
+request_fill(struct request *request, uint32_t type, uint32_t space_id,
+	     uint32_t index_id, const char *key, const char *key_end,
+	     const char *tuple, const char *tuple_end, int index_base)
+{
+	memset(request, 0, sizeof(*request));
+	request->type = type;
+	request->space_id = space_id;
+	request->index_id = index_id;
+	switch (type) {
+	case IPROTO_INSERT:
+	case IPROTO_REPLACE:
+		request->tuple = tuple;
+		request->tuple_end = tuple_end;
+		break;
+	case IPROTO_DELETE:
+		request->key = key;
+		request->key_end = key_end;
+		break;
+	case IPROTO_UPDATE:
+		request->key = key;
+		request->key_end = key_end;
+		request->tuple = tuple;
+		request->tuple_end = tuple_end;
+		request->index_base = index_base;
+		break;
+	case IPROTO_UPSERT:
+		request->ops = key;
+		request->ops_end = key_end;
+		request->tuple = tuple;
+		request->tuple_end = tuple_end;
+		request->index_base = index_base;
+		break;
+	default:
+		unreachable();
+	}
+}
+
+/**
  * Execute a request against a given space id with
  * a variable-argument tuple described in format.
  *
@@ -1125,11 +1171,8 @@ box_insert(uint32_t space_id, const char *tuple, const char *tuple_end,
 	if (space == NULL || space_check_writable(space) != 0)
 		return -1;
 	struct request request;
-	memset(&request, 0, sizeof(request));
-	request.type = IPROTO_INSERT;
-	request.space_id = space_id;
-	request.tuple = tuple;
-	request.tuple_end = tuple_end;
+	request_fill(&request, IPROTO_INSERT, space_id, 0, NULL, NULL, tuple,
+		     tuple_end, 0);
 	return box_process_rw(&request, space, result);
 }
 
@@ -1142,11 +1185,8 @@ box_replace(uint32_t space_id, const char *tuple, const char *tuple_end,
 	if (space == NULL || space_check_writable(space) != 0)
 		return -1;
 	struct request request;
-	memset(&request, 0, sizeof(request));
-	request.type = IPROTO_REPLACE;
-	request.space_id = space_id;
-	request.tuple = tuple;
-	request.tuple_end = tuple_end;
+	request_fill(&request, IPROTO_REPLACE, space_id, 0, NULL, NULL, tuple,
+		     tuple_end, 0);
 	return box_process_rw(&request, space, result);
 }
 
@@ -1160,12 +1200,8 @@ box_delete(uint32_t space_id, uint32_t index_id, const char *key,
 	    key_check_findable(space, index_id, key) != 0)
 		return -1;
 	struct request request;
-	memset(&request, 0, sizeof(request));
-	request.type = IPROTO_DELETE;
-	request.space_id = space_id;
-	request.index_id = index_id;
-	request.key = key;
-	request.key_end = key_end;
+	request_fill(&request, IPROTO_DELETE, space_id, index_id, key, key_end,
+		     NULL, NULL, 0);
 	return box_process_rw(&request, space, result);
 }
 
@@ -1181,17 +1217,8 @@ box_update(uint32_t space_id, uint32_t index_id, const char *key,
 	    key_check_findable(space, index_id, key) != 0)
 		return -1;
 	struct request request;
-	memset(&request, 0, sizeof(request));
-	request.type = IPROTO_UPDATE;
-	request.space_id = space_id;
-	request.index_id = index_id;
-	request.key = key;
-	request.key_end = key_end;
-	request.index_base = index_base;
-	/** Legacy: in case of update, ops are passed in in request tuple */
-	request.tuple = ops;
-	request.tuple_end = ops_end;
-
+	request_fill(&request, IPROTO_UPDATE, space_id, index_id, key, key_end,
+		     ops, ops_end, index_base);
 	return box_process_rw(&request, space, result);
 }
 
@@ -1206,18 +1233,74 @@ box_upsert(uint32_t space_id, uint32_t index_id, const char *tuple,
 	if (space == NULL || space_check_writable(space) != 0)
 		return -1;
 	struct request request;
-	memset(&request, 0, sizeof(request));
-	request.type = IPROTO_UPSERT;
-	request.space_id = space_id;
-	request.index_id = index_id;
-	request.ops = ops;
-	request.ops_end = ops_end;
-	request.tuple = tuple;
-	request.tuple_end = tuple_end;
-	request.index_base = index_base;
+	request_fill(&request, IPROTO_UPSERT, space_id, index_id, ops, ops_end,
+		     tuple, tuple_end, index_base);
 	return box_process_rw(&request, space, result);
 }
 
+int
+box_ephemeral_insert(struct space *space, const char *tuple,
+		     const char *tuple_end, box_tuple_t **result)
+{
+	mp_tuple_assert(tuple, tuple_end);
+	struct request request;
+	request_fill(&request, IPROTO_INSERT, 0, 0, NULL, NULL, tuple,
+		     tuple_end, 0);
+	return space_execute_dml(space, NULL, &request, result);
+}
+
+int
+box_ephemeral_replace(struct space *space, const char *tuple,
+		      const char *tuple_end, box_tuple_t **result)
+{
+	mp_tuple_assert(tuple, tuple_end);
+	struct request request;
+	request_fill(&request, IPROTO_REPLACE, 0, 0, NULL, NULL, tuple,
+		     tuple_end, 0);
+	return space_execute_dml(space, NULL, &request, result);
+}
+
+int
+box_ephemeral_delete(struct space *space, uint32_t index_id, const char *key,
+		     const char *key_end, box_tuple_t **result)
+{
+	mp_tuple_assert(key, key_end);
+	if (key_check_findable(space, index_id, key) != 0)
+		return -1;
+	struct request request;
+	request_fill(&request, IPROTO_DELETE, 0, index_id, key, key_end,
+		     NULL, NULL, 0);
+	return space_execute_dml(space, NULL, &request, result);
+}
+
+int
+box_ephemeral_update(struct space *space, uint32_t index_id, const char *key,
+		     const char *key_end, const char *ops, const char *ops_end,
+		     int index_base, box_tuple_t **result)
+{
+	mp_tuple_assert(key, key_end);
+	mp_tuple_assert(ops, ops_end);
+	if (key_check_findable(space, index_id, key) != 0)
+		return -1;
+	struct request request;
+	request_fill(&request, IPROTO_UPDATE, 0, index_id, key, key_end,
+		     ops, ops_end, index_base);
+	return space_execute_dml(space, NULL, &request, result);
+}
+
+int
+box_ephemeral_upsert(struct space *space, uint32_t index_id, const char *tuple,
+		     const char *tuple_end, const char *ops,
+		     const char *ops_end, int index_base, box_tuple_t **result)
+{
+	mp_tuple_assert(ops, ops_end);
+	mp_tuple_assert(tuple, tuple_end);
+	struct request request;
+	request_fill(&request, IPROTO_UPSERT, 0, index_id, ops, ops_end,
+		     tuple, tuple_end, index_base);
+	return space_execute_dml(space, NULL, &request, result);
+}
+
 /**
  * Trigger space truncation by bumping a counter
  * in _truncate space.
diff --git a/src/box/box.h b/src/box/box.h
index 422f62f..3601823 100644
--- a/src/box/box.h
+++ b/src/box/box.h
@@ -401,6 +401,100 @@ int
 box_process1(struct request *request, box_tuple_t **result);
 
 /**
+ * Execute an INSERT request for ephemeral spaces.
+ *
+ * \param space ephemeral space.
+ * \param tuple encoded tuple in
+ * MsgPack Array format.
+ * \param tuple_end end of @a tuple.
+ * \param[out] result a new tuple.
+ * \retval -1 on error.
+ * \retval 0 on success.
+ */
+int
+box_ephemeral_insert(struct space *space, const char *tuple,
+		     const char *tuple_end, box_tuple_t **result);
+
+/**
+ * Execute an REPLACE request for ephemeral spaces.
+ *
+ * \param space ephemeral space.
+ * \param tuple encoded tuple in
+ * MsgPack Array format.
+ * \param tuple_end end of @a tuple.
+ * \param[out] result a new tuple.
+ * \retval -1 on error.
+ * \retval 0 on success.
+ */
+int
+box_ephemeral_replace(struct space *space, const char *tuple,
+		      const char *tuple_end, box_tuple_t **result);
+
+/**
+ * Execute an DELETE request for ephemeral spaces.
+ *
+ * \param space ephemeral space.
+ * \param index_id index identifier
+ * \param key encoded key in
+ * MsgPack Array format.
+ * \param key_end the end of encoded \a key.
+ * \param[out] result an old tuple.
+ * \retval -1 on error.
+ * \retval 0 on success.
+ */
+int
+box_ephemeral_delete(struct space *space, uint32_t index_id, const char *key,
+		     const char *key_end, box_tuple_t **result);
+
+/**
+ * Execute an UPDATE request for ephemeral spaces.
+ *
+ * \param space ephemeral space.
+ * \param index_id index identifier
+ * \param key encoded key in
+ * MsgPack Array format.
+ * \param key_end the end of encoded \a key.
+ * \param ops encoded operations in
+ * MsgPack Arrat format.
+ * \param ops_end the end of encoded \a ops.
+ * \param index_base 0 if fieldnos in
+ * update operations are zero-based
+ * indexed (like C) or 1 if for one-based
+ * indexed field ids (like Lua).
+ * \param[out] result a new tuple.
+ * \retval -1 on error.
+ * \retval 0 on success.
+ */
+int
+box_ephemeral_update(struct space *space, uint32_t index_id, const char *key,
+		     const char *key_end, const char *ops, const char *ops_end,
+		     int index_base, box_tuple_t **result);
+
+/**
+ * Execute an UPSERT request for ephemeral spaces.
+ *
+ * \param space ephemeral space.
+ * \param index_id index identifier
+ * \param ops encoded operations in
+ * MsgPack Arrat format.
+ * \param ops_end the end of encoded \a ops.
+ * \param tuple encoded tuple in
+ * MsgPack Array format.
+ * \param tuple_end end of @a tuple.
+ * \param index_base 0 if fieldnos in update
+ * operations are zero-based
+ * indexed (like C) or 1 if for one-based
+ * indexed field ids (like Lua).
+ * \param[out] result a new tuple.
+ * \retval -1 on error.
+ * \retval 0 on success.
+ */
+int
+box_ephemeral_upsert(struct space *space, uint32_t index_id, const char *tuple,
+		     const char *tuple_end, const char *ops,
+		     const char *ops_end, int index_base, box_tuple_t **result);
+
+/**
  * Execute request on given space.
  *
  * \param request Request to be executed
diff --git a/src/box/memtx_space.c b/src/box/memtx_space.c
index f440951..ce169be 100644
--- a/src/box/memtx_space.c
+++ b/src/box/memtx_space.c
@@ -327,77 +327,76 @@ rollback:
 	return -1;
 }
 
-static int
-memtx_space_execute_replace(struct space *space, struct txn *txn,
-			    struct request *request, struct tuple **result)
+static inline int
+memtx_space_replace_impl(struct space *space, struct request *request,
+			 struct tuple **new_tuple, struct tuple **old_tuple,
+			 struct tuple **result)
 {
 	struct memtx_space *memtx_space = (struct memtx_space *)space;
-	struct txn_stmt *stmt = txn_current_stmt(txn);
 	enum dup_replace_mode mode = dup_replace_mode(request->type);
-	stmt->new_tuple = memtx_tuple_new(space->format, request->tuple,
-					  request->tuple_end);
-	if (stmt->new_tuple == NULL)
+	*new_tuple = memtx_tuple_new(space->format, request->tuple,
+				     request->tuple_end);
+	if (*new_tuple == NULL)
 		return -1;
-	tuple_ref(stmt->new_tuple);
-	struct tuple *old_tuple;
-	if (memtx_space->replace(space, stmt->old_tuple, stmt->new_tuple,
-				 mode, &old_tuple) != 0)
+	tuple_ref(*new_tuple);
+	struct tuple *tmp_tuple;
+	if (memtx_space->replace(space, *old_tuple, *new_tuple, mode,
+				 &tmp_tuple) != 0)
 		return -1;
-	stmt->old_tuple = old_tuple;
-	stmt->engine_savepoint = stmt;
+	*old_tuple = tmp_tuple;
 	/** The new tuple is referenced by the primary key. */
-	*result = stmt->new_tuple;
+	*result = *new_tuple;
 	return 0;
+
 }
 
-static int
-memtx_space_execute_delete(struct space *space, struct txn *txn,
-			   struct request *request, struct tuple **result)
+static inline int
+memtx_space_delete_impl(struct space *space, struct request *request,
+			struct tuple **new_tuple, struct tuple **old_tuple,
+			struct tuple **result)
 {
 	struct memtx_space *memtx_space = (struct memtx_space *)space;
-	struct txn_stmt *stmt = txn_current_stmt(txn);
 	/* Try to find the tuple by unique key. */
 	struct index *pk = index_find_unique(space, request->index_id);
 	if (pk == NULL)
 		return -1;
 	const char *key = request->key;
 	uint32_t part_count = mp_decode_array(&key);
-	if (index_get(pk, key, part_count, &stmt->old_tuple) != 0)
+	if (index_get(pk, key, part_count, old_tuple) != 0)
 		return -1;
-	struct tuple *old_tuple = NULL;
-	if (stmt->old_tuple != NULL &&
-	    memtx_space->replace(space, stmt->old_tuple, stmt->new_tuple,
-				 DUP_REPLACE_OR_INSERT, &old_tuple) != 0)
+	struct tuple *tmp_tuple = NULL;
+	if (*old_tuple != NULL &&
+	    memtx_space->replace(space, *old_tuple, *new_tuple,
+				 DUP_REPLACE_OR_INSERT, &tmp_tuple) != 0)
 		return -1;
-	stmt->old_tuple = old_tuple;
-	stmt->engine_savepoint = stmt;
-	*result = stmt->old_tuple;
+	*old_tuple = tmp_tuple;
+	*result = *old_tuple;
 	return 0;
 }
 
 static int
-memtx_space_execute_update(struct space *space, struct txn *txn,
-			   struct request *request, struct tuple **result)
+memtx_space_update_impl(struct space *space, struct request *request,
+			struct tuple **new_tuple, struct tuple **old_tuple,
+			struct tuple **result)
 {
 	struct memtx_space *memtx_space = (struct memtx_space *)space;
-	struct txn_stmt *stmt = txn_current_stmt(txn);
 	/* Try to find the tuple by unique key. */
 	struct index *pk = index_find_unique(space, request->index_id);
 	if (pk == NULL)
 		return -1;
 	const char *key = request->key;
 	uint32_t part_count = mp_decode_array(&key);
-	if (index_get(pk, key, part_count, &stmt->old_tuple) != 0)
+	if (index_get(pk, key, part_count, old_tuple) != 0)
 		return -1;
 
-	if (stmt->old_tuple == NULL) {
+	if (*old_tuple == NULL) {
 		*result = NULL;
 		return 0;
 	}
 
 	/* Update the tuple; legacy, request ops are in request->tuple */
 	uint32_t new_size = 0, bsize;
-	const char *old_data = tuple_data_range(stmt->old_tuple, &bsize);
+	const char *old_data = tuple_data_range(*old_tuple, &bsize);
 	const char *new_data =
 		tuple_update_execute(region_aligned_alloc_cb, &fiber()->gc,
 				     request->tuple, request->tuple_end,
@@ -406,28 +405,26 @@ memtx_space_execute_update(struct space *space, struct txn *txn,
 	if (new_data == NULL)
 		return -1;
 
-	stmt->new_tuple = memtx_tuple_new(space->format, new_data,
-					  new_data + new_size);
-	if (stmt->new_tuple == NULL)
+	*new_tuple = memtx_tuple_new(space->format, new_data,
+				     new_data + new_size);
+	if (*new_tuple == NULL)
 		return -1;
-	tuple_ref(stmt->new_tuple);
-	struct tuple *old_tuple = NULL;
-	if (stmt->old_tuple != NULL &&
-	    memtx_space->replace(space, stmt->old_tuple, stmt->new_tuple,
-				 DUP_REPLACE, &old_tuple) != 0)
+	tuple_ref(*new_tuple);
+	struct tuple *tmp_tuple = NULL;
+	if (*old_tuple != NULL &&
+	    memtx_space->replace(space, *old_tuple, *new_tuple,
+				 DUP_REPLACE, &tmp_tuple) != 0)
 		return -1;
-	stmt->old_tuple = old_tuple;
-	stmt->engine_savepoint = stmt;
-	*result = stmt->new_tuple;
+	*old_tuple = tmp_tuple;
+	*result = *new_tuple;
 	return 0;
 }
 
 static int
-memtx_space_execute_upsert(struct space *space, struct txn *txn,
-			   struct request *request)
+memtx_space_upsert_impl(struct space *space, struct request *request,
+			struct tuple **new_tuple, struct tuple **old_tuple)
 {
 	struct memtx_space *memtx_space = (struct memtx_space *)space;
-	struct txn_stmt *stmt = txn_current_stmt(txn);
 	/*
 	 * Check all tuple fields: we should produce an error on
 	 * malformed tuple even if upsert turns into an update.
@@ -450,10 +447,10 @@ memtx_space_execute_upsert(struct space *space, struct txn *txn,
 	mp_decode_array(&key);
 
 	/* Try to find the tuple by primary key. */
-	if (index_get(index, key, part_count, &stmt->old_tuple) != 0)
+	if (index_get(index, key, part_count, old_tuple) != 0)
 		return -1;
 
-	if (stmt->old_tuple == NULL) {
+	if (*old_tuple == NULL) {
 		/**
 		 * Old tuple was not found. A write optimized
 		 * engine may only know this after commit, so
@@ -470,21 +467,19 @@ memtx_space_execute_upsert(struct space *space, struct txn *txn,
 		 *   we get it here, it's also OK to throw it
 		 * @sa https://github.com/tarantool/tarantool/issues/1156
 		 */
-		if (tuple_update_check_ops(region_aligned_alloc_cb, &fiber()->gc,
-				       request->ops, request->ops_end,
-				       request->index_base)) {
+		if (tuple_update_check_ops(region_aligned_alloc_cb,
+					   &fiber()->gc, request->ops,
+					   request->ops_end,
+					   request->index_base))
 			return -1;
-		}
-		stmt->new_tuple = memtx_tuple_new(space->format,
-						  request->tuple,
-						  request->tuple_end);
-		if (stmt->new_tuple == NULL)
+		*new_tuple = memtx_tuple_new(space->format, request->tuple,
+					     request->tuple_end);
+		if (*new_tuple == NULL)
 			return -1;
-		tuple_ref(stmt->new_tuple);
+		tuple_ref(*new_tuple);
 	} else {
 		uint32_t new_size = 0, bsize;
-		const char *old_data = tuple_data_range(stmt->old_tuple,
-							&bsize);
+		const char *old_data = tuple_data_range(*old_tuple, &bsize);
 		/*
 		 * Update the tuple.
 		 * tuple_upsert_execute() fails on totally wrong
@@ -502,24 +497,24 @@ memtx_space_execute_upsert(struct space *space, struct txn *txn,
 		if (new_data == NULL)
 			return -1;
 
-		stmt->new_tuple = memtx_tuple_new(space->format, new_data,
-						  new_data + new_size);
-		if (stmt->new_tuple == NULL)
+		*new_tuple = memtx_tuple_new(space->format, new_data,
+					     new_data + new_size);
+		if (*new_tuple == NULL)
 			return -1;
-		tuple_ref(stmt->new_tuple);
+		tuple_ref(*new_tuple);
 
 		struct index *pk = space->index[0];
 		if (!key_update_can_be_skipped(pk->def->key_def->column_mask,
 					       column_mask) &&
-		    tuple_compare(stmt->old_tuple, stmt->new_tuple,
+		    tuple_compare(*old_tuple, *new_tuple,
 				  pk->def->key_def) != 0) {
 			/* Primary key is changed: log error and do nothing. */
 			diag_set(ClientError, ER_CANT_UPDATE_PRIMARY_KEY,
 				 pk->def->name, space_name(space));
 			diag_log();
-			tuple_unref(stmt->new_tuple);
-			stmt->old_tuple = NULL;
-			stmt->new_tuple = NULL;
+			tuple_unref(*new_tuple);
+			*old_tuple = NULL;
+			*new_tuple = NULL;
 		}
 	}
 	/*
@@ -528,77 +523,153 @@ memtx_space_execute_upsert(struct space *space, struct txn *txn,
 	 * we checked this case explicitly and skipped the upsert
 	 * above.
 	 */
-	struct tuple *old_tuple = NULL;
-	if (stmt->new_tuple != NULL &&
-	    memtx_space->replace(space, stmt->old_tuple, stmt->new_tuple,
-				 DUP_REPLACE_OR_INSERT, &old_tuple) != 0)
+	struct tuple *tmp_tuple = NULL;
+	if (*new_tuple != NULL &&
+	    memtx_space->replace(space, *old_tuple, *new_tuple,
+				 DUP_REPLACE_OR_INSERT, &tmp_tuple) != 0)
+		return -1;
+	*old_tuple = tmp_tuple;
+	return 0;
+}
+
+static int
+memtx_space_execute_replace(struct space *space, struct txn *txn,
+			    struct request *request, struct tuple **result)
+{
+	struct txn_stmt *stmt = txn_current_stmt(txn);
+	if (memtx_space_replace_impl(space, request, &stmt->new_tuple,
+				     &stmt->old_tuple, result) != 0)
+		return -1;
+	stmt->engine_savepoint = stmt;
+	return 0;
+}
+
+static int
+memtx_space_execute_delete(struct space *space, struct txn *txn,
+			   struct request *request, struct tuple **result)
+{
+	struct txn_stmt *stmt = txn_current_stmt(txn);
+	if (memtx_space_delete_impl(space, request, &stmt->new_tuple,
+				    &stmt->old_tuple, result) != 0)
+		return -1;
+	stmt->engine_savepoint = stmt;
+	return 0;
+}
+
+static int
+memtx_space_execute_update(struct space *space, struct txn *txn,
+			   struct request *request, struct tuple **result)
+{
+	struct txn_stmt *stmt = txn_current_stmt(txn);
+	if (memtx_space_update_impl(space, request, &stmt->new_tuple,
+				    &stmt->old_tuple, result) != 0)
+		return -1;
+	stmt->engine_savepoint = stmt;
+	return 0;
+}
+
+static int
+memtx_space_execute_upsert(struct space *space, struct txn *txn,
+			   struct request *request)
+{
+	struct txn_stmt *stmt = txn_current_stmt(txn);
+	if (memtx_space_upsert_impl(space, request, &stmt->new_tuple,
+				    &stmt->old_tuple) != 0)
 		return -1;
-	stmt->old_tuple = old_tuple;
 	stmt->engine_savepoint = stmt;
 	/* Return nothing: UPSERT does not return data. */
 	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.
+ * Executes INSERT and REPLACE
+ * operations for ephemeral spaces.
+ *
+ * This function isn't involved in
+ * any transaction routine.
  */
 static int
-memtx_space_ephemeral_replace(struct space *space, const char *tuple,
-				      const char *tuple_end)
+memtx_space_ephemeral_replace(struct space *space, struct txn *txn,
+			      struct request *request, struct tuple **result)
 {
-	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);
+	assert(txn == NULL);
+	(void)txn;
+	struct tuple *new_tuple = NULL;
 	struct tuple *old_tuple = NULL;
-	if (memtx_space->replace(space, old_tuple, new_tuple,
-				 DUP_REPLACE_OR_INSERT, &old_tuple) != 0) {
+	int rc = memtx_space_replace_impl(space, request, &new_tuple,
+					  &old_tuple, result);
+	if (rc && new_tuple != NULL)
 		tuple_unref(new_tuple);
+	if (rc != 0)
 		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.
+ * Executes DELETE operation
+ * for ephemeral space.
  *
- * Similarly to ephemeral replace function,
- * it isn't involved in any transaction routine.
+ * This function isn't involved in
+ * any transaction routine.
  */
 static int
-memtx_space_ephemeral_delete(struct space *space, const char *key)
+memtx_space_ephemeral_delete(struct space *space, struct txn *txn,
+			     struct request *request, struct tuple **result)
 {
-	struct memtx_space *memtx_space = (struct memtx_space *)space;
-	struct index *primary_index = space_index(space, 0 /* primary index*/);
-	if (primary_index == NULL)
+	assert(txn == NULL);
+	(void)txn;
+	struct tuple *new_tuple = NULL;
+	struct tuple *old_tuple = NULL;
+	if (memtx_space_delete_impl(space, request, &new_tuple, &old_tuple,
+				    result) != 0)
 		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 0;
+}
+
+/**
+ * Executes UPDATE operation
+ * for ephemeral space.
+ *
+ * This function isn't involved in
+ * any transaction routine.
+ */
+static int
+memtx_space_ephemeral_update(struct space *space, struct txn *txn,
+			     struct request *request, struct tuple **result)
+{
+	assert(txn == NULL);
+	(void)txn;
+	struct tuple *new_tuple = NULL;
+	struct tuple *old_tuple = NULL;
+	int rc = memtx_space_update_impl(space, request, &new_tuple,
+					 &old_tuple, result);
+	if (rc != 0 && new_tuple != NULL)
+		tuple_unref(new_tuple);
+	if (rc != 0)
 		return -1;
-	if (old_tuple != NULL &&
-	    memtx_space->replace(space, old_tuple, NULL,
-				 DUP_REPLACE, &old_tuple) != 0)
+	return 0;
+}
+
+/**
+ * Executes UPSERT operation
+ * for ephemral space.
+ *
+ * This function isn't involved in
+ * any transaction routine.
+ */
+static int
+memtx_space_ephemeral_upsert(struct space *space, struct txn *txn,
+			     struct request *request)
+{
+	assert(txn == NULL);
+	(void)txn;
+	struct tuple *old_tuple = NULL;
+	struct tuple *new_tuple = NULL;
+	if (memtx_space_upsert_impl(space, request, &new_tuple,
+				    &old_tuple) != 0)
 		return -1;
-	tuple_unref(old_tuple);
 	return 0;
 }
 
@@ -839,9 +910,14 @@ memtx_init_system_space(struct space *space)
 }
 
 static void
-memtx_init_ephemeral_space(struct space *space)
+memtx_init_ephemeral_space(struct space *space);
+
+static void
+memtx_init_unsupported_space(struct space *space)
 {
-	memtx_space_add_primary_key(space);
+	(void)space;
+	diag_set(ClientError, ER_UNSUPPORTED, space_name(space),
+		 "init_ephemeral_space");
 }
 
 static int
@@ -940,8 +1016,6 @@ 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,
@@ -954,6 +1028,33 @@ static const struct space_vtab memtx_space_vtab = {
 	/* .prepare_alter = */ memtx_space_prepare_alter,
 };
 
+static const struct space_vtab memtx_space_ephemeral_vtab = {
+	/* .destroy = */ memtx_space_destroy,
+	/* .bsize = */ memtx_space_bsize,
+	/* .apply_initial_join_row = */ memtx_space_apply_initial_join_row,
+	/* .execute_replace = */ memtx_space_ephemeral_replace,
+	/* .execute_delete = */ memtx_space_ephemeral_delete,
+	/* .execute_update = */ memtx_space_ephemeral_update,
+	/* .execute_upsert = */ memtx_space_ephemeral_upsert,
+	/* .init_system_space = */ memtx_init_system_space,
+	/* .init_ephemeral_space = */ memtx_init_unsupported_space,
+	/* .check_index_def = */ memtx_space_check_index_def,
+	/* .create_index = */ memtx_space_create_index,
+	/* .add_primary_key = */ memtx_space_add_primary_key,
+	/* .drop_primary_key = */ memtx_space_drop_primary_key,
+	/* .check_format  = */ memtx_space_check_format,
+	/* .build_index = */ memtx_space_build_index,
+	/* .swap_index = */ generic_space_swap_index,
+	/* .prepare_alter = */ memtx_space_prepare_alter,
+};
+
+static void
+memtx_init_ephemeral_space(struct space *space)
+{
+	space->vtab = &memtx_space_ephemeral_vtab;
+	memtx_space_add_primary_key(space);
+}
+
 struct space *
 memtx_space_new(struct memtx_engine *memtx,
 		struct space_def *def, struct rlist *key_list)
diff --git a/src/box/space.h b/src/box/space.h
index adf06b7..60fa603 100644
--- a/src/box/space.h
+++ b/src/box/space.h
@@ -67,10 +67,6 @@ 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.
@@ -310,19 +306,6 @@ int
 space_execute_dml(struct space *space, struct txn *txn,
 		  struct request *request, struct tuple **result);
 
-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);
-}
-
 /**
  * Generic implementation of space_vtab::swap_index
  * that simply swaps the two indexes in index maps.
diff --git a/src/box/sql.c b/src/box/sql.c
index d2cc0a9..4077890 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -451,7 +451,13 @@ int tarantoolSqlite3EphemeralInsert(struct space *space, const char *tuple,
 {
 	assert(space != NULL);
 	mp_tuple_assert(tuple, tuple_end);
-	if (space_ephemeral_replace(space, tuple, tuple_end) != 0)
+	struct request request;
+	memset(&request, 0, sizeof(request));
+	request.type = IPROTO_REPLACE;
+	request.tuple = tuple;
+	request.tuple_end = tuple_end;
+	struct tuple *result;
+	if (space_execute_dml(space, NULL, &request, &result) != 0)
 		return SQL_TARANTOOL_INSERT_FAIL;
 	return SQLITE_OK;
 }
@@ -516,11 +522,20 @@ int tarantoolSqlite3EphemeralDelete(BtCursor *pCur)
 	if (key == NULL)
 		return SQL_TARANTOOL_DELETE_FAIL;
 
-	int rc = space_ephemeral_delete(pCur->space, key);
-	if (rc != 0) {
+	mp_tuple_assert(key, key + key_size);
+	struct request request;
+	struct tuple *result;
+	memset(&request, 0, sizeof(request));
+	request.type = IPROTO_DELETE;
+	request.key = key;
+	request.key_end = key + key_size;
+
+	if (space_execute_dml(pCur->space, NULL, &request, &result) != 0) {
 		diag_log();
 		return SQL_TARANTOOL_DELETE_FAIL;
 	}
+	if (result != NULL)
+		box_tuple_unref(result);
 	return SQLITE_OK;
 }
 
@@ -596,14 +611,24 @@ int tarantoolSqlite3EphemeralClearTable(BtCursor *pCur)
 	struct tuple *tuple;
 	char *key;
 	uint32_t  key_size;
+	struct request request;
+	struct tuple *result;
+	memset(&request, 0, sizeof(request));
+	request.type = IPROTO_DELETE;
 
 	while (iterator_next(it, &tuple) == 0 && tuple != NULL) {
 		key = tuple_extract_key(tuple, it->index->def->key_def,
 					&key_size);
-		if (space_ephemeral_delete(pCur->space, key) != 0) {
+		mp_tuple_assert(key, key + key_size);
+		request.key = key;
+		request.key_end = key + key_size;
+		if (space_execute_dml(pCur->space, NULL, &request,
+				      &result) != 0) {
 			iterator_delete(it);
 			return SQL_TARANTOOL_DELETE_FAIL;
 		}
+		if (result != NULL)
+			box_tuple_unref(result);
 	}
 	iterator_delete(it);
 
diff --git a/src/box/sysview_engine.c b/src/box/sysview_engine.c
index bd9432a..3067175 100644
--- a/src/box/sysview_engine.c
+++ b/src/box/sysview_engine.c
@@ -99,26 +99,6 @@ 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)
 {
@@ -197,8 +177,6 @@ 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 10ec3ca..d089f68 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -2325,26 +2325,6 @@ 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)
 {
@@ -4494,8 +4474,6 @@ 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,
-- 
2.7.4





More information about the Tarantool-patches mailing list