Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@freelists.org, Nikita Pettik <korablev@tarantool.org>
Subject: [tarantool-patches] Re: [PATCH 5/8] sql: replace field type with affinity for VDBE runtime
Date: Sat, 29 Dec 2018 20:42:28 +0300	[thread overview]
Message-ID: <6e7623ee-fdcc-616f-6a99-20aff0e97f43@tarantool.org> (raw)
In-Reply-To: <e12bf5bc50b1f276bbc71afe42a9c7f1467c9c44.1545987214.git.korablev@tarantool.org>

Thanks for the patch! See 8 comments below.

> sql: replace field type with affinity for VDBE runtime

1. Maybe vice versa? Replace affinity with field type?

On 28/12/2018 12:34, Nikita Pettik wrote:
> This stage of affinity removal requires introducing of auxiliary
> intermediate function to convert array of affinity values to field type
> values. The rest of job done in this commit is a straightforward
> refactoring.
> 
> Part of #3698
> ---
>   src/box/sql/analyze.c                |  5 +-
>   src/box/sql/build.c                  | 13 +++++
>   src/box/sql/delete.c                 | 16 +++----
>   src/box/sql/expr.c                   | 21 ++++----
>   src/box/sql/fkey.c                   |  3 +-
>   src/box/sql/insert.c                 | 31 ++++++++----
>   src/box/sql/select.c                 | 17 +++++--
>   src/box/sql/sqliteInt.h              | 13 +++--
>   src/box/sql/update.c                 | 17 ++++---
>   src/box/sql/vdbe.c                   | 92 ++++++++++++++++--------------------
>   src/box/sql/vdbeInt.h                |  2 +-
>   src/box/sql/vdbemem.c                | 18 +++----
>   src/box/sql/where.c                  |  2 +-
>   src/box/sql/wherecode.c              |  6 +--
>   test/sql-tap/cast.test.lua           | 10 ++--
>   test/sql-tap/tkt-80e031a00f.test.lua |  8 ++--
>   16 files changed, 156 insertions(+), 118 deletions(-)
> 
> diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
> index 51c63fa7a..a04dc8681 100644
> --- a/src/box/sql/analyze.c
> +++ b/src/box/sql/analyze.c
> @@ -993,9 +993,10 @@ vdbe_emit_analyze_space(struct Parse *parse, struct space *space)
>   		sqlite3VdbeAddOp2(v, OP_Next, idx_cursor, next_row_addr);
>   		/* Add the entry to the stat1 table. */
>   		callStatGet(v, stat4_reg, STAT_GET_STAT1, stat1_reg);
> -		assert("BBB"[0] == AFFINITY_TEXT);
> +		char types[3] = { FIELD_TYPE_STRING, FIELD_TYPE_STRING,
> +				  FIELD_TYPE_STRING };

2. How about explicit type? Not char[], but enum field_type[] ? It will
look much more readable and convenient, IMO. Here and in other places.

'type_str', used now in all places instead of affinity str, looks crutchy.

>   		sqlite3VdbeAddOp4(v, OP_MakeRecord, tab_name_reg, 3, tmp_reg,
> -				  "BBB", 0);
> +				  types, 3);
>   		sqlite3VdbeAddOp4(v, OP_IdxInsert, tmp_reg, 0, 0,
>   				  (char *)stat1, P4_SPACEPTR);
>   		/* Add the entries to the stat4 table. */
> diff --git a/src/box/sql/build.c b/src/box/sql/build.c
> index e51e2db2a..b3f98c317 100644
> --- a/src/box/sql/build.c
> +++ b/src/box/sql/build.c
> @@ -520,6 +520,19 @@ sql_field_type_to_affinity(enum field_type field_type)
>   	}
>   }
>   
> +char *

2. So not char *, but enum field_type *. Ok?

> +sql_affinity_str_to_field_type_str(const char *affinity_str)
> +{
> +	if (affinity_str == NULL)
> +		return NULL;
> +	size_t len = strlen(affinity_str) + 1;
> +	char *type_str = (char *) sqlite3DbMallocRaw(sql_get(), len);
> +	for (uint32_t i = 0; i < len - 1; ++i)
> +		type_str[i] = sql_affinity_to_field_type(affinity_str[i]);
> +	type_str[len - 1] = '\0';

2. Instead of 0 you can use field_type_MAX terminator, if we will move
to enum field_type[].

> +	return type_str;
> +}
> +
>   /*
>    * Add a new column to the table currently being constructed.
>    *
> diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
> index f9c42fdec..7b0d6b2fd 100644
> --- a/src/box/sql/delete.c
> +++ b/src/box/sql/delete.c
> @@ -332,12 +332,12 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
>   			 */
>   			key_len = 0;
>   			struct index *pk = space_index(space, 0);
> -			const char *zAff = is_view ? NULL :
> -					   sql_space_index_affinity_str(parse->db,
> -									space->def,
> -									pk->def);
> +			char *type_str = is_view ? NULL :
> +					 sql_index_type_str(parse->db,
> +							    pk->def);
>   			sqlite3VdbeAddOp4(v, OP_MakeRecord, reg_pk, pk_len,
> -					  reg_key, zAff, pk_len);
> +					  reg_key, type_str, is_view ? 0 :
> +							     P4_DYNAMIC);

