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

Version 2.0.6 (CVS 291)

FossilOrigin-Name: 8467d84fc6e67bd93051f54338a8f6c9b1711ee1
This commit is contained in:
drh
2001-10-19 16:44:56 +00:00
parent 98808babd3
commit 6a535340bc
16 changed files with 399 additions and 227 deletions

View File

@ -1 +1 @@
2.0.5 2.0.6

View File

@ -1,9 +1,9 @@
C Support\sfor\sUTF-8\sand\sISO8859\scharacters\sin\sidentifiers.\s\sBug\sfix\sin\nthe\scolumn\sname\sgenerator\sfor\sselects\s(was\scoreing).\s(CVS\s290) C Version\s2.0.6\s(CVS\s291)
D 2001-10-18T12:34:47 D 2001-10-19T16:44:56
F Makefile.in 6801df952cb1df64aa32e4de85fed24511d28efd F Makefile.in 6801df952cb1df64aa32e4de85fed24511d28efd
F Makefile.template 1fdb891f14083ee0b63cf7282f91529634438e7a F Makefile.template 1fdb891f14083ee0b63cf7282f91529634438e7a
F README 93d2977cc5c6595c448de16bdefc312b9d401533 F README 93d2977cc5c6595c448de16bdefc312b9d401533
F VERSION e14d2010c343ae28a0dd038c3850eae3a88a9307 F VERSION be4a9c5c382f200a4575c3dc5133f6359a33606a
F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d
F config.guess f38b1e93d1e0fa6f5a6913e9e7b12774b9232588 F config.guess f38b1e93d1e0fa6f5a6913e9e7b12774b9232588
F config.log 6a73d03433669b10a3f0c221198c3f26b9413914 F config.log 6a73d03433669b10a3f0c221198c3f26b9413914
@ -21,7 +21,7 @@ F publish.sh badcd69b8e3a8bc69b162c4c9d7c209b2a0b119e
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6 F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
F src/btree.c 97653e88bc4b7396226b93c878b153c77f1d3d03 F src/btree.c 97653e88bc4b7396226b93c878b153c77f1d3d03
F src/btree.h 57d653ef5137b91f2a068aaf71a2905468dd2cb7 F src/btree.h 57d653ef5137b91f2a068aaf71a2905468dd2cb7
F src/build.c fe71d516148226bd6249403e82f8d07129206489 F src/build.c d18081e69b23390cb6baaaf6f6c804b93775a0be
F src/delete.c 6fe2191c49c4a31336e2fac11b3ad665ddcd4246 F src/delete.c 6fe2191c49c4a31336e2fac11b3ad665ddcd4246
F src/expr.c c1381b8229a5573b0928ede962e45c1c49d067af F src/expr.c c1381b8229a5573b0928ede962e45c1c49d067af
F src/hash.c b7ced0735287c142a3b2db46c3cae3e6826afb75 F src/hash.c b7ced0735287c142a3b2db46c3cae3e6826afb75
@ -36,21 +36,21 @@ F src/pager.h a0d4c5ae271914aa07b62aee0707997d6932b6ca
F src/parse.y 148e4cd134d3cbd816dcb0df50e49e498faa6ba4 F src/parse.y 148e4cd134d3cbd816dcb0df50e49e498faa6ba4
F src/printf.c b1e22a47be8cdf707815647239991e08e8cb69f9 F src/printf.c b1e22a47be8cdf707815647239991e08e8cb69f9
F src/random.c 2a9cc2c9716d14815fd4c2accf89d87a1143e46b F src/random.c 2a9cc2c9716d14815fd4c2accf89d87a1143e46b
F src/select.c 0e8089c5ae84fa3eb7e64b40350832983918e7a4 F src/select.c 10957c2fd52ee36fbb40171c36377c9f94dd36ea
F src/shell.c cb8c41f1b2173efd212dab3f35f1fc6bf32ead76 F src/shell.c 71597951753b56a97fea1c7a30908f31e635c00c
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in b95c161abf1d58bceb05290fa3f657d8f388fc11 F src/sqlite.h.in b95c161abf1d58bceb05290fa3f657d8f388fc11
F src/sqliteInt.h acfd52eb2949abb847b1be93687e93e3663231b2 F src/sqliteInt.h 52577abf2805ba148972f69788ed49c64064fa31
F src/table.c abd0adbe0fee39d995287b3bcccd908d174dfcac F src/table.c 4e8cbabfbc6018fdd0615f7c5d06fb431cd56505
F src/tclsqlite.c 0b947866c89fe5b683fc86e8419b7f8da3cebf7d F src/tclsqlite.c 7d205aeda449047f86b39a6c55731a1ded7a7ab5
F src/test1.c e4b31f62ea71963cbae44338acf477a04fc8fc49 F src/test1.c e4b31f62ea71963cbae44338acf477a04fc8fc49
F src/test2.c e9f99aa5ee73872819259d6612c11e55e1644321 F src/test2.c e9f99aa5ee73872819259d6612c11e55e1644321
F src/test3.c 4a0d7b882fdae731dbb759f512ad867122452f96 F src/test3.c 4a0d7b882fdae731dbb759f512ad867122452f96
F src/tokenize.c 2b95e67bcb5f68e7fe4a5a426fcbe0891d7aaa54 F src/tokenize.c 59ddae1501de472e9a6274a1cbf451170c52488c
F src/update.c c916182c6bfbc8a6f20c24920c4560fece6c9569 F src/update.c c916182c6bfbc8a6f20c24920c4560fece6c9569
F src/util.c 4da3be37d0fd3c640d2d3033503768afdc8e5387 F src/util.c 4da3be37d0fd3c640d2d3033503768afdc8e5387
F src/vdbe.c 01617df84381c3ace10feb370b8d1f72f275c1ab F src/vdbe.c e326ff611c9d2c273fdcb86b4661b464f2af128b
F src/vdbe.h 86fc2ef42f48024c9a2e1b7fb01eda22b65a5295 F src/vdbe.h f8407fd6b644bc001b1e7c65460c9962f6a15f6b
F src/where.c 22fe910c7c8e2736eb37e9861343e90c0b513c86 F src/where.c 22fe910c7c8e2736eb37e9861343e90c0b513c86
F test/all.test a2320eb40b462f25bd3e33115b1cabf3791450dd F test/all.test a2320eb40b462f25bd3e33115b1cabf3791450dd
F test/bigrow.test a35f2de9948b24e427fb292c35947795efe182d0 F test/bigrow.test a35f2de9948b24e427fb292c35947795efe182d0
@ -74,7 +74,7 @@ F test/printf.test 3cb415073754cb8ff076f26173143c3cd293a9da
F test/quick.test b6ec50f808efc06595fd324bf4f3fabadb9c7e9c F test/quick.test b6ec50f808efc06595fd324bf4f3fabadb9c7e9c
F test/quote.test 286db944717afa9a9bf829dd85e59185c65d5435 F test/quote.test 286db944717afa9a9bf829dd85e59185c65d5435
F test/rowid.test 427bfbbe9684fe7a2f851aa05badaae6d4972ce8 F test/rowid.test 427bfbbe9684fe7a2f851aa05badaae6d4972ce8
F test/select1.test 129c0188565383c3d22858161b96fefd3f7fa09f F test/select1.test 75af194669ff9f4fe42c6fd070d9ec3b268354bb
F test/select2.test f91c903e2bab0e9d45274855a981eebf846d5e32 F test/select2.test f91c903e2bab0e9d45274855a981eebf846d5e32
F test/select3.test 5e1fe8e5a4e63fb2827ab3b89527e0fd4ae35259 F test/select3.test 5e1fe8e5a4e63fb2827ab3b89527e0fd4ae35259
F test/select4.test 29a2ffb187f3d8b6ca42a0a6b619e9cabe12e228 F test/select4.test 29a2ffb187f3d8b6ca42a0a6b619e9cabe12e228
@ -101,20 +101,20 @@ F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4 F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
F www/arch.tcl 03b521d252575f93b9c52f7c8b0007011512fcfb F www/arch.tcl 03b521d252575f93b9c52f7c8b0007011512fcfb
F www/c_interface.tcl a59ee0835d1b33fcddab7d4fd65cf9e50f7d2dc7 F www/c_interface.tcl 6c5989670e014de44dce6580cbde0eea965dadbb
F www/changes.tcl 5ff43653f6387ce7b6e0a8aa384855b3f3b76550 F www/changes.tcl 7f249321a6ccb4abb79e56b801dede791a44c237
F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e
F www/download.tcl 3e51c9ff1326b0a182846134987301310dff7d60 F www/download.tcl 3e51c9ff1326b0a182846134987301310dff7d60
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
F www/index.tcl 68c815d64b35b2dcc4d4f6845827df71c6869f9f F www/index.tcl 68c815d64b35b2dcc4d4f6845827df71c6869f9f
F www/lang.tcl 37d4a44bdafe42a270b9e28554651278086ce806 F www/lang.tcl 1899ec4fb77cd69de335ebd998253de869f34d8e
F www/mingw.tcl fc5f4ba9d336b6e8c97347cc6496d6162461ef60 F www/mingw.tcl fc5f4ba9d336b6e8c97347cc6496d6162461ef60
F www/opcode.tcl 4365ad9798872491dbd7d3071510ebe461785ac3 F www/opcode.tcl 4365ad9798872491dbd7d3071510ebe461785ac3
F www/speed.tcl ab7d6d3bc898472bd94320a5d3c63de928d4804b F www/speed.tcl ab7d6d3bc898472bd94320a5d3c63de928d4804b
F www/sqlite.tcl 6a21242a272e9c0939a04419a51c3d50cae33e3e F www/sqlite.tcl 6a21242a272e9c0939a04419a51c3d50cae33e3e
F www/tclsqlite.tcl 13d50723f583888fc80ae1a38247c0ab415066fa F www/tclsqlite.tcl 13d50723f583888fc80ae1a38247c0ab415066fa
F www/vdbe.tcl bb7d620995f0a987293e9d4fb6185a3b077e9b44 F www/vdbe.tcl bb7d620995f0a987293e9d4fb6185a3b077e9b44
P e2d84f71ed39cbb75884205521aa9e316ab3b56c P 22948fc685299ca888907eea68edb8a6e87c3f49
R 3132f2509f739a21413aa9b99beee504 R 517debf090e30b01a34d90ad2b9ba498
U drh U drh
Z 7eb9951a3a4ed42d9ed165321f9fc396 Z 0b94093f141bb1ed6e93360cffc751d6

