]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Move the sqlite3MinimumFileFormat() routine from build.c over to alter.c
authordrh <drh@noemail.net>
Tue, 12 May 2009 17:46:53 +0000 (17:46 +0000)
committerdrh <drh@noemail.net>
Tue, 12 May 2009 17:46:53 +0000 (17:46 +0000)
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

manifest
manifest.uuid
src/alter.c
src/build.c

index 3ceec2b12b1048e2f048c54558410fc3edf0320e..a86a132875cdae8e0464c5c870f18e4d0f9a23d8 100644 (file)
--- 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
index 60d9dd4ddd6b8aa8a31796fffbbfbef048aac6ce..d82019cf0c6fc747a7ba0732cd009aca66004d99 100644 (file)
@@ -1 +1 @@
-c37f0279ebfaf76b4086e6d16b6e12633424c27d
\ No newline at end of file
+6fe3750a30ab432ed476c2ae6b58972187abc624
\ No newline at end of file
index 11f8452cb0f570add453740a6ac9d26728bc0561..807bb8daa1c860f260ae17dfee105e723552ecb0 100644 (file)
@@ -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
index d1e3dfe5ed3c2b2f614e2a5d7fe656aea40a65ef..0eb13bde32500ac20e66bc52536c989c7cf183ca 100644 (file)
@@ -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; i<pList->nExpr; 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; i<pList->nExpr; 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; k<pIdx->nColumn; 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);