Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@freelists.org,
	Kirill Shcherbatov <kshcherbatov@tarantool.org>,
	korablev@tarantool.org
Subject: [tarantool-patches] Re: [PATCH v2 5/9] schema: add new system space for CHECK constraints
Date: Fri, 22 Mar 2019 12:29:02 +0300	[thread overview]
Message-ID: <e025b179-6a45-7c42-1550-9dfd31f40118@tarantool.org> (raw)
In-Reply-To: <186b109d1f6049b1413fe0cdded43e5fad29a895.1548838034.git.kshcherbatov@tarantool.org>

Thanks for the patch! See 9 comments below. It is not a
complete review, because Kirill Y. said, that the patchset
is not finished (then why is it in the patches mailing list?).

On 30/01/2019 11:59, Kirill Shcherbatov wrote:
> This patch introduces new system space to persist check
> constraints. Format of the space:
> 
> _ck_constraint (space id = 357)
> [<constraint name> STR, <space id> UINT, <expression string>STR]
> 
> CK constraint is local to space, so every pair <CK name, space id>
> is unique (and it is PK in _ck_constraint space).
> 
> After insertion into this space, a new instance describing check
> constraint is created. Check constraint held Expr tree.

1. held -> hold

> Until space features check constraints, it isn't allowed to
> be dropped.

2. Sorry, the sentence is invalid. In Russian you said literally
this: "Пока спейс не поддерживает check ограничение, он не может
быть удален". But why? If a space does not have a check, it is ok
to drop the space. Probably you thought that 'Until' == 'While'?
Vice versa, rather 'While' == 'Until not'.

> The :drop() space method firstly deletes all check
> constraints and than removes entry from _space.

3. than -> then.

My piece of advice - go to English courses. Fortunately, Kirill
and Kostja appreciate such activity and can reimburse your
expenses (likely that they will).

> 
> We use BuildCkConstraints Alter operation object because space
> definition may be modified and check AST must be recreated.
> 
> Needed for #3691
> ---
> diff --git a/src/box/alter.cc b/src/box/alter.cc
> index eff3524cf..3ba604ca6 100644
> --- a/src/box/alter.cc
> +++ b/src/box/alter.cc
> @@ -1351,6 +1341,56 @@ TruncateIndex::commit(struct alter_space *alter, int64_t signature)
>   	index_commit_create(new_index, signature);
>   }
>   
> +/** BuildCkConstraints - rebuild ck_constraints on alter. */

4. Instead of the comments like you wrote below, it would be
much better to focus your efforts on the code like this. Here
I do not understand what is happening, especially in prepare().

> +class BuildCkConstraints: public AlterSpaceOp
> +{
> +public:
> +	BuildCkConstraints(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 ~BuildCkConstraints();
> +};
> +
> +void
> +BuildCkConstraints::prepare(struct alter_space *alter)
> +{
> +	struct ck_constraint *old_ck_constraint;
> +	rlist_foreach_entry(old_ck_constraint, &alter->old_space->ck_constraint,
> +			    link) {
> +		struct ck_constraint *new_ck_constraint =
> +			ck_constraint_new(old_ck_constraint->def,
> +					  alter->new_space->def);
> +		if (new_ck_constraint == NULL)
> +			diag_raise();
> +		rlist_add_entry(&ck_constraint, new_ck_constraint, link);
> +	}
> +}
> +
> +void
> +BuildCkConstraints::alter(struct alter_space *alter)
> +{
> +	rlist_swap(&alter->new_space->ck_constraint, &ck_constraint);
> +	rlist_swap(&ck_constraint, &alter->old_space->ck_constraint);
> +}
> +
> +void
> +BuildCkConstraints::rollback(struct alter_space *alter)
> +{
> +	rlist_swap(&alter->old_space->ck_constraint, &ck_constraint);
> +	rlist_swap(&ck_constraint, &alter->new_space->ck_constraint);
> +}
> +
> +BuildCkConstraints::~BuildCkConstraints()
> +{
> +	struct ck_constraint *old_ck_constraint, *tmp;
> +	rlist_foreach_entry_safe(old_ck_constraint, &ck_constraint, link, tmp)
> +		ck_constraint_delete(old_ck_constraint);
> +}
> +
>   /**
>    * UpdateSchemaVersion - increment schema_version. Used on
>    * in alter_space_do(), i.e. when creating or dropping
> @@ -1757,6 +1797,12 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event)
>   				  space_name(old_space),
>   				  "the space has foreign key constraints");
>   		}
> +		/* Can't drop space having check constraints. */
> +		if (!rlist_empty(&old_space->ck_constraint)) {
> +			tnt_raise(ClientError, ER_DROP_SPACE,
> +				  space_name(old_space),
> +				  "the space has check constraints");
> +		}
>   		/**
>   		 * The space must be deleted from the space
>   		 * cache right away to achieve linearisable
> @@ -1854,6 +1900,8 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event)
>   						     def->field_count);
>   		(void) new CheckSpaceFormat(alter);
>   		(void) new ModifySpace(alter, def);
> +		/* Add an op to rebuild check constraints. */
> +		(void) new BuildCkConstraints(alter);
>   		def_guard.is_active = false;
>   		/* Create MoveIndex ops for all space indexes. */
>   		alter_space_move_indexes(alter, 0, old_space->index_id_max + 1);
> @@ -2096,6 +2144,8 @@ on_replace_dd_index(struct trigger * /* trigger */, void *event)
>   	 * old space.
>   	 */
>   	alter_space_move_indexes(alter, iid + 1, old_space->index_id_max + 1);
> +	/* Add an op to rebuild check constraints. */
> +	(void) new BuildCkConstraints(alter);

5. Why do you need checks rebuild on an index update? As I know, checks
depend on space format only. Strictly speaking, even on space alter you
do not need to rebuild checks, if the space format is unchanged. However,
I am not sure, if checks AST does not contain space pointers.

>   	/* Add an op to update schema_version on commit. */
>   	(void) new UpdateSchemaVersion(alter);
>   	alter_space_do(txn, alter);
> @@ -2163,7 +2213,8 @@ on_replace_dd_truncate(struct trigger * /* trigger */, void *event)
>   		struct index *old_index = old_space->index[i];
>   		(void) new TruncateIndex(alter, old_index->def->iid);
>   	}
> -
> +	/* Add an op to rebuild check constraints. */
> +	(void) new BuildCkConstraints(alter);

