[tarantool-patches] Re: [PATCH 6/8] sql: replace affinity with field type in struct Expr
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Tue Jan 22 18:41:13 MSK 2019
Thanks for the fixes!
>>> -int
>>> -sqlite3IndexAffinityOk(Expr * pExpr, char idx_affinity)
>>> +enum field_type
>>> +sql_index_type_is_ok(struct Expr *expr, enum field_type idx_type)
>>
>> 4. Strictly speaking, it is not idx_type. It is a type of one
>> column. I think, it should be renamed to just type, or field_type,
>> as well as in struct WhereScan.
>
> Yea, it’s fair. Renamed:
>
> -/*
> - * pExpr is a comparison operator. Return the type affinity that should
> - * be applied to both operands prior to doing the comparison.
> +/**
> + * pExpr is a comparison operator. Return the type affinity
> + * that should be applied to both operands prior to doing
> + * the comparison.
> */
> static enum field_type
> -comparisonAffinity(Expr * pExpr)
> +expr_cmp_mutual_type(struct Expr *pExpr)
> {
> assert(pExpr->op == TK_EQ || pExpr->op == TK_IN || pExpr->op == TK_LT ||
> pExpr->op == TK_GT || pExpr->op == TK_GE || pExpr->op == TK_LE ||
>
Are you sure? Looks like it is not renamed. Also, the comment
was about sql_index_type_is_ok and its parameter idx_type, but you
changed comparisonAffinity function.
>>> + default:
>>> + return 0;
>>> }
>>> }
>>> @@ -2826,16 +2795,15 @@ sqlite3CodeSubselect(Parse * pParse, /* Parsing context */
>>> * that columns affinity when building index keys. If <expr> is not
>>> * a column, use numeric affinity.
>>> */
>>> - char affinity; /* Affinity of the LHS of the IN */
>>> int i;
>>> ExprList *pList = pExpr->x.pList;
>>> struct ExprList_item *pItem;
>>> int r1, r2, r3;
>>> - affinity = sqlite3ExprAffinity(pLeft);
>>> - if (!affinity) {
>>> - affinity = AFFINITY_BLOB;
>>> - }
>>> + enum field_type lhs_type =
>>> + sql_expr_type(pLeft);
>>> + if (lhs_type == FIELD_TYPE_ANY)
>>> + lhs_type = FIELD_TYPE_SCALAR;
>>
>> 7. Why did not you move this conversion to sql_expr_type? I mean
>> ANY -> SCALAR.
>
> Unfortunately, right now I can’t replace it with ANY. It is still used
> when IN operator comes with one operand (see EP_Generic flag).
> I have already sent patch which removes it:
> https://github.com/tarantool/tarantool/tree/np/gh-3934-IN-operator-fix
I've already acked the patch. Please, hurry up Kirill Y. to push it,
rebase this branch, and replace ANY with SCALAR.
>
> After it hits 2.1, I will replace SCALAR with ANY.
Vice versa? Not SCALAR with ANY, but ANY with SCALAR, I think.
>
>> ANY differs from SCALAR in only one thing - it is
>> able to store MP_MAP and MP_ARRAY. So I am slightly bent upon
>> frequency of ANY usage in SQL, wherein MAP/ARRAY does not exist.
>
> But still we can SELECT data from spaces created from Lua.
> For instance, _fk_constraint features type ARRAY in its format,
> so we can’t ignore this type even now (IMHO).
Despite our ability to select complex types, in SQL they are all
mere binary data with *sub*type msgpack, not array/map type. So
in SQL we never truly work with anything but SCALAR.
See 5 comments below.
> -/*
> - * Return TRUE if the given expression is a constant which would be
> - * unchanged by OP_ApplyType with the type given in the second
> - * argument.
> - *
> - * This routine is used to determine if the OP_ApplyType operation
> - * can be omitted. When in doubt return FALSE. A false negative
> - * is harmless. A false positive, however, can result in the wrong
> - * answer.
> - */
> int
> -sqlite3ExprNeedsNoAffinityChange(const Expr * p, char aff)
> +sql_expr_needs_no_type_change(const Expr *p, enum field_type type)
1. const Expr -> const struct Expr
> -int sqlite3ExprNeedsNoAffinityChange(const Expr *, char);
> +
> +/**
> + * Return TRUE if the given expression is a constant which would
> + * be unchanged by OP_ApplyType with the type given in the second
> + * argument.
> + *
> + * This routine is used to determine if the OP_ApplyType operation
> + * can be omitted. When in doubt return FALSE. A false negative
> + * is harmless. A false positive, however, can result in the wrong
> + * answer.
> + */
> +int
> +sql_expr_needs_no_type_change(const Expr *epr, enum field_type type);
2. epr -> p, and the same as 1.
> diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
> index cd71641b0..d12a2a833 100644
> --- a/src/box/sql/vdbemem.c
> +++ b/src/box/sql/vdbemem.c
> @@ -1316,8 +1315,8 @@ valueFromExpr(sqlite3 * db, /* The database connection */
> sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_DYNAMIC);
> }
> if ((op == TK_INTEGER || op == TK_FLOAT)
> - && affinity == AFFINITY_BLOB) {
> - sqlite3ValueApplyAffinity(pVal, AFFINITY_REAL);
> + && affinity == FIELD_TYPE_SCALAR) {
> + sqlite3ValueApplyAffinity(pVal, FIELD_TYPE_INTEGER);
3. Why before your patch it was REAL and now it is INTEGER?
> } else {
> sqlite3ValueApplyAffinity(pVal, affinity);
> }
> diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
> index efbc91cf8..33b860f36 100644
> --- a/src/box/sql/wherecode.c
> +++ b/src/box/sql/wherecode.c
> @@ -423,10 +423,11 @@ updateRangeAffinityStr(Expr * pRight, /* RHS of comparison */
> {
> int i;
> for (i = 0; i < n; i++) {
> + enum field_type type = sql_affinity_to_field_type(zAff[i]);
> Expr *p = sqlite3VectorFieldSubexpr(pRight, i);
> - enum affinity_type aff = sqlite3ExprAffinity(p);
> - if (sql_affinity_result(aff, zAff[i]) == AFFINITY_BLOB
> - || sqlite3ExprNeedsNoAffinityChange(p, zAff[i])) {
> + enum field_type expr_type = sql_expr_type(p);
> + if (sql_type_result(expr_type, type) == FIELD_TYPE_SCALAR ||
> + sql_expr_needs_no_type_change(p, type)) {
> zAff[i] = AFFINITY_BLOB;
> }
> }
4. Something is wrong with formatting. sql_expr_needs_no_type_change should be
aligned under sql_type_result as a part of the condition.
> @@ -1166,20 +1167,12 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t
> }
> struct index_def *idx_pk = space->index[0]->def;
> int fieldno = idx_pk->key_def->parts[0].fieldno;
> - char affinity = is_format_set ?
> - space->def->fields[fieldno].affinity :
> - AFFINITY_BLOB;
> - if (affinity == AFFINITY_UNDEFINED) {
> - if (idx_pk->key_def->part_count == 1 &&
> - space->def->fields[fieldno].type ==
> - FIELD_TYPE_INTEGER)
> - affinity = AFFINITY_INTEGER;
> - else
> - affinity = AFFINITY_BLOB;
> - }
> + char fd_type = is_format_set ?
> + space->def->fields[fieldno].type :
> + FIELD_TYPE_ANY;
>
5. Why char? And the alignment is slightly wrong. Non-first lines
should be aligned under is_format_set.
More information about the Tarantool-patches
mailing list