1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Parse foreign key constraints and populate internal data structures

appropriately.  Constraints are still not enforced. (CVS 738)

FossilOrigin-Name: 170711ca65dc894d0486b9d575edb8f1708250fb
This commit is contained in:
drh
2002-08-31 18:53:06 +00:00
parent b680a344e5
commit c2eef3b32b
13 changed files with 527 additions and 174 deletions

View File

@@ -1,5 +1,5 @@
C Version\s2.7.1\s(CVS\s737) C Parse\sforeign\skey\sconstraints\sand\spopulate\sinternal\sdata\sstructures\nappropriately.\s\sConstraints\sare\sstill\snot\senforced.\s(CVS\s738)
D 2002-08-31T17:02:43 D 2002-08-31T18:53:06
F Makefile.in 420fada882179cb72ffd07313f3fd693f9f06640 F Makefile.in 420fada882179cb72ffd07313f3fd693f9f06640
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -20,7 +20,7 @@ F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
F src/btree.c 9e21606581a5a4a5b18ad304d7a4f433101f1538 F src/btree.c 9e21606581a5a4a5b18ad304d7a4f433101f1538
F src/btree.h 0ca6c2631338df62e4f7894252d9347ae234eda9 F src/btree.h 0ca6c2631338df62e4f7894252d9347ae234eda9
F src/build.c b367b4a839f978c0225d984e327287852835948e F src/build.c 0116afe4f67687206364c4d1e88dc07aefc661de
F src/delete.c c9f59ee217e062eb9de7b64b76b5cfff42b2f028 F src/delete.c c9f59ee217e062eb9de7b64b76b5cfff42b2f028
F src/encode.c 346b12b46148506c32038524b95c4631ab46d760 F src/encode.c 346b12b46148506c32038524b95c4631ab46d760
F src/expr.c ee027b908a1e157fc21644121811fa6ec1eec798 F src/expr.c ee027b908a1e157fc21644121811fa6ec1eec798
@@ -28,25 +28,25 @@ F src/func.c e45cd908b9b723d9b91473d09e12c23f786b3fc2
F src/hash.c 6a6236b89c8c060c65dabd300a1c8ce7c10edb72 F src/hash.c 6a6236b89c8c060c65dabd300a1c8ce7c10edb72
F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8 F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
F src/insert.c a2f5455009904476b43ec5304a181b505235f72f F src/insert.c a2f5455009904476b43ec5304a181b505235f72f
F src/main.c 26a31201133c93b6065e11b49a83f5b987642e96 F src/main.c 46d6a88070974360918cdfd1241b1906c6e189ce
F src/md5.c 0ae1f3e2cac92d06fc6246d1b4b8f61a2fe66d3b F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
F src/os.c 00d10655e1dc9a52b4aabca58c8d8e45048057b0 F src/os.c 00d10655e1dc9a52b4aabca58c8d8e45048057b0
F src/os.h 3009379b06941e7796a9812d1b6cbc59b26248c8 F src/os.h 3009379b06941e7796a9812d1b6cbc59b26248c8
F src/pager.c 4b0169e91b34f6ff91e8feb57545c43e4d6eb370 F src/pager.c 4b0169e91b34f6ff91e8feb57545c43e4d6eb370
F src/pager.h 6991c9c2dc5e4c7f2df4d4ba47d1c6458f763a32 F src/pager.h 6991c9c2dc5e4c7f2df4d4ba47d1c6458f763a32
F src/parse.y 1b180e14b6346e323bd4279469748716f412cc1c F src/parse.y 818b03a73f6b3b8b284b515c5b1d9998d4663dc3
F src/printf.c 5c50fc1da75c8f5bf432b1ad17d91d6653acd167 F src/printf.c 5c50fc1da75c8f5bf432b1ad17d91d6653acd167
F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
F src/select.c 6cd3673edbb36a8f8027341093085e01c04dd3d4 F src/select.c 6cd3673edbb36a8f8027341093085e01c04dd3d4
F src/shell.c 9e9a6eb6bca07f01e6472a603f908a0127ea50ff F src/shell.c 9e9a6eb6bca07f01e6472a603f908a0127ea50ff
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in d3999a9c6374675779058d6cfe5431131618e92b F src/sqlite.h.in d3999a9c6374675779058d6cfe5431131618e92b
F src/sqliteInt.h 4d42c8685693ecf9d99edf52c9a404da2b2df7fd F src/sqliteInt.h 62177a08d332148b1d69cd040840aac45ad86a42
F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63 F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63
F src/tclsqlite.c c502819c209011659e1bbb428cbac5670cce7f79 F src/tclsqlite.c e6c6de6ce41614b9ae82161ed998308070a5790d
F src/test1.c 456cb080db85056be723e770435d9509afc3a83a F src/test1.c a46e9f61915b32787c5d5a05a4b92e4dacc437d9
F src/test2.c 279057a854359665b89122070ac1fc472acce1b2 F src/test2.c 5fa694d130b3309e3f9c852f0a437750fcb5a006
F src/test3.c b99d5ab68ee672f1fbb00520723b5c21bac35822 F src/test3.c 540fa7fc3cb3732517b779b5f90ad9cc4303d0ab
F src/threadtest.c 72bce0a284647314847bbea44616ceb056bfb77f F src/threadtest.c 72bce0a284647314847bbea44616ceb056bfb77f
F src/tokenize.c 62c98842447effe92eba9622bb2f9a2a8a4b97ad F src/tokenize.c 62c98842447effe92eba9622bb2f9a2a8a4b97ad
F src/trigger.c c90a292a4bef25e478fd5deda6d300319be6a023 F src/trigger.c c90a292a4bef25e478fd5deda6d300319be6a023
@@ -64,6 +64,7 @@ F test/conflict.test 0173a12a257f73bac2c9d53ad44cac9b15ea517e
F test/copy.test 55d60a4d5ed342a0fa08b7cd07d46d43ea0d0d7f F test/copy.test 55d60a4d5ed342a0fa08b7cd07d46d43ea0d0d7f
F test/delete.test 5821a95a66061ae09723a88938f23d10d8a881ad F test/delete.test 5821a95a66061ae09723a88938f23d10d8a881ad
F test/expr.test dea1cd62684a8bf116426447c948f5e8fb2c84b6 F test/expr.test dea1cd62684a8bf116426447c948f5e8fb2c84b6
F test/fkey1.test 33c850201a6ec35f0b370daf4e57f44456f1b35d
F test/format3.test cbb168d446152fcf1dd85be299ad2d6cd507da4e F test/format3.test cbb168d446152fcf1dd85be299ad2d6cd507da4e
F test/func.test bed7ae7a3482df05db0f5eed2debdf25ac2d07fc F test/func.test bed7ae7a3482df05db0f5eed2debdf25ac2d07fc
F test/in.test e59461f1702b7387880bf08a0ce6bb777925d282 F test/in.test e59461f1702b7387880bf08a0ce6bb777925d282
@@ -97,7 +98,7 @@ F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac
F test/select6.test efb8d0c07a440441db87db2c4ade6904e1407e85 F test/select6.test efb8d0c07a440441db87db2c4ade6904e1407e85
F test/sort.test 876b76c5a837af5bead713146c7c65f85e84fbf5 F test/sort.test 876b76c5a837af5bead713146c7c65f85e84fbf5
F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f
F test/table.test dedb4d3a73340d811e309672ca14537daa542fb1 F test/table.test 10508e5e53fb7971b9fa6acb29d85748e545745c
F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6 F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6
F test/tclsqlite.test 6f4b9760681c7dbca52a18d0ab46a1679cdc79b9 F test/tclsqlite.test 6f4b9760681c7dbca52a18d0ab46a1679cdc79b9
F test/temptable.test 9ed7ec0288f887e132de66d90c428ad109105f67 F test/temptable.test 9ed7ec0288f887e132de66d90c428ad109105f67
@@ -149,7 +150,7 @@ F www/speed.tcl a20a792738475b68756ea7a19321600f23d1d803
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
P b7f788fcc4a26ae42196a209d2e94672321dc154 P 5f51e13d56a58d7c263043cae9898d796017a369
R c5c569997115d1f2c07a9211654c4fdd R 5f57a541da1cc0eea6b8b3a2339bca70
U drh U drh
Z 53b53adb384374736e4596208d092298 Z 53eaaf70a55382e9bd46cf1caade9346

