From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> To: tarantool-patches@freelists.org, Kirill Shcherbatov <kshcherbatov@tarantool.org> Subject: [tarantool-patches] Re: [PATCH v5 4/6] schema: add new system space for CHECK constraints Date: Sun, 26 May 2019 15:06:46 +0300 [thread overview] Message-ID: <c48a4885-faa3-77b0-f2e8-69c4e24a43f9@tarantool.org> (raw) In-Reply-To: <788556b70e154103ed1f6131db7ee1f8cd687848.1558605591.git.kshcherbatov@tarantool.org> Thanks for the patch! See 12 comments below. > @@ -1387,6 +1377,79 @@ UpdateSchemaVersion::alter(struct alter_space *alter) > ++schema_version; > } > > +/** > + * As ck_constraint object depends on space_def we must rebuild > + * all ck constraints on space alter. > + * > + * To perform it transactionally, we create a list of new ck > + * constraints objects in ::prepare method that is fault-tolerant. > + * Finally in ::alter or ::rollback methods we only swap thouse 1. 'thouse' word does not exist, it is clearly visible with a spell checker, which usually highlights unknown words. > + * lists securely. > + */ > +class RebuildCkConstraints: public AlterSpaceOp > +{ > + void space_swap_ck_constraint(struct space *old_space, > + struct space *new_space); > +public: > + RebuildCkConstraints(struct alter_space *alter) : AlterSpaceOp(alter), > + ck_constraint(RLIST_HEAD_INITIALIZER(ck_constraint)) {} > + struct rlist ck_constraint; > + virtual void prepare(struct alter_space *alter); > + virtual void alter(struct alter_space *alter); > + virtual void rollback(struct alter_space *alter); > + virtual ~RebuildCkConstraints(); > +}; > @@ -4040,6 +4111,176 @@ on_replace_dd_fk_constraint(struct trigger * /* trigger*/, void *event) > + > +/** A trigger invoked on replace in the _ck_constraint space. */ > +static void > +on_replace_dd_ck_constraint(struct trigger * /* trigger*/, void *event) > +{ > + struct txn *txn = (struct txn *) event; > + txn_check_singlestatement_xc(txn, "Space _ck_constraint"); > + struct txn_stmt *stmt = txn_current_stmt(txn); > + struct tuple *old_tuple = stmt->old_tuple; > + struct tuple *new_tuple = stmt->new_tuple; > + uint32_t space_id = > + tuple_field_u32_xc(old_tuple != NULL ? old_tuple : new_tuple, > + BOX_CK_CONSTRAINT_FIELD_SPACE_ID); > + struct space *space = space_cache_find_xc(space_id); > + struct trigger *on_rollback = > + txn_alter_trigger_new(on_replace_ck_constraint_rollback, NULL); > + struct trigger *on_commit = > + txn_alter_trigger_new(on_replace_ck_constraint_commit, NULL); > + > + if (new_tuple != NULL) { > + bool is_deferred = > + tuple_field_bool_xc(new_tuple, > + BOX_CK_CONSTRAINT_FIELD_DEFERRED); > + if (is_deferred) { > + tnt_raise(ClientError, ER_UNSUPPORTED, "Tarantool", > + "deferred ck constraints"); > + } > + /* Create or replace check constraint. */ > + struct ck_constraint_def *ck_def = > + ck_constraint_def_new_from_tuple(new_tuple); > + auto ck_guard = make_scoped_guard([=] { free(ck_def); }); 2. Please, implement and use ck_constraint_def_delete. Free() will leak, when ck_constraint will become more complex. > + /* > + * FIXME: Ck constraint creation on non-empty > + * space must be implemented as preparatory > + * step for ALTER SPACE ADD CONSTRAINT feature. > + */ > + struct index *pk = space_index(space, 0); > + if (pk != NULL && index_size(pk) > 0) { > + tnt_raise(ClientError, ER_CREATE_CK_CONSTRAINT, > + ck_def->name, > + "referencing space must be empty"); > + } > + struct ck_constraint *new_ck_constraint = > + ck_constraint_new(ck_def, space->def); > + if (new_ck_constraint == NULL) > + diag_raise(); > + ck_guard.is_active = false; > + const char *name = new_ck_constraint->def->name; > + struct ck_constraint *old_ck_constraint = > + space_ck_constraint_by_name(space, name, strlen(name)); > + if (old_ck_constraint != NULL) > + rlist_del_entry(old_ck_constraint, link); > + rlist_add_entry(&space->ck_constraint, new_ck_constraint, link); > + on_commit->data = old_tuple == NULL ? new_ck_constraint : > + old_ck_constraint; > + on_rollback->data = on_commit->data; > diff --git a/src/box/ck_constraint.c b/src/box/ck_constraint.c > new file mode 100644 > index 000000000..c74687b31 > --- /dev/null > +++ b/src/box/ck_constraint.c > + > +void > +ck_constraint_delete(struct ck_constraint *ck_constraint) > +{ > + sql_expr_delete(sql_get(), ck_constraint->expr, false); > + free(ck_constraint->def); 3. The same. Use ck_constraint_def_delete. > + TRASH(ck_constraint); > + free(ck_constraint); > +} > diff --git a/src/box/ck_constraint.h b/src/box/ck_constraint.h > new file mode 100644 > index 000000000..e20203bb5 > --- /dev/null > +++ b/src/box/ck_constraint.h > + > +/** > + * Calculate check constraint definition memory size and fields > + * offsets for given arguments. > + * > + * Alongside with struct ck_constraint_def itself, we reserve > + * memory for string containing its name and expression string. > + * > + * Memory layout: > + * +-----------------------------+ <- Allocated memory starts here > + * | struct ck_constraint_def | > + * |-----------------------------| > + * | name + \0 | > + * |-----------------------------| > + * | expr_str + \0 | > + * +-----------------------------+ > + * > + * @param name_len The length of the name. > + * @param expr_str_len The length of the expr_str. > + * @param[out] name_offset The offset of the name string. > + * @param[out] expr_str_offset The offset of the expr_str string. > + * @retval The size of the ck constraint definition object for > + * given parameters. 4. I said it probably 2-3 times, but you still ignore. @retval takes one parameter, @return take 0 parameters. Here you wrote, that returned value is 'The'. > + */ > +static inline uint32_t > +ck_constraint_def_sizeof(uint32_t name_len, uint32_t expr_str_len, > + uint32_t *name_offset, uint32_t *expr_str_offset) > +{ > + *name_offset = sizeof(struct ck_constraint_def); > + *expr_str_offset = *name_offset + name_len + 1; > + return *expr_str_offset + expr_str_len + 1; > +} > diff --git a/src/box/schema_def.h b/src/box/schema_def.h > index dea3fad19..317e6b51f 100644 > --- a/src/box/schema_def.h > +++ b/src/box/schema_def.h > @@ -108,6 +108,8 @@ enum { > BOX_SPACE_SEQUENCE_ID = 340, > /** Space id of _fk_constraint. */ > BOX_FK_CONSTRAINT_ID = 356, > + /** Space id of _ck_contraint. */ > + BOX_CK_CONSTRAINT_ID = 357, 5. Please, leave a gap after BOX_FK_CONSTRAINT_ID. We keep gaps to be able in future to add a view space, and to choose recovery order. Gap is typically 7 unused IDs. The new ID should be 364. > /** End of the reserved range of system spaces. */ > BOX_SYSTEM_ID_MAX = 511, > BOX_ID_NIL = 2147483647 > diff --git a/src/box/sql/build.c b/src/box/sql/build.c > index 91b977de2..a3b11531f 100644 > --- a/src/box/sql/build.c > +++ b/src/box/sql/build.c > @@ -638,40 +640,116 @@ primary_key_exit: > return; > } > > +/** > + * Prepare a 0-terminated string in the wptr memory buffer that > + * does not contain a sequence of more than one whatespace > + * character. Routine enforces ' ' (space) as whitespace > + * delimiter. When character ' or " was met, the sting is copied > + * without any changes until the next (corres) ' or " . 6. What is 'corres'? > + * The wptr buffer is expected to have str_len + 1 bytes > + * (this is the expected scenario where no extra whitespace > + * characters preset in the source string). 7. What is 'characters preset'? > + * @param wptr The destination memory buffer of size > + * @a str_len + 1. > + * @param str The source string to be copied. > + * @param str_len The source string @a str length. > + */ > +static void > +trim_space_snprintf(char *wptr, const char *str, uint32_t str_len) > @@ -1416,6 +1529,37 @@ vdbe_emit_fk_constraint_drop(struct Parse *parse_context, char *constraint_name, > sqlReleaseTempRange(parse_context, key_reg, 3); > } > > +/** > + * Generate VDBE program to remove entry from _ck_constraint space. > + * > + * @param parser Parsing context. > + * @param ck_name Name of CK constraint to be dropped. > + * @param child_id Id of table which constraint belongs to. 8. There is no parameter 'child_id'. > + */ > +static void > +vdbe_emit_ck_constraint_drop(struct Parse *parser, const char *ck_name, > + uint32_t space_id) > diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y > index f241b8d52..e93dfe751 100644 > --- a/src/box/sql/parse.y > +++ b/src/box/sql/parse.y > @@ -297,7 +297,7 @@ ccons ::= check_constraint_def . > > check_constraint_def ::= cconsname(N) CHECK LP expr(X) RP. { > create_ck_def_init(&pParse->create_ck_def, &N, &X); > - sql_add_check_constraint(pParse); > + sql_create_check_contraint(pParse); 9. What was a motivation of this rename? As I understand, we can add many CHECK constraints in one CREATE TABLE. We do not 'create' one single CHECK, we add multiple ones. Please, keep the old name. > } > > ccons ::= cconsname(N) REFERENCES nm(T) eidlist_opt(TA) matcharg(M) refargs(R). { > diff --git a/test/sql/checks.result b/test/sql/checks.result > index f7cddec43..5f0098e23 100644 > --- a/test/sql/checks.result > +++ b/test/sql/checks.result > @@ -30,89 +32,216 @@ t = {513, 1, 'test', 'memtx', 0, opts, format} > -s = box.space._space:insert(t) > +-- Pass integer instead of expression. > +box.space._ck_constraint:insert({513, 'CK_CONSTRAINT_01', false, 'SQL', 666}) > +--- > +- error: 'Tuple field 5 type does not match one required by operation: expected string' > +... > +-- Defered CK constraints are not supported. 10. 'Defered' word does not exist, use 'deferred'. 'Unexistent' word does not exist as well. Non-existent is better. > +box.space._ck_constraint:insert({513, 'CK_CONSTRAINT_01', true, 'SQL', 'X<5'}) > +--- > +- error: Tarantool does not support deferred ck constraints > +... > +-- The only supperted language is SQL. 11. 'Supperted' word does not exist. > +box.space._ck_constraint:insert({513, 'CK_CONSTRAINT_01', false, 'LUA', 'X<5'}) > +--- > +- error: Unsupported language 'LUA' specified for function 'CK_CONSTRAINT_01' > +... > ... > +--- > +... > +box.execute("CREATE TABLE T2(ID INT PRIMARY KEY, CONSTRAINT CK1 CHECK(ID > 0), CONSTRAINT CK1 CHECK(ID < 0))") > +--- > +- error: Duplicate key exists in unique index 'primary' in space '_ck_constraint' 12. The error is not ok. It should not expose any system details like _ck_constraint space. Please, check duplicate names before an insertion. > +... > +box.space._ck_constraint:select() > +--- > +- [] > ...
next prev parent reply other threads:[~2019-05-26 12:06 UTC|newest] Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-05-23 10:19 [tarantool-patches] [PATCH v5 0/6] box: run checks on insertions in LUA spaces Kirill Shcherbatov 2019-05-23 10:19 ` [tarantool-patches] [PATCH v5 1/6] sql: introduce a new method to bind a pointer Kirill Shcherbatov 2019-05-23 10:19 ` [tarantool-patches] [PATCH v5 2/6] sql: refactor OP_Column vdbe instruction Kirill Shcherbatov 2019-05-23 10:19 ` [tarantool-patches] [PATCH v5 3/6] sql: introduce tuple_fetcher class Kirill Shcherbatov 2019-05-26 12:05 ` [tarantool-patches] " Vladislav Shpilevoy 2019-05-31 13:45 ` Kirill Shcherbatov 2019-05-31 19:45 ` Konstantin Osipov 2019-05-31 19:50 ` Kirill Shcherbatov 2019-05-31 22:36 ` Vladislav Shpilevoy 2019-06-01 5:45 ` Konstantin Osipov 2019-06-02 18:50 ` Kirill Shcherbatov 2019-06-03 21:15 ` Vladislav Shpilevoy 2019-06-05 6:47 ` Konstantin Osipov 2019-06-05 6:48 ` Konstantin Osipov 2019-05-23 10:19 ` [tarantool-patches] [PATCH v5 4/6] schema: add new system space for CHECK constraints Kirill Shcherbatov 2019-05-26 12:06 ` Vladislav Shpilevoy [this message] 2019-05-26 13:31 ` [tarantool-patches] " n.pettik 2019-05-26 13:32 ` Vladislav Shpilevoy 2019-05-31 13:45 ` Kirill Shcherbatov 2019-06-03 21:15 ` Vladislav Shpilevoy 2019-05-23 10:19 ` [tarantool-patches] [PATCH v5 5/6] box: run check constraint tests on space alter Kirill Shcherbatov 2019-05-26 12:07 ` [tarantool-patches] " Vladislav Shpilevoy 2019-05-31 13:45 ` Kirill Shcherbatov 2019-06-03 21:15 ` Vladislav Shpilevoy 2019-05-23 10:19 ` [tarantool-patches] [PATCH v5 6/6] box: user-friendly interface to manage ck constraints Kirill Shcherbatov 2019-05-26 12:07 ` [tarantool-patches] " Vladislav Shpilevoy 2019-05-31 13:45 ` Kirill Shcherbatov 2019-06-03 21:15 ` [tarantool-patches] Re: [PATCH v5 0/6] box: run checks on insertions in LUA spaces Vladislav Shpilevoy 2019-06-04 7:21 ` Kirill Shcherbatov 2019-06-04 18:59 ` Vladislav Shpilevoy 2019-06-06 11:58 ` Kirill Yukhin
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=c48a4885-faa3-77b0-f2e8-69c4e24a43f9@tarantool.org \ --to=v.shpilevoy@tarantool.org \ --cc=kshcherbatov@tarantool.org \ --cc=tarantool-patches@freelists.org \ --subject='[tarantool-patches] Re: [PATCH v5 4/6] schema: add new system space for CHECK constraints' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox