Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix problem in the code generator were incorrect code was being created if the SQL source contained a negative integer that was too large to fit in a 32-bit signed integer variable. Ticket #552. (CVS 1157) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
b8381d9fe99273507e86266381106468 |
User & Date: | drh 2004-01-06 01:13:46.000 |
Context
2004-01-06
| ||
01:27 | Increase the version number and update the change log prior to the next release. (CVS 1158) (check-in: b99b68d026 user: drh tags: trunk) | |
01:13 | Fix problem in the code generator were incorrect code was being created if the SQL source contained a negative integer that was too large to fit in a 32-bit signed integer variable. Ticket #552. (CVS 1157) (check-in: b8381d9fe9 user: drh tags: trunk) | |
00:44 | Add the sqlite_current_time variable for testing purposes. (CVS 1156) (check-in: 23fa407d50 user: drh tags: trunk) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.103 2004/01/06 01:13:46 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Construct a new expression node and return a pointer to it. Memory ** for this node is obtained from sqliteMalloc(). The calling function |
︙ | ︙ | |||
324 325 326 327 328 329 330 | return p->pLeft!=0 || p->pRight!=0 || (p->pList && p->pList->nExpr>0); } } return 0; } /* | | > | | > | | > > | | 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | return p->pLeft!=0 || p->pRight!=0 || (p->pList && p->pList->nExpr>0); } } return 0; } /* ** If the given expression codes a constant integer that is small enough ** to fit in a 32-bit integer, return 1 and put the value of the integer ** in *pValue. If the expression is not an integer or if it is too big ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. */ int sqliteExprIsInteger(Expr *p, int *pValue){ switch( p->op ){ case TK_INTEGER: { if( sqliteFitsIn32Bits(p->token.z) ){ *pValue = atoi(p->token.z); return 1; } break; } case TK_STRING: { const char *z = p->token.z; int n = p->token.n; if( n>0 && z[0]=='-' ){ z++; n--; } while( n>0 && *z && isdigit(*z) ){ z++; n--; } if( n==0 && sqliteFitsIn32Bits(p->token.z) ){ *pValue = atoi(p->token.z); return 1; } break; } case TK_UPLUS: { return sqliteExprIsInteger(p->pLeft, pValue); |
︙ | ︙ | |||
965 966 967 968 969 970 971 972 973 974 975 976 977 978 | default: assert( p->op==TK_ABORT ); /* Can't Happen */ break; } return SQLITE_SO_NUM; } /* ** Generate code into the current Vdbe to evaluate the given ** expression and leave the result on the top of stack. */ void sqliteExprCode(Parse *pParse, Expr *pExpr){ Vdbe *v = pParse->pVdbe; int op; | > > > | 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 | default: assert( p->op==TK_ABORT ); /* Can't Happen */ break; } return SQLITE_SO_NUM; } /* ** Run /* ** Generate code into the current Vdbe to evaluate the given ** expression and leave the result on the top of stack. */ void sqliteExprCode(Parse *pParse, Expr *pExpr){ Vdbe *v = pParse->pVdbe; int op; |
︙ | ︙ | |||
1010 1011 1012 1013 1014 1015 1016 | sqliteVdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn); }else{ sqliteVdbeAddOp(v, OP_Recno, pExpr->iTable, 0); } break; } case TK_INTEGER: { | | < < < < < < | | 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 | sqliteVdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn); }else{ sqliteVdbeAddOp(v, OP_Recno, pExpr->iTable, 0); } break; } case TK_INTEGER: { if( !sqliteFitsIn32Bits(pExpr->token.z) ){ sqliteVdbeAddOp(v, OP_String, 0, 0); }else{ sqliteVdbeAddOp(v, OP_Integer, atoi(pExpr->token.z), 0); } sqliteVdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n); break; } case TK_FLOAT: { sqliteVdbeAddOp(v, OP_String, 0, 0); assert( pExpr->token.z ); |
︙ | ︙ | |||
1086 1087 1088 1089 1090 1091 1092 | sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, OP_Concat, 2, 0); break; } case TK_UPLUS: { Expr *pLeft = pExpr->pLeft; if( pLeft && pLeft->op==TK_INTEGER ){ | > | > > > | | 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 | sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, OP_Concat, 2, 0); break; } case TK_UPLUS: { Expr *pLeft = pExpr->pLeft; if( pLeft && pLeft->op==TK_INTEGER ){ if( sqliteFitsIn32Bits(pLeft->token.z) ){ sqliteVdbeAddOp(v, OP_Integer, atoi(pLeft->token.z), 0); }else{ sqliteVdbeAddOp(v, OP_String, 0, 0); } sqliteVdbeChangeP3(v, -1, pLeft->token.z, pLeft->token.n); }else if( pLeft && pLeft->op==TK_FLOAT ){ sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeChangeP3(v, -1, pLeft->token.z, pLeft->token.n); }else{ sqliteExprCode(pParse, pExpr->pLeft); } break; } case TK_UMINUS: { assert( pExpr->pLeft ); if( pExpr->pLeft->op==TK_FLOAT || pExpr->pLeft->op==TK_INTEGER ){ Token *p = &pExpr->pLeft->token; char *z = sqliteMalloc( p->n + 2 ); sprintf(z, "-%.*s", p->n, p->z); if( pExpr->pLeft->op==TK_INTEGER && sqliteFitsIn32Bits(z) ){ sqliteVdbeAddOp(v, OP_Integer, atoi(z), 0); }else{ sqliteVdbeAddOp(v, OP_String, 0, 0); } sqliteVdbeChangeP3(v, -1, z, p->n+1); sqliteFree(z); break; |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.206 2004/01/06 01:13:47 drh Exp $ */ #include "config.h" #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" |
︙ | ︙ | |||
1201 1202 1203 1204 1205 1206 1207 | int sqliteFixSrcList(DbFixer*, SrcList*); int sqliteFixSelect(DbFixer*, Select*); int sqliteFixExpr(DbFixer*, Expr*); int sqliteFixExprList(DbFixer*, ExprList*); int sqliteFixTriggerStep(DbFixer*, TriggerStep*); double sqliteAtoF(const char *z); int sqlite_snprintf(int,char*,const char*,...); | > | 1201 1202 1203 1204 1205 1206 1207 1208 | int sqliteFixSrcList(DbFixer*, SrcList*); int sqliteFixSelect(DbFixer*, Select*); int sqliteFixExpr(DbFixer*, Expr*); int sqliteFixExprList(DbFixer*, ExprList*); int sqliteFixTriggerStep(DbFixer*, TriggerStep*); double sqliteAtoF(const char *z); int sqlite_snprintf(int,char*,const char*,...); int sqliteFitsIn32Bits(const char *); |
Changes to src/util.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.70 2004/01/06 01:13:47 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* ** If malloc() ever fails, this global variable gets set to 1. |
︙ | ︙ | |||
708 709 710 711 712 713 714 715 716 717 718 719 720 721 | v1 /= scale; }else{ v1 *= scale; } } return sign<0 ? -v1 : v1; } /* This comparison routine is what we use for comparison operations ** between numeric values in an SQL expression. "Numeric" is a little ** bit misleading here. What we mean is that the strings have a ** type of "numeric" from the point of view of SQL. The strings ** do not necessarily contain numbers. They could contain text. ** | > > > > > > > > > > > > > > > > > > | 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 | v1 /= scale; }else{ v1 *= scale; } } return sign<0 ? -v1 : v1; } /* ** The string zNum represents an integer. There might be some other ** information following the integer too, but that part is ignored. ** If the integer that the prefix of zNum represents will fit in a ** 32-bit signed integer, return TRUE. Otherwise return FALSE. ** ** This routine returns FALSE for the string -2147483648 even that ** that number will, in theory fit in a 32-bit integer. But positive ** 2147483648 will not fit in 32 bits. So it seems safer to return ** false. */ int sqliteFitsIn32Bits(const char *zNum){ int i, c; if( *zNum=='-' || *zNum=='+' ) zNum++; for(i=0; (c=zNum[i])>='0' && c<='9'; i++){} return i<10 || (i==10 && memcmp(zNum,"2147483647",10)<=0); } /* This comparison routine is what we use for comparison operations ** between numeric values in an SQL expression. "Numeric" is a little ** bit misleading here. What we mean is that the strings have a ** type of "numeric" from the point of view of SQL. The strings ** do not necessarily contain numbers. They could contain text. ** |
︙ | ︙ |
Changes to test/misc3.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # # $Id: misc3.test,v 1.3 2004/01/06 01:13:47 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Ticket #529. Make sure an ABORT does not damage the in-memory cache # that will be used by subsequent statements in the same transaction. # |
︙ | ︙ | |||
94 95 96 97 98 99 100 | do_test misc3-2.8 { execsql {SELECT 2.0e-27 * '+0.5e+127'} } 1e+100 do_test misc3-2.9 { execsql {SELECT 2.0e-27 * '+0.000005e+132'} } 1e+100 | > > | > > > > > > > > > > > > > > > > > > > > > > | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | do_test misc3-2.8 { execsql {SELECT 2.0e-27 * '+0.5e+127'} } 1e+100 do_test misc3-2.9 { execsql {SELECT 2.0e-27 * '+0.000005e+132'} } 1e+100 # Ticket #522. Make sure integer overflow is handled properly in # indices. # do_test misc3-3.1 { execsql {PRAGMA integrity_check} } ok do_test misc3-3.2 { execsql { CREATE TABLE t2(a INT UNIQUE); PRAGMA integrity_check; } } ok do_test misc3-3.3 { execsql { INSERT INTO t2 VALUES(2147483648); PRAGMA integrity_check; } } ok do_test misc3-3.4 { execsql { INSERT INTO t2 VALUES(-2147483649); PRAGMA integrity_check; } } ok finish_test |