View File

@@ -1 +1 @@
5f51e13d56a58d7c263043cae9898d796017a369 170711ca65dc894d0486b9d575edb8f1708250fb

View File

@@ -25,7 +25,7 @@
** ROLLBACK ** ROLLBACK
** PRAGMA ** PRAGMA
** **
** $Id: build.c,v 1.110 2002/08/24 18:24:53 drh Exp $ ** $Id: build.c,v 1.111 2002/08/31 18:53:06 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -152,6 +152,7 @@ void sqliteResetInternalSchema(sqlite *db){
Hash temp1; Hash temp1;
Hash temp2; Hash temp2;
sqliteHashClear(&db->aFKey);
temp1 = db->tblHash; temp1 = db->tblHash;
temp2 = db->trigHash; temp2 = db->trigHash;
sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0);
@@ -194,8 +195,10 @@ void sqliteCommitInternalChanges(sqlite *db){
** Table. No changes are made to disk by this routine. ** Table. No changes are made to disk by this routine.
** **
** This routine just deletes the data structure. It does not unlink ** This routine just deletes the data structure. It does not unlink
** the table data structure from the hash table. But it does destroy ** the table data structure from the hash table. Nor does it remove
** memory structures of the indices associated with the table. ** foreign keys from the sqlite.aFKey hash table. But it does destroy
** memory structures of the indices and foreign keys associated with
** the table.
** **
** Indices associated with the table are unlinked from the "db" ** Indices associated with the table are unlinked from the "db"
** data structure if db!=NULL. If db==NULL, indices attached to ** data structure if db!=NULL. If db==NULL, indices attached to
@@ -205,16 +208,33 @@ void sqliteCommitInternalChanges(sqlite *db){
void sqliteDeleteTable(sqlite *db, Table *pTable){ void sqliteDeleteTable(sqlite *db, Table *pTable){
int i; int i;
Index *pIndex, *pNext; Index *pIndex, *pNext;
FKey *pFKey, *pNextFKey;
if( pTable==0 ) return; if( pTable==0 ) return;
/* Delete all indices associated with this table
*/
for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
pNext = pIndex->pNext;
sqliteDeleteIndex(db, pIndex);
}
/* Delete all foreign keys associated with this table. The keys
** should have already been unlinked from the db->aFKey hash table
*/
for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){
pNextFKey = pFKey->pNextFrom;
assert( sqliteHashFind(&db->aFKey,pFKey->zTo,strlen(pFKey->zTo)+1)!=pFKey );
sqliteFree(pFKey);
}
/* Delete the Table structure itself.
*/
for(i=0; i<pTable->nCol; i++){ for(i=0; i<pTable->nCol; i++){
sqliteFree(pTable->aCol[i].zName); sqliteFree(pTable->aCol[i].zName);
sqliteFree(pTable->aCol[i].zDflt); sqliteFree(pTable->aCol[i].zDflt);
sqliteFree(pTable->aCol[i].zType); sqliteFree(pTable->aCol[i].zType);
} }
for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
pNext = pIndex->pNext;
sqliteDeleteIndex(db, pIndex);
}
sqliteFree(pTable->zName); sqliteFree(pTable->zName);
sqliteFree(pTable->aCol); sqliteFree(pTable->aCol);
sqliteSelectDelete(pTable->pSelect); sqliteSelectDelete(pTable->pSelect);
@@ -223,13 +243,26 @@ void sqliteDeleteTable(sqlite *db, Table *pTable){
/* /*
** Unlink the given table from the hash tables and the delete the ** Unlink the given table from the hash tables and the delete the
** table structure with all its indices. ** table structure with all its indices and foreign keys.
*/ */
static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){ static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){
Table *pOld; Table *pOld;
FKey *pF1, *pF2;
assert( db!=0 ); assert( db!=0 );
pOld = sqliteHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, 0); pOld = sqliteHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, 0);
assert( pOld==0 || pOld==p ); assert( pOld==0 || pOld==p );
for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
int nTo = strlen(pF1->zTo) + 1;
pF2 = sqliteHashFind(&db->aFKey, pF1->zTo, nTo);
if( pF2==pF1 ){
sqliteHashInsert(&db->aFKey, pF1->zTo, nTo, pF1->pNextTo);
}else{
while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
if( pF2 ){
pF2->pNextTo = pF1->pNextTo;
}
}
}
sqliteDeleteTable(db, p); sqliteDeleteTable(db, p);
} }
@@ -739,11 +772,17 @@ void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
assert( pParse->nameClash==0 || pParse->initFlag==1 ); assert( pParse->nameClash==0 || pParse->initFlag==1 );
if( pParse->explain==0 && pParse->nameClash==0 ){ if( pParse->explain==0 && pParse->nameClash==0 ){
Table *pOld; Table *pOld;
FKey *pFKey;
pOld = sqliteHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, p); pOld = sqliteHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, p);
if( pOld ){ if( pOld ){
assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
return; return;
} }
for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){
int nTo = strlen(pFKey->zTo) + 1;
pFKey->pNextTo = sqliteHashFind(&db->aFKey, pFKey->zTo, nTo);
sqliteHashInsert(&db->aFKey, pFKey->zTo, nTo, pFKey);
}
pParse->pNewTable = 0; pParse->pNewTable = 0;
db->nTable++; db->nTable++;
db->flags |= SQLITE_InternChanges; db->flags |= SQLITE_InternChanges;
@@ -1141,6 +1180,137 @@ void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){
sqliteFree(zType); sqliteFree(zType);
} }
/*
** This routine is called to create a new foreign key on the table
** currently under construction. pFromCol determines which columns
** in the current table point to the foreign key. If pFromCol==0 then
** connect the key to the last column inserted. pTo is the name of
** the table referred to. pToCol is a list of tables in the other
** pTo table that the foreign key points to. flags contains all
** information about the conflict resolution algorithms specified
** in the ON DELETE, ON UPDATE and ON INSERT clauses.
**
** An FKey structure is created and added to the table currently
** under construction in the pParse->pNewTable field. The new FKey
** is not linked into db->aFKey at this point - that does not happen
** until sqliteEndTable().
**
** The foreign key is set for IMMEDIATE processing. A subsequent call
** to sqliteDeferForeignKey() might change this to DEFERRED.
*/
void sqliteCreateForeignKey(
Parse *pParse, /* Parsing context */
IdList *pFromCol, /* Columns in this table that point to other table */
Token *pTo, /* Name of the other table */
IdList *pToCol, /* Columns in the other table */
int flags /* Conflict resolution algorithms. */
){
Table *p = pParse->pNewTable;
int nByte;
int i;
int nCol;
char *z;
FKey *pFKey = 0;
assert( pTo!=0 );
if( p==0 || pParse->nErr ) goto fk_end;
if( pFromCol==0 ){
int iCol = p->nCol-1;
if( iCol<0 ) goto fk_end;
if( pToCol && pToCol->nId!=1 ){
sqliteSetNString(&pParse->zErrMsg, "foreign key on ", -1,
p->aCol[iCol].zName, -1,
" should reference only one column of table ", -1,
pTo->z, pTo->n, 0);
pParse->nErr++;
goto fk_end;
}
nCol = 1;
}else if( pToCol && pToCol->nId!=pFromCol->nId ){
sqliteSetString(&pParse->zErrMsg,
"number of columns in foreign key does not match the number of "
"columns in the referenced table", 0);
pParse->nErr++;
goto fk_end;
}else{
nCol = pFromCol->nId;
}
nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1;
if( pToCol ){
for(i=0; i<pToCol->nId; i++){
nByte += strlen(pToCol->a[i].zName) + 1;
}
}
pFKey = sqliteMalloc( nByte );
if( pFKey==0 ) goto fk_end;
pFKey->pFrom = p;
pFKey->pNextFrom = p->pFKey;
pFKey->zTo = z = (char*)&pFKey[1];
memcpy(z, pTo->z, pTo->n);
z[pTo->n] = 0;
z += pTo->n+1;
pFKey->pNextTo = 0;
pFKey->nCol = nCol;
pFKey->aCol = (struct sColMap*)z;
z += sizeof(struct sColMap)*nCol;
if( pFromCol==0 ){
pFKey->aCol[0].iFrom = p->nCol-1;
}else{
for(i=0; i<nCol; i++){
int j;
for(j=0; j<p->nCol; j++){
if( sqliteStrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){
pFKey->aCol[i].iFrom = j;
break;
}
}
if( j>=p->nCol ){
sqliteSetString(&pParse->zErrMsg, "unknown column \"",
pFromCol->a[i].zName, "\" in foreign key definition", 0);
pParse->nErr++;
goto fk_end;
}
}
}
if( pToCol ){
for(i=0; i<nCol; i++){
int n = strlen(pToCol->a[i].zName);
pFKey->aCol[i].zCol = z;
memcpy(z, pToCol->a[i].zName, n);
z[n] = 0;
z += n+1;
}
}
pFKey->isDeferred = 0;
pFKey->deleteConf = flags & 0xff;
pFKey->updateConf = (flags >> 8 ) & 0xff;
pFKey->insertConf = (flags >> 16 ) & 0xff;
/* Link the foreign key to the table as the last step.
*/
p->pFKey = pFKey;
pFKey = 0;
fk_end:
sqliteFree(pFKey);
sqliteIdListDelete(pFromCol);
sqliteIdListDelete(pToCol);
}
/*
** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED
** clause is seen as part of a foreign key definition. The isDeferred
** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE.
** The behavior of the most recently created foreign key is adjusted
** accordingly.
*/
void sqliteDeferForeignKey(Parse *pParse, int isDeferred){
Table *pTab;
FKey *pFKey;
if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
pFKey->isDeferred = isDeferred;
}
/* /*
** Create a new index for an SQL table. pIndex is the name of the index ** Create a new index for an SQL table. pIndex is the name of the index
** and pTable is the name of the table that is to be indexed. Both will ** and pTable is the name of the table that is to be indexed. Both will

View File

@@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be ** other files are for internal use by SQLite and should not be
** accessed by users of the library. ** accessed by users of the library.
** **
** $Id: main.c,v 1.99 2002/08/29 23:59:48 drh Exp $ ** $Id: main.c,v 1.100 2002/08/31 18:53:06 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "os.h" #include "os.h"
@@ -354,6 +354,7 @@ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1); sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1);
sqliteHashInit(&db->aFKey, SQLITE_HASH_STRING, 1);
sqliteRegisterBuiltinFunctions(db); sqliteRegisterBuiltinFunctions(db);
db->onError = OE_Default; db->onError = OE_Default;
db->priorNewRowid = 0; db->priorNewRowid = 0;
@@ -466,6 +467,7 @@ void sqlite_close(sqlite *db){
} }
} }
sqliteHashClear(&db->aFunc); sqliteHashClear(&db->aFunc);
sqliteHashClear(&db->aFKey);
sqliteFree(db); sqliteFree(db);
} }

View File

@@ -293,7 +293,7 @@ static void DigestToBase16(unsigned char *digest, char *zBuf){
** A TCL command for md5. The argument is the text to be hashed. The ** A TCL command for md5. The argument is the text to be hashed. The
** Result is the hash in base64. ** Result is the hash in base64.
*/ */
static int md5_cmd(ClientData cd, Tcl_Interp *interp, int argc, char **argv){ static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv){
MD5Context ctx; MD5Context ctx;
unsigned char digest[16]; unsigned char digest[16];
@@ -313,7 +313,7 @@ static int md5_cmd(ClientData cd, Tcl_Interp *interp, int argc, char **argv){
** A TCL command to take the md5 hash of a file. The argument is the ** A TCL command to take the md5 hash of a file. The argument is the
** name of the file. ** name of the file.
*/ */
static int md5file_cmd(ClientData cd, Tcl_Interp*interp, int argc, char **argv){ static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv){
FILE *in; FILE *in;
MD5Context ctx; MD5Context ctx;
unsigned char digest[16]; unsigned char digest[16];
@@ -347,8 +347,8 @@ static int md5file_cmd(ClientData cd, Tcl_Interp*interp, int argc, char **argv){
** Register the two TCL commands above with the TCL interpreter. ** Register the two TCL commands above with the TCL interpreter.
*/ */
int Md5_Init(Tcl_Interp *interp){ int Md5_Init(Tcl_Interp *interp){
Tcl_CreateCommand(interp, "md5", md5_cmd, 0, 0); Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd, 0, 0);
Tcl_CreateCommand(interp, "md5file", md5file_cmd, 0, 0); Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd, 0, 0);
return TCL_OK; return TCL_OK;
} }

View File

@@ -14,7 +14,7 @@
** the parser. Lemon will also generate a header file containing ** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens. ** numeric codes for all of the tokens.
** **
** @(#) $Id: parse.y,v 1.82 2002/08/24 18:24:54 drh Exp $ ** @(#) $Id: parse.y,v 1.83 2002/08/31 18:53:07 drh Exp $
*/ */
%token_prefix TK_ %token_prefix TK_
%token_type {Token} %token_type {Token}
@@ -169,31 +169,38 @@ ccons ::= NOT NULL onconf(R). {sqliteAddNotNull(pParse, R);}
ccons ::= PRIMARY KEY sortorder onconf(R). {sqliteAddPrimaryKey(pParse,0,R);} ccons ::= PRIMARY KEY sortorder onconf(R). {sqliteAddPrimaryKey(pParse,0,R);}
ccons ::= UNIQUE onconf(R). {sqliteCreateIndex(pParse,0,0,0,R,0,0);} ccons ::= UNIQUE onconf(R). {sqliteCreateIndex(pParse,0,0,0,R,0,0);}
ccons ::= CHECK LP expr RP onconf. ccons ::= CHECK LP expr RP onconf.
ccons ::= references. ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
ccons ::= defer_subclause. {sqliteCreateForeignKey(pParse,0,&T,TA,R);}
ccons ::= defer_subclause(D). {sqliteDeferForeignKey(pParse,D);}
ccons ::= COLLATE id(C). { ccons ::= COLLATE id(C). {
sqliteAddCollateType(pParse, sqliteCollateType(pParse, &C)); sqliteAddCollateType(pParse, sqliteCollateType(pParse, &C));
} }
// A REFERENCES clause is parsed but the current implementation does not // The next group of rules parses the arguments to a REFERENCES clause
// do anything with it. // that determine if the referential integrity checking is deferred or
// or immediate and which determine what action to take if a ref-integ
// check fails.
// //
references ::= REFERENCES nm LP idxlist RP refargs. %type refargs {int}
references ::= REFERENCES nm refargs. refargs(A) ::= . { A = OE_Restrict * 0x010101; }
refargs ::= . refargs(A) ::= refargs(X) refarg(Y). { A = (X & Y.mask) | Y.value; }
refargs ::= refargs refarg. %type refarg {struct {int value; int mask;}}
refarg ::= MATCH nm. refarg(A) ::= MATCH nm. { A.value = 0; A.mask = 0x000000; }
refarg ::= ON DELETE refact. refarg(A) ::= ON DELETE refact(X). { A.value = X; A.mask = 0x0000ff; }
refarg ::= ON UPDATE refact. refarg(A) ::= ON UPDATE refact(X). { A.value = X<<8; A.mask = 0x00ff00; }
refact ::= SET NULL. refarg(A) ::= ON INSERT refact(X). { A.value = X<<16; A.mask = 0xff0000; }
refact ::= SET DEFAULT. %type refact {int}
refact ::= CASCADE. refact(A) ::= SET NULL. { A = OE_SetNull; }
refact ::= RESTRICT. refact(A) ::= SET DEFAULT. { A = OE_SetDflt; }
defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt. refact(A) ::= CASCADE. { A = OE_Cascade; }
defer_subclause ::= DEFERRABLE init_deferred_pred_opt. refact(A) ::= RESTRICT. { A = OE_Restrict; }
init_deferred_pred_opt ::= . %type defer_subclause {int}
init_deferred_pred_opt ::= INITIALLY DEFERRED. defer_subclause(A) ::= NOT DEFERRABLE init_deferred_pred_opt(X). {A = X;}
init_deferred_pred_opt ::= INITIALLY IMMEDIATE. defer_subclause(A) ::= DEFERRABLE init_deferred_pred_opt(X). {A = X;}
%type init_deferred_pred_opt {int}
init_deferred_pred_opt(A) ::= . {A = 0;}
init_deferred_pred_opt(A) ::= INITIALLY DEFERRED. {A = 1;}
init_deferred_pred_opt(A) ::= INITIALLY IMMEDIATE. {A = 0;}
// For the time being, the only constraint we care about is the primary // For the time being, the only constraint we care about is the primary
// key and UNIQUE. Both create indices. // key and UNIQUE. Both create indices.
@@ -209,9 +216,14 @@ tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R).
tcons ::= UNIQUE LP idxlist(X) RP onconf(R). tcons ::= UNIQUE LP idxlist(X) RP onconf(R).
{sqliteCreateIndex(pParse,0,0,X,R,0,0);} {sqliteCreateIndex(pParse,0,0,X,R,0,0);}
tcons ::= CHECK expr onconf. tcons ::= CHECK expr onconf.
tcons ::= FOREIGN KEY LP idxlist RP references defer_subclause_opt. tcons ::= FOREIGN KEY LP idxlist(FA) RP
defer_subclause_opt ::= . REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). {
defer_subclause_opt ::= defer_subclause. sqliteCreateForeignKey(pParse, FA, &T, TA, R);
sqliteDeferForeignKey(pParse, D);
}
%type defer_subclause_opt {int}
defer_subclause_opt(A) ::= . {A = 0;}
defer_subclause_opt(A) ::= defer_subclause(X). {A = X;}
// The following is a non-standard extension that allows us to declare the // The following is a non-standard extension that allows us to declare the
// default behavior when there is a constraint conflict. // default behavior when there is a constraint conflict.
@@ -677,13 +689,15 @@ uniqueflag(A) ::= . { A = OE_None; }
%type idxlist {IdList*} %type idxlist {IdList*}
%destructor idxlist {sqliteIdListDelete($$);} %destructor idxlist {sqliteIdListDelete($$);}
%type idxlist_opt {IdList*}
%destructor idxlist_opt {sqliteIdListDelete($$);}
%type idxitem {Token} %type idxitem {Token}
idxlist(A) ::= idxlist(X) COMMA idxitem(Y). idxlist_opt(A) ::= . {A = 0;}
{A = sqliteIdListAppend(X,&Y);} idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;}
idxlist(A) ::= idxitem(Y). idxlist(A) ::= idxlist(X) COMMA idxitem(Y). {A = sqliteIdListAppend(X,&Y);}
{A = sqliteIdListAppend(0,&Y);} idxlist(A) ::= idxitem(Y). {A = sqliteIdListAppend(0,&Y);}
idxitem(A) ::= nm(X). {A = X;} idxitem(A) ::= nm(X). {A = X;}
///////////////////////////// The DROP INDEX command ///////////////////////// ///////////////////////////// The DROP INDEX command /////////////////////////
// //

