Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix arithmetic operators so that they do not change the affinity of their input operands. Ticket [a8a0d2996a]. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
221f8f944703108e47d789fa8ce6c00f |
User & Date: | drh 2014-03-24 15:00:15.271 |
Context
2014-03-24
| ||
16:30 | Remove unused variables Parse.nColCache and Parse.iColCache. (check-in: 4d7551ce46 user: dan tags: trunk) | |
15:00 | Fix arithmetic operators so that they do not change the affinity of their input operands. Ticket [a8a0d2996a]. (check-in: 221f8f9447 user: drh tags: trunk) | |
11:23 | Avoid attempting to mmap memory from an offset that is not a multiple of the system page size on systems with page sizes larger than 32KB. (check-in: db7d62c8d5 user: dan tags: trunk) | |
Changes
Changes to src/vdbe.c.
︙ | ︙ | |||
305 306 307 308 309 310 311 312 313 314 315 316 317 318 | void sqlite3ValueApplyAffinity( sqlite3_value *pVal, u8 affinity, u8 enc ){ applyAffinity((Mem *)pVal, affinity, enc); } #ifdef SQLITE_DEBUG /* ** Write a nice string representation of the contents of cell pMem ** into buffer zBuf, length nBuf. */ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ | > > > > > > > > > > > > > > > > > > > > > > > | 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | void sqlite3ValueApplyAffinity( sqlite3_value *pVal, u8 affinity, u8 enc ){ applyAffinity((Mem *)pVal, affinity, enc); } /* ** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or ** none. ** ** Unlike applyNumericAffinity(), this routine does not modify pMem->flags. ** But it does set pMem->r and pMem->u.i appropriately. */ static u16 numericType(Mem *pMem){ if( pMem->flags & (MEM_Int|MEM_Real) ){ return pMem->flags & (MEM_Int|MEM_Real); } if( pMem->flags & (MEM_Str|MEM_Blob) ){ if( sqlite3AtoF(pMem->z, &pMem->r, pMem->n, pMem->enc)==0 ){ return 0; } if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){ return MEM_Int; } return MEM_Real; } return 0; } #ifdef SQLITE_DEBUG /* ** Write a nice string representation of the contents of cell pMem ** into buffer zBuf, length nBuf. */ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ |
︙ | ︙ | |||
1347 1348 1349 1350 1351 1352 1353 | */ case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ char bIntint; /* Started out as two integer operands */ | | > > | | | | 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 | */ case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ char bIntint; /* Started out as two integer operands */ u16 flags; /* Combined MEM_* flags from both inputs */ u16 type1; /* Numeric type of left operand */ u16 type2; /* Numeric type of right operand */ i64 iA; /* Integer value of left operand */ i64 iB; /* Integer value of right operand */ double rA; /* Real value of left operand */ double rB; /* Real value of right operand */ pIn1 = &aMem[pOp->p1]; type1 = numericType(pIn1); pIn2 = &aMem[pOp->p2]; type2 = numericType(pIn2); pOut = &aMem[pOp->p3]; flags = pIn1->flags | pIn2->flags; if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; if( (type1 & type2 & MEM_Int)!=0 ){ iA = pIn1->u.i; iB = pIn2->u.i; bIntint = 1; switch( pOp->opcode ){ case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break; case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break; case OP_Multiply: if( sqlite3MulInt64(&iB,iA) ) goto fp_math; break; |
︙ | ︙ | |||
1416 1417 1418 1419 1420 1421 1422 | MemSetTypeFlag(pOut, MEM_Int); #else if( sqlite3IsNaN(rB) ){ goto arithmetic_result_is_null; } pOut->r = rB; MemSetTypeFlag(pOut, MEM_Real); | | | 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 | MemSetTypeFlag(pOut, MEM_Int); #else if( sqlite3IsNaN(rB) ){ goto arithmetic_result_is_null; } pOut->r = rB; MemSetTypeFlag(pOut, MEM_Real); if( ((type1|type2)&MEM_Real)==0 && !bIntint ){ sqlite3VdbeIntegerAffinity(pOut); } #endif } break; arithmetic_result_is_null: |
︙ | ︙ |
Added test/tkt-a8a0d2996a.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | # 2014-03-24 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # Tests to verify that arithmetic operators do not change the type of # input operands. Ticket [a8a0d2996a] # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix tkt-a8a0d2996a do_execsql_test 1.0 { CREATE TABLE t(x,y); INSERT INTO t VALUES('1','1'); SELECT typeof(x), typeof(y) FROM t WHERE 1=x+0 AND y=='1'; } {text text} do_execsql_test 1.1 { SELECT typeof(x), typeof(y) FROM t WHERE 1=x-0 AND y=='1'; } {text text} do_execsql_test 1.2 { SELECT typeof(x), typeof(y) FROM t WHERE 1=x*1 AND y=='1'; } {text text} do_execsql_test 1.3 { SELECT typeof(x), typeof(y) FROM t WHERE 1=x/1 AND y=='1'; } {text text} do_execsql_test 1.4 { SELECT typeof(x), typeof(y) FROM t WHERE 1=x%4 AND y=='1'; } {text text} do_execsql_test 2.0 { UPDATE t SET x='1xyzzy'; SELECT typeof(x), typeof(y) FROM t WHERE 1=x+0 AND y=='1'; } {text text} do_execsql_test 2.1 { SELECT typeof(x), typeof(y) FROM t WHERE 1=x-0 AND y=='1'; } {text text} do_execsql_test 2.2 { SELECT typeof(x), typeof(y) FROM t WHERE 1=x*1 AND y=='1'; } {text text} do_execsql_test 2.3 { SELECT typeof(x), typeof(y) FROM t WHERE 1=x/1 AND y=='1'; } {text text} do_execsql_test 2.4 { SELECT typeof(x), typeof(y) FROM t WHERE 1=x%4 AND y=='1'; } {text text} do_execsql_test 3.0 { UPDATE t SET x='1.0'; SELECT typeof(x), typeof(y) FROM t WHERE 1=x+0 AND y=='1'; } {text text} do_execsql_test 3.1 { SELECT typeof(x), typeof(y) FROM t WHERE 1=x-0 AND y=='1'; } {text text} do_execsql_test 3.2 { SELECT typeof(x), typeof(y) FROM t WHERE 1=x*1 AND y=='1'; } {text text} do_execsql_test 3.3 { SELECT typeof(x), typeof(y) FROM t WHERE 1=x/1 AND y=='1'; } {text text} do_execsql_test 3.4 { SELECT typeof(x), typeof(y) FROM t WHERE 1=x%4 AND y=='1'; } {text text} do_execsql_test 4.0 { SELECT 1+1.; } {2.0} do_execsql_test 4.1 { SELECT '1.23e64'/'1.0000e+62'; } {123.0} do_execsql_test 4.2 { SELECT '100x'+'-2y'; } {98} do_execsql_test 4.3 { SELECT '100x'+'4.5y'; } {104.5} do_execsql_test 4.4 { SELECT '-9223372036854775807x'-'1x'; } {-9.22337203685478e+18} do_execsql_test 4.5 { SELECT '9223372036854775806x'+'1x'; } {9.22337203685478e+18} do_execsql_test 4.6 { SELECT '1234x'/'10y'; } {123.4} |