Everything is working on Linux. This is release 2.0-Alpha-1. (CVS 246)

FossilOrigin-Name: 14474fa144fe7c5dc63e0990d6cc92d769e6013e
This commit is contained in:
drh 2001-09-15 00:57:28 +00:00
parent f57b14a657
commit 50e5dadf2c
15 changed files with 397 additions and 208 deletions

View File

@ -1,5 +1,5 @@
C Added\sa\sPRAGMA\sstatement.\s\sTook\sout\sthe\sspecial\scomment\sparsing.\s(CVS\s245)
D 2001-09-14T18:54:08
C Everything\sis\sworking\son\sLinux.\s\sThis\sis\srelease\s2.0-Alpha-1.\s(CVS\s246)
D 2001-09-15T00:57:28
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
F Makefile.in 7ecb2370b5cb34d390af1fcb3118ea6d84a253ca
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
@ -12,11 +12,11 @@ F notes/notes1.txt b7c0812b704a022e88c621146ae50955c923d464
F notes/notes2.txt 7e3fafd5e25906c1fe1e95f13b089aa398ca403e
F notes/notes2b.txt 1c17a5b7f6b44a75cd3eb98ed2c24db1eefb06c3
F notes/notes3.txt 71e47be517e3d2578b3b9343a45b772d43b7ba16
F src/TODO f0ea267ab55c4d15127c1ac1667edbf781147438
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
F src/btree.c 3adf545b8e072000923f7e0f7f91d33072a9f869
F src/btree.h a3d9c20fa876e837680745ac60500be697026b7b
F src/build.c b5c682960b5889555cd059f3b5157668778b8834
F src/delete.c 62500a09606c0f714b651756475cd42979ef08e8
F src/build.c 8359e553db8138d09f44957e2d1bcc9b8720117b
F src/delete.c c84b5a26e29fda3c3de51345073a76bb161271fd
F src/ex/README b745b00acce2d892f60c40111dacdfc48e0c1c7a
F src/ex/db.c f1419ae6c93e40b5ac6e39fe7efd95d868e6f9d7
F src/ex/db.h 3f2933ee20c147fe494835786e4c6f3a562def4e
@ -26,10 +26,10 @@ F src/ex/pg.c 2bbf6a94f37226d06337868b6bf4d7affc60197f
F src/ex/pg.h 23a4ac807b0546ec2bb6239ec8bd3e06926572cd
F src/ex/sizes.tcl f54bad4a2ac567624be59131a6ee42d71b41a3d7
F src/expr.c bcd91d0487c71cfa44413a46efe5e2c2244901b6
F src/insert.c edf098ecbbe00e3ecde6b5f22404a8230590c9fd
F src/main.c a2c142626b46e3eb3e01436626df6c2d0a8f3ae6
F src/insert.c 750a44c0d205779b2c42b0791a163937cfb00e74
F src/main.c 73be8d00a8a9bbec715a6260840a19020a074090
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
F src/pager.c bb0891d49b9068711e4b8bab14db2959f56f5be9
F src/pager.c 048c20ac85485ca87ed33d6b7711375a3444f817
F src/pager.h bb9136e833de46bc84aafd8403713d3c46fcbfdf
F src/parse.y 8b30e072208c3dfabd97c7d06f0924f194919533
F src/printf.c b1e22a47be8cdf707815647239991e08e8cb69f9
@ -37,19 +37,19 @@ F src/random.c b626726c4f0066610739e52e7431adae7ccd9651
F src/select.c f1673b4d06c24665097faf28d76c4533bce18b84
F src/shell.c 1fcdf8c4180098bcfdee12501e01b4c8eb21d726
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in 8faa2fed0513d188ced16e5f9094e57694594e70
F src/sqliteInt.h 11d74bfd90777afafc529434b86c413fed44f0bf
F src/sqlite.h.in 1d6a7d13284c3861e61bd0b71491fda613613c68
F src/sqliteInt.h c7c0580ceb9b5ce92c6fc7ef9434320952b14dc0
F src/table.c adcaf074f6c1075e86359174e68701fa2acfc4d6
F src/tclsqlite.c d328970848c028e13e61e173bef79adcc379568a
F src/test1.c abb3cb427e735ae87e6533f5b3b7164b7da91bc4
F src/test2.c b3177e061fabd20d48e4b1b4bca610a0d2b28670
F src/test3.c 1fc103f198cbd0447d1a12c3ce48795755ec1a53
F src/tokenize.c 2d4d1534b321422384de0f311d417ffce14fedc6
F src/update.c ea8f2c0712cd4cd19314a26ef4766866013facda
F src/util.c c77668fef860cfd2e4e682ef4f3ed8f9e68c551b
F src/vdbe.c 244c86e406170c76b89ab07de4c7258f716c36ff
F src/vdbe.h 9f32bd12c47bd2b4bdd7e93092bb796f2a3b649f
F src/where.c fef978a9a2234b01e30e36833ab63e14bbc626d3
F src/update.c 8a9d514c7f3bfe5d99fe3dfc1ad92ed3e9daea47
F src/util.c f3f1550fb7a02348c3d0a0969951e489806e055b
F src/vdbe.c d5bb5d8dda994779e4d20de5e4a31edf995269ff
F src/vdbe.h b9d60d90aeb3acb5dbc1cdac6b0201991921b272
F src/where.c b831b506e17cb592d9781ed066f3459cef768318
F test/all.test 5cefdb035b45639ddbb9f80324185b0f0a9ebda2
F test/btree.test 5e1eeb03cda22161eec827dc5224ce6c500eaaf9
F test/btree2.test 061365dfc2a6cd784e17a014b67b277a4cd374ee
@ -107,7 +107,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
P 7da856cd94d2572070e40762e5bc477679e60042
R 07caee6e3ed361d3efc95a7817451754
P 5e3724603e6f52bb74deb1c62e6e8f323d7b64b7
R f702824af0e6fb733e46f0ad203329d6
U drh
Z 4e11150d8699ec673e8745d72c606c4d
Z 7366e408d799dcad27172164daf780cc

