From: "n.pettik" <korablev@tarantool.org>
To: tarantool-patches@freelists.org
Cc: Ivan Koptelov <ivan.koptelov@tarantool.org>
Subject: [tarantool-patches] Re: [PATCH v2] sql: add index_def to struct Index
Date: Fri, 13 Jul 2018 22:19:08 +0300 [thread overview]
Message-ID: <513397CB-4A4B-4C7D-A0C9-249000100E03@tarantool.org> (raw)
In-Reply-To: <0566bdde-5972-6c5e-707d-0ad58b6b45da@tarantool.org>
[-- Attachment #1: Type: text/plain, Size: 8016 bytes --]
> + /*
> + * Here we handle cases like
> + * CREATE TABLE t1(a UNIQUE, PRIMARY KEY(a))
> + * In these cases (where UNIQUE constraints precede
> + * PRIMARY constraint) appropriate Index->def->cmp_def
> + * can not be set 'on the fly' for indexes implementing
> + * UNIQUE constraints as PK key_def is missing and
> + * needed for it.
> + * At this point we can set appropriate cmp_def, since
> + * all indexes (from CREATE TABLE statement) is created.
> + */
> + if (!p->def->opts.is_view) {
> + assert(p->pIndex != NULL);
> + struct Index *pk;
> + for (struct Index *idx = p->pIndex; idx != NULL;
> + idx = idx->pNext) {
> + if (idx->index_type == SQL_INDEX_TYPE_CONSTRAINT_PK)
> + pk = idx;
> + }
> + struct key_def *pk_def = pk->def->key_def;
> +
> + for (struct Index *idx = p->pIndex; idx != NULL;
> + idx = idx->pNext) {
> + if (idx->index_type != SQL_INDEX_TYPE_CONSTRAINT_PK) {
> + struct index_def *def = idx->def;
> + struct key_def *cmp_def =
> + key_def_merge(def->key_def,
> + pk_def);
> + if (cmp_def == NULL) {
> + pParse->rc = SQL_TARANTOOL_ERROR;
> + ++pParse->nErr;
> + return;
> + }
> + if (!def->opts.is_unique) {
> + def->cmp_def->unique_part_count =
> + def->cmp_def->part_count;
> + } else {
> + def->cmp_def->unique_part_count =
> + def->key_def->part_count;
> + }
> + }
> + }
> + }
I don’t understand: why do you need at all this cmp_def?
In SQL it is extremely unlikely to be useful.
> if (db->init.busy) {
> /*
> * As rebuild creates a new ExpList tree and
> @@ -2398,8 +2441,7 @@
> struct Index *
> sql_index_alloc(struct sqlite3 *db)
> {
> - int index_size = ROUND8(sizeof(struct Index));
> - struct Index *p = sqlite3DbMallocZero(db, index_size);
> + struct Index *p = sqlite3DbMallocZero(db, sizeof(struct Index));
> return p;
> }
>
> @@ -2566,12 +2608,25 @@
> if (parse->nErr > 0)
> goto cleanup;
>
> - struct key_def *pk_key_def;
> - if (idx_type == SQL_INDEX_TYPE_UNIQUE ||
> - idx_type == SQL_INDEX_TYPE_NON_UNIQUE)
> + struct key_def *pk_key_def = NULL;
> + if (idx_type != SQL_INDEX_TYPE_CONSTRAINT_PK &&
> + parse->pNewTable == NULL)
> pk_key_def = table->pIndex->def->key_def;
> - else
> - pk_key_def = NULL;
> + /*
> + * In cases like CREATE TABLE t1(a UNIQUE, PRIMARY KEY(a))
> + * fill_index_def() will be firstly executed for creating
> + * index_def for UNIQUE constraint and then for creating
> + * index_def for PRIMARY KEY constraint. So when
> + * fill_index_def will be called for UNIQUE constraint
> + * there will be no PK, while PK->def->key_def is needed
> + * to create cmp_def (inside index_def_new()).
Again: explain pls why do you need cmp_def on client-side (i.e. parser)?
> To handle
> + * this case we set here pk_key_def to key_def and later
> + * in sqlite3EndTable (when PK index is already created)
> + * we go over all indexes and set appropriate cmp_def in
> + * them.
> + */
> + if (parse->pNewTable != NULL)
> + pk_key_def = key_def;
>
> index->def = index_def_new(space_def->id, iid, name, name_len, TREE,
> &opts, key_def, pk_key_def);
> @@ -2618,12 +2673,6 @@
> */
> struct Table *table = NULL;
> if (tbl_name != NULL) {
> - /*
> - * Use the two-part index name to determine the
> - * database to search for the table. 'Fix' the
> - * table name to this db before looking up the
> - * table.
> - */
> assert(token != NULL && token->z != NULL);
> table = sqlite3LocateTable(parse, 0, tbl_name->a[0].zName);
> assert(db->mallocFailed == 0 || table == NULL);
> @@ -2642,7 +2691,7 @@
> }
> /*
> * Find the name of the index. Make sure there is not
> - * already another index or table with the same name.
> + * already another index with the same name.
> *
> * Exception: If we are reading the names of permanent
> * indices from the Tarantool schema (because some other
> @@ -2660,7 +2709,7 @@
> * 2) UNIQUE constraint is non-named and standard
> * auto-index name will be generated.
> */
> - bool is_constraint_named = false;
> + bool is_constraint_named;
> if (token != NULL) {
> name = sqlite3NameFromToken(db, token);
> if (name == NULL)
> @@ -2691,14 +2740,26 @@
> }
> name = sqlite3MPrintf(db, "sql_autoindex_%s_%d",
> table->def->name, n);
> + is_constraint_named = false;
> } else {
> - name = sqlite3MPrintf(db, "sql_autoindex_%s",
> - constraint_name);
> + /*
> + * This naming is temporary. Now it's not
> + * possible (since we implement UNIQUE
> + * and PK constraints with indexes and
> + * indexes can not have same names), but
> + * in future we would use names exactly
> + * as they are set by user.
> + */
> + if (idx_type == SQL_INDEX_TYPE_CONSTRAINT_UNIQUE)
> + name = sqlite3MPrintf(db,
> + "unique_constraint_%s",
> + constraint_name);
> + if (idx_type == SQL_INDEX_TYPE_CONSTRAINT_PK)
> + name = sqlite3MPrintf(db, "pk_constraint_%s",
> + constraint_name);
> is_constraint_named = true;
> }
> - if (constraint_name != NULL) {
> - sqlite3DbFree(db, constraint_name);
> - }
> + sqlite3DbFree(db, constraint_name);
> }
>
> if (name == NULL)
> @@ -2708,7 +2769,8 @@
> table->def->id < BOX_SYSTEM_ID_MAX;
> if (is_system_space && (idx_type == SQL_INDEX_TYPE_NON_UNIQUE ||
> idx_type == SQL_INDEX_TYPE_UNIQUE)) {
> - diag_set(ClientError, ER_MODIFY_INDEX, name, table->def->name,
> + diag_set(ClientError, ER_MODIFY_INDEX, name,
> + table->def->name,
> "can't create index on system space");
> parse->nErr++;
> parse->rc = SQL_TARANTOOL_ERROR;
> @@ -2745,7 +2807,7 @@
>
> index->pTable = table;
> index->onError = (u8) on_error;
> - index->index_type = idx_type;
> + index->index_type = idx_type;
> index->pSchema = db->pSchema;
> /* Tarantool have access to each column by any index. */
> if (where != NULL) {
> @@ -2775,8 +2837,22 @@
> goto exit_create_index;
> }
>
> - /* If it is parsing stage, then iid may have any value. */
> - uint32_t iid = 1;
> + /*
> + * We set no SQL statement for indexes created during
> + * CREATE TABLE statement. Instead we use
> + * Index->index_def->opts.sql to store information if
> + * this index implements named or non-named constraint.
> + */
> + if (tbl_name == NULL &&
> + idx_type == SQL_INDEX_TYPE_CONSTRAINT_UNIQUE)
If idx_type == SQL_INDEX_TYPE_CONSTRAINT_UNIQUE than tbl_name must be NULL:
you can’t declare unique constraint outside CREATE TABLE statement.
> + sql_stmt = is_constraint_named ?
> + "named constraint" : "non-named constraint”;
You can set ‘sql_stmt’ only for name constraints:
sql_stmt = is_constraint_name ? “_named_constr” : “”;
And use strncmp when comparing with it.
Also, if <if-clause> contains mode than one row,
we wrap it in brackets.
> +
> + /*
> + * If it is parsing stage, then iid may have any value,
> + * but PK still must have iid == 0
> + */
> + uint32_t iid = idx_type == SQL_INDEX_TYPE_CONSTRAINT_PK ? 0 : 1;
> if (db->init.busy)
> iid = SQLITE_PAGENO_TO_INDEXID(db->init.newTnum);
You can just do this:
uint32_t iid = idx_type == SQL_INDEX_TYPE_CONSTRAINT_PK;
> +
> + if (k != key_def->part_count)
> + continue;
> +
> + if (index->onError != existing_idx->onError) {
> + if (index->onError !=
> + ON_CONFLICT_ACTION_DEFAULT &&
> + existing_idx->onError !=
> + ON_CONFLICT_ACTION_DEFAULT)
> + sqlite3ErrorMsg(parse,
> + "conflicting "\
> + "ON CONFLICT "\
> + "clauses specified”);
Again: here you have already set error. What is the reason to
continue process smth? You are able to go to exit_create_index.
[-- Attachment #2: Type: text/html, Size: 10540 bytes --]
next prev parent reply other threads:[~2018-07-13 19:19 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-09 10:46 Ivan Koptelov
2018-07-12 11:18 ` n.pettik
2018-07-13 15:58 ` Ivan Koptelov
2018-07-13 19:19 ` n.pettik [this message]
2018-07-16 5:54 ` Ivan Koptelov
2018-07-17 1:22 ` n.pettik
2018-07-17 11:21 ` Kirill Yukhin
-- strict thread matches above, loose matches on Subject: below --
2018-07-09 0:31 Ivan Koptelov
2018-06-13 7:30 [tarantool-patches] Re: [PATCH v3] " Ivan Koptelov
2018-06-18 18:45 ` Kirill Shcherbatov
2018-06-21 12:57 ` [tarantool-patches] Re: [PATCH v4] " Ivan Koptelov
2018-06-22 8:46 ` Kirill Shcherbatov
2018-06-27 17:46 ` [tarantool-patches] Re: [PATCH v5] " Ivan Koptelov
2018-06-27 17:57 ` Kirill Shcherbatov
2018-06-28 18:49 ` Vladislav Shpilevoy
2018-06-29 13:49 ` [tarantool-patches] Re: [PATCH v6] " Ivan Koptelov
2018-06-29 20:46 ` Vladislav Shpilevoy
2018-07-03 11:37 ` [tarantool-patches] Re: [PATCH v9] " Ivan Koptelov
2018-07-03 23:54 ` n.pettik
2018-07-04 15:55 ` [tarantool-patches] Re: [PATCH v11] " Ivan Koptelov
2018-07-04 19:28 ` n.pettik
2018-07-05 14:50 ` Ivan Koptelov
2018-07-06 0:51 ` n.pettik
2018-07-08 14:17 ` [tarantool-patches] Re: [PATCH v2] " Ivan Koptelov
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=513397CB-4A4B-4C7D-A0C9-249000100E03@tarantool.org \
--to=korablev@tarantool.org \
--cc=ivan.koptelov@tarantool.org \
--cc=tarantool-patches@freelists.org \
--subject='[tarantool-patches] Re: [PATCH v2] sql: add index_def to struct Index' \
/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