diff --git a/manifest b/manifest index 76bfe06db7..ca5db471c4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C respect\s$LDFLAGS\sfrom\senv/configure\s(CVS\s4141) -D 2007-06-27T15:01:46 +C Allow\sALTER\sTABLE\son\svirtual\stables.\s(CVS\s4142) +D 2007-06-27T15:53:35 F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -62,7 +62,7 @@ F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4 F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a -F src/alter.c 1b1deeb97446ed87f2fa17a3eb6236548841a348 +F src/alter.c 3402b657de80c242b0382f768df273505f8178cc F src/analyze.c 8d345472e0f4e44fc88f5cf489c16dcb77904525 F src/attach.c ba628db0c2b6a362f036d017bf1196cdfe4ebb37 F src/auth.c 5ea90bc93dfea46e9fe4bf531e14c7cd98219ecb @@ -107,7 +107,7 @@ F src/random.c 6119474a6f6917f708c1dee25b9a8e519a620e88 F src/select.c e363327d0eba8d758ab00055de962a3bb0bc213e F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c 4b0fc3c76a9f23a1c963e01703c0fbbca1b5c34d -F src/sqlite.h.in a3c5d9f8566efe43589b428bd4f7f0f77766e9ae +F src/sqlite.h.in bbcc5481af9f40ce5762c323cf555581a025f3de F src/sqlite3ext.h 95575e0d175a0271fe2c3232c0d11e8720ed6887 F src/sqliteInt.h 81183ae71162818bf60478e738ff68604128bb06 F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa @@ -120,7 +120,7 @@ F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25 F src/test5.c c40a4cf43266c1c6da7bcb737d294304a177e6cc F src/test6.c 5957d249d437e4db74045ce2f1f661648d94bf94 F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3 -F src/test8.c c3c4aeea4e3d70966306d6eca1b77ce7eee2f059 +F src/test8.c 4f0a8624028588e083731c11927f5b2a07184618 F src/test9.c c0f38f7795cc51d37db6c63874d90f40f10d0f0e F src/test_async.c 9d326ceda4306bcab252b8f7e8e480ed45d7ccb6 F src/test_autoext.c 855157d97aa28cf84233847548bfacda21807436 @@ -138,11 +138,11 @@ F src/update.c 6b10becb6235ea314ed245fbfbf8b38755e3166e F src/utf.c 01b2aba02b10d12903e9e1ff897215c9faf6b662 F src/util.c 9e81d417fc60bd2fe156f8f2317aa4845bc6cc90 F src/vacuum.c 8bd895d29e7074e78d4e80f948e35ddc9cf2beef -F src/vdbe.c b776b68ad926974c72296145d1282ff6e956b4ff +F src/vdbe.c 32f39e9cab8a6ef64ad392711396d65ae89fc790 F src/vdbe.h 001c5b257567c1d3de7feb2203aac71d0d7b16a3 -F src/vdbeInt.h 7d2bf163d6d4e815724a457f2216dd8e38c3955c +F src/vdbeInt.h c3514903cad9e36d6b3242be20261351d09db56c F src/vdbeapi.c 7930b9a188ab385287ca3eb3840af7225cb43549 -F src/vdbeaux.c c580d3605edc2c24ba9bd26fa7aa8b4fff10daa4 +F src/vdbeaux.c ca1d673fd5e45fe9ba994391b11568c48a7e1b59 F src/vdbeblob.c bb30b3e387c35ba869949494b2736aff97159470 F src/vdbefifo.c 3ca8049c561d5d67cbcb94dc909ae9bb68c0bf8f F src/vdbemem.c ca4d3994507cb0a9504820293af69f5c778b4abd @@ -420,16 +420,17 @@ F test/vacuum.test cf839fc3ff24d601057319bbb5c700ce9c8e0fb0 F test/vacuum2.test 5aea8c88a65cb29f7d175296e7c819c6158d838c F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/view.test 852bd4101e6d171c46ad682eb5c5faf662b2eba4 -F test/vtab1.test bf129928444f1fe3d992894f6e0b4c6d4a534d49 +F test/vtab1.test e740d4761b9125e6e541c62d199a3822f54614ff F test/vtab2.test 94bb3bf691ac10e34cf7dad46b1cf94b861d513c F test/vtab3.test f38d6d7d19f08bffdadce4d5b8cba078f8118587 F test/vtab4.test a9d7104d41a787754a734740d7aa61c807a69f87 -F test/vtab5.test 9fb8f335651afe8f870011e2f68e5b00c5ad03cd +F test/vtab5.test 26bc7a0a52c5c2bcfa849ba327f8a0d4abccdb23 F test/vtab6.test ec0036f29f8a803da9935206f2d9d1b6a8026392 F test/vtab7.test 5f9ef9fb84733e928d5d0267c821072561b198d5 F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583 F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b F test/vtabA.test 9cb6b1afead6fdd91bbdf1ca65c44ccfd9b10936 +F test/vtab_alter.test 87617789086fd1767aa071e7805f1af7e1dac144 F test/vtab_err.test 9eabf98b26838fed8bac4aea986580be0a2bd52e F test/vtab_shared.test d631d1f820c38c18939d53aab1fc35db5f0a8094 F test/where.test 1bcde8984c63747ac6d6bafcacd20fd6e8a223de @@ -516,7 +517,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 850822e2904bc340afd0b7535ef51fbdf9e1f486 -R 1afeab26f16295155c75ffe8baa66b82 -U vapier -Z 83aaaa53ff941923277b0d6c2cfa7d3d +P 9c13fc0f4bf22c8e05b11ef5feaaf07d8a8b3f01 +R 53f2a209b5d25f95ed550b0d365211d1 +U danielk1977 +Z ba48bbb530071e692ea4d7c53d55d66a diff --git a/manifest.uuid b/manifest.uuid index 9c8528d181..94cfb98e2c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9c13fc0f4bf22c8e05b11ef5feaaf07d8a8b3f01 \ No newline at end of file +37d1f9f37ea9d2e8a4dbe0ec67c0d6eb7fcc5f3f \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index ddcedddcbb..d93da8f299 100644 --- a/src/alter.c +++ b/src/alter.c @@ -12,7 +12,7 @@ ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: alter.c,v 1.25 2007/05/15 14:34:32 drh Exp $ +** $Id: alter.c,v 1.26 2007/06/27 15:53:35 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -53,7 +53,7 @@ static void renameTableFunc( /* The principle used to locate the table name in the CREATE TABLE ** statement is that the table name is the first token that is immediatedly - ** followed by a left parenthesis - TK_LP. + ** followed by a left parenthesis - TK_LP - or "USING" TK_USING. */ if( zSql ){ do { @@ -74,7 +74,7 @@ static void renameTableFunc( len = sqlite3GetToken(zCsr, &token); } while( token==TK_SPACE ); assert( len>0 ); - } while( token!=TK_LP ); + } while( token!=TK_LP && token!=TK_USING ); zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql, zTableName, tname.z+tname.n); @@ -279,18 +279,13 @@ void sqlite3AlterRenameTable( #ifndef SQLITE_OMIT_TRIGGER char *zWhere = 0; /* Where clause to locate temp triggers */ #endif + int isVirtualRename = 0; /* True if this is a v-table with an xRename() */ if( sqlite3MallocFailed() ) goto exit_rename_table; assert( pSrc->nSrc==1 ); pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase); if( !pTab ) goto exit_rename_table; -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - sqlite3ErrorMsg(pParse, "virtual tables may not be altered"); - goto exit_rename_table; - } -#endif iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); zDb = db->aDb[iDb].zName; @@ -325,17 +320,36 @@ void sqlite3AlterRenameTable( } #endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) && pTab->pMod->pModule->xRename ){ + isVirtualRename = 1; + } +#endif + /* Begin a transaction and code the VerifyCookie for database iDb. ** Then modify the schema cookie (since the ALTER TABLE modifies the - ** schema). + ** schema). Open a statement transaction if the table is a virtual + ** table. */ v = sqlite3GetVdbe(pParse); if( v==0 ){ goto exit_rename_table; } - sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3BeginWriteOperation(pParse, isVirtualRename, iDb); sqlite3ChangeCookie(db, v, iDb); + /* If this is a virtual table, invoke the xRename() function if + ** one is defined. The xRename() callback will modify the names + ** of any resources used by the v-table implementation (including other + ** SQLite tables) that are identified by the name of the virtual table. + */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( isVirtualRename ){ + sqlite3VdbeOp3(v, OP_String8, 0, 0, zName, 0); + sqlite3VdbeOp3(v, OP_VRename, 0, 0, (const char*)pTab->pVtab, P3_VTAB); + } +#endif + /* figure out how many UTF-8 characters are in zName */ zTabName = pTab->zName; nTabName = sqlite3Utf8CharLen(zTabName, -1); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index f8e02c5dc8..7bc4feb61b 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -30,7 +30,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.216 2007/06/27 10:21:39 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.217 2007/06/27 15:53:35 danielk1977 Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -2403,6 +2403,8 @@ struct sqlite3_module { int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), void **ppArg); + + int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); }; /* diff --git a/src/test8.c b/src/test8.c index 1267a1ec58..1c19c563cd 100644 --- a/src/test8.c +++ b/src/test8.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test8.c,v 1.46 2007/04/18 17:04:01 danielk1977 Exp $ +** $Id: test8.c,v 1.47 2007/06/27 15:53:35 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -61,6 +61,8 @@ struct echo_vtab { Tcl_Interp *interp; /* Tcl interpreter containing debug variables */ sqlite3 *db; /* Database connection */ + int isPattern; + char *zThis; /* Name of the echo table */ char *zTableName; /* Name of the real table */ char *zLogName; /* Name of the log table */ int nCol; /* Number of columns in the real table */ @@ -74,6 +76,46 @@ struct echo_cursor { sqlite3_stmt *pStmt; }; +/* +** Convert an SQL-style quoted string into a normal string by removing +** the quote characters. The conversion is done in-place. If the +** input does not begin with a quote character, then this routine +** is a no-op. +** +** Examples: +** +** "abc" becomes abc +** 'xyz' becomes xyz +** [pqr] becomes pqr +** `mno` becomes mno +*/ +static void dequoteString(char *z){ + int quote; + int i, j; + if( z==0 ) return; + quote = z[0]; + switch( quote ){ + case '\'': break; + case '"': break; + case '`': break; /* For MySQL compatibility */ + case '[': quote = ']'; break; /* For MS SqlServer compatibility */ + default: return; + } + for(i=1, j=0; z[i]; i++){ + if( z[i]==quote ){ + if( z[i+1]==quote ){ + z[j++] = quote; + i++; + }else{ + z[j++] = 0; + break; + } + }else{ + z[j++] = z[i]; + } + } +} + /* ** Retrieve the column names for the table named zTab via database ** connection db. SQLITE_OK is returned on success, or an sqlite error @@ -256,18 +298,16 @@ static void appendToEchoModule(Tcl_Interp *interp, const char *zArg){ */ static int echoDeclareVtab( echo_vtab *pVtab, - sqlite3 *db, - int argc, - const char *const*argv + sqlite3 *db ){ int rc = SQLITE_OK; - if( argc>=4 ){ + if( pVtab->zTableName ){ sqlite3_stmt *pStmt = 0; sqlite3_prepare(db, "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?", -1, &pStmt, 0); - sqlite3_bind_text(pStmt, 1, argv[3], -1, 0); + sqlite3_bind_text(pStmt, 1, pVtab->zTableName, -1, 0); if( sqlite3_step(pStmt)==SQLITE_ROW ){ int rc2; const char *zCreateTable = (const char *)sqlite3_column_text(pStmt, 0); @@ -282,12 +322,11 @@ static int echoDeclareVtab( rc = SQLITE_ERROR; } } - if( rc==SQLITE_OK ){ - rc = getColumnNames(db, argv[3], &pVtab->aCol, &pVtab->nCol); + rc = getColumnNames(db, pVtab->zTableName, &pVtab->aCol, &pVtab->nCol); } if( rc==SQLITE_OK ){ - rc = getIndexArray(db, argv[3], pVtab->nCol, &pVtab->aIndex); + rc = getIndexArray(db, pVtab->zTableName, pVtab->nCol, &pVtab->aIndex); } } @@ -302,6 +341,7 @@ static int echoDestructor(sqlite3_vtab *pVtab){ echo_vtab *p = (echo_vtab*)pVtab; sqliteFree(p->aIndex); sqliteFree(p->aCol); + sqliteFree(p->zThis); sqliteFree(p->zTableName); sqliteFree(p->zLogName); sqliteFree(p); @@ -331,13 +371,29 @@ static int echoConstructor( pVtab->interp = (Tcl_Interp *)pAux; pVtab->db = db; - /* Allocate echo_vtab.zTableName */ - pVtab->zTableName = sqlite3MPrintf("%s", argv[3]); - if( !pVtab->zTableName ){ + /* Allocate echo_vtab.zThis */ + pVtab->zThis = sqlite3MPrintf("%s", argv[2]); + if( !pVtab->zThis ){ echoDestructor((sqlite3_vtab *)pVtab); return SQLITE_NOMEM; } + /* Allocate echo_vtab.zTableName */ + if( argc>3 ){ + pVtab->zTableName = sqlite3MPrintf("%s", argv[3]); + dequoteString(pVtab->zTableName); + if( pVtab->zTableName && pVtab->zTableName[0]=='*' ){ + char *z = sqlite3MPrintf("%s%s", argv[2], &(pVtab->zTableName[1])); + sqliteFree(pVtab->zTableName); + pVtab->zTableName = z; + pVtab->isPattern = 1; + } + if( !pVtab->zTableName ){ + echoDestructor((sqlite3_vtab *)pVtab); + return SQLITE_NOMEM; + } + } + /* Log the arguments to this function to Tcl var ::echo_module */ for(i=0; iinterp, argv[i]); @@ -347,7 +403,7 @@ static int echoConstructor( ** structure. If an error occurs, delete the sqlite3_vtab structure and ** return an error code. */ - if( echoDeclareVtab(pVtab, db, argc, argv) ){ + if( echoDeclareVtab(pVtab, db) ){ echoDestructor((sqlite3_vtab *)pVtab); return SQLITE_ERROR; } @@ -975,6 +1031,21 @@ static int echoFindFunction( return 1; } +static int echoRename(sqlite3_vtab *vtab, const char *zNewName){ + int rc = SQLITE_OK; + echo_vtab *p = (echo_vtab *)vtab; + + if( p->isPattern ){ + int nThis = strlen(p->zThis); + char *zSql = sqlite3MPrintf("ALTER TABLE %s RENAME TO %s%s", + p->zTableName, zNewName, &p->zTableName[nThis] + ); + rc = sqlite3_exec(p->db, zSql, 0, 0, 0); + } + + return rc; +} + /* ** A virtual table module that merely "echos" the contents of another ** table (like an SQL VIEW). @@ -999,6 +1070,7 @@ static sqlite3_module echoModule = { echoCommit, /* xCommit - commit transaction */ echoRollback, /* xRollback - rollback transaction */ echoFindFunction, /* xFindFunction - function overloading */ + echoRename, /* xRename - rename the table */ }; /* diff --git a/src/vdbe.c b/src/vdbe.c index 688dcd7761..a090b22eba 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.634 2007/06/26 12:52:34 danielk1977 Exp $ +** $Id: vdbe.c,v 1.635 2007/06/27 15:53:35 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -2408,6 +2408,7 @@ case OP_Statement: { /* no-push */ assert( sqlite3BtreeIsInTrans(pBt) ); if( !sqlite3BtreeIsInStmt(pBt) ){ rc = sqlite3BtreeBeginStmt(pBt); + p->openedStatement = 1; } } break; @@ -4999,6 +5000,30 @@ case OP_VNext: { /* no-push */ } #endif /* SQLITE_OMIT_VIRTUALTABLE */ +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VRename * * P3 +** +** P3 is a pointer to a virtual table object, an sqlite3_vtab structure. +** This opcode invokes the corresponding xRename method. The value +** on the top of the stack is popped and passed as the zName argument +** to the xRename method. +*/ +case OP_VRename: { /* no-push */ + sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3); + assert( pVtab->pModule->xRename ); + + Stringify(pTos, encoding); + + if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; + sqlite3VtabLock(pVtab); + rc = pVtab->pModule->xRename(pVtab, pTos->z); + sqlite3VtabUnlock(db, pVtab); + if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; + + popStack(&pTos, 1); + break; +} +#endif #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VUpdate P1 P2 P3 diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 472ce743a7..78550c4347 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -343,6 +343,7 @@ struct Vdbe { #ifdef SQLITE_DEBUG FILE *trace; /* Write an execution trace here, if not NULL */ #endif + int openedStatement; /* True if this VM has opened a statement journal */ #ifdef SQLITE_SSE int fetchId; /* Statement number used by sqlite3_fetch_statement */ int lru; /* Counter used for LRU cache replacement */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 1bef9976ba..b3d92c4276 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -299,18 +299,23 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){ #endif ){ if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; - }else if( opcode==OP_Halt ){ + } + if( opcode==OP_Halt ){ if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){ doesStatementRollback = 1; } }else if( opcode==OP_Statement ){ hasStatementBegin = 1; +#ifndef SQLITE_OMIT_VIRTUALTABLE + }else if( opcode==OP_VUpdate || opcode==OP_VRename ){ + doesStatementRollback = 1; }else if( opcode==OP_VFilter ){ int n; assert( p->nOp - i >= 3 ); assert( pOp[-2].opcode==OP_Integer ); n = pOp[-2].p1; if( n>nMaxArgs ) nMaxArgs = n; +#endif } if( opcodeNoPush(opcode) ){ nMaxStack--; @@ -898,6 +903,7 @@ void sqlite3VdbeMakeReady( p->nChange = 0; p->cacheCtr = 1; p->minWriteFileFormat = 255; + p->openedStatement = 0; #ifdef VDBE_PROFILE { int i; @@ -1447,7 +1453,9 @@ int sqlite3VdbeHalt(Vdbe *p){ } }else if( !xFunc ){ if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ - xFunc = sqlite3BtreeCommitStmt; + if( p->openedStatement ){ + xFunc = sqlite3BtreeCommitStmt; + } }else if( p->errorAction==OE_Abort ){ xFunc = sqlite3BtreeRollbackStmt; }else{ diff --git a/test/vtab1.test b/test/vtab1.test index b0eb78365b..98d5625fab 100644 --- a/test/vtab1.test +++ b/test/vtab1.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is creating and dropping virtual tables. # -# $Id: vtab1.test,v 1.42 2007/03/30 14:56:35 danielk1977 Exp $ +# $Id: vtab1.test,v 1.43 2007/06/27 15:53:35 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -243,7 +243,6 @@ do_test vtab1-2.4 { # echo module has not been registered with this database connection. # do_test vtab1.2.6 { -breakpoint catchsql { PRAGMA table_info(t1); } } {1 {no such module: echo}} @@ -890,6 +889,44 @@ do_test vtab1.11-5 { } } {{2 1} {2 2}} +#---------------------------------------------------------------------- +# Test the outcome if a constraint is encountered half-way through +# a multi-row INSERT that is inside a transaction +# +do_test vtab1.12-1 { + execsql { + CREATE TABLE b(a, b, c); + CREATE TABLE c(a UNIQUE, b, c); + INSERT INTO b VALUES(1, 'A', 'B'); + INSERT INTO b VALUES(2, 'C', 'D'); + INSERT INTO b VALUES(3, 'E', 'F'); + INSERT INTO c VALUES(3, 'G', 'H'); + CREATE VIRTUAL TABLE echo_c USING echo(c); + } +} {} + +# First test outside of a transaction. +do_test vtab1.12-2 { + catchsql { INSERT INTO echo_c SELECT * FROM b; } +} {1 {constraint failed}} +do_test vtab1.12-3 { + execsql { SELECT * FROM c } +} {3 G H} + +breakpoint + +# Now the real test - wrapped in a transaction. +do_test vtab1.12-4 { + execsql {BEGIN} + catchsql { INSERT INTO echo_c SELECT * FROM b; } +} {1 {constraint failed}} +do_test vtab1.12-5 { + execsql { SELECT * FROM c } +} {3 G H} +do_test vtab1.12-6 { + execsql { COMMIT } + execsql { SELECT * FROM c } +} {3 G H} unset -nocomplain echo_module_begin_fail finish_test diff --git a/test/vtab5.test b/test/vtab5.test index 36dad9bb56..4fd678c052 100644 --- a/test/vtab5.test +++ b/test/vtab5.test @@ -10,7 +10,7 @@ #*********************************************************************** # This file implements regression tests for SQLite library. # -# $Id: vtab5.test,v 1.6 2006/06/21 12:36:26 danielk1977 Exp $ +# $Id: vtab5.test,v 1.7 2007/06/27 15:53:35 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -140,13 +140,14 @@ do_test vtab5.4.2 { } } {1 {virtual tables may not be altered}} -# Test that it is impossible to add a column to a virtual table. +# Test that it is impossible to rename a virtual table. +# UPDATE: It is now possible. # -do_test vtab5.4.3 { - catchsql { - ALTER TABLE echo_strings RENAME TO echo_strings2; - } -} {1 {virtual tables may not be altered}} +# do_test vtab5.4.3 { +# catchsql { +# ALTER TABLE echo_strings RENAME TO echo_strings2; +# } +# } {1 {virtual tables may not be altered}} finish_test diff --git a/test/vtab_alter.test b/test/vtab_alter.test new file mode 100644 index 0000000000..fddd76f862 --- /dev/null +++ b/test/vtab_alter.test @@ -0,0 +1,104 @@ +# 2007 June 26 +# +# 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. The +# focus of this file is testing the ALTER TABLE ... RENAME TO +# command on virtual tables. +# +# $Id: vtab_alter.test,v 1.1 2007/06/27 15:53:35 danielk1977 Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +ifcapable !vtab { + finish_test + return +} + +# Register the echo module. +# +# This test uses a special feature of the echo module. If the name +# of the virtual table is a prefix of the name of the underlying +# real table (for example if the v-table is "tbl" and the real table +# is "tbl_base"), then the name of the real table is modified +# when an "ALTER TABLE ... RENAME TO" is executed on the v-table. +# For example: +# +# sqlite> CREATE TABLE t1_base(a, b, c); +# sqlite> CREATE VIRTUAL TABLE t1 USING(t1_base); +# sqlite> ALTER TABLE t1 RENAME TO t2; +# sqlite> SELECT tbl_name FROM sqlite_master; +# t2_base +# t2 +# +register_echo_module [sqlite3_connection_pointer db] + + +# Try to rename an echo table. Make sure nothing terrible happens. +# +do_test vtab_alter-1.1 { + execsql { CREATE TABLE t1(a, b VARCHAR, c INTEGER) } +} {} +do_test vtab_alter-1.2 { + execsql { CREATE VIRTUAL TABLE t1echo USING echo(t1) } +} {} +do_test vtab_alter-1.3 { + catchsql { SELECT * FROM t1echo } +} {0 {}} +do_test vtab_alter-1.4 { + execsql { ALTER TABLE t1echo RENAME TO new } +} {} +do_test vtab_alter-1.5 { + catchsql { SELECT * FROM t1echo } +} {1 {no such table: t1echo}} +do_test vtab_alter-1.6 { + catchsql { SELECT * FROM new } +} {0 {}} + +# Try to rename an echo table that renames it's base table. Make +# sure nothing terrible happens. +# +do_test vtab_alter-2.1 { + execsql { + DROP TABLE new; + DROP TABLE t1; + CREATE TABLE t1_base(a, b, c); + CREATE VIRTUAL TABLE t1 USING echo('*_base'); + } +} {} +do_test vtab_alter-2.2 { + execsql { + INSERT INTO t1_base VALUES(1, 2, 3); + SELECT * FROM t1; + } +} {1 2 3} +do_test vtab_alter-2.3 { + execsql { ALTER TABLE t1 RENAME TO x } +} {} +do_test vtab_alter-2.4 { + execsql { SELECT * FROM x; } +} {1 2 3} +do_test vtab_alter-2.5 { + execsql { SELECT * FROM x_base; } +} {1 2 3} + +# Cause an error to occur when the echo module renames it's +# backing store table. +# +do_test vtab_alter-3.1 { + execsql { CREATE TABLE y_base(a, b, c) } + catchsql { ALTER TABLE x RENAME TO y } +} {1 {SQL logic error or missing database}} +do_test vtab_alter-3.2 { + execsql { SELECT * FROM x } +} {1 2 3} + +finish_test +