[Tarantool-patches] [PATCH v4 4/5] sql: change implicit cast for assignment

Nikita Pettik korablev at tarantool.org
Mon Jul 13 17:42:55 MSK 2020


On 13 Jul 08:33, imeevma at tarantool.org wrote:
> +
>   * Synopsis: type(r[P1 at P2])
>   *
> - * Apply types to a range of P2 registers starting with P1.
> - *
> - * P4 is a string that is P2 characters long. The nth character of the
> - * string indicates the column type that should be used for the nth
> - * memory cell in the range.
> + * Check that types of P2 registers starting from register P1 are
> + * compatible with given field types in P4. If the MEM_type of the
> + * value and the given type are incompatible according to
> + * field_mp_plain_type_is_compatible(), but both are numeric,
> + * this opcode attempts to convert the value to the type.
>   */
>  case OP_ApplyType: {
>  	enum field_type *types = pOp->p4.types;
> @@ -2762,7 +2900,13 @@ case OP_ApplyType: {
>  	while((type = *(types++)) != field_type_MAX) {
>  		assert(pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)]);
>  		assert(memIsValid(pIn1));
> -		if (mem_apply_type(pIn1, type) != 0) {
> +		if (mem_is_type_compatible(pIn1, type)) {
> +			pIn1++;
> +			continue;
> +		}
> +		if (!mp_type_is_numeric(mem_mp_type(pIn1)) ||
> +		    !sql_type_is_numeric(type) ||
> +		    mem_convert_to_numeric(pIn1, type, false) != 0) {

Consider refactoring:

diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 863f38f5d..41a4750da 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -2900,19 +2900,23 @@ case OP_ApplyType: {
        while((type = *(types++)) != field_type_MAX) {
                assert(pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)]);
                assert(memIsValid(pIn1));
-               if (mem_is_type_compatible(pIn1, type)) {
-                       pIn1++;
-                       continue;
-               }
-               if (!mp_type_is_numeric(mem_mp_type(pIn1)) ||
-                   !sql_type_is_numeric(type) ||
-                   mem_convert_to_numeric(pIn1, type, false) != 0) {
-                       diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-                                sql_value_to_diag_str(pIn1),
-                                field_type_strs[type]);
-                       goto abort_due_to_error;
+               if (!mem_is_type_compatible(pIn1, type)) {
+                       /* Implicit cast is allowed only to numeric type. */
+                       if (!sql_type_is_numeric(type))
+                               goto type_mismatch;
+                       /* Implicit cast is allowed only from numeric type. */
+                       if (!mp_type_is_numeric(mem_mp_type(pIn1)))
+                               goto type_mismatch;
+                       /* Try to convert numeric-to-numeric. */
+                       if (mem_convert_to_numeric(pIn1, type, false) != 0)
+                               goto type_mismatch;
                }
                pIn1++;
+               continue;
+type_mismatch:
+               diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+                        sql_value_to_diag_str(pIn1), field_type_strs[type]);
+               goto abort_due_to_error;
        }
        break;
 }

Otherwise LGTM

>  			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
>  				 sql_value_to_diag_str(pIn1),
>  				 field_type_strs[type]);
> diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
> index 44c27bdb7..ad46ab129 100644
> --- a/src/box/sql/vdbeInt.h
> +++ b/src/box/sql/vdbeInt.h
> @@ -566,6 +566,10 @@ mem_mp_type(struct Mem *mem);
>   */
>  #define mp_type_is_bloblike(X) ((X) == MP_BIN || (X) == MP_ARRAY || (X) == MP_MAP)
>  
> +/** Return TRUE if MP_type of X is numeric, FALSE otherwise. */
> +#define mp_type_is_numeric(X) ((X) == MP_INT || (X) == MP_UINT ||\
> +			       (X) == MP_DOUBLE)


More information about the Tarantool-patches mailing list