mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
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
This commit is contained in:
30
manifest
30
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
|
||||
|
@ -1 +1 @@
|
||||
85793a4f03250166c21007cab3525709592d0866
|
||||
b4737a16c997a6c139d616211fb6bc4b0fae181c
|
44
src/build.c
44
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 <ctype.h>
|
||||
@ -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; 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;
|
||||
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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;}
|
||||
|
||||
|
73
src/select.c
73
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; i<pOrderBy->nExpr; 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; i<nColumn; i++){
|
||||
zType[i] = sqliteExprType(pEList->a[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; i<pEList->nExpr; i++){
|
||||
sqliteExprCode(pParse, pEList->a[i].pExpr);
|
||||
}
|
||||
nColumn = pEList->nExpr;
|
||||
}else{
|
||||
if( nColumn>0 ){
|
||||
for(i=0; i<nColumn; i++){
|
||||
sqliteVdbeAddOp(v, OP_Column, srcTab, i);
|
||||
}
|
||||
}else{
|
||||
nColumn = pEList->nExpr;
|
||||
for(i=0; i<pEList->nExpr; 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; i<pParse->nAgg; i++){
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*/
|
||||
|
78
src/util.c
78
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 <stdarg.h>
|
||||
@ -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( rA<rB ){
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if( rA>rB ){
|
||||
if( a[0]=='A' || a[0]=='D' ){
|
||||
res = strcmp(&a[1],&b[1]);
|
||||
if( res ) break;
|
||||
}else{
|
||||
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( rA<rB ){
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if( rA>rB ){
|
||||
res = +1;
|
||||
break;
|
||||
}
|
||||
}else if( isNumB ){
|
||||
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;
|
||||
}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;
|
||||
}
|
||||
|
||||
|
@ -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 <ctype.h>
|
||||
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user