From: drh Date: Tue, 12 May 2009 17:46:53 +0000 (+0000) Subject: Move the sqlite3MinimumFileFormat() routine from build.c over to alter.c X-Git-Tag: version-3.6.15~120 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d3001711506af92f381a8ebdd9bf0932de0d9314;p=thirdparty%2Fsqlite.git Move the sqlite3MinimumFileFormat() routine from build.c over to alter.c since alter.c is the only code that uses it. Additional changes and cleanup to build.c to facility coverage testing. (CVS 6630) FossilOrigin-Name: 6fe3750a30ab432ed476c2ae6b58972187abc624 --- diff --git a/manifest b/manifest index 3ceec2b12b..a86a132875 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthe\sSQLITE_OPEN_EXCLUSIVE\sflag\sis\signored\sby\ssqlite3_open_v2().\nThat\sflag\sis\sto\sbe\sused\sby\sthe\sVFS\sinterface\sonly.\s\sTicket\s#3855.\s(CVS\s6629) -D 2009-05-12T13:35:12 +C Move\sthe\ssqlite3MinimumFileFormat()\sroutine\sfrom\sbuild.c\sover\sto\salter.c\nsince\salter.c\sis\sthe\sonly\scode\sthat\suses\sit.\s\sAdditional\schanges\sand\ncleanup\sto\sbuild.c\sto\sfacility\scoverage\stesting.\s(CVS\s6630) +D 2009-05-12T17:46:54 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 583e87706abc3026960ed759aff6371faf84c211 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -99,7 +99,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad -F src/alter.c 8ab5824bde0a03dae5829f61557ab7c72757000a +F src/alter.c f0430ee68d8d80711155ddf27876abf218903b03 F src/analyze.c e239496cfb5394ac8867f1c112905ddab8d01cd9 F src/attach.c 3b99611f04926fc69c35b1145603fc3ddb0ca967 F src/auth.c 98db07c2088455797678eb1031f42d4d94d18a71 @@ -109,7 +109,7 @@ F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c F src/btree.c 7c4b02afea7efb561361f20408414fec68df898c F src/btree.h 58d876d3ed944a8f4f1fd0e67024b385243fc9dd F src/btreeInt.h df64030d632f8c8ac217ed52e8b6b3eacacb33a5 -F src/build.c 65caba758665cc1f511864329940aac19344e2db +F src/build.c f796caf373c56bfdfea82bbf2a986970be7086d6 F src/callback.c bf295cfdc065b56cc49a5f6452126dc4ffe0ff5b F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0 F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3 @@ -729,7 +729,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 6572b438a02cc44546174e132dfbdc1d141cd451 -R 666fd2a04f0518bbc32649a56bab9cef +P c37f0279ebfaf76b4086e6d16b6e12633424c27d +R 0b3cc9c4878bf4b27ccc7fb166bcea2d U drh -Z e60d2b410985dcb25fdd3decf9513c5e +Z 77a2a07efa50be8c1aaf1350b336a029 diff --git a/manifest.uuid b/manifest.uuid index 60d9dd4ddd..d82019cf0c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c37f0279ebfaf76b4086e6d16b6e12633424c27d \ No newline at end of file +6fe3750a30ab432ed476c2ae6b58972187abc624 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 11f8452cb0..807bb8daa1 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.57 2009/04/16 16:30:18 drh Exp $ +** $Id: alter.c,v 1.58 2009/05/12 17:46:54 drh Exp $ */ #include "sqliteInt.h" @@ -426,6 +426,31 @@ exit_rename_table: } +/* +** Generate code to make sure the file format number is at least minFormat. +** The generated code will increase the file format number if necessary. +*/ +void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ + Vdbe *v; + v = sqlite3GetVdbe(pParse); + /* The VDBE should have been allocated before this routine is called. + ** If that allocation failed, we would have quit before reaching this + ** point */ + if( ALWAYS(v) ){ + int r1 = sqlite3GetTempReg(pParse); + int r2 = sqlite3GetTempReg(pParse); + int j1; + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, 1); + sqlite3VdbeUsesBtree(v, iDb); + sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); + j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 1, r2); + sqlite3VdbeJumpHere(v, j1); + sqlite3ReleaseTempReg(pParse, r1); + sqlite3ReleaseTempReg(pParse, r2); + } +} + /* ** This function is called after an "ALTER TABLE ... ADD" statement ** has been parsed. Argument pColDef contains the text of the new diff --git a/src/build.c b/src/build.c index d1e3dfe5ed..0eb13bde32 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.539 2009/05/12 00:40:13 drh Exp $ +** $Id: build.c,v 1.540 2009/05/12 17:46:54 drh Exp $ */ #include "sqliteInt.h" @@ -2156,10 +2156,10 @@ void sqlite3CreateForeignKey( char *z; assert( pTo!=0 ); - if( p==0 || pParse->nErr || IN_DECLARE_VTAB ) goto fk_end; + if( p==0 || NEVER(pParse->nErr) || IN_DECLARE_VTAB ) goto fk_end; if( pFromCol==0 ){ int iCol = p->nCol-1; - if( iCol<0 ) goto fk_end; + if( NEVER(iCol<0) ) goto fk_end; if( pToCol && pToCol->nExpr!=1 ){ sqlite3ErrorMsg(pParse, "foreign key on %s" " should reference only one column of table %T", @@ -2376,7 +2376,11 @@ void sqlite3CreateIndex( int nExtra = 0; char *zExtra; - if( pParse->nErr || db->mallocFailed || IN_DECLARE_VTAB ){ + assert( pStart==0 || pEnd!=0 ); /* pEnd must be non-NULL if pStart is */ + if( NEVER(pParse->nErr>0) || db->mallocFailed || IN_DECLARE_VTAB ){ + goto exit_create_index; + } + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto exit_create_index; } @@ -2400,7 +2404,7 @@ void sqlite3CreateIndex( */ if( !db->init.busy ){ pTab = sqlite3SrcListLookup(pParse, pTblName); - if( pName2 && pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ + if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ iDb = 1; } } @@ -2425,7 +2429,8 @@ void sqlite3CreateIndex( } pDb = &db->aDb[iDb]; - if( pTab==0 || pParse->nErr ) goto exit_create_index; + assert( pTab!=0 ); + assert( pParse->nErr==0 ); if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 && memcmp(&pTab->zName[7],"altertab_",9)!=0 ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); @@ -2459,13 +2464,11 @@ void sqlite3CreateIndex( */ if( pName ){ zName = sqlite3NameFromToken(db, pName); - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; if( zName==0 ) goto exit_create_index; if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto exit_create_index; } if( !db->init.busy ){ - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; if( sqlite3FindTable(db, zName, 0)!=0 ){ sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); goto exit_create_index; @@ -2520,10 +2523,14 @@ void sqlite3CreateIndex( ** specified collation sequence names. */ for(i=0; inExpr; i++){ - Expr *pExpr; - CollSeq *pColl; - if( (pExpr = pList->a[i].pExpr)!=0 && (pColl = pExpr->pColl)!=0 ){ - nExtra += (1 + sqlite3Strlen30(pColl->zName)); + Expr *pExpr = pList->a[i].pExpr; + if( pExpr ){ + CollSeq *pColl = pExpr->pColl; + /* Either pColl!=0 or there was an OOM failure. But if an OOM + ** failure we have quit before reaching this point. */ + if( ALWAYS(pColl) ){ + nExtra += (1 + sqlite3Strlen30(pColl->zName)); + } } } @@ -2568,6 +2575,12 @@ void sqlite3CreateIndex( /* Scan the names of the columns of the table to be indexed and ** load the column indices into the Index structure. Report an error ** if any column is not found. + ** + ** TODO: Add a test to make sure that the same column is not named + ** more than once within the same index. Only the first instance of + ** the column will ever be used by the optimizer. Note that using the + ** same column more than once cannot be an error because that would + ** break backwards compatibility - it needs to be a warning. */ for(i=0, pListItem=pList->a; inExpr; i++, pListItem++){ const char *zColName = pListItem->zName; @@ -2583,18 +2596,21 @@ void sqlite3CreateIndex( pTab->zName, zColName); goto exit_create_index; } - /* TODO: Add a test to make sure that the same column is not named - ** more than once within the same index. Only the first instance of - ** the column will ever be used by the optimizer. Note that using the - ** same column more than once cannot be an error because that would - ** break backwards compatibility - it needs to be a warning. - */ pIndex->aiColumn[i] = j; - if( pListItem->pExpr && pListItem->pExpr->pColl ){ - assert( pListItem->pExpr->pColl ); + /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of + ** the way the "idxlist" non-terminal is constructed by the parser, + ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl + ** must exist or else there must have been an OOM error. But if there + ** was an OOM error, we would never reach this point. */ + if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){ + int nColl; + zColl = pListItem->pExpr->pColl->zName; + nColl = sqlite3Strlen30(zColl) + 1; + assert( nExtra>=nColl ); + memcpy(zExtra, zColl, nColl); zColl = zExtra; - sqlite3_snprintf(nExtra, zExtra, "%s", pListItem->pExpr->pColl->zName); - zExtra += (sqlite3Strlen30(zColl) + 1); + zExtra += nColl; + nExtra -= nColl; }else{ zColl = pTab->aCol[j].zColl; if( !zColl ){ @@ -2623,6 +2639,14 @@ void sqlite3CreateIndex( ** so, don't bother creating this one. This only applies to ** automatically created indices. Users can do as they wish with ** explicit indices. + ** + ** Two UNIQUE or PRIMARY KEY constraints are considered equivalent + ** (and thus suppressing the second one) even if they have different + ** sort orders. + ** + ** If there are different collating sequences or if the columns of + ** the constraint occur in different orders, then the constraints are + ** considered distinct and both result in separate indices. */ Index *pIdx; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ @@ -2633,10 +2657,11 @@ void sqlite3CreateIndex( if( pIdx->nColumn!=pIndex->nColumn ) continue; for(k=0; knColumn; k++){ - const char *z1 = pIdx->azColl[k]; - const char *z2 = pIndex->azColl[k]; + const char *z1; + const char *z2; if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break; - if( pIdx->aSortOrder[k]!=pIndex->aSortOrder[k] ) break; + z1 = pIdx->azColl[k]; + z2 = pIndex->azColl[k]; if( z1!=z2 && sqlite3StrICmp(z1, z2) ) break; } if( k==pIdx->nColumn ){ @@ -2695,7 +2720,7 @@ void sqlite3CreateIndex( ** has just been created, it contains no data and the index initialization ** step can be skipped. */ - else if( db->init.busy==0 ){ + else{ /* if( db->init.busy==0 ) */ Vdbe *v; char *zStmt; int iMem = ++pParse->nMem; @@ -2712,7 +2737,8 @@ void sqlite3CreateIndex( /* Gather the complete text of the CREATE INDEX statement into ** the zStmt variable */ - if( pStart && pEnd ){ + if( pStart ){ + assert( pEnd!=0 ); /* A named index with an explicit CREATE INDEX statement */ zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s", onError==OE_None ? "" : " UNIQUE", @@ -2750,8 +2776,9 @@ void sqlite3CreateIndex( /* When adding an index to the list of indices for a table, make ** sure all indices labeled OE_Replace come after all those labeled - ** OE_Ignore. This is necessary for the correct operation of UPDATE - ** and INSERT. + ** OE_Ignore. This is necessary for the correct constraint check + ** processing (in sqlite3GenerateConstraintChecks()) as part of + ** UPDATE and INSERT statements. */ if( db->init.busy || pTblName==0 ){ if( onError!=OE_Replace || pTab->pIndex==0 @@ -2781,28 +2808,6 @@ exit_create_index: return; } -/* -** Generate code to make sure the file format number is at least minFormat. -** The generated code will increase the file format number if necessary. -*/ -void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ - Vdbe *v; - v = sqlite3GetVdbe(pParse); - if( v ){ - int r1 = sqlite3GetTempReg(pParse); - int r2 = sqlite3GetTempReg(pParse); - int j1; - sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, 1); - sqlite3VdbeUsesBtree(v, iDb); - sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); - j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 1, r2); - sqlite3VdbeJumpHere(v, j1); - sqlite3ReleaseTempReg(pParse, r1); - sqlite3ReleaseTempReg(pParse, r2); - } -} - /* ** Fill the Index.aiRowEst[] array with default information - information ** to be used when we have not run the ANALYZE command. @@ -2848,7 +2853,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){ sqlite3 *db = pParse->db; int iDb; - if( pParse->nErr || db->mallocFailed ){ + if( NEVER(pParse->nErr>0) || db->mallocFailed ){ goto exit_drop_index; } assert( pName->nSrc==1 ); @@ -3104,7 +3109,10 @@ SrcList *sqlite3SrcListEnlarge( ** ** sqlite3SrcListAppend(D,A,B,C); ** -** Then C is the table name and B is the database name. +** Then C is the table name and B is the database name. If C is defined +** then so is B. In other words, we never have a case where: +** +** sqlite3SrcListAppend(D,A,0,C); */ SrcList *sqlite3SrcListAppend( sqlite3 *db, /* Connection to notify of malloc failures */ @@ -3113,6 +3121,7 @@ SrcList *sqlite3SrcListAppend( Token *pDatabase /* Database of the table */ ){ struct SrcList_item *pItem; + assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */ if( pList==0 ){ pList = sqlite3DbMallocZero(db, sizeof(SrcList) ); if( pList==0 ) return 0; @@ -3127,7 +3136,7 @@ SrcList *sqlite3SrcListAppend( if( pDatabase && pDatabase->z==0 ){ pDatabase = 0; } - if( pDatabase && pTable ){ + if( pDatabase ){ Token *pTemp = pDatabase; pDatabase = pTable; pTable = pTemp; @@ -3271,10 +3280,14 @@ void sqlite3BeginTransaction(Parse *pParse, int type){ Vdbe *v; int i; - if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || db->mallocFailed ) return; - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; - + assert( pParse!=0 ); + db = pParse->db; + assert( db!=0 ); + if( db->aDb[0].pBt==0 ) return; +// if( pParse->nErr || db->mallocFailed ) return; + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){ + return; + } v = sqlite3GetVdbe(pParse); if( !v ) return; if( type!=TK_DEFERRED ){ @@ -3293,10 +3306,14 @@ void sqlite3CommitTransaction(Parse *pParse){ sqlite3 *db; Vdbe *v; - if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || db->mallocFailed ) return; - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; - + assert( pParse!=0 ); + db = pParse->db; + assert( db!=0 ); + if( db->aDb[0].pBt==0 ) return; +// if( pParse->nErr || db->mallocFailed ) return; + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ){ + return; + } v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 0); @@ -3310,10 +3327,14 @@ void sqlite3RollbackTransaction(Parse *pParse){ sqlite3 *db; Vdbe *v; - if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || db->mallocFailed ) return; - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; - + assert( pParse!=0 ); + db = pParse->db; + assert( db!=0 ); + if( db->aDb[0].pBt==0 ) return; +// if( pParse->nErr || db->mallocFailed ) return; + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ){ + return; + } v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 1); @@ -3530,20 +3551,18 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ return; } - if( pName1==0 || pName1->z==0 ){ + if( pName1==0 || NEVER(pName1->z==0) ){ reindexDatabases(pParse, 0); return; - }else if( pName2==0 || pName2->z==0 ){ + }else if( NEVER(pName2==0) || pName2->z==0 ){ char *zColl; assert( pName1->z ); zColl = sqlite3NameFromToken(pParse->db, pName1); if( !zColl ) return; pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); if( pColl ){ - if( zColl ){ - reindexDatabases(pParse, zColl); - sqlite3DbFree(db, zColl); - } + reindexDatabases(pParse, zColl); + sqlite3DbFree(db, zColl); return; } sqlite3DbFree(db, zColl);