6. Comments like that, and the 2 same ones above looks like this, sorry:
https://github.com/Gerold103/tarantool-memes/blob/master/CAPTAIN.png
How is such a comment supposed to help a reader?

>   	alter_space_do(txn, alter);
>   	scoped_guard.is_active = false;
>   }
> @@ -4051,6 +4102,144 @@ on_replace_dd_fk_constraint(struct trigger * /* trigger*/, void *event)
> +/**
> + * Trigger invoked on commit in the _ck_constraint space.
> + * Drop useless old check constraint object if exists.
> + */
> +static void
> +on_replace_ck_constraint_commit(struct trigger *trigger, void * /* event */)
> +{
> +	struct ck_constraint *old_ck_constraint =
> +		(struct ck_constraint *)trigger->data;
> +	if (old_ck_constraint != NULL)
> +		ck_constraint_delete(old_ck_constraint);
> +	++schema_version;

7. We have UpdateSchemaVersion for that. It can be touched
direcrtly only by _space triggers.

> +}
> +
> +/** 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);
> +	access_check_ddl(space->def->name, space->def->id, space->def->uid,
> +			 SC_SPACE, PRIV_A);
> +
> +	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) {
> +		/* Create or replace check constraint. */
> +		struct ck_constraint_def *ck_constraint_def =
> +			ck_constraint_def_decode(new_tuple, &fiber()->gc);
> +		struct ck_constraint *new_ck_constraint =
> +			ck_constraint_new(ck_constraint_def, space->def);
> +		if (new_ck_constraint == NULL)
> +			diag_raise();
> +		const char *space_name = new_ck_constraint->def->name;
> +		struct ck_constraint *old_ck_constraint =
> +			space_ck_constraint_by_name(space, space_name,
> +						    strlen(space_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_ck_constraint;
> +		on_rollback->data = old_tuple == NULL ? new_ck_constraint :
> +							old_ck_constraint;
> +	} else if (new_tuple == NULL && old_tuple != NULL) {

8. As I understand, it should be an assertion, not 'if'. When new_tuple == NULL,
it is impossible that old_tuple == NULL too. What is more, if you reached 'else'
branch, then 'new_tuple == NULL' is already true, and you do not need to check
that again.

> +		/* Drop check constraint. */
> +		uint32_t name_len;
> +		const char *name =
> +			tuple_field_str_xc(old_tuple,
> +					   BOX_CK_CONSTRAINT_FIELD_NAME,
> +					   &name_len);
> +		struct ck_constraint *old_ck_constraint =
> +			space_ck_constraint_by_name(space, name, name_len);
> +		assert(old_ck_constraint != NULL);
> +		rlist_del_entry(old_ck_constraint, link);
> +		on_commit->data = old_ck_constraint;
> +		on_rollback->data = old_ck_constraint;
> +	}
> +
> +	txn_on_rollback(txn, on_rollback);
> +	txn_on_commit(txn, on_commit);
> +}
> diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua
> index cc172dc15..a304290a2 100644
> --- a/src/box/lua/upgrade.lua
> +++ b/src/box/lua/upgrade.lua
> @@ -629,10 +631,46 @@ local function upgrade_priv_to_2_1_1()
>   local function upgrade_to_2_1_1()
>       log.info("started upgrade_to_2_1_1")
> +    local _space = box.space[box.schema.SPACE_ID]
> +    local _index = box.space[box.schema.INDEX_ID]
> +    local _ck_constraint = box.space[box.schema.CK_CONSTRAINT_ID]
> +    local MAP = setmap({})
> +
> +    log.info("create space _ck_constraint")
> +    local format = {{name='name', type='string'},
> +                    {name='space_id', type='unsigned'},
> +                    {name='expr_str', type='str'}}

