1
0
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:
danielk1977
2004-05-16 11:15:36 +00:00
parent 3add367f2f
commit a37cdde042
16 changed files with 709 additions and 179 deletions

View File

@@ -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

View File

@@ -1 +1 @@
aab4b794b4238bad5c4a6aee7d4443732921127d
a4af838f8d1b81ec6c8db97655c6876aca0738d9

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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:

View File

@@ -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 },

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 *);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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 *);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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
View 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