Tarantool development patches archive
 help / color / mirror / Atom feed
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;

  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