mirror of
https://github.com/sqlite/sqlite.git
synced 2025-12-24 14:17:58 +03:00
More changes to support the manifest type model. A few things are currently
broken. (CVS 1385) FossilOrigin-Name: a4af838f8d1b81ec6c8db97655c6876aca0738d9
This commit is contained in:
39
manifest
39
manifest
@@ -1,5 +1,5 @@
|
||||
C More\sspeed\simprovements\sto\sbtree.\s(CVS\s1384)
|
||||
D 2004-05-15T00:29:24
|
||||
C More\schanges\sto\ssupport\sthe\smanifest\stype\smodel.\sA\sfew\sthings\sare\scurrently\nbroken.\s(CVS\s1385)
|
||||
D 2004-05-16T11:15:36
|
||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
@@ -26,16 +26,16 @@ F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
|
||||
F src/btree.c 05aefd3eec56690d9731bf090203b57d8ae4bf19
|
||||
F src/btree.h 6f51ad0ffebfba71295fcacdbe86007512200050
|
||||
F src/btree_rb.c 9d7973e266ee6f9c61ce592f68742ce9cd5b10e5
|
||||
F src/build.c e93f443a20eab57ffb77ff6244b1e09a1f7d9390
|
||||
F src/build.c 6c0463907ba80e0269f0b7fdf4210a049275b48a
|
||||
F src/copy.c 4d2038602fd0549d80c59bda27d96f13ea9b5e29
|
||||
F src/date.c 0eb0a89960bb45c7f7e768748605a7a97b0c8064
|
||||
F src/delete.c 30c8c4375e75e811c3668abf3f78970fe549f375
|
||||
F src/delete.c ea8212a44b5c0dad8fb1794fe7297654f7ed05f9
|
||||
F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
|
||||
F src/expr.c a3aed7057bafb3a01e8af98a5f74a102621b7a91
|
||||
F src/func.c 4053dc2141ea46e8e35df089d87bfcbab54320bc
|
||||
F src/expr.c d2d1ddc0ee98f1d70c6caddc11b46a0121d9bddd
|
||||
F src/func.c cfbb7096efb58e2857e3b312a8958a12774b625a
|
||||
F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f
|
||||
F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
|
||||
F src/insert.c 5d4d1a59f66b558213984391985a418efc1c2797
|
||||
F src/insert.c 76e13b736391a342bd0fc152ade2558588322868
|
||||
F src/main.c 4b82d7e78f4c9799343b02740a5ba9768d5e464d
|
||||
F src/md5.c 8e39fdae6d8776b87558e91dcc94740c9b635a9c
|
||||
F src/os.c ddcda92f7fd71b4513c57c1ec797917f206d504e
|
||||
@@ -43,13 +43,13 @@ F src/os.h fbb2f6595fc34fa351830d88fe1c6b85118f0383
|
||||
F src/pager.c 6ff6b906427d4824099140776cb8768f922f3dc5
|
||||
F src/pager.h 78a00ac280899bcba1a89dc51585dcae6b7b3253
|
||||
F src/parse.y d0258aa3cc8b0c5742b07b699d10fa98f3caea7d
|
||||
F src/pragma.c 2ab2a12b62ec5370b9221f44b4743a633a90bfa8
|
||||
F src/pragma.c 351836bce186f4eee45a32868b7a379c22ac344a
|
||||
F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53
|
||||
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
||||
F src/select.c ca99ae4db14a45a436ec51d3e6bd48d44a3efb3c
|
||||
F src/shell.c 0c4662e13bfbfd3d13b066c5859cc97ad2f95d21
|
||||
F src/sqlite.h.in 799c5e726296ec7bc20e6407cdf4df0e0bc00c0c
|
||||
F src/sqliteInt.h e94edafb9924f22f038c6a8209c29ddd04cd326a
|
||||
F src/sqliteInt.h bc118a7a701afb954f4cd2110cd0986478e1a741
|
||||
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
|
||||
F src/tclsqlite.c fbf0fac73624ae246551a6c671f1de0235b5faa1
|
||||
F src/test1.c 12ef76b8aaba4408422f21f269256b630d4dd627
|
||||
@@ -59,15 +59,15 @@ F src/test4.c b3fab9aea7a8940a8a7386ce1c7e2157b09bd296
|
||||
F src/test5.c eb39aac8fed61bd930b92613cd705c145244074a
|
||||
F src/tokenize.c e7536dd31205d5afb76c1bdc832dea009c7a3847
|
||||
F src/trigger.c 8df308e09113410bb895e88a2db65b55490268db
|
||||
F src/update.c 0441f8b64d616ef244583449e66c984e536c6c9b
|
||||
F src/update.c 04492438aee57a6be5a8a8e54e3add12c1d598ca
|
||||
F src/utf.c fc799748d43fe1982d157b871e3e420a19c85d4f
|
||||
F src/util.c f9511ffba78e6cf71a28774c2820d7750b5bacdf
|
||||
F src/vacuum.c c134702e023db8778e6be59ac0ea7b02315b5476
|
||||
F src/vdbe.c c12726cf16c9a4e70ff606f87dc0e10e55a11988
|
||||
F src/vdbe.c 38a477ae68e78936adb62ef9c6cffebdebbb5be5
|
||||
F src/vdbe.h 94457ca73bae972dc61bca33a4dccc2e6e14e2f8
|
||||
F src/vdbeInt.h 67c3b2cf924e176c10ba75b36d295b165d55c451
|
||||
F src/vdbeaux.c 8411f411b421bc19ded1e992db82434aef740f5f
|
||||
F src/where.c 6957bbd333cc7ffa7b3878adbe67a095319daa54
|
||||
F src/vdbeInt.h 311c2a046ea419781d0ef331198b7b0a65eebc92
|
||||
F src/vdbeaux.c bd259da3ae52cd4f6febb0c83f60c0b9170f3ebb
|
||||
F src/where.c 610fadd08c5a25c2aa3bdd8700c3173de64298d0
|
||||
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
|
||||
F test/attach.test cb9b884344e6cfa5e165965d5b1adea679a24c83
|
||||
F test/attach2.test 7c388dee63a4c1997695c3d41957f32ce784ac56
|
||||
@@ -144,7 +144,8 @@ F test/trigger1.test 4538c1c7d6bbca5dfe619ea6e1682b07ece95b21
|
||||
F test/trigger2.test 0767ab30cb5a2c8402c8524f3d566b410b6f5263
|
||||
F test/trigger3.test a95ccace88291449f5eae7139ec438a42f90654d
|
||||
F test/trigger4.test 542afce45774e8f8e1130b96b8675f414d6e4bd8
|
||||
F test/types.test 53e3d97c33651afad7bc8bd4cf71b97b473b19ad
|
||||
F test/types.test d30ee85040cec5c12ebd98a6419916cc29a6c11e
|
||||
F test/types2.test bc684cc2a75edb240f9fd49275f3cacb025c0f1e
|
||||
F test/unique.test 0e38d4cc7affeef2527720d1dafd1f6870f02f2b
|
||||
F test/update.test b29bd9061a1150426dab6959806fcc73a41b1217
|
||||
F test/vacuum.test a2a44544df719666efb51afbfeb6062fd59a672a
|
||||
@@ -191,7 +192,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
||||
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||
P d8bacc16801606176fe8639b2f55b4584ad549df
|
||||
R d43b2b97f5dc394b60a54b98133aa83a
|
||||
U drh
|
||||
Z 06eabac28a7b451889010e7a03f02723
|
||||
P aab4b794b4238bad5c4a6aee7d4443732921127d
|
||||
R b2648c3d83df0dd5d82ceb6fe4e0bc60
|
||||
U danielk1977
|
||||
Z a958d50ee5923975cc30d387e46d379d
|
||||
|
||||
@@ -1 +1 @@
|
||||
aab4b794b4238bad5c4a6aee7d4443732921127d
|
||||
a4af838f8d1b81ec6c8db97655c6876aca0738d9
|
||||
87
src/build.c
87
src/build.c
@@ -23,7 +23,7 @@
|
||||
** ROLLBACK
|
||||
** PRAGMA
|
||||
**
|
||||
** $Id: build.c,v 1.183 2004/05/14 11:00:53 danielk1977 Exp $
|
||||
** $Id: build.c,v 1.184 2004/05/16 11:15:36 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -184,6 +184,9 @@ static void sqliteDeleteIndex(sqlite *db, Index *p){
|
||||
sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,
|
||||
strlen(pOld->zName)+1, pOld);
|
||||
}
|
||||
if( p->zColAff ){
|
||||
sqliteFree(p->zColAff);
|
||||
}
|
||||
sqliteFree(p);
|
||||
}
|
||||
|
||||
@@ -581,7 +584,12 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){
|
||||
pCol = &p->aCol[p->nCol];
|
||||
memset(pCol, 0, sizeof(p->aCol[0]));
|
||||
pCol->zName = z;
|
||||
pCol->sortOrder = SQLITE_SO_NUM;
|
||||
|
||||
/* If there is no type specified, columns have the default affinity
|
||||
** 'NONE'. If there is a type specified, then sqlite3AddColumnType()
|
||||
** will be called next to set pCol->affinity correctly.
|
||||
*/
|
||||
pCol->affinity = SQLITE_AFF_NONE;
|
||||
p->nCol++;
|
||||
}
|
||||
|
||||
@@ -629,7 +637,8 @@ void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
|
||||
z[j++] = c;
|
||||
}
|
||||
z[j] = 0;
|
||||
pCol->sortOrder = sqlite3CollateType(z, n);
|
||||
// pCol->sortOrder = sqlite3CollateType(z, n);
|
||||
pCol->affinity = sqlite3AffinityType(z, n);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -751,7 +760,42 @@ void sqlite3AddCollateType(Parse *pParse, int collType){
|
||||
int i;
|
||||
if( (p = pParse->pNewTable)==0 ) return;
|
||||
i = p->nCol-1;
|
||||
if( i>=0 ) p->aCol[i].sortOrder = collType;
|
||||
|
||||
/* FIX ME */
|
||||
/* if( i>=0 ) p->aCol[i].sortOrder = collType; */
|
||||
}
|
||||
|
||||
/*
|
||||
** Parse the column type name zType (length nType) and return the
|
||||
** associated affinity type.
|
||||
*/
|
||||
char sqlite3AffinityType(const char *zType, int nType){
|
||||
/* FIX ME: This could be done more efficiently */
|
||||
int n, i;
|
||||
struct {
|
||||
const char *zSub;
|
||||
int nSub;
|
||||
char affinity;
|
||||
} substrings[] = {
|
||||
{"INT", 3, SQLITE_AFF_INTEGER},
|
||||
{"REAL", 4, SQLITE_AFF_NUMERIC},
|
||||
{"FLOAT", 5, SQLITE_AFF_NUMERIC},
|
||||
{"DOUBLE", 6, SQLITE_AFF_NUMERIC},
|
||||
{"NUM", 3, SQLITE_AFF_NUMERIC},
|
||||
{"CHAR", 4, SQLITE_AFF_TEXT},
|
||||
{"CLOB", 4, SQLITE_AFF_TEXT},
|
||||
{"TEXT", 4, SQLITE_AFF_TEXT}
|
||||
};
|
||||
|
||||
for(n=0; n<(nType-3); n++){
|
||||
for(i=0; i<sizeof(substrings)/sizeof(substrings[0]); i++){
|
||||
if( 0==sqlite3StrNICmp(zType, substrings[i].zSub, substrings[i].nSub) ){
|
||||
return substrings[i].affinity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SQLITE_AFF_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1295,39 +1339,6 @@ void sqlite3DropTable(Parse *pParse, Token *pName, int isView){
|
||||
sqliteViewResetAll(db, iDb);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine constructs a P3 string suitable for an OP_MakeIdxKey
|
||||
** opcode and adds that P3 string to the most recently inserted instruction
|
||||
** in the virtual machine. The P3 string consists of a single character
|
||||
** for each column in the index pIdx of table pTab. If the column uses
|
||||
** a numeric sort order, then the P3 string character corresponding to
|
||||
** that column is 'n'. If the column uses a text sort order, then the
|
||||
** P3 string is 't'. See the OP_MakeIdxKey opcode documentation for
|
||||
** additional information. See also the sqlite3AddKeyType() routine.
|
||||
*/
|
||||
void sqlite3AddIdxKeyType(Vdbe *v, Index *pIdx){
|
||||
char *zType;
|
||||
Table *pTab;
|
||||
int i, n;
|
||||
assert( pIdx!=0 && pIdx->pTable!=0 );
|
||||
pTab = pIdx->pTable;
|
||||
n = pIdx->nColumn;
|
||||
zType = sqliteMallocRaw( n+1 );
|
||||
if( zType==0 ) return;
|
||||
for(i=0; i<n; i++){
|
||||
int iCol = pIdx->aiColumn[i];
|
||||
assert( iCol>=0 && iCol<pTab->nCol );
|
||||
if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){
|
||||
zType[i] = 't';
|
||||
}else{
|
||||
zType[i] = 'n';
|
||||
}
|
||||
}
|
||||
zType[n] = 0;
|
||||
sqlite3VdbeChangeP3(v, -1, zType, n);
|
||||
sqliteFree(zType);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is called to create a new foreign key on the table
|
||||
** currently under construction. pFromCol determines which columns
|
||||
@@ -1725,7 +1736,7 @@ void sqlite3CreateIndex(
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0);
|
||||
sqlite3AddIdxKeyType(v, pIndex);
|
||||
sqlite3IndexAffinityStr(v, pIndex);
|
||||
sqlite3VdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None,
|
||||
"indexed columns are not unique", P3_STATIC);
|
||||
sqlite3VdbeAddOp(v, OP_Next, 2, lbl1);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle DELETE FROM statements.
|
||||
**
|
||||
** $Id: delete.c,v 1.64 2004/05/11 07:11:53 danielk1977 Exp $
|
||||
** $Id: delete.c,v 1.65 2004/05/16 11:15:37 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -387,7 +387,7 @@ void sqlite3GenerateRowIndexDelete(
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
|
||||
sqlite3AddIdxKeyType(v, pIdx);
|
||||
sqlite3IndexAffinityStr(v, pIdx);
|
||||
sqlite3VdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
91
src/expr.c
91
src/expr.c
@@ -12,11 +12,51 @@
|
||||
** This file contains routines used for analyzing expressions and
|
||||
** for generating VDBE code that evaluates expressions in SQLite.
|
||||
**
|
||||
** $Id: expr.c,v 1.117 2004/05/11 07:11:53 danielk1977 Exp $
|
||||
** $Id: expr.c,v 1.118 2004/05/16 11:15:37 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
|
||||
static char exprAffinity(Expr *pExpr){
|
||||
if( pExpr->op==TK_AS ){
|
||||
return exprAffinity(pExpr->pLeft);
|
||||
}
|
||||
if( pExpr->op==TK_SELECT ){
|
||||
return exprAffinity(pExpr->pSelect->pEList->a[0].pExpr);
|
||||
}
|
||||
return pExpr->affinity;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the P1 value that should be used for a binary comparison
|
||||
** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
|
||||
** If jumpIfNull is true, then set the low byte of the returned
|
||||
** P1 value to tell the opcode to jump if either expression
|
||||
** evaluates to NULL.
|
||||
*/
|
||||
int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
|
||||
char aff1 = exprAffinity(pExpr1);
|
||||
char aff2 = exprAffinity(pExpr2);
|
||||
|
||||
if( aff1 && aff2 ){
|
||||
/* Both sides of the comparison are columns. If one has numeric or
|
||||
** integer affinity, use that. Otherwise use no affinity.
|
||||
*/
|
||||
if( aff1==SQLITE_AFF_INTEGER || aff2==SQLITE_AFF_INTEGER ){
|
||||
aff1 = SQLITE_AFF_INTEGER;
|
||||
}else
|
||||
if( aff1==SQLITE_AFF_NUMERIC || aff2==SQLITE_AFF_NUMERIC ){
|
||||
aff1 = SQLITE_AFF_NUMERIC;
|
||||
}else{
|
||||
aff1 = SQLITE_AFF_NONE;
|
||||
}
|
||||
}else if( !aff1 ){
|
||||
aff1 = aff2;
|
||||
}
|
||||
|
||||
return (((int)aff1)<<8)+(jumpIfNull?1:0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Construct a new expression node and return a pointer to it. Memory
|
||||
** for this node is obtained from sqliteMalloc(). The calling function
|
||||
@@ -472,7 +512,11 @@ static int lookupName(
|
||||
pExpr->iDb = pTab->iDb;
|
||||
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
|
||||
pExpr->iColumn = j==pTab->iPKey ? -1 : j;
|
||||
pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;
|
||||
pExpr->affinity = pTab->aCol[j].affinity;
|
||||
|
||||
/* FIX ME: Expr::dataType will be removed... */
|
||||
pExpr->dataType =
|
||||
(pCol->affinity==SQLITE_AFF_TEXT?SQLITE_SO_TEXT:SQLITE_SO_NUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -504,7 +548,10 @@ static int lookupName(
|
||||
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
||||
cnt++;
|
||||
pExpr->iColumn = j==pTab->iPKey ? -1 : j;
|
||||
pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;
|
||||
pExpr->affinity = pTab->aCol[j].affinity;
|
||||
/* FIX ME: Expr::dataType will be removed... */
|
||||
pExpr->dataType =
|
||||
(pCol->affinity==SQLITE_AFF_TEXT?SQLITE_SO_TEXT:SQLITE_SO_NUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -518,6 +565,7 @@ static int lookupName(
|
||||
cnt = 1;
|
||||
pExpr->iColumn = -1;
|
||||
pExpr->dataType = SQLITE_SO_NUM;
|
||||
pExpr->affinity = SQLITE_AFF_INTEGER;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1050,6 +1098,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
case TK_INTEGER: {
|
||||
if( pExpr->op==TK_INTEGER && sqlite3FitsIn32Bits(pExpr->token.z) ){
|
||||
sqlite3VdbeAddOp(v, OP_Integer, atoi(pExpr->token.z), 0);
|
||||
}else if( pExpr->op==TK_FLOAT ){
|
||||
sqlite3VdbeAddOp(v, OP_Real, 0, 0);
|
||||
}else{
|
||||
sqlite3VdbeAddOp(v, OP_String, 0, 0);
|
||||
}
|
||||
@@ -1072,10 +1122,17 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
case TK_GE:
|
||||
case TK_NE:
|
||||
case TK_EQ: {
|
||||
int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, 0);
|
||||
sqlite3ExprCode(pParse, pExpr->pLeft);
|
||||
sqlite3ExprCode(pParse, pExpr->pRight);
|
||||
sqlite3VdbeAddOp(v, op, p1, 0);
|
||||
break;
|
||||
#if 0
|
||||
if( sqlite3ExprType(pExpr)==SQLITE_SO_TEXT ){
|
||||
op += 6; /* Convert numeric opcodes to text opcodes */
|
||||
}
|
||||
/* Fall through into the next case */
|
||||
#endif
|
||||
}
|
||||
case TK_AND:
|
||||
case TK_OR:
|
||||
@@ -1135,8 +1192,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
dest = sqlite3VdbeCurrentAddr(v) + 2;
|
||||
sqlite3VdbeAddOp(v, op, 1, dest);
|
||||
sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TK_AGG_FUNCTION: {
|
||||
sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
|
||||
break;
|
||||
@@ -1153,7 +1210,13 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, 0);
|
||||
assert( pDef!=0 );
|
||||
nExpr = sqlite3ExprCodeExprList(pParse, pList, pDef->includeTypes);
|
||||
sqlite3VdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_POINTER);
|
||||
/* FIX ME: The following is a temporary hack. */
|
||||
if( 0==sqlite3StrNICmp(zId, "classof", nId) ){
|
||||
assert( nExpr==1 );
|
||||
sqlite3VdbeOp3(v, OP_Class, nExpr, 0, 0, 0);
|
||||
}else{
|
||||
sqlite3VdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_POINTER);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TK_SELECT: {
|
||||
@@ -1332,12 +1395,10 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
case TK_GE:
|
||||
case TK_NE:
|
||||
case TK_EQ: {
|
||||
int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, jumpIfNull);
|
||||
sqlite3ExprCode(pParse, pExpr->pLeft);
|
||||
sqlite3ExprCode(pParse, pExpr->pRight);
|
||||
if( sqlite3ExprType(pExpr)==SQLITE_SO_TEXT ){
|
||||
op += 6; /* Convert numeric opcodes to text opcodes */
|
||||
}
|
||||
sqlite3VdbeAddOp(v, op, jumpIfNull, dest);
|
||||
sqlite3VdbeAddOp(v, op, p1, dest);
|
||||
break;
|
||||
}
|
||||
case TK_ISNULL:
|
||||
@@ -1427,18 +1488,10 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
case TK_GE:
|
||||
case TK_NE:
|
||||
case TK_EQ: {
|
||||
if( sqlite3ExprType(pExpr)==SQLITE_SO_TEXT ){
|
||||
/* Convert numeric comparison opcodes into text comparison opcodes.
|
||||
** This step depends on the fact that the text comparision opcodes are
|
||||
** always 6 greater than their corresponding numeric comparison
|
||||
** opcodes.
|
||||
*/
|
||||
assert( OP_Eq+6 == OP_StrEq );
|
||||
op += 6;
|
||||
}
|
||||
int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, jumpIfNull);
|
||||
sqlite3ExprCode(pParse, pExpr->pLeft);
|
||||
sqlite3ExprCode(pParse, pExpr->pRight);
|
||||
sqlite3VdbeAddOp(v, op, jumpIfNull, dest);
|
||||
sqlite3VdbeAddOp(v, op, p1, dest);
|
||||
break;
|
||||
}
|
||||
case TK_ISNULL:
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
**
|
||||
** $Id: func.c,v 1.47 2004/05/14 11:00:53 danielk1977 Exp $
|
||||
** $Id: func.c,v 1.48 2004/05/16 11:15:38 danielk1977 Exp $
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
@@ -571,6 +571,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite *db){
|
||||
{ "max", -1, SQLITE_ARGS, 2, minmaxFunc },
|
||||
{ "max", 0, 0, 2, 0 },
|
||||
{ "typeof", 1, SQLITE_TEXT, 0, typeofFunc },
|
||||
{ "classof", 1, SQLITE_TEXT, 0, typeofFunc }, /* FIX ME: hack */
|
||||
{ "length", 1, SQLITE_NUMERIC, 0, lengthFunc },
|
||||
{ "substr", 3, SQLITE_TEXT, 0, substrFunc },
|
||||
{ "abs", 1, SQLITE_NUMERIC, 0, absFunc },
|
||||
|
||||
74
src/insert.c
74
src/insert.c
@@ -12,13 +12,13 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle INSERT statements in SQLite.
|
||||
**
|
||||
** $Id: insert.c,v 1.98 2004/05/14 11:00:53 danielk1977 Exp $
|
||||
** $Id: insert.c,v 1.99 2004/05/16 11:15:38 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Set P3 of the most recently inserted opcode to a column affinity
|
||||
** string for table pTab. A column affinity string has one character
|
||||
** string for index pIdx. A column affinity string has one character
|
||||
** for each column in the table, according to the affinity of the column:
|
||||
**
|
||||
** Character Column affinity
|
||||
@@ -28,9 +28,45 @@
|
||||
** 't' TEXT
|
||||
** 'o' NONE
|
||||
*/
|
||||
int sqlite3AddRecordType(Vdbe *v, Table *pTab){
|
||||
assert( pTab );
|
||||
void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
|
||||
if( !pIdx->zColAff ){
|
||||
/* The first time a column affinity string for a particular table is
|
||||
** required, it is allocated and populated here. It is then stored as
|
||||
** a member of the Table structure for subsequent use.
|
||||
**
|
||||
** The column affinity string will eventually be deleted by
|
||||
** sqliteDeleteIndex() when the Table structure itself is cleaned
|
||||
** up.
|
||||
*/
|
||||
int n;
|
||||
Table *pTab = pIdx->pTable;
|
||||
pIdx->zColAff = (char *)sqliteMalloc(pIdx->nColumn+1);
|
||||
if( !pIdx->zColAff ){
|
||||
return;
|
||||
}
|
||||
for(n=0; n<pIdx->nColumn; n++){
|
||||
pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity;
|
||||
}
|
||||
pIdx->zColAff[pIdx->nColumn] = '\0';
|
||||
}
|
||||
|
||||
sqlite3VdbeChangeP3(v, -1, pIdx->zColAff, P3_STATIC);
|
||||
}
|
||||
|
||||
/*
|
||||
** Set P3 of the most recently inserted opcode to a column affinity
|
||||
** string for table pTab. A column affinity string has one character
|
||||
** for each column indexed by the index, according to the affinity of the
|
||||
** column:
|
||||
**
|
||||
** Character Column affinity
|
||||
** ------------------------------
|
||||
** 'n' NUMERIC
|
||||
** 'i' INTEGER
|
||||
** 't' TEXT
|
||||
** 'o' NONE
|
||||
*/
|
||||
void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
|
||||
/* The first time a column affinity string for a particular table
|
||||
** is required, it is allocated and populated here. It is then
|
||||
** stored as a member of the Table structure for subsequent use.
|
||||
@@ -42,28 +78,20 @@ int sqlite3AddRecordType(Vdbe *v, Table *pTab){
|
||||
char *zColAff;
|
||||
int i;
|
||||
|
||||
zColAff = sqliteMalloc(pTab->nCol+1);
|
||||
zColAff = (char *)sqliteMalloc(pTab->nCol+1);
|
||||
if( !zColAff ){
|
||||
return SQLITE_NOMEM;
|
||||
return;
|
||||
}
|
||||
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( pTab->aCol[i].sortOrder&SQLITE_SO_TEXT ){
|
||||
zColAff[i] = 't';
|
||||
}else{
|
||||
zColAff[i] = 'n';
|
||||
}
|
||||
zColAff[i] = pTab->aCol[i].affinity;
|
||||
}
|
||||
zColAff[pTab->nCol] = '\0';
|
||||
|
||||
pTab->zColAff = zColAff;
|
||||
}
|
||||
|
||||
/* Set the memory management at the vdbe to P3_STATIC, as the column
|
||||
** affinity string is managed as part of the Table structure.
|
||||
*/
|
||||
sqlite3VdbeChangeP3(v, -1, pTab->zColAff, P3_STATIC);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -267,7 +295,7 @@ void sqlite3Insert(
|
||||
srcTab = pParse->nTab++;
|
||||
sqlite3VdbeResolveLabel(v, iInsertBlock);
|
||||
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
|
||||
sqlite3AddRecordType(v, pTab);
|
||||
sqlite3TableAffinityStr(v, pTab);
|
||||
sqlite3VdbeAddOp(v, OP_NewRecno, srcTab, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, srcTab, 0);
|
||||
@@ -446,7 +474,15 @@ void sqlite3Insert(
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
|
||||
sqlite3AddRecordType(v, pTab);
|
||||
|
||||
/* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
|
||||
** do not attempt any conversions before assembling the record.
|
||||
** If this is a real table, attempt conversions as required by the
|
||||
** table column affinities.
|
||||
*/
|
||||
if( !isView ){
|
||||
sqlite3TableAffinityStr(v, pTab);
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
|
||||
|
||||
/* Fire BEFORE or INSTEAD OF triggers */
|
||||
@@ -826,7 +862,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
}
|
||||
}
|
||||
jumpInst1 = sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
|
||||
sqlite3AddIdxKeyType(v, pIdx);
|
||||
sqlite3IndexAffinityStr(v, pIdx);
|
||||
|
||||
/* Find out what action to take in case there is an indexing conflict */
|
||||
onError = pIdx->onError;
|
||||
@@ -936,7 +972,7 @@ void sqlite3CompleteInsertion(
|
||||
sqlite3VdbeAddOp(v, OP_IdxPut, base+i+1, 0);
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
|
||||
sqlite3AddRecordType(v, pTab);
|
||||
sqlite3TableAffinityStr(v, pTab);
|
||||
if( newIdx>=0 ){
|
||||
sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
**
|
||||
** $Id: pragma.c,v 1.22 2004/05/11 08:48:11 danielk1977 Exp $
|
||||
** $Id: pragma.c,v 1.23 2004/05/16 11:15:38 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -667,7 +667,7 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
|
||||
sqlite3AddIdxKeyType(v, pIdx);
|
||||
sqlite3IndexAffinityStr(v, pIdx);
|
||||
jmp2 = sqlite3VdbeAddOp(v, OP_Found, j+2, 0);
|
||||
addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
|
||||
sqlite3VdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.233 2004/05/14 16:50:06 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.234 2004/05/16 11:15:39 danielk1977 Exp $
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "sqlite.h"
|
||||
@@ -457,7 +457,8 @@ struct Column {
|
||||
char *zType; /* Data type for this column */
|
||||
u8 notNull; /* True if there is a NOT NULL constraint */
|
||||
u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */
|
||||
u8 sortOrder; /* Some combination of SQLITE_SO_... values */
|
||||
// u8 sortOrder; /* Some combination of SQLITE_SO_... values */
|
||||
char affinity; /* One of the SQLITE_AFF_... values */
|
||||
u8 dottedName; /* True if zName contains a "." character */
|
||||
};
|
||||
|
||||
@@ -475,6 +476,15 @@ struct Column {
|
||||
#define SQLITE_SO_DESC 1 /* Sort in descending order */
|
||||
#define SQLITE_SO_DIRMASK 1 /* Mask to extract the sort direction */
|
||||
|
||||
/*
|
||||
** Column affinity types.
|
||||
*/
|
||||
#define SQLITE_AFF_INTEGER 'i'
|
||||
#define SQLITE_AFF_NUMERIC 'n'
|
||||
#define SQLITE_AFF_TEXT 't'
|
||||
#define SQLITE_AFF_NONE 'o'
|
||||
|
||||
|
||||
/*
|
||||
** Each SQL table is represented in memory by an instance of the
|
||||
** following structure.
|
||||
@@ -638,6 +648,7 @@ struct Index {
|
||||
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
|
||||
u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */
|
||||
u8 iDb; /* Index in sqlite.aDb[] of where this index is stored */
|
||||
char *zColAff; /* String defining the affinity of each column */
|
||||
Index *pNext; /* The next index associated with the same table */
|
||||
};
|
||||
|
||||
@@ -707,6 +718,7 @@ struct Expr {
|
||||
** result from the iAgg-th element of the aggregator */
|
||||
Select *pSelect; /* When the expression is a sub-select. Also the
|
||||
** right side of "<expr> IN (<select>)" */
|
||||
char affinity; /* The affinity of the column or 0 if not a column */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1291,4 +1303,7 @@ int sqlite3PutVarint(unsigned char *, u64);
|
||||
int sqlite3GetVarint(const unsigned char *, u64 *);
|
||||
int sqlite3GetVarint32(const unsigned char *, u32 *);
|
||||
int sqlite3VarintLen(u64 v);
|
||||
int sqlite3AddRecordType(Vdbe*, Table*);
|
||||
char sqlite3AffinityType(const char *, int);
|
||||
void sqlite3IndexAffinityStr(Vdbe *, Index *);
|
||||
void sqlite3TableAffinityStr(Vdbe *, Table *);
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle UPDATE statements.
|
||||
**
|
||||
** $Id: update.c,v 1.73 2004/05/14 11:00:53 danielk1977 Exp $
|
||||
** $Id: update.c,v 1.74 2004/05/16 11:15:39 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -287,7 +287,10 @@ void sqlite3Update(
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
|
||||
sqlite3AddRecordType(v, pTab);
|
||||
if( !isView ){
|
||||
sqlite3TableAffinityStr(v, pTab);
|
||||
}
|
||||
if( pParse->nErr ) goto update_cleanup;
|
||||
sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
|
||||
if( !isView ){
|
||||
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
|
||||
|
||||
190
src/vdbe.c
190
src/vdbe.c
@@ -43,7 +43,7 @@
|
||||
** in this file for details. If in doubt, do not deviate from existing
|
||||
** commenting and indentation practices when changing or adding code.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.293 2004/05/14 21:59:40 drh Exp $
|
||||
** $Id: vdbe.c,v 1.294 2004/05/16 11:15:40 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -428,15 +428,16 @@ static int expandCursorArraySize(Vdbe *p, int mxCursor){
|
||||
** Apply any conversion required by the supplied column affinity to
|
||||
** memory cell pRec. affinity may be one of:
|
||||
**
|
||||
** SQLITE_AFF_NUM
|
||||
** SQLITE_AFF_NUMERIC
|
||||
** SQLITE_AFF_TEXT
|
||||
** SQLITE_AFF_NONE
|
||||
** SQLITE_AFF_INTEGER
|
||||
**
|
||||
*/
|
||||
static void applyAffinity(Mem *pRec, int affinity){
|
||||
static void applyAffinity(Mem *pRec, char affinity){
|
||||
switch( affinity ){
|
||||
case SQLITE_SO_NUM:
|
||||
case SQLITE_AFF_INTEGER:
|
||||
case SQLITE_AFF_NUMERIC:
|
||||
if( 0==(pRec->flags&(MEM_Real|MEM_Int)) ){
|
||||
/* pRec does not have a valid integer or real representation.
|
||||
** Attempt a conversion if pRec has a string representation and
|
||||
@@ -451,8 +452,19 @@ static void applyAffinity(Mem *pRec, int affinity){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( affinity==SQLITE_AFF_INTEGER ){
|
||||
/* For INTEGER affinity, try to convert a real value to an int */
|
||||
if( pRec->flags&MEM_Real ){
|
||||
pRec->i = pRec->r;
|
||||
if( ((double)pRec->i)==pRec->r ){
|
||||
pRec->flags |= MEM_Int;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SQLITE_SO_TEXT:
|
||||
|
||||
case SQLITE_AFF_TEXT:
|
||||
/* Only attempt the conversion if there is an integer or real
|
||||
** representation (blob and NULL do not get converted) but no string
|
||||
** representation.
|
||||
@@ -464,28 +476,15 @@ static void applyAffinity(Mem *pRec, int affinity){
|
||||
|
||||
break;
|
||||
|
||||
/*
|
||||
case SQLITE_AFF_INTEGER:
|
||||
case SQLITE_AFF_NONE:
|
||||
/* Affinity NONE. Do nothing. */
|
||||
break;
|
||||
*/
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This function interprets the character 'affinity' according to the
|
||||
** following table and calls the applyAffinity() function.
|
||||
*/
|
||||
static void applyAffinityByChar(Mem *pRec, char affinity){
|
||||
switch( affinity ){
|
||||
case 'n': return applyAffinity(pRec, SQLITE_SO_NUM);
|
||||
case 't': return applyAffinity(pRec, SQLITE_SO_TEXT);
|
||||
default: assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VDBE_PROFILE
|
||||
/*
|
||||
** The following routine only works on pentium-class processors.
|
||||
@@ -773,6 +772,24 @@ case OP_String: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Real * * P3
|
||||
**
|
||||
** The string value P3 is converted to a real and pushed on to the stack.
|
||||
*/
|
||||
case OP_Real: {
|
||||
char *z = pOp->p3;
|
||||
|
||||
assert( z );
|
||||
assert( sqlite3IsNumber(z, 0) );
|
||||
|
||||
pTos++;
|
||||
pTos->r = sqlite3AtoF(z, 0);
|
||||
pTos->z = z;
|
||||
pTos->n = strlen(z)+1;
|
||||
pTos->flags = MEM_Real|MEM_Str|MEM_Static;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Variable P1 * *
|
||||
**
|
||||
** Push the value of variable P1 onto the stack. A variable is
|
||||
@@ -1358,17 +1375,31 @@ mismatch:
|
||||
** Pop the top two elements from the stack. If they are equal, then
|
||||
** jump to instruction P2. Otherwise, continue to the next instruction.
|
||||
**
|
||||
** If either operand is NULL (and thus if the result is unknown) then
|
||||
** take the jump if P1 is true.
|
||||
** The least significant byte of P1 may be either 0x00 or 0x01. If either
|
||||
** operand is NULL (and thus if the result is unknown) then take the jump
|
||||
** only if the least significant byte of P1 is 0x01.
|
||||
**
|
||||
** If both values are numeric, they are converted to doubles using atof()
|
||||
** and compared for equality that way. Otherwise the strcmp() library
|
||||
** routine is used for the comparison. For a pure text comparison
|
||||
** use OP_StrEq.
|
||||
** The second least significant byte of P1 determines whether any
|
||||
** conversions are applied to the two values before the comparison is made.
|
||||
** If this byte is 0x00, and one of the values being compared is numeric
|
||||
** and the other text, an attempt is made to convert the text value to
|
||||
** a numeric form.
|
||||
**
|
||||
** If the second least significant byte of P1 is not 0x00, then it must
|
||||
** be an affinity character - 'n', 't', 'i' or 'o'. In this case an
|
||||
** attempt is made to coerce both values according to the affinity before
|
||||
** the comparison is made.
|
||||
**
|
||||
** Once any conversions have taken place, and neither value is NULL,
|
||||
** the values are compared. If both values are blobs, or both are text,
|
||||
** then memcmp() is used to determine the results of the comparison. If
|
||||
** both values are numeric, then a numeric comparison is used. If the
|
||||
** two values are of different types, then they are inequal.
|
||||
**
|
||||
** If P2 is zero, do not jump. Instead, push an integer 1 onto the
|
||||
** stack if the jump would have been taken, or a 0 if not. Push a
|
||||
** NULL if either operand was NULL.
|
||||
**
|
||||
*/
|
||||
/* Opcode: Ne P1 P2 *
|
||||
**
|
||||
@@ -1463,6 +1494,8 @@ mismatch:
|
||||
** If P2 is zero, do not jump. Instead, push an integer 1 onto the
|
||||
** stack if the jump would have been taken, or a 0 if not. Push a
|
||||
** NULL if either operand was NULL.
|
||||
**
|
||||
** FIX ME: The comment for OP_Eq is up to date, but none of the others are.
|
||||
*/
|
||||
case OP_Eq:
|
||||
case OP_Ne:
|
||||
@@ -1470,6 +1503,62 @@ case OP_Lt:
|
||||
case OP_Le:
|
||||
case OP_Gt:
|
||||
case OP_Ge: {
|
||||
Mem *pNos;
|
||||
int flags;
|
||||
int res;
|
||||
char affinity;
|
||||
|
||||
pNos = &pTos[-1];
|
||||
flags = pTos->flags|pNos->flags;
|
||||
|
||||
/* If either value is a NULL P2 is not zero, take the jump if the least
|
||||
** significant byte of P1 is true. If P2 is zero, then push a NULL onto
|
||||
** the stack.
|
||||
*/
|
||||
if( flags&MEM_Null ){
|
||||
popStack(&pTos, 2);
|
||||
if( pOp->p2 ){
|
||||
if( pOp->p1 ) pc = pOp->p2-1;
|
||||
}else{
|
||||
pTos++;
|
||||
pTos->flags = MEM_Null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
affinity = (pOp->p1>>8)&0xFF;
|
||||
if( !affinity && (flags&(MEM_Real|MEM_Int)) ){
|
||||
affinity = SQLITE_AFF_NUMERIC;
|
||||
}
|
||||
if( affinity ){
|
||||
applyAffinity(pNos, affinity);
|
||||
applyAffinity(pTos, affinity);
|
||||
}
|
||||
|
||||
res = sqlite3MemCompare(pNos, pTos);
|
||||
switch( pOp->opcode ){
|
||||
case OP_Eq: res = res==0; break;
|
||||
case OP_Ne: res = res!=0; break;
|
||||
case OP_Lt: res = res<0; break;
|
||||
case OP_Le: res = res<=0; break;
|
||||
case OP_Gt: res = res>0; break;
|
||||
default: res = res>=0; break;
|
||||
}
|
||||
|
||||
popStack(&pTos, 2);
|
||||
if( pOp->p2 ){
|
||||
if( res ){
|
||||
pc = pOp->p2-1;
|
||||
}
|
||||
}else{
|
||||
pTos++;
|
||||
pTos->flags = MEM_Int;
|
||||
pTos->i = res;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
Mem *pNos = &pTos[-1];
|
||||
i64 c, v;
|
||||
int ft, fn;
|
||||
@@ -1514,6 +1603,7 @@ case OP_Ge: {
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* INSERT NO CODE HERE!
|
||||
**
|
||||
** The opcode numbers are extracted from this source file by doing
|
||||
@@ -1874,6 +1964,44 @@ case OP_NotNull: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Class * * *
|
||||
**
|
||||
** Pop a single value from the top of the stack and push on one of the
|
||||
** following strings, according to the storage class of the value just
|
||||
** popped:
|
||||
**
|
||||
** "NULL", "INTEGER", "REAL", "TEXT", "BLOB"
|
||||
**
|
||||
** This opcode is probably temporary.
|
||||
*/
|
||||
case OP_Class: {
|
||||
int flags = pTos->flags;
|
||||
int i;
|
||||
|
||||
struct {
|
||||
int mask;
|
||||
char * zClass;
|
||||
} classes[] = {
|
||||
{MEM_Null, "NULL"},
|
||||
{MEM_Int, "INTEGER"},
|
||||
{MEM_Real, "REAL"},
|
||||
{MEM_Str, "TEXT"},
|
||||
{MEM_Blob, "BLOB"}
|
||||
};
|
||||
|
||||
Release(pTos);
|
||||
pTos->flags = MEM_Str|MEM_Static;
|
||||
|
||||
for(i=0; i<5; i++){
|
||||
if( classes[i].mask&flags ){
|
||||
pTos->z = classes[i].zClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert( i<5 );
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Column P1 P2 *
|
||||
**
|
||||
** Interpret the data that cursor P1 points to as a structure built using
|
||||
@@ -1958,11 +2086,11 @@ case OP_Column: {
|
||||
if( zRec ){
|
||||
zData = zRec;
|
||||
}else{
|
||||
/* We can assume that 9 bytes (maximum length of a varint) fits
|
||||
/* We can assume that 10 bytes (maximum length of a varint) fits
|
||||
** on the main page in all cases.
|
||||
*/
|
||||
int n = 9;
|
||||
if( payloadSize<9 ) n = payloadSize;
|
||||
int n = 10;
|
||||
if( payloadSize<10 ) n = payloadSize;
|
||||
if( pC->keyAsData ){
|
||||
zData = (char *)sqlite3BtreeKeyFetch(pCrsr, n);
|
||||
}else{
|
||||
@@ -2152,7 +2280,7 @@ case OP_MakeRecord: {
|
||||
for(pRec=pData0; pRec<=pTos; pRec++){
|
||||
u64 serial_type;
|
||||
if( zAffinity ){
|
||||
applyAffinityByChar(pRec, zAffinity[pRec-pData0]);
|
||||
applyAffinity(pRec, zAffinity[pRec-pData0]);
|
||||
}
|
||||
serial_type = sqlite3VdbeSerialType(pRec);
|
||||
nBytes += sqlite3VdbeSerialTypeLen(serial_type);
|
||||
@@ -2274,7 +2402,7 @@ case OP_MakeIdxKey: {
|
||||
for(pRec=pData0; pRec<=pTos; pRec++){
|
||||
u64 serial_type;
|
||||
if( zAffinity ){
|
||||
applyAffinityByChar(pRec, zAffinity[pRec-pData0]);
|
||||
applyAffinity(pRec, zAffinity[pRec-pData0]);
|
||||
}else{
|
||||
applyAffinity(pRec, SQLITE_SO_NUM);
|
||||
}
|
||||
|
||||
@@ -333,3 +333,4 @@ int sqlite3VdbeSerialGet(const unsigned char *, u64, Mem *);
|
||||
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
|
||||
int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int, int*);
|
||||
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
|
||||
int sqlite3MemCompare(Mem *, Mem *);
|
||||
|
||||
@@ -1317,7 +1317,7 @@ int sqlite3VdbeSerialGet(const unsigned char *buf, u64 serial_type, Mem *pMem){
|
||||
**
|
||||
** Two NULL values are considered equal by this function.
|
||||
*/
|
||||
int compareMemCells(Mem *pMem1, Mem *pMem2){
|
||||
int sqlite3MemCompare(Mem *pMem1, Mem *pMem2){
|
||||
int rc;
|
||||
int combined_flags = pMem1->flags|pMem2->flags;
|
||||
|
||||
@@ -1430,7 +1430,7 @@ int sqlite3VdbeKeyCompare(
|
||||
offset1 += sqlite3VdbeSerialGet(&aKey1[offset1], serial_type1, &mem1);
|
||||
offset2 += sqlite3VdbeSerialGet(&aKey2[offset2], serial_type2, &mem2);
|
||||
|
||||
rc = compareMemCells(&mem1, &mem2);
|
||||
rc = sqlite3MemCompare(&mem1, &mem2);
|
||||
if( mem1.flags&MEM_Dyn ){
|
||||
sqliteFree(mem1.z);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
** This module contains C code that generates VDBE code used to process
|
||||
** the WHERE clause of SQL statements.
|
||||
**
|
||||
** $Id: where.c,v 1.93 2004/05/14 11:16:56 danielk1977 Exp $
|
||||
** $Id: where.c,v 1.94 2004/05/16 11:15:41 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -798,7 +798,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Goto, 0, brk);
|
||||
sqlite3VdbeAddOp(v, OP_MakeKey, nColumn, 0);
|
||||
sqlite3AddIdxKeyType(v, pIdx);
|
||||
sqlite3IndexAffinityStr(v, pIdx);
|
||||
sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
|
||||
if( nColumn==pIdx->nColumn || pLevel->bRev ){
|
||||
testOp = OP_IdxGT;
|
||||
@@ -1003,7 +1003,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
sqlite3VdbeAddOp(v, OP_Pop, nCol, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Goto, 0, brk);
|
||||
sqlite3VdbeAddOp(v, OP_MakeKey, nCol, 0);
|
||||
sqlite3AddIdxKeyType(v, pIdx);
|
||||
sqlite3IndexAffinityStr(v, pIdx);
|
||||
if( pLevel->bRev ){
|
||||
sqlite3VdbeAddOp(v, OP_MoveLt, pLevel->iCur, brk);
|
||||
if( !geFlag ){
|
||||
@@ -1059,7 +1059,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
sqlite3VdbeAddOp(v, OP_Pop, nCol, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Goto, 0, brk);
|
||||
sqlite3VdbeAddOp(v, OP_MakeKey, nCol, 0);
|
||||
sqlite3AddIdxKeyType(v, pIdx);
|
||||
sqlite3IndexAffinityStr(v, pIdx);
|
||||
if( pLevel->bRev ){
|
||||
pLevel->iMem = pParse->nMem++;
|
||||
sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
|
||||
|
||||
164
test/types.test
164
test/types.test
@@ -8,25 +8,117 @@
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
# This file implements regression tests for SQLite library. Specfically
|
||||
# it tests that the different storage classes (integer, real, text etc.)
|
||||
# all work correctly.
|
||||
#
|
||||
# $Id:
|
||||
|
||||
# $Id: types.test,v 1.2 2004/05/16 11:15:42 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# Tests in this file are organized roughly as follows:
|
||||
#
|
||||
# Test cases are organized as follows:
|
||||
# types-1.*.*: Test that values are stored using the expected storage
|
||||
# classes when various forms of literals are inserted into
|
||||
# columns with different affinities.
|
||||
# types-1.1.*: INSERT INTO <table> VALUES(...)
|
||||
# types-1.2.*: INSERT INTO <table> SELECT...
|
||||
# types-1.3.*: UPDATE <table> SET...
|
||||
#
|
||||
# types-1.*: Insert some records with integers of various sizes, checking
|
||||
# that the integers are stored correctly and can be retrieved.
|
||||
# types-2.*: Insert and retrieve some records with reals.
|
||||
# types-3.*: Insert and retrieve some records with NULLs.
|
||||
# types-4.*: Insert and retrieve some records with strings of various sizes.
|
||||
# types-5.*: Some tests inserting and retrieving records with several
|
||||
# fields each.
|
||||
# types-2.*.*: Check that values can be stored and retrieving using the
|
||||
# various storage classes.
|
||||
# types-2.1.*: INTEGER
|
||||
# types-2.2.*: REAL
|
||||
# types-2.3.*: NULL
|
||||
# types-2.4.*: TEXT
|
||||
# types-2.5.*: Records with a few different storage classes.
|
||||
#
|
||||
# types-3.*: Test that the '=' operator respects manifest types.
|
||||
#
|
||||
|
||||
|
||||
# Create a table with one column for each type of affinity
|
||||
do_test types-1.1.0 {
|
||||
execsql {
|
||||
CREATE TABLE t1(i integer, n numeric, t text, o);
|
||||
}
|
||||
} {}
|
||||
|
||||
# Each element of the following list represents one test case.
|
||||
#
|
||||
# The first value of each sub-list is an SQL literal. The following
|
||||
# four value are the storage classes that would be used if the
|
||||
# literal were inserted into a column with affinity INTEGER, NUMERIC, TEXT
|
||||
# or NONE, respectively.
|
||||
set values [list \
|
||||
[list 5.0 INTEGER REAL TEXT REAL] \
|
||||
[list 5 INTEGER INTEGER TEXT INTEGER] \
|
||||
[list '5.0' INTEGER REAL TEXT TEXT] \
|
||||
[list '5' INTEGER INTEGER TEXT TEXT] \
|
||||
[list 'abc' TEXT TEXT TEXT TEXT] \
|
||||
[list NULL NULL NULL NULL NULL] \
|
||||
]
|
||||
|
||||
# This code tests that the storage classes specified above (in the $values
|
||||
# table) are correctly assigned when values are inserted using a statement
|
||||
# of the form:
|
||||
#
|
||||
# INSERT INTO <table> VALUE(<values>);
|
||||
#
|
||||
set tnum 1
|
||||
foreach val $values {
|
||||
set lit [lindex $val 0]
|
||||
execsql "DELETE FROM t1;"
|
||||
execsql "INSERT INTO t1 VALUES($lit, $lit, $lit, $lit);"
|
||||
do_test types-1.1.$tnum {
|
||||
execsql {
|
||||
SELECT classof(i), classof(n), classof(t), classof(o) FROM t1;
|
||||
}
|
||||
} [lrange $val 1 end]
|
||||
incr tnum
|
||||
}
|
||||
|
||||
# This code tests that the storage classes specified above (in the $values
|
||||
# table) are correctly assigned when values are inserted using a statement
|
||||
# of the form:
|
||||
#
|
||||
# INSERT INTO t1 SELECT ....
|
||||
#
|
||||
set tnum 1
|
||||
foreach val $values {
|
||||
set lit [lindex $val 0]
|
||||
execsql "DELETE FROM t1;"
|
||||
execsql "INSERT INTO t1 SELECT $lit, $lit, $lit, $lit;"
|
||||
do_test types-1.2.$tnum {
|
||||
execsql {
|
||||
SELECT classof(i), classof(n), classof(t), classof(o) FROM t1;
|
||||
}
|
||||
} [lrange $val 1 end]
|
||||
incr tnum
|
||||
}
|
||||
|
||||
# This code tests that the storage classes specified above (in the $values
|
||||
# table) are correctly assigned when values are inserted using a statement
|
||||
# of the form:
|
||||
#
|
||||
# UPDATE <table> SET <column> = <value>;
|
||||
#
|
||||
set tnum 1
|
||||
foreach val $values {
|
||||
set lit [lindex $val 0]
|
||||
execsql "UPDATE t1 SET i = $lit, n = $lit, t = $lit, o = $lit;"
|
||||
do_test types-1.3.$tnum {
|
||||
execsql {
|
||||
SELECT classof(i), classof(n), classof(t), classof(o) FROM t1;
|
||||
}
|
||||
} [lrange $val 1 end]
|
||||
incr tnum
|
||||
}
|
||||
|
||||
execsql {
|
||||
DROP TABLE t1;
|
||||
}
|
||||
|
||||
# Open the table with root-page $rootpage at the btree
|
||||
# level. Return a list that is the length of each record
|
||||
@@ -47,7 +139,7 @@ proc record_sizes {rootpage} {
|
||||
|
||||
# Create a table and insert some 1-byte integers. Make sure they
|
||||
# can be read back OK. These should be 3 byte records.
|
||||
do_test types-1.1 {
|
||||
do_test types-2.1.1 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a integer);
|
||||
INSERT INTO t1 VALUES(0);
|
||||
@@ -55,46 +147,46 @@ do_test types-1.1 {
|
||||
INSERT INTO t1 VALUES(-120);
|
||||
}
|
||||
} {}
|
||||
do_test types-1.2 {
|
||||
do_test types-2.1.2 {
|
||||
execsql {
|
||||
SELECT a FROM t1;
|
||||
}
|
||||
} {0 120 -120}
|
||||
|
||||
# Try some 2-byte integers (4 byte records)
|
||||
do_test types-1.3 {
|
||||
do_test types-2.1.3 {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(30000);
|
||||
INSERT INTO t1 VALUES(-30000);
|
||||
}
|
||||
} {}
|
||||
do_test types-1.4 {
|
||||
do_test types-2.1.4 {
|
||||
execsql {
|
||||
SELECT a FROM t1;
|
||||
}
|
||||
} {0 120 -120 30000 -30000}
|
||||
|
||||
# 4-byte integers (6 byte records)
|
||||
do_test types-1.5 {
|
||||
do_test types-2.1.5 {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(2100000000);
|
||||
INSERT INTO t1 VALUES(-2100000000);
|
||||
}
|
||||
} {}
|
||||
do_test types-1.6 {
|
||||
do_test types-2.1.6 {
|
||||
execsql {
|
||||
SELECT a FROM t1;
|
||||
}
|
||||
} {0 120 -120 30000 -30000 2100000000 -2100000000}
|
||||
|
||||
# 8-byte integers (10 byte records)
|
||||
do_test types-1.7 {
|
||||
do_test types-2.1.7 {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(9000000*1000000*1000000);
|
||||
INSERT INTO t1 VALUES(-9000000*1000000*1000000);
|
||||
}
|
||||
} {}
|
||||
do_test types-1.8 {
|
||||
do_test types-2.1.8 {
|
||||
execsql {
|
||||
SELECT a FROM t1;
|
||||
}
|
||||
@@ -102,53 +194,53 @@ do_test types-1.8 {
|
||||
9000000000000000000 -9000000000000000000]
|
||||
|
||||
# Check that all the record sizes are as we expected.
|
||||
do_test types-1.9 {
|
||||
do_test types-2.1.9 {
|
||||
set root [db eval {select rootpage from sqlite_master where name = 't1'}]
|
||||
record_sizes $root
|
||||
} {3 3 3 4 4 6 6 10 10}
|
||||
|
||||
# Insert some reals. These should be 10 byte records.
|
||||
do_test types-2.1 {
|
||||
do_test types-2.2.1 {
|
||||
execsql {
|
||||
CREATE TABLE t2(a float);
|
||||
INSERT INTO t2 VALUES(0.0 + 0.0);
|
||||
INSERT INTO t2 VALUES(12345.678 + 0.0);
|
||||
INSERT INTO t2 VALUES(-12345.678 + 0.0);
|
||||
INSERT INTO t2 VALUES(0.0);
|
||||
INSERT INTO t2 VALUES(12345.678);
|
||||
INSERT INTO t2 VALUES(-12345.678);
|
||||
}
|
||||
} {}
|
||||
do_test types-2.2 {
|
||||
do_test types-2.2.2 {
|
||||
execsql {
|
||||
SELECT a FROM t2;
|
||||
}
|
||||
} {0 12345.678 -12345.678}
|
||||
|
||||
# Check that all the record sizes are as we expected.
|
||||
do_test types-2.3 {
|
||||
do_test types-2.2.3 {
|
||||
set root [db eval {select rootpage from sqlite_master where name = 't2'}]
|
||||
record_sizes $root
|
||||
} {10 10 10}
|
||||
|
||||
# Insert a NULL. This should be a two byte record.
|
||||
do_test types-3.1 {
|
||||
do_test types-2.3.1 {
|
||||
execsql {
|
||||
CREATE TABLE t3(a nullvalue);
|
||||
INSERT INTO t3 VALUES(NULL);
|
||||
}
|
||||
} {}
|
||||
do_test types-3.2 {
|
||||
do_test types-2.3.2 {
|
||||
execsql {
|
||||
SELECT a ISNULL FROM t3;
|
||||
}
|
||||
} {1}
|
||||
|
||||
# Check that all the record sizes are as we expected.
|
||||
do_test types-3.3 {
|
||||
do_test types-2.3.3 {
|
||||
set root [db eval {select rootpage from sqlite_master where name = 't3'}]
|
||||
record_sizes $root
|
||||
} {2}
|
||||
|
||||
# Insert a couple of strings.
|
||||
do_test types-4.1 {
|
||||
do_test types-2.4.1 {
|
||||
set string10 abcdefghij
|
||||
set string500 [string repeat $string10 50]
|
||||
set string500000 [string repeat $string10 50000]
|
||||
@@ -160,19 +252,19 @@ do_test types-4.1 {
|
||||
INSERT INTO t4 VALUES('$string500000');
|
||||
"
|
||||
} {}
|
||||
do_test types-4.2 {
|
||||
do_test types-2.4.2 {
|
||||
execsql {
|
||||
SELECT a FROM t4;
|
||||
}
|
||||
} [list $string10 $string500 $string500000]
|
||||
|
||||
# Check that all the record sizes are as we expected.
|
||||
do_test types-4.3 {
|
||||
do_test types-2.4.3 {
|
||||
set root [db eval {select rootpage from sqlite_master where name = 't4'}]
|
||||
record_sizes $root
|
||||
} {13 504 500005}
|
||||
|
||||
do_test types-5.1 {
|
||||
do_test types-2.5.1 {
|
||||
execsql {
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
@@ -181,7 +273,7 @@ do_test types-5.1 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
}
|
||||
} {}
|
||||
do_test types-5.2 {
|
||||
do_test types-2.5.2 {
|
||||
set string10 abcdefghij
|
||||
set string500 [string repeat $string10 50]
|
||||
set string500000 [string repeat $string10 50000]
|
||||
@@ -190,11 +282,11 @@ do_test types-5.2 {
|
||||
execsql "INSERT INTO t1 VALUES('$string500', 4000, NULL);"
|
||||
execsql "INSERT INTO t1 VALUES(4000, NULL, '$string500000');"
|
||||
} {}
|
||||
do_test types-5.3 {
|
||||
do_test types-2.5.3 {
|
||||
execsql {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} [list {} $string10 4000 $string500 4000 {} 4000 {} $string500000]
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
189
test/types2.test
Normal file
189
test/types2.test
Normal file
@@ -0,0 +1,189 @@
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The focus
|
||||
# of this file is testing the interaction of manifest types, type affinity
|
||||
# and comparison expressions.
|
||||
#
|
||||
# $Id: types2.test,v 1.1 2004/05/16 11:15:42 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# Tests in this file are organized roughly as follows:
|
||||
#
|
||||
# types2-1.*: The '=' operator in the absence of an index.
|
||||
# types2-2.*: The '=' operator implemented using an index.
|
||||
# types2-2.*: The '<' operator implemented using an index.
|
||||
# types2-3.*: The '>' operator in the absense of an index.
|
||||
#
|
||||
|
||||
execsql {
|
||||
CREATE TABLE t1(
|
||||
i1 INTEGER,
|
||||
i2 INTEGER,
|
||||
n1 NUMERIC,
|
||||
n2 NUMERIC,
|
||||
t1 TEXT,
|
||||
t2 TEXT,
|
||||
o1,
|
||||
o2
|
||||
);
|
||||
INSERT INTO t1 VALUES(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
}
|
||||
|
||||
proc test_bool {testname vars expr res} {
|
||||
if { $vars != "" } {
|
||||
execsql "UPDATE t1 SET $vars"
|
||||
}
|
||||
|
||||
foreach {t e r} [list $testname $expr $res] {}
|
||||
|
||||
do_test $t.1 "execsql {SELECT $e FROM t1}" $r
|
||||
do_test $t.2 "execsql {SELECT 1 FROM t1 WHERE $expr}" [expr $r?"1":""]
|
||||
do_test $t.3 "execsql {SELECT 1 FROM t1 WHERE NOT ($e)}" [expr $r?"":"1"]
|
||||
}
|
||||
|
||||
# Compare literals against literals
|
||||
test_bool types2-1.1 "" {500 = 500.0} 1
|
||||
test_bool types2-1.2 "" {'500' = 500.0} 1
|
||||
test_bool types2-1.3 "" {500 = '500.0'} 1
|
||||
test_bool types2-1.4 "" {'500' = '500.0'} 0
|
||||
|
||||
# Compare literals against a column with TEXT affinity
|
||||
test_bool types2-1.5 {t1=500} {500 = t1} 1
|
||||
test_bool types2-1.6 {t1=500} {'500' = t1} 1
|
||||
test_bool types2-1.7 {t1=500} {500.0 = t1} 0
|
||||
test_bool types2-1.8 {t1=500} {'500.0' = t1} 0
|
||||
test_bool types2-1.9 {t1='500'} {500 = t1} 1
|
||||
test_bool types2-1.10 {t1='500'} {'500' = t1} 1
|
||||
test_bool types2-1.11 {t1='500'} {500.0 = t1} 0
|
||||
test_bool types2-1.12 {t1='500'} {'500.0' = t1} 0
|
||||
|
||||
# Compare literals against a column with NUMERIC affinity
|
||||
test_bool types2-1.13 {n1=500} {500 = n1} 1
|
||||
test_bool types2-1.14 {n1=500} {'500' = n1} 1
|
||||
test_bool types2-1.15 {n1=500} {500.0 = n1} 1
|
||||
test_bool types2-1.16 {n1=500} {'500.0' = n1} 1
|
||||
test_bool types2-1.17 {n1='500'} {500 = n1} 1
|
||||
test_bool types2-1.18 {n1='500'} {'500' = n1} 1
|
||||
test_bool types2-1.19 {n1='500'} {500.0 = n1} 1
|
||||
test_bool types2-1.20 {n1='500'} {'500.0' = n1} 1
|
||||
|
||||
# Compare literals against a column with affinity NONE
|
||||
test_bool types2-1.21 {o1=500} {500 = o1} 1
|
||||
test_bool types2-1.22 {o1=500} {'500' = o1} 0
|
||||
test_bool types2-1.23 {o1=500} {500.0 = o1} 1
|
||||
test_bool types2-1.24 {o1=500} {'500.0' = o1} 0
|
||||
test_bool types2-1.25 {o1='500'} {500 = o1} 0
|
||||
test_bool types2-1.26 {o1='500'} {'500' = o1} 1
|
||||
test_bool types2-1.27 {o1='500'} {500.0 = o1} 0
|
||||
test_bool types2-1.28 {o1='500'} {'500.0' = o1} 0
|
||||
|
||||
set vals [list 10 10.0 '10' '10.0' 20 20.0 '20' '20.0' 30 30.0 '30' '30.0']
|
||||
# 1 2 3 4 5 6 7 8 9 10 11 12
|
||||
|
||||
execsql {
|
||||
CREATE TABLE t2(i INTEGER, n NUMERIC, t TEXT, o);
|
||||
CREATE INDEX t2i1 ON t2(i);
|
||||
CREATE INDEX t2i2 ON t2(n);
|
||||
CREATE INDEX t2i3 ON t2(t);
|
||||
CREATE INDEX t2i4 ON t2(o);
|
||||
}
|
||||
foreach v $vals {
|
||||
execsql "INSERT INTO t2 VALUES($v, $v, $v, $v);"
|
||||
}
|
||||
|
||||
proc test_boolset {testname where set} {
|
||||
set ::tb_sql "SELECT rowid FROM t2 WHERE $where"
|
||||
do_test $testname {
|
||||
lsort -integer [execsql $::tb_sql]
|
||||
} $set
|
||||
}
|
||||
|
||||
test_boolset types2-2.1 {i = 10} {1 2 3 4}
|
||||
test_boolset types2-2.2 {i = 10.0} {1 2 3 4}
|
||||
test_boolset types2-2.3 {i = '10'} {1 2 3 4}
|
||||
test_boolset types2-2.4 {i = '10.0'} {1 2 3 4}
|
||||
|
||||
test_boolset types2-2.5 {n = 20} {5 6 7 8}
|
||||
test_boolset types2-2.6 {n = 20.0} {5 6 7 8}
|
||||
test_boolset types2-2.7 {n = '20'} {5 6 7 8}
|
||||
test_boolset types2-2.8 {n = '20.0'} {5 6 7 8}
|
||||
|
||||
test_boolset types2-2.9 {t = 20} {5 7}
|
||||
test_boolset types2-2.10 {t = 20.0} {6 8}
|
||||
test_boolset types2-2.11 {t = '20'} {5 7}
|
||||
test_boolset types2-2.12 {t = '20.0'} {6 8}
|
||||
|
||||
test_boolset types2-2.10 {o = 30} {9 10}
|
||||
test_boolset types2-2.11 {o = 30.0} {9 10}
|
||||
test_boolset types2-2.12 {o = '30'} 11
|
||||
test_boolset types2-2.13 {o = '30.0'} 12
|
||||
|
||||
test_boolset types2-3.1 {i < 20} {1 2 3 4}
|
||||
test_boolset types2-3.2 {i < 20.0} {1 2 3 4}
|
||||
test_boolset types2-3.3 {i < '20'} {1 2 3 4}
|
||||
test_boolset types2-3.4 {i < '20.0'} {1 2 3 4}
|
||||
|
||||
test_boolset types2-3.1 {n < 20} {1 2 3 4}
|
||||
test_boolset types2-3.2 {n < 20.0} {1 2 3 4}
|
||||
test_boolset types2-3.3 {n < '20'} {1 2 3 4}
|
||||
test_boolset types2-3.4 {n < '20.0'} {1 2 3 4}
|
||||
|
||||
test_boolset types2-3.1 {t < 20} {1 2 3 4}
|
||||
test_boolset types2-3.2 {t < 20.0} {1 2 3 4 5 7}
|
||||
test_boolset types2-3.3 {t < '20'} {1 2 3 4}
|
||||
test_boolset types2-3.4 {t < '20.0'} {1 2 3 4 5 7}
|
||||
|
||||
test_boolset types2-3.1 {o < 20} {1 2}
|
||||
test_boolset types2-3.2 {o < 20.0} {1 2}
|
||||
test_boolset types2-3.3 {o < '20'} {1 2 3 4 5 6 9 10}
|
||||
test_boolset types2-3.3 {o < '20.0'} {1 2 3 4 5 6 7 9 10}
|
||||
|
||||
# Compare literals against literals
|
||||
test_bool types2-4.1 "" {500 > 60.0} 1
|
||||
test_bool types2-4.2 "" {'500' > 60.0} 1
|
||||
test_bool types2-4.3 "" {500 > '60.0'} 1
|
||||
test_bool types2-4.4 "" {'500' > '60.0'} 0
|
||||
|
||||
# Compare literals against a column with TEXT affinity
|
||||
test_bool types2-4.5 {t1=500.0} {t1 > 500} 1
|
||||
test_bool types2-4.6 {t1=500.0} {t1 > '500' } 1
|
||||
test_bool types2-4.7 {t1=500.0} {t1 > 500.0 } 0
|
||||
test_bool types2-4.8 {t1=500.0} {t1 > '500.0' } 0
|
||||
test_bool types2-4.9 {t1='500.0'} {t1 > 500 } 1
|
||||
test_bool types2-4.10 {t1='500.0'} {t1 > '500' } 1
|
||||
test_bool types2-4.11 {t1='500.0'} {t1 > 500.0 } 0
|
||||
test_bool types2-4.12 {t1='500.0'} {t1 > '500.0' } 0
|
||||
|
||||
# Compare literals against a column with NUMERIC affinity
|
||||
test_bool types2-4.13 {n1=400} {500 > n1} 1
|
||||
test_bool types2-4.14 {n1=400} {'500' > n1} 1
|
||||
test_bool types2-4.15 {n1=400} {500.0 > n1} 1
|
||||
test_bool types2-4.16 {n1=400} {'500.0' > n1} 1
|
||||
test_bool types2-4.17 {n1='400'} {500 > n1} 1
|
||||
test_bool types2-4.18 {n1='400'} {'500' > n1} 1
|
||||
test_bool types2-4.19 {n1='400'} {500.0 > n1} 1
|
||||
test_bool types2-4.20 {n1='400'} {'500.0' > n1} 1
|
||||
|
||||
# Compare literals against a column with affinity NONE
|
||||
test_bool types2-4.21 {o1=500} {500 > o1} 0
|
||||
test_bool types2-4.22 {o1=500} {'500' > o1} 1
|
||||
test_bool types2-4.23 {o1=500} {500.0 > o1} 0
|
||||
test_bool types2-4.24 {o1=500} {'500.0' > o1} 1
|
||||
test_bool types2-4.25 {o1='500'} {500 > o1} 0
|
||||
test_bool types2-4.26 {o1='500'} {'500' > o1} 0
|
||||
test_bool types2-4.27 {o1='500'} {500.0 > o1} 0
|
||||
test_bool types2-4.28 {o1='500'} {'500.0' > o1} 1
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
Reference in New Issue
Block a user