3. How did it work before your patch? Looks like it was a leak. Before the
patch, pk_len was passed instead of STATIC/DYNAMIC.

>   			/* Set flag to save memory allocating one
>   			 * by malloc.
>   			 */
> diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
> index 917e6e30b..c823c5a06 100644
> --- a/src/box/sql/expr.c
> +++ b/src/box/sql/expr.c
> @@ -2858,8 +2858,11 @@ sqlite3CodeSubselect(Parse * pParse,	/* Parsing context */
>   						jmpIfDynamic = -1;
>   					}
>   					r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
> +					char type =
> +						sql_affinity_to_field_type(affinity);
>   	 				sqlite3VdbeAddOp4(v, OP_MakeRecord, r3,
> -							  1, r2, &affinity, 1);
> +							  1, r2, &type,
> +							  1);

4. I do not understand. Is p4type of sqlite3VdbeAddOp4 of OP_MakeRecord
a length of an affinity string, or a type of its allocation? Or both?

Also, I wonder how does this code works:

	if (zAffinity) {
		pRec = pData0;
		do{
			mem_apply_type(pRec++, *(zAffinity++));
		}while( zAffinity[0]);
	}

in OP_MakeRecord. It assumes, that zAffinity is a null-terminated string,
but in the code above you pass one char, without zero-termination.