View File

@ -1 +1 @@
5e3724603e6f52bb74deb1c62e6e8f323d7b64b7
14474fa144fe7c5dc63e0990d6cc92d769e6013e

View File

@ -3,5 +3,4 @@
* "OPTIMIZE select" statement to automatically create indices and/or
invoke a CLUSTER command.
* "CREATE INDEX FOR select" to automatically generate needed indices.
* Implement a PRAGMA command
* Parse and use constraints.

View File

@ -33,7 +33,7 @@
** COPY
** VACUUM
**
** $Id: build.c,v 1.34 2001/09/14 18:54:08 drh Exp $
** $Id: build.c,v 1.35 2001/09/15 00:57:28 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -67,6 +67,7 @@ void sqliteExec(Parse *pParse){
pParse->pVdbe = 0;
pParse->colNamesSet = 0;
pParse->rc = rc;
pParse->schemaVerified = 0;
}
}
@ -278,6 +279,7 @@ static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *pTable){
void sqliteCommitInternalChanges(sqlite *db){
int i;
if( (db->flags & SQLITE_InternChanges)==0 ) return;
db->schema_cookie = db->next_cookie;
for(i=0; i<N_HASH; i++){
Table *pTable, *pNext;
for(pTable = db->apTblHash[i]; pTable; pTable=pNext){
@ -314,6 +316,7 @@ void sqliteCommitInternalChanges(sqlite *db){
void sqliteRollbackInternalChanges(sqlite *db){
int i;
if( (db->flags & SQLITE_InternChanges)==0 ) return;
db->next_cookie = db->schema_cookie;
for(i=0; i<N_HASH; i++){
Table *pTable, *pNext;
for(pTable = db->apTblHash[i]; pTable; pTable=pNext){
@ -398,6 +401,7 @@ void sqliteStartTable(Parse *pParse, Token *pStart, Token *pName){
Vdbe *v = sqliteGetVdbe(pParse);
if( v ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
}
}
}
@ -450,6 +454,30 @@ void sqliteAddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
sqliteDequote(*pz);
}
/*
** Come up with a new random value for the schema cookie. Make sure
** the new value is different from the old.
**
** The schema cookie is used to determine when the schema for the
** database changes. After each schema change, the cookie value
** changes. When a process first reads the schema it records the
** cookie. Thereafter, whenever it goes to access the database,
** it checks the cookie to make sure the schema has not changed
** since it was last read.
**
** This plan is not completely bullet-proof. It is possible for
** the schema to change multiple times and for the cookie to be
** set back to prior value. But schema changes are infrequent
** and the probability of hitting the same cookie value is only
** 1 chance in 2^32. So we're safe enough.
*/
static void changeCookie(sqlite *db){
if( db->next_cookie==db->schema_cookie ){
db->next_cookie = db->schema_cookie + sqliteRandomByte() + 1;
db->flags |= SQLITE_InternChanges;
}
}
/*
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.
@ -503,6 +531,7 @@ void sqliteEndTable(Parse *pParse, Token *pEnd){
{ OP_String, 0, 0, 0}, /* 6 */
{ OP_MakeRecord, 5, 0, 0},
{ OP_Put, 0, 0, 0},
{ OP_SetCookie, 0, 0, 0}, /* 9 */
};
int n, base;
Vdbe *v;
@ -515,6 +544,8 @@ void sqliteEndTable(Parse *pParse, Token *pEnd){
sqliteVdbeTableRootAddr(v, &p->tnum);
sqliteVdbeChangeP3(v, base+5, p->zName, 0);
sqliteVdbeChangeP3(v, base+6, pParse->sFirstToken.z, n);
changeCookie(db);
sqliteVdbeChangeP1(v, base+9, db->next_cookie);
sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
if( p->pIndex ){
/* If the table has a primary key, create an index in the database
@ -586,15 +617,19 @@ void sqliteDropTable(Parse *pParse, Token *pName){
{ OP_Delete, 0, 0, 0},
{ OP_Goto, 0, ADDR(3), 0},
{ OP_Destroy, 0, 0, 0}, /* 9 */
{ OP_SetCookie, 0, 0, 0}, /* 10 */
{ OP_Close, 0, 0, 0},
};
Index *pIdx;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
}
base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
sqliteVdbeChangeP3(v, base+2, pTable->zName, 0);
sqliteVdbeChangeP1(v, base+9, pTable->tnum);
changeCookie(db);
sqliteVdbeChangeP1(v, base+10, db->next_cookie);
for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, 0, 0, 0);
}
@ -772,6 +807,7 @@ void sqliteCreateIndex(
{ OP_String, 0, 0, 0}, /* 8 */
{ OP_MakeRecord, 5, 0, 0},
{ OP_Put, 2, 0, 0},
{ OP_SetCookie, 0, 0, 0}, /* 11 */
{ OP_Close, 2, 0, 0},
};
int n;
@ -783,6 +819,7 @@ void sqliteCreateIndex(
if( v==0 ) goto exit_create_index;
if( pTable!=0 && (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
}
if( pStart && pEnd ){
int base;
@ -793,6 +830,8 @@ void sqliteCreateIndex(
sqliteVdbeChangeP3(v, base+6, pIndex->zName, 0);
sqliteVdbeChangeP3(v, base+7, pTab->zName, 0);
sqliteVdbeChangeP3(v, base+8, pStart->z, n);
changeCookie(db);
sqliteVdbeChangeP1(v, base+11, db->next_cookie);
}
sqliteVdbeAddOp(v, OP_Open, 0, pTab->tnum, pTab->zName, 0);
lbl1 = sqliteVdbeMakeLabel(v);
@ -861,16 +900,20 @@ void sqliteDropIndex(Parse *pParse, Token *pName){
{ OP_Ne, 0, ADDR(3), 0},
{ OP_Delete, 0, 0, 0},
{ OP_Destroy, 0, 0, 0}, /* 8 */
{ OP_SetCookie, 0, 0, 0}, /* 9 */
{ OP_Close, 0, 0, 0},
};
int base;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
}
base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
sqliteVdbeChangeP3(v, base+2, pIndex->zName, 0);
sqliteVdbeChangeP1(v, base+8, pIndex->tnum);
changeCookie(db);
sqliteVdbeChangeP1(v, base+9, db->next_cookie);
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0);
}
@ -1037,6 +1080,7 @@ void sqliteCopy(
if( v ){
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
}
addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0, 0, 0);
sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n);
@ -1109,6 +1153,7 @@ void sqliteVacuum(Parse *pParse, Token *pTableName){
if( v==0 ) goto vacuum_cleanup;
if( (db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
}
if( zName ){
sqliteVdbeAddOp(v, OP_Reorganize, 0, 0, zName, 0);
@ -1147,6 +1192,7 @@ void sqliteBeginTransaction(Parse *pParse){
v = sqliteGetVdbe(pParse);
if( v ){
sqliteVdbeAddOp(v, OP_Transaction, 1, 0, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
}
db->flags |= SQLITE_InTrans;
}

View File

@ -24,7 +24,7 @@
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.12 2001/09/13 21:53:10 drh Exp $
** $Id: delete.c,v 1.13 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"
@ -92,6 +92,7 @@ void sqliteDeleteFrom(
if( v==0 ) goto delete_from_cleanup;
if( (pParse->db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0, 0, 0);
}

View File

@ -24,7 +24,7 @@
** This file contains C code routines that are called by the parser
** to handle INSERT statements.
**
** $Id: insert.c,v 1.16 2001/09/14 03:24:25 drh Exp $
** $Id: insert.c,v 1.17 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"
@ -87,6 +87,7 @@ void sqliteInsert(
if( v==0 ) goto insert_cleanup;
if( (pParse->db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0, 0, 0);
}
/* Figure out how many columns of data are supplied. If the data

View File

@ -26,7 +26,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.35 2001/09/14 16:42:12 drh Exp $
** $Id: main.c,v 1.36 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"
#if defined(HAVE_USLEEP) && HAVE_USLEEP
@ -51,7 +51,12 @@ static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){
assert( argc==4 );
switch( argv[0][0] ){
case 'm': { /* Meta information */
sscanf(argv[1],"file format %d",&db->file_format);
if( strcmp(argv[1],"file-format")==0 ){
db->file_format = atoi(argv[3]);
}else if( strcmp(argv[1],"schema-cookie")==0 ){
db->schema_cookie = atoi(argv[3]);
db->next_cookie = db->schema_cookie;
}
break;
}
case 'i':
@ -170,7 +175,12 @@ static int sqliteInit(sqlite *db, char **pzErrMsg){
{ OP_Column, 0, 4, 0},
{ OP_Callback, 4, 0, 0},
{ OP_Goto, 0, 24, 0},
{ OP_Close, 0, 0, 0}, /* 34 */
{ OP_String, 0, 0, "meta"}, /* 34 */
{ OP_String, 0, 0, "schema-cookie"},
{ OP_String, 0, 0, ""},
{ OP_ReadCookie,0,0, 0},
{ OP_Callback, 4, 0, 0},
{ OP_Close, 0, 0, 0},
{ OP_Halt, 0, 0, 0},
};
@ -281,11 +291,16 @@ no_mem_on_open:
}
/*
** Close an existing SQLite database
** Erase all schema information from the schema hash table.
**
** The database schema is normally read in once when the database
** is first opened and stored in a hash table in the sqlite structure.
** This routine erases the stored schema. This erasure occurs because
** either the database is being closed or because some other process
** changed the schema and this process needs to reread it.
*/
void sqlite_close(sqlite *db){
static void clearHashTable(sqlite *db){
int i;
sqliteBtreeClose(db->pBe);
for(i=0; i<N_HASH; i++){
Table *pNext, *pList = db->apTblHash[i];
db->apTblHash[i] = 0;
@ -296,6 +311,15 @@ void sqlite_close(sqlite *db){
pList = pNext;
}
}
db->flags &= ~SQLITE_Initialized;
}
/*
** Close an existing SQLite database
*/
void sqlite_close(sqlite *db){
sqliteBtreeClose(db->pBe);
clearHashTable(db);
sqliteFree(db);
}
@ -387,6 +411,9 @@ int sqlite_exec(
sParse.rc = SQLITE_NOMEM;
}
sqliteStrRealloc(pzErrMsg);
if( sParse.rc==SQLITE_SCHEMA ){
clearHashTable(db);
}
return sParse.rc;
}

View File

@ -27,7 +27,7 @@
** all writes in order to support rollback. Locking is used to limit
** access to one or more reader or to one writer.
**
** @(#) $Id: pager.c,v 1.18 2001/09/14 18:54:09 drh Exp $
** @(#) $Id: pager.c,v 1.19 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
@ -683,6 +683,28 @@ int sqlitepager_ref(void *pData){
return SQLITE_OK;
}
/*
** Sync the journal and write all free dirty pages to the database file.
*/
static int syncAllPages(Pager *pPager){
PgHdr *pPg;
int rc = SQLITE_OK;
if( pPager->needSync ){
rc = fsync(pPager->jfd);
if( rc!=0 ) return rc;
pPager->needSync = 0;
}
for(pPg=pPager->pFirst; pPg; pPg=pPg->pNextFree){
if( pPg->dirty ){
pager_seek(pPager->fd, (pPg->pgno-1)*SQLITE_PAGE_SIZE);
rc = pager_write(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
if( rc!=SQLITE_OK ) break;
pPg->dirty = 0;
}
}
return SQLITE_OK;
}
/*
** Acquire a page.
**
@ -791,15 +813,28 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
/* Recycle an older page. First locate the page to be recycled.
** Try to find one that is not dirty and is near the head of
** of the free list */
/* int cnt = pPager->mxPage/2; */
int cnt = 10;
int cnt = pPager->mxPage/2;
pPg = pPager->pFirst;
while( pPg->dirty && 0<cnt-- && pPg->pNextFree ){
pPg = pPg->pNextFree;
}
if( pPg==0 || pPg->dirty ) pPg = pPager->pFirst;
if( pPg==0 || pPg->dirty ){
int rc = syncAllPages(pPager);
if( rc!=0 ){
sqlitepager_rollback(pPager);
*ppPage = 0;
return SQLITE_IOERR;
}
pPg = pPager->pFirst;
}
assert( pPg->nRef==0 );
#if 0
/**** Since putting in the call to syncAllPages() above, this code
** is no longer used. I've kept it here for historical reference
** only.
*/
/* If the page to be recycled is dirty, sync the journal and write
** the old page into the database. */
if( pPg->dirty ){
@ -825,6 +860,8 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
return rc;
}
}
#endif
assert( pPg->dirty==0 );
/* Unlink the old page from the free list and the hash table
*/

View File

@ -24,7 +24,7 @@
** This header file defines the interface that the sqlite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.14 2001/09/13 13:46:57 drh Exp $
** @(#) $Id: sqlite.h.in,v 1.15 2001/09/15 00:57:29 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
@ -160,6 +160,7 @@ int sqlite_exec(
#define SQLITE_CANTOPEN 13 /* Unable to open the database file */
#define SQLITE_PROTOCOL 14 /* Database lock protocol error */
#define SQLITE_EMPTY 15 /* Database table is empty */
#define SQLITE_SCHEMA 16 /* The database schema changed */
/* This function causes any pending database operation to abort and
** return at its earliest opportunity. This routine is typically

View File

@ -23,7 +23,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.47 2001/09/14 18:54:09 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.48 2001/09/15 00:57:29 drh Exp $
*/
#include "sqlite.h"
#include "vdbe.h"
@ -143,6 +143,8 @@ struct sqlite {
Btree *pBe; /* The B*Tree backend */
int flags; /* Miscellanous flags. See below */
int file_format; /* What file format version is this database? */
int schema_cookie; /* Magic number that changes with the schema */
int next_cookie; /* Value of schema_cookie after commit */
int nTable; /* Number of tables in the database */
void *pBusyArg; /* 1st Argument to the busy callback */
int (*xBusyCallback)(void *,const char*,int); /* The busy callback */
@ -376,6 +378,8 @@ struct Parse {
int iAggCount; /* Index of the count(*) aggregate in aAgg[] */
int useAgg; /* If true, extract field values from the aggregator
** while generating expressions. Normally false */
int schemaVerified; /* True if an OP_VerifySchema has been coded someplace
** other than after an OP_Transaction */
};
/*

View File

@ -24,7 +24,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.12 2001/09/13 13:46:57 drh Exp $
** $Id: update.c,v 1.13 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"
@ -146,6 +146,7 @@ void sqliteUpdate(
if( v==0 ) goto update_cleanup;
if( (pParse->db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0, 0, 0);
}
/* Begin the database scan

View File

@ -26,7 +26,7 @@
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.22 2001/09/13 13:46:57 drh Exp $
** $Id: util.c,v 1.23 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
@ -978,25 +978,26 @@ sqliteLikeCompare(const unsigned char *zPattern, const unsigned char *zString){
** argument.
*/
const char *sqliteErrStr(int rc){
char *z = 0;
const char *z;
switch( rc ){
case SQLITE_OK: z = "not an error"; break;
case SQLITE_ERROR: z = "SQL logic error or missing database"; break;
case SQLITE_INTERNAL: z = "internal SQLite implementation flaw"; break;
case SQLITE_PERM: z = "access permission denied"; break;
case SQLITE_ABORT: z = "callback requested query abort"; break;
case SQLITE_BUSY: z = "database in use by another process"; break;
case SQLITE_NOMEM: z = "out of memory"; break;
case SQLITE_READONLY: z = "attempt to write a readonly database"; break;
case SQLITE_INTERRUPT: z = "interrupted"; break;
case SQLITE_IOERR: z = "disk I/O error"; break;
case SQLITE_CORRUPT: z = "database disk image is malformed"; break;
case SQLITE_NOTFOUND: z = "table or record not found"; break;
case SQLITE_FULL: z = "database is full"; break;
case SQLITE_CANTOPEN: z = "unable to open database file"; break;
case SQLITE_PROTOCOL: z = "database locking protocol failure"; break;
case SQLITE_EMPTY: z = "table contains no data";
default:
case SQLITE_OK: z = "not an error"; break;
case SQLITE_ERROR: z = "SQL logic error or missing database"; break;
case SQLITE_INTERNAL: z = "internal SQLite implementation flaw"; break;
case SQLITE_PERM: z = "access permission denied"; break;
case SQLITE_ABORT: z = "callback requested query abort"; break;
case SQLITE_BUSY: z = "database in use by another process"; break;
case SQLITE_NOMEM: z = "out of memory"; break;
case SQLITE_READONLY: z = "attempt to write a readonly database"; break;
case SQLITE_INTERRUPT: z = "interrupted"; break;
case SQLITE_IOERR: z = "disk I/O error"; break;
case SQLITE_CORRUPT: z = "database disk image is malformed"; break;
case SQLITE_NOTFOUND: z = "table or record not found"; break;
case SQLITE_FULL: z = "database is full"; break;
case SQLITE_CANTOPEN: z = "unable to open database file"; break;
case SQLITE_PROTOCOL: z = "database locking protocol failure"; break;
case SQLITE_EMPTY: z = "table contains no data"; break;
case SQLITE_SCHEMA: z = "database schema has changed"; break;
default: z = "unknown error"; break;
}
return z;
}

View File

@ -41,7 +41,7 @@
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.66 2001/09/14 16:42:12 drh Exp $
** $Id: vdbe.c,v 1.67 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -759,6 +759,23 @@ static void KeylistFree(Keylist *p){
}
}
/*
** Close a cursor and release all the resources that cursor happens
** to hold.
*/
static void cleanupCursor(Cursor *pCx){
if( pCx->pCursor ){
sqliteBtreeCloseCursor(pCx->pCursor);
}
if( pCx->zKey ){
sqliteFree(pCx->zKey);
}
if( pCx->pBt ){
sqliteBtreeClose(pCx->pBt);
}
memset(pCx, 0, sizeof(Cursor));
}
/*
** Clean up the VM after execution.
**
@ -771,19 +788,7 @@ static void Cleanup(Vdbe *p){
sqliteFree(p->azColName);
p->azColName = 0;
for(i=0; i<p->nCursor; i++){
Cursor *pCx = &p->aCsr[i];
if( pCx->pCursor ){
sqliteBtreeCloseCursor(pCx->pCursor);
pCx->pCursor = 0;
}
if( pCx->zKey ){
sqliteFree(pCx->zKey);
pCx->zKey = 0;
}
if( pCx->pBt ){
sqliteBtreeClose(pCx->pBt);
pCx->pBt = 0;
}
cleanupCursor(&p->aCsr[i]);
}
sqliteFree(p->aCsr);
p->aCsr = 0;
@ -871,31 +876,32 @@ void sqliteVdbeDelete(Vdbe *p){
** this array, then copy and paste it into this file, if you want.
*/
static char *zOpName[] = { 0,
"Transaction", "Commit", "Rollback", "Open",
"OpenTemp", "Close", "MoveTo", "Fcnt",
"NewRecno", "Put", "Distinct", "Found",
"NotFound", "Delete", "Column", "KeyAsData",
"Recno", "FullKey", "Rewind", "Next",
"Destroy", "Clear", "CreateIndex", "CreateTable",
"Reorganize", "BeginIdx", "NextIdx", "PutIdx",
"DeleteIdx", "MemLoad", "MemStore", "ListOpen",
"ListWrite", "ListRewind", "ListRead", "ListClose",
"SortOpen", "SortPut", "SortMakeRec", "SortMakeKey",
"Sort", "SortNext", "SortKey", "SortCallback",
"SortClose", "FileOpen", "FileRead", "FileColumn",
"FileClose", "AggReset", "AggFocus", "AggIncr",
"AggNext", "AggSet", "AggGet", "SetInsert",
"SetFound", "SetNotFound", "SetClear", "MakeRecord",
"MakeKey", "MakeIdxKey", "Goto", "If",
"Halt", "ColumnCount", "ColumnName", "Callback",
"Integer", "String", "Null", "Pop",
"Dup", "Pull", "Add", "AddImm",
"Subtract", "Multiply", "Divide", "Min",
"Max", "Like", "Glob", "Eq",
"Ne", "Lt", "Le", "Gt",
"Ge", "IsNull", "NotNull", "Negative",
"And", "Or", "Not", "Concat",
"Noop", "Strlen", "Substr",
"Transaction", "Commit", "Rollback", "ReadCookie",
"SetCookie", "VerifyCookie", "Open", "OpenTemp",
"Close", "MoveTo", "Fcnt", "NewRecno",
"Put", "Distinct", "Found", "NotFound",
"Delete", "Column", "KeyAsData", "Recno",
"FullKey", "Rewind", "Next", "Destroy",
"Clear", "CreateIndex", "CreateTable", "Reorganize",
"BeginIdx", "NextIdx", "PutIdx", "DeleteIdx",
"MemLoad", "MemStore", "ListOpen", "ListWrite",
"ListRewind", "ListRead", "ListClose", "SortOpen",
"SortPut", "SortMakeRec", "SortMakeKey", "Sort",
"SortNext", "SortKey", "SortCallback", "SortClose",
"FileOpen", "FileRead", "FileColumn", "FileClose",
"AggReset", "AggFocus", "AggIncr", "AggNext",
"AggSet", "AggGet", "SetInsert", "SetFound",
"SetNotFound", "SetClear", "MakeRecord", "MakeKey",
"MakeIdxKey", "Goto", "If", "Halt",
"ColumnCount", "ColumnName", "Callback", "Integer",
"String", "Null", "Pop", "Dup",
"Pull", "Add", "AddImm", "Subtract",
"Multiply", "Divide", "Min", "Max",
"Like", "Glob", "Eq", "Ne",
"Lt", "Le", "Gt", "Ge",
"IsNull", "NotNull", "Negative", "And",
"Or", "Not", "Concat", "Noop",
"Strlen", "Substr",
};
/*
@ -1974,6 +1980,73 @@ case OP_Rollback: {
break;
}
/* Opcode: ReadCookie * * *
**
** Read the magic cookie from the database file and push it onto the
** stack. The magic cookie is an integer that is used like a version
** number for the database schema. Everytime the schema changes, the
** cookie changes to a new random value. This opcode is used during
** initialization to read the initial cookie value so that subsequent
** database accesses can verify that the cookie has not changed.
**
** There must be a read-lock on the database (either a transaction
** must be started or there must be a prior OP_Open opcode) before
** executing this instruction.
*/
case OP_ReadCookie: {
int i = ++p->tos;
int aMeta[SQLITE_N_BTREE_META];
VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
rc = sqliteBtreeGetMeta(pBt, aMeta);
aStack[i].i = aMeta[1];
aStack[i].flags = STK_Int;
break;
}
/* Opcode: SetCookie P1 * *
**
** This operation changes the value of the cookie on the database.
** The new value is P1.
**
** The cookie changes its value whenever the database schema changes.
** That way, other processes can recognize when the schema has changed
** and reread it.
**
** A transaction must be started before executing this opcode.
*/
case OP_SetCookie: {
int aMeta[SQLITE_N_BTREE_META];
rc = sqliteBtreeGetMeta(pBt, aMeta);
if( rc==SQLITE_OK ){
aMeta[1] = pOp->p1;
rc = sqliteBtreeUpdateMeta(pBt, aMeta);
}
break;
}
/* Opcode: VerifyCookie P1 * *
**
** Check the current value of the database cookie and make sure it is
** equal to P1. If it is not, abort with an SQLITE_SCHEMA error.
**
** The cookie changes its value whenever the database schema changes.
** This operation is used to detech when that the cookie has changed
** and that the current process needs to reread the schema.
**
** Either a transaction needs to have been started or an OP_Open needs
** to be executed (to establish a read lock) before this opcode is
** invoked.
*/
case OP_VerifyCookie: {
int aMeta[SQLITE_N_BTREE_META];
rc = sqliteBtreeGetMeta(pBt, aMeta);
if( rc==SQLITE_OK && aMeta[1]!=pOp->p1 ){
sqliteSetString(pzErrMsg, "database schema has changed", 0);
rc = SQLITE_SCHEMA;
}
break;
}
/* Opcode: Open P1 P2 P3
**
** Open a new cursor for the database table whose root page is
@ -2013,9 +2086,8 @@ case OP_Open: {
memset(&p->aCsr[j], 0, sizeof(Cursor));
}
p->nCursor = i+1;
}else if( p->aCsr[i].pCursor ){
sqliteBtreeCloseCursor(p->aCsr[i].pCursor);
}
cleanupCursor(&p->aCsr[i]);
memset(&p->aCsr[i], 0, sizeof(Cursor));
do{
rc = sqliteBtreeCursor(pBt, p2, &p->aCsr[i].pCursor);
@ -2058,10 +2130,9 @@ case OP_OpenTemp: {
memset(&p->aCsr[j], 0, sizeof(Cursor));
}
p->nCursor = i+1;
}else if( p->aCsr[i].pCursor ){
sqliteBtreeCloseCursor(p->aCsr[i].pCursor);
}
pCx = &p->aCsr[i];
cleanupCursor(pCx);
memset(pCx, 0, sizeof(*pCx));
rc = sqliteBtreeOpen(0, 0, TEMP_PAGES, &pCx->pBt);
if( rc==SQLITE_OK ){
@ -2081,17 +2152,7 @@ case OP_OpenTemp: {
case OP_Close: {
int i = pOp->p1;
if( i>=0 && i<p->nCursor && p->aCsr[i].pCursor ){
Cursor *pCx = &p->aCsr[i];
sqliteBtreeCloseCursor(pCx->pCursor);
pCx->pCursor = 0;
if( pCx->zKey ){
sqliteFree(pCx->zKey);
pCx->zKey = 0;
}
if( pCx->pBt ){
sqliteBtreeClose(pCx->pBt);
pCx->pBt = 0;
}
cleanupCursor(&p->aCsr[i]);
}
break;
}
@ -2523,6 +2584,7 @@ case OP_BeginIdx: {
VERIFY( if( tos<0 ) goto not_enough_stack; )
if( i>=0 && i<p->nCursor && (pCrsr = &p->aCsr[i])->pCursor!=0 ){
if( Stringify(p, tos) ) goto no_mem;
if( pCrsr->zKey ) sqliteFree(pCrsr->zKey);
pCrsr->nKey = aStack[tos].n;
pCrsr->zKey = sqliteMalloc( 2*(pCrsr->nKey + 1) );
if( pCrsr->zKey==0 ) goto no_mem;

View File

@ -27,7 +27,7 @@
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h,v 1.21 2001/09/13 21:53:10 drh Exp $
** $Id: vdbe.h,v 1.22 2001/09/15 00:57:29 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@ -75,118 +75,122 @@ typedef struct VdbeOp VdbeOp;
#define OP_Commit 2
#define OP_Rollback 3
#define OP_Open 4
#define OP_OpenTemp 5
#define OP_Close 6
#define OP_MoveTo 7
#define OP_Fcnt 8
#define OP_NewRecno 9
#define OP_Put 10
#define OP_Distinct 11
#define OP_Found 12
#define OP_NotFound 13
#define OP_Delete 14
#define OP_Column 15
#define OP_KeyAsData 16
#define OP_Recno 17
#define OP_FullKey 18
#define OP_Rewind 19
#define OP_Next 20
#define OP_ReadCookie 4
#define OP_SetCookie 5
#define OP_VerifyCookie 6
#define OP_Destroy 21
#define OP_Clear 22
#define OP_CreateIndex 23
#define OP_CreateTable 24
#define OP_Reorganize 25
#define OP_Open 7
#define OP_OpenTemp 8
#define OP_Close 9
#define OP_MoveTo 10
#define OP_Fcnt 11
#define OP_NewRecno 12
#define OP_Put 13
#define OP_Distinct 14
#define OP_Found 15
#define OP_NotFound 16
#define OP_Delete 17
#define OP_Column 18
#define OP_KeyAsData 19
#define OP_Recno 20
#define OP_FullKey 21
#define OP_Rewind 22
#define OP_Next 23
#define OP_BeginIdx 26
#define OP_NextIdx 27
#define OP_PutIdx 28
#define OP_DeleteIdx 29
#define OP_Destroy 24
#define OP_Clear 25
#define OP_CreateIndex 26
#define OP_CreateTable 27
#define OP_Reorganize 28
#define OP_MemLoad 30
#define OP_MemStore 31
#define OP_BeginIdx 29
#define OP_NextIdx 30
#define OP_PutIdx 31
#define OP_DeleteIdx 32
#define OP_ListOpen 32
#define OP_ListWrite 33
#define OP_ListRewind 34
#define OP_ListRead 35
#define OP_ListClose 36
#define OP_MemLoad 33
#define OP_MemStore 34
#define OP_SortOpen 37
#define OP_SortPut 38
#define OP_SortMakeRec 39
#define OP_SortMakeKey 40
#define OP_Sort 41
#define OP_SortNext 42
#define OP_SortKey 43
#define OP_SortCallback 44
#define OP_SortClose 45
#define OP_ListOpen 35
#define OP_ListWrite 36
#define OP_ListRewind 37
#define OP_ListRead 38
#define OP_ListClose 39
#define OP_FileOpen 46
#define OP_FileRead 47
#define OP_FileColumn 48
#define OP_FileClose 49
#define OP_SortOpen 40
#define OP_SortPut 41
#define OP_SortMakeRec 42
#define OP_SortMakeKey 43
#define OP_Sort 44
#define OP_SortNext 45
#define OP_SortKey 46
#define OP_SortCallback 47
#define OP_SortClose 48
#define OP_AggReset 50
#define OP_AggFocus 51
#define OP_AggIncr 52
#define OP_AggNext 53
#define OP_AggSet 54
#define OP_AggGet 55
#define OP_FileOpen 49
#define OP_FileRead 50
#define OP_FileColumn 51
#define OP_FileClose 52
#define OP_SetInsert 56
#define OP_SetFound 57
#define OP_SetNotFound 58
#define OP_SetClear 59
#define OP_AggReset 53
#define OP_AggFocus 54
#define OP_AggIncr 55
#define OP_AggNext 56
#define OP_AggSet 57
#define OP_AggGet 58
#define OP_MakeRecord 60
#define OP_MakeKey 61
#define OP_MakeIdxKey 62
#define OP_SetInsert 59
#define OP_SetFound 60
#define OP_SetNotFound 61
#define OP_SetClear 62
#define OP_Goto 63
#define OP_If 64
#define OP_Halt 65
#define OP_MakeRecord 63
#define OP_MakeKey 64
#define OP_MakeIdxKey 65
#define OP_ColumnCount 66
#define OP_ColumnName 67
#define OP_Callback 68
#define OP_Goto 66
#define OP_If 67
#define OP_Halt 68
#define OP_Integer 69
#define OP_String 70
#define OP_Null 71
#define OP_Pop 72
#define OP_Dup 73
#define OP_Pull 74
#define OP_ColumnCount 69
#define OP_ColumnName 70
#define OP_Callback 71
#define OP_Add 75
#define OP_AddImm 76
#define OP_Subtract 77
#define OP_Multiply 78
#define OP_Divide 79
#define OP_Min 80
#define OP_Max 81
#define OP_Like 82
#define OP_Glob 83
#define OP_Eq 84
#define OP_Ne 85
#define OP_Lt 86
#define OP_Le 87
#define OP_Gt 88
#define OP_Ge 89
#define OP_IsNull 90
#define OP_NotNull 91
#define OP_Negative 92
#define OP_And 93
#define OP_Or 94
#define OP_Not 95
#define OP_Concat 96
#define OP_Noop 97
#define OP_Integer 72
#define OP_String 73
#define OP_Null 74
#define OP_Pop 75
#define OP_Dup 76
#define OP_Pull 77
#define OP_Strlen 98
#define OP_Substr 99
#define OP_Add 78
#define OP_AddImm 79
#define OP_Subtract 80
#define OP_Multiply 81
#define OP_Divide 82
#define OP_Min 83
#define OP_Max 84
#define OP_Like 85
#define OP_Glob 86
#define OP_Eq 87
#define OP_Ne 88
#define OP_Lt 89
#define OP_Le 90
#define OP_Gt 91
#define OP_Ge 92
#define OP_IsNull 93
#define OP_NotNull 94
#define OP_Negative 95
#define OP_And 96
#define OP_Or 97
#define OP_Not 98
#define OP_Concat 99
#define OP_Noop 100
#define OP_MAX 99
#define OP_Strlen 101
#define OP_Substr 102
#define OP_MAX 102
/*
** Prototypes for the VDBE interface. See comments on the implementation

View File

@ -25,7 +25,7 @@
** the WHERE clause of SQL statements. Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.18 2001/09/13 16:18:55 drh Exp $
** $Id: where.c,v 1.19 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"
@ -299,6 +299,11 @@ WhereInfo *sqliteWhereBegin(
for(i=0; i<pTabList->nId; i++){
sqliteVdbeAddOp(v, OP_Open, base+i, pTabList->a[i].pTab->tnum,
pTabList->a[i].pTab->zName, 0);
if( i==0 && !pParse->schemaVerified &&
(pParse->db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0, 0, 0);
pParse->schemaVerified = 1;
}
if( i<ARRAYSIZE(aIdx) && aIdx[i]!=0 ){
sqliteVdbeAddOp(v, OP_Open, base+pTabList->nId+i, aIdx[i]->tnum,
aIdx[i]->zName, 0);