View File

@@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** Internal interface definitions for SQLite.
** **
** @(#) $Id: sqliteInt.h,v 1.144 2002/08/28 03:00:59 drh Exp $ ** @(#) $Id: sqliteInt.h,v 1.145 2002/08/31 18:53:07 drh Exp $
*/ */
#include "sqlite.h" #include "sqlite.h"
#include "hash.h" #include "hash.h"
@@ -175,6 +175,7 @@ typedef struct FuncDef FuncDef;
typedef struct Trigger Trigger; typedef struct Trigger Trigger;
typedef struct TriggerStep TriggerStep; typedef struct TriggerStep TriggerStep;
typedef struct TriggerStack TriggerStack; typedef struct TriggerStack TriggerStack;
typedef struct FKey FKey;
/* /*
** Each database is an instance of the following structure. ** Each database is an instance of the following structure.
@@ -206,6 +207,7 @@ struct sqlite {
Hash idxHash; /* All (named) indices indexed by name */ Hash idxHash; /* All (named) indices indexed by name */
Hash trigHash; /* All triggers indexed by name */ Hash trigHash; /* All triggers indexed by name */
Hash aFunc; /* All functions that can be in SQL exprs */ Hash aFunc; /* All functions that can be in SQL exprs */
Hash aFKey; /* Foreign keys indexed by to-table */
int lastRowid; /* ROWID of most recent insert */ int lastRowid; /* ROWID of most recent insert */
int priorNewRowid; /* Last randomly generated ROWID */ int priorNewRowid; /* Last randomly generated ROWID */
int onError; /* Default conflict algorithm */ int onError; /* Default conflict algorithm */
@@ -330,10 +332,52 @@ struct Table {
u8 hasPrimKey; /* True if there exists a primary key */ u8 hasPrimKey; /* True if there exists a primary key */
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
Trigger *pTrigger; /* List of SQL triggers on this table */ Trigger *pTrigger; /* List of SQL triggers on this table */
FKey *pFKey; /* Linked list of all foreign keys in this table */
}; };
/* /*
** SQLite supports 5 different ways to resolve a contraint ** Each foreign key constraint is an instance of the following structure.
**
** A foreign key is associated with two tables. The "from" table is
** the table that contains the REFERENCES clause that creates the foreign
** key. The "to" table is the table that is named in the REFERENCES clause.
** Consider this example:
**
** CREATE TABLE ex1(
** a INTEGER PRIMARY KEY,
** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x)
** );
**
** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2".
**
** Each REFERENCES clause generates an instance of the following structure
** which is attached to the from-table. The to-table need not exist when
** the from-table is created. The existance of the to-table is not checked
** until an attempt is made to insert data into the from-table.
**
** The sqlite.aFKey hash table stores pointers to to this structure
** given the name of a to-table. For each to-table, all foreign keys
** associated with that table are on a linked list using the FKey.pNextTo
** field.
*/
struct FKey {
Table *pFrom; /* The table that constains the REFERENCES clause */
FKey *pNextFrom; /* Next foreign key in pFrom */
char *zTo; /* Name of table that the key points to */
FKey *pNextTo; /* Next foreign key that points to zTo */
int nCol; /* Number of columns in this key */
struct sColMap { /* Mapping of columns in pFrom to columns in zTo */
int iFrom; /* Index of column in pFrom */
char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */
} *aCol; /* One entry for each of nCol column s */
u8 isDeferred; /* True if constraint checking is deferred till COMMIT */
u8 updateConf; /* How to resolve conflicts that occur on UPDATE */
u8 deleteConf; /* How to resolve conflicts that occur on DELETE */
u8 insertConf; /* How to resolve conflicts that occur on INSERT */
};
/*
** SQLite supports many different ways to resolve a contraint
** error. ROLLBACK processing means that a constraint violation ** error. ROLLBACK processing means that a constraint violation
** causes the operation in process to fail and for the current transaction ** causes the operation in process to fail and for the current transaction
** to be rolled back. ABORT processing means the operation in process ** to be rolled back. ABORT processing means the operation in process
@@ -346,6 +390,13 @@ struct Table {
** is returned. REPLACE means that preexisting database rows that caused ** is returned. REPLACE means that preexisting database rows that caused
** a UNIQUE constraint violation are removed so that the new insert or ** a UNIQUE constraint violation are removed so that the new insert or
** update can proceed. Processing continues and no error is reported. ** update can proceed. Processing continues and no error is reported.
**
** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys.
** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the
** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign
** key is set to NULL. CASCADE means that a DELETE or UPDATE of the
** referenced table row is propagated into the row that holds the
** foreign key.
** **
** The following there symbolic values are used to record which type ** The following there symbolic values are used to record which type
** of action to take. ** of action to take.
@@ -356,7 +407,13 @@ struct Table {
#define OE_Fail 3 /* Stop the operation but leave all prior changes */ #define OE_Fail 3 /* Stop the operation but leave all prior changes */
#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ #define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */
#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ #define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */
#define OE_Default 9 /* Do whatever the default action is */
#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
#define OE_SetNull 7 /* Set the foreign key value to NULL */
#define OE_SetDflt 8 /* Set the foreign key value to its default */
#define OE_Cascade 9 /* Cascade the changes */
#define OE_Default 99 /* Do whatever the default action is */
/* /*
** Each SQL index is represented in memory by an ** Each SQL index is represented in memory by an
@@ -947,3 +1004,5 @@ TriggerStep *sqliteTriggerUpdateStep(Token*, ExprList*, Expr*, int);
TriggerStep *sqliteTriggerDeleteStep(Token*, Expr*); TriggerStep *sqliteTriggerDeleteStep(Token*, Expr*);
void sqliteDeleteTrigger(Trigger*); void sqliteDeleteTrigger(Trigger*);
int sqliteJoinType(Parse*, Token*, Token*, Token*); int sqliteJoinType(Parse*, Token*, Token*, Token*);
void sqliteCreateForeignKey(Parse*, IdList*, Token*, IdList*, int);
void sqliteDeferForeignKey(Parse*, int);

View File

@@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** A TCL Interface to SQLite ** A TCL Interface to SQLite
** **
** $Id: tclsqlite.c,v 1.39 2002/07/15 20:58:48 drh Exp $ ** $Id: tclsqlite.c,v 1.40 2002/08/31 18:53:08 drh Exp $
*/ */
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
@@ -643,13 +643,13 @@ static int DbMain(void *cd, Tcl_Interp *interp, int argc, char **argv){
*/ */
int Sqlite_Init(Tcl_Interp *interp){ int Sqlite_Init(Tcl_Interp *interp){
Tcl_InitStubs(interp, "8.0", 0); Tcl_InitStubs(interp, "8.0", 0);
Tcl_CreateCommand(interp, "sqlite", DbMain, 0, 0); Tcl_CreateCommand(interp, "sqlite", (Tcl_CmdProc*)DbMain, 0, 0);
Tcl_PkgProvide(interp, "sqlite", "2.0"); Tcl_PkgProvide(interp, "sqlite", "2.0");
return TCL_OK; return TCL_OK;
} }
int Tclsqlite_Init(Tcl_Interp *interp){ int Tclsqlite_Init(Tcl_Interp *interp){
Tcl_InitStubs(interp, "8.0", 0); Tcl_InitStubs(interp, "8.0", 0);
Tcl_CreateCommand(interp, "sqlite", DbMain, 0, 0); Tcl_CreateCommand(interp, "sqlite", (Tcl_CmdProc*)DbMain, 0, 0);
Tcl_PkgProvide(interp, "sqlite", "2.0"); Tcl_PkgProvide(interp, "sqlite", "2.0");
return TCL_OK; return TCL_OK;
} }

View File

@@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated ** is not included in the SQLite library. It is used for automated
** testing of the SQLite library. ** testing of the SQLite library.
** **
** $Id: test1.c,v 1.12 2002/07/10 21:26:01 drh Exp $ ** $Id: test1.c,v 1.13 2002/08/31 18:53:08 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "tcl.h" #include "tcl.h"
@@ -238,7 +238,7 @@ static void sqliteExecFunc(sqlite_func *context, int argc, const char **argv){
** sqlite_create_function function while a query is in progress in order ** sqlite_create_function function while a query is in progress in order
** to test the SQLITE_MISUSE detection logic. ** to test the SQLITE_MISUSE detection logic.
*/ */
static int sqlite_test_create_function( static int test_create_function(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
@@ -288,7 +288,7 @@ static void countFinalize(sqlite_func *context){
** sqlite_create_aggregate function while a query is in progress in order ** sqlite_create_aggregate function while a query is in progress in order
** to test the SQLITE_MISUSE detection logic. ** to test the SQLITE_MISUSE detection logic.
*/ */
static int sqlite_test_create_aggregate( static int test_create_aggregate(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
@@ -484,7 +484,7 @@ static void testFunc(sqlite_func *context, int argc, const char **argv){
** **
** Register the test SQL function on the database DB under the name NAME. ** Register the test SQL function on the database DB under the name NAME.
*/ */
static int sqlite_register_test_function( static int test_register_func(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
@@ -511,27 +511,33 @@ static int sqlite_register_test_function(
*/ */
int Sqlitetest1_Init(Tcl_Interp *interp){ int Sqlitetest1_Init(Tcl_Interp *interp){
extern int sqlite_search_count; extern int sqlite_search_count;
Tcl_CreateCommand(interp, "sqlite_mprintf_int", sqlite_mprintf_int, 0, 0); static struct {
Tcl_CreateCommand(interp, "sqlite_mprintf_str", sqlite_mprintf_str, 0, 0); char *zName;
Tcl_CreateCommand(interp, "sqlite_mprintf_double", sqlite_mprintf_double,0,0); Tcl_CmdProc *xProc;
Tcl_CreateCommand(interp, "sqlite_open", sqlite_test_open, 0, 0); } aCmd[] = {
Tcl_CreateCommand(interp, "sqlite_last_insert_rowid", test_last_rowid, 0, 0); { "sqlite_mprintf_int", (Tcl_CmdProc*)sqlite_mprintf_int },
Tcl_CreateCommand(interp, "sqlite_exec_printf", test_exec_printf, 0, 0); { "sqlite_mprintf_str", (Tcl_CmdProc*)sqlite_mprintf_str },
Tcl_CreateCommand(interp, "sqlite_get_table_printf", test_get_table_printf, { "sqlite_mprintf_double", (Tcl_CmdProc*)sqlite_mprintf_double },
0, 0); { "sqlite_open", (Tcl_CmdProc*)sqlite_test_open },
Tcl_CreateCommand(interp, "sqlite_close", sqlite_test_close, 0, 0); { "sqlite_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
Tcl_CreateCommand(interp, "sqlite_create_function", { "sqlite_exec_printf", (Tcl_CmdProc*)test_exec_printf },
sqlite_test_create_function, 0, 0); { "sqlite_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
Tcl_CreateCommand(interp, "sqlite_create_aggregate", { "sqlite_close", (Tcl_CmdProc*)sqlite_test_close },
sqlite_test_create_aggregate, 0, 0); { "sqlite_create_function", (Tcl_CmdProc*)test_create_function },
Tcl_CreateCommand(interp, "sqlite_register_test_function", { "sqlite_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
sqlite_register_test_function, 0, 0); { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
{ "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
#ifdef MEMORY_DEBUG
{ "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail },
{ "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat },
#endif
};
int i;
for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
}
Tcl_LinkVar(interp, "sqlite_search_count", Tcl_LinkVar(interp, "sqlite_search_count",
(char*)&sqlite_search_count, TCL_LINK_INT); (char*)&sqlite_search_count, TCL_LINK_INT);
#ifdef MEMORY_DEBUG
Tcl_CreateCommand(interp, "sqlite_malloc_fail", sqlite_malloc_fail, 0, 0);
Tcl_CreateCommand(interp, "sqlite_malloc_stat", sqlite_malloc_stat, 0, 0);
#endif
Tcl_CreateCommand(interp, "sqlite_abort", sqlite_abort, 0, 0);
return TCL_OK; return TCL_OK;
} }

View File

@@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated ** is not included in the SQLite library. It is used for automated
** testing of the SQLite library. ** testing of the SQLite library.
** **
** $Id: test2.c,v 1.9 2002/08/12 12:29:57 drh Exp $ ** $Id: test2.c,v 1.10 2002/08/31 18:53:08 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "pager.h" #include "pager.h"
@@ -62,7 +62,7 @@ static int pager_open(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Pager *pPager; Pager *pPager;
int nPage; int nPage;
@@ -93,7 +93,7 @@ static int pager_close(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Pager *pPager; Pager *pPager;
int rc; int rc;
@@ -120,7 +120,7 @@ static int pager_rollback(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Pager *pPager; Pager *pPager;
int rc; int rc;
@@ -147,7 +147,7 @@ static int pager_commit(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Pager *pPager; Pager *pPager;
int rc; int rc;
@@ -174,7 +174,7 @@ static int pager_ckpt_begin(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Pager *pPager; Pager *pPager;
int rc; int rc;
@@ -201,7 +201,7 @@ static int pager_ckpt_rollback(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Pager *pPager; Pager *pPager;
int rc; int rc;
@@ -228,7 +228,7 @@ static int pager_ckpt_commit(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Pager *pPager; Pager *pPager;
int rc; int rc;
@@ -255,7 +255,7 @@ static int pager_stats(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Pager *pPager; Pager *pPager;
int i, *a; int i, *a;
@@ -288,7 +288,7 @@ static int pager_pagecount(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Pager *pPager; Pager *pPager;
char zBuf[100]; char zBuf[100];
@@ -312,7 +312,7 @@ static int page_get(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Pager *pPager; Pager *pPager;
char zBuf[100]; char zBuf[100];
@@ -346,7 +346,7 @@ static int page_lookup(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Pager *pPager; Pager *pPager;
char zBuf[100]; char zBuf[100];
@@ -376,7 +376,7 @@ static int page_unref(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
void *pPage; void *pPage;
int rc; int rc;
@@ -403,7 +403,7 @@ static int page_read(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
char zBuf[100]; char zBuf[100];
void *pPage; void *pPage;
@@ -427,7 +427,7 @@ static int page_number(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
char zBuf[100]; char zBuf[100];
void *pPage; void *pPage;
@@ -451,7 +451,7 @@ static int page_write(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
void *pPage; void *pPage;
int rc; int rc;
@@ -476,21 +476,30 @@ static int page_write(
*/ */
int Sqlitetest2_Init(Tcl_Interp *interp){ int Sqlitetest2_Init(Tcl_Interp *interp){
extern int sqlite_io_error_pending; extern int sqlite_io_error_pending;
Tcl_CreateCommand(interp, "pager_open", pager_open, 0, 0); static struct {
Tcl_CreateCommand(interp, "pager_close", pager_close, 0, 0); char *zName;
Tcl_CreateCommand(interp, "pager_commit", pager_commit, 0, 0); Tcl_CmdProc *xProc;
Tcl_CreateCommand(interp, "pager_rollback", pager_rollback, 0, 0); } aCmd[] = {
Tcl_CreateCommand(interp, "pager_ckpt_begin", pager_ckpt_begin, 0, 0); { "pager_open", (Tcl_CmdProc*)pager_open },
Tcl_CreateCommand(interp, "pager_ckpt_commit", pager_ckpt_commit, 0, 0); { "pager_close", (Tcl_CmdProc*)pager_close },
Tcl_CreateCommand(interp, "pager_ckpt_rollback", pager_ckpt_rollback, 0, 0); { "pager_commit", (Tcl_CmdProc*)pager_commit },
Tcl_CreateCommand(interp, "pager_stats", pager_stats, 0, 0); { "pager_rollback", (Tcl_CmdProc*)pager_rollback },
Tcl_CreateCommand(interp, "pager_pagecount", pager_pagecount, 0, 0); { "pager_ckpt_begin", (Tcl_CmdProc*)pager_ckpt_begin },
Tcl_CreateCommand(interp, "page_get", page_get, 0, 0); { "pager_ckpt_commit", (Tcl_CmdProc*)pager_ckpt_commit },
Tcl_CreateCommand(interp, "page_lookup", page_lookup, 0, 0); { "pager_ckpt_rollback", (Tcl_CmdProc*)pager_ckpt_rollback },
Tcl_CreateCommand(interp, "page_unref", page_unref, 0, 0); { "pager_stats", (Tcl_CmdProc*)pager_stats },
Tcl_CreateCommand(interp, "page_read", page_read, 0, 0); { "pager_pagecount", (Tcl_CmdProc*)pager_pagecount },
Tcl_CreateCommand(interp, "page_write", page_write, 0, 0); { "page_get", (Tcl_CmdProc*)page_get },
Tcl_CreateCommand(interp, "page_number", page_number, 0, 0); { "page_lookup", (Tcl_CmdProc*)page_lookup },
{ "page_unref", (Tcl_CmdProc*)page_unref },
{ "page_read", (Tcl_CmdProc*)page_read },
{ "page_write", (Tcl_CmdProc*)page_write },
{ "page_number", (Tcl_CmdProc*)page_number },
};
int i;
for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
}
Tcl_LinkVar(interp, "sqlite_io_error_pending", Tcl_LinkVar(interp, "sqlite_io_error_pending",
(char*)&sqlite_io_error_pending, TCL_LINK_INT); (char*)&sqlite_io_error_pending, TCL_LINK_INT);
#ifdef SQLITE_TEST #ifdef SQLITE_TEST

View File

@@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated ** is not included in the SQLite library. It is used for automated
** testing of the SQLite library. ** testing of the SQLite library.
** **
** $Id: test3.c,v 1.18 2002/08/11 20:10:48 drh Exp $ ** $Id: test3.c,v 1.19 2002/08/31 18:53:08 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "pager.h" #include "pager.h"
@@ -57,7 +57,7 @@ static int btree_open(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int rc; int rc;
@@ -89,7 +89,7 @@ static int btree_close(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int rc; int rc;
@@ -116,7 +116,7 @@ static int btree_begin_transaction(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int rc; int rc;
@@ -143,7 +143,7 @@ static int btree_rollback(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int rc; int rc;
@@ -170,7 +170,7 @@ static int btree_commit(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int rc; int rc;
@@ -197,7 +197,7 @@ static int btree_create_table(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int rc, iTable; int rc, iTable;
@@ -227,7 +227,7 @@ static int btree_drop_table(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int iTable; int iTable;
@@ -256,7 +256,7 @@ static int btree_clear_table(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int iTable; int iTable;
@@ -285,7 +285,7 @@ static int btree_get_meta(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int rc; int rc;
@@ -319,7 +319,7 @@ static int btree_update_meta(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int rc; int rc;
@@ -354,7 +354,7 @@ static int btree_page_dump(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int iPage; int iPage;
@@ -384,7 +384,7 @@ static int btree_tree_dump(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int iPage; int iPage;
@@ -414,7 +414,7 @@ static int btree_pager_stats(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int i; int i;
@@ -449,7 +449,7 @@ static int btree_pager_ref_dump(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
@@ -474,7 +474,7 @@ static int btree_integrity_check(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
char *zResult; char *zResult;
@@ -510,7 +510,7 @@ static int btree_cursor(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
Btree *pBt; Btree *pBt;
int iTable; int iTable;
@@ -546,7 +546,7 @@ static int btree_close_cursor(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
BtCursor *pCur; BtCursor *pCur;
int rc; int rc;
@@ -574,7 +574,7 @@ static int btree_move_to(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
BtCursor *pCur; BtCursor *pCur;
int rc; int rc;
@@ -608,7 +608,7 @@ static int btree_delete(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
BtCursor *pCur; BtCursor *pCur;
int rc; int rc;
@@ -637,7 +637,7 @@ static int btree_insert(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
BtCursor *pCur; BtCursor *pCur;
int rc; int rc;
@@ -666,7 +666,7 @@ static int btree_next(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
BtCursor *pCur; BtCursor *pCur;
int rc; int rc;
@@ -698,7 +698,7 @@ static int btree_first(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
BtCursor *pCur; BtCursor *pCur;
int rc; int rc;
@@ -730,7 +730,7 @@ static int btree_key(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
BtCursor *pCur; BtCursor *pCur;
int rc; int rc;
@@ -768,7 +768,7 @@ static int btree_data(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
BtCursor *pCur; BtCursor *pCur;
int rc; int rc;
@@ -806,7 +806,7 @@ static int btree_payload_size(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
BtCursor *pCur; BtCursor *pCur;
int n1, n2; int n1, n2;
@@ -845,7 +845,7 @@ static int btree_cursor_dump(
void *NotUsed, void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */ int argc, /* Number of arguments */
char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
BtCursor *pCur; BtCursor *pCur;
int rc; int rc;
@@ -877,33 +877,42 @@ static int btree_cursor_dump(
** Register commands with the TCL interpreter. ** Register commands with the TCL interpreter.
*/ */
int Sqlitetest3_Init(Tcl_Interp *interp){ int Sqlitetest3_Init(Tcl_Interp *interp){
Tcl_CreateCommand(interp, "btree_open", btree_open, 0, 0); static struct {
Tcl_CreateCommand(interp, "btree_close", btree_close, 0, 0); char *zName;
Tcl_CreateCommand(interp, "btree_begin_transaction", Tcl_CmdProc *xProc;
btree_begin_transaction, 0, 0); } aCmd[] = {
Tcl_CreateCommand(interp, "btree_commit", btree_commit, 0, 0); { "btree_open", (Tcl_CmdProc*)btree_open },
Tcl_CreateCommand(interp, "btree_rollback", btree_rollback, 0, 0); { "btree_close", (Tcl_CmdProc*)btree_close },
Tcl_CreateCommand(interp, "btree_create_table", btree_create_table, 0, 0); { "btree_begin_transaction", (Tcl_CmdProc*)btree_begin_transaction },
Tcl_CreateCommand(interp, "btree_drop_table", btree_drop_table, 0, 0); { "btree_commit", (Tcl_CmdProc*)btree_commit },
Tcl_CreateCommand(interp, "btree_clear_table", btree_clear_table, 0, 0); { "btree_rollback", (Tcl_CmdProc*)btree_rollback },
Tcl_CreateCommand(interp, "btree_get_meta", btree_get_meta, 0, 0); { "btree_create_table", (Tcl_CmdProc*)btree_create_table },
Tcl_CreateCommand(interp, "btree_update_meta", btree_update_meta, 0, 0); { "btree_drop_table", (Tcl_CmdProc*)btree_drop_table },
Tcl_CreateCommand(interp, "btree_page_dump", btree_page_dump, 0, 0); { "btree_clear_table", (Tcl_CmdProc*)btree_clear_table },
Tcl_CreateCommand(interp, "btree_tree_dump", btree_tree_dump, 0, 0); { "btree_get_meta", (Tcl_CmdProc*)btree_get_meta },
Tcl_CreateCommand(interp, "btree_pager_stats", btree_pager_stats, 0, 0); { "btree_update_meta", (Tcl_CmdProc*)btree_update_meta },
Tcl_CreateCommand(interp, "btree_pager_ref_dump", btree_pager_ref_dump, 0, 0); { "btree_page_dump", (Tcl_CmdProc*)btree_page_dump },
Tcl_CreateCommand(interp, "btree_cursor", btree_cursor, 0, 0); { "btree_tree_dump", (Tcl_CmdProc*)btree_tree_dump },
Tcl_CreateCommand(interp, "btree_close_cursor", btree_close_cursor, 0, 0); { "btree_pager_stats", (Tcl_CmdProc*)btree_pager_stats },
Tcl_CreateCommand(interp, "btree_move_to", btree_move_to, 0, 0); { "btree_pager_ref_dump", (Tcl_CmdProc*)btree_pager_ref_dump },
Tcl_CreateCommand(interp, "btree_delete", btree_delete, 0, 0); { "btree_cursor", (Tcl_CmdProc*)btree_cursor },
Tcl_CreateCommand(interp, "btree_insert", btree_insert, 0, 0); { "btree_close_cursor", (Tcl_CmdProc*)btree_close_cursor },
Tcl_CreateCommand(interp, "btree_next", btree_next, 0, 0); { "btree_move_to", (Tcl_CmdProc*)btree_move_to },
Tcl_CreateCommand(interp, "btree_key", btree_key, 0, 0); { "btree_delete", (Tcl_CmdProc*)btree_delete },
Tcl_CreateCommand(interp, "btree_data", btree_data, 0, 0); { "btree_insert", (Tcl_CmdProc*)btree_insert },
Tcl_CreateCommand(interp, "btree_payload_size", btree_payload_size, 0, 0); { "btree_next", (Tcl_CmdProc*)btree_next },
Tcl_CreateCommand(interp, "btree_first", btree_first, 0, 0); { "btree_key", (Tcl_CmdProc*)btree_key },
Tcl_CreateCommand(interp, "btree_cursor_dump", btree_cursor_dump, 0, 0); { "btree_data", (Tcl_CmdProc*)btree_data },
Tcl_CreateCommand(interp, "btree_integrity_check", btree_integrity_check,0,0); { "btree_payload_size", (Tcl_CmdProc*)btree_payload_size },
{ "btree_first", (Tcl_CmdProc*)btree_first },
{ "btree_cursor_dump", (Tcl_CmdProc*)btree_cursor_dump },
{ "btree_integrity_check", (Tcl_CmdProc*)btree_integrity_check },
};
int i;
for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
}
Tcl_LinkVar(interp, "pager_refinfo_enable", (char*)&pager_refinfo_enable, Tcl_LinkVar(interp, "pager_refinfo_enable", (char*)&pager_refinfo_enable,
TCL_LINK_INT); TCL_LINK_INT);
Tcl_LinkVar(interp, "btree_native_byte_order",(char*)&btree_native_byte_order, Tcl_LinkVar(interp, "btree_native_byte_order",(char*)&btree_native_byte_order,

44
test/fkey1.test Normal file
View File

@@ -0,0 +1,44 @@
# 2001 September 15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for foreign keys.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Create a table and some data to work with.
#
do_test fkey1-1.0 {
execsql {
CREATE TABLE t1(
a INTEGER PRIMARY KEY,
b INTEGER
REFERENCES t1 ON DELETE CASCADE
REFERENCES t2,
c TEXT,
FOREIGN KEY (b,c) REFERENCES t2(x,y) ON UPDATE CASCADE
);
}
} {}
do_test fkey1-1.1 {
execsql {
CREATE TABLE t2(
x INTEGER PRIMARY KEY,
y TEXT
);
}
} {}
finish_test

View File

@@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The # This file implements regression tests for SQLite library. The
# focus of this file is testing the CREATE TABLE statement. # focus of this file is testing the CREATE TABLE statement.
# #
# $Id: table.test,v 1.19 2002/08/13 23:02:58 drh Exp $ # $Id: table.test,v 1.20 2002/08/31 18:53:09 drh Exp $
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@@ -433,6 +433,45 @@ do_test table-10.8 {
); );
} }
} {0 {}} } {0 {}}
do_test table-10.9 {
catchsql {
DROP TABLE t6;
CREATE TABLE t6(a,b,c,
FOREIGN KEY (b,c) REFERENCES t4(x)
);
}
} {1 {number of columns in foreign key does not match the number of columns in the referenced table}}
do_test table-10.10 {
catchsql {DROP TABLE t6}
catchsql {
CREATE TABLE t6(a,b,c,
FOREIGN KEY (b,c) REFERENCES t4(x,y,z)
);
}
} {1 {number of columns in foreign key does not match the number of columns in the referenced table}}
do_test table-10.11 {
catchsql {DROP TABLE t6}
catchsql {
CREATE TABLE t6(a,b, c REFERENCES t4(x,y));
}
} {1 {foreign key on c should reference only one column of table t4}}
do_test table-10.12 {
catchsql {DROP TABLE t6}
catchsql {
CREATE TABLE t6(a,b,c,
FOREIGN KEY (b,x) REFERENCES t4(x,y)
);
}
} {1 {unknown column "x" in foreign key definition}}
do_test table-10.13 {
catchsql {DROP TABLE t6}
catchsql {
CREATE TABLE t6(a,b,c,
FOREIGN KEY (x,b) REFERENCES t4(x,y)
);
}
} {1 {unknown column "x" in foreign key definition}}
# Test for the "typeof" function. # Test for the "typeof" function.
# #