diff --git a/Makefile.template b/Makefile.template index f76e22c786..14a30b63d1 100644 --- a/Makefile.template +++ b/Makefile.template @@ -20,6 +20,7 @@ TOP = ../sqlite # will run on the platform that is doing the build. # BCC = gcc -g -O2 +#BCC = /opt/ancic/bin/c89 -0 #### If the target operating system supports the "usleep()" system # call, then define the HAVE_USLEEP macro for all C modules. @@ -58,6 +59,7 @@ EXE = TCC = gcc -O6 #TCC = gcc -g -O0 -Wall #TCC = /opt/mingw/bin/i386-mingw32-gcc -O6 +#TCC = /opt/ansic/bin/c89 -O +z -Wl,-a,archive #### Tools used to build a static library. # @@ -72,12 +74,14 @@ RANLIB = ranlib #TCL_FLAGS = -DSTATIC_BUILD=1 TCL_FLAGS = -I/home/drh/tcltk/8.4linux #TCL_FLAGS = -I/home/drh/tcltk/8.4win -DSTATIC_BUILD=1 +#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux #### Linker options needed to link against the TCL library. # #LIBTCL = -ltcl -lm -ldl LIBTCL = /home/drh/tcltk/8.4linux/libtcl8.4g.a -lm -ldl #LIBTCL = /home/drh/tcltk/8.4win/libtcl84s.a -lmsvcrt +#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc #### Compiler options needed for programs that use the readline() library. # diff --git a/manifest b/manifest index 0f1a7e3001..ba3a348a84 100644 --- a/manifest +++ b/manifest @@ -1,7 +1,7 @@ -C Version\s2.0.1\s(CVS\s469) -D 2001-10-02T13:05:00 +C Adding\stable\scolumn\squery\scapability\sto\ssupport\sODBC.\s(CVS\s278) +D 2001-10-06T16:33:02 F Makefile.in 98d4627cb364537e4c3a29ee806171f3abf5211a -F Makefile.template 7179523fdf3d6e7933ec843e2352dcfc9785c700 +F Makefile.template 1e54087c0390c4ce0bb5be43e14ba028283751e6 F README 93d2977cc5c6595c448de16bdefc312b9d401533 F VERSION 1fb7be12efaa1608dc63e784e33082ae0ac7919b F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d @@ -19,37 +19,37 @@ F libtool c56e618713c9510a103bda6b95f3ea3900dcacd6 F ltmain.sh e9ed72eb1d690f447c13945eaf69e28af531eda1 F publish.sh 502b907fa9e0214309406fa5f520b3d3c14f9c1d F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6 -F src/btree.c a001f151a7dd32b7afb328fd6f8e445c57d8a74c +F src/btree.c 7e9c33a714ed1630562f89ad19847f5f28bd6d4d F src/btree.h 57d653ef5137b91f2a068aaf71a2905468dd2cb7 -F src/build.c 64a7325c1471087ada81588d6ace6d294b28cd1d +F src/build.c 7cbac6c3a5d35e56f8d57bb6b07fba5e8a41c806 F src/delete.c 81002d889aae874decf507627207c5d1b3599dc2 -F src/expr.c 343a515a4abaf60e9e26c7412aa8c43fd3eae97d +F src/expr.c 2f68829d983ec3f92eeb8b89ce4b9e5704169a80 F src/hash.c bf36fb4cba114015123b0050f137d2c4553778a1 F src/hash.h 5f6e7c04c46ed015ab4e01797c2049b4af5b006d -F src/insert.c 0552c2a4b5fd359e9ed5d1e314d5e89093802c8e -F src/main.c 87cabd64c99af66ba95f06a7dcd870eec65d89af +F src/insert.c 01dd6ddee901a8a55c9b05a62b30023ec43de9ce +F src/main.c 6db4ba7ed8f1c1866b04eab6d0f9b46455e152c8 F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c F src/os.c 45376582c41dc8829330816d56b8e9e6cd1b7972 F src/os.h 0f478e2fef5ec1612f94b59b163d4807d4c77d6d -F src/pager.c 0fe02b63a89d8eebb42ad30529d0c7cc918ecb94 +F src/pager.c 592c16b06ad07c715240e382028e29b0e83378be F src/pager.h a0d4c5ae271914aa07b62aee0707997d6932b6ca -F src/parse.y 5ead6fe1e7c5f13220030f41ce68af155b54c6ab +F src/parse.y fcd3452640cf5ae2304ce430668112e0da07745a F src/printf.c b1e22a47be8cdf707815647239991e08e8cb69f9 F src/random.c 708a23f69f40d6f2ae5ce1a04e6a4055d4a6ecec -F src/select.c 7d90a6464906419fde96c0707a4cf4f3280db318 -F src/shell.c cd2ae9f22dec5e4e5411e6253abfc3e240b4e030 +F src/select.c 0ef8ca1b7de2467fe082bcb35a5ab3b5be56153c +F src/shell.c cb8c41f1b2173efd212dab3f35f1fc6bf32ead76 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e -F src/sqlite.h.in 08151912b382ded315b5c8fc6288d9d7a9332aa4 -F src/sqliteInt.h 3ead85324704b79b2ae6799d6af3e5fd710756d9 +F src/sqlite.h.in b95c161abf1d58bceb05290fa3f657d8f388fc11 +F src/sqliteInt.h 78b1890c4b61d35f33941cf9a2aae366b32b3dd3 F src/table.c abd0adbe0fee39d995287b3bcccd908d174dfcac F src/tclsqlite.c 765599686c19ed777ac379928d732c8bfc63ebac F src/test1.c e4b31f62ea71963cbae44338acf477a04fc8fc49 F src/test2.c 0168b39225b768cfdadd534406f9dec58c27879e F src/test3.c 4a0d7b882fdae731dbb759f512ad867122452f96 -F src/tokenize.c 2ab07b85fde38d8fa2b4e73417b93e94f9cf8f5f +F src/tokenize.c 8a2aa0443f8bb1a02d021604377e2783e8e45f42 F src/update.c 0449af173b5f2f0b26e2f0e4545ee0e0429763cb F src/util.c 4da3be37d0fd3c640d2d3033503768afdc8e5387 -F src/vdbe.c 173892798e1698605fafb24d29e26e3a5644ddf5 +F src/vdbe.c 5c865988f8b33dcb8c5282f24bde404ab5d96899 F src/vdbe.h c543a58f52fb654c90dd31d0d0c31309f4d838de F src/where.c cce952b6a2459ac2296e3432876a4252d2fe3b87 F test/all.test a2320eb40b462f25bd3e33115b1cabf3791450dd @@ -73,7 +73,7 @@ F test/printf.test 3cb415073754cb8ff076f26173143c3cd293a9da F test/quick.test b6ec50f808efc06595fd324bf4f3fabadb9c7e9c F test/quote.test 286db944717afa9a9bf829dd85e59185c65d5435 F test/rowid.test 427bfbbe9684fe7a2f851aa05badaae6d4972ce8 -F test/select1.test e0c3ff05f44233cde7918cb22ba4be05ea7a08ec +F test/select1.test b59e8c713277d7545f5b6e782e6223e51fea45a5 F test/select2.test f91c903e2bab0e9d45274855a981eebf846d5e32 F test/select3.test 5e1fe8e5a4e63fb2827ab3b89527e0fd4ae35259 F test/select4.test 29a2ffb187f3d8b6ca42a0a6b619e9cabe12e228 @@ -100,10 +100,11 @@ F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4 F www/arch.tcl 03b521d252575f93b9c52f7c8b0007011512fcfb F www/c_interface.tcl 8e8d9e66e8467c5751116c3427296bde77f474a6 -F www/changes.tcl c02f83b3fb83cc6450000f66c4f751306e0fee14 +F www/changes.tcl 8c2ecc905283cfe3221722d8e8bcb660af2297b2 F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e +F www/download.tcl 3e51c9ff1326b0a182846134987301310dff7d60 F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c -F www/index.tcl 998f61fe69be9f1b04e403c8efb75bca92710e83 +F www/index.tcl 68c815d64b35b2dcc4d4f6845827df71c6869f9f F www/lang.tcl 33a74d727615ccbee8be7c8efd5876ce008c4b0e F www/mingw.tcl fc5f4ba9d336b6e8c97347cc6496d6162461ef60 F www/opcode.tcl 4365ad9798872491dbd7d3071510ebe461785ac3 @@ -111,7 +112,7 @@ F www/speed.tcl ab7d6d3bc898472bd94320a5d3c63de928d4804b F www/sqlite.tcl 6a21242a272e9c0939a04419a51c3d50cae33e3e F www/tclsqlite.tcl 13d50723f583888fc80ae1a38247c0ab415066fa F www/vdbe.tcl bb7d620995f0a987293e9d4fb6185a3b077e9b44 -P 4b7710e2daadffb716bd88f3a213f94ffbb750ef -R 749797abfff4d2facdf1fb82f0e97dc2 +P e4980849403a8d7bd63753c9b7f275519bd7df4f +R 7502c066a19df2a451414aa8e23b0cac U drh -Z 53199e04c7e509c37ae5c48d753ad83b +Z 47fec5ca7cd29a261f31f63e809cee33 diff --git a/manifest.uuid b/manifest.uuid index d0d348ac81..586cbaeb4e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e4980849403a8d7bd63753c9b7f275519bd7df4f \ No newline at end of file +b63b3f3684a3d584ef99f54cde76b6c483bbfef7 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 471cd0c743..761ccac948 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.32 2001/10/02 13:01:49 drh Exp $ +** $Id: btree.c,v 1.33 2001/10/06 16:33:02 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -595,6 +595,10 @@ static void pageDestructor(void *pData){ ** Actually, this routine just sets up the internal data structures ** for accessing the database. We do not open the database file ** until the first page is loaded. +** +** zFilename is the name of the database file. If zFilename is NULL +** a new database with a random name is created. The database will be +** destroyed when sqliteBtreeClose() is called. */ int sqliteBtreeOpen( const char *zFilename, /* Name of the file containing the BTree database */ diff --git a/src/build.c b/src/build.c index 70f0c7e2d3..e8d213b43b 100644 --- a/src/build.c +++ b/src/build.c @@ -25,7 +25,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.43 2001/09/27 15:11:54 drh Exp $ +** $Id: build.c,v 1.44 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" #include @@ -203,6 +203,7 @@ void sqliteDeleteTable(sqlite *db, Table *pTable){ for(i=0; inCol; i++){ sqliteFree(pTable->aCol[i].zName); sqliteFree(pTable->aCol[i].zDflt); + sqliteFree(pTable->aCol[i].zType); } for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; @@ -335,7 +336,7 @@ char *sqliteTableNameFromToken(Token *pName){ ** after seeing tokens "CREATE" and "TABLE" and the table name. The ** pStart token is the CREATE and pName is the table name. ** -** The new table is constructed in files of the pParse structure. As +** The new table is constructed in fields of the pParse structure. As ** more of the CREATE TABLE statement is parsed, additional action ** routines are called to build up more of the table. */ @@ -406,6 +407,48 @@ void sqliteAddColumn(Parse *pParse, Token *pName){ sqliteDequote(*pz); } +/* +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. A "NOT NULL" constraint has +** been seen on a column. This routine sets the notNull flag on +** the column currently under construction. +*/ +void sqliteAddNotNull(Parse *pParse){ + Table *p; + int i; + if( (p = pParse->pNewTable)==0 ) return; + i = p->nCol-1; + p->aCol[i].notNull = 1; +} + +/* +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. The pFirst token is the first +** token in the sequence of tokens that describe the type of the +** column currently under construction. pLast is the last token +** in the sequence. Use this information to construct a string +** that contains the typename of the column and store that string +** in zType. +*/ +void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){ + Table *p; + int i, j; + int n; + char *z, **pz; + if( (p = pParse->pNewTable)==0 ) return; + i = p->nCol-1; + pz = &p->aCol[i].zType; + n = pLast->n + ((int)pLast->z) - (int)pFirst->z; + sqliteSetNString(pz, pFirst->z, n, 0); + z = *pz; + for(i=j=0; z[i]; i++){ + int c = z[i]; + if( isspace(c) ) continue; + z[j++] = c; + } + z[j] = 0; +} + /* ** The given token is the default value for the last column added to ** the table currently under construction. If "minusFlag" is true, it @@ -486,9 +529,7 @@ void sqliteEndTable(Parse *pParse, Token *pEnd){ ** "sqlite_master" table on the disk. So do not write to the disk ** again. Extract the root page number for the table from the ** pParse->newTnum field. (The page number should have been put - ** there by the sqliteOpenCb routine.) If the table has a primary - ** key, the root page of the index associated with the primary key - ** should be in pParse->newKnum. + ** there by the sqliteOpenCb routine.) */ if( pParse->initFlag ){ p->tnum = pParse->newTnum; @@ -618,11 +659,12 @@ void sqliteDropTable(Parse *pParse, Token *pName){ ** and pTable is the name of the table that is to be indexed. Both will ** be NULL for a primary key or an index that is created to satisfy a ** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable -** as the table to be indexed. +** as the table to be indexed. pParse->pNewTable is a table that is +** currently being constructed by a CREATE TABLE statement. ** -** pList is a list of columns to be indexed. pList will be NULL if the -** most recently added column of the table is the primary key or has -** the UNIQUE constraint. +** pList is a list of columns to be indexed. pList will be NULL if this +** is a primary key or unique-constraint on the most recent column added +** to the table currently under construction. */ void sqliteCreateIndex( Parse *pParse, /* All information about this parse */ @@ -763,10 +805,9 @@ void sqliteCreateIndex( ** we don't want to recreate it. ** ** If pTable==0 it means this index is generated as a primary key - ** or UNIQUE constraint of a CREATE TABLE statement. The code generator - ** for CREATE TABLE will have already opened cursor 0 for writing to - ** the sqlite_master table and will take care of closing that cursor - ** for us in the end. So those steps are skipped when pTable==0 + ** or UNIQUE constraint of a CREATE TABLE statement. Since the table + ** has just been created, it contains no data and the index initialization + ** step can be skipped. */ else if( pParse->initFlag==0 ){ int n; @@ -796,12 +837,10 @@ void sqliteCreateIndex( sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0); sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0, 0, 0); } + addr = sqliteVdbeAddOp(v, OP_String, 0, 0, 0, 0); if( pStart && pEnd ){ n = (int)pEnd->z - (int)pStart->z + 1; - addr = sqliteVdbeAddOp(v, OP_String, 0, 0, "", 0); sqliteVdbeChangeP3(v, addr, pStart->z, n); - }else{ - sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0); } sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0, 0, 0); sqliteVdbeAddOp(v, OP_Put, 0, 0, 0, 0); @@ -1262,6 +1301,68 @@ void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ } }else + if( sqliteStrICmp(zLeft, "full_column_names")==0 ){ + if( getBoolean(zRight) ){ + db->flags |= SQLITE_FullColNames; + }else{ + db->flags &= ~SQLITE_FullColNames; + } + }else + + if( sqliteStrICmp(zLeft, "table_info")==0 ){ + Table *pTab; + Vdbe *v; + pTab = sqliteFindTable(db, zRight); + if( pTab ) v = sqliteGetVdbe(pParse); + if( pTab && v ){ + static VdbeOp tableInfoPreface[] = { + { OP_ColumnCount, 5, 0, 0}, + { OP_ColumnName, 0, 0, "cid"}, + { OP_ColumnName, 1, 0, "name"}, + { OP_ColumnName, 2, 0, "type"}, + { OP_ColumnName, 3, 0, "notnull"}, + { OP_ColumnName, 4, 0, "dflt_value"}, + }; + int i; + sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface); + for(i=0; inCol; i++){ + sqliteVdbeAddOp(v, OP_Integer, i, 0, 0, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0, pTab->aCol[i].zName, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0, + pTab->aCol[i].zType ? pTab->aCol[i].zType : "text", 0); + sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0, 0, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0, pTab->aCol[i].zDflt, 0); + sqliteVdbeAddOp(v, OP_Callback, 5, 0, 0, 0); + } + } + }else + + if( sqliteStrICmp(zLeft, "index_info")==0 ){ + Index *pIdx; + Table *pTab; + Vdbe *v; + pIdx = sqliteFindIndex(db, zRight); + if( pIdx ) v = sqliteGetVdbe(pParse); + if( pIdx && v ){ + static VdbeOp tableInfoPreface[] = { + { OP_ColumnCount, 3, 0, 0}, + { OP_ColumnName, 0, 0, "seqno"}, + { OP_ColumnName, 1, 0, "cid"}, + { OP_ColumnName, 2, 0, "name"}, + }; + int i; + pTab = pIdx->pTable; + sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface); + for(i=0; inColumn; i++){ + sqliteVdbeAddOp(v, OP_Integer, i, 0, 0, 0); + sqliteVdbeAddOp(v, OP_Integer, pIdx->aiColumn[i], 0, 0, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0, + pTab->aCol[pIdx->aiColumn[i]].zName, 0); + sqliteVdbeAddOp(v, OP_Callback, 3, 0, 0, 0); + } + } + }else + #ifndef NDEBUG if( sqliteStrICmp(zLeft, "parser_trace")==0 ){ extern void sqliteParserTrace(FILE*, char *); diff --git a/src/expr.c b/src/expr.c index 7710743f73..0bf74727a1 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.28 2001/09/16 00:13:27 drh Exp $ +** $Id: expr.c,v 1.29 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" @@ -526,7 +526,7 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){ break; } case TK_NULL: { - sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0, 0, 0); break; } case TK_AND: diff --git a/src/insert.c b/src/insert.c index 1c209be2d5..9529a1f9ff 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.20 2001/09/27 03:22:33 drh Exp $ +** $Id: insert.c,v 1.21 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" @@ -186,12 +186,7 @@ void sqliteInsert( } } if( pColumn && j>=pColumn->nId ){ - char *zDflt = pTab->aCol[i].zDflt; - if( zDflt==0 ){ - sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0); - }else{ - sqliteVdbeAddOp(v, OP_String, 0, 0, zDflt, 0); - } + sqliteVdbeAddOp(v, OP_String, 0, 0, pTab->aCol[i].zDflt, 0); }else if( srcTab>=0 ){ sqliteVdbeAddOp(v, OP_Column, srcTab, i, 0, 0); }else{ @@ -218,12 +213,7 @@ void sqliteInsert( } } if( pColumn && j>=pColumn->nId ){ - char *zDflt = pTab->aCol[idx].zDflt; - if( zDflt==0 ){ - sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0); - }else{ - sqliteVdbeAddOp(v, OP_String, 0, 0, zDflt, 0); - } + sqliteVdbeAddOp(v, OP_String, 0, 0, pTab->aCol[idx].zDflt, 0); }else if( srcTab>=0 ){ sqliteVdbeAddOp(v, OP_Column, srcTab, idx, 0, 0); }else{ diff --git a/src/main.c b/src/main.c index 5fcc32cccc..d96aad914f 100644 --- a/src/main.c +++ b/src/main.c @@ -14,14 +14,16 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.42 2001/09/27 15:11:54 drh Exp $ +** $Id: main.c,v 1.43 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" #include "os.h" /* ** This is the callback routine for the code that initializes the -** database. Each callback contains the following information: +** database. See sqliteInit() below for additional information. +** +** Each callback contains the following information: ** ** argv[0] = "meta" or "table" or "index" ** argv[1] = table or index name or meta statement type. @@ -34,8 +36,9 @@ static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){ Parse sParse; int nErr = 0; -/* TODO: Do some validity checks on all fields. In particular, -** make sure fields do not contain NULLs. */ + /* TODO: Do some validity checks on all fields. In particular, + ** make sure fields do not contain NULLs. Otherwise we might core + ** when attempting to initialize from a corrupt database file. */ assert( argc==4 ); switch( argv[0][0] ){ @@ -51,12 +54,23 @@ static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){ case 'i': case 't': { /* CREATE TABLE and CREATE INDEX statements */ if( argv[3] && argv[3][0] ){ + /* Call the parser to process a CREATE TABLE or CREATE INDEX statement. + ** But because sParse.initFlag is set to 1, no VDBE code is generated + ** or executed. All the parser does is build the internal data + ** structures that describe the table or index. + */ memset(&sParse, 0, sizeof(sParse)); sParse.db = db; sParse.initFlag = 1; sParse.newTnum = atoi(argv[2]); nErr = sqliteRunParser(&sParse, argv[3], 0); }else{ + /* If the SQL column is blank it means this is an index that + ** was created to be the PRIMARY KEY or to fulfill a UNIQUE + ** constraint or a CREATE TABLE. The index should have already + ** been created when we processed the CREATE TABLE. All we have + ** to do here is record the root page. + */ Index *pIndex = sqliteFindIndex(db, argv[1]); if( pIndex==0 || pIndex->tnum!=0 ){ nErr++; @@ -123,9 +137,12 @@ static int sqliteInit(sqlite *db, char **pzErrMsg){ ** The "tbl_name" is the name of the associated table. For tables, ** the tbl_name column is always the same as name. For indices, the ** tbl_name column contains the name of the table that the index - ** indexes. Finally, the "sql" column contains the complete text of - ** the CREATE TABLE or CREATE INDEX statement that originally created - ** the table or index. + ** indexes. The "rootpage" column holds the number of the root page + ** for the b-tree for the table or index. Finally, the "sql" column + ** contains the complete text of the CREATE TABLE or CREATE INDEX + ** statement that originally created the table or index. If an index + ** was created to fulfill a PRIMARY KEY or UNIQUE constraint on a table, + ** then the "sql" column is NULL. ** ** If the "type" column has the value "meta", then the "sql" column ** contains extra information about the database, such as the @@ -175,7 +192,7 @@ static int sqliteInit(sqlite *db, char **pzErrMsg){ { OP_Goto, 0, 24, 0}, { OP_String, 0, 0, "meta"}, /* 34 */ { OP_String, 0, 0, "schema-cookie"}, - { OP_Null, 0, 0, 0}, + { OP_String, 0, 0, 0}, { OP_ReadCookie,0,0, 0}, { OP_Callback, 4, 0, 0}, { OP_Close, 0, 0, 0}, @@ -183,7 +200,7 @@ static int sqliteInit(sqlite *db, char **pzErrMsg){ }; /* Create a virtual machine to run the initialization program. Run - ** the program. The delete the virtual machine. + ** the program. Then delete the virtual machine. */ vdbe = sqliteVdbeCreate(db); if( vdbe==0 ){ diff --git a/src/pager.c b/src/pager.c index 6f60301af4..6bb71efc7b 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.24 2001/09/20 01:44:43 drh Exp $ +** @(#) $Id: pager.c,v 1.25 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" @@ -377,6 +377,10 @@ void sqlitepager_set_cachesize(Pager *pPager, int mxPage){ ** The file to be cached need not exist. The file is not locked until ** the first call to sqlitepager_get() and is only held open until the ** last page is released using sqlitepager_unref(). +** +** If zFilename is NULL then a random temporary file is created and used +** as the file to be cached. The file will be deleted automatically when +** it is closed. */ int sqlitepager_open( Pager **ppPager, /* Return the Pager structure here */ diff --git a/src/parse.y b/src/parse.y index d64c56ba36..56e6af75af 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.33 2001/10/01 14:29:23 drh Exp $ +** @(#) $Id: parse.y,v 1.34 2001/10/06 16:33:03 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -49,9 +49,7 @@ ecmd ::= cmd. {sqliteExec(pParse);} ecmd ::= . explain ::= EXPLAIN. {pParse->explain = 1;} -// Begin and end transactions. Transaction support is sparse. -// Some backends support only COMMIT and not ROLLBACK. There can -// be only a single active transaction at a time. +///////////////////// Begin and end transactions. //////////////////////////// // cmd ::= BEGIN trans_opt. {sqliteBeginTransaction(pParse);} trans_opt ::= . @@ -61,7 +59,7 @@ cmd ::= COMMIT trans_opt. {sqliteCommitTransaction(pParse);} cmd ::= END trans_opt. {sqliteCommitTransaction(pParse);} cmd ::= ROLLBACK trans_opt. {sqliteRollbackTransaction(pParse);} -// The first form of a command is a CREATE TABLE statement. +///////////////////// The CREATE TABLE statement //////////////////////////// // cmd ::= create_table create_table_args. create_table ::= CREATE(X) TABLE ids(Y). {sqliteStartTable(pParse,&X,&Y);} @@ -79,7 +77,8 @@ columnid ::= ids(X). {sqliteAddColumn(pParse,&X);} // An IDENTIFIER can be a generic identifier, or one of several // keywords. Any non-standard keyword can also be an identifier. -// We also make DESC and identifier since it comes up so often. +// We also make DESC and identifier since it comes up so often (as +// an abbreviation of "description"). // %type id {Token} id(A) ::= DESC(X). {A = X;} @@ -99,11 +98,14 @@ id(A) ::= ID(X). {A = X;} ids(A) ::= id(X). {A = X;} ids(A) ::= STRING(X). {A = X;} -type ::= typename. -type ::= typename LP signed RP. -type ::= typename LP signed COMMA signed RP. -typename ::= ids. -typename ::= typename ids. +type ::= . +type ::= typename(X). {sqliteAddColumnType(pParse,&X,&X);} +type ::= typename(X) LP signed RP(Y). {sqliteAddColumnType(pParse,&X,&Y);} +type ::= typename(X) LP signed COMMA signed RP(Y). + {sqliteAddColumnType(pParse,&X,&Y);} +%type typename {Token} +typename(A) ::= ids(X). {A = X;} +typename(A) ::= typename(X) ids. {A = X;} signed ::= INTEGER. signed ::= PLUS INTEGER. signed ::= MINUS INTEGER. @@ -121,15 +123,16 @@ carg ::= DEFAULT PLUS FLOAT(X). {sqliteAddDefaultValue(pParse,&X,0);} carg ::= DEFAULT MINUS FLOAT(X). {sqliteAddDefaultValue(pParse,&X,1);} carg ::= DEFAULT NULL. -// In addition to the type name, we also care about the primary key. +// In addition to the type name, we also care about the primary key and +// UNIQUE constraints. // -ccons ::= NOT NULL. +ccons ::= NOT NULL. {sqliteAddNotNull(pParse);} ccons ::= PRIMARY KEY sortorder. {sqliteCreateIndex(pParse,0,0,0,1,0,0);} ccons ::= UNIQUE. {sqliteCreateIndex(pParse,0,0,0,1,0,0);} ccons ::= CHECK LP expr RP. // For the time being, the only constraint we care about is the primary -// key. +// key and UNIQUE. Both create indices. // conslist_opt ::= . conslist_opt ::= COMMA conslist. @@ -140,14 +143,12 @@ tcons ::= CONSTRAINT ids. tcons ::= PRIMARY KEY LP idxlist(X) RP. {sqliteCreateIndex(pParse,0,0,X,1,0,0);} tcons ::= UNIQUE LP idxlist(X) RP. {sqliteCreateIndex(pParse,0,0,X,1,0,0);} tcons ::= CHECK expr. -// idlist ::= idlist COMMA ids. -// idlist ::= ids. -// The next command format is dropping tables. +////////////////////////// The DROP TABLE ///////////////////////////////////// // cmd ::= DROP TABLE ids(X). {sqliteDropTable(pParse,&X);} -// The select statement +//////////////////////// The SELECT statement ///////////////////////////////// // cmd ::= select(X). { sqliteSelect(pParse, X, SRT_Callback, 0); @@ -253,7 +254,8 @@ groupby_opt(A) ::= GROUP BY exprlist(X). {A = X;} having_opt(A) ::= . {A = 0;} having_opt(A) ::= HAVING expr(X). {A = X;} - +/////////////////////////// The DELETE statement ///////////////////////////// +// cmd ::= DELETE FROM ids(X) where_opt(Y). {sqliteDeleteFrom(pParse, &X, Y);} @@ -266,6 +268,8 @@ where_opt(A) ::= WHERE expr(X). {A = X;} %type setlist {ExprList*} %destructor setlist {sqliteExprListDelete($$);} +////////////////////////// The UPDATE command //////////////////////////////// +// cmd ::= UPDATE ids(X) SET setlist(Y) where_opt(Z). {sqliteUpdate(pParse,&X,Y,Z);} @@ -273,6 +277,8 @@ setlist(A) ::= setlist(Z) COMMA ids(X) EQ expr(Y). {A = sqliteExprListAppend(Z,Y,&X);} setlist(A) ::= ids(X) EQ expr(Y). {A = sqliteExprListAppend(0,Y,&X);} +////////////////////////// The INSERT command ///////////////////////////////// +// cmd ::= INSERT INTO ids(X) inscollist_opt(F) VALUES LP itemlist(Y) RP. {sqliteInsert(pParse, &X, Y, 0, F);} cmd ::= INSERT INTO ids(X) inscollist_opt(F) select(S). @@ -311,6 +317,8 @@ inscollist_opt(A) ::= LP inscollist(X) RP. {A = X;} inscollist(A) ::= inscollist(X) COMMA ids(Y). {A = sqliteIdListAppend(X,&Y);} inscollist(A) ::= ids(Y). {A = sqliteIdListAppend(0,&Y);} +/////////////////////////// Expression Processing ///////////////////////////// +// %left OR. %left AND. %right NOT. @@ -452,7 +460,8 @@ exprlist(A) ::= expritem(X). {A = sqliteExprListAppend(0,X,0);} expritem(A) ::= expr(X). {A = X;} expritem(A) ::= . {A = 0;} - +///////////////////////////// The CREATE INDEX command /////////////////////// +// cmd ::= CREATE(S) uniqueflag(U) INDEX ids(X) ON ids(Y) LP idxlist(Z) RP(E). {sqliteCreateIndex(pParse, &X, &Y, Z, U, &S, &E);} @@ -470,20 +479,31 @@ idxlist(A) ::= idxitem(Y). {A = sqliteIdListAppend(0,&Y);} idxitem(A) ::= ids(X). {A = X;} +///////////////////////////// The CREATE INDEX command /////////////////////// +// + cmd ::= DROP INDEX ids(X). {sqliteDropIndex(pParse, &X);} + +///////////////////////////// The DROP INDEX command ///////////////////////// +// cmd ::= COPY ids(X) FROM ids(Y) USING DELIMITERS STRING(Z). {sqliteCopy(pParse,&X,&Y,&Z);} cmd ::= COPY ids(X) FROM ids(Y). {sqliteCopy(pParse,&X,&Y,0);} +///////////////////////////// The VACUUM command ///////////////////////////// +// cmd ::= VACUUM. {sqliteVacuum(pParse,0);} cmd ::= VACUUM ids(X). {sqliteVacuum(pParse,&X);} +///////////////////////////// The PRAGMA command ///////////////////////////// +// cmd ::= PRAGMA ids(X) EQ ids(Y). {sqlitePragma(pParse,&X,&Y,0);} cmd ::= PRAGMA ids(X) EQ ON(Y). {sqlitePragma(pParse,&X,&Y,0);} cmd ::= PRAGMA ids(X) EQ plus_num(Y). {sqlitePragma(pParse,&X,&Y,0);} cmd ::= PRAGMA ids(X) EQ minus_num(Y). {sqlitePragma(pParse,&X,&Y,1);} +cmd ::= PRAGMA ids(X) LP ids(Y) RP. {sqlitePragma(pParse,&X,&Y,0);} plus_num(A) ::= plus_opt number(X). {A = X;} minus_num(A) ::= MINUS number(X). {A = X;} number(A) ::= INTEGER(X). {A = X;} diff --git a/src/select.c b/src/select.c index 7b9c479425..ab1cc5a27f 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.37 2001/09/16 00:13:27 drh Exp $ +** $Id: select.c,v 1.38 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" @@ -250,7 +250,7 @@ void generateColumnNames(Parse *pParse, IdList *pTabList, ExprList *pEList){ sprintf(zName, "column%d", i+1); sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0); }else{ - if( pTabList->nId>1 ){ + if( pTabList->nId>1 || (pParse->db->flags & SQLITE_FullColNames)!=0 ){ char *zName = 0; Table *pTab = pTabList->a[p->iTable].pTab; char *zTab; @@ -861,7 +861,7 @@ int sqliteSelect( /* Initialize the memory cell to NULL */ if( eDest==SRT_Mem ){ - sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0, 0, 0); sqliteVdbeAddOp(v, OP_MemStore, iParm, 0, 0, 0); } diff --git a/src/shell.c b/src/shell.c index a9f34e110f..726dd92619 100644 --- a/src/shell.c +++ b/src/shell.c @@ -12,13 +12,12 @@ ** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** -** $Id: shell.c,v 1.35 2001/10/01 14:29:23 drh Exp $ +** $Id: shell.c,v 1.36 2001/10/06 16:33:03 drh Exp $ */ #include #include #include #include "sqlite.h" -#include #include #ifdef OS_UNIX # include @@ -603,8 +602,6 @@ static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){ }else if( strncmp(azArg[1],"html",n2)==0 ){ p->mode = MODE_Html; }else if( strncmp(azArg[1],"insert",n2)==0 ){ - char *zTab; - int k, n; p->mode = MODE_Insert; if( nArg>=3 ){ set_table_name(p, azArg[2]); @@ -908,6 +905,7 @@ int main(int argc, char **argv){ exit(1); } }else{ + extern int isatty(); if( isatty(0) ){ printf( "SQLite version %s\n" diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 9056ed4567..4bf2fdd4de 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.20 2001/09/27 03:22:33 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.21 2001/10/06 16:33:03 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ @@ -23,6 +23,13 @@ */ #define SQLITE_VERSION "--VERS--" +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" { +#endif + /* ** The version string is also compiled into the library so that a program ** can check to make sure that the lib*.a file and the *.h file are from @@ -342,4 +349,8 @@ int sqlite_get_table_vprintf( va_list ap /* Arguments to the format string */ ); +#ifdef __cplusplus +} /* End of the 'extern "C"' block */ +#endif + #endif /* _SQLITE_H_ */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5d1d7438fb..59f0a25577 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.56 2001/09/27 15:11:54 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.57 2001/10/06 16:33:03 drh Exp $ */ #include "sqlite.h" #include "hash.h" @@ -164,6 +164,7 @@ struct sqlite { #define SQLITE_Interrupt 0x00000004 /* Cancel current operation */ #define SQLITE_InTrans 0x00000008 /* True if in a transaction */ #define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */ +#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ /* ** Current file format version @@ -177,6 +178,7 @@ struct sqlite { struct Column { char *zName; /* Name of this column */ char *zDflt; /* Default value of this column */ + char *zType; /* Data type for this column */ int notNull; /* True if there is a NOT NULL constraint */ }; @@ -423,6 +425,8 @@ void sqliteCommitInternalChanges(sqlite*); void sqliteRollbackInternalChanges(sqlite*); void sqliteStartTable(Parse*,Token*,Token*); void sqliteAddColumn(Parse*,Token*); +void sqliteAddNotNull(Parse*); +void sqliteAddColumnType(Parse*,Token*,Token*); void sqliteAddDefaultValue(Parse*,Token*,int); void sqliteEndTable(Parse*,Token*); void sqliteDropTable(Parse*, Token*); diff --git a/src/tokenize.c b/src/tokenize.c index 53ebbbf1a2..619ae6ea90 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -15,7 +15,7 @@ ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.23 2001/09/23 02:35:53 drh Exp $ +** $Id: tokenize.c,v 1.24 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" #include @@ -333,7 +333,6 @@ int sqliteRunParser(Parse *pParse, char *zSql, char **pzErrMsg){ } switch( tokenType ){ case TK_SPACE: - break; case TK_COMMENT: { break; } diff --git a/src/vdbe.c b/src/vdbe.c index 546b7bf86f..0e2614bcb4 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -30,11 +30,10 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.79 2001/09/27 15:11:54 drh Exp $ +** $Id: vdbe.c,v 1.80 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" #include -#include /* ** SQL is translated into a sequence of instructions to be @@ -1084,20 +1083,26 @@ case OP_Integer: { /* Opcode: String * * P3 ** -** The string value P3 is pushed onto the stack. +** The string value P3 is pushed onto the stack. If P3==0 then a +** NULL is pushed onto the stack. */ case OP_String: { int i = ++p->tos; char *z; VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; ) z = pOp->p3; - if( z==0 ) z = ""; - zStack[i] = z; - aStack[i].n = strlen(z) + 1; - aStack[i].flags = STK_Str; + if( z==0 ){ + zStack[i] = 0; + aStack[i].flags = STK_Null; + }else{ + zStack[i] = z; + aStack[i].n = strlen(z) + 1; + aStack[i].flags = STK_Str; + } break; } +#if 0 /* NOT USED */ /* Opcode: Null * * * ** ** Push a NULL value onto the stack. @@ -1109,6 +1114,7 @@ case OP_Null: { aStack[i].flags = STK_Null; break; } +#endif /* Opcode: Pop P1 * * ** diff --git a/test/select1.test b/test/select1.test index 08aa84e384..7516aab77d 100644 --- a/test/select1.test +++ b/test/select1.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # -# $Id: select1.test,v 1.10 2001/09/16 00:13:28 drh Exp $ +# $Id: select1.test,v 1.11 2001/10/06 16:33:03 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -238,6 +238,20 @@ do_test select1-6.1 { set v [catch {execsql2 {SELECT f1 FROM test1 ORDER BY f2}} msg] lappend v $msg } {0 {f1 11 f1 33}} +do_test select1-6.1.1 { + execsql {PRAGMA full_column_names=on} + set v [catch {execsql2 {SELECT f1 FROM test1 ORDER BY f2}} msg] + lappend v $msg +} {0 {f1 11 f1 33}} +do_test select1-6.1.2 { + set v [catch {execsql2 {SELECT * FROM test1 WHERE f1==11}} msg] + execsql {PRAGMA full_column_names=off} + lappend v $msg +} {0 {test1.f1 11 test1.f2 22}} +do_test select1-6.1.2 { + set v [catch {execsql2 {SELECT * FROM test1 WHERE f1==11}} msg] + lappend v $msg +} {0 {f1 11 f2 22}} do_test select1-6.2 { set v [catch {execsql2 {SELECT f1 as xyzzy FROM test1 ORDER BY f2}} msg] lappend v $msg diff --git a/www/changes.tcl b/www/changes.tcl index 51a4f183d8..b92ee88f41 100644 --- a/www/changes.tcl +++ b/www/changes.tcl @@ -17,6 +17,13 @@ proc chng {date desc} { puts "

    $desc

