Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: "n.pettik" <korablev@tarantool.org>, tarantool-patches@freelists.org
Subject: [tarantool-patches] Re: [PATCH 2/5] schema: add new system space for FK constraints
Date: Fri, 3 Aug 2018 01:15:14 +0300	[thread overview]
Message-ID: <30b2a1cc-3e6d-e5f6-bca5-6a5e5396bc14@tarantool.org> (raw)
In-Reply-To: <FAAA2017-8559-4DE3-9662-8572DF598979@tarantool.org>

Thanks for the patch! See 3 comments below and a separate
commit on the branch.

>     schema: add new system space for FK constraints
>     
>     This patch introduces new system space to persist foreign keys
>     constraints. Format of the space:
>     
>     _fk_constraint (space id = 358)
>     
>     [<contraint name> STR, <parent id> UINT, <child id> UINT,

1. Typo: contraint.

>      <is deferred> BOOL, <match> STR, <on delete action> STR,
>      <on update action> STR, <child cols> ARRAY<UINT>,
>      <parent cols> ARRAY<UINT>]
>     
>     FK constraint is local to space, so every pair <FK name, child id>
>     is unique (and it is PK in _fk_constraint space).
>     
>     After insertion into this space, new instance describing FK constraint
>     is created. FK constraints are held in data-dictionary as two lists
>     (for child and parent constraints) in struct space.
>     
>     There is a list of FK restrictions:
>      - At the time of FK creation parent and child spaces must exist;
>      - VIEWs can't be involved into FK processing;
>      - Child space must be empty;
>      - Types of referencing and referenced fields must be comparable;
>      - Collations of referencing and referenced fields must match;
>      - Referenced fields must compose unique index;
>      - Referenced fields can not contain duplicates.
>     
>     Until space (child) features FK constraints it isn't allowed to be
>     dropped. Implicitly referenced index also can't be dropped
>     (and that is why parent space can't be dropped). But :drop() method
>     of child space firstly deletes all FK constraint (the same as SQL
>     triggers, indexes etc) and then removes entry from _space.
>     
>     Part of #3271> diff --git a/src/box/alter.cc b/src/box/alter.cc
> index 7b6bd1a5a..5b55bfd7a 100644
> --- a/src/box/alter.cc
> +++ b/src/box/alter.cc
> @@ -3459,6 +3515,395 @@ on_replace_dd_trigger(struct trigger * /* trigger */, void *event)> +
> +/**
> + * On rollback of creation we remove FK constraint from DD, i.e.
> + * from parent's and child's lists of constraints and
> + * release memory.
> + */
> +static void
> +on_create_fkey_rollback(struct trigger *trigger, void *event)
> +{
> +	(void) event;
> +	struct fkey *fk = (struct fkey *)trigger->data;
> +	rlist_del_entry(fk, parent_link);
> +	rlist_del_entry(fk, child_link);
> +	fkey_delete(fk);
> +}
> +
> +/** Return old FK and release memory for the new one. */
> +static void
> +on_replace_fkey_rollback(struct trigger *trigger, void *event)
> +{
> +	(void) event;
> +	struct fkey *fk = (struct fkey *)trigger->data;
> +	struct space *parent = space_by_id(fk->def->parent_id);
> +	struct space *child = space_by_id(fk->def->child_id);
> +	struct fkey *old_fkey = fkey_grab_by_name(&child->child_fkey,
> +						  fk->def->name);
> +	fkey_delete(old_fkey);
> +	rlist_add_entry(&child->child_fkey, fk, child_link);
> +	rlist_add_entry(&parent->parent_fkey, fk, parent_link);


2. In the comment you said that this function restores the old fk and
deletes the new one. But on the code we see the line:
fkey_delete(old_fkey).

Secondly, you got old_fkey from child->child_fkey, but earlier, in
on_replace trigger, you had removed old_fkey from child_fkey list
and put here new fkey. So here actually old_fkey == fkey (I tested, it is).

I think, it can be fixed quite simple: you have ability to fetch the new
fkey from child_list and have no the latter for the old one since it is
unlinked already. So lets pass here old_fkey as trigger->data and fetch
the new fkey from the list.

The test for this bug is below:

	box.sql.execute("CREATE TABLE t1 (id PRIMARY KEY, a REFERENCES t1, b INT);")
	t = box.space._fk_constraint:select{}[1]:totable()
	errinj = box.error.injection
	errinj.set("ERRINJ_WAL_IO", true)
	box.space._fk_constraint:replace(t)

But it crashes on the next commit. On the current one this function is
unreachable.

	Process 51167 stopped
	* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

> +/**
> + * ANSI SQL doesn't allow list of referenced fields to contain
> + * duplicates. Firstly, we try to follow the easiest way:
> + * if all referenced fields numbers are less than 63, we can
> + * use bit mask. Otherwise, fall through slow check where we
> + * use O(field_cont^2) simple nested cycle iterations.
> + */
> +static void
> +fkey_links_check_duplicates(struct fkey_def *fk_def)
> +{
> +	uint64_t field_mask = 0;
> +	for (uint32_t i = 0; i < fk_def->field_count; ++i) {
> +		uint32_t parent_field = fk_def->links[i].parent_field;
> +		if (parent_field > 63)
> +			goto slow_check;
> +		if (field_mask & (((uint64_t) 1) << parent_field))
> +			goto error;
> +		column_mask_set_fieldno(&field_mask, parent_field);

3. Looks like column_mask API is not applicable here since you
anyway still use raw bit setting. I have removed column_mask API
from there on the branch.

> +	}
> +	return;
> +slow_check:
> +	for (uint32_t i = 0; i < fk_def->field_count; ++i) {
> +		uint32_t parent_field = fk_def->links[i].parent_field;
> +		for (uint32_t j = i + 1; j < fk_def->field_count; ++j) {
> +			if (parent_field == fk_def->links[j].parent_field)
> +				goto error;
> +		}
> +	}
> +	return;
> +error:
> +	tnt_raise(ClientError, ER_CREATE_FK_CONSTRAINT, fk_def->name,
> +		  "referenced fields can not contain duplicates");
> +}
> +

  reply	other threads:[~2018-08-02 22:15 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-13  2:04 [tarantool-patches] [PATCH 0/5] Move FK constraints to server Nikita Pettik
2018-07-13  2:04 ` [tarantool-patches] [PATCH 1/5] sql: prohibit creation of FK on unexisting tables Nikita Pettik
2018-07-17 21:05   ` [tarantool-patches] " Vladislav Shpilevoy
2018-07-25 10:03     ` n.pettik
2018-07-26 20:12       ` Vladislav Shpilevoy
2018-08-01 20:54         ` n.pettik
2018-08-02 22:15           ` Vladislav Shpilevoy
2018-08-06  0:27             ` n.pettik
2018-07-13  2:04 ` [tarantool-patches] [PATCH 2/5] schema: add new system space for FK constraints Nikita Pettik
2018-07-17 21:05   ` [tarantool-patches] " Vladislav Shpilevoy
2018-07-25 10:03     ` n.pettik
2018-07-26 20:12       ` Vladislav Shpilevoy
2018-08-01 20:54         ` n.pettik
2018-08-02 22:15           ` Vladislav Shpilevoy [this message]
2018-08-06  0:28             ` n.pettik
2018-08-06 18:24               ` Vladislav Shpilevoy
2018-07-13  2:04 ` [tarantool-patches] [PATCH 3/5] sql: introduce ADD CONSTRAINT statement Nikita Pettik
2018-07-17 21:05   ` [tarantool-patches] " Vladislav Shpilevoy
2018-07-25 10:03     ` n.pettik
2018-07-26 20:12       ` Vladislav Shpilevoy
2018-08-01 20:54         ` n.pettik
2018-08-02 22:15           ` Vladislav Shpilevoy
2018-08-06  0:28             ` n.pettik
2018-08-06 18:24               ` Vladislav Shpilevoy
2018-08-06 23:43                 ` n.pettik
2018-07-13  2:04 ` [tarantool-patches] [PATCH 4/5] sql: display error on FK creation and drop failure Nikita Pettik
2018-07-17 21:04   ` [tarantool-patches] " Vladislav Shpilevoy
2018-07-25 10:03     ` n.pettik
2018-07-26 20:11       ` Vladislav Shpilevoy
2018-07-13  2:04 ` [tarantool-patches] [PATCH 5/5] sql: remove SQLITE_OMIT_FOREIGN_KEY define guard Nikita Pettik
2018-07-17 21:04 ` [tarantool-patches] Re: [PATCH 0/5] Move FK constraints to server Vladislav Shpilevoy
2018-08-07 14:57 ` 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=30b2a1cc-3e6d-e5f6-bca5-6a5e5396bc14@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=korablev@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='[tarantool-patches] Re: [PATCH 2/5] schema: add new system space for FK 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