>   					sqlite3ExprCacheAffinityChange(pParse,
>   								       r3, 1);
>   					sqlite3VdbeAddOp2(v, OP_IdxInsert, r2,
> @@ -3172,7 +3175,8 @@ sqlite3ExprCodeIN(Parse * pParse,	/* Parsing and code generating context */
>   	 * of the RHS using the LHS as a probe.  If found, the result is
>   	 * true.
>   	 */
> -	sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
> +	char *type_str = sql_affinity_str_to_field_type_str(zAff);
> +	sqlite3VdbeAddOp4(v, OP_ApplyType, rLhs, nVector, 0, type_str, nVector);

5. type_str is dynamically allocated, nVector (== p4type) is > 0. But freeP4
function in vdbeaux.c does not know how to free p4type > 0. So it is definitely
a leak. Please, validate all places where dynamic type string is created.

>   	if (destIfFalse == destIfNull) {
>   		/* Combine Step 3 and Step 5 into a single opcode */
>   		sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable,
> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> index 4345af24e..369fb4b79 100644
> --- a/src/box/sql/vdbe.c
> +++ b/src/box/sql/vdbe.c
> @@ -306,32 +306,35 @@ applyNumericAffinity(Mem *pRec, int bTryForInt)
>   }
>   
>   /**
> - * Processing is determine by the affinity parameter:
> + * Processing is determine by the field type parameter:
>    *
> - * AFFINITY_INTEGER:
> - * AFFINITY_REAL:
> - *    Try to convert mem to an integer representation or a
> - *    floating-point representation if an integer representation
> - *    is not possible.  Note that the integer representation is
> - *    always preferred, even if the affinity is REAL, because
> - *    an integer representation is more space efficient on disk.
> + * INTEGER:
> + *    If memory holds floating point value and it can be
> + *    converted without loss (2.0 - > 2), it's type is
> + *    changed to INT. Otherwise, simply return success status.
>    *
> - * AFFINITY_TEXT:
> - *    Convert mem to a text representation.
> + * NUMBER:
> + *    If memory holds INT or floating point value,
> + *    no actions take place.
>    *
> - * AFFINITY_BLOB:
> - *    No-op. mem is unchanged.
> + * STRING:
> + *    Convert mem to a string representation.
>    *
> - * @param record The value to apply affinity to.
> - * @param affinity The affinity to be applied.
> + * SCALAR:
> + *    Mem is unchanged, but flat is set to BLOB.

6. flat -> flag?

> + *
> + * @param record The value to apply type to.
> + * @param type_t The type to be applied.
>    */
>   static int
> -mem_apply_affinity(struct Mem *record, enum affinity_type affinity)
> +mem_apply_type(struct Mem *record, enum field_type f_type)
>   {
>   	if ((record->flags & MEM_Null) != 0)
>   		return 0;
> -	switch (affinity) {
> -	case AFFINITY_INTEGER:
> +	assert(f_type  < field_type_MAX);

7. Double white-space.

> +	switch (f_type) {
> +	case FIELD_TYPE_INTEGER:
> +	case FIELD_TYPE_UNSIGNED:
>   		if ((record->flags & MEM_Int) == MEM_Int)
>   			return 0;
>   		if ((record->flags & MEM_Real) == MEM_Real) {
> diff --git a/src/box/sql/where.c b/src/box/sql/where.c
> index 571b5af78..539296079 100644
> --- a/src/box/sql/where.c
> +++ b/src/box/sql/where.c
> @@ -1200,7 +1200,7 @@ whereRangeSkipScanEst(Parse * pParse,		/* Parsing & code generating context */
>   	int nLower = -1;
>   	int nUpper = index->def->opts.stat->sample_count + 1;
>   	int rc = SQLITE_OK;
> -	u8 aff = sql_space_index_part_affinity(space->def, p, nEq);
> +	u8 aff = p->key_def->parts[nEq].type;

8. Why? Below in this function aff is used as affinity, not type.

>   
>   	sqlite3_value *p1 = 0;	/* Value extracted from pLower */
>   	sqlite3_value *p2 = 0;	/* Value extracted from pUpper */

  reply	other threads:[~2018-12-29 17:42 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-28  9:34 [tarantool-patches] [PATCH 0/8] Eliminate affinity from source code Nikita Pettik
2018-12-28  9:34 ` [tarantool-patches] [PATCH 1/8] sql: remove SQLITE_ENABLE_UPDATE_DELETE_LIMIT define Nikita Pettik
2018-12-29 17:42   ` [tarantool-patches] " Vladislav Shpilevoy
2019-01-16 14:25     ` n.pettik
2018-12-28  9:34 ` [tarantool-patches] [PATCH 2/8] sql: use field type instead of affinity for type_def Nikita Pettik
2018-12-29 17:42   ` [tarantool-patches] " Vladislav Shpilevoy
2019-01-16 14:26     ` n.pettik
2018-12-28  9:34 ` [tarantool-patches] [PATCH 3/8] sql: remove numeric affinity Nikita Pettik
2018-12-29  9:01   ` [tarantool-patches] " Konstantin Osipov
2018-12-29 17:42   ` Vladislav Shpilevoy
2019-01-09  8:26     ` Konstantin Osipov
2019-01-16 14:26     ` n.pettik
2019-01-22 15:41       ` Vladislav Shpilevoy
2019-01-28 16:39         ` n.pettik
2019-01-30 13:04           ` Vladislav Shpilevoy
2019-02-01 16:39             ` n.pettik
2019-01-09  8:20   ` Konstantin Osipov
2018-12-28  9:34 ` [tarantool-patches] [PATCH 4/8] sql: replace affinity with field type for func Nikita Pettik
2018-12-28  9:34 ` [tarantool-patches] [PATCH 5/8] sql: replace field type with affinity for VDBE runtime Nikita Pettik
2018-12-29 17:42   ` Vladislav Shpilevoy [this message]
2019-01-16 14:26     ` [tarantool-patches] " n.pettik
2019-01-22 15:41       ` Vladislav Shpilevoy
2019-01-28 16:39         ` n.pettik
2019-01-30 13:04           ` Vladislav Shpilevoy
2019-02-01 16:39             ` n.pettik
2019-02-05 15:08               ` Vladislav Shpilevoy
2019-02-05 17:46                 ` n.pettik
2018-12-28  9:34 ` [tarantool-patches] [PATCH 6/8] sql: replace affinity with field type in struct Expr Nikita Pettik
2018-12-29 17:42   ` [tarantool-patches] " Vladislav Shpilevoy
2019-01-16 14:26     ` n.pettik
2019-01-22 15:41       ` Vladislav Shpilevoy
2019-01-28 16:39         ` n.pettik
2019-01-30 13:04           ` Vladislav Shpilevoy
2019-02-01 16:39             ` n.pettik
2019-02-05 15:08               ` Vladislav Shpilevoy
2019-02-05 17:46                 ` n.pettik
2018-12-28  9:34 ` [tarantool-patches] [PATCH 7/8] sql: clean-up affinity from SQL source code Nikita Pettik
2018-12-29 17:42   ` [tarantool-patches] " Vladislav Shpilevoy
2019-01-16 14:26     ` n.pettik
2019-01-22 15:41       ` Vladislav Shpilevoy
2019-01-28 16:40         ` n.pettik
2019-01-30 13:04           ` Vladislav Shpilevoy
2019-02-01 16:39             ` n.pettik
2019-02-05 15:08               ` Vladislav Shpilevoy
2019-02-05 17:46                 ` n.pettik
2018-12-28  9:34 ` [tarantool-patches] [PATCH 8/8] Remove affinity from field definition Nikita Pettik
2019-02-05 19:41 ` [tarantool-patches] Re: [PATCH 0/8] Eliminate affinity from source code Vladislav Shpilevoy
2019-02-08 13:37 ` 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=6e7623ee-fdcc-616f-6a99-20aff0e97f43@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=korablev@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='[tarantool-patches] Re: [PATCH 5/8] sql: replace field type with affinity for VDBE runtime' \
    /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