View File

@ -1 +1 @@
22948fc685299ca888907eea68edb8a6e87c3f49 8467d84fc6e67bd93051f54338a8f6c9b1711ee1

View File

@ -25,7 +25,7 @@
** ROLLBACK ** ROLLBACK
** PRAGMA ** PRAGMA
** **
** $Id: build.c,v 1.50 2001/10/15 00:44:36 drh Exp $ ** $Id: build.c,v 1.51 2001/10/19 16:44:57 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@ -1449,6 +1449,14 @@ void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
} }
}else }else
if( sqliteStrICmp(zLeft, "empty_result_callbacks")==0 ){
if( getBoolean(zRight) ){
db->flags |= SQLITE_NullCallback;
}else{
db->flags &= ~SQLITE_NullCallback;
}
}else
if( sqliteStrICmp(zLeft, "table_info")==0 ){ if( sqliteStrICmp(zLeft, "table_info")==0 ){
Table *pTab; Table *pTab;
Vdbe *v; Vdbe *v;

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.41 2001/10/18 12:34:47 drh Exp $ ** $Id: select.c,v 1.42 2001/10/19 16:44:57 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@ -994,5 +994,13 @@ int sqliteSelect(
generateSortTail(v, pEList->nExpr); generateSortTail(v, pEList->nExpr);
} }
pParse->nTab = base; pParse->nTab = base;
/* 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, pEList->nExpr, 0);
}
return 0; return 0;
} }

View File

@ -12,7 +12,7 @@
** This file contains code to implement the "sqlite" command line ** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases. ** utility for accessing SQLite databases.
** **
** $Id: shell.c,v 1.36 2001/10/06 16:33:03 drh Exp $ ** $Id: shell.c,v 1.37 2001/10/19 16:44:57 drh Exp $
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -244,6 +244,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
switch( p->mode ){ switch( p->mode ){
case MODE_Line: { case MODE_Line: {
int w = 5; int w = 5;
if( azArg==0 ) break;
for(i=0; i<nArg; i++){ for(i=0; i<nArg; i++){
int len = strlen(azCol[i]); int len = strlen(azCol[i]);
if( len>w ) w = len; if( len>w ) w = len;
@ -266,7 +267,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
if( w<=0 ){ if( w<=0 ){
w = strlen(azCol[i] ? azCol[i] : ""); w = strlen(azCol[i] ? azCol[i] : "");
if( w<10 ) w = 10; if( w<10 ) w = 10;
n = strlen(azArg[i] ? azArg[i] : ""); n = strlen(azArg && azArg[i] ? azArg[i] : "");
if( w<n ) w = n; if( w<n ) w = n;
} }
if( i<ArraySize(p->actualWidth) ){ if( i<ArraySize(p->actualWidth) ){
@ -290,6 +291,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
} }
} }
} }
if( azArg==0 ) break;
for(i=0; i<nArg; i++){ for(i=0; i<nArg; i++){
int w; int w;
if( i<ArraySize(p->actualWidth) ){ if( i<ArraySize(p->actualWidth) ){
@ -309,6 +311,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator); fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator);
} }
} }
if( azArg==0 ) break;
for(i=0; i<nArg; i++){ for(i=0; i<nArg; i++){
char *z = azArg[i]; char *z = azArg[i];
if( z==0 ) z = ""; if( z==0 ) z = "";
@ -342,6 +345,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
} }
fprintf(p->out,"</TR>\n"); fprintf(p->out,"</TR>\n");
} }
if( azArg==0 ) break;
fprintf(p->out,"<TR>"); fprintf(p->out,"<TR>");
for(i=0; i<nArg; i++){ for(i=0; i<nArg; i++){
fprintf(p->out,"<TD>"); fprintf(p->out,"<TD>");
@ -352,6 +356,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
break; break;
} }
case MODE_Insert: { case MODE_Insert: {
if( azArg==0 ) break;
fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable); fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
for(i=0; i<nArg; i++){ for(i=0; i<nArg; i++){
char *zSep = i>0 ? ",": ""; char *zSep = i>0 ? ",": "";
@ -365,6 +370,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
} }
} }
fprintf(p->out,");\n"); fprintf(p->out,");\n");
break;
} }
} }
return 0; return 0;

View File

@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** Internal interface definitions for SQLite.
** **
** @(#) $Id: sqliteInt.h,v 1.63 2001/10/18 12:34:47 drh Exp $ ** @(#) $Id: sqliteInt.h,v 1.64 2001/10/19 16:44:57 drh Exp $
*/ */
#include "sqlite.h" #include "sqlite.h"
#include "hash.h" #include "hash.h"
@ -166,6 +166,8 @@ struct sqlite {
#define SQLITE_CountRows 0x00000040 /* Count rows changed by INSERT, */ #define SQLITE_CountRows 0x00000040 /* Count rows changed by INSERT, */
/* DELETE, or UPDATE and return */ /* DELETE, or UPDATE and return */
/* the count using a callback. */ /* the count using a callback. */
#define SQLITE_NullCallback 0x00000080 /* Invoke the callback once if the */
/* result set is empty */
/* /*
** Current file format version ** Current file format version

View File

@ -47,7 +47,7 @@ static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
/* Make sure there is enough space in p->azResult to hold everything /* Make sure there is enough space in p->azResult to hold everything
** we need to remember from this invocation of the callback. ** we need to remember from this invocation of the callback.
*/ */
if( p->nRow==0 ){ if( p->nRow==0 && argv!=0 ){
p->nColumn = nCol; p->nColumn = nCol;
need = nCol*2; need = nCol*2;
}else{ }else{
@ -83,20 +83,22 @@ static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
/* Copy over the row data /* Copy over the row data
*/ */
for(i=0; i<nCol; i++){ if( argv!=0 ){
if( argv[i]==0 ){ for(i=0; i<nCol; i++){
z = 0; if( argv[i]==0 ){
}else{ z = 0;
z = malloc( strlen(argv[i])+1 ); }else{
if( z==0 ){ z = malloc( strlen(argv[i])+1 );
p->rc = SQLITE_NOMEM; if( z==0 ){
return 1; p->rc = SQLITE_NOMEM;
return 1;
}
strcpy(z, argv[i]);
} }
strcpy(z, argv[i]); p->azResult[p->nData++] = z;
} }
p->azResult[p->nData++] = z; p->nRow++;
} }
p->nRow++;
return 0; return 0;
} }

View File

@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** A TCL Interface to SQLite ** A TCL Interface to SQLite
** **
** $Id: tclsqlite.c,v 1.25 2001/10/18 12:34:47 drh Exp $ ** $Id: tclsqlite.c,v 1.26 2001/10/19 16:44:57 drh Exp $
*/ */
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
@ -72,42 +72,44 @@ static int DbEvalCallback(
#ifdef UTF_TRANSLATION_NEEDED #ifdef UTF_TRANSLATION_NEEDED
Tcl_DString dCol; Tcl_DString dCol;
#endif #endif
if( cbData->zArray[0] ){ if( azCol==0 || (cbData->once && cbData->zArray[0]) ){
if( cbData->once ){ Tcl_SetVar2(cbData->interp, cbData->zArray, "*", "", 0);
Tcl_SetVar2(cbData->interp, cbData->zArray, "*", "", 0); for(i=0; i<nCol; i++){
Tcl_SetVar2(cbData->interp, cbData->zArray, "*", azN[i],
TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
}
cbData->once = 0;
}
if( azCol!=0 ){
if( cbData->zArray[0] ){
for(i=0; i<nCol; i++){ for(i=0; i<nCol; i++){
Tcl_SetVar2(cbData->interp, cbData->zArray, "*", azN[i], char *z = azCol[i];
TCL_LIST_ELEMENT|TCL_APPEND_VALUE); if( z==0 ) z = "";
#ifdef UTF_TRANSLATION_NEEDED
Tcl_DStringInit(&dCol);
Tcl_ExternalToUtfDString(NULL, z, -1, &dCol);
Tcl_SetVar2(cbData->interp, cbData->zArray, azN[i],
Tcl_DStringValue(&dCol), 0);
Tcl_DStringFree(&dCol);
#else
Tcl_SetVar2(cbData->interp, cbData->zArray, azN[i], z, 0);
#endif
}
}else{
for(i=0; i<nCol; i++){
char *z = azCol[i];
if( z==0 ) z = "";
#ifdef UTF_TRANSLATION_NEEDED
Tcl_DStringInit(&dCol);
Tcl_ExternalToUtfDString(NULL, z, -1, &dCol);
Tcl_SetVar(cbData->interp, azN[i], Tcl_DStringValue(&dCol), 0);
Tcl_DStringFree(&dCol);
#else
Tcl_SetVar(cbData->interp, azN[i], z, 0);
#endif
} }
} }
for(i=0; i<nCol; i++){
char *z = azCol[i];
if( z==0 ) z = "";
#ifdef UTF_TRANSLATION_NEEDED
Tcl_DStringInit(&dCol);
Tcl_ExternalToUtfDString(NULL, z, -1, &dCol);
Tcl_SetVar2(cbData->interp, cbData->zArray, azN[i],
Tcl_DStringValue(&dCol), 0);
Tcl_DStringFree(&dCol);
#else
Tcl_SetVar2(cbData->interp, cbData->zArray, azN[i], z, 0);
#endif
}
}else{
for(i=0; i<nCol; i++){
char *z = azCol[i];
if( z==0 ) z = "";
#ifdef UTF_TRANSLATION_NEEDED
Tcl_DStringInit(&dCol);
Tcl_ExternalToUtfDString(NULL, z, -1, &dCol);
Tcl_SetVar(cbData->interp, azN[i], Tcl_DStringValue(&dCol), 0);
Tcl_DStringFree(&dCol);
#else
Tcl_SetVar(cbData->interp, azN[i], z, 0);
#endif
}
} }
cbData->once = 0;
rc = Tcl_EvalObj(cbData->interp, cbData->pCode); rc = Tcl_EvalObj(cbData->interp, cbData->pCode);
if( rc==TCL_CONTINUE ) rc = TCL_OK; if( rc==TCL_CONTINUE ) rc = TCL_OK;
cbData->tcl_rc = rc; cbData->tcl_rc = rc;
@ -128,6 +130,7 @@ static int DbEvalCallback2(
){ ){
Tcl_Obj *pList = (Tcl_Obj*)clientData; Tcl_Obj *pList = (Tcl_Obj*)clientData;
int i; int i;
if( azCol==0 ) return 0;
for(i=0; i<nCol; i++){ for(i=0; i<nCol; i++){
Tcl_Obj *pElem; Tcl_Obj *pElem;
if( azCol[i] && *azCol[i] ){ if( azCol[i] && *azCol[i] ){

View File

@ -15,7 +15,7 @@
** individual tokens and sends those tokens one-by-one over to the ** individual tokens and sends those tokens one-by-one over to the
** parser for analysis. ** parser for analysis.
** **
** $Id: tokenize.c,v 1.28 2001/10/18 12:34:48 drh Exp $ ** $Id: tokenize.c,v 1.29 2001/10/19 16:44:57 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "os.h" #include "os.h"
@ -331,7 +331,7 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
break; break;
} }
for(i=1; isIdChar[z[i]]; i++){} for(i=1; isIdChar[z[i]]; i++){}
*tokenType = sqliteKeywordCode(z, i); *tokenType = sqliteKeywordCode((char*)z, i);
return i; return i;
} }
} }

View File

@ -30,7 +30,7 @@
** But other routines are also provided to help in building up ** But other routines are also provided to help in building up
** a program instruction by instruction. ** a program instruction by instruction.
** **
** $Id: vdbe.c,v 1.86 2001/10/18 12:34:48 drh Exp $ ** $Id: vdbe.c,v 1.87 2001/10/19 16:44:57 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@ -202,6 +202,7 @@ struct Vdbe {
int nSet; /* Number of sets allocated */ int nSet; /* Number of sets allocated */
Set *aSet; /* An array of sets */ Set *aSet; /* An array of sets */
int nFetch; /* Number of OP_Fetch instructions executed */ int nFetch; /* Number of OP_Fetch instructions executed */
int nCallback; /* Number of callbacks invoked so far */
}; };
/* /*
@ -811,17 +812,17 @@ static char *zOpName[] = { 0,
"AggGet", "SetInsert", "SetFound", "SetNotFound", "AggGet", "SetInsert", "SetFound", "SetNotFound",
"SetClear", "MakeRecord", "MakeKey", "MakeIdxKey", "SetClear", "MakeRecord", "MakeKey", "MakeIdxKey",
"Goto", "If", "Halt", "ColumnCount", "Goto", "If", "Halt", "ColumnCount",
"ColumnName", "Callback", "Integer", "String", "ColumnName", "Callback", "NullCallback", "Integer",
"Null", "Pop", "Dup", "Pull", "String", "Null", "Pop", "Dup",
"Add", "AddImm", "Subtract", "Multiply", "Pull", "Add", "AddImm", "Subtract",
"Divide", "Remainder", "BitAnd", "BitOr", "Multiply", "Divide", "Remainder", "BitAnd",
"BitNot", "ShiftLeft", "ShiftRight", "AbsValue", "BitOr", "BitNot", "ShiftLeft", "ShiftRight",
"Precision", "Min", "Max", "Like", "AbsValue", "Precision", "Min", "Max",
"Glob", "Eq", "Ne", "Lt", "Like", "Glob", "Eq", "Ne",
"Le", "Gt", "Ge", "IsNull", "Lt", "Le", "Gt", "Ge",
"NotNull", "Negative", "And", "Or", "IsNull", "NotNull", "Negative", "And",
"Not", "Concat", "Noop", "Strlen", "Or", "Not", "Concat", "Noop",
"Substr", "Strlen", "Substr",
}; };
/* /*
@ -1194,6 +1195,7 @@ case OP_ColumnCount: {
p->azColName = sqliteRealloc(p->azColName, (pOp->p1+1)*sizeof(char*)); p->azColName = sqliteRealloc(p->azColName, (pOp->p1+1)*sizeof(char*));
if( p->azColName==0 ) goto no_mem; if( p->azColName==0 ) goto no_mem;
p->azColName[pOp->p1] = 0; p->azColName[pOp->p1] = 0;
p->nCallback = 0;
break; break;
} }
@ -1207,6 +1209,7 @@ case OP_ColumnCount: {
*/ */
case OP_ColumnName: { case OP_ColumnName: {
p->azColName[pOp->p1] = pOp->p3 ? pOp->p3 : ""; p->azColName[pOp->p1] = pOp->p3 ? pOp->p3 : "";
p->nCallback = 0;
break; break;
} }
@ -1231,11 +1234,38 @@ case OP_Callback: {
if( xCallback(pArg, pOp->p1, &zStack[i], p->azColName)!=0 ){ if( xCallback(pArg, pOp->p1, &zStack[i], p->azColName)!=0 ){
rc = SQLITE_ABORT; rc = SQLITE_ABORT;
} }
p->nCallback++;
} }
PopStack(p, pOp->p1); PopStack(p, pOp->p1);
break; break;
} }
/* Opcode: NullCallback P1 * *
**
** Invoke the callback function once with the 2nd argument (the
** number of columns) equal to P1 and with the 4th argument (the
** names of the columns) set according to prior OP_ColumnName and
** OP_ColumnCount instructions. This is all like the regular
** OP_Callback or OP_SortCallback opcodes. But the 3rd argument
** which normally contains a pointer to an array of pointers to
** data is NULL.
**
** The callback is only invoked if there have been no prior calls
** to OP_Callback or OP_SortCallback.
**
** This opcode is used to report the number and names of columns
** in cases where the result set is empty.
*/
case OP_NullCallback: {
if( xCallback!=0 && p->nCallback==0 ){
if( xCallback(pArg, pOp->p1, 0, p->azColName)!=0 ){
rc = SQLITE_ABORT;
}
p->nCallback++;
}
break;
}
/* Opcode: Concat P1 P2 P3 /* Opcode: Concat P1 P2 P3
** **
** Look at the first P1 elements of the stack. Append them all ** Look at the first P1 elements of the stack. Append them all
@ -3376,6 +3406,7 @@ case OP_SortCallback: {
if( xCallback(pArg, pOp->p1, (char**)zStack[i], p->azColName) ){ if( xCallback(pArg, pOp->p1, (char**)zStack[i], p->azColName) ){
rc = SQLITE_ABORT; rc = SQLITE_ABORT;
} }
p->nCallback++;
} }
POPSTACK; POPSTACK;
break; break;

View File

@ -15,7 +15,7 @@
** or VDBE. The VDBE implements an abstract machine that runs a ** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database. ** simple program to access and modify the underlying database.
** **
** $Id: vdbe.h,v 1.29 2001/10/13 02:59:09 drh Exp $ ** $Id: vdbe.h,v 1.30 2001/10/19 16:44:57 drh Exp $
*/ */
#ifndef _SQLITE_VDBE_H_ #ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_
@ -155,50 +155,51 @@ typedef struct VdbeOp VdbeOp;
#define OP_ColumnCount 72 #define OP_ColumnCount 72
#define OP_ColumnName 73 #define OP_ColumnName 73
#define OP_Callback 74 #define OP_Callback 74
#define OP_NullCallback 75
#define OP_Integer 75 #define OP_Integer 76
#define OP_String 76 #define OP_String 77
#define OP_Null 77 #define OP_Null 78
#define OP_Pop 78 #define OP_Pop 79
#define OP_Dup 79 #define OP_Dup 80
#define OP_Pull 80 #define OP_Pull 81
#define OP_Add 81 #define OP_Add 82
#define OP_AddImm 82 #define OP_AddImm 83
#define OP_Subtract 83 #define OP_Subtract 84
#define OP_Multiply 84 #define OP_Multiply 85
#define OP_Divide 85 #define OP_Divide 86
#define OP_Remainder 86 #define OP_Remainder 87
#define OP_BitAnd 87 #define OP_BitAnd 88
#define OP_BitOr 88 #define OP_BitOr 89
#define OP_BitNot 89 #define OP_BitNot 90
#define OP_ShiftLeft 90 #define OP_ShiftLeft 91
#define OP_ShiftRight 91 #define OP_ShiftRight 92
#define OP_AbsValue 92 #define OP_AbsValue 93
#define OP_Precision 93 #define OP_Precision 94
#define OP_Min 94 #define OP_Min 95
#define OP_Max 95 #define OP_Max 96
#define OP_Like 96 #define OP_Like 97
#define OP_Glob 97 #define OP_Glob 98
#define OP_Eq 98 #define OP_Eq 99
#define OP_Ne 99 #define OP_Ne 100
#define OP_Lt 100 #define OP_Lt 101
#define OP_Le 101 #define OP_Le 102
#define OP_Gt 102 #define OP_Gt 103
#define OP_Ge 103 #define OP_Ge 104
#define OP_IsNull 104 #define OP_IsNull 105
#define OP_NotNull 105 #define OP_NotNull 106
#define OP_Negative 106 #define OP_Negative 107
#define OP_And 107 #define OP_And 108
#define OP_Or 108 #define OP_Or 109
#define OP_Not 109 #define OP_Not 110
#define OP_Concat 110 #define OP_Concat 111
#define OP_Noop 111 #define OP_Noop 112
#define OP_Strlen 112 #define OP_Strlen 113
#define OP_Substr 113 #define OP_Substr 114
#define OP_MAX 113 #define OP_MAX 114
/* /*
** Prototypes for the VDBE interface. See comments on the implementation ** Prototypes for the VDBE interface. See comments on the implementation

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 SELECT statement. # focus of this file is testing the SELECT statement.
# #
# $Id: select1.test,v 1.13 2001/10/18 12:34:48 drh Exp $ # $Id: select1.test,v 1.14 2001/10/19 16:44:58 drh Exp $
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@ -414,4 +414,36 @@ do_test select1-8.5 {
} }
} {1 -3 1 -3} } {1 -3 1 -3}
# Check the behavior when the result set is empty
#
do_test select1-9.1 {
catch {unset r}
set r(*) {}
db eval {SELECT * FROM test1 WHERE f1<0} r {}
set r(*)
} {}
do_test select1-9.2 {
execsql {PRAGMA empty_result_callbacks=on}
set r(*) {}
db eval {SELECT * FROM test1 WHERE f1<0} r {}
set r(*)
} {f1 f2}
do_test select1-9.3 {
set r(*) {}
db eval {SELECT * FROM test1 WHERE f1<(select count(*) from test2)} r {}
set r(*)
} {f1 f2}
do_test select1-9.4 {
set r(*) {}
db eval {SELECT * FROM test1 ORDER BY f1} r {}
set r(*)
} {f1 f2}
do_test select1-9.5 {
set r(*) {}
db eval {SELECT * FROM test1 WHERE f1<0 ORDER BY f1} r {}
set r(*)
} {f1 f2}
unset r
finish_test finish_test

View File

@ -1,7 +1,7 @@
# #
# Run this Tcl script to generate the sqlite.html file. # Run this Tcl script to generate the sqlite.html file.
# #
set rcsid {$Id: c_interface.tcl,v 1.17 2001/10/12 17:30:05 drh Exp $} set rcsid {$Id: c_interface.tcl,v 1.18 2001/10/19 16:44:58 drh Exp $}
puts {<html> puts {<html>
<head> <head>
@ -20,7 +20,7 @@ puts {
a C or C++ program. This document gives an overview of the C/C++ a C or C++ program. This document gives an overview of the C/C++
programming interface.</p> programming interface.</p>
<h2>The API</h2> <h2>The Core API</h2>
<p>The interface to the SQLite library consists of three core functions, <p>The interface to the SQLite library consists of three core functions,
one opaque data structure, and some constants used as return values. one opaque data structure, and some constants used as return values.
@ -28,6 +28,7 @@ The core interface is as follows:</p>
<blockquote><pre> <blockquote><pre>
typedef struct sqlite sqlite; typedef struct sqlite sqlite;
#define SQLITE_OK 0 /* Successful result */
sqlite *sqlite_open(const char *dbname, int mode, char **errmsg); sqlite *sqlite_open(const char *dbname, int mode, char **errmsg);
@ -40,101 +41,14 @@ int sqlite_exec(
void*, void*,
char **errmsg char **errmsg
); );
#define SQLITE_OK 0 /* Successful result */
#define SQLITE_ERROR 1 /* SQL error or missing database */
#define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */
#define SQLITE_PERM 3 /* Access permission denied */
#define SQLITE_ABORT 4 /* Callback routine requested an abort */
#define SQLITE_BUSY 5 /* The database file is locked */
#define SQLITE_LOCKED 6 /* A table in the database is locked */
#define SQLITE_NOMEM 7 /* A malloc() failed */
#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */
#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
#define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */
#define SQLITE_FULL 13 /* Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
#define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* Too much data for one row of a table */
#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */
</pre></blockquote> </pre></blockquote>
<p>Only the three core routines shown above are required to use <p>
SQLite. But there are many other functions that provide The above is all you really need to know in order to use SQLite
useful interfaces. These extended routines are as follows: in your C or C++ programs. There are other convenience functions
available (and described below) but we will begin by describing
the core functions shown above.
</p> </p>
<blockquote><pre>
int sqlite_get_table(
sqlite*,
char *sql,
char ***result,
int *nrow,
int *ncolumn,
char **errmsg
);
void sqlite_free_table(char**);
void sqlite_interrupt(sqlite*);
int sqlite_complete(const char *sql);
void sqlite_busy_handler(sqlite*, int (*)(void*,const char*,int), void*);
void sqlite_busy_timeout(sqlite*, int ms);
const char sqlite_version[];
const char sqlite_encoding[];
int sqlite_exec_printf(
sqlite*,
char *sql,
int (*)(void*,int,char**,char**),
void*,
char **errmsg,
...
);
int sqlite_exec_vprintf(
sqlite*,
char *sql,
int (*)(void*,int,char**,char**),
void*,
char **errmsg,
va_list
);
int sqlite_get_table_printf(
sqlite*,
char *sql,
char ***result,
int *nrow,
int *ncolumn,
char **errmsg,
...
);
int sqlite_get_table_vprintf(
sqlite*,
char *sql,
char ***result,
int *nrow,
int *ncolumn,
char **errmsg,
va_list
);
</pre></blockquote>
<p>All of the above definitions are included in the "sqlite.h"
header file that comes in the source tree.</p>
<h2>Opening a database</h2> <h2>Opening a database</h2>
<p>Use the <b>sqlite_open()</b> function to open an existing SQLite <p>Use the <b>sqlite_open()</b> function to open an existing SQLite
@ -225,13 +139,57 @@ argv[i] == 0
</pre></blockquote> </pre></blockquote>
<p>The names of the columns are contained in the fourth argument.</p> <p>The names of the columns are contained in the fourth argument.</p>
<p>If the EMPTY_RESULT_CALLBACKS pragma is set to ON and the result of
a query is an empty set, then the callback is invoked once with the
third parameter (argv) set to 0. In other words
<blockquote><pre>
argv == 0
</pre></blockquote>
The second parameter (argc)
and the fourth parameter (columnNames) are still valid
and can be used to determine the number and names of the result
columns if there had been a result.
The default behavior is not to invoke the callback at all if the
result set is empty.</p>
<p>The callback function should normally return 0. If the callback <p>The callback function should normally return 0. If the callback
function returns non-zero, the query is immediately aborted and function returns non-zero, the query is immediately aborted and
<b>sqlite_exec()</b> will return SQLITE_ABORT.</p> <b>sqlite_exec()</b> will return SQLITE_ABORT.</p>
<p>The <b>sqlite_exec()</b> function returns an integer to indicate <h2>Error Codes</h2>
success or failure of the operation. The following are possible
return values:</p> <p>
The <b>sqlite_exec()</b> function normally returns SQLITE_OK. But
if something goes wrong it can return a different value to indicate
the type of error. Here is a complete list of the return codes:
</p>
<blockquote><pre>
#define SQLITE_OK 0 /* Successful result */
#define SQLITE_ERROR 1 /* SQL error or missing database */
#define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */
#define SQLITE_PERM 3 /* Access permission denied */
#define SQLITE_ABORT 4 /* Callback routine requested an abort */
#define SQLITE_BUSY 5 /* The database file is locked */
#define SQLITE_LOCKED 6 /* A table in the database is locked */
#define SQLITE_NOMEM 7 /* A malloc() failed */
#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */
#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
#define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */
#define SQLITE_FULL 13 /* Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
#define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* Too much data for one row of a table */
#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */
</pre></blockquote>
<p>
The meanings of these various return values are as follows:
</p>
<blockquote> <blockquote>
<dl> <dl>
@ -332,6 +290,80 @@ a database constraint.
</dl> </dl>
</blockquote> </blockquote>
<h2>The Extended API</h2>
<p>Only the three core routines shown above are required to use
SQLite. But there are many other functions that provide
useful interfaces. These extended routines are as follows:
</p>
<blockquote><pre>
int sqlite_get_table(
sqlite*,
char *sql,
char ***result,
int *nrow,
int *ncolumn,
char **errmsg
);
void sqlite_free_table(char**);
void sqlite_interrupt(sqlite*);
int sqlite_complete(const char *sql);
void sqlite_busy_handler(sqlite*, int (*)(void*,const char*,int), void*);
void sqlite_busy_timeout(sqlite*, int ms);
const char sqlite_version[];
const char sqlite_encoding[];
int sqlite_exec_printf(
sqlite*,
char *sql,
int (*)(void*,int,char**,char**),
void*,
char **errmsg,
...
);
int sqlite_exec_vprintf(
sqlite*,
char *sql,
int (*)(void*,int,char**,char**),
void*,
char **errmsg,
va_list
);
int sqlite_get_table_printf(
sqlite*,
char *sql,
char ***result,
int *nrow,
int *ncolumn,
char **errmsg,
...
);
int sqlite_get_table_vprintf(
sqlite*,
char *sql,
char ***result,
int *nrow,
int *ncolumn,
char **errmsg,
va_list
);
</pre></blockquote>
<p>All of the above definitions are included in the "sqlite.h"
header file that comes in the source tree.</p>
<h2>Querying without using a callback function</h2> <h2>Querying without using a callback function</h2>
<p>The <b>sqlite_get_table()</b> function is a wrapper around <p>The <b>sqlite_get_table()</b> function is a wrapper around
@ -375,10 +407,46 @@ result[8] = "zadok"
<p>Notice that the "host" value for the "dummy" record is NULL so <p>Notice that the "host" value for the "dummy" record is NULL so
the result[] array contains a NULL pointer at that slot.</p> the result[] array contains a NULL pointer at that slot.</p>
<p>If the result set of a query is empty, then by default
<b>sqlite_get_table()</b> will set nrow to 0 and leave its
result parameter is set to NULL. But if the EMPTY_RESULT_CALLBACKS
pragma is ON then the result parameter is initialized to the names
of the columns only. For example, consider this query which has
an empty result set:</p>
<blockquote>
SELECT employee_name, login, host FROM users WHERE employee_name IS NULL;
</blockquote>
<p>
The default behavior gives this results:
</p>
<blockquote>
nrow = 0<br>
ncolumn = 0<br>
result = 0<br>
</blockquote>
<p>
But if the EMPTY_RESULT_CALLBACKS pragma is ON, then the following
is returned:
</p>
<blockquote>
nrow = 0<br>
ncolumn = 3<br>
result[0] = "employee_name"<br>
result[1] = "login"<br>
result[2] = "host"<br>
</blockquote>
<p>Memory to hold the information returned by <b>sqlite_get_table()</b> <p>Memory to hold the information returned by <b>sqlite_get_table()</b>
is obtained from malloc(). But the calling function should not try is obtained from malloc(). But the calling function should not try
to free this information directly. Instead, pass the complete table to free this information directly. Instead, pass the complete table
to <b>sqlite_free_table()</b> when the table is no longer needed.</p> to <b>sqlite_free_table()</b> when the table is no longer needed.
It is safe to call <b>sqlite_free_table()</b> will a NULL pointer such
as would be returned if the result set is empty.</p>
<p>The <b>sqlite_get_table()</b> routine returns the same integer <p>The <b>sqlite_get_table()</b> routine returns the same integer
result code as <b>sqlite_exec()</b>.</p> result code as <b>sqlite_exec()</b>.</p>

