From f9e7dda7efc977e73a265fbcc1c68ed3bb1db6be Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Fri, 16 Jun 2006 16:08:53 +0000 Subject: [PATCH] Add code to invoke the virtual table transaction interface. Untested at this point. (CVS 3261) FossilOrigin-Name: 6125140228e09cad2029a48e92aa0123d3daecfb --- manifest | 28 +++++++------- manifest.uuid | 2 +- src/build.c | 8 +++- src/delete.c | 6 +-- src/insert.c | 3 +- src/main.c | 3 +- src/sqliteInt.h | 24 +++++++++--- src/update.c | 3 +- src/vdbe.c | 14 ++++++- src/vdbeaux.c | 5 +++ src/vtab.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++- 11 files changed, 165 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index 14f9245d79..4a4feee934 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\ssome\stests\s(and\sfixes)\sfor\svirtual\stables\sand\sthe\sauthorization\scallback.\sStill\smore\sto\scome.\s(CVS\s3260) -D 2006-06-16T08:01:03 +C Add\scode\sto\sinvoke\sthe\svirtual\stable\stransaction\sinterface.\sUntested\sat\sthis\spoint.\s(CVS\s3261) +D 2006-06-16T16:08:54 F Makefile.in f839b470345d3cb4b0644068474623fe2464b5d3 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -36,20 +36,20 @@ F src/attach.c 27a31d3b89d7ebb5b358847607b1ec795384123c F src/auth.c 902f4722661c796b97f007d9606bd7529c02597f F src/btree.c ed343b3dbcbc7da9ac481ef2b98c4239fe6d9629 F src/btree.h 40055cfc09defd1146bc5b922399c035f969e56d -F src/build.c 28208a9049d7bf61f16fcb4bb850406857135953 +F src/build.c 3eb63f61249fd0fcd7075456b522a1ceb5f912bd F src/callback.c fd9bb39f7ff6b52bad8365617abc61c720640429 F src/complete.c 7d1a44be8f37de125fcafd3d3a018690b3799675 F src/date.c cd2bd5d1ebc6fa12d6312f69789ae5b0a2766f2e -F src/delete.c f34599f681d291d5b5762ff162a4b10214809aef +F src/delete.c e6a324650fb9f6afe5757ec5c7d8dad62d9496b8 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b F src/expr.c 78b521337d628b1fd9d87b12dbbe771247aab585 F src/func.c 01e559893b5e43bea85135ad3e481d86c447942a F src/hash.c 449f3d6620193aa557f5d86cbc5cc6b87702b185 F src/hash.h 1b3f7e2609141fd571f62199fc38687d262e9564 -F src/insert.c 09440829e4fa2b0e11dbde5508b8a291025a745d +F src/insert.c 5c1fddd7e4d05805e02e12bdced2a3841d2bd8dc F src/legacy.c fa15d505dd4e45044177ee4d1c6aeaf8c836d390 F src/loadext.c 676257ae268457e7f03261d8ca0d1e72968a26c8 -F src/main.c 7875e8835539d4f16e8b62fad1dee9bda2091272 +F src/main.c 7101314a365120465bf5e308caaf518b7776430c F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217 F src/os.c 59f05de8c5777c34876607114a2fbe55ae578235 F src/os.h ac2ccb4f48902c1611a7e1f171eb81d17e3b8eb2 @@ -74,7 +74,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c ad73192b30a338a58fe81183d4a5d5a1d4e51d36 F src/sqlite.h.in 77b42d1bb5deafa04ae156d24cd243c2d75800ac F src/sqlite3ext.h fc8647211af0caa9d8e49ab31624b357c1332380 -F src/sqliteInt.h 2eb48bd25f5fccce86d80e6872b045ed61b91687 +F src/sqliteInt.h 5f8de04c331fb6c80e70e309f550c8cc8efb6e1f F src/table.c f64ec4fbfe333f8df925bc6ba494f55e05b0e75e F src/tclsqlite.c c408a49ae44525fc69757b4ed39f6ca0f56549a5 F src/test1.c 40f20775903bc76d3be3e7c026dddcbc221c1cb0 @@ -93,18 +93,18 @@ F src/test_server.c a6460daed0b92ecbc2531b6dc73717470e7a648c F src/test_tclvar.c c52f67fbe06d32804af2ba9a2d7aadfc15f5910c F src/tokenize.c 6ebcafa6622839968dda4418a7b6945f277a128f F src/trigger.c 0fc40125820409a6274834a6e04ad804d96e2793 -F src/update.c 5e638a61102776c0f0333994e18361b40598b44f +F src/update.c d3b991905ed8b26feb2055bdab40ce3c42e1b522 F src/utf.c ab81ac59084ff1c07d421eb1a0a84ec809603b44 F src/util.c ca6ee72772c0f5dc04d2e0ab1973fd3b6a9bf79d F src/vacuum.c 5b37d0f436f8e1ffacd17934e44720b38d2247f9 -F src/vdbe.c f17a90ab6c630438394807c4e21c0c1c7731ee4f +F src/vdbe.c 704940e7c0c811d721a4eac0f4bb3da4f4f88dc9 F src/vdbe.h 258b5d1c0aaa72192f09ff0568ce42b383f156fa F src/vdbeInt.h 6ccb7eaae76ebd761470f6a035501ff33aa92c20 F src/vdbeapi.c 6af0e7160af260052a7a4500464221a03dada75f -F src/vdbeaux.c 85f2184f536219d3c20c66f1403ef77321d1e715 +F src/vdbeaux.c dc5cfd11a0529fcfd217a1807f7c9df513f1c276 F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 F src/vdbemem.c 5f0afe3b92bb2c037f8d5d697f7c151fa50783a3 -F src/vtab.c cb5a2b23a241e657a8ee7c2b03574f6afa27214a +F src/vtab.c 5d69a87980eaac026f74c8712961ed2b306ffba2 F src/where.c d7c3cc011834882b2d58ebb3a6a1a569ead7ebd7 F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -368,7 +368,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P afa39a46320e9996a5478ea6e19eb4c2014327ac -R e864f985538904b7098e2d0d1765152d +P 9497c66e5533ec143d0efda4a419e4bdf922ae8c +R d4bc1ee77da86ad3a4a5c0b77f2ab8e7 U danielk1977 -Z b35d7828e5c540d613e21e95c6dfce99 +Z d74361b9f31a7257bb399e37ec5aacb7 diff --git a/manifest.uuid b/manifest.uuid index 0b1a8c6b44..94fa1cadbe 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9497c66e5533ec143d0efda4a419e4bdf922ae8c \ No newline at end of file +6125140228e09cad2029a48e92aa0123d3daecfb \ No newline at end of file diff --git a/src/build.c b/src/build.c index 9f9eea17ee..517c27dafb 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.402 2006/06/16 08:01:03 danielk1977 Exp $ +** $Id: build.c,v 1.403 2006/06/16 16:08:54 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -164,6 +164,12 @@ void sqlite3FinishCoding(Parse *pParse){ sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0); sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pParse->pVirtualLock ){ + char *vtab = (char *)pParse->pVirtualLock->pVtab; + sqlite3VdbeOp3(v, OP_VBegin, 0, 0, vtab, P3_VTAB); + } +#endif /* Once all the cookies have been verified and transactions opened, ** obtain the required table-locks. This is a no-op unless the diff --git a/src/delete.c b/src/delete.c index f1cdcdb9a2..196d7fc6c0 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** -** $Id: delete.c,v 1.125 2006/06/15 04:28:13 danielk1977 Exp $ +** $Id: delete.c,v 1.126 2006/06/16 16:08:55 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -236,8 +236,7 @@ void sqlite3DeleteFrom( sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, iDb); } } - } - + } /* The usual case: There is a WHERE clause so we have to scan through ** the table and pick which records to delete. */ @@ -312,6 +311,7 @@ void sqlite3DeleteFrom( /* Delete the row */ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ + pParse->pVirtualLock = pTab; sqlite3VdbeOp3(v, OP_VUpdate, 0, 1, (const char*)pTab->pVtab, P3_VTAB); }else #endif diff --git a/src/insert.c b/src/insert.c index efefb2aaee..60737ededf 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.168 2006/06/16 06:17:47 danielk1977 Exp $ +** $Id: insert.c,v 1.169 2006/06/16 16:08:55 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -632,6 +632,7 @@ void sqlite3Insert( */ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ + pParse->pVirtualLock = pTab; sqlite3VdbeOp3(v, OP_VUpdate, 1, pTab->nCol+2, (const char*)pTab->pVtab, P3_VTAB); }else diff --git a/src/main.c b/src/main.c index 463ba997a0..44569e011a 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.344 2006/06/15 04:28:13 danielk1977 Exp $ +** $Id: main.c,v 1.345 2006/06/16 16:08:55 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -206,6 +206,7 @@ void sqlite3RollbackAll(sqlite3 *db){ if( db->flags&SQLITE_InternChanges ){ sqlite3ResetInternalSchema(db, 0); } + sqlite3VtabRollback(db); /* If one has been configured, invoke the rollback-hook callback */ if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index bec2be02c5..95d2966141 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.507 2006/06/16 08:01:04 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.508 2006/06/16 16:08:55 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -494,6 +494,8 @@ struct sqlite3 { #ifndef SQLITE_OMIT_VIRTUALTABLE Hash aModule; /* populated by sqlite3_create_module() */ Table *pVTab; /* vtab with active Connect/Create method */ + sqlite3_vtab **aVTrans; /* Virtual tables with open transactions */ + int nVTrans; /* Allocated size of aVTrans */ #endif Hash aFunc; /* All functions that can be in SQL exprs */ Hash aCollSeq; /* All collating sequences */ @@ -722,6 +724,7 @@ struct Table { u8 isVirtual; /* True if this is a virtual table */ int nModuleArg; /* Number of arguments to the module */ char **azModuleArg; /* Text of all module args. [0] is module name */ + u8 isCommit; /* True once the CREATE TABLE has been committed */ #endif Schema *pSchema; }; @@ -1304,10 +1307,11 @@ struct Parse { TriggerStack *trigStack; /* Trigger actions being coded */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ #ifndef SQLITE_OMIT_VIRTUALTABLE - int nArgAlloc; /* Number of bytes allocated for zArg[] */ - int nArgUsed; /* Number of bytes of zArg[] used so far */ - char *zArg; /* Complete text of a module argument */ - u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ + int nArgAlloc; /* Number of bytes allocated for zArg[] */ + int nArgUsed; /* Number of bytes of zArg[] used so far */ + char *zArg; /* Complete text of a module argument */ + u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ + Table *pVirtualLock; /* Require virtual table lock on this table */ #endif }; @@ -1815,8 +1819,15 @@ void sqlite3CloseExtensions(sqlite3*); #ifdef SQLITE_OMIT_VIRTUALTABLE # define sqlite3VtabClear(X) +# define sqlite3VtabCodeLock(X,Y) +# define sqlite3VtabSync(X,Y) (Y) +# define sqlite3VtabRollback(X) +# define sqlite3VtabCommit(X) #else - void sqlite3VtabClear(Table*); + void sqlite3VtabCodeLock(Parse *pParse, Table *pTab); + int sqlite3VtabSync(sqlite3 *db, int rc); + int sqlite3VtabRollback(sqlite3 *db); + int sqlite3VtabCommit(sqlite3 *db); #endif void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*); void sqlite3VtabFinishParse(Parse*, Token*); @@ -1825,6 +1836,7 @@ void sqlite3VtabArgExtend(Parse*, Token*); int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **); int sqlite3VtabCallConnect(Parse*, Table*); int sqlite3VtabCallDestroy(sqlite3*, int, const char *); +int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *); #ifdef SQLITE_SSE #include "sseInt.h" diff --git a/src/update.c b/src/update.c index bc2a271502..b40d3a20d0 100644 --- a/src/update.c +++ b/src/update.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.125 2006/06/14 19:00:22 drh Exp $ +** $Id: update.c,v 1.126 2006/06/16 16:08:55 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -475,6 +475,7 @@ void sqlite3Update( } /* Make the update */ + pParse->pVirtualLock = pTab; sqlite3VdbeOp3(v, OP_VUpdate, 0, pTab->nCol+2, (const char*)pTab->pVtab, P3_VTAB); } diff --git a/src/vdbe.c b/src/vdbe.c index 0441334743..b75bfe2663 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.562 2006/06/16 06:17:47 danielk1977 Exp $ +** $Id: vdbe.c,v 1.563 2006/06/16 16:08:55 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -4537,6 +4537,18 @@ case OP_TableLock: { /* no-push */ } #endif /* SQLITE_OMIT_SHARED_CACHE */ +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VCreate P1 * P3 +** +** P3 is the name of a virtual table in database P1. Call the xCreate method +** for that table. +*/ +case OP_VBegin: { /* no-push */ + rc = sqlite3VtabBegin(db, (sqlite3_vtab *)pOp->p3); + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VCreate P1 * P3 ** diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 13d5cfd788..f599fdd3e4 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1002,6 +1002,7 @@ static int vdbeCommit(sqlite3 *db){ rc = sqlite3BtreeSync(pBt, 0); } } + rc = sqlite3VtabSync(db, rc); /* Do the commit only if all databases successfully synced */ if( rc==SQLITE_OK ){ @@ -1011,6 +1012,7 @@ static int vdbeCommit(sqlite3 *db){ sqlite3BtreeCommit(pBt); } } + sqlite3VtabCommit(db); } } @@ -1103,6 +1105,8 @@ static int vdbeCommit(sqlite3 *db){ } } } + rc = sqlite3VtabSync(db, SQLITE_OK); + if( rc!=SQLITE_OK ) return rc; sqlite3OsClose(&master); /* Delete the master journal file. This commits the transaction. After @@ -1138,6 +1142,7 @@ static int vdbeCommit(sqlite3 *db){ sqlite3BtreeCommit(pBt); } } + sqlite3VtabCommit(db); } #endif diff --git a/src/vtab.c b/src/vtab.c index 2b647b12ea..fb1f4d933e 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to help implement virtual tables. ** -** $Id: vtab.c,v 1.14 2006/06/16 08:01:04 danielk1977 Exp $ +** $Id: vtab.c,v 1.15 2006/06/16 16:08:55 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE #include "sqliteInt.h" @@ -441,4 +441,101 @@ int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab) return rc; } +static int callFinaliser(sqlite3 *db, int offset, int doDelete){ + int rc = SQLITE_OK; + int i; + for(i=0; rc==SQLITE_OK && inVTrans && db->aVTrans[i]; i++){ + sqlite3_vtab *pVtab = db->aVTrans[i]; + int (*x)(sqlite3_vtab *); + x = (int (*)(sqlite3_vtab *))((char *)pVtab->pModule + offset); + if( x ){ + rc = x(pVtab); + } + } + if( doDelete ){ + sqliteFree(db->aVTrans); + db->nVTrans = 0; + db->aVTrans = 0; + } + return rc; +} + +void sqlite3VtabCodeLock(Parse *pParse, Table *pTab){ + Vdbe *v = sqlite3GetVdbe(pParse); + sqlite3VdbeOp3(v, OP_VBegin, 0, 0, (const char*)pTab->pVtab, P3_VTAB); +} + +/* +** If argument rc is not SQLITE_OK, then return it and do nothing. +** Otherwise, invoke the xSync method of all virtual tables in the +** sqlite3.aVTrans array. Return the error code for the first error +** that occurs, or SQLITE_OK if all xSync operations are successful. +*/ +int sqlite3VtabSync(sqlite3 *db, int rc){ + if( rc!=SQLITE_OK ) return rc; + return callFinaliser(db, (int)(&((sqlite3_module *)0)->xSync), 0); +} + +/* +** Invoke the xRollback method of all virtual tables in the +** sqlite3.aVTrans array. Then clear the array itself. +*/ +int sqlite3VtabRollback(sqlite3 *db){ + return callFinaliser(db, (int)(&((sqlite3_module *)0)->xRollback), 1); +} + +/* +** Invoke the xCommit method of all virtual tables in the +** sqlite3.aVTrans array. Then clear the array itself. +*/ +int sqlite3VtabCommit(sqlite3 *db){ + return callFinaliser(db, (int)(&((sqlite3_module *)0)->xCommit), 1); +} + +/* +** If the virtual table pVtab supports the transaction interface +** (xBegin/xRollback/xCommit and optionally xSync) and a transaction is +** not currently open, invoke the xBegin method now. +** +** If the xBegin call is successful, place the sqlite3_vtab pointer +** in the sqlite3.aVTrans array. +*/ +int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){ + int rc = SQLITE_OK; + const int ARRAY_INCR = 5; + const sqlite3_module *pModule = pVtab->pModule; + if( pModule->xBegin ){ + int i; + + /* If pVtab is already in the aVTrans array, return early */ + for(i=0; (inVTrans) && 0!=db->aVTrans[i]; i++){ + if( db->aVTrans[i]==pVtab ){ + return SQLITE_OK; + } + } + + /* Invoke the xBegin method */ + rc = pModule->xBegin(pVtab); + if( rc!=SQLITE_OK ){ + return rc; + } + + /* Grow the sqlite3.aVTrans array if required */ + if( (db->nVTrans%ARRAY_INCR)==0 ){ + sqlite3_vtab *aVTrans; + int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR); + aVTrans = sqliteRealloc((void *)db->aVTrans, nBytes); + if( !aVTrans ){ + return SQLITE_NOMEM; + } + memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR); + db->aVTrans = aVTrans; + } + + /* Add pVtab to the end of sqlite3.aVTrans */ + db->aVTrans[db->nVTrans++] = pVtab; + } + return rc; +} + #endif /* SQLITE_OMIT_VIRTUALTABLE */