9. Why a name is mandatory? As I know, I can omit the name, according to
the standard.

> +    _space:insert{_ck_constraint.id, ADMIN, '_ck_constraint', 'memtx', 0, MAP, format}
> +
> +    log.info("create index primary on _ck_constraint")
> +    _index:insert{_ck_constraint.id, 0, 'primary', 'tree',
> +                  {unique = true}, {{0, 'string'}, {1, 'unsigned'}}}
> +
> +    log.info("create secondary index child_id on _ck_constraint")
> +    _index:insert{_ck_constraint.id, 1, 'space_id', 'tree',
> +                  {unique = false}, {{1, 'unsigned'}}}
> +
>       upgrade_priv_to_2_1_1()
>   end
>   

  reply	other threads:[~2019-03-22  9:29 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-30  8:59 [tarantool-patches] [PATCH v2 0/9] sql: Checks on server side Kirill Shcherbatov
2019-01-30  8:59 ` [tarantool-patches] [PATCH v2 1/9] box: fix upgrade script for _fk_constraint space Kirill Shcherbatov
2019-03-11 18:44   ` [tarantool-patches] " n.pettik
2019-03-13 11:36   ` Kirill Yukhin
2019-01-30  8:59 ` [tarantool-patches] [PATCH v2 2/9] box: fix _trigger and _ck_constraint access check Kirill Shcherbatov
2019-03-11 19:29   ` [tarantool-patches] " n.pettik
2019-03-22  9:29     ` Vladislav Shpilevoy
2019-03-26 10:59     ` Kirill Shcherbatov
2019-04-01 14:06       ` n.pettik
2019-03-13 11:38   ` Kirill Yukhin
2019-03-13 11:44     ` Kirill Yukhin
2019-01-30  8:59 ` [tarantool-patches] [PATCH v2 3/9] box: fix Tarantool upgrade from 2.1.0 to 2.1.1 Kirill Shcherbatov
2019-03-12 11:45   ` [tarantool-patches] " n.pettik
2019-03-20 15:12     ` n.pettik
2019-03-20 15:38       ` Kirill Shcherbatov
2019-03-21 15:23         ` n.pettik
2019-03-21 15:36           ` Vladislav Shpilevoy
2019-03-22  9:28         ` Vladislav Shpilevoy
2019-03-22 10:18           ` Kirill Shcherbatov
2019-03-22 10:21             ` Vladislav Shpilevoy
2019-03-26  9:52   ` Kirill Yukhin
2019-01-30  8:59 ` [tarantool-patches] [PATCH v2 4/9] box: fix on_replace_trigger_rollback routine Kirill Shcherbatov
2019-03-11 20:00   ` [tarantool-patches] " n.pettik
2019-03-13 11:39   ` Kirill Yukhin
2019-01-30  8:59 ` [tarantool-patches] [PATCH v2 5/9] schema: add new system space for CHECK constraints Kirill Shcherbatov
2019-03-22  9:29   ` Vladislav Shpilevoy [this message]
2019-03-22  9:52     ` [tarantool-patches] " n.pettik
2019-03-26 10:59     ` Kirill Shcherbatov
2019-04-01 19:45       ` n.pettik
2019-04-16 13:51         ` Kirill Shcherbatov
2019-01-30  8:59 ` [tarantool-patches] [PATCH v2 6/9] sql: disallow use of TYPEOF in Check Kirill Shcherbatov
2019-03-26 10:59   ` [tarantool-patches] " Kirill Shcherbatov
2019-04-01 19:52     ` n.pettik
2019-01-30  8:59 ` [tarantool-patches] [PATCH v2 7/9] sql: refactor sqlite3_reset routine Kirill Shcherbatov
2019-03-26 10:59   ` [tarantool-patches] " Kirill Shcherbatov
2019-01-30  8:59 ` [tarantool-patches] [PATCH v2 8/9] box: exported sql_bind structure and API Kirill Shcherbatov
2019-03-26 10:59   ` [tarantool-patches] " Kirill Shcherbatov
2019-01-30  8:59 ` [tarantool-patches] [PATCH v2 9/9] sql: run check constraint tests on space alter Kirill Shcherbatov
2019-03-26 10:59   ` [tarantool-patches] " Kirill Shcherbatov
2019-04-02 14:14     ` n.pettik
2019-04-16 13:51       ` Kirill Shcherbatov

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=e025b179-6a45-7c42-1550-9dfd31f40118@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=korablev@tarantool.org \
    --cc=kshcherbatov@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='[tarantool-patches] Re: [PATCH v2 5/9] 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