[Tarantool-patches] [PATCH v1 2/2] sql: remove implicit cast in bitwise operations
imeevma at tarantool.org
imeevma at tarantool.org
Fri Aug 21 11:40:52 MSK 2020
This patch removes the implicit conversion from STRING to INTEGER from
bitwise operations. However, DOUBLE can still be implicitly converted to
INTEGER.
Follow-up #3809
---
src/box/sql/vdbe.c | 59 ++++++++++++++++++++++++++++++++---------
test/sql/types.result | 49 ++++++++++++++++++++++++++++++++++
test/sql/types.test.lua | 14 ++++++++++
3 files changed, 110 insertions(+), 12 deletions(-)
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index c0143a6b1..a8db6d076 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -1989,19 +1989,44 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
pIn1 = &aMem[pOp->p1];
pIn2 = &aMem[pOp->p2];
+ enum mp_type type1 = mem_mp_type(pIn1);
+ enum mp_type type2 = mem_mp_type(pIn2);
pOut = vdbe_prepare_null_out(p, pOp->p3);
- if ((pIn1->flags | pIn2->flags) & MEM_Null) {
+ if (type1 == MP_NIL || type2 == MP_NIL) {
/* Force NULL be of type INTEGER. */
pOut->field_type = FIELD_TYPE_INTEGER;
break;
}
- bool unused;
- if (sqlVdbeIntValue(pIn2, (int64_t *) &iA, &unused) != 0) {
+ if (type2 == MP_DOUBLE) {
+ double r = pIn2->u.r;
+ if (r >= 0 && r < (double)UINT64_MAX) {
+ iB = (int64_t)(uint64_t)r;
+ type2 = MP_UINT;
+ } else if (r >= (double)INT64_MIN && r < 0) {
+ iB = (int64_t)r;
+ type2 = MP_INT;
+ }
+ }
+ if (type2 == MP_INT || type2 == MP_UINT) {
+ iB = pIn2->u.i;
+ } else {
diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
sql_value_to_diag_str(pIn2), "integer");
goto abort_due_to_error;
}
- if (sqlVdbeIntValue(pIn1, (int64_t *) &iB, &unused) != 0) {
+ if (type1 == MP_DOUBLE) {
+ double r = pIn1->u.r;
+ if (r >= 0 && r < (double)UINT64_MAX) {
+ iA = (int64_t)(uint64_t)r;
+ type1 = MP_UINT;
+ } else if (r >= (double)INT64_MIN && r < 0) {
+ iA = (int64_t)r;
+ type1 = MP_INT;
+ }
+ }
+ if (type1 == MP_INT || type1 == MP_UINT) {
+ iA = pIn1->u.i;
+ } else {
diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
sql_value_to_diag_str(pIn1), "integer");
goto abort_due_to_error;
@@ -2621,19 +2646,29 @@ case OP_Not: { /* same as TK_NOT, in1, out2 */
*/
case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
pIn1 = &aMem[pOp->p1];
+ enum mp_type type = mem_mp_type(pIn1);
pOut = vdbe_prepare_null_out(p, pOp->p2);
/* Force NULL be of type INTEGER. */
pOut->field_type = FIELD_TYPE_INTEGER;
- if ((pIn1->flags & MEM_Null)==0) {
- int64_t i;
- bool is_neg;
- if (sqlVdbeIntValue(pIn1, &i, &is_neg) != 0) {
- diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
- sql_value_to_diag_str(pIn1), "integer");
- goto abort_due_to_error;
+ int64_t i;
+ if (type == MP_DOUBLE) {
+ double r = pIn1->u.r;
+ if (r >= 0 && r < (double)UINT64_MAX) {
+ i = (int64_t)(uint64_t)r;
+ type = MP_UINT;
+ } else if (r >= (double)INT64_MIN && r < 0) {
+ i = (int64_t)r;
+ type = MP_INT;
}
- mem_set_i64(pOut, ~i);
}
+ if (type == MP_INT || type == MP_UINT) {
+ i = pIn1->u.i;
+ } else {
+ diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+ sql_value_to_diag_str(pIn1), "integer");
+ goto abort_due_to_error;
+ }
+ mem_set_i64(pOut, ~i);
break;
}
diff --git a/test/sql/types.result b/test/sql/types.result
index caedbf409..601e5beca 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -2846,3 +2846,52 @@ box.execute([[SELECT 1 - '2';]])
- null
- 'Type mismatch: can not convert 2 to numeric'
...
+--
+-- Make sure there is no implicit string-to-number conversion in bitwise
+-- operations.
+--
+box.execute([[SELECT '1' | 2;]])
+---
+- null
+- 'Type mismatch: can not convert 1 to integer'
+...
+box.execute([[SELECT '1' & 2;]])
+---
+- null
+- 'Type mismatch: can not convert 1 to integer'
+...
+box.execute([[SELECT '1' << 2;]])
+---
+- null
+- 'Type mismatch: can not convert 1 to integer'
+...
+box.execute([[SELECT '1' >> 2;]])
+---
+- null
+- 'Type mismatch: can not convert 1 to integer'
+...
+box.execute([[SELECT ~'1';]])
+---
+- null
+- 'Type mismatch: can not convert 1 to integer'
+...
+box.execute([[SELECT 1 | '2';]])
+---
+- null
+- 'Type mismatch: can not convert 2 to integer'
+...
+box.execute([[SELECT 1 & '2';]])
+---
+- null
+- 'Type mismatch: can not convert 2 to integer'
+...
+box.execute([[SELECT 1 << '2';]])
+---
+- null
+- 'Type mismatch: can not convert 2 to integer'
+...
+box.execute([[SELECT 1 >> '2';]])
+---
+- null
+- 'Type mismatch: can not convert 2 to integer'
+...
diff --git a/test/sql/types.test.lua b/test/sql/types.test.lua
index 844a6b670..2d2f41da2 100644
--- a/test/sql/types.test.lua
+++ b/test/sql/types.test.lua
@@ -638,3 +638,17 @@ box.execute([[SELECT 1 % '2';]])
box.execute([[SELECT 1 * '2';]])
box.execute([[SELECT 1 / '2';]])
box.execute([[SELECT 1 - '2';]])
+
+--
+-- Make sure there is no implicit string-to-number conversion in bitwise
+-- operations.
+--
+box.execute([[SELECT '1' | 2;]])
+box.execute([[SELECT '1' & 2;]])
+box.execute([[SELECT '1' << 2;]])
+box.execute([[SELECT '1' >> 2;]])
+box.execute([[SELECT ~'1';]])
+box.execute([[SELECT 1 | '2';]])
+box.execute([[SELECT 1 & '2';]])
+box.execute([[SELECT 1 << '2';]])
+box.execute([[SELECT 1 >> '2';]])
--
2.25.1
More information about the Tarantool-patches
mailing list