From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Vladimir Davydov Subject: [PATCH v2 7/8] vinyl: factor out vy_check_is_unique_secondary Date: Sun, 27 May 2018 22:05:55 +0300 Message-Id: <089a67b8077d0fa67da66c4868e0755f3aa01973.1527446023.git.vdavydov.dev@gmail.com> In-Reply-To: References: In-Reply-To: References: To: kostja@tarantool.org Cc: tarantool-patches@freelists.org List-ID: 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