1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Fix datatype reporting and collating sequence selection so that it works

correctly on views and with the UNION, EXCEPT, and INTERCEPT operators. (CVS 839)

FossilOrigin-Name: 71cc292dce59cf8224b205d1cdbff59ad12f1043
This commit is contained in:
drh
2003-01-18 20:11:05 +00:00
parent be4f31c226
commit fcb78a4900
13 changed files with 299 additions and 96 deletions

View File

@ -1 +1 @@
2.7.6-beta1 2.7.6-beta2

View File

@ -1,9 +1,9 @@
C Do\snot\sreport\san\serror\sif\sthe\sinput\sto\sthe\ssqlite\sshell\sends\sin\sa\scomment.\nTicket\s#211.\s(CVS\s838) C Fix\sdatatype\sreporting\sand\scollating\ssequence\sselection\sso\sthat\sit\sworks\ncorrectly\son\sviews\sand\swith\sthe\sUNION,\sEXCEPT,\sand\sINTERCEPT\soperators.\s(CVS\s839)
D 2003-01-18T17:05:01 D 2003-01-18T20:11:06
F Makefile.in 6606854b1512f185b8e8c779b8d7fc2750463d64 F Makefile.in 6606854b1512f185b8e8c779b8d7fc2750463d64
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
F VERSION cb5dfb005f1dfad89748ecd8dd06a6a31de4d01f F VERSION e62321dec1c1ffc06dc20c388bee76fd95a8567b
F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d
F config.guess f38b1e93d1e0fa6f5a6913e9e7b12774b9232588 F config.guess f38b1e93d1e0fa6f5a6913e9e7b12774b9232588
F config.sub f14b07d544ca26b5d698259045136b783e18fc7f F config.sub f14b07d544ca26b5d698259045136b783e18fc7f
@ -15,16 +15,16 @@ F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
F libtool c56e618713c9510a103bda6b95f3ea3900dcacd6 F libtool c56e618713c9510a103bda6b95f3ea3900dcacd6
F ltmain.sh e9ed72eb1d690f447c13945eaf69e28af531eda1 F ltmain.sh e9ed72eb1d690f447c13945eaf69e28af531eda1
F main.mk 8b10c5df8a21cdd343986a90c75247bafaebb3aa F main.mk 8b10c5df8a21cdd343986a90c75247bafaebb3aa
F publish.sh e5b83867d14708ed58cec8cba0a4f201e969474d F publish.sh ce0bf7e235984bc156dc5d1a0c8092db4c8442f3
F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
F src/auth.c 9c2db0bc7707f2d2e227f47e3d557b41d44ade75 F src/auth.c 9c2db0bc7707f2d2e227f47e3d557b41d44ade75
F src/btree.c 131b5903f66e148f0f9af0cedd1c6654932c4e04 F src/btree.c 131b5903f66e148f0f9af0cedd1c6654932c4e04
F src/btree.h 17710339f7a8f46e3c7d6d0d4648ef19c584ffda F src/btree.h 17710339f7a8f46e3c7d6d0d4648ef19c584ffda
F src/build.c 3bf5d10439f669f01f45a7c7b604ee0115b23154 F src/build.c 0454fd02e163865c82106dd52dec4a4caf908ebf
F src/delete.c cbd499f3f9297504c42e328af89bef1a2113d04c F src/delete.c cbd499f3f9297504c42e328af89bef1a2113d04c
F src/encode.c 09d1fe8a2e97ff94cce496e2909e2ebc8947960b F src/encode.c 09d1fe8a2e97ff94cce496e2909e2ebc8947960b
F src/expr.c 19f315a6c274897275d15ad7f238f604d178d706 F src/expr.c 382839b92cb66a34cfa71cf1d2bc8fb818226c90
F src/func.c 90c583f0b91220f7cd411a2407deaf9327245d63 F src/func.c 90c583f0b91220f7cd411a2407deaf9327245d63
F src/hash.c 4fc39feb7b7711f6495ee9f2159559bedb043e1f F src/hash.c 4fc39feb7b7711f6495ee9f2159559bedb043e1f
F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8 F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
@ -35,14 +35,14 @@ F src/os.c 3a652608c296cf639ce63bd31d255db862e45685
F src/os.h afa3e096213bad86845f8bdca81a9e917505e401 F src/os.h afa3e096213bad86845f8bdca81a9e917505e401
F src/pager.c 081155624cff7bec54590133b69906a23f9b3659 F src/pager.c 081155624cff7bec54590133b69906a23f9b3659
F src/pager.h 540833e8cb826b80ce2e39aa917deee5e12db626 F src/pager.h 540833e8cb826b80ce2e39aa917deee5e12db626
F src/parse.y 58655a50817f93ddd0bc3d8949e267729396949c F src/parse.y a4fbfbe3c4254c96dae8c33264fb54af755a3770
F src/printf.c 5c50fc1da75c8f5bf432b1ad17d91d6653acd167 F src/printf.c 5c50fc1da75c8f5bf432b1ad17d91d6653acd167
F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
F src/select.c 5ce75c1381d8ec3b89ea4d7eb5171bc57785e610 F src/select.c 65373244633151884ea83daffb34ef98382ac3b3
F src/shell.c cbb29252f0bd7b144d1e3126e64e17e5a314f2fd F src/shell.c cbb29252f0bd7b144d1e3126e64e17e5a314f2fd
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in 90657185cff387069d17c5b876a87a6a7a3b6f10 F src/sqlite.h.in 90657185cff387069d17c5b876a87a6a7a3b6f10
F src/sqliteInt.h 1df32c9bcf08e30b5b8b978fd587fac018273c33 F src/sqliteInt.h 1d614e04f3c439d7bb60a65f821f8ec53ef6a7e8
F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63 F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63
F src/tclsqlite.c 9f2c00a92338c51171ded8943bd42d77f7e69e64 F src/tclsqlite.c 9f2c00a92338c51171ded8943bd42d77f7e69e64
F src/test1.c 921e5dda494f836d2ebea703bd5b239a7cc963d0 F src/test1.c 921e5dda494f836d2ebea703bd5b239a7cc963d0
@ -84,12 +84,12 @@ F test/main.test c66b564554b770ee7fdbf6a66c0cd90329bc2c85
F test/malloc.test 7ba32a9ebd3aeed52ae4aaa6d42ca37e444536fd F test/malloc.test 7ba32a9ebd3aeed52ae4aaa6d42ca37e444536fd
F test/memleak.test b4f59aa44488793b00feff2011d77d0f05b22468 F test/memleak.test b4f59aa44488793b00feff2011d77d0f05b22468
F test/minmax.test 29bc5727c3e4c792d5c4745833dd4b505905819e F test/minmax.test 29bc5727c3e4c792d5c4745833dd4b505905819e
F test/misc1.test 828ea289e37d396432064ab23d2efc6ce660a0f9 F test/misc1.test 9f9e8b6f824b4c388ce3ad0cabdc873e0d22e28e
F test/misuse.test a3aa2b18a97e4c409a1fcaff5151a4dd804a0162 F test/misuse.test a3aa2b18a97e4c409a1fcaff5151a4dd804a0162
F test/notnull.test b1f3e42fc475b0b5827b27b2e9b562081995ff30 F test/notnull.test b1f3e42fc475b0b5827b27b2e9b562081995ff30
F test/null.test 5c2b57307e4b6178aae825eb65ddbee01e76b0fd F test/null.test 5c2b57307e4b6178aae825eb65ddbee01e76b0fd
F test/pager.test d3a2e2f00999f97e056822a39d5ee2fad18bf12c F test/pager.test d3a2e2f00999f97e056822a39d5ee2fad18bf12c
F test/pragma.test 94c82c75af9c237866ce5290494a7bc08b661092 F test/pragma.test 0ca0773e2559ec9715f72d90695554dc3368e8f2
F test/printf.test a29b8afa24edb4411adfe473b12ac32c84098fce F test/printf.test a29b8afa24edb4411adfe473b12ac32c84098fce
F test/quick.test b372c8dad4fa1554747e90683fc72e59c0c98502 F test/quick.test b372c8dad4fa1554747e90683fc72e59c0c98502
F test/quote.test 08f23385c685d3dc7914ec760d492cacea7f6e3d F test/quote.test 08f23385c685d3dc7914ec760d492cacea7f6e3d
@ -100,7 +100,7 @@ F test/select3.test ba35d6611e8bfe526a89355da39dde482d4ecd41
F test/select4.test 10ba54f24ef6ca7958a7045b001079378db2370c F test/select4.test 10ba54f24ef6ca7958a7045b001079378db2370c
F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac
F test/select6.test efb8d0c07a440441db87db2c4ade6904e1407e85 F test/select6.test efb8d0c07a440441db87db2c4ade6904e1407e85
F test/sort.test 876b76c5a837af5bead713146c7c65f85e84fbf5 F test/sort.test 61a729023ae4ac3be9b225dc0be026fb43fec4e6
F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f
F test/table.test 2a94f55b39008daa79b81f37aaf7be81386ca71e F test/table.test 2a94f55b39008daa79b81f37aaf7be81386ca71e
F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6 F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6
@ -143,7 +143,7 @@ F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
F www/faq.tcl 06276ff6c3e369374bb83034cc9d4a7d3a2a34a1 F www/faq.tcl 06276ff6c3e369374bb83034cc9d4a7d3a2a34a1
F www/fileformat.tcl a4b5c2c6e89b7d42d09f97fd4d7bbd39cbf24936 F www/fileformat.tcl a4b5c2c6e89b7d42d09f97fd4d7bbd39cbf24936
F www/formatchng.tcl b4449e065d2da38b6563bdf12cf46cfe1d4d765e F www/formatchng.tcl b4449e065d2da38b6563bdf12cf46cfe1d4d765e
F www/index.tcl 7764032a802318a916ae747b047c9ad5149658a5 F www/index.tcl 374d30b92a753428baed933623fb9f4259fc5a5c
F www/lang.tcl 1ea38a9fe867e4fed2220f519f5c0862e7022c53 F www/lang.tcl 1ea38a9fe867e4fed2220f519f5c0862e7022c53
F www/mingw.tcl f1c7c0a7f53387dd9bb4f8c7e8571b7561510ebc F www/mingw.tcl f1c7c0a7f53387dd9bb4f8c7e8571b7561510ebc
F www/nulls.tcl 29497dac2bc5b437aa7e2e94577dad4d8933ed26 F www/nulls.tcl 29497dac2bc5b437aa7e2e94577dad4d8933ed26
@ -154,7 +154,7 @@ F www/speed.tcl a20a792738475b68756ea7a19321600f23d1d803
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
P 960a2e4af3b940d74a82f98e8bf19aeec88a05ce P 32a8e6e9771d636c0ad3042632d35865bc08585b
R 401c88fefa12fdbc2635d9394c8dc749 R 04e23a1126d9810e8620977dfdd8daac
U drh U drh
Z d11acb4a94d33c83e2103e12a2cf5085 Z d5604eb0c9b6db0f87d9ac88ab2eea6a

