From: drh Date: Fri, 5 Jul 2002 21:42:36 +0000 (+0000) Subject: All the code is now in place for SQLite to distinguish between NUMERIC and X-Git-Tag: version-3.6.10~5416 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=38640e15af4c00270c20bdf980225e2a6f7423b5;p=thirdparty%2Fsqlite.git All the code is now in place for SQLite to distinguish between NUMERIC and TEXT datatypes. Still need to turn on the new code and test it. (CVS 659) FossilOrigin-Name: b4737a16c997a6c139d616211fb6bc4b0fae181c --- diff --git a/manifest b/manifest index 61265ffe64..e8849d23c3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sfor\sticket\s#92:\sCorrect\sthe\ssqliteExprCompare()\sfunction\sso\sthat\sis\stakes\ninto\saccount\sthe\siTable\sand\siColumn\sfields\sof\sthe\sExpr\sstructure.\s\sOtherwise,\n"min(a)"\sand\s"min(b)"\swill\scompare\sequal\sto\seach\sother\sin\sviews.\s(CVS\s658) -D 2002-07-02T13:05:05 +C All\sthe\scode\sis\snow\sin\splace\sfor\sSQLite\sto\sdistinguish\sbetween\sNUMERIC\sand\nTEXT\sdatatypes.\s\sStill\sneed\sto\sturn\son\sthe\snew\scode\sand\stest\sit.\s(CVS\s659) +D 2002-07-05T21:42:36 F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -20,28 +20,28 @@ F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6 F src/btree.c 6aaa67d7eab70c2531dc13e5d9eb87e626c0b4d7 F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3 -F src/build.c 0834185cbe316dda5173de50886ed804b82e3ba6 -F src/delete.c 44c45460b1e03033756e35adc6d569ffbf30b725 +F src/build.c ea4a3bc15d6338294e68100f642edf48e4082403 +F src/delete.c 215492ffcea4262a993e55f3c4a67dc9fea4da9c F src/encode.c 346b12b46148506c32038524b95c4631ab46d760 F src/expr.c 4b25ee5e65f351d40dea8575b998605762556d76 F src/func.c 5eae8227a8b0d276a64d51a3880a6e86f238fedf F src/hash.c 6a6236b89c8c060c65dabd300a1c8ce7c10edb72 F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8 -F src/insert.c 4bb40ed9dbaba4516fc2abbcff3f08d5687b073c +F src/insert.c 4511e06abce1688664ce90cbf09fa13433b82c43 F src/main.c 6ac32ca71ab4728212c5b44aed25e26dc6cfe73c F src/md5.c 0ae1f3e2cac92d06fc6246d1b4b8f61a2fe66d3b F src/os.c 9cc40c5384baba4a85e160e67807645ca98ba3cc F src/os.h 4a361fccfbc4e7609b3e1557f604f94c1e96ad10 F src/pager.c 58ae9f569b3c664ea9205c6f6da432e3ae180f56 F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e -F src/parse.y dcaf21965b6cba956d1ad014b87d849cee52af13 +F src/parse.y 35437ac29441ce2d34904d8e93f40b7d112147a9 F src/printf.c 236ed7a79386feed4456fa728fff8be793f1547c F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe -F src/select.c 63a10ea636c8ac8cdf2fbb804fbfcfd372150717 +F src/select.c 1c7c0b42c27b9d115c955023074a292197a17b3b F src/shell.c 0b06e4421ddf34f30263a2674abe768a2b5fd538 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/sqlite.h.in 75c5bbb066d0faf34424b7d1babf8b44d5b31af2 -F src/sqliteInt.h 314a4feb08cccdeb90b434e6dde86b93d2f36b8e +F src/sqliteInt.h 6a36f4fc32cbbf3e6bf15516137b113b3dc973aa F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63 F src/tclsqlite.c e932591c0bb522b0a35ea7dc861c623ccb2e3aa8 F src/test1.c a2f2b6b1df07d4e8b380323896c3ed34442cea91 @@ -50,9 +50,9 @@ F src/test3.c 72ac6a9017a70e542954907a1dfd87ab6f7824e3 F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f F src/tokenize.c b5500e193a82b5b9888fbf947efd90d3b4858178 F src/trigger.c d88ab4d68d68955c217b38fb6717e090fbbf54a4 -F src/update.c 06303bf3895032c7eccb748927f650ed02b9f0cf -F src/util.c 876b259f9186e84b944b72e793dd3dad50e63e95 -F src/vdbe.c c83ece2aeb3a6ce7de9a1636c98c3feec9267499 +F src/update.c 494479cc4fe34165cb9ea97bccefb405e7b875d2 +F src/util.c 7a99e754c44dd220e881122e30581c08b6d6adef +F src/vdbe.c 0169270bb73e8dec4174b90dffc7070c4cabe039 F src/vdbe.h a9292f2b5fcecef924fa255fb74609e9cbc776c2 F src/where.c 6a43aa6c80eab12221eeca754cba852a9ecd1e13 F test/all.test e4d3821eeba751829b419cd47814bd20af4286d1 @@ -95,7 +95,7 @@ F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac F test/select6.test efb8d0c07a440441db87db2c4ade6904e1407e85 F test/sort.test 3b996ce7ca385f9cd559944ac0f4027a23aa546b F test/subselect.test 64e71b1be804dc57c72b61d2bd7b506dbc962c40 -F test/table.test 42511f98a3e9bbee62913e3ae1774777faa23d35 +F test/table.test bc571115def9be8adab6df93aca0b0c05c007eea F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6 F test/tclsqlite.test 6f4b9760681c7dbca52a18d0ab46a1679cdc79b9 F test/temptable.test 9ed7ec0288f887e132de66d90c428ad109105f67 @@ -137,7 +137,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 3cac283de4939538f09cd11e2cbdc84e9a9602f2 -R dcd0974614e55fffecaf44a18cd6cd53 +P 85793a4f03250166c21007cab3525709592d0866 +R f77acd757b229f1cdb42ab7cac78b933 U drh -Z d34a13be1a939e0f9ee685ea0fba9ad6 +Z 6c4c383ead0a1302c4ea68955c9a4a90 diff --git a/manifest.uuid b/manifest.uuid index 1f47792465..24b731aef6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -85793a4f03250166c21007cab3525709592d0866 \ No newline at end of file +b4737a16c997a6c139d616211fb6bc4b0fae181c \ No newline at end of file diff --git a/src/build.c b/src/build.c index 47bdf12d90..9f1aa9cd20 100644 --- a/src/build.c +++ b/src/build.c @@ -25,7 +25,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.100 2002/06/28 12:18:47 drh Exp $ +** $Id: build.c,v 1.101 2002/07/05 21:42:36 drh Exp $ */ #include "sqliteInt.h" #include @@ -463,6 +463,14 @@ void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){ pCol->sortOrder = SQLITE_SO_NUM; for(i=0; z[i]; i++){ switch( z[i] ){ + case 'b': + case 'B': { + if( sqliteStrNICmp(&z[i],"blob",4)==0 ){ + pCol->sortOrder = SQLITE_SO_TEXT; + return; + } + break; + } case 'c': case 'C': { if( sqliteStrNICmp(&z[i],"char",4)==0 || @@ -1092,6 +1100,39 @@ void sqliteDropTable(Parse *pParse, Token *pName, int isView){ sqliteViewResetAll(db); } +/* +** 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 sqliteAddKeyType() routine. +*/ +void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){ + char *zType; + Table *pTab; + int i, n; + assert( pIdx!=0 && pIdx->pTable!=0 ); + pTab = pIdx->pTable; + n = pIdx->nColumn; + zType = sqliteMalloc( n+1 ); + if( zType==0 ) return; + for(i=0; iaiColumn[i]; + assert( iCol>=0 && iColnCol ); + if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){ + zType[i] = 't'; + }else{ + zType[i] = 'n'; + } + } + zType[n] = 0; + sqliteVdbeChangeP3(v, -1, zType, n); + sqliteFree(zType); +} + /* ** Create a new index for an SQL table. pIndex is the name of the index ** and pTable is the name of the table that is to be indexed. Both will @@ -1355,6 +1396,7 @@ void sqliteCreateIndex( sqliteVdbeAddOp(v, OP_Column, 2, pIndex->aiColumn[i]); } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0); + if( db->file_format>=3 ) sqliteAddIdxKeyType(v, pIndex); sqliteVdbeAddOp(v, OP_IdxPut, 1, pIndex->onError!=OE_None); sqliteVdbeAddOp(v, OP_Next, 2, lbl1); sqliteVdbeResolveLabel(v, lbl2); diff --git a/src/delete.c b/src/delete.c index 1dfc7f2443..8e91e25eed 100644 --- a/src/delete.c +++ b/src/delete.c @@ -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.38 2002/06/19 14:27:05 drh Exp $ +** $Id: delete.c,v 1.39 2002/07/05 21:42:37 drh Exp $ */ #include "sqliteInt.h" @@ -261,7 +261,7 @@ void sqliteDeleteFrom( } /* Delete the row */ - sqliteGenerateRowDelete(v, pTab, base, pParse->trigStack==0); + sqliteGenerateRowDelete(db, v, pTab, base, pParse->trigStack==0); /* If there are row triggers, close all cursors then invoke ** the AFTER triggers @@ -329,6 +329,7 @@ delete_from_cleanup: ** entries that point to that record. */ void sqliteGenerateRowDelete( + sqlite *db, /* The database containing the index */ Vdbe *v, /* Generate code into this VDBE */ Table *pTab, /* Table containing the row to be deleted */ int base, /* Cursor number for the table */ @@ -336,7 +337,7 @@ void sqliteGenerateRowDelete( ){ int addr; addr = sqliteVdbeAddOp(v, OP_NotExists, base, 0); - sqliteGenerateRowIndexDelete(v, pTab, base, 0); + sqliteGenerateRowIndexDelete(db, v, pTab, base, 0); sqliteVdbeAddOp(v, OP_Delete, base, count); sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); } @@ -358,6 +359,7 @@ void sqliteGenerateRowDelete( ** deleted. */ void sqliteGenerateRowIndexDelete( + sqlite *db, /* The database containing the index */ Vdbe *v, /* Generate code into this VDBE */ Table *pTab, /* Table containing the row to be deleted */ int base, /* Cursor number for the table */ @@ -379,6 +381,7 @@ void sqliteGenerateRowIndexDelete( } } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); + if( db->file_format>=3 ) sqliteAddIdxKeyType(v, pIdx); sqliteVdbeAddOp(v, OP_IdxDelete, base+i, 0); } } diff --git a/src/insert.c b/src/insert.c index ee5b31f92d..a6b2e858ed 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.62 2002/06/19 20:32:44 drh Exp $ +** $Id: insert.c,v 1.63 2002/07/05 21:42:37 drh Exp $ */ #include "sqliteInt.h" @@ -616,6 +616,7 @@ void sqliteGenerateConstraintChecks( } } jumpInst1 = sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); + if( pParse->db->file_format>=3 ) sqliteAddIdxKeyType(v, pIdx); onError = pIdx->onError; if( onError==OE_None ) continue; if( overrideError!=OE_Default ){ @@ -640,7 +641,7 @@ void sqliteGenerateConstraintChecks( break; } case OE_Replace: { - sqliteGenerateRowDelete(v, pTab, base, 0); + sqliteGenerateRowDelete(pParse->db, v, pTab, base, 0); if( isUpdate ){ sqliteVdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1); sqliteVdbeAddOp(v, OP_MoveTo, base, 0); diff --git a/src/parse.y b/src/parse.y index 0eadf3570c..6a2e3dc86f 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.76 2002/07/01 12:27:09 drh Exp $ +** @(#) $Id: parse.y,v 1.77 2002/07/05 21:42:37 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -394,9 +394,9 @@ sortlist(A) ::= sortlist(X) COMMA sortitem(Y) collate(C) sortorder(Z). { A = sqliteExprListAppend(X,Y,0); if( A ) A->a[A->nExpr-1].sortOrder = C+Z; } -sortlist(A) ::= sortitem(Y) sortorder(Z). { +sortlist(A) ::= sortitem(Y) collate(C) sortorder(Z). { A = sqliteExprListAppend(0,Y,0); - if( A ) A->a[0].sortOrder = Z; + if( A ) A->a[0].sortOrder = C+Z; } sortitem(A) ::= expr(X). {A = X;} diff --git a/src/select.c b/src/select.c index 92fa302a52..882e8885c3 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.102 2002/06/29 02:20:08 drh Exp $ +** $Id: select.c,v 1.103 2002/07/05 21:42:37 drh Exp $ */ #include "sqliteInt.h" @@ -315,7 +315,24 @@ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){ zSortOrder = sqliteMalloc( pOrderBy->nExpr + 1 ); if( zSortOrder==0 ) return; for(i=0; inExpr; i++){ - zSortOrder[i] = pOrderBy->a[i].sortOrder ? '-' : '+'; + int order = pOrderBy->a[i].sortOrder; + int type; + int c; + if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){ + type = SQLITE_SO_TEXT; + }else if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_NUM ){ + type = SQLITE_SO_NUM; + }else if( pParse->db->file_format>=3 ){ + type = sqliteExprType(pOrderBy->a[i].pExpr); + }else{ + type = SQLITE_SO_NUM; + } + if( (order & SQLITE_SO_DIRMASK)==SQLITE_SO_ASC ){ + c = type==SQLITE_SO_TEXT ? 'A' : '+'; + }else{ + c = type==SQLITE_SO_TEXT ? 'D' : '-'; + } + zSortOrder[i] = c; sqliteExprCode(pParse, pOrderBy->a[i].pExpr); } zSortOrder[pOrderBy->nExpr] = 0; @@ -325,13 +342,37 @@ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){ sqliteVdbeAddOp(v, OP_SortPut, 0, 0); } +/* +** This routine adds a P3 argument to the last VDBE opcode that was +** inserted. The P3 argument added is a string suitable for the +** OP_MakeKey or OP_MakeIdxKey opcodes. The string consists of +** characters 't' or 'n' depending on whether or not the various +** fields of the key to be generated should be treated as numeric +** or as text. See the OP_MakeKey and OP_MakeIdxKey opcode +** documentation for additional information about the P3 string. +** See also the sqliteAddIdxKeyType() routine. +*/ +void sqliteAddKeyType(Vdbe *v, ExprList *pEList){ + int nColumn = pEList->nExpr; + char *zType = sqliteMalloc( nColumn+1 ); + int i; + if( zType==0 ) return; + for(i=0; ia[i].pExpr)==SQLITE_SO_NUM ? 'n' : 't'; + } + zType[i] = 0; + sqliteVdbeChangeP3(v, -1, zType, nColumn); + sqliteFree(zType); +} + /* ** This routine generates the code for the inside of the inner loop ** of a SELECT. ** -** The pEList is used to determine the values for each column in the -** result row. Except if pEList==NULL, then we just read nColumn -** elements from the srcTab table. +** If srcTab and nColumn are both zero, then the pEList expressions +** are evaluated in order to get the data for this row. If nColumn>0 +** then data is pulled from srcTab and pEList is used only to get the +** datatypes for each column. */ static int selectInnerLoop( Parse *pParse, /* The parser context */ @@ -348,7 +389,9 @@ static int selectInnerLoop( ){ Vdbe *v = pParse->pVdbe; int i; + if( v==0 ) return 0; + assert( pEList!=0 ); /* If there was a LIMIT clause on the SELECT statement, then do the check ** to see if this row should be output. @@ -366,15 +409,15 @@ static int selectInnerLoop( /* Pull the requested columns. */ - if( pEList ){ - for(i=0; inExpr; i++){ - sqliteExprCode(pParse, pEList->a[i].pExpr); - } - nColumn = pEList->nExpr; - }else{ + if( nColumn>0 ){ for(i=0; inExpr; + for(i=0; inExpr; i++){ + sqliteExprCode(pParse, pEList->a[i].pExpr); + } } /* If the DISTINCT keyword was present on the SELECT statement @@ -386,6 +429,7 @@ static int selectInnerLoop( sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7); #endif sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1); + if( pParse->db->file_format>=3 ) sqliteAddKeyType(v, pEList); sqliteVdbeAddOp(v, OP_Distinct, distinct, sqliteVdbeCurrentAddr(v)+3); sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, iContinue); @@ -1119,7 +1163,7 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){ iCont = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, unionTab, iBreak); iStart = sqliteVdbeCurrentAddr(v); - rc = selectInnerLoop(pParse, p, 0, unionTab, p->pEList->nExpr, + rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, p->pOrderBy, -1, eDest, iParm, iCont, iBreak); if( rc ) return 1; @@ -1175,7 +1219,7 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){ sqliteVdbeAddOp(v, OP_Rewind, tab1, iBreak); iStart = sqliteVdbeAddOp(v, OP_FullKey, tab1, 0); sqliteVdbeAddOp(v, OP_NotFound, tab2, iCont); - rc = selectInnerLoop(pParse, p, 0, tab1, p->pEList->nExpr, + rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, p->pOrderBy, -1, eDest, iParm, iCont, iBreak); if( rc ) return 1; @@ -1547,7 +1591,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ eList.a = &eListItem; eList.a[0].pExpr = pExpr; cont = sqliteVdbeMakeLabel(v); - selectInnerLoop(pParse, p, &eList, base, 1, 0, -1, eDest, iParm, cont, cont); + selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont); sqliteVdbeResolveLabel(v, cont); sqliteVdbeAddOp(v, OP_Close, base, 0); return 1; @@ -1914,6 +1958,7 @@ int sqliteSelect( sqliteExprCode(pParse, pGroupBy->a[i].pExpr); } sqliteVdbeAddOp(v, OP_MakeKey, pGroupBy->nExpr, 0); + if( pParse->db->file_format>=3 ) sqliteAddKeyType(v, pGroupBy); lbl1 = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_AggFocus, 0, lbl1); for(i=0; inAgg; i++){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5f842e0c03..7b7e142321 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.133 2002/06/29 02:20:09 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.134 2002/07/05 21:42:37 drh Exp $ */ #include "sqlite.h" #include "hash.h" @@ -871,6 +871,8 @@ void sqliteIdListDelete(IdList*); void sqliteSrcListDelete(SrcList*); void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, int, Token*, Token*); void sqliteDropIndex(Parse*, Token*); +void sqliteAddKeyType(Vdbe*, ExprList*); +void sqliteAddIdxKeyType(Vdbe*, Index*); int sqliteSelect(Parse*, Select*, int, int, Select*, int, int*); Select *sqliteSelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*, int,int,int); @@ -909,8 +911,8 @@ char *sqlite_mprintf(const char *, ...); int sqliteExprIsConstant(Expr*); int sqliteExprIsInteger(Expr*, int*); int sqliteIsRowid(const char*); -void sqliteGenerateRowDelete(Vdbe*, Table*, int, int); -void sqliteGenerateRowIndexDelete(Vdbe*, Table*, int, char*); +void sqliteGenerateRowDelete(sqlite*, Vdbe*, Table*, int, int); +void sqliteGenerateRowIndexDelete(sqlite*, Vdbe*, Table*, int, char*); void sqliteGenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int); void sqliteCompleteInsertion(Parse*, Table*, int, char*, int, int); void sqliteBeginWriteOperation(Parse*, int); diff --git a/src/update.c b/src/update.c index 0a6f6db203..656b8edfd9 100644 --- a/src/update.c +++ b/src/update.c @@ -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.46 2002/06/29 02:20:09 drh Exp $ +** $Id: update.c,v 1.47 2002/07/05 21:42:37 drh Exp $ */ #include "sqliteInt.h" @@ -319,7 +319,7 @@ void sqliteUpdate( /* Delete the old indices for the current record. */ - sqliteGenerateRowIndexDelete(v, pTab, base, aIdxUsed); + sqliteGenerateRowIndexDelete(db, v, pTab, base, aIdxUsed); /* If changing the record number, delete the old record. */ diff --git a/src/util.c b/src/util.c index 007dd5aa1d..21736e9ea3 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.46 2002/06/14 20:58:45 drh Exp $ +** $Id: util.c,v 1.47 2002/07/05 21:42:37 drh Exp $ */ #include "sqliteInt.h" #include @@ -705,11 +705,15 @@ int sqliteCompare(const char *atext, const char *btext){ ** returns negative, zero, or positive if the first argument is less ** than, equal to, or greater than the first. (Result is a-b). ** -** Every string begins with either a "+" or "-" character. If the -** character is "-" then the return value is negated. This is done -** to implement a sort in descending order. +** Each string begins with one of the characters "+", "-", "A", "D". +** This character determines the sort order and collating sequence: ** -** For sorting purposes, pur numeric strings (strings for which the +** + Sort numerically in ascending order +** - Sort numerically in descending order +** A Sort as strings in ascending order +** D Sort as strings in descending order. +** +** For the "+" and "-" sorting, pure numeric strings (strings for which the ** isNum() function above returns TRUE) always compare less than strings ** that are not pure numerics. Within non-numeric strings, substrings ** of digits compare in numerical order. Finally, case is used only @@ -721,6 +725,10 @@ int sqliteCompare(const char *atext, const char *btext){ ** lexigraphical order. This routine does the additional processing ** to sort substrings of digits into numerical order and to use case ** only as a tie-breaker. +** +** The special rules above apply only to numeric sorting, when the +** prefix is "+" or "-". If the prefix is "A" or "D" then plain old +** "strcmp()" is used for the comparison. */ int sqliteSortCompare(const char *a, const char *b){ int len; @@ -728,6 +736,7 @@ int sqliteSortCompare(const char *a, const char *b){ int isNumA, isNumB; while( res==0 && *a && *b ){ + assert( a[0]==b[0] ); if( a[1]==0 ){ res = -1; break; @@ -735,41 +744,46 @@ int sqliteSortCompare(const char *a, const char *b){ res = +1; break; } - isNumA = sqliteIsNumber(&a[1]); - isNumB = sqliteIsNumber(&b[1]); - if( isNumA ){ - double rA, rB; - if( !isNumB ){ - res = -1; - break; - } - rA = atof(&a[1]); - rB = atof(&b[1]); - if( rArB ){ - res = +1; - break; - } - }else if( isNumB ){ - res = +1; - break; + if( a[0]=='A' || a[0]=='D' ){ + res = strcmp(&a[1],&b[1]); + if( res ) break; }else{ - res = sortStrCmp(&a[1],&b[1],0); - if( res==0 ){ - res = sortStrCmp(&a[1],&b[1],1); - } - if( res!=0 ){ + isNumA = sqliteIsNumber(&a[1]); + isNumB = sqliteIsNumber(&b[1]); + if( isNumA ){ + double rA, rB; + if( !isNumB ){ + res = -1; + break; + } + rA = atof(&a[1]); + rB = atof(&b[1]); + if( rArB ){ + res = +1; + break; + } + }else if( isNumB ){ + res = +1; break; + }else{ + res = sortStrCmp(&a[1],&b[1],0); + if( res==0 ){ + res = sortStrCmp(&a[1],&b[1],1); + } + if( res!=0 ){ + break; + } } } len = strlen(&a[1]) + 2; a += len; b += len; } - if( *a=='-' ) res = -res; + if( *a=='-' || *a=='D' ) res = -res; return res; } diff --git a/src/vdbe.c b/src/vdbe.c index 83b36d90ce..3700a4baa6 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -30,7 +30,7 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.163 2002/06/29 02:20:09 drh Exp $ +** $Id: vdbe.c,v 1.164 2002/07/05 21:42:37 drh Exp $ */ #include "sqliteInt.h" #include @@ -2632,7 +2632,7 @@ case OP_MakeRecord: { ** P3 is a string that is P1 characters long. Each character is either ** an 'n' or a 't' to indicates if the argument should be numeric or ** text. The first character corresponds to the lowest element on the -** stack. +** stack. If P3 is NULL then all arguments are assumed to be numeric. ** ** See also: MakeIdxKey, SortMakeKey */ @@ -2661,7 +2661,7 @@ case OP_MakeRecord: { ** P3 is a string that is P1 characters long. Each character is either ** an 'n' or a 't' to indicates if the argument should be numeric or ** text. The first character corresponds to the lowest element on the -** stack. +** stack. If P3 is null then all arguments are assumed to be numeric. ** ** See also: MakeKey, SortMakeKey */ diff --git a/test/table.test b/test/table.test index 6c8c00bb78..c4b432070f 100644 --- a/test/table.test +++ b/test/table.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing the CREATE TABLE statement. # -# $Id: table.test,v 1.17 2002/06/02 18:19:00 drh Exp $ +# $Id: table.test,v 1.18 2002/07/05 21:42:38 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -434,6 +434,31 @@ do_test table-10.8 { } } {0 {}} - +# Test for the "typeof" function. +# +do_test table-11.1 { + execsql { + CREATE TABLE t7( + a integer primary key, + b number(5,10), + c character varying (8), + d VARCHAR(9), + e clob, + f BLOB, + g Text, + h + ); + INSERT INTO t7(a) VALUES(1); + SELECT typeof(a), typeof(b), typeof(c), typeof(d), + typeof(e), typeof(f), typeof(g), typeof(h) + FROM t7 LIMIT 1; + } +} {numeric numeric text text text text text numeric} +do_test table-11.2 { + execsql { + SELECT typeof(a+b), typeof(a||b), typeof(c+d), typeof(c||d) + FROM t7 LIMIT 1; + } +} {numeric text numeric text} finish_test