" } +chng {2001 Oct ? (2.0.2)} { +
  • Removed some unused "#include " that were causing problems + for VC++.
  • +
  • Added the FULL_COLUMN_NAMES pragma. When set to "ON", the names of + columns are reported back as TABLE.COLUMN instead of just COLUMN.
  • +} + chng {2001 Oct 2 (2.0.1)} {
  • Remove some C++ style comments from btree.c so that it will compile using compilers other than gcc.
  • diff --git a/www/download.tcl b/www/download.tcl new file mode 100644 index 0000000000..2a4b82f159 --- /dev/null +++ b/www/download.tcl @@ -0,0 +1,72 @@ +# +# Run this TCL script to generate HTML for the download.html file. +# +set rcsid {$Id: download.tcl,v 1.1 2001/10/06 16:33:04 drh Exp $} + +puts { +SQLite Download Page + +

    SQLite Download Page

    } +#

    } +#puts "This page was last modified on [lrange $rcsid 3 4] GMT
    " +#set vers [lindex $argv 0] +#puts "The latest SQLite version is $vers" +#puts " created on [exec cat last_change] GMT" +#puts {

    } + +puts {

    Precompiled Binaries For Linux

    } + +proc Product {file desc} { + if {![file exists $file]} return + set size [file size $file] + puts [subst { + + + + + +
    +$file
    ($size bytes) +
    [string trim $desc]
    }] +} + +Product sqlite.bin.gz { + A command-line program for accessing and modifing SQLite databases. + See the documentation for additional information. +} + +Product tclsqlite.so.gz { + Bindings for TCL. You can import this shared library into either + tclsh or wish to get SQLite database access from Tcl/Tk. + See the documentation for details. +} + +puts {

    Precompiled Binaries For Windows

    } + +Product sqlite.zip { + A command-line program for accessing and modifing SQLite databases. + See the documentation for additional information. +} +Product tclsqlite.zip { + Bindings for TCL. You can import this shared library into either + tclsh or wish to get SQLite database access from Tcl/Tk. + See the documentation for details. +} + +puts {

    Source Code

    } + +foreach name [lsort -dict -decreasing [glob -nocomplain sqlite-*.tar.gz]] { + regexp {sqlite-(.*)\.tar\.gz} $name match vers + Product $name " + Version $vers of the source tree including all documentation. + " +} + +puts { +


    +

    + +Back to the SQLite home page +

    + +} diff --git a/www/index.tcl b/www/index.tcl index 3abbdaad81..9483caa084 100644 --- a/www/index.tcl +++ b/www/index.tcl @@ -1,7 +1,7 @@ # # Run this TCL script to generate HTML for the index.html file. # -set rcsid {$Id: index.tcl,v 1.43 2001/09/28 23:11:24 drh Exp $} +set rcsid {$Id: index.tcl,v 1.44 2001/10/06 16:33:04 drh Exp $} puts { SQLite: An SQL Database Engine In A C Library @@ -170,6 +170,10 @@ puts {

    Related Sites