Tarantool development patches archive
 help / color / mirror / Atom feed
From: "n.pettik" <korablev@tarantool.org>
To: tarantool-patches@freelists.org
Cc: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Subject: [tarantool-patches] Re: [PATCH 6/8] sql: replace affinity with field type in struct Expr
Date: Wed, 16 Jan 2019 17:26:24 +0300	[thread overview]
Message-ID: <8D9E26B4-FC3D-4EBD-9941-5570A5ECFA17@tarantool.org> (raw)
In-Reply-To: <406a1cab-d3cd-437b-668e-141697fbd637@tarantool.org>


>>  -enum affinity_type
>> -sql_affinity_result(enum affinity_type aff1, enum affinity_type aff2)
>> +enum field_type
>> +sql_type_result(enum field_type lhs, enum field_type rhs)
>>  {
>> -	if (aff1 && aff2) {
>> -		/* Both sides of the comparison are columns. If one has numeric
>> -		 * affinity, use that. Otherwise use no affinity.
>> +	if (lhs != FIELD_TYPE_ANY && rhs != FIELD_TYPE_ANY) {
>> +		/*
>> +		 * Both sides of the comparison are columns.
>> +		 * If one has numeric type, use that.
>>  		 */
> 
> 1. The comment is useless IMO. It just repeats exactly the
> same obvious thing what is written in the next line.

Ok, I’d rather agree. I simply copied that comment from
original SQLite function. Now removed:

diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 4816310c3..ba7269d08 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -235,15 +235,10 @@ enum field_type
 sql_type_result(enum field_type lhs, enum field_type rhs)
 {
        if (lhs != FIELD_TYPE_ANY && rhs != FIELD_TYPE_ANY) {
-               /*
-                * Both sides of the comparison are columns.
-                * If one has numeric type, use that.
-                */

> 
>> -		if (sqlite3IsNumericAffinity(aff1)
>> -		    || sqlite3IsNumericAffinity(aff2)) {
>> -			return AFFINITY_REAL;
>> -		} else {
>> -			return AFFINITY_BLOB;
>> -		}
>> -	} else if (!aff1 && !aff2) {
>> -		/* Neither side of the comparison is a column.  Compare the
>> -		 * results directly.
>> +		if (sql_type_is_numeric(lhs) || sql_type_is_numeric(rhs))
>> +			return FIELD_TYPE_NUMBER;
>> +		else
>> +			return FIELD_TYPE_SCALAR;
>> +
> 
> 2. Unnecessary empty line.

Removed:

                if (sql_type_is_numeric(lhs) || sql_type_is_numeric(rhs))
                        return FIELD_TYPE_NUMBER;
                else
                        return FIELD_TYPE_SCALAR;
-
        } else if (lhs == FIELD_TYPE_ANY && rhs == FIELD_TYPE_ANY) {
                /*
                 * Neither side of the comparison is a column.

> 
>> +	} else if (lhs == FIELD_TYPE_ANY && rhs == FIELD_TYPE_ANY) {
>> +		/*
>> +		 * Neither side of the comparison is a column.
>> +		 * Compare the results directly.
>>  		 */
>> -		return AFFINITY_BLOB;
>> +		return FIELD_TYPE_SCALAR;
>>  	} else {
>> -		/* One side is a column, the other is not. Use the columns affinity. */
>> -		assert(aff1 == 0 || aff2 == 0);
>> -		return (aff1 + aff2);
>> +		if (lhs == FIELD_TYPE_ANY)
>> +			return rhs;
>> +		return lhs;
>>  	}
>>  }
>>  @@ -285,45 +261,44 @@ sql_affinity_result(enum affinity_type aff1, enum affinity_type aff2)
>>   * pExpr is a comparison operator.  Return the type affinity that should
>>   * be applied to both operands prior to doing the comparison.
>>   */
>> -static char
>> +static enum field_type
>>  comparisonAffinity(Expr * pExpr)
> 
> 3. But it is not affinity anymore.

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)
+comparison_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 ||

>>  -/*
>> - * pExpr is a comparison expression, eg. '=', '<', IN(...) etc.
>> - * idx_affinity is the affinity of an indexed column. Return true
>> - * if the index with affinity idx_affinity may be used to implement
>> - * the comparison in pExpr.
>> +/**
>> + * @param expr is a comparison expression, eg. '=', '<', IN(...) etc.
>> + * @param idx_affinity is the affinity of an indexed column.
>> + * @retval Return true if the index with @idx_type may be used to
>> + * implement the comparison in expr.
>>   */
>> -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 ||

> Also, sorry, but I hate this suffix '_ok' or 'Ok'. It just says
> nothing about what this function does. As well as that it has
> nothing to do with an index, but has 'index' in the name.
> 
> Maybe rename to something like 'sql_expr_cmp_type_is_possible’ ?

Done:

@@ -289,9 +285,9 @@ comparisonAffinity(Expr * pExpr)
  * implement the comparison in expr.
  */
 enum field_type
-sql_index_type_is_ok(struct Expr *expr, enum field_type idx_type)
+sql_expr_cmp_type_is_compatible(struct Expr *expr, enum field_type idx_type)
 {
-       enum field_type type = comparisonAffinity(expr);
+       enum field_type type = expr_cmp_mutual_type(expr);
        switch (type) {
        case FIELD_TYPE_SCALAR:
                return 1;
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 216e8d57f..7116f34c5 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -4261,7 +4261,7 @@ enum field_type
 sql_type_result(enum field_type lhs, enum field_type rhs);
 
 enum field_type
-sql_index_type_is_ok(struct Expr *expr, enum field_type idx_type);
+sql_expr_cmp_type_is_compatible(struct Expr *expr, enum field_type idx_type);
 
 /**
  * Return the type of the expression pExpr.
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index 54531a8a5..a2e55e8ac 100644
--- a/src/box/sql/where.c
+++ b/src/box/sql/where.c
@@ -298,7 +298,7 @@ whereScanNext(WhereScan * pScan)
                                                /* Verify the affinity and collating sequence match */
                                                if ((pTerm->eOperator & WO_ISNULL) == 0) {
                                                        pX = pTerm->pExpr;
-                                                       if (!sql_index_type_is_ok(pX, pScan->idx_type))
+                                                       if (!sql_expr_cmp_type_is_compatible(pX, pScan->idx_type))
                                                                continue;
                                                        if (pScan->is_column_seen) {
                                                                Parse *pParse =

> 
>>  {
>> -	char aff = comparisonAffinity(pExpr);
>> -	switch (aff) {
>> -	case AFFINITY_BLOB:
>> +	enum field_type type = comparisonAffinity(expr);
>> +	switch (type) {
>> +	case FIELD_TYPE_SCALAR:
>>  		return 1;
>> -	case AFFINITY_TEXT:
>> -		return idx_affinity == AFFINITY_TEXT;
>> +	case FIELD_TYPE_STRING:
>> +		return idx_type == FIELD_TYPE_STRING;
>>  	default:
>> -		return sqlite3IsNumericAffinity(idx_affinity);
>> +		return sql_type_is_numeric(idx_type);
>>  	}
>>  }
>>  @@ -2155,10 +2130,10 @@ sqlite3ExprCanBeNull(const Expr * p)
>>   * answer.
>>   */
>>  int
>> -sqlite3ExprNeedsNoAffinityChange(const Expr * p, char aff)
>> +sql_expr_needs_type_change(const Expr *p, enum field_type type)
> 
> 5. Name is changed from negative to positive, but the logic is
> the same, why? Original was 'NoChange', now it is 'needs_change’.

My fault, missed ’no’ particle. Fixed:

-/*
- * 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_type_change(const Expr *p, enum field_type type)
+sql_expr_needs_no_type_change(const Expr *p, enum field_type type)

diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 216e8d57f..5541cb6b2 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -3710,8 +3710,18 @@ int sqlite3ExprIsTableConstant(Expr *, int);
 int sqlite3ExprIsInteger(Expr *, int *);
 int sqlite3ExprCanBeNull(const Expr *);
 
+/**
+ * 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_type_change(const Expr *epr, enum field_type type);
+sql_expr_needs_no_type_change(const Expr *epr, enum field_type type);

diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index fe5c56c07..98b55db7a 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -428,7 +428,7 @@ updateRangeAffinityStr(Expr * pRight,       /* RHS of comparison */
                Expr *p = sqlite3VectorFieldSubexpr(pRight, i);
                enum field_type expr_type = sql_expr_type(p);
                if (sql_type_result(expr_type, type) == FIELD_TYPE_SCALAR ||
-                   sql_expr_needs_type_change(p, type)) {
+                       sql_expr_needs_no_type_change(p, type)) {
                        zAff[i] = AFFINITY_BLOB;
                }
        }
@@ -788,7 +788,7 @@ codeAllEqualityTerms(Parse * pParse,        /* Parsing context */
                                    FIELD_TYPE_SCALAR) {
                                        zAff[j] = AFFINITY_BLOB;
                                }
-                               if (sql_expr_needs_type_change(pRight, idx_type))
+                               if (sql_expr_needs_no_type_change(pRight, idx_type))
                                        zAff[j] = AFFINITY_BLOB;
                        }

> Also, please, move the function comment to the declaration in sqliteInt.h.

Done, see above.

> 
>>  {
>>  	u8 op;
>> -	if (aff == AFFINITY_BLOB)
>> +	if (type == FIELD_TYPE_SCALAR)
>>  		return 1;
>>  	while (p->op == TK_UPLUS || p->op == TK_UMINUS) {
>>  		p = p->pLeft;
>> @@ -2167,27 +2142,21 @@ sqlite3ExprNeedsNoAffinityChange(const Expr * p, char aff)
>>  	if (op == TK_REGISTER)
>>  		op = p->op2;
>>  	switch (op) {
>> -	case TK_INTEGER:{
>> -			return aff == AFFINITY_INTEGER;
>> -		}
>> -	case TK_FLOAT:{
>> -			return aff == AFFINITY_REAL;
>> -		}
>> -	case TK_STRING:{
>> -			return aff == AFFINITY_TEXT;
>> -		}
>> -	case TK_BLOB:{
>> -			return 1;
>> -		}
>> +	case TK_INTEGER:
>> +		return type == FIELD_TYPE_INTEGER;
>> +	case TK_FLOAT:
>> +		return type == FIELD_TYPE_NUMBER;
>> +	case TK_STRING:
>> +		return type == FIELD_TYPE_STRING;
>> +	case TK_BLOB:
>> +		return 1;
>>  	case TK_COLUMN:{
>> -			assert(p->iTable >= 0);	/* p cannot be part of a CHECK constraint */
>> -			return p->iColumn < 0
>> -			    && (aff == AFFINITY_INTEGER
>> -				|| aff == AFFINITY_REAL);
>> -		}
>> -	default:{
>> -			return 0;
>> +			/* p cannot be part of a CHECK constraint. */
>> +			assert(p->iTable >= 0);
>> +			return p->iColumn < 0 && sql_type_is_numeric(type);
>>  		}
> 
> 6. Please, remove these braces too, if you decided to refactor
> sqlite3ExprNeedsNoAffinityChange.

Ok:

@@ -2150,11 +2136,10 @@ sql_expr_needs_type_change(const Expr *p, enum field_type type)
                return type == FIELD_TYPE_STRING;
        case TK_BLOB:
                return 1;
-       case TK_COLUMN:{
-                       /* p cannot be part of a CHECK constraint. */
-                       assert(p->iTable >= 0);
-                       return p->iColumn < 0 && sql_type_is_numeric(type);
-               }
+       case TK_COLUMN:
+               /* p cannot be part of a CHECK constraint. */
+               assert(p->iTable >= 0);
+               return p->iColumn < 0 && sql_type_is_numeric(type);
        default:

> 
>> +	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

After it hits 2.1, I will replace SCALAR with ANY.

> 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).

> 
>>  				bool unused;
>>  				sql_expr_coll(pParse, pExpr->pLeft,
>>  					      &unused, &key_info->parts[0].coll_id);
>> diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
>> index 690fa6431..7d1159345 100644
>> --- a/src/box/sql/sqliteInt.h
>> +++ b/src/box/sql/sqliteInt.h
>> @@ -2092,7 +2094,7 @@ struct Expr {
>>  	u8 op;			/* Operation performed by this node */
>>  	union {
>>  		/** The affinity of the column. */
> 
> 8. Not affinity anymore.

Fixed:

diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 216e8d57f..209e7bf0f 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -2093,7 +2093,7 @@ typedef int ynVar;
 struct Expr {
        u8 op;                  /* Operation performed by this node */
        union {
-               /** The affinity of the column. */
+               /** The Type of the column. */

> 
>> -		enum affinity_type affinity;
>> +		enum field_type type;
>>  		/** Conflict action for RAISE() function. */
>>  		enum on_conflict_action on_conflict_action;
>>  	};
>> @@ -4253,26 +4257,30 @@ sql_index_type_str(struct sqlite3 *db, const struct index_def *idx_def);
>>  void
>>  sql_emit_table_types(struct Vdbe *v, struct space_def *def, int reg);
>>  -/**
>> - * Return superposition of two affinities.
>> - * This may be required for determining resulting
>> - * affinity of expressions like a + '2'.
>> - */
>> -enum affinity_type
>> -sql_affinity_result(enum affinity_type aff1, enum affinity_type aff2);
>> +enum field_type
>> +sql_type_result(enum field_type lhs, enum field_type rhs);
>>  -int sqlite3IndexAffinityOk(Expr * pExpr, char idx_affinity);
>> +enum field_type
>> +sql_index_type_is_ok(struct Expr *expr, enum field_type idx_type);
>>    /**
>> - * Return the affinity character for a single column of a table.
>> - * @param def space definition.
>> - * @param idx column index.
>> - * @retval AFFINITY
>> + * Return the type of the expression pExpr.
>> + *
>> + * If pExpr is a column, a reference to a column via an 'AS' alias,
>> + * or a sub-select with a column as the return value, then the
>> + * type of that column is returned. Otherwise, type ANY is returned,
>> + * indicating that the expression can feature any type.
> 
> 9. Returning to point 7 - I do not think it should return ANY. Anyway
> you convert it to SCALAR in all places.

See explanation above.

> 
>> + *
>> + * The WHERE clause expressions in the following statements all
>> + * have an type:
>> + *
>> + * CREATE TABLE t1(a);
>> + * SELECT * FROM t1 WHERE a;
>> + * SELECT a AS b FROM t1 WHERE b;
>> + * SELECT * FROM t1 WHERE (select a from t1);
>>   */
>> -char
>> -sqlite3TableColumnAffinity(struct space_def *def, int idx);
>> -
>> -char sqlite3ExprAffinity(Expr * pExpr);
>> +enum field_type
>> +sql_expr_type(Expr *pExpr);
>>      /**
>> diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
>> index aae5d6617..06335bcf7 100644
>> --- a/src/box/sql/wherecode.c
>> +++ b/src/box/sql/wherecode.c
>> @@ -392,6 +392,7 @@ codeApplyAffinity(Parse * pParse, int base, int n, char *zAff)
>>  		base++;
>>  		zAff++;
>>  	}
>> +
>>  	while (n > 1 && zAff[n - 1] == AFFINITY_BLOB) {
> 
> 10. Garbage diff.

Fixed:

diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index fe5c56c07..33b860f36 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -392,7 +392,6 @@ codeApplyAffinity(Parse * pParse, int base, int n, char *zAff)
                base++;
                zAff++;
        }
-
        while (n > 1 && zAff[n - 1] == AFFINITY_BLOB) {
                n--;
        }

  reply	other threads:[~2019-01-16 14:26 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   ` [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 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 [this message]
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=8D9E26B4-FC3D-4EBD-9941-5570A5ECFA17@tarantool.org \
    --to=korablev@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='[tarantool-patches] Re: [PATCH 6/8] sql: replace affinity with field type in struct Expr' \
    /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