]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Remove "PRAGMA ota_mode".
authordan <dan@noemail.net>
Tue, 3 Feb 2015 15:56:08 +0000 (15:56 +0000)
committerdan <dan@noemail.net>
Tue, 3 Feb 2015 15:56:08 +0000 (15:56 +0000)
FossilOrigin-Name: 1c111447a07687c30ed4ad5a6c27a169c85b7ea6

16 files changed:
ext/ota/ota3.test
ext/ota/ota4.test
ext/ota/sqlite3ota.c
manifest
manifest.uuid
src/btree.c
src/delete.c
src/insert.c
src/main.c
src/pragma.c
src/sqlite.h.in
src/sqliteInt.h
src/test1.c
src/trigger.c
src/vdbeblob.c
tool/mkpragmatab.tcl

index 8921c12b359596644c03ca695909486d64506530..74dba1f16651a7d916d2672a3b971f7ab82debf0 100644 (file)
@@ -63,19 +63,29 @@ do_execsql_test 2.0 {
   CREATE INDEX i1 ON x1(b, c);
 } {}
 
-do_test 2.1 {
-  sqlite3 db2 ota.db
-  db2 eval {
+foreach {tn otadb} {
+  1 {
     CREATE TABLE data_x1(a, b, c, ota_control);
     INSERT INTO data_x1 VALUES(NULL, 'a', 'b', 0);
   }
-  db2 close
-  list [catch { run_ota test.db ota.db } msg] $msg
-} {1 {SQLITE_MISMATCH - datatype mismatch}}
 
-do_execsql_test 2.2 {
-  PRAGMA integrity_check;
-} {ok}
+  2 {
+    CREATE TABLE data_x1(c, b, a, ota_control);
+    INSERT INTO data_x1 VALUES('b', 'a', NULL, 0);
+  }
+} {
+  do_test 2.$tn.1 {
+    forcedelete ota.db
+    sqlite3 db2 ota.db
+    db2 eval $otadb
+    db2 close
+    list [catch { run_ota test.db ota.db } msg] $msg
+  } {1 {SQLITE_MISMATCH - datatype mismatch}}
+
+  do_execsql_test 2.1.2 {
+    PRAGMA integrity_check;
+  } {ok}
+}
 
 #--------------------------------------------------------------------
 # Test that missing columns are detected.
@@ -102,4 +112,28 @@ do_execsql_test 2.2 {
   PRAGMA integrity_check;
 } {ok}
 
+# Also extra columns.
+#
+do_execsql_test 2.3 {
+  CREATE TABLE x2(a INTEGER PRIMARY KEY, b, c);
+  CREATE INDEX i2 ON x2(b, c);
+} {}
+
+do_test 2.4 {
+  forcedelete ota.db
+  sqlite3 db2 ota.db
+  db2 eval {
+    CREATE TABLE data_x2(a, b, c, d, ota_control);
+    INSERT INTO data_x2 VALUES(1, 'a', 2, 3, 0);
+  }
+  db2 close
+  breakpoint
+  list [catch { run_ota test.db ota.db } msg] $msg
+} {1 SQLITE_ERROR}
+
+do_execsql_test 2.5 {
+  PRAGMA integrity_check;
+} {ok}
+
 finish_test
+
index b14225dc528d41419eb5200eb0969c2a044915e1..a12cbd8b7be099041a747e6c70a75b283f5e7a78 100644 (file)
@@ -124,110 +124,5 @@ do_catchsql_test 1.5.4 {
   SELECT * FROM t1;
 } {1 {database is locked}}
 
-#-------------------------------------------------------------------------
-# These tests - ota4-2.* - aim to verify some properties of the ota_mode
-# pragma.
-#
-#   1. Check that UNIQUE constraints are not tested in ota_mode.
-#   2. Except for (real) PRIMARY KEY constraints.
-#   3. Check that all non-temporary triggers are ignored.
-#
-reset_db
-do_execsql_test 2.1.1 {
-  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
-  CREATE UNIQUE INDEX i1 ON t1(b);
-  INSERT INTO t1 VALUES(1, 2, 3);
-  INSERT INTO t1 VALUES(2, 4, 6);
-}
-
-do_execsql_test 2.1.2 {
-  PRAGMA ota_mode = 1;
-  INSERT INTO t1 VALUES(3, 2, 6);
-  UPDATE t1 SET b=2 WHERE a=2;
-  SELECT * FROM t1;
-} {
-  1 2 3
-  2 2 6
-  3 2 6
-}
-
-reset_db
-do_execsql_test 2.2.1 {
-  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
-  CREATE TABLE t2(x, y, z, PRIMARY KEY(y, z)) WITHOUT ROWID;
-
-  INSERT INTO t1 VALUES(1, 2, 3);
-  INSERT INTO t2 VALUES(4, 5, 6);
-  PRAGMA ota_mode = 1;
-}
-do_catchsql_test 2.2.2 {
-  INSERT INTO t1 VALUES(1, 'two', 'three');
-} {1 {UNIQUE constraint failed: t1.a}}
-do_catchsql_test 2.2.3 {
-  INSERT INTO t2 VALUES('four', 5, 6);
-} {1 {UNIQUE constraint failed: t2.y, t2.z}}
-
-reset_db
-do_execsql_test 2.3.1 {
-  CREATE TABLE t1(a, b, c);
-  CREATE TABLE log(x);
-  INSERT INTO t1 VALUES(1, 2, 3);
-
-  CREATE TRIGGER tr1 BEFORE INSERT ON t1 BEGIN
-    INSERT INTO log VALUES('permanent');
-  END;
-  CREATE TRIGGER tr2 AFTER INSERT ON t1 BEGIN
-    INSERT INTO log VALUES('permanent');
-  END;
-  CREATE TRIGGER tr3 BEFORE DELETE ON t1 BEGIN
-    INSERT INTO log VALUES('permanent');
-  END;
-  CREATE TRIGGER tr4 AFTER DELETE ON t1 BEGIN
-    INSERT INTO log VALUES('permanent');
-  END;
-  CREATE TRIGGER tr5 BEFORE UPDATE ON t1 BEGIN
-    INSERT INTO log VALUES('permanent');
-  END;
-  CREATE TRIGGER tr6 AFTER UPDATE ON t1 BEGIN
-    INSERT INTO log VALUES('permanent');
-  END;
-
-  CREATE TEMP TRIGGER ttr1 BEFORE INSERT ON t1 BEGIN
-    INSERT INTO log VALUES('temp');
-  END;
-  CREATE TEMP TRIGGER ttr2 AFTER INSERT ON t1 BEGIN
-    INSERT INTO log VALUES('temp');
-  END;
-  CREATE TEMP TRIGGER ttr3 BEFORE DELETE ON t1 BEGIN
-    INSERT INTO log VALUES('temp');
-  END;
-  CREATE TEMP TRIGGER ttr4 AFTER DELETE ON t1 BEGIN
-    INSERT INTO log VALUES('temp');
-  END;
-  CREATE TEMP TRIGGER ttr5 BEFORE UPDATE ON t1 BEGIN
-    INSERT INTO log VALUES('temp');
-  END;
-  CREATE TEMP TRIGGER ttr6 AFTER UPDATE ON t1 BEGIN
-    INSERT INTO log VALUES('temp');
-  END;
-}
-do_execsql_test 2.3.2 {
-  INSERT INTO t1 VALUES(4, 5, 6);
-  DELETE FROM t1 WHERE a = 4;
-  UPDATE t1 SET c = 6;
-  SELECT x FROM log;
-} {
-  temp permanent temp permanent temp permanent 
-  temp permanent temp permanent temp permanent
-}
-do_execsql_test 2.3.3 {
-  DELETE FROM log;
-  PRAGMA ota_mode = 1;
-  INSERT INTO t1 VALUES(4, 5, 6);
-  DELETE FROM t1 WHERE a = 4;
-  UPDATE t1 SET c = 6;
-  SELECT x FROM log;
-} {temp temp temp temp temp temp}
-
 finish_test
 
index 1727e51f1fbdcc1bb255d720687306c4d9687e53..ae45db032b0b4acc8a4271c5ba75bbab8af49c09 100644 (file)
@@ -102,8 +102,9 @@ struct OtaObjIter {
   sqlite3_stmt *pTblIter;         /* Iterate through tables */
   sqlite3_stmt *pIdxIter;         /* Index iterator */
   int nTblCol;                    /* Size of azTblCol[] array */
-  char **azTblCol;                /* Array of quoted column names */
+  char **azTblCol;                /* Array of unquoted column names */
   char **azTblType;               /* Array of column types */
+  int *aiTblOrder;                /* Order of columns in target table */
   unsigned char *abTblPk;         /* Array of flags - true for PK columns */
   int eType;
 
@@ -128,11 +129,18 @@ struct OtaObjIter {
 
 /*
 ** Values for OtaObjIter.eType
+**
+**     1: Table has an implicit rowid.
+**     2: Table has an explicit IPK column.
+**     3: Table has an external PK index.
+**     4: Table is WITHOUT ROWID.
+**     5: Table is a virtual table.
 */
-#define OTA_PK_REAL     1         /* Table has a real primary key */
-#define OTA_PK_EXTERNAL 2         /* Table has an external primary key index */
-#define OTA_PK_NONE     3         /* Table has no PK (use rowid) */
-#define OTA_PK_VTAB     4         /* Table is a virtual table (use rowid) */
+#define OTA_PK_NONE           1
+#define OTA_PK_IPK            2
+#define OTA_PK_EXTERNAL       3
+#define OTA_PK_WITHOUT_ROWID  4
+#define OTA_PK_VTAB           5
 
 /*
 ** OTA handle.
@@ -225,7 +233,7 @@ static int prepareFreeAndCollectError(
 
 /*
 ** Free the OtaObjIter.azTblCol[] and OtaObjIter.abTblPk[] arrays allocated
-** by an earlier call to otaObjIterGetCols().
+** by an earlier call to otaObjIterCacheTableInfo().
 */
 static void otaObjIterFreeCols(OtaObjIter *pIter){
   int i;
@@ -236,6 +244,7 @@ static void otaObjIterFreeCols(OtaObjIter *pIter){
   sqlite3_free(pIter->azTblCol);
   pIter->azTblCol = 0;
   pIter->azTblType = 0;
+  pIter->aiTblOrder = 0;
   pIter->abTblPk = 0;
   pIter->nTblCol = 0;
   sqlite3_free(pIter->zMask);
@@ -285,32 +294,44 @@ static int otaObjIterNext(sqlite3ota *p, OtaObjIter *pIter){
 
     /* Free any SQLite statements used while processing the previous object */ 
     otaObjIterClearStatements(pIter);
+    if( pIter->zIdx==0 ){
+      rc = sqlite3_exec(p->db, 
+          "DROP TRIGGER IF EXISTS temp.ota_insert_tr;"
+          "DROP TRIGGER IF EXISTS temp.ota_update1_tr;"
+          "DROP TRIGGER IF EXISTS temp.ota_update2_tr;"
+          "DROP TRIGGER IF EXISTS temp.ota_delete_tr;"
+          , 0, 0, &p->zErrmsg
+      );
+    }
 
-    if( pIter->bCleanup ){
-      otaObjIterFreeCols(pIter);
-      pIter->bCleanup = 0;
-      rc = sqlite3_step(pIter->pTblIter);
-      if( rc!=SQLITE_ROW ){
-        rc = sqlite3_reset(pIter->pTblIter);
-        pIter->zTbl = 0;
-      }else{
-        pIter->zTbl = (const char*)sqlite3_column_text(pIter->pTblIter, 0);
-        rc = SQLITE_OK;
-      }
-    }else{
-      if( pIter->zIdx==0 ){
-        sqlite3_bind_text(pIter->pIdxIter, 1, pIter->zTbl, -1, SQLITE_STATIC);
-      }
-      rc = sqlite3_step(pIter->pIdxIter);
-      if( rc!=SQLITE_ROW ){
-        rc = sqlite3_reset(pIter->pIdxIter);
-        pIter->bCleanup = 1;
-        pIter->zIdx = 0;
+    if( rc==SQLITE_OK ){
+      if( pIter->bCleanup ){
+        otaObjIterFreeCols(pIter);
+        pIter->bCleanup = 0;
+        rc = sqlite3_step(pIter->pTblIter);
+        if( rc!=SQLITE_ROW ){
+          rc = sqlite3_reset(pIter->pTblIter);
+          pIter->zTbl = 0;
+        }else{
+          pIter->zTbl = (const char*)sqlite3_column_text(pIter->pTblIter, 0);
+          pIter->tnum = sqlite3_column_int(pIter->pTblIter, 1);
+          rc = SQLITE_OK;
+        }
       }else{
-        pIter->zIdx = (const char*)sqlite3_column_text(pIter->pIdxIter, 0);
-        pIter->tnum = sqlite3_column_int(pIter->pIdxIter, 1);
-        pIter->bUnique = sqlite3_column_int(pIter->pIdxIter, 2);
-        rc = SQLITE_OK;
+        if( pIter->zIdx==0 ){
+          sqlite3_bind_text(pIter->pIdxIter, 1, pIter->zTbl, -1, SQLITE_STATIC);
+        }
+        rc = sqlite3_step(pIter->pIdxIter);
+        if( rc!=SQLITE_ROW ){
+          rc = sqlite3_reset(pIter->pIdxIter);
+          pIter->bCleanup = 1;
+          pIter->zIdx = 0;
+        }else{
+          pIter->zIdx = (const char*)sqlite3_column_text(pIter->pIdxIter, 0);
+          pIter->tnum = sqlite3_column_int(pIter->pIdxIter, 1);
+          pIter->bUnique = sqlite3_column_int(pIter->pIdxIter, 2);
+          rc = SQLITE_OK;
+        }
       }
     }
   }
@@ -336,8 +357,10 @@ static int otaObjIterFirst(sqlite3ota *p, OtaObjIter *pIter){
   memset(pIter, 0, sizeof(OtaObjIter));
 
   rc = prepareAndCollectError(p->db, &pIter->pTblIter, &p->zErrmsg, 
-      "SELECT substr(name, 6) FROM ota.sqlite_master "
-      "WHERE type='table' AND name LIKE 'data_%'"
+      "SELECT substr(a.name, 6), b.rootpage FROM ota.sqlite_master AS a "
+      "LEFT JOIN main.sqlite_master AS b ON "
+      "(substr(a.name, 6)==b.name) "
+      "WHERE a.type='table' AND a.name LIKE 'data_%'"
   );
 
   if( rc==SQLITE_OK ){
@@ -353,53 +376,6 @@ static int otaObjIterFirst(sqlite3ota *p, OtaObjIter *pIter){
   return otaObjIterNext(p, pIter);
 }
 
-/*
-** Allocate a buffer and populate it with the double-quoted version of the
-** string in the argument buffer, suitable for use as an SQL identifier. 
-** For example:
-**
-**      [quick `brown` fox]    ->    [`quick ``brown`` fox`]
-**
-** Assuming the allocation is successful, a pointer to the new buffer is 
-** returned. It is the responsibility of the caller to free it using 
-** sqlite3_free() at some point in the future. Or, if the allocation fails,
-** a NULL pointer is returned.
-*/
-static char *otaQuoteName(const char *zName){
-  int nName = strlen(zName);
-  char *zRet = sqlite3_malloc(nName * 2 + 2 + 1);
-  if( zRet ){
-    int i;
-    char *p = zRet;
-    *p++ = '`';
-    for(i=0; i<nName; i++){
-      if( zName[i]=='`' ) *p++ = '`';
-      *p++ = zName[i];
-    }
-    *p++ = '`';
-    *p++ = '\0';
-  }
-  return zRet;
-}
-
-/*
-** Argument zName points to a column name. Argument zQuoted also points
-** to a column name, but one that has been quoted using otaQuoteName().
-** Return true if the column names are the same, or false otherwise.
-*/
-static int otaMatchName(const char *zName, const char *zQuoted){
-  const char *p = zName;
-  const char *q = &zQuoted[1];
-  while( 1 ){
-    if( *q=='`' ) q++;
-    if( sqlite3_strnicmp(q, p, 1) ) return 0;
-    if( !*q ) break;
-    p++;
-    q++;
-  }
-  return 1;
-}
-
 /*
 ** Argument zFmt is a sqlite3_mprintf() style format string. The trailing
 ** arguments are the usual subsitution values. This function performs
@@ -432,7 +408,7 @@ static int otaMPrintfExec(sqlite3ota *p, const char *zFmt, ...){
 ** error code in the OTA handle passed as the first argument.
 */
 static void otaAllocateIterArrays(sqlite3ota *p, OtaObjIter *pIter, int nCol){
-  int nByte = sizeof(char*) * nCol * 2 + sizeof(unsigned char*) * nCol;
+  int nByte = (sizeof(char*) * 2 + sizeof(int) + sizeof(unsigned char)) * nCol;
   char **azNew;
 
   assert( p->rc==SQLITE_OK );
@@ -441,7 +417,8 @@ static void otaAllocateIterArrays(sqlite3ota *p, OtaObjIter *pIter, int nCol){
     memset(azNew, 0, nByte);
     pIter->azTblCol = azNew;
     pIter->azTblType = &azNew[nCol];
-    pIter->abTblPk = (unsigned char*)&pIter->azTblType[nCol];
+    pIter->aiTblOrder = (int*)&pIter->azTblType[nCol];
+    pIter->abTblPk = (unsigned char*)&pIter->aiTblOrder[nCol];
   }else{
     p->rc = SQLITE_NOMEM;
   }
@@ -466,50 +443,33 @@ static char *otaStrndup(const char *zStr, int nStr, int *pRc){
 }
 
 
-/*
-** Return true if zTab is the name of a virtual table within the target
-** database.
-*/
-static int otaIsVtab(sqlite3ota *p, const char *zTab){
-  int res = 0;
-  sqlite3_stmt *pSelect = 0;
-
-  if( p->rc==SQLITE_OK ){
-    p->rc = prepareAndCollectError(p->db, &pSelect, &p->zErrmsg,
-        "SELECT count(*) FROM sqlite_master WHERE name = ? AND type='table' "
-        "AND sql LIKE 'CREATE VIRTUAL TABLE%'"
-    );
-  }
-
-  if( p->rc==SQLITE_OK ){
-    sqlite3_bind_text(pSelect, 1, zTab, -1, SQLITE_STATIC);
-    if( sqlite3_step(pSelect)==SQLITE_ROW ){
-      res = sqlite3_column_int(pSelect, 0);
-    }
-    p->rc = sqlite3_finalize(pSelect);
-  }
-
-  return res;
-}
-
 /*
 ** If they are not already populated, populate the pIter->azTblCol[],
 ** pIter->abTblPk[], pIter->nTblCol and pIter->bRowid variables according to
-** the table that the iterator currently points to.
+** the table (not index) that the iterator currently points to.
 **
 ** Return SQLITE_OK if successful, or an SQLite error code otherwise. If
 ** an error does occur, an error code and error message are also left in 
 ** the OTA handle.
 */
-static int otaObjIterGetCols(sqlite3ota *p, OtaObjIter *pIter){
+static int otaObjIterCacheTableInfo(sqlite3ota *p, OtaObjIter *pIter){
   if( pIter->azTblCol==0 ){
     sqlite3_stmt *pStmt = 0;
     int nCol = 0;
     int i;                        /* for() loop iterator variable */
     int rc2;                      /* sqlite3_finalize() return value */
     int bOtaRowid = 0;            /* If input table has column "ota_rowid" */
+    int iOrder = 0;
 
+    /* Figure out the type of table this step will deal with. */
     assert( pIter->eType==0 );
+    sqlite3_test_control(
+        SQLITE_TESTCTRL_TBLTYPE, p->db, "main", pIter->zTbl, &pIter->eType
+    );
+    assert( pIter->eType==OTA_PK_NONE || pIter->eType==OTA_PK_IPK 
+         || pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_WITHOUT_ROWID
+         || pIter->eType==OTA_PK_VTAB
+    );
 
     /* Populate the azTblCol[] and nTblCol variables based on the columns
     ** of the input table. Ignore any input table columns that begin with
@@ -524,9 +484,8 @@ static int otaObjIterGetCols(sqlite3ota *p, OtaObjIter *pIter){
     for(i=0; p->rc==SQLITE_OK && i<nCol; i++){
       const char *zName = (const char*)sqlite3_column_name(pStmt, i);
       if( sqlite3_strnicmp("ota_", zName, 4) ){
-        char *zCopy = otaQuoteName(zName);
+        char *zCopy = otaStrndup(zName, -1, &p->rc);
         pIter->azTblCol[pIter->nTblCol++] = zCopy;
-        if( zCopy==0 ) p->rc = SQLITE_NOMEM;
       }
       else if( 0==sqlite3_stricmp("ota_rowid", zName) ){
         bOtaRowid = 1;
@@ -535,9 +494,19 @@ static int otaObjIterGetCols(sqlite3ota *p, OtaObjIter *pIter){
     sqlite3_finalize(pStmt);
     pStmt = 0;
 
+    if( p->rc==SQLITE_OK
+     && bOtaRowid!=(pIter->eType==OTA_PK_VTAB || pIter->eType==OTA_PK_NONE)
+    ){
+      p->rc = SQLITE_ERROR;
+      p->zErrmsg = sqlite3_mprintf(
+          "table data_%q %s ota_rowid column", pIter->zTbl,
+          (bOtaRowid ? "may not have" : "requires")
+      );
+    }
+
     /* Check that all non-HIDDEN columns in the destination table are also
-    ** present in the input table. Populate the abTblPk[] array at the
-    ** same time.  */
+    ** present in the input table. Populate the abTblPk[], azTblType[] and
+    ** aiTblOrder[] arrays at the same time.  */
     if( p->rc==SQLITE_OK ){
       p->rc = prepareFreeAndCollectError(p->db, &pStmt, &p->zErrmsg, 
           sqlite3_mprintf("PRAGMA main.table_info(%Q)", pIter->zTbl)
@@ -546,7 +515,7 @@ static int otaObjIterGetCols(sqlite3ota *p, OtaObjIter *pIter){
     while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
       const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
       for(i=0; i<pIter->nTblCol; i++){
-        if( otaMatchName(zName, pIter->azTblCol[i]) ) break;
+        if( 0==strcmp(zName, pIter->azTblCol[i]) ) break;
       }
       if( i==pIter->nTblCol ){
         p->rc = SQLITE_ERROR;
@@ -556,37 +525,34 @@ static int otaObjIterGetCols(sqlite3ota *p, OtaObjIter *pIter){
       }else{
         int iPk = sqlite3_column_int(pStmt, 5);
         const char *zType = (const char*)sqlite3_column_text(pStmt, 2);
+        pIter->aiTblOrder[i] = iOrder++;
         pIter->azTblType[i] = otaStrndup(zType, -1, &p->rc);
         pIter->abTblPk[i] = (iPk!=0);
-        if( iPk ){
-          pIter->eType = (iPk<0) ? OTA_PK_EXTERNAL : OTA_PK_REAL;
-        }
       }
     }
-    rc2 = sqlite3_finalize(pStmt);
-    if( p->rc==SQLITE_OK ) p->rc = rc2;
-
-    if( p->rc==SQLITE_OK ){
-      if( pIter->eType==0 ){
-        /* This must either be a virtual table, or a regular table with no
-        ** PRIMARY KEY declaration whatsoever.  */
-        if( bOtaRowid==0 ){
-          p->rc = SQLITE_ERROR;
-          p->zErrmsg = sqlite3_mprintf(
-              "table data_%q requires ota_rowid column", pIter->zTbl
-          );
-        }else if( otaIsVtab(p, pIter->zTbl) ){
-          pIter->eType = OTA_PK_VTAB;
-        }else{
-          pIter->eType = OTA_PK_NONE;
+    while( iOrder<pIter->nTblCol ){
+      for(i=0; i<pIter->nTblCol; i++){
+        if( pIter->aiTblOrder[i]==0 ){
+          pIter->aiTblOrder[i] = iOrder++;
+          continue;
         }
-      }else if( bOtaRowid ){
-        p->rc = SQLITE_ERROR;
-        p->zErrmsg = sqlite3_mprintf(
-            "table data_%q may not have ota_rowid column", pIter->zTbl
-        );
       }
     }
+
+    /* Check that there were no extra columns in the data_xxx table that
+    ** are not present in the target table. If there are, an error. */
+#if 0
+    assert( iOrder<=pIter->nTblCol );
+    if( p->rc==SQLITE_OK && iOrder!=pIter->nTblCol ){
+      p->rc = SQLITE_ERROR;
+      p->zErrmsg = sqlite3_mprintf("data_%q has %d columns, expected %d",
+          pIter->zTbl, iOrder, pIter->nTblCol
+      );
+    }
+#endif
+
+    rc2 = sqlite3_finalize(pStmt);
+    if( p->rc==SQLITE_OK ) p->rc = rc2;
   }
 
   return p->rc;
@@ -612,60 +578,18 @@ static char *otaMPrintfAndCollectError(sqlite3ota *p, const char *zFmt, ...){
 ** This function constructs and returns a pointer to a nul-terminated 
 ** string containing some SQL clause or list based on one or more of the 
 ** column names currently stored in the pIter->azTblCol[] array.
-**
-** If an OOM error is encountered, NULL is returned and an error code
-** left in the OTA handle passed as the first argument. Otherwise, a pointer
-** to the allocated string buffer is returned. It is the responsibility
-** of the caller to eventually free this buffer using sqlite3_free().
-**
-** The number of column names to include in the returned string is passed
-** as the third argument.
-**
-** If arguments aiCol and azCollate are both NULL, then the returned string
-** contains the first nCol column names as a comma-separated list. For 
-** example:
-**
-**     "a", "b", "c"
-**
-** If argument aiCol is not NULL, it must point to an array containing nCol
-** entries - the index of each column name to include in the comma-separated
-** list. For example, if aiCol[] contains {2, 0, 1), then the returned 
-** string is changed to:
-**
-**     "c", "a", "b"
-**
-** If azCollate is not NULL, it must also point to an array containing nCol
-** entries - collation sequence names to associated with each element of
-** the comma separated list. For example, ef azCollate[] contains 
-** {"BINARY", "NOCASE", "REVERSE"}, then the retuned string is:
-**
-**     "c" COLLATE "BINARY", "a" COLLATE "NOCASE", "b" COLLATE "REVERSE"
-**
 */
 static char *otaObjIterGetCollist(
   sqlite3ota *p,                  /* OTA object */
-  OtaObjIter *pIter,              /* Object iterator for column names */
-  int nCol,                       /* Number of column names */
-  int *aiCol,                     /* Array of nCol column indexes */
-  const char **azCollate          /* Array of nCol collation sequence names */
+  OtaObjIter *pIter               /* Object iterator for column names */
 ){
   char *zList = 0;
-  if( p->rc==SQLITE_OK ){
-    const char *zSep = "";
-    int i;
-    for(i=0; i<nCol; i++){
-      int iCol = aiCol ? aiCol[i] : i;
-      char *zCol = (iCol>=0 ? pIter->azTblCol[iCol] : "ota_rowid");
-      zList = sqlite3_mprintf("%z%s%s", zList, zSep, zCol);
-      if( zList && azCollate ){
-        zList = sqlite3_mprintf("%z COLLATE %Q", zList, azCollate[i]);
-      }
-      zSep = ", ";
-      if( zList==0 ){
-        p->rc = SQLITE_NOMEM;
-        break;
-      }
-    }
+  const char *zSep = "";
+  int i;
+  for(i=0; i<pIter->nTblCol; i++){
+    const char *z = pIter->azTblCol[i];
+    zList = otaMPrintfAndCollectError(p, "%z%s\"%w\"", zList, zSep, z);
+    zSep = ", ";
   }
   return zList;
 }
@@ -709,7 +633,7 @@ static char *otaObjIterGetIndexCols(
   char *zImpPK = 0;               /* String to return via *pzImposterPK */
   char *zWhere = 0;               /* String to return via *pzWhere */
   int nBind = 0;                  /* Value to return via *pnBind */
-  const char *zComma = "";        /* Set to ", " later on */
+  const char *zCom = "";          /* Set to ", " later on */
   const char *zAnd = "";          /* Set to " AND " later on */
   sqlite3_stmt *pXInfo = 0;       /* PRAGMA index_xinfo = ? */
 
@@ -729,7 +653,7 @@ static char *otaObjIterGetIndexCols(
     if( iCid<0 ){
       /* An integer primary key. If the table has an explicit IPK, use
       ** its name. Otherwise, use "ota_rowid".  */
-      if( pIter->eType==OTA_PK_REAL ){
+      if( pIter->eType==OTA_PK_IPK ){
         int i;
         for(i=0; i<pIter->nTblCol && pIter->abTblPk[i]==0; i++);
         assert( i<pIter->nTblCol );
@@ -743,16 +667,16 @@ static char *otaObjIterGetIndexCols(
       zType = pIter->azTblType[iCid];
     }
 
-    zRet = sqlite3_mprintf("%z%s%s COLLATE %Q", zRet, zComma, zCol, zCollate);
+    zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom, zCol, zCollate);
     if( pIter->bUnique==0 || sqlite3_column_int(pXInfo, 5) ){
-      zImpPK = sqlite3_mprintf("%z%sc%d", zImpPK, zComma, nBind);
+      zImpPK = sqlite3_mprintf("%z%sc%d", zImpPK, zCom, nBind);
     }
     zImpCols = sqlite3_mprintf(
-        "%z%sc%d %s COLLATE %Q", zImpCols, zComma, nBind, zType, zCollate
+        "%z%sc%d %s COLLATE %Q", zImpCols, zCom, nBind, zType, zCollate
     );
     zWhere = sqlite3_mprintf("%z%sc%d IS ?", zWhere, zAnd, nBind);
     if( zRet==0 || zImpPK==0 || zImpCols==0 || zWhere==0 ) rc = SQLITE_NOMEM;
-    zComma = ", ";
+    zCom = ", ";
     zAnd = " AND ";
     nBind++;
   }
@@ -800,7 +724,8 @@ static char *otaObjIterGetOldlist(
     const char *zS = "";
     int i;
     for(i=0; i<pIter->nTblCol; i++){
-      zList = sqlite3_mprintf("%z%s%s.%s", zList, zS, zObj, pIter->azTblCol[i]);
+      const char *zCol = pIter->azTblCol[i];
+      zList = sqlite3_mprintf("%z%s%s.\"%w\"", zList, zS, zObj, zCol);
       zS = ", ";
       if( zList==0 ){
         p->rc = SQLITE_NOMEM;
@@ -831,20 +756,18 @@ static char *otaObjIterGetWhere(
   OtaObjIter *pIter
 ){
   char *zList = 0;
-  if( p->rc==SQLITE_OK ){
-    if( pIter->eType==OTA_PK_VTAB || pIter->eType==OTA_PK_NONE ){
-      zList = otaMPrintfAndCollectError(p, "_rowid_ = ?%d", pIter->nTblCol+1);
-    }else{
-      const char *zSep = "";
-      int i;
-      for(i=0; i<pIter->nTblCol; i++){
-        if( pIter->abTblPk[i] ){
-          const char *zCol = pIter->azTblCol[i];
-          zList = otaMPrintfAndCollectError(
-              p, "%z%s%s=?%d", zList, zSep, zCol, i+1
-          );
-          zSep = " AND ";
-        }
+  if( pIter->eType==OTA_PK_VTAB || pIter->eType==OTA_PK_NONE ){
+    zList = otaMPrintfAndCollectError(p, "_rowid_ = ?%d", pIter->nTblCol+1);
+  }else{
+    const char *zSep = "";
+    int i;
+    for(i=0; i<pIter->nTblCol; i++){
+      if( pIter->abTblPk[i] ){
+        const char *zCol = pIter->azTblCol[i];
+        zList = otaMPrintfAndCollectError(
+            p, "%z%s\"%w\"=?%d", zList, zSep, zCol, i+1
+            );
+        zSep = " AND ";
       }
     }
   }
@@ -880,13 +803,14 @@ static char *otaObjIterGetSetlist(
       for(i=0; i<pIter->nTblCol; i++){
         char c = zMask[i];
         if( c=='x' ){
-          zList = otaMPrintfAndCollectError(p, "%z%s%s=?%d", 
+          zList = otaMPrintfAndCollectError(p, "%z%s\"%w\"=?%d", 
               zList, zSep, pIter->azTblCol[i], i+1
           );
           zSep = ", ";
         }
         if( c=='d' ){
-          zList = otaMPrintfAndCollectError(p, "%z%s%s=ota_delta(%s, ?%d)", 
+          zList = otaMPrintfAndCollectError(p, 
+              "%z%s\"%w\"=ota_delta(\"%w\", ?%d)", 
               zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1
           );
           zSep = ", ";
@@ -915,6 +839,81 @@ static char *otaObjIterGetBindlist(sqlite3ota *p, int nBind){
   return zRet;
 }
 
+/*
+** If an error has already occurred when this function is called, it 
+** immediately returns zero (without doing any work). Or, if an error
+** occurs during the execution of this function, it sets the error code
+** in the sqlite3ota object indicated by the first argument and returns
+** zero.
+**
+** The iterator passed as the second argument is guaranteed to point to
+** a table (not an index) when this function is called. This function
+** attempts to create any imposter tables required to write to the main
+** table b-tree of the table before returning. Non-zero is returned if
+** imposter tables are created, or zero otherwise.
+**
+** The required imposter tables depend on the type of table that the
+** iterator currently points to.
+**
+**   OTA_PK_NONE, OTA_PK_IPK, OTA_PK_WITHOUT_ROWID:
+**     A single imposter table is required. With the same schema as
+**     the actual target table (less any UNIQUE constraints). More
+**     precisely, the "same schema" means the same columns, types, collation
+**     sequences and primary key declaration.
+**
+**   OTA_PK_VTAB:
+**     No imposters required. 
+**
+**   OTA_PK_EXTERNAL:
+**     Two imposters are required (TODO!!)
+*/
+static void otaCreateImposterTable(sqlite3ota *p, OtaObjIter *pIter){
+  if( p->rc==SQLITE_OK && pIter->eType!=OTA_PK_VTAB ){
+    int tnum = pIter->tnum;
+    const char *zComma = "";
+    char *zSql = 0;
+    int iCol;
+    sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
+
+    for(iCol=0; p->rc==SQLITE_OK && iCol<pIter->nTblCol; iCol++){
+      int iDataCol = pIter->aiTblOrder[iCol];
+      const char *zCol = pIter->azTblCol[iDataCol];
+      const char *zColl = 0;
+      p->rc = sqlite3_table_column_metadata(
+          p->db, "main", pIter->zTbl, zCol, 0, &zColl, 0, 0, 0
+      );
+      zSql = otaMPrintfAndCollectError(p, "%z%s\"%w\" %s COLLATE %s", 
+          zSql, zComma, zCol, pIter->azTblType[iDataCol], zColl
+      );
+      zComma = ", ";
+    }
+
+    if( pIter->eType==OTA_PK_IPK || pIter->eType==OTA_PK_WITHOUT_ROWID ){
+      zSql = otaMPrintfAndCollectError(p, "%z, PRIMARY KEY(", zSql);
+      zComma = "";
+      for(iCol=0; iCol<pIter->nTblCol; iCol++){
+        if( pIter->abTblPk[iCol] ){
+          zSql = otaMPrintfAndCollectError(p, "%z%s\"%w\"", 
+              zSql, zComma, pIter->azTblCol[iCol]
+          );
+          zComma = ", ";
+        }
+      }
+      zSql = otaMPrintfAndCollectError(p, "%z)", zSql);
+    }
+
+    zSql = otaMPrintfAndCollectError(p, "CREATE TABLE ota_imposter(%z)%s", 
+        zSql, (pIter->eType==OTA_PK_WITHOUT_ROWID ? " WITHOUT ROWID" : "")
+    );
+    if( p->rc==SQLITE_OK ){
+      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
+      p->rc = sqlite3_exec(p->db, zSql, 0, 0, &p->zErrmsg);
+      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
+    }
+    sqlite3_free(zSql);
+  }
+}
+
 /*
 ** Ensure that the SQLite statement handles required to update the 
 ** target database object currently indicated by the iterator passed 
@@ -926,7 +925,7 @@ static int otaObjIterPrepareAll(
   int nOffset                     /* Add "LIMIT -1 OFFSET $nOffset" to SELECT */
 ){
   assert( pIter->bCleanup==0 );
-  if( pIter->pSelect==0 && otaObjIterGetCols(p, pIter)==SQLITE_OK ){
+  if( pIter->pSelect==0 && otaObjIterCacheTableInfo(p, pIter)==SQLITE_OK ){
     const int tnum = pIter->tnum;
     char *zCollist = 0;           /* List of indexed columns */
     char **pz = &p->zErrmsg;
@@ -939,9 +938,9 @@ static int otaObjIterPrepareAll(
     }
 
     if( zIdx ){
-      char *zImposterCols = 0;
-      char *zImposterPK = 0;
-      char *zWhere = 0;
+      char *zImposterCols = 0;    /* Columns for imposter table */
+      char *zImposterPK = 0;      /* Primary key declaration for imposter */
+      char *zWhere = 0;           /* WHERE clause on PK columns */
       char *zBind = 0;
       int nBind = 0;
 
@@ -1005,13 +1004,15 @@ static int otaObjIterPrepareAll(
       sqlite3_free(zBind);
     }else{
       int bOtaRowid = (pIter->eType==OTA_PK_VTAB || pIter->eType==OTA_PK_NONE);
-      const char *zTbl = pIter->zTbl;
+      const char *zTbl = pIter->zTbl;       /* Table this step applies to */
+      const char *zWrite;                   /* Imposter table name */
+
+      char *zBindings = otaObjIterGetBindlist(p, pIter->nTblCol + bOtaRowid);
       char *zWhere = otaObjIterGetWhere(p, pIter);
       char *zOldlist = otaObjIterGetOldlist(p, pIter, "old");
       char *zNewlist = otaObjIterGetOldlist(p, pIter, "new");
-      char *zBindings = otaObjIterGetBindlist(p, pIter->nTblCol + bOtaRowid);
 
-      zCollist = otaObjIterGetCollist(p, pIter, pIter->nTblCol, 0, 0);
+      zCollist = otaObjIterGetCollist(p, pIter);
       pIter->nCol = pIter->nTblCol;
 
       /* Create the SELECT statement to read keys from data_xxx */
@@ -1024,12 +1025,16 @@ static int otaObjIterPrepareAll(
         );
       }
 
+      /* Create the imposter table or tables (if required). */
+      otaCreateImposterTable(p, pIter);
+      zWrite = (pIter->eType==OTA_PK_VTAB ? zTbl : "ota_imposter");
+
       /* Create the INSERT statement to write to the target PK b-tree */
       if( p->rc==SQLITE_OK ){
         p->rc = prepareFreeAndCollectError(p->db, &pIter->pInsert, pz,
             sqlite3_mprintf(
               "INSERT INTO main.%Q(%s%s) VALUES(%s)", 
-              zTbl, zCollist, (bOtaRowid ? ", _rowid_" : ""), zBindings
+              zWrite, zCollist, (bOtaRowid ? ", _rowid_" : ""), zBindings
             )
         );
       }
@@ -1038,7 +1043,7 @@ static int otaObjIterPrepareAll(
       if( p->rc==SQLITE_OK ){
         p->rc = prepareFreeAndCollectError(p->db, &pIter->pDelete, pz,
             sqlite3_mprintf(
-              "DELETE FROM main.%Q WHERE %s", zTbl, zWhere
+              "DELETE FROM main.%Q WHERE %s", zWrite, zWhere
             )
         );
       }
@@ -1055,34 +1060,34 @@ static int otaObjIterPrepareAll(
             "CREATE TABLE IF NOT EXISTS ota.'ota_tmp_%q' AS "
             "SELECT *%s FROM ota.'data_%q' WHERE 0;"
 
-            "CREATE TEMP TRIGGER ota_delete_%q BEFORE DELETE ON main.%Q "
+            "CREATE TEMP TRIGGER ota_delete_tr BEFORE DELETE ON ota_imposter "
             "BEGIN "
             "  INSERT INTO 'ota_tmp_%q'(ota_control, %s%s) VALUES(2, %s);"
             "END;"
 
-            "CREATE TEMP TRIGGER ota_update1_%q BEFORE UPDATE ON main.%Q "
+            "CREATE TEMP TRIGGER ota_update1_tr BEFORE UPDATE ON ota_imposter "
             "BEGIN "
             "  INSERT INTO 'ota_tmp_%q'(ota_control, %s%s) VALUES(2, %s);"
             "END;"
 
-            "CREATE TEMP TRIGGER ota_update2_%q AFTER UPDATE ON main.%Q "
+            "CREATE TEMP TRIGGER ota_update2_tr AFTER UPDATE ON ota_imposter "
             "BEGIN "
             "  INSERT INTO 'ota_tmp_%q'(ota_control, %s%s) VALUES(3, %s);"
             "END;"
             , zTbl, (pIter->eType==OTA_PK_EXTERNAL ? ", 0 AS ota_rowid" : "")
             , zTbl, 
-            zTbl, zTbl, zTbl, zCollist, zOtaRowid, zOldlist,
-            zTbl, zTbl, zTbl, zCollist, zOtaRowid, zOldlist,
-            zTbl, zTbl, zTbl, zCollist, zOtaRowid, zNewlist
+            zTbl, zCollist, zOtaRowid, zOldlist,
+            zTbl, zCollist, zOtaRowid, zOldlist,
+            zTbl, zCollist, zOtaRowid, zNewlist
         );
         if( pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_NONE ){
           otaMPrintfExec(p, 
-              "CREATE TEMP TRIGGER ota_insert_%q AFTER INSERT ON main.%Q "
+              "CREATE TEMP TRIGGER ota_insert_tr AFTER INSERT ON ota_imposter "
               "BEGIN "
               "  INSERT INTO 'ota_tmp_%q'(ota_control, %s, ota_rowid)"
               "  VALUES(0, %s);"
               "END;"
-              , zTbl, zTbl, zTbl, zCollist, zNewlist
+              , zTbl, zCollist, zNewlist
           );
         }
       }else if( p->rc==SQLITE_OK ){
@@ -1133,8 +1138,9 @@ static int otaGetUpdateStmt(
     sqlite3_finalize(pIter->pUpdate);
     pIter->pUpdate = 0;
     if( p->rc==SQLITE_OK ){
-      zUpdate = sqlite3_mprintf("UPDATE %Q SET %s WHERE %s", 
-          pIter->zTbl, zSet, zWhere
+      zUpdate = sqlite3_mprintf("UPDATE \"%w\" SET %s WHERE %s", 
+          (pIter->eType==OTA_PK_VTAB ? pIter->zTbl : "ota_imposter"),
+          zSet, zWhere
       );
       p->rc = prepareFreeAndCollectError(
           p->db, &pIter->pUpdate, &p->zErrmsg, zUpdate
@@ -1337,9 +1343,22 @@ static int otaStep(sqlite3ota *p){
       }
 
       for(i=0; i<pIter->nCol; i++){
+        /* If this is an INSERT into a table b-tree and the table has an
+        ** explicit INTEGER PRIMARY KEY, check that this is not an attempt
+        ** to write a NULL into the IPK column. That is not permitted.  */
+        if( eType==OTA_INSERT 
+         && pIter->zIdx==0 && pIter->eType==OTA_PK_IPK && pIter->abTblPk[i] 
+         && sqlite3_column_type(pIter->pSelect, i)==SQLITE_NULL
+        ){
+          p->rc = SQLITE_MISMATCH;
+          p->zErrmsg = sqlite3_mprintf("datatype mismatch");
+          goto step_out;
+        }
+
         if( eType==SQLITE_DELETE && pIter->zIdx==0 && pIter->abTblPk[i]==0 ){
           continue;
         }
+
         pVal = sqlite3_column_value(pIter->pSelect, i);
         sqlite3_bind_value(pWriter, i+1, pVal);
       }
@@ -1383,6 +1402,7 @@ static int otaStep(sqlite3ota *p){
     }
   }
 
+ step_out:
   return p->rc;
 }
 
index 3c7bd57c8046e5f02a6c9f0160987d914e543840..0a49c2b2a10f7833d404aeedfc346c76a0c432e5 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Have\sota\suse\simposter\stables\sto\swrite\sto\sindexes\sinstead\sof\sthe\ssqlite3_index_writer()\sinterface.\sThe\serror\shandling\sin\sthis\sversion\sis\sbroken\sin\sa\sfew\ssmall\sways.
-D 2015-01-31T20:42:04.027
+C Remove\s"PRAGMA\sota_mode".
+D 2015-02-03T15:56:08.271
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5407a688f4d77a05c18a8142be8ae5a2829dd610
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -128,15 +128,15 @@ F ext/ota/ota.c c11a85af71dccc45976622fe7a51169a481caa91
 F ext/ota/ota1.test d76b9ec77437759e9da0ff4abe9c070bb9f4eae1
 F ext/ota/ota10.test ab815dff9cef7248c504f06b888627d236f25e9c
 F ext/ota/ota2.test 2829bc08ffbb71b605392a68fedfd554763356a7
-F ext/ota/ota3.test 71bd8cc0cf8d7e7d9bb11a1fcc238320a5a9d8c8
-F ext/ota/ota4.test 60f897f329a6782ef2f24862640acf3c52e48077
+F ext/ota/ota3.test a77efbce7723332eb688d2b28bf18204fc9614d7
+F ext/ota/ota4.test 82434aa39c9acca6cd6317f6b0ab07b0ec6c2e7d
 F ext/ota/ota5.test ad0799daf8923ddebffe75ae8c5504ca90b7fadb
 F ext/ota/ota6.test 82f1f757ec9b2ad07d6de4060b8e3ba8e44dfdd3
 F ext/ota/ota7.test 1fe2c5761705374530e29f70c39693076028221a
 F ext/ota/ota8.test cd70e63a0c29c45c0906692827deafa34638feda
 F ext/ota/ota9.test d3eee95dd836824d07a22e5efcdb7bf6e869358b
 F ext/ota/otafault.test 508ba87c83d632670ac0f94371a465d4bb4d49dd
-F ext/ota/sqlite3ota.c 975ccfe032ee81ee39368ed5e9cb33cbb6edc603
+F ext/ota/sqlite3ota.c 52c91eec41b8fbb5ed12a8f0a2159bc5ec16498f
 F ext/ota/sqlite3ota.h ce378c0c503f625611713133f9c79704ea4ee7a4
 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
 F ext/rtree/rtree.c 14e6239434d4e3f65d3e90320713f26aa24e167f
@@ -188,7 +188,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
 F src/backup.c 7ddee9c7d505e07e959a575b18498f17c71e53ea
 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
 F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5
-F src/btree.c ddca0ae681c49813a4bfd88d5f922fac71e0ffaa
+F src/btree.c 2a1245df0356a229bcd0fd87a8536b5067f16e82
 F src/btree.h 94277c1d30c0b75705974bcc8b0c05e79c03d474
 F src/btreeInt.h a3d0ae1d511365e1a2b76ad10960dbe55c286f34
 F src/build.c eefaa4f1d86bc3c08023a61fdd1e695b47796975
@@ -196,7 +196,7 @@ F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
 F src/complete.c 198a0066ba60ab06fc00fba1998d870a4d575463
 F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887
 F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
-F src/delete.c e68b70ac41dcf6e92a813d860fa984fcd9aec042
+F src/delete.c bd1a91ddd247ce13004075251e0b7fe2bf9925ef
 F src/expr.c abe930897ccafae3819fd2855cbc1b00c262fd12
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c e0444b61bed271a76840cbe6182df93a9baa3f12
@@ -205,12 +205,12 @@ F src/global.c 12561d70a1b25f67b21154622bb1723426724f75
 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
-F src/insert.c fef86ab8218cf0d926db93280b9eb5b583981353
+F src/insert.c 5b9243a33726008cc4132897d2be371db12a13be
 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
 F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
 F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
 F src/loadext.c 86bd4e2fccd520b748cba52492ab60c4a770f660
-F src/main.c c4cb192ebf0bcc975648ae05ac40bc1f40018c52
+F src/main.c 55d548a2c2f32d27366968c394d091475f7ea00a
 F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
@@ -238,7 +238,7 @@ F src/parse.y c5d0d964f9ac023e8154cad512e54b0b6058e086
 F src/pcache.c d210cf90d04365a74f85d21374dded65af67b0cb
 F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
 F src/pcache1.c 1e77432b40b7d3288327d9cdf399dcdfd2b6d3bf
-F src/pragma.c e49831e54c72894cce08702fe2e127e5c53d90f0
+F src/pragma.c 26fc55619109828c9b7add4cfa8a961b6f4c456d
 F src/prepare.c 173a5a499138451b2561614ecb87d78f9f4644b9
 F src/printf.c 05edc41450d0eb2c05ef7db113bf32742ae65325
 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
@@ -246,15 +246,15 @@ F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada
 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
 F src/select.c 1f2087523007c42900ffcbdeaef06a23ad9329fc
 F src/shell.c 22b4406b0b59efd14b3b351a5809dda517df6d30
-F src/sqlite.h.in 78e493f94202d8083dd270e257786a6311d1fb3b
+F src/sqlite.h.in 8913937ba11415bf369818431700adf3a921fb18
 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
 F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
-F src/sqliteInt.h 66180aa8f81155a7f391bbf759ee5a3b61d2f89f
+F src/sqliteInt.h 57f8f45028598cc2877fc08ac03b402242242c68
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 81712116e826b0089bb221b018929536b2b5406f
 F src/table.c e7a09215315a978057fb42c640f890160dbcc45e
 F src/tclsqlite.c b321464aba1fff1ed9317ebc82a1a94887f97af8
-F src/test1.c 313567541c980e45220d6faed393b6ad454f8ecd
+F src/test1.c ce8ea168800d129acb2c0afdf2831ddf8667e082
 F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
 F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
 F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
@@ -302,7 +302,7 @@ F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
 F src/tokenize.c e00458c9938072b0ea711c850b8dcf4ddcb5fe18
-F src/trigger.c 6dcdf46a21acf4d4e011c809b2c971e63f797a1a
+F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f
 F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13
 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
 F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e
@@ -312,7 +312,7 @@ F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3
 F src/vdbeInt.h 9bb69ff2447c34b6ccc58b34ec35b615f86ead78
 F src/vdbeapi.c 4bc511a46b9839392ae0e90844a71dc96d9dbd71
 F src/vdbeaux.c 97911edb61074b871ec4aa2d6bb779071643dee5
-F src/vdbeblob.c ad7787440295e43c12248dc48cde4b13e5df4ca0
+F src/vdbeblob.c 4af4bfb71f6df7778397b4a0ebc1879793276778
 F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f
 F src/vdbesort.c 6d64c5448b64851b99931ede980addc3af70d5e2
 F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
@@ -1218,7 +1218,7 @@ F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
 F tool/mkautoconfamal.sh d1a2da0e15b2ed33d60af35c7e9d483f13a8eb9f
 F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670
 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
-F tool/mkpragmatab.tcl 5a401a3f5461fedb2e3230eb9908a18d485fefea
+F tool/mkpragmatab.tcl aea392b69f8e72715760629cd50411d37bc85de4
 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
 F tool/mksqlite3c-noext.tcl 9ef48e1748dce7b844f67e2450ff9dfeb0fb4ab5
 F tool/mksqlite3c.tcl cfde806851c413db7689b9cb74a4eeb92539c601
@@ -1254,7 +1254,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P f9b6dc77021ee421bffd5697d5d337d3bbd07eb9
-R 907483269529ba471a525b7f8d05bc2e
+P cdaeab467f6aa3217be161377a9b78a4eec37093
+R 2703aba199c695992db82956950982ca
 U dan
-Z 87f206a3330dd276f74650f9e68af8ed
+Z fae9dc4e5e5c1a2d2a162b422a05ccf9
index ecf8a3c6bb7eaa06d8f5117c7f054a64067b7fcf..0e07d68cdf7b62a43a90934a03e83489334e1667 100644 (file)
@@ -1 +1 @@
-cdaeab467f6aa3217be161377a9b78a4eec37093
\ No newline at end of file
+1c111447a07687c30ed4ad5a6c27a169c85b7ea6
\ No newline at end of file
index 4f752066acc2c3e2a970eab6f012c2e2e89e6d81..eb5151351c68d3b4815da028b35d2e61588da34e 100644 (file)
@@ -151,8 +151,7 @@ static int hasSharedCacheTableLock(
   ** and has the read-uncommitted flag set, then no lock is required. 
   ** Return true immediately.
   */
-  if( (pBtree->db->flags & SQLITE_OtaMode)
-   || (pBtree->sharable==0)
+  if( (pBtree->sharable==0)
    || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommitted))
   ){
     return 1;
index 17f7a87459db37a9b8f2ed19e7567b0f446d8ce0..011fb80deee2420949264ce286b02a214912c6e7 100644 (file)
@@ -730,9 +730,6 @@ void sqlite3GenerateRowIndexDelete(
   Vdbe *v;           /* The prepared statement under construction */
   Index *pPk;        /* PRIMARY KEY index, or NULL for rowid tables */
 
-  /* Skip this if we are in OTA mode */
-  if( pParse->db->flags & SQLITE_OtaMode ) return;
-
   v = pParse->pVdbe;
   pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
   for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
index 0cc2078179b7f98b15386950a3437f9a4c258b6b..a5c3f3e92d437dcb0bd349017afae3e5e4c00843 100644 (file)
@@ -1365,10 +1365,6 @@ void sqlite3GenerateConstraintChecks(
     int iThisCur;        /* Cursor for this UNIQUE index */
     int addrUniqueOk;    /* Jump here if the UNIQUE constraint is satisfied */
 
-    /* If the "ota_mode" flag is set, ignore all indexes except the PK 
-    ** index of WITHOUT ROWID tables.  */
-    if( (db->flags & SQLITE_OtaMode) && pIdx!=pPk) continue;
-
     if( aRegIdx[ix]==0 ) continue;  /* Skip indices that do not change */
     if( bAffinityDone==0 ){
       sqlite3TableAffinity(v, pTab, regNewData+1);
@@ -1560,15 +1556,6 @@ void sqlite3CompleteInsertion(
   assert( pTab->pSelect==0 );  /* This table is not a VIEW */
   for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
     if( aRegIdx[i]==0 ) continue;
-
-    /* If the "ota_mode" flag is set, ignore all indexes except the PK 
-    ** index of WITHOUT ROWID tables.  */
-    if( (pParse->db->flags & SQLITE_OtaMode) 
-     && (HasRowid(pTab) || pIdx->idxType!=SQLITE_IDXTYPE_PRIMARYKEY) 
-    ){
-      continue;
-    }
-
     bAffinityDone = 1;
     if( pIdx->pPartIdxWhere ){
       sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
index 7bca1e57773be4d5bc59a8b2f173e6e112e40fad..710d1dfb84a07c6a0229f034eaf4033c7c3913a7 100644 (file)
@@ -3654,6 +3654,45 @@ int sqlite3_test_control(int op, ...){
       sqlite3_mutex_leave(db->mutex);
       break;
     }
+
+    /* sqlite3_test_control(SQLITE_TESTCTRL_TBLTYPE, db, dbName, zTbl, peType)
+    **
+    **   peType is of type (int*), a pointer to an output parameter of type
+    **   (int). This call sets the output parameter as follows, depending
+    **   on the type of the table specified by parameters dbName and zTbl.
+    **
+    **     0: No such table.
+    **     1: Table has an implicit rowid.
+    **     2: Table has an explicit IPK column.
+    **     3: Table has an external PK index.
+    **     4: Table is WITHOUT ROWID.
+    **     5: Table is a virtual table.
+    */
+    case SQLITE_TESTCTRL_TBLTYPE: {
+      sqlite3 *db = va_arg(ap, sqlite3*);
+      const char *zDb = va_arg(ap, const char*);
+      const char *zTab = va_arg(ap, const char*);
+      int *peType = va_arg(ap, int*);
+      Table *pTab;
+      sqlite3_mutex_enter(db->mutex);
+      sqlite3BtreeEnterAll(db);
+      pTab = sqlite3FindTable(db, zTab, zDb);
+      if( pTab==0 ){
+        *peType = 0;
+      }else if( IsVirtual(pTab) ){
+        *peType = 5;
+      }else if( HasRowid(pTab)==0 ){
+        *peType = 4;
+      }else if( pTab->iPKey>=0 ){
+        *peType = 2;
+      }else{
+        Index *pPk = sqlite3PrimaryKeyIndex(pTab);
+        *peType = (pPk ? 3 : 1);
+      }
+      sqlite3BtreeLeaveAll(db);
+      sqlite3_mutex_leave(db->mutex);
+      break;
+    }
   }
   va_end(ap);
 #endif /* SQLITE_OMIT_BUILTIN_TEST */
index a2913abdbddcbd5c9dc5d53be170387cdfc01c90..61c721f4d219728786631e760465aaf7b191ecae 100644 (file)
@@ -320,14 +320,6 @@ static const struct sPragmaNames {
     /* ePragTyp:  */ PragTyp_MMAP_SIZE,
     /* ePragFlag: */ 0,
     /* iArg:      */ 0 },
-#endif
-#if defined(SQLITE_ENABLE_OTA)
-  { /* zName:     */ "ota_mode",
-    /* ePragTyp:  */ PragTyp_FLAG,
-    /* ePragFlag: */ 0,
-    /* iArg:      */ SQLITE_OtaMode },
-#endif
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
   { /* zName:     */ "page_count",
     /* ePragTyp:  */ PragTyp_PAGE_COUNT,
     /* ePragFlag: */ PragFlag_NeedSchema,
@@ -496,7 +488,7 @@ static const struct sPragmaNames {
     /* iArg:      */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
 #endif
 };
-/* Number of pragmas: 59 on by default, 74 total. */
+/* Number of pragmas: 59 on by default, 73 total. */
 /* End of the automatically generated pragma table.
 ***************************************************************************/
 
@@ -1545,9 +1537,6 @@ void sqlite3Pragma(
           k = 1;
         }else{
           for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){}
-          if( (db->flags & SQLITE_OtaMode) && HasRowid(pTab) ){
-            k = -1 * k;
-          }
         }
         sqlite3VdbeAddOp2(v, OP_Integer, k, 6);
         sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
index 6e02a98688b3feef72159f22d7c83740188c611a..1cba5b17724d6e4d29605652fbd7d3dfd2a599fc 100644 (file)
@@ -6266,7 +6266,8 @@ int sqlite3_test_control(int op, ...);
 #define SQLITE_TESTCTRL_ISINIT                  23
 #define SQLITE_TESTCTRL_SORTER_MMAP             24
 #define SQLITE_TESTCTRL_IMPOSTER                25
-#define SQLITE_TESTCTRL_LAST                    25
+#define SQLITE_TESTCTRL_TBLTYPE                 26
+#define SQLITE_TESTCTRL_LAST                    26
 
 /*
 ** CAPI3REF: SQLite Runtime Status
@@ -7585,66 +7586,6 @@ SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus(
 */
 SQLITE_EXPERIMENTAL void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
 
-/*
-** Allocate a statement handle that may be used to write directly to an
-** index b-tree. This allows the user to create a corrupt database. Once
-** the statement handle is allocated, it may be used with the same APIs
-** as any statement handle created with sqlite3_prepare().
-**
-** The statement writes to the index specified by parameter zIndex, which
-** must be in the "main" database. If argument bDelete is false, then each
-** time the statement is sqlite3_step()ed, an entry is inserted into the
-** b-tree index. If it is true, then an entry may be deleted (or may not, if 
-** the specified key is not found) each time the statement is 
-** sqlite3_step()ed.
-**
-** If statement compilation is successful, *ppStmt is set to point to the 
-** new statement handle and SQLITE_OK is returned. Otherwise, if an error
-** occurs, *ppStmt is set to NULL and an error code returned. An error
-** message may be left in the database handle in this case.
-**
-** If statement compilation succeeds, output variable *pnCol is set to the
-** total number of columns in the index, including the primary key columns
-** at the end. Variable *paiCol is set to point to an array *pnCol entries 
-** in size. Each entry is the table column index, numbered from zero from left 
-** to right, of the corresponding index column. For example, if:
-**
-**       CREATE TABLE t1(a, b, c, d);
-**       CREATE INDEX i1 ON t1(b, c);
-**
-** then *pnCol is 3 and *paiCol points to an array containing {1, 2, -1}.
-** If table t1 had an explicit INTEGER PRIMARY KEY, then the "-1" in the
-** *paiCol array would be replaced by its column index. Or if:
-**
-**       CREATE TABLE t2(a, b, c, d, PRIMARY KEY(d, c)) WITHOUT ROWID;
-**       CREATE INDEX i2 ON t2(a);
-**
-** then (*pnCol) is 3 and *paiCol points to an array containing {0, 3, 2}.
-**
-** The lifetime of the array is the same as that of the statement handle -
-** it is automatically freed when the statement handle is passed to
-** sqlite3_finalize().
-**
-** The statement has (*pnCol) SQL variables that values may be bound to.
-** They correspond to the values used to create the index key that is
-** inserted or deleted when the statement is stepped.
-**
-** If the index is a UNIQUE index, the usual checking and error codes apply
-** to insert operations.
-**
-** This API is only available if SQLITE_ENABLE_OTA is defined at compile
-** time. It is intended for use by the OTA extension only. As such, it is 
-** subject to change or removal at any point.
-*/
-int sqlite3_index_writer(
-  sqlite3 *db, 
-  int bDelete,                    /* Zero for insert, non-zero for delete */
-  const char *zIndex,             /* Index to write to */
-  sqlite3_stmt**,                 /* OUT: New statement handle */
-  const char ***pazColl,          /* OUT: Collation sequence for each column */
-  int **paiCol, int *pnCol        /* OUT: See above */
-);
-
 /*
 ** Incremental checkpoint API.
 **
index 9de37160bf940cc8025ef4848bbad4cf0f45cd6f..5fdbc6d65d49670de3190c9619f3f211be23623a 100644 (file)
@@ -1207,12 +1207,6 @@ struct sqlite3 {
 #define SQLITE_QueryOnly      0x02000000  /* Disable database changes */
 #define SQLITE_VdbeEQP        0x04000000  /* Debug EXPLAIN QUERY PLAN */
 
-#ifdef SQLITE_ENABLE_OTA
-# define SQLITE_OtaMode       0x08000000  /* True in "ota mode" */
-#else
-# define SQLITE_OtaMode       0x00000000
-#endif
-
 /*
 ** Bits of the sqlite3.dbOptFlags field that are used by the
 ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
index ae6e7bc0eae56389371c139deb9cdf9c5d42718f..d3c3d314bf7d9a439a878163f48d3c513e401c06 100644 (file)
@@ -6922,11 +6922,11 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "sqlite3_user_change",       test_user_change,       0 },
      { "sqlite3_user_delete",       test_user_delete,       0 },
 #endif
-
 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
      { "sqlite3_stmt_scanstatus",       test_stmt_scanstatus,   0 },
      { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset,   0 },
 #endif
+
   };
 
   static int bitmask_size = sizeof(Bitmask)*8;
index 44b9b89fcc5a6b9585101721166443e68e607c66..d2e7b5a1e6580b0b1be26ac5278dfad763b10fd0 100644 (file)
@@ -43,14 +43,10 @@ void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){
 ** To state it another way:  This routine returns a list of all triggers
 ** that fire off of pTab.  The list will include any TEMP triggers on
 ** pTab as well as the triggers lised in pTab->pTrigger.
-**
-** If the SQLITE_OtaMode flag is set, do not include any non-temporary
-** triggers in the returned list.
 */
 Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
   Schema * const pTmpSchema = pParse->db->aDb[1].pSchema;
   Trigger *pList = 0;                  /* List of triggers to return */
-  const int bOta = !!(pParse->db->flags & SQLITE_OtaMode);
 
   if( pParse->disableTriggers ){
     return 0;
@@ -64,13 +60,13 @@ Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
       if( pTrig->pTabSchema==pTab->pSchema
        && 0==sqlite3StrICmp(pTrig->table, pTab->zName) 
       ){
-        pTrig->pNext = ((pList || bOta) ? pList : pTab->pTrigger);
+        pTrig->pNext = (pList ? pList : pTab->pTrigger);
         pList = pTrig;
       }
     }
   }
 
-  return ((pList || bOta) ? pList : pTab->pTrigger);
+  return (pList ? pList : pTab->pTrigger);
 }
 
 /*
index 93a17ed38425a4cc9642e00853956cc3aa86d219..cf1eb5905427edf0035d25a8d396b20fb9543f95 100644 (file)
@@ -467,183 +467,4 @@ int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
   return rc;
 }
 
-#ifdef SQLITE_ENABLE_OTA
-/*
-** Allocate and populate the output arrays returned by the 
-** sqlite3_index_writer() function.
-*/
-static int indexWriterOutputVars(
-  sqlite3 *db,
-  Index *pIdx,
-  const char ***pazColl,          /* OUT: Array of collation sequences */
-  int **paiCol,                   /* OUT: Array of column indexes */
-  int *pnCol                      /* OUT: Total columns in index keys */
-){
-  Table *pTbl = pIdx->pTable;     /* Table index is attached to */
-  Index *pPk = 0;
-  int nByte = 0;                  /* Total bytes of space to allocate */
-  int i;                          /* Iterator variable */
-
-  int *aiCol;
-  const char **azColl;
-  char *pCsr;
-
-  if( !HasRowid(pTbl) ){
-    pPk = sqlite3PrimaryKeyIndex(pTbl);
-  }
-
-  for(i=0; i<pIdx->nColumn; i++){
-    const char *zColl = 0;
-    if( i<pIdx->nKeyCol ){
-      zColl = pIdx->azColl[i];
-    }else if( pPk ){
-      zColl = pPk->azColl[i-pIdx->nKeyCol];
-    }
-    if( zColl==0 ) zColl = "BINARY";
-    nByte += sqlite3Strlen30(zColl) + 1;
-  }
-  nByte += (pIdx->nColumn) * (sizeof(const char*) + sizeof(int));
-
-  /* Populate the output variables */
-  *pazColl = azColl = (const char**)sqlite3DbMallocZero(db, nByte);
-  if( azColl==0 ) return SQLITE_NOMEM;
-  *paiCol = aiCol = (int*)&azColl[pIdx->nColumn];
-  *pnCol = pIdx->nColumn;
-  pCsr = (char*)&aiCol[pIdx->nColumn];
-
-  for(i=0; i<pIdx->nColumn; i++){
-    const char *zColl = 0;
-    int nColl;
-    int iCol = pTbl->iPKey;
-    if( i<pIdx->nKeyCol ){
-      zColl = pIdx->azColl[i];
-      iCol = pIdx->aiColumn[i];
-    }else if( pPk ){
-      zColl = pPk->azColl[i-pIdx->nKeyCol];
-      iCol = pPk->aiColumn[i-pIdx->nKeyCol];
-    }
-    if( zColl==0 ) zColl = "BINARY";
-
-    aiCol[i] = iCol;
-    azColl[i] = pCsr;
-    nColl = 1 + sqlite3Strlen30(zColl);
-    memcpy(pCsr, zColl, nColl);
-    pCsr += nColl;
-  }
-
-  return SQLITE_OK;
-}
-
-/*
-** Prepare and return an SQL statement handle that can be used to write
-** directly to an index b-tree.
-*/
-int sqlite3_index_writer(
-  sqlite3 *db, 
-  int bDelete,
-  const char *zIndex, 
-  sqlite3_stmt **ppStmt,
-  const char ***pazColl,          /* OUT: Array of collation sequences */
-  int **paiCol,                   /* OUT: Array of column indexes */
-  int *pnCol                      /* OUT: Total columns in index keys */
-){
-  int rc = SQLITE_OK;
-  Parse *pParse = 0;
-  Index *pIdx = 0;                /* The index to write to */
-  Table *pTab;
-  int i;                          /* Used to iterate through index columns */
-  Vdbe *v = 0;
-  int regRec;                     /* Register to assemble record in */
-  const char *zAffinity = 0;      /* Affinity string for the current index */
-
-  sqlite3_mutex_enter(db->mutex);
-  sqlite3BtreeEnterAll(db);
-
-  /* Allocate the parse context */
-  pParse = sqlite3StackAllocRaw(db, sizeof(*pParse));
-  if( !pParse ) goto index_writer_out;
-  memset(pParse, 0, sizeof(Parse));
-  pParse->db = db;
-
-  /* Allocate the Vdbe */
-  v = sqlite3GetVdbe(pParse);
-  if( v==0 ) goto index_writer_out;
-
-  /* Find the index to write to */
-  pIdx = sqlite3FindIndex(db, zIndex, "main");
-  if( pIdx==0 ){
-    sqlite3ErrorMsg(pParse, "no such index: %s", zIndex);
-    goto index_writer_out;
-  }
-  pTab = pIdx->pTable;
-  zAffinity = sqlite3IndexAffinityStr(v, pIdx);
-
-  rc = indexWriterOutputVars(db, pIdx, pazColl, paiCol, pnCol);
-  if( rc!=SQLITE_OK ) goto index_writer_out;
-
-  /* Add an OP_Noop to the VDBE program. Then store a pointer to the 
-  ** output array *paiCol as its P4 value. This is so that the array
-  ** is automatically deleted when the user finalizes the statement. The
-  ** OP_Noop serves no other purpose. */
-  sqlite3VdbeAddOp0(v, OP_Noop);
-  sqlite3VdbeChangeP4(v, -1, (const char*)(*pazColl), P4_INTARRAY);
-
-  sqlite3BeginWriteOperation(pParse, 0, 0);
-
-  /* Open a write cursor on the index */
-  pParse->nTab = 1;
-  sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, pIdx->tnum, 0);
-  sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
-
-  /* Create the record to insert into the index. Store it in register regRec. */
-  pParse->nVar = pIdx->nColumn;
-  pParse->nMem = pIdx->nColumn;
-  for(i=1; i<=pIdx->nColumn; i++){
-    sqlite3VdbeAddOp2(v, OP_Variable, i, i);
-  }
-  regRec = ++pParse->nMem;
-
-  /* If this is a rowid table, check that the rowid field is an integer. */
-  if( HasRowid(pTab) ){
-    sqlite3VdbeAddOp2(v, OP_MustBeInt, pIdx->nColumn, 0);
-    VdbeCoverageNeverTaken(v);
-  }
-
-  if( bDelete==0 ){
-    sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, pIdx->nColumn, regRec, zAffinity, 0);
-
-    /* If this is a UNIQUE index, check the constraint. */
-    if( pIdx->onError ){
-      int addr = sqlite3VdbeAddOp4Int(v, OP_NoConflict, 0, 0, 1, pIdx->nKeyCol);
-      VdbeCoverage(v);
-      sqlite3UniqueConstraint(pParse, SQLITE_ABORT, pIdx);
-      sqlite3VdbeJumpHere(v, addr);
-    }
-
-    /* Code the IdxInsert to write to the b-tree index. */
-    sqlite3VdbeAddOp2(v, OP_IdxInsert, 0, regRec);
-  }else{
-    /* Code the IdxDelete to remove the entry from the b-tree index. */
-    sqlite3VdbeAddOp4(v, OP_Affinity, 1, pIdx->nColumn, 0, zAffinity, 0);
-    sqlite3VdbeAddOp3(v, OP_IdxDelete, 0, 1, pIdx->nColumn);
-  }
-  sqlite3FinishCoding(pParse);
-
-index_writer_out:
-  if( rc==SQLITE_OK && db->mallocFailed==0 ){
-    *ppStmt = (sqlite3_stmt*)v;
-  }else{
-    *ppStmt = 0;
-    if( v ) sqlite3VdbeFinalize(v);
-  }
-
-  sqlite3ParserReset(pParse);
-  sqlite3StackFree(db, pParse);
-  sqlite3BtreeLeaveAll(db);
-  rc = sqlite3ApiExit(db, rc);
-  sqlite3_mutex_leave(db->mutex);
-  return rc;
-}
-#endif /* SQLITE_ENABLE_OTA */
-
 #endif /* #ifndef SQLITE_OMIT_INCRBLOB */
index 149a1bfff764c0bb8c479617c84f7e6877caffa6..0d93704d70f100afa0bb85e3dd39b52acf6e7204 100644 (file)
@@ -318,11 +318,6 @@ set pragma_def {
 
   NAME: pager_ota_mode
   IF:   defined(SQLITE_ENABLE_OTA)
-
-  NAME: ota_mode
-  TYPE: FLAG
-  ARG:  SQLITE_OtaMode
-  IF:   defined(SQLITE_ENABLE_OTA)
 }
 fconfigure stdout -translation lf
 set name {}