View File

@ -1 +1 @@
32a8e6e9771d636c0ad3042632d35865bc08585b 71cc292dce59cf8224b205d1cdbff59ad12f1043

View File

@ -113,6 +113,8 @@ sqlite_set_result_error
sqliteMalloc sqliteMalloc
sqliteFree sqliteFree
sqliteRealloc sqliteRealloc
sqlite_set_authorizer
sqlite_trace
END_OF_FILE END_OF_FILE
i386-mingw32msvc-dllwrap \ i386-mingw32msvc-dllwrap \
--def sqlite.def -v --export-all \ --def sqlite.def -v --export-all \

View File

@ -25,7 +25,7 @@
** ROLLBACK ** ROLLBACK
** PRAGMA ** PRAGMA
** **
** $Id: build.c,v 1.123 2003/01/14 02:54:08 drh Exp $ ** $Id: build.c,v 1.124 2003/01/18 20:11:07 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@ -530,40 +530,10 @@ void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
z[j++] = c; z[j++] = c;
} }
z[j] = 0; z[j] = 0;
pCol->sortOrder = SQLITE_SO_NUM;
if( pParse->db->file_format>=4 ){ if( pParse->db->file_format>=4 ){
for(i=0; z[i]; i++){ pCol->sortOrder = sqliteCollateType(z, n);
switch( z[i] ){ }else{
case 'b': pCol->sortOrder = SQLITE_SO_NUM;
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 ||
sqliteStrNICmp(&z[i],"clob",4)==0 ){
pCol->sortOrder = SQLITE_SO_TEXT;
return;
}
break;
}
case 'x':
case 'X': {
if( i>=2 && sqliteStrNICmp(&z[i-2],"text",4)==0 ){
pCol->sortOrder = SQLITE_SO_TEXT;
return;
}
break;
}
default: {
break;
}
}
}
} }
} }
@ -643,21 +613,47 @@ void sqliteAddPrimaryKey(Parse *pParse, IdList *pList, int onError){
} }
/* /*
** Return the appropriate collating type given the collation type token. ** Return the appropriate collating type given a type name.
** Report an error if the type is undefined. **
** The collation type is text (SQLITE_SO_TEXT) if the type
** name contains the character stream "text" or "blob" or
** "clob". Any other type name is collated as numeric
** (SQLITE_SO_NUM).
*/ */
int sqliteCollateType(Parse *pParse, Token *pType){ int sqliteCollateType(const char *zType, int nType){
if( pType==0 ) return SQLITE_SO_UNK; int i;
if( pType->n==4 && sqliteStrNICmp(pType->z, "text", 4)==0 ){ int sortOrder = SQLITE_SO_NUM;
return SQLITE_SO_TEXT; for(i=0; i<nType-1; i++){
switch( zType[i] ){
case 'b':
case 'B': {
if( i<nType-3 && sqliteStrNICmp(&zType[i],"blob",4)==0 ){
return SQLITE_SO_TEXT;
}
break;
}
case 'c':
case 'C': {
if( i<nType-3 && (sqliteStrNICmp(&zType[i],"char",4)==0 ||
sqliteStrNICmp(&zType[i],"clob",4)==0)
){
return SQLITE_SO_TEXT;
}
break;
}
case 'x':
case 'X': {
if( i>=2 && sqliteStrNICmp(&zType[i-2],"text",4)==0 ){
return SQLITE_SO_TEXT;
}
break;
}
default: {
break;
}
}
} }
if( pType->n==7 && sqliteStrNICmp(pType->z, "numeric", 7)==0 ){ return SQLITE_SO_NUM;
return SQLITE_SO_NUM;
}
sqliteSetNString(&pParse->zErrMsg, "unknown collating type: ", -1,
pType->z, pType->n, 0);
pParse->nErr++;
return SQLITE_SO_UNK;
} }
/* /*

View File

@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and ** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite. ** for generating VDBE code that evaluates expressions in SQLite.
** **
** $Id: expr.c,v 1.85 2003/01/14 02:49:28 drh Exp $ ** $Id: expr.c,v 1.86 2003/01/18 20:11:07 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@ -122,7 +122,7 @@ void sqliteExprDelete(Expr *p){
Expr *sqliteExprDup(Expr *p){ Expr *sqliteExprDup(Expr *p){
Expr *pNew; Expr *pNew;
if( p==0 ) return 0; if( p==0 ) return 0;
pNew = sqliteMalloc( sizeof(*p) ); pNew = sqliteMallocRaw( sizeof(*p) );
if( pNew==0 ) return 0; if( pNew==0 ) return 0;
memcpy(pNew, p, sizeof(*pNew)); memcpy(pNew, p, sizeof(*pNew));
if( p->token.z!=0 ){ if( p->token.z!=0 ){

View File

@ -14,7 +14,7 @@
** the parser. Lemon will also generate a header file containing ** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens. ** numeric codes for all of the tokens.
** **
** @(#) $Id: parse.y,v 1.87 2003/01/13 23:27:33 drh Exp $ ** @(#) $Id: parse.y,v 1.88 2003/01/18 20:11:07 drh Exp $
*/ */
%token_prefix TK_ %token_prefix TK_
%token_type {Token} %token_type {Token}
@ -174,7 +174,7 @@ ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
{sqliteCreateForeignKey(pParse,0,&T,TA,R);} {sqliteCreateForeignKey(pParse,0,&T,TA,R);}
ccons ::= defer_subclause(D). {sqliteDeferForeignKey(pParse,D);} ccons ::= defer_subclause(D). {sqliteDeferForeignKey(pParse,D);}
ccons ::= COLLATE id(C). { ccons ::= COLLATE id(C). {
sqliteAddCollateType(pParse, sqliteCollateType(pParse, &C)); sqliteAddCollateType(pParse, sqliteCollateType(C.z, C.n));
} }
// The next group of rules parses the arguments to a REFERENCES clause // The next group of rules parses the arguments to a REFERENCES clause
@ -417,7 +417,7 @@ sortorder(A) ::= ASC. {A = SQLITE_SO_ASC;}
sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;} sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;}
sortorder(A) ::= . {A = SQLITE_SO_ASC;} sortorder(A) ::= . {A = SQLITE_SO_ASC;}
collate(C) ::= . {C = SQLITE_SO_UNK;} collate(C) ::= . {C = SQLITE_SO_UNK;}
collate(C) ::= COLLATE id(X). {C = sqliteCollateType(pParse, &X);} collate(C) ::= COLLATE id(X). {C = sqliteCollateType(X.z, X.n);}
%type groupby_opt {ExprList*} %type groupby_opt {ExprList*}
%destructor groupby_opt {sqliteExprListDelete($$);} %destructor groupby_opt {sqliteExprListDelete($$);}

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite. ** to handle SELECT statements in SQLite.
** **
** $Id: select.c,v 1.121 2003/01/13 23:27:33 drh Exp $ ** $Id: select.c,v 1.122 2003/01/18 20:11:07 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@ -675,9 +675,48 @@ static void generateSortTail(
} }
/* /*
** Generate code that will tell the VDBE how many columns there ** Generate code that will tell the VDBE the datatypes of
** are in the result and the name for each column. This information ** columns in the result set.
** is used to provide "argc" and "azCol[]" values in the callback. */
static void generateColumnTypes(
Parse *pParse, /* Parser context */
int base, /* VDBE cursor corresponding to first entry in pTabList */
SrcList *pTabList, /* List of tables */
ExprList *pEList /* Expressions defining the result set */
){
Vdbe *v = pParse->pVdbe;
int i;
if( (pParse->db->flags & SQLITE_ReportTypes)==0 ) return;
for(i=0; i<pEList->nExpr; i++){
Expr *p = pEList->a[i].pExpr;
char *zType = 0;
if( p==0 ) continue;
if( p->op==TK_COLUMN && pTabList ){
Table *pTab = pTabList->a[p->iTable - base].pTab;
int iCol = p->iColumn;
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
if( iCol<0 ){
zType = "INTEGER";
}else{
zType = pTab->aCol[iCol].zType;
}
}else{
if( sqliteExprType(p)==SQLITE_SO_TEXT ){
zType = "TEXT";
}else{
zType = "NUMERIC";
}
}
sqliteVdbeAddOp(v, OP_ColumnName, i + pEList->nExpr, 0);
sqliteVdbeChangeP3(v, -1, zType, P3_STATIC);
}
}
/*
** Generate code that will tell the VDBE the names of columns
** in the result set. This information is used to provide the
** azCol[] vaolues in the callback.
*/ */
static void generateColumnNames( static void generateColumnNames(
Parse *pParse, /* Parser context */ Parse *pParse, /* Parser context */
@ -695,17 +734,6 @@ static void generateColumnNames(
int showFullNames; int showFullNames;
p = pEList->a[i].pExpr; p = pEList->a[i].pExpr;
if( p==0 ) continue; if( p==0 ) continue;
if( pParse->db->flags & SQLITE_ReportTypes ){
if( zType==0 ){
if( sqliteExprType(p)==SQLITE_SO_TEXT ){
zType = "TEXT";
}else{
zType = "NUMERIC";
}
}
sqliteVdbeAddOp(v, OP_ColumnName, i + pEList->nExpr, 0);
sqliteVdbeChangeP3(v, -1, zType, P3_STATIC);
}
if( pEList->a[i].zName ){ if( pEList->a[i].zName ){
char *zName = pEList->a[i].zName; char *zName = pEList->a[i].zName;
sqliteVdbeAddOp(v, OP_ColumnName, i, 0); sqliteVdbeAddOp(v, OP_ColumnName, i, 0);
@ -1050,6 +1078,13 @@ void sqliteSelectUnbind(Select *p){
** **
** Any entry that does not match is flagged as an error. The number ** Any entry that does not match is flagged as an error. The number
** of errors is returned. ** of errors is returned.
**
** This routine does NOT correctly initialize the Expr.dataType field
** of the ORDER BY expressions. The multiSelectSortOrder() routine
** must be called to do that after the individual select statements
** have all been analyzed. This routine is unable to compute Expr.dataType
** because it must be called before the individual select statements
** have been analyzed.
*/ */
static int matchOrderbyToColumn( static int matchOrderbyToColumn(
Parse *pParse, /* A place to leave error messages */ Parse *pParse, /* A place to leave error messages */
@ -1089,6 +1124,7 @@ static int matchOrderbyToColumn(
nErr++; nErr++;
break; break;
} }
if( !mustComplete ) continue;
iCol--; iCol--;
} }
for(j=0; iCol<0 && j<pEList->nExpr; j++){ for(j=0; iCol<0 && j<pEList->nExpr; j++){
@ -1137,7 +1173,43 @@ Vdbe *sqliteGetVdbe(Parse *pParse){
} }
return v; return v;
} }
/*
** This routine sets the Expr.dataType field on all elements of
** the pOrderBy expression list. The pOrderBy list will have been
** set up by matchOrderbyToColumn(). Hence each expression has
** a TK_COLUMN as its root node. The Expr.iColumn refers to a
** column in the result set. The datatype is set to SQLITE_SO_TEXT
** if the corresponding column in p and every SELECT to the left of
** p has a datatype of SQLITE_SO_TEXT. If the cooressponding column
** in p or any of the left SELECTs is SQLITE_SO_NUM, then the datatype
** of the order-by expression is set to SQLITE_SO_NUM.
**
** Examples:
**
** SELECT a,b
*/
static void multiSelectSortOrder(Select *p, ExprList *pOrderBy){
int i;
ExprList *pEList;
if( pOrderBy==0 ) return;
if( p==0 ){
for(i=0; i<pOrderBy->nExpr; i++){
pOrderBy->a[i].pExpr->dataType = SQLITE_SO_TEXT;
}
return;
}
multiSelectSortOrder(p->pPrior, pOrderBy);
pEList = p->pEList;
for(i=0; i<pOrderBy->nExpr; i++){
Expr *pE = pOrderBy->a[i].pExpr;
if( pE->dataType==SQLITE_SO_NUM ) continue;
assert( pE->iColumn>=0 );
if( pEList->nExpr>pE->iColumn ){
pE->dataType = sqliteExprType(pEList->a[pE->iColumn].pExpr);
}
}
}
/* /*
** This routine is called to process a query that is really the union ** This routine is called to process a query that is really the union
@ -1248,11 +1320,13 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
assert( p->pEList ); assert( p->pEList );
if( eDest==SRT_Callback ){ if( eDest==SRT_Callback ){
generateColumnNames(pParse, p->base, 0, p->pEList); generateColumnNames(pParse, p->base, 0, p->pEList);
generateColumnTypes(pParse, p->base, p->pSrc, p->pEList);
} }
iBreak = sqliteVdbeMakeLabel(v); iBreak = sqliteVdbeMakeLabel(v);
iCont = sqliteVdbeMakeLabel(v); iCont = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_Rewind, unionTab, iBreak); sqliteVdbeAddOp(v, OP_Rewind, unionTab, iBreak);
iStart = sqliteVdbeCurrentAddr(v); iStart = sqliteVdbeCurrentAddr(v);
multiSelectSortOrder(p, p->pOrderBy);
rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
p->pOrderBy, -1, eDest, iParm, p->pOrderBy, -1, eDest, iParm,
iCont, iBreak); iCont, iBreak);
@ -1303,12 +1377,14 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
assert( p->pEList ); assert( p->pEList );
if( eDest==SRT_Callback ){ if( eDest==SRT_Callback ){
generateColumnNames(pParse, p->base, 0, p->pEList); generateColumnNames(pParse, p->base, 0, p->pEList);
generateColumnTypes(pParse, p->base, p->pSrc, p->pEList);
} }
iBreak = sqliteVdbeMakeLabel(v); iBreak = sqliteVdbeMakeLabel(v);
iCont = sqliteVdbeMakeLabel(v); iCont = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_Rewind, tab1, iBreak); sqliteVdbeAddOp(v, OP_Rewind, tab1, iBreak);
iStart = sqliteVdbeAddOp(v, OP_FullKey, tab1, 0); iStart = sqliteVdbeAddOp(v, OP_FullKey, tab1, 0);
sqliteVdbeAddOp(v, OP_NotFound, tab2, iCont); sqliteVdbeAddOp(v, OP_NotFound, tab2, iCont);
multiSelectSortOrder(p, p->pOrderBy);
rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
p->pOrderBy, -1, eDest, iParm, p->pOrderBy, -1, eDest, iParm,
iCont, iBreak); iCont, iBreak);
@ -1331,6 +1407,12 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
pParse->nErr++; pParse->nErr++;
return 1; return 1;
} }
/* Issue a null callback if that is what the user wants.
*/
if( (pParse->db->flags & SQLITE_NullCallback)!=0 && eDest==SRT_Callback ){
sqliteVdbeAddOp(v, OP_NullCallback, p->pEList->nExpr, 0);
}
return 0; return 0;
} }
@ -1383,6 +1465,7 @@ static void substExpr(Expr *pExpr, int iTable, ExprList *pEList, int iSub){
pNew = pEList->a[pExpr->iColumn].pExpr; pNew = pEList->a[pExpr->iColumn].pExpr;
assert( pNew!=0 ); assert( pNew!=0 );
pExpr->op = pNew->op; pExpr->op = pNew->op;
pExpr->dataType = pNew->dataType;
assert( pExpr->pLeft==0 ); assert( pExpr->pLeft==0 );
pExpr->pLeft = sqliteExprDup(pNew->pLeft); pExpr->pLeft = sqliteExprDup(pNew->pLeft);
assert( pExpr->pRight==0 ); assert( pExpr->pRight==0 );
@ -1686,6 +1769,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
if( v==0 ) return 0; if( v==0 ) return 0;
if( eDest==SRT_Callback ){ if( eDest==SRT_Callback ){
generateColumnNames(pParse, p->base, p->pSrc, p->pEList); generateColumnNames(pParse, p->base, p->pSrc, p->pEList);
generateColumnTypes(pParse, p->base, p->pSrc, p->pEList);
} }
/* Generating code to find the min or the max. Basically all we have /* Generating code to find the min or the max. Basically all we have
@ -1992,6 +2076,13 @@ int sqliteSelect(
return rc; return rc;
} }
/* Identify column types if we will be using in the callback. This
** step is skipped if the output is going to a table or a memory cell.
*/
if( eDest==SRT_Callback ){
generateColumnTypes(pParse, p->base, pTabList, pEList);
}
/* If the output is destined for a temporary table, open that table. /* If the output is destined for a temporary table, open that table.
*/ */
if( eDest==SRT_TempTable ){ if( eDest==SRT_TempTable ){

View File

@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** Internal interface definitions for SQLite.
** **
** @(#) $Id: sqliteInt.h,v 1.155 2003/01/16 16:28:54 drh Exp $ ** @(#) $Id: sqliteInt.h,v 1.156 2003/01/18 20:11:07 drh Exp $
*/ */
#include "config.h" #include "config.h"
#include "sqlite.h" #include "sqlite.h"
@ -948,7 +948,7 @@ void sqliteAddNotNull(Parse*, int);
void sqliteAddPrimaryKey(Parse*, IdList*, int); void sqliteAddPrimaryKey(Parse*, IdList*, int);
void sqliteAddColumnType(Parse*,Token*,Token*); void sqliteAddColumnType(Parse*,Token*,Token*);
void sqliteAddDefaultValue(Parse*,Token*,int); void sqliteAddDefaultValue(Parse*,Token*,int);
int sqliteCollateType(Parse*, Token*); int sqliteCollateType(const char*, int);
void sqliteAddCollateType(Parse*, int); void sqliteAddCollateType(Parse*, int);
void sqliteEndTable(Parse*,Token*,Select*); void sqliteEndTable(Parse*,Token*,Select*);
void sqliteCreateView(Parse*,Token*,Token*,Select*,int); void sqliteCreateView(Parse*,Token*,Token*,Select*,int);

View File

@ -13,7 +13,7 @@
# This file implements tests for miscellanous features that were # This file implements tests for miscellanous features that were
# left out of other test files. # left out of other test files.
# #
# $Id: misc1.test,v 1.17 2002/12/07 21:45:14 drh Exp $ # $Id: misc1.test,v 1.18 2003/01/18 20:11:07 drh Exp $
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@ -376,11 +376,16 @@ do_test misc1-12.9 {
SELECT min(z), max(z), count(z) FROM t7 GROUP BY y ORDER BY 1; SELECT min(z), max(z), count(z) FROM t7 GROUP BY y ORDER BY 1;
} }
} {1 2 2 3 4 2} } {1 2 2 3 4 2}
# This used to be an error. But we changed the code so that arbitrary
# identifiers can be used as a collating sequence. Collation is by text
# if the identifier contains "text", "blob", or "clob" and is numeric
# otherwise.
do_test misc1-12.10 { do_test misc1-12.10 {
catchsql { catchsql {
SELECT * FROM t6 ORDER BY a COLLATE unknown; SELECT * FROM t6 ORDER BY a COLLATE unknown;
} }
} {1 {unknown collating type: unknown}} } {0 {0 0.0 y 0}}
do_test misc1-12.11 { do_test misc1-12.11 {
execsql { execsql {
CREATE TABLE t8(x TEXT COLLATE numeric, y INTEGER COLLATE text, z); CREATE TABLE t8(x TEXT COLLATE numeric, y INTEGER COLLATE text, z);

View File

@ -12,7 +12,7 @@
# #
# This file implements tests for the PRAGMA command. # This file implements tests for the PRAGMA command.
# #
# $Id: pragma.test,v 1.2 2003/01/11 14:19:52 drh Exp $ # $Id: pragma.test,v 1.3 2003/01/18 20:11:07 drh Exp $
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@ -129,7 +129,7 @@ do_test pragma-1.12 {
PRAGMA empty_result_callbacks=on; PRAGMA empty_result_callbacks=on;
} }
sqlite_datatypes $::DB {SELECT * FROM sqlite_master} sqlite_datatypes $::DB {SELECT * FROM sqlite_master}
} {NUMERIC NUMERIC NUMERIC NUMERIC NUMERIC} } {text text text integer text}
do_test pragma-1.13 { do_test pragma-1.13 {
execsql { execsql {
CREATE TABLE t1( CREATE TABLE t1(
@ -143,7 +143,7 @@ do_test pragma-1.13 {
); );
} }
sqlite_datatypes $::DB {SELECT * FROM t1} sqlite_datatypes $::DB {SELECT * FROM t1}
} {NUMERIC TEXT NUMERIC TEXT TEXT TEXT TEXT} } {INTEGER TEXT WHATEVER CLOB BLOB VARCHAR(123) nVaRcHaR(432)}
do_test pragma-1.14 { do_test pragma-1.14 {
sqlite_datatypes $::DB { sqlite_datatypes $::DB {
SELECT 1, 'hello', NULL SELECT 1, 'hello', NULL
@ -154,6 +154,33 @@ do_test pragma-1.15 {
SELECT 1+2 AS X, 'hello' || 5 AS Y, NULL AS Z SELECT 1+2 AS X, 'hello' || 5 AS Y, NULL AS Z
} }
} {NUMERIC TEXT TEXT} } {NUMERIC TEXT TEXT}
do_test pragma-1.16 {
execsql {
CREATE VIEW v1 AS SELECT a+b, b||c, * FROM t1;
}
sqlite_datatypes $::DB {SELECT * FROM v1}
} {NUMERIC TEXT INTEGER TEXT WHATEVER CLOB BLOB VARCHAR(123) nVaRcHaR(432)}
do_test pragma-1.17 {
sqlite_datatypes $::DB {
SELECT d,e FROM t1 UNION SELECT a,c FROM t1
}
} {INTEGER WHATEVER}
do_test pragma-1.18 {
sqlite_datatypes $::DB {
SELECT d,e FROM t1 EXCEPT SELECT c,e FROM t1
}
} {WHATEVER BLOB}
do_test pragma-1.19 {
sqlite_datatypes $::DB {
SELECT d,e FROM t1 INTERSECT SELECT c,e FROM t1
}
} {WHATEVER BLOB}
do_test pragma-1.20 {
sqlite_datatypes $::DB {
SELECT d,e FROM t1 INTERSECT SELECT c,e FROM v1
}
} {WHATEVER BLOB}
finish_test finish_test

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The # This file implements regression tests for SQLite library. The
# focus of this file is testing the CREATE TABLE statement. # focus of this file is testing the CREATE TABLE statement.
# #
# $Id: sort.test,v 1.7 2002/08/26 19:55:11 drh Exp $ # $Id: sort.test,v 1.8 2003/01/18 20:11:07 drh Exp $
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@ -267,4 +267,84 @@ do_test sort-6.4 {
} }
} {4 1 6 5 3 2} } {4 1 6 5 3 2}
do_test sort-7.1 {
execsql {
CREATE TABLE t4(
a INTEGER,
b VARCHAR(30)
);
INSERT INTO t4 VALUES(1,1);
INSERT INTO t4 VALUES(2,2);
INSERT INTO t4 VALUES(11,11);
INSERT INTO t4 VALUES(12,12);
SELECT a FROM t4 ORDER BY 1;
}
} {1 2 11 12}
do_test sort-7.2 {
execsql {
SELECT b FROM t4 ORDER BY 1
}
} {1 11 12 2}
do_test sort-7.3 {
execsql {
CREATE VIEW v4 AS SELECT * FROM t4;
SELECT a FROM v4 ORDER BY 1;
}
} {1 2 11 12}
do_test sort-7.4 {
execsql {
SELECT b FROM v4 ORDER BY 1;
}
} {1 11 12 2}
do_test sort-7.5 {
execsql {
SELECT a FROM t4 UNION SELECT a FROM v4 ORDER BY 1;
}
} {1 2 11 12}
do_test sort-7.6 {
execsql {
SELECT b FROM t4 UNION SELECT a FROM v4 ORDER BY 1;
}
} {1 2 11 12}
do_test sort-7.7 {
execsql {
SELECT a FROM t4 UNION SELECT b FROM v4 ORDER BY 1;
}
} {1 2 11 12}
do_test sort-7.8 {
execsql {
SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1;
}
} {1 11 12 2}
do_test sort-7.9 {
execsql {
SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE numeric;
}
} {1 2 11 12}
do_test sort-7.10 {
execsql {
SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE integer;
}
} {1 2 11 12}
do_test sort-7.11 {
execsql {
SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE text;
}
} {1 11 12 2}
do_test sort-7.12 {
execsql {
SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE blob;
}
} {1 11 12 2}
do_test sort-7.13 {
execsql {
SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE clob;
}
} {1 11 12 2}
do_test sort-7.14 {
execsql {
SELECT b FROM t4 UNION SELECT b FROM v4 ORDER BY 1 COLLATE varchar;
}
} {1 11 12 2}
finish_test finish_test

View File

@ -1,7 +1,7 @@
# #
# Run this TCL script to generate HTML for the index.html file. # Run this TCL script to generate HTML for the index.html file.
# #
set rcsid {$Id: index.tcl,v 1.70 2002/11/06 14:08:12 drh Exp $} set rcsid {$Id: index.tcl,v 1.71 2003/01/18 20:11:07 drh Exp $}
puts {<html> puts {<html>
<head><title>SQLite: An Embeddable SQL Database Engine</title></head> <head><title>SQLite: An Embeddable SQL Database Engine</title></head>
@ -180,7 +180,9 @@ puts {
If you would like professional support for SQLite If you would like professional support for SQLite
or if you want custom modifications to SQLite preformed by the or if you want custom modifications to SQLite preformed by the
original author, these services are available for a modest fee. original author, these services are available for a modest fee.
For additional information contact:</p> For additional information visit
<a href="http://www.hwaci.com/sw/sqlite/support.html">
http://www.hwaci.com/sw/sqlite/support.html</a> or contact:</p>
<blockquote> <blockquote>
D. Richard Hipp <br /> D. Richard Hipp <br />