View File

@ -17,7 +17,8 @@ proc chng {date desc} {
puts "<DD><P><UL>$desc</UL></P></DD>" puts "<DD><P><UL>$desc</UL></P></DD>"
} }
chng {2001 Oct ?? (2.0.6)} { chng {2001 Oct 19 (2.0.6)} {
<li>Added the EMPTY_RESULT_CALLBACKS pragma</li>
<li>Support for UTF-8 and ISO8859 characters in column and table names.</li> <li>Support for UTF-8 and ISO8859 characters in column and table names.</li>
<li>Bug fix: Compute correct table names with the FULL_COLUMN_NAMES pragma <li>Bug fix: Compute correct table names with the FULL_COLUMN_NAMES pragma
is turned on.</li> is turned on.</li>

View File

@ -1,7 +1,7 @@
# #
# Run this Tcl script to generate the sqlite.html file. # Run this Tcl script to generate the sqlite.html file.
# #
set rcsid {$Id: lang.tcl,v 1.13 2001/10/15 00:44:36 drh Exp $} set rcsid {$Id: lang.tcl,v 1.14 2001/10/19 16:44:58 drh Exp $}
puts {<html> puts {<html>
<head> <head>
@ -637,6 +637,16 @@ with caution.</p>
be invoked once for each DELETE, INSERT, or UPDATE operation. The be invoked once for each DELETE, INSERT, or UPDATE operation. The
argument is the number of rows that were changed.</p> argument is the number of rows that were changed.</p>
<li><p><b>PRAGMA empty_result_callbacks = ON;
<br>PRAGMA empty_result_callbacks = OFF;</b></p>
<p>When on, the EMPTY_RESULT_CALLBACKS pragma causes the callback
function to be invoked once for each query that has an empty result
set. The third "<b>argv</b>" parameter to the callback is set to NULL
because there is no data to report. But the second "<b>argc</b>" and
fourth "<b>columnNames</b>" parameters are valid and can be used to
determine the number and names of the columns that would have been in
the result set had the set not been empty.</p>
<li><p><b>PRAGMA full_column_names = ON; <li><p><b>PRAGMA full_column_names = ON;
<br>PRAGMA full_column_names = OFF;</b></p> <br>PRAGMA full_column_names = OFF;</b></p>
<p>The column names reported in an SQLite callback are normally just <p>The column names reported in an SQLite callback are normally just