[PATCH v2 7/8] vinyl: factor out vy_check_is_unique_secondary
Vladimir Davydov
vdavydov.dev at gmail.com
Sun May 27 22:05:55 MSK 2018
We need to check unique constraint when building a new index. So let's
factor out this helper function and pass space_name, index_name, and
read view to it explicitly (because index_name_by_id isn't going to work
for an index that is under construction and there's no tx when we are
building a new index). Suggested by @Gerold103.
Needed for #1653
---
src/box/vinyl.c | 81 +++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 56 insertions(+), 25 deletions(-)
diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index 4d670328..41ffa42c 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -1353,7 +1353,9 @@ vy_lsm_get(struct vy_lsm *lsm, struct vy_tx *tx,
* a duplicate key error in the diagnostics area.
* @param env Vinyl environment.
* @param tx Current transaction.
- * @param space Target space.
+ * @param rv Read view.
+ * @param space_name Space name.
+ * @param index_name Index name.
* @param lsm LSM tree in which to search.
* @param key Key statement.
*
@@ -1361,7 +1363,9 @@ vy_lsm_get(struct vy_lsm *lsm, struct vy_tx *tx,
* @retval -1 Memory error or the key is found.
*/
static inline int
-vy_check_is_unique(struct vy_env *env, struct vy_tx *tx, struct space *space,
+vy_check_is_unique(struct vy_env *env, struct vy_tx *tx,
+ const struct vy_read_view **rv,
+ const char *space_name, const char *index_name,
struct vy_lsm *lsm, struct tuple *key)
{
struct tuple *found;
@@ -1371,20 +1375,57 @@ vy_check_is_unique(struct vy_env *env, struct vy_tx *tx, struct space *space,
*/
if (env->status != VINYL_ONLINE)
return 0;
- if (vy_lsm_get(lsm, tx, vy_tx_read_view(tx), key, &found))
+ if (vy_lsm_get(lsm, tx, rv, key, &found))
return -1;
if (found) {
tuple_unref(found);
diag_set(ClientError, ER_TUPLE_FOUND,
- index_name_by_id(space, lsm->index_id),
- space_name(space));
+ index_name, space_name);
return -1;
}
return 0;
}
/**
+ * Check if insertion of a new tuple violates unique constraint
+ * of a secondary index.
+ * @param env Vinyl environment.
+ * @param tx Current transaction.
+ * @param rv Read view.
+ * @param space_name Space name.
+ * @param index_name Index name.
+ * @param lsm LSM tree corresponding to the index.
+ * @param stmt New tuple.
+ *
+ * @retval 0 Success, unique constraint is satisfied.
+ * @retval -1 Duplicate is found or read error occurred.
+ */
+static int
+vy_check_is_unique_secondary(struct vy_env *env, struct vy_tx *tx,
+ const struct vy_read_view **rv,
+ const char *space_name, const char *index_name,
+ struct vy_lsm *lsm, const struct tuple *stmt)
+{
+ assert(lsm->index_id > 0);
+ struct key_def *def = lsm->key_def;
+ if (lsm->check_is_unique &&
+ !key_update_can_be_skipped(def->column_mask,
+ vy_stmt_column_mask(stmt)) &&
+ (!def->is_nullable || !vy_tuple_key_contains_null(stmt, def))) {
+ struct tuple *key = vy_stmt_extract_key(stmt, def,
+ lsm->env->key_format);
+ if (key == NULL)
+ return -1;
+ int rc = vy_check_is_unique(env, tx, rv, space_name,
+ index_name, lsm, key);
+ tuple_unref(key);
+ return rc;
+ }
+ return 0;
+}
+
+/**
* Insert a tuple in a primary index LSM tree.
* @param env Vinyl environment.
* @param tx Current transaction.
@@ -1407,7 +1448,9 @@ vy_insert_primary(struct vy_env *env, struct vy_tx *tx, struct space *space,
* conflict with existing tuples.
*/
if (pk->check_is_unique &&
- vy_check_is_unique(env, tx, space, pk, stmt) != 0)
+ vy_check_is_unique(env, tx, vy_tx_read_view(tx), space_name(space),
+ index_name_by_id(space, pk->index_id),
+ pk, stmt) != 0)
return -1;
return vy_tx_set(tx, pk, stmt);
}
@@ -1431,25 +1474,13 @@ vy_insert_secondary(struct vy_env *env, struct vy_tx *tx, struct space *space,
vy_stmt_type(stmt) == IPROTO_REPLACE);
assert(tx != NULL && tx->state == VINYL_TX_READY);
assert(lsm->index_id > 0);
- /*
- * If the index is unique then the new tuple must not
- * conflict with existing tuples. If the index is not
- * unique a conflict is impossible.
- */
- if (lsm->check_is_unique &&
- !key_update_can_be_skipped(lsm->key_def->column_mask,
- vy_stmt_column_mask(stmt)) &&
- (!lsm->key_def->is_nullable ||
- !vy_tuple_key_contains_null(stmt, lsm->key_def))) {
- struct tuple *key = vy_stmt_extract_key(stmt, lsm->key_def,
- lsm->env->key_format);
- if (key == NULL)
- return -1;
- int rc = vy_check_is_unique(env, tx, space, lsm, key);
- tuple_unref(key);
- if (rc != 0)
- return -1;
- }
+
+ if (vy_check_is_unique_secondary(env, tx, vy_tx_read_view(tx),
+ space_name(space),
+ index_name_by_id(space, lsm->index_id),
+ lsm, stmt) != 0)
+ return -1;
+
/*
* We must always append the statement to transaction write set
* of each LSM tree, even if operation itself does not update
--
2.11.0
More information about the Tarantool-patches
mailing list