From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: Kirill Shcherbatov <kshcherbatov@tarantool.org>,
tarantool-patches@freelists.org
Cc: Ivan Koptelov <ivan.koptelov@tarantool.org>
Subject: [tarantool-patches] Re: [PATCH v5] sql: add index_def to struct Index
Date: Thu, 28 Jun 2018 21:49:38 +0300 [thread overview]
Message-ID: <bb3bb8de-ff05-659d-6ead-95d94e6af91f@tarantool.org> (raw)
In-Reply-To: <898ec1ac-51b9-13a6-6298-3a20eeac5b2b@tarantool.org>
Hello. Thanks for the patch!
See 11 comments below. Besides, see some of them and others
in the separate commit on the branch. Please, look at it and
squash. Note: I did not run the tests, so please, repair them
if they fail.
> commit cba31099432e47a4f65d5d48280da2608d6e615d
> Author: Ivan Koptelov <ivan.koptelov@tarantool.org>
> Date: Fri Jun 8 10:32:01 2018 +0300
>
> sql: add index_def to Index
>
> Now every sqlite struct Index is created with tnt struct
> index_def inside. This allows us to use tnt index_def
> in work with sqlite indexes in the same manner as with
> tnt index and is a step to remove sqlite Index with
> tnt index.
> Fields coll_array, coll_id_array, aiColumn, sort_order
> and zName are removed from Index. All usages of this
> fields changed to usage of corresponding index_def
> fields.
> index_is_unique(), sql_index_collation() and
> index_column_count() are removed with calls of
> index_def corresponding fields.
>
> Closes: #3369
>
> diff --git a/src/box/sql/build.c b/src/box/sql/build.c
> index 0da7d805b..2c82644e6 100644
> --- a/src/box/sql/build.c
> +++ b/src/box/sql/build.c
> @@ -1049,22 +1052,20 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken)
> uint32_t *id = &p->def->fields[i].coll_id;
> p->aCol[i].coll = sql_get_coll_seq(pParse, zColl, id);
> if (p->aCol[i].coll != NULL) {
> - Index *pIdx;
> /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
> * then an index may have been created on this column before the
> * collation type was added. Correct this if it is the case.
> */
> - for (pIdx = p->pIndex; pIdx; pIdx = pIdx->pNext) {
> - assert(pIdx->nColumn == 1);
> - if (pIdx->aiColumn[0] == i) {
> - id = &pIdx->coll_id_array[0];
> - pIdx->coll_array[0] =
> + for (struct Index *pIdx = p->pIndex; pIdx; pIdx = pIdx->pNext) {
> + assert(pIdx->def->key_def->part_count == 1);
> + if (pIdx->def->key_def->parts[0].fieldno == i) {
> + pIdx->def->key_def->parts[0].coll_id = *id;
1. Here you should set id to address of parts[0].coll_id so that it will
be initialized in sql_column_collation(). Now you set coll_id to id before
initialization of id (fixed by me on the branch).
> + pIdx->def->key_def->parts[0].coll =
> sql_column_collation(p->def, i, id);
> }
> }
> - } else {
> - sqlite3DbFree(db, zColl);
> }
> + sqlite3DbFree(db, zColl);
> }
2. I caught a crash:
box.cfg{}
box.sql.execute('CREATE TABLE test (a int, b int, c int, PRIMARY KEY (a, a, b, c))')
Process 85357 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x38)
frame #0: 0x000000010036122f tarantool`convertToWithoutRowidTable(pParse=0x000000010401f8b0, pTab=0x0000000104600218) at build.c:1365
1362 * PRIMARY KEY contains no repeated columns.
1363 */
1364
-> 1365 struct key_part *parts = pPk->def->key_def->parts;
1366 uint32_t part_count = pPk->def->key_def->part_count;
1367 uint32_t new_part_count = part_count;
1368
Target 0: (tarantool) stopped
> @@ -1404,18 +1355,33 @@ convertToWithoutRowidTable(Parse * pParse, Table * pTab)
> pPk = sqlite3PrimaryKeyIndex(pTab);
>
> /*
> - * Remove all redundant columns from the PRIMARY KEY. For example, change
> - * "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later
> - * code assumes the PRIMARY KEY contains no repeated columns.
> + * Remove all redundant columns from the PRIMARY
> + * KEY. For example, change
> + * "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just
> + * "PRIMARY KEY(a,b,c,d)". Later code assumes the
> + * PRIMARY KEY contains no repeated columns.
> */
> - for (i = j = 1; i < pPk->nColumn; i++) {
> - if (hasColumn(pPk->aiColumn, j, pPk->aiColumn[i])) {
> - pPk->nColumn--;
> - } else {
> - pPk->aiColumn[j++] = pPk->aiColumn[i];
> +
> + struct key_part *parts = pPk->def->key_def->parts;
> + uint32_t part_count = pPk->def->key_def->part_count;
> + uint32_t new_part_count = part_count;
> +
> + for (uint32_t i = 1; i < part_count; i++) {
> + if (is_part_duplicated(parts, i)) {
> + new_part_count--;
> + bool is_found = false;
> + for (uint32_t j = i + 1; j < part_count; j++) {
> + if (!is_part_duplicated(parts, j)) {
> + parts[i] = parts[j];
> + is_found = true;
> + break;
> + }
> + }
> + if (!is_found)
> + break;
> }
> }
3. This cycle and is_part_duplicated still are useless non working things.
Example:
CREATE TABLE test (a int, b int, c int, PRIMARY KEY (a, a, a, a))
Here the primary index has duplicate 'a'. Its key_def has these
fieldnos: [0, 0, 0, 0].
In your cycle you will update this def to [0, 0, 0], it is not? So there
is still 3 duplicates.
And please, remove is_part_duplicated and use key_def_find.
> - pPk->nColumn = j;
> + pPk->def->key_def->part_count = new_part_count;
> }
> assert(pPk != 0);
> }
> @@ -2531,34 +2499,20 @@ sqlite3RefillIndex(Parse * pParse, Index * pIndex, int memRootPage)
> */
> Index *
> sqlite3AllocateIndexObject(sqlite3 * db, /* Database connection */
> - i16 nCol, /* Total number of columns in the index */
> - int nExtra, /* Number of bytes of extra space to alloc */
> - char **ppExtra /* Pointer to the "extra" space */
> + i16 nCol /* Total number of columns in the index */
4. You have removed more than half of the function, so it is time to
convert it to Tarantool code style.
(fixed by me on the branch).
> )
> {
> Index *p; /* Allocated index object */
> int nByte; /* Bytes of space for Index object + arrays */
>
> nByte = ROUND8(sizeof(Index)) + /* Index structure */
> - ROUND8(sizeof(struct coll *) * nCol) + /* Index.coll_array */
> - ROUND8(sizeof(uint32_t) * nCol) + /* Index.coll_id_array*/
> - ROUND8(sizeof(LogEst) * (nCol + 1) + /* Index.aiRowLogEst */
> - sizeof(i16) * nCol + /* Index.aiColumn */
> - sizeof(enum sort_order) * nCol); /* Index.sort_order */
> - p = sqlite3DbMallocZero(db, nByte + nExtra);
> + ROUND8(sizeof(LogEst) * (nCol + 1)); /* Index.aiRowLogEst */
> + p = sqlite3DbMallocZero(db, nByte);
> if (p) {
> char *pExtra = ((char *)p) + ROUND8(sizeof(Index));
> - p->coll_array = (struct coll **)pExtra;
> - pExtra += ROUND8(sizeof(struct coll **) * nCol);
> - p->coll_id_array = (uint32_t *) pExtra;
> - pExtra += ROUND8(sizeof(uint32_t) * nCol);
> p->aiRowLogEst = (LogEst *) pExtra;
> pExtra += sizeof(LogEst) * (nCol + 1);
> - p->aiColumn = (i16 *) pExtra;
> pExtra += sizeof(i16) * nCol;
5. You do not need pExtra propagation. It is not used below.
(fixed by me on the branch).
> - p->sort_order = (enum sort_order *) pExtra;
> - p->nColumn = nCol;
> - *ppExtra = ((char *)p) + nByte;
> }
> return p;
> }
> @@ -2646,18 +2600,142 @@ addIndexToTable(Index * pIndex, Table * pTab)
6. Please, add a comment here.
> +static void
> +set_index_def(Parse *parse, Index *index, Table *table, uint32_t iid,
> + const char *name, uint32_t name_len, int on_error,
> + struct ExprList *expr_list, u8 idx_type)
> diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
> index e3fff37fe..c14a70836 100644
> --- a/src/box/sql/fkey.c
> +++ b/src/box/sql/fkey.c
> @@ -287,9 +294,16 @@ sqlite3FkLocateIndex(Parse * pParse, /* Parse context to store any error in */
> * the default collation sequences for each column.
> */
> int i, j;
> - for (i = 0; i < nCol; i++) {
> - i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */
> - char *zIdxCol; /* Name of indexed column */
> + struct key_part *part =
> + index->def->key_def->parts;
> + for (i = 0; i < nCol; i++, part++) {
> + /*
> + * Index of column in
> + * parent table.
> + * */
> + i16 iCol = (int) part->fieldno;
> + /* Name of indexed column. */
> + char *zIdxCol;
>
> if (iCol < 0)
7. How can iCol be < 0, if it was get from uint fieldno?
> diff --git a/src/box/sql/where.c b/src/box/sql/where.c
> index c0c26ce29..599863041 100644
> --- a/src/box/sql/where.c
> +++ b/src/box/sql/where.c
> @@ -2523,14 +2505,16 @@ whereLoopAddBtreeIndex(WhereLoopBuilder * pBuilder, /* The WhereLoop factory */
> */
> }
> } else if (eOp & WO_EQ) {
> - int iCol = pProbe->aiColumn[saved_nEq];
> + int iCol = pProbe->def->key_def->parts[saved_nEq].fieldno;
> pNew->wsFlags |= WHERE_COLUMN_EQ;
> assert(saved_nEq == pNew->nEq);
> - if ((iCol > 0 && nInMul == 0
> - && saved_nEq == nProbeCol - 1)
> - ) {
> - if (iCol >= 0 &&
> - !index_is_unique_not_null(pProbe)) {
8. This function is still declared (with not implementation)
and is even used in a couple of places.
> @@ -2913,11 +2896,28 @@ whereLoopAddBtree(WhereLoopBuilder * pBuilder, /* WHERE clause information */
> */
> Index *pFirst; /* First of real indices on the table */
> memset(&sPk, 0, sizeof(Index));
> - sPk.nColumn = 1;
> - sPk.aiColumn = &aiColumnPk;
> sPk.aiRowLogEst = aiRowEstPk;
> sPk.onError = ON_CONFLICT_ACTION_REPLACE;
> sPk.pTable = pTab;
> +
> + struct key_def *key_def = key_def_new(1);
> + if (key_def == NULL)
> + return SQLITE_ERROR;
9. Why SQLITE_ERROR. AFAIR we have decided to use SQL_TARANTOOL_ERROR +
nErr + rc setting.
> +
> + key_def_set_part(key_def, 0, 0, pTab->def->fields[0].type,
> + ON_CONFLICT_ACTION_ABORT,
> + NULL, COLL_NONE, SORT_ORDER_ASC);
> +
> + struct index_opts index_opts = index_opts_default;
> +
> + sPk.def = index_def_new(pTab->def->id, 0, "primary",
> + sizeof("primary") - 1, TREE, &index_opts,
> + key_def, NULL);
> + key_def_delete(key_def);
> +
> + if (sPk.def == NULL)
> + return SQLITE_ERROR;
10. Same.
11. Where is sPk.def is deleted?
> +
> aiRowEstPk[0] = sql_space_tuple_log_count(pTab);
> aiRowEstPk[1] = 0;
> pFirst = pSrc->pTab->pIndex;
next prev parent reply other threads:[~2018-06-28 18:49 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
2018-06-29 13:49 ` [tarantool-patches] Re: [PATCH v6] " Ivan Koptelov
2018-06-29 20:46 ` Vladislav Shpilevoy
[not found] ` <146c3bd4-e9e6-f943-5a42-c6db966d1c9c@tarantool.org>
2018-07-03 9:00 ` [tarantool-patches] Re: [PATCH v8] " Ivan Koptelov
2018-07-03 9:46 ` [tarantool-patches] Re: [PATCH v8.5] " Ivan Koptelov
2018-07-03 12:13 ` Vladislav Shpilevoy
2018-07-03 11:37 ` [tarantool-patches] Re: [PATCH v9] " Ivan Koptelov
2018-07-03 23:54 ` n.pettik
2018-07-04 0:08 ` Vladislav Shpilevoy
2018-07-04 9:17 ` 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
2018-07-04 10:46 ` [tarantool-patches] Re: [PATCH v9] " Kirill Yukhin
2018-07-04 12:10 ` 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=bb3bb8de-ff05-659d-6ead-95d94e6af91f@tarantool.org \
--to=v.shpilevoy@tarantool.org \
--cc=ivan.koptelov@tarantool.org \
--cc=kshcherbatov@tarantool.org \
--cc=tarantool-patches@freelists.org \
--subject='[tarantool-patches] Re: [PATCH v5] 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