SQLite

Check-in [1c111447a0]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Remove "PRAGMA ota_mode".
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | ota-update
Files: files | file ages | folders
SHA1: 1c111447a07687c30ed4ad5a6c27a169c85b7ea6
User & Date: dan 2015-02-03 15:56:08.271
Context
2015-02-03
18:43
Fix some problems surrounding WITHOUT ROWID tables with DESC primary key indexes . (check-in: a21fefb79a user: dan tags: ota-update)
15:56
Remove "PRAGMA ota_mode". (check-in: 1c111447a0 user: dan tags: ota-update)
2015-01-31
20:42
Have ota use imposter tables to write to indexes instead of the sqlite3_index_writer() interface. The error handling in this version is broken in a few small ways. (check-in: cdaeab467f user: dan tags: ota-update)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/ota/ota3.test.
59
60
61
62
63
64
65

66
67
68
69
70
71










72
73
74
75
76
77
78

79
80
81
82
83
84
85
reset_db

do_execsql_test 2.0 {
  CREATE TABLE x1(a INTEGER PRIMARY KEY, b TEXT, c REAL);
  CREATE INDEX i1 ON x1(b, c);
} {}


do_test 2.1 {
  sqlite3 db2 ota.db
  db2 eval {
    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}


#--------------------------------------------------------------------
# Test that missing columns are detected.
#
forcedelete ota.db
reset_db








>
|
<
<



>
>
>
>
>
>
>
>
>
>
|
|
|

|
|
|
>







59
60
61
62
63
64
65
66
67


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
reset_db

do_execsql_test 2.0 {
  CREATE TABLE x1(a INTEGER PRIMARY KEY, b TEXT, c REAL);
  CREATE INDEX i1 ON x1(b, c);
} {}

foreach {tn otadb} {
  1 {


    CREATE TABLE data_x1(a, b, c, ota_control);
    INSERT INTO data_x1 VALUES(NULL, 'a', 'b', 0);
  }

  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.
#
forcedelete ota.db
reset_db

97
98
99
100
101
102
103
104























105

  db2 close
  list [catch { run_ota test.db ota.db } msg] $msg
} {1 {SQLITE_ERROR - column missing from data_x1: c}}

do_execsql_test 2.2 {
  PRAGMA integrity_check;
} {ok}
























finish_test









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  db2 close
  list [catch { run_ota test.db ota.db } msg] $msg
} {1 {SQLITE_ERROR - column missing from data_x1: c}}

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

Changes to ext/ota/ota4.test.
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  }
} {1 2 7 8}
do_catchsql_test 1.5.4 {
  PRAGMA pager_ota_mode = 1;
  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








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


120
121
122
123
124
125
126









































































































127
128
  }
} {1 2 7 8}
do_catchsql_test 1.5.4 {
  PRAGMA pager_ota_mode = 1;
  SELECT * FROM t1;
} {1 {database is locked}}










































































































finish_test

Changes to ext/ota/sqlite3ota.c.
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
**     * each index of the table (zero or more points to visit), and
**     * a special "cleanup table" state.
*/
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 **azTblType;               /* Array of column types */

  unsigned char *abTblPk;         /* Array of flags - true for PK columns */
  int eType;

  /* Output variables. zTbl==0 implies EOF. */
  int bCleanup;                   /* True in "cleanup" state */
  const char *zTbl;               /* Name of target db table */
  const char *zIdx;               /* Name of target db index (or null) */







|

>







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
**     * each index of the table (zero or more points to visit), and
**     * a special "cleanup table" state.
*/
struct OtaObjIter {
  sqlite3_stmt *pTblIter;         /* Iterate through tables */
  sqlite3_stmt *pIdxIter;         /* Index iterator */
  int nTblCol;                    /* Size of azTblCol[] array */
  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;

  /* Output variables. zTbl==0 implies EOF. */
  int bCleanup;                   /* True in "cleanup" state */
  const char *zTbl;               /* Name of target db table */
  const char *zIdx;               /* Name of target db index (or null) */
124
125
126
127
128
129
130






131
132

133
134
135
136
137
138
139
140
141
142
  /* Last UPDATE used (for PK b-tree updates only), or NULL. */
  char *zMask;                    /* Copy of update mask used with pUpdate */
  sqlite3_stmt *pUpdate;          /* Last update statement (or NULL) */
};

/*
** Values for OtaObjIter.eType






*/
#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) */

/*
** OTA handle.
*/
struct sqlite3ota {
  int eStage;                     /* Value of OTA_STATE_STAGE field */
  sqlite3 *db;                    /* "main" -> target db, "ota" -> ota db */







>
>
>
>
>
>

|
>
|
|
|







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  /* Last UPDATE used (for PK b-tree updates only), or NULL. */
  char *zMask;                    /* Copy of update mask used with pUpdate */
  sqlite3_stmt *pUpdate;          /* Last update statement (or NULL) */
};

/*
** 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_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.
*/
struct sqlite3ota {
  int eStage;                     /* Value of OTA_STATE_STAGE field */
  sqlite3 *db;                    /* "main" -> target db, "ota" -> ota db */
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
    sqlite3_free(zSql);
  }
  return rc;
}

/*
** Free the OtaObjIter.azTblCol[] and OtaObjIter.abTblPk[] arrays allocated
** by an earlier call to otaObjIterGetCols().
*/
static void otaObjIterFreeCols(OtaObjIter *pIter){
  int i;
  for(i=0; i<pIter->nTblCol; i++){
    sqlite3_free(pIter->azTblCol[i]);
    sqlite3_free(pIter->azTblType[i]);
  }
  sqlite3_free(pIter->azTblCol);
  pIter->azTblCol = 0;
  pIter->azTblType = 0;

  pIter->abTblPk = 0;
  pIter->nTblCol = 0;
  sqlite3_free(pIter->zMask);
  pIter->zMask = 0;
  pIter->eType = 0;               /* Invalid value */
}








|










>







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
    sqlite3_free(zSql);
  }
  return rc;
}

/*
** Free the OtaObjIter.azTblCol[] and OtaObjIter.abTblPk[] arrays allocated
** by an earlier call to otaObjIterCacheTableInfo().
*/
static void otaObjIterFreeCols(OtaObjIter *pIter){
  int i;
  for(i=0; i<pIter->nTblCol; i++){
    sqlite3_free(pIter->azTblCol[i]);
    sqlite3_free(pIter->azTblType[i]);
  }
  sqlite3_free(pIter->azTblCol);
  pIter->azTblCol = 0;
  pIter->azTblType = 0;
  pIter->aiTblOrder = 0;
  pIter->abTblPk = 0;
  pIter->nTblCol = 0;
  sqlite3_free(pIter->zMask);
  pIter->zMask = 0;
  pIter->eType = 0;               /* Invalid value */
}

281
282
283
284
285
286
287








288


289
290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
*/
static int otaObjIterNext(sqlite3ota *p, OtaObjIter *pIter){
  int rc = p->rc;
  if( rc==SQLITE_OK ){

    /* Free any SQLite statements used while processing the previous object */ 
    otaObjIterClearStatements(pIter);











    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;
      }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( rc!=SQLITE_OK ){
    otaObjIterFinalize(pIter);
    p->rc = rc;







>
>
>
>
>
>
>
>
|
>
>
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
*/
static int otaObjIterNext(sqlite3ota *p, OtaObjIter *pIter){
  int rc = p->rc;
  if( rc==SQLITE_OK ){

    /* 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( 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{
        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;
        }
      }
    }
  }

  if( rc!=SQLITE_OK ){
    otaObjIterFinalize(pIter);
    p->rc = rc;
332
333
334
335
336
337
338
339


340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
** error code is returned.
*/
static int otaObjIterFirst(sqlite3ota *p, OtaObjIter *pIter){
  int rc;
  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_%'"
  );

  if( rc==SQLITE_OK ){
    rc = prepareAndCollectError(p->db, &pIter->pIdxIter, &p->zErrmsg,
        "SELECT name, rootpage, sql IS NULL OR substr(8, 6)=='UNIQUE' "
        "  FROM main.sqlite_master "
        "  WHERE type='index' AND tbl_name = ?"
    );
  }

  pIter->bCleanup = 1;
  p->rc = rc;
  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
** the printf() style substitutions and executes the result as an SQL
** statement on the OTA handles database.
**
** If an error occurs, an error code and error message is stored in the







|
>
>
|















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378















































379
380
381
382
383
384
385
** error code is returned.
*/
static int otaObjIterFirst(sqlite3ota *p, OtaObjIter *pIter){
  int rc;
  memset(pIter, 0, sizeof(OtaObjIter));

  rc = prepareAndCollectError(p->db, &pIter->pTblIter, &p->zErrmsg, 
      "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 ){
    rc = prepareAndCollectError(p->db, &pIter->pIdxIter, &p->zErrmsg,
        "SELECT name, rootpage, sql IS NULL OR substr(8, 6)=='UNIQUE' "
        "  FROM main.sqlite_master "
        "  WHERE type='index' AND tbl_name = ?"
    );
  }

  pIter->bCleanup = 1;
  p->rc = rc;
  return otaObjIterNext(p, pIter);
}
















































/*
** Argument zFmt is a sqlite3_mprintf() style format string. The trailing
** arguments are the usual subsitution values. This function performs
** the printf() style substitutions and executes the result as an SQL
** statement on the OTA handles database.
**
** If an error occurs, an error code and error message is stored in the
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443

444
445
446
447
448
449
450
451

/*
** Allocate and zero the pIter->azTblCol[] and abTblPk[] arrays so that
** there is room for at least nCol elements. If an OOM occurs, store an
** 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;
  char **azNew;

  assert( p->rc==SQLITE_OK );
  azNew = (char**)sqlite3_malloc(nByte);
  if( azNew ){
    memset(azNew, 0, nByte);
    pIter->azTblCol = azNew;
    pIter->azTblType = &azNew[nCol];

    pIter->abTblPk = (unsigned char*)&pIter->azTblType[nCol];
  }else{
    p->rc = SQLITE_NOMEM;
  }
}

static char *otaStrndup(const char *zStr, int nStr, int *pRc){
  char *zRet = 0;







|








>
|







404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428

/*
** Allocate and zero the pIter->azTblCol[] and abTblPk[] arrays so that
** there is room for at least nCol elements. If an OOM occurs, store an
** error code in the OTA handle passed as the first argument.
*/
static void otaAllocateIterArrays(sqlite3ota *p, OtaObjIter *pIter, int nCol){
  int nByte = (sizeof(char*) * 2 + sizeof(int) + sizeof(unsigned char)) * nCol;
  char **azNew;

  assert( p->rc==SQLITE_OK );
  azNew = (char**)sqlite3_malloc(nByte);
  if( azNew ){
    memset(azNew, 0, nByte);
    pIter->azTblCol = azNew;
    pIter->azTblType = &azNew[nCol];
    pIter->aiTblOrder = (int*)&pIter->azTblType[nCol];
    pIter->abTblPk = (unsigned char*)&pIter->aiTblOrder[nCol];
  }else{
    p->rc = SQLITE_NOMEM;
  }
}

static char *otaStrndup(const char *zStr, int nStr, int *pRc){
  char *zRet = 0;
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510

511

512







513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537










538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558

559
560




561
562

563
564
565
566
567
568




569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588

589


590
591
592
593
594
595
596
    }
  }

  return zRet;
}


/*
** 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.
**
** 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){
  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" */



    assert( pIter->eType==0 );








    /* Populate the azTblCol[] and nTblCol variables based on the columns
    ** of the input table. Ignore any input table columns that begin with
    ** "ota_".  */
    p->rc = prepareFreeAndCollectError(p->db, &pStmt, &p->zErrmsg, 
        sqlite3_mprintf("SELECT * FROM 'data_%q'", pIter->zTbl)
    );
    if( p->rc==SQLITE_OK ){
      nCol = sqlite3_column_count(pStmt);
      otaAllocateIterArrays(p, pIter, nCol);
    }
    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);
        pIter->azTblCol[pIter->nTblCol++] = zCopy;
        if( zCopy==0 ) p->rc = SQLITE_NOMEM;
      }
      else if( 0==sqlite3_stricmp("ota_rowid", zName) ){
        bOtaRowid = 1;
      }
    }
    sqlite3_finalize(pStmt);
    pStmt = 0;











    /* 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.  */
    if( p->rc==SQLITE_OK ){
      p->rc = prepareFreeAndCollectError(p->db, &pStmt, &p->zErrmsg, 
          sqlite3_mprintf("PRAGMA main.table_info(%Q)", pIter->zTbl)
      );
    }
    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( i==pIter->nTblCol ){
        p->rc = SQLITE_ERROR;
        p->zErrmsg = sqlite3_mprintf("column missing from data_%q: %s",
            pIter->zTbl, zName
        );
      }else{
        int iPk = sqlite3_column_int(pStmt, 5);
        const char *zType = (const char*)sqlite3_column_text(pStmt, 2);

        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;
        }
      }else if( bOtaRowid ){
        p->rc = SQLITE_ERROR;
        p->zErrmsg = sqlite3_mprintf(
            "table data_%q may not have ota_rowid column", pIter->zTbl
        );
      }

    }


  }

  return p->rc;
}

/*
** This is a wrapper around "sqlite3_mprintf(zFmt, ...)". If an OOM occurs,








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|





|






>

>

>
>
>
>
>
>
>














|

<








>
>
>
>
>
>
>
>
>
>

|
|








|









>


>
>
>
>
|
|
>



<
<

>
>
>
>
|
<
<
<
<
|
|
<
<
|
<
<
<
<
<
<
<
<
|
|
>
|
>
>







439
440
441
442
443
444
445
446


























447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488

489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540


541
542
543
544
545
546




547
548


549








550
551
552
553
554
555
556
557
558
559
560
561
562
    }
  }

  return zRet;
}


/*


























** If they are not already populated, populate the pIter->azTblCol[],
** pIter->abTblPk[], pIter->nTblCol and pIter->bRowid variables according 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 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
    ** "ota_".  */
    p->rc = prepareFreeAndCollectError(p->db, &pStmt, &p->zErrmsg, 
        sqlite3_mprintf("SELECT * FROM 'data_%q'", pIter->zTbl)
    );
    if( p->rc==SQLITE_OK ){
      nCol = sqlite3_column_count(pStmt);
      otaAllocateIterArrays(p, pIter, nCol);
    }
    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 = otaStrndup(zName, -1, &p->rc);
        pIter->azTblCol[pIter->nTblCol++] = zCopy;

      }
      else if( 0==sqlite3_stricmp("ota_rowid", zName) ){
        bOtaRowid = 1;
      }
    }
    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[], 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)
      );
    }
    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( 0==strcmp(zName, pIter->azTblCol[i]) ) break;
      }
      if( i==pIter->nTblCol ){
        p->rc = SQLITE_ERROR;
        p->zErrmsg = sqlite3_mprintf("column missing from data_%q: %s",
            pIter->zTbl, zName
        );
      }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);
      }
    }
    while( iOrder<pIter->nTblCol ){
      for(i=0; i<pIter->nTblCol; i++){
        if( pIter->aiTblOrder[i]==0 ){
          pIter->aiTblOrder[i] = iOrder++;
          continue;
        }
      }
    }



    /* 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;
}

/*
** This is a wrapper around "sqlite3_mprintf(zFmt, ...)". If an OOM occurs,
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
  return zSql;
}

/*
** 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 */
){
  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;
      }
    }
  }
  return zList;
}

/*
** This function is used to create a SELECT list (the list of SQL 
** expressions that follows a SELECT keyword) for a SELECT statement 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



|
<
<
<


<
|
|
|
<
|
|
<
<
<
|
<
<
<
<
<







574
575
576
577
578
579
580





























581
582
583
584



585
586

587
588
589

590
591



592





593
594
595
596
597
598
599
  return zSql;
}

/*
** 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.





























*/
static char *otaObjIterGetCollist(
  sqlite3ota *p,                  /* OTA object */
  OtaObjIter *pIter               /* Object iterator for column names */



){
  char *zList = 0;

  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;
}

/*
** This function is used to create a SELECT list (the list of SQL 
** expressions that follows a SELECT keyword) for a SELECT statement 
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
  int rc = p->rc;                 /* Error code */
  int rc2;                        /* sqlite3_finalize() return code */
  char *zRet = 0;                 /* String to return */
  char *zImpCols = 0;             /* String to return via *pzImposterCols */
  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 *zAnd = "";          /* Set to " AND " later on */
  sqlite3_stmt *pXInfo = 0;       /* PRAGMA index_xinfo = ? */

  if( rc==SQLITE_OK ){
    assert( p->zErrmsg==0 );
    rc = prepareFreeAndCollectError(p->db, &pXInfo, &p->zErrmsg,
        sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zIdx)
    );
  }

  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
    const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4);
    int iCid = sqlite3_column_int(pXInfo, 1);
    const char *zCol;
    const char *zType;

    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 ){
        int i;
        for(i=0; i<pIter->nTblCol && pIter->abTblPk[i]==0; i++);
        assert( i<pIter->nTblCol );
        zCol = pIter->azTblCol[i];
      }else{
        zCol = "ota_rowid";
      }
      zType = "INTEGER";
    }else{
      zCol = pIter->azTblCol[iCid];
      zType = pIter->azTblType[iCid];
    }

    zRet = sqlite3_mprintf("%z%s%s COLLATE %Q", zRet, zComma, zCol, zCollate);
    if( pIter->bUnique==0 || sqlite3_column_int(pXInfo, 5) ){
      zImpPK = sqlite3_mprintf("%z%sc%d", zImpPK, zComma, nBind);
    }
    zImpCols = sqlite3_mprintf(
        "%z%sc%d %s COLLATE %Q", zImpCols, zComma, 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 = ", ";
    zAnd = " AND ";
    nBind++;
  }

  rc2 = sqlite3_finalize(pXInfo);
  if( rc==SQLITE_OK ) rc = rc2;








|



















|













|

|


|



|







629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
  int rc = p->rc;                 /* Error code */
  int rc2;                        /* sqlite3_finalize() return code */
  char *zRet = 0;                 /* String to return */
  char *zImpCols = 0;             /* String to return via *pzImposterCols */
  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 *zCom = "";          /* Set to ", " later on */
  const char *zAnd = "";          /* Set to " AND " later on */
  sqlite3_stmt *pXInfo = 0;       /* PRAGMA index_xinfo = ? */

  if( rc==SQLITE_OK ){
    assert( p->zErrmsg==0 );
    rc = prepareFreeAndCollectError(p->db, &pXInfo, &p->zErrmsg,
        sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zIdx)
    );
  }

  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
    const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4);
    int iCid = sqlite3_column_int(pXInfo, 1);
    const char *zCol;
    const char *zType;

    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_IPK ){
        int i;
        for(i=0; i<pIter->nTblCol && pIter->abTblPk[i]==0; i++);
        assert( i<pIter->nTblCol );
        zCol = pIter->azTblCol[i];
      }else{
        zCol = "ota_rowid";
      }
      zType = "INTEGER";
    }else{
      zCol = pIter->azTblCol[iCid];
      zType = pIter->azTblType[iCid];
    }

    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, zCom, nBind);
    }
    zImpCols = sqlite3_mprintf(
        "%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;
    zCom = ", ";
    zAnd = " AND ";
    nBind++;
  }

  rc2 = sqlite3_finalize(pXInfo);
  if( rc==SQLITE_OK ) rc = rc2;

796
797
798
799
800
801
802

803
804
805
806
807
808
809
810
  const char *zObj
){
  char *zList = 0;
  if( p->rc==SQLITE_OK ){
    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]);
      zS = ", ";
      if( zList==0 ){
        p->rc = SQLITE_NOMEM;
        break;
      }
    }








>
|







720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
  const char *zObj
){
  char *zList = 0;
  if( p->rc==SQLITE_OK ){
    const char *zS = "";
    int i;
    for(i=0; i<pIter->nTblCol; 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;
        break;
      }
    }

827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
**   "b = ?1 AND c = ?2"
*/
static char *otaObjIterGetWhere(
  sqlite3ota *p, 
  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 ";
        }
      }
    }
  }
  return zList;
}

/*







<
|
|
|
|
|
|
|
|
|
|
|
|
<







752
753
754
755
756
757
758

759
760
761
762
763
764
765
766
767
768
769
770

771
772
773
774
775
776
777
**   "b = ?1 AND c = ?2"
*/
static char *otaObjIterGetWhere(
  sqlite3ota *p, 
  OtaObjIter *pIter
){
  char *zList = 0;

  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 ";

      }
    }
  }
  return zList;
}

/*
876
877
878
879
880
881
882
883
884
885
886
887
888
889

890
891
892
893
894
895
896
    if( strlen(zMask)!=pIter->nTblCol ){
      otaBadControlError(p);
    }else{
      const char *zSep = "";
      for(i=0; i<pIter->nTblCol; i++){
        char c = zMask[i];
        if( c=='x' ){
          zList = otaMPrintfAndCollectError(p, "%z%s%s=?%d", 
              zList, zSep, pIter->azTblCol[i], i+1
          );
          zSep = ", ";
        }
        if( c=='d' ){
          zList = otaMPrintfAndCollectError(p, "%z%s%s=ota_delta(%s, ?%d)", 

              zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1
          );
          zSep = ", ";
        }
      }
    }
  }







|





|
>







799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
    if( strlen(zMask)!=pIter->nTblCol ){
      otaBadControlError(p);
    }else{
      const char *zSep = "";
      for(i=0; i<pIter->nTblCol; i++){
        char c = zMask[i];
        if( c=='x' ){
          zList = otaMPrintfAndCollectError(p, "%z%s\"%w\"=?%d", 
              zList, zSep, pIter->azTblCol[i], i+1
          );
          zSep = ", ";
        }
        if( c=='d' ){
          zList = otaMPrintfAndCollectError(p, 
              "%z%s\"%w\"=ota_delta(\"%w\", ?%d)", 
              zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1
          );
          zSep = ", ";
        }
      }
    }
  }
910
911
912
913
914
915
916











































































917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
        zRet[i*2] = '?';
        zRet[i*2+1] = (i+1==nBind) ? '\0' : ',';
      }
    }
  }
  return zRet;
}












































































/*
** Ensure that the SQLite statement handles required to update the 
** target database object currently indicated by the iterator passed 
** as the second argument are available.
*/
static int otaObjIterPrepareAll(
  sqlite3ota *p, 
  OtaObjIter *pIter,
  int nOffset                     /* Add "LIMIT -1 OFFSET $nOffset" to SELECT */
){
  assert( pIter->bCleanup==0 );
  if( pIter->pSelect==0 && otaObjIterGetCols(p, pIter)==SQLITE_OK ){
    const int tnum = pIter->tnum;
    char *zCollist = 0;           /* List of indexed columns */
    char **pz = &p->zErrmsg;
    const char *zIdx = pIter->zIdx;
    char *zLimit = 0;

    if( nOffset ){
      zLimit = sqlite3_mprintf(" LIMIT -1 OFFSET %d", nOffset);
      if( !zLimit ) p->rc = SQLITE_NOMEM;
    }

    if( zIdx ){
      char *zImposterCols = 0;
      char *zImposterPK = 0;
      char *zWhere = 0;
      char *zBind = 0;
      int nBind = 0;

      assert( pIter->eType!=OTA_PK_VTAB );
      zCollist = otaObjIterGetIndexCols(
          p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind
      );







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












|












|
|
|







834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
        zRet[i*2] = '?';
        zRet[i*2+1] = (i+1==nBind) ? '\0' : ',';
      }
    }
  }
  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 
** as the second argument are available.
*/
static int otaObjIterPrepareAll(
  sqlite3ota *p, 
  OtaObjIter *pIter,
  int nOffset                     /* Add "LIMIT -1 OFFSET $nOffset" to SELECT */
){
  assert( pIter->bCleanup==0 );
  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;
    const char *zIdx = pIter->zIdx;
    char *zLimit = 0;

    if( nOffset ){
      zLimit = sqlite3_mprintf(" LIMIT -1 OFFSET %d", nOffset);
      if( !zLimit ) p->rc = SQLITE_NOMEM;
    }

    if( zIdx ){
      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;

      assert( pIter->eType!=OTA_PK_VTAB );
      zCollist = otaObjIterGetIndexCols(
          p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind
      );
1001
1002
1003
1004
1005
1006
1007
1008



1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026




1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092

      sqlite3_free(zImposterCols);
      sqlite3_free(zImposterPK);
      sqlite3_free(zWhere);
      sqlite3_free(zBind);
    }else{
      int bOtaRowid = (pIter->eType==OTA_PK_VTAB || pIter->eType==OTA_PK_NONE);
      const char *zTbl = pIter->zTbl;



      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);
      pIter->nCol = pIter->nTblCol;

      /* Create the SELECT statement to read keys from data_xxx */
      if( p->rc==SQLITE_OK ){
        p->rc = prepareFreeAndCollectError(p->db, &pIter->pSelect, pz,
            sqlite3_mprintf(
              "SELECT %s, ota_control%s FROM ota.'data_%q'%s", 
              zCollist, (bOtaRowid ? ", ota_rowid" : ""), zTbl, zLimit
            )
        );
      }





      /* 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
            )
        );
      }

      /* Create the DELETE statement to write to the target PK b-tree */
      if( p->rc==SQLITE_OK ){
        p->rc = prepareFreeAndCollectError(p->db, &pIter->pDelete, pz,
            sqlite3_mprintf(
              "DELETE FROM main.%Q WHERE %s", zTbl, zWhere
            )
        );
      }

      if( pIter->eType!=OTA_PK_VTAB ){
        const char *zOtaRowid = "";
        if( pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_NONE ){
          zOtaRowid = ", ota_rowid";
        }

        /* Create the ota_tmp_xxx table and the triggers to populate it. */
        otaMPrintfExec(p, 
            "PRAGMA ota_mode = 1;"
            "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 "
            "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 "
            "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 "
            "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
        );
        if( pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_NONE ){
          otaMPrintfExec(p, 
              "CREATE TEMP TRIGGER ota_insert_%q AFTER INSERT ON main.%Q "
              "BEGIN "
              "  INSERT INTO 'ota_tmp_%q'(ota_control, %s, ota_rowid)"
              "  VALUES(0, %s);"
              "END;"
              , zTbl, zTbl, zTbl, zCollist, zNewlist
          );
        }
      }else if( p->rc==SQLITE_OK ){
        p->rc = sqlite3_exec(p->db, "PRAGMA ota_mode = 0", 0, 0, &p->zErrmsg);
      }

      /* Allocate space required for the zMask field. */







|
>
>
>



<

|












>
>
>
>





|








|
















|




|




|





|
|
|



|




|







1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013

1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097

      sqlite3_free(zImposterCols);
      sqlite3_free(zImposterPK);
      sqlite3_free(zWhere);
      sqlite3_free(zBind);
    }else{
      int bOtaRowid = (pIter->eType==OTA_PK_VTAB || pIter->eType==OTA_PK_NONE);
      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");


      zCollist = otaObjIterGetCollist(p, pIter);
      pIter->nCol = pIter->nTblCol;

      /* Create the SELECT statement to read keys from data_xxx */
      if( p->rc==SQLITE_OK ){
        p->rc = prepareFreeAndCollectError(p->db, &pIter->pSelect, pz,
            sqlite3_mprintf(
              "SELECT %s, ota_control%s FROM ota.'data_%q'%s", 
              zCollist, (bOtaRowid ? ", ota_rowid" : ""), zTbl, zLimit
            )
        );
      }

      /* 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)", 
              zWrite, zCollist, (bOtaRowid ? ", _rowid_" : ""), zBindings
            )
        );
      }

      /* Create the DELETE statement to write to the target PK b-tree */
      if( p->rc==SQLITE_OK ){
        p->rc = prepareFreeAndCollectError(p->db, &pIter->pDelete, pz,
            sqlite3_mprintf(
              "DELETE FROM main.%Q WHERE %s", zWrite, zWhere
            )
        );
      }

      if( pIter->eType!=OTA_PK_VTAB ){
        const char *zOtaRowid = "";
        if( pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_NONE ){
          zOtaRowid = ", ota_rowid";
        }

        /* Create the ota_tmp_xxx table and the triggers to populate it. */
        otaMPrintfExec(p, 
            "PRAGMA ota_mode = 1;"
            "CREATE TABLE IF NOT EXISTS ota.'ota_tmp_%q' AS "
            "SELECT *%s FROM ota.'data_%q' WHERE 0;"

            "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_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_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, 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_tr AFTER INSERT ON ota_imposter "
              "BEGIN "
              "  INSERT INTO 'ota_tmp_%q'(ota_control, %s, ota_rowid)"
              "  VALUES(0, %s);"
              "END;"
              , zTbl, zCollist, zNewlist
          );
        }
      }else if( p->rc==SQLITE_OK ){
        p->rc = sqlite3_exec(p->db, "PRAGMA ota_mode = 0", 0, 0, &p->zErrmsg);
      }

      /* Allocate space required for the zMask field. */
1129
1130
1131
1132
1133
1134
1135
1136

1137
1138
1139
1140
1141
1142
1143
1144
  }else{
    char *zWhere = otaObjIterGetWhere(p, pIter);
    char *zSet = otaObjIterGetSetlist(p, pIter, zMask);
    char *zUpdate = 0;
    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
      );
      p->rc = prepareFreeAndCollectError(
          p->db, &pIter->pUpdate, &p->zErrmsg, zUpdate
      );
      *ppStmt = pIter->pUpdate;
    }
    if( p->rc==SQLITE_OK ){







|
>
|







1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
  }else{
    char *zWhere = otaObjIterGetWhere(p, pIter);
    char *zSet = otaObjIterGetSetlist(p, pIter, zMask);
    char *zUpdate = 0;
    sqlite3_finalize(pIter->pUpdate);
    pIter->pUpdate = 0;
    if( p->rc==SQLITE_OK ){
      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
      );
      *ppStmt = pIter->pUpdate;
    }
    if( p->rc==SQLITE_OK ){
1333
1334
1335
1336
1337
1338
1339












1340
1341
1342

1343
1344
1345
1346
1347
1348
1349
      if( eType==OTA_IDX_DELETE || eType==OTA_DELETE ){
        pWriter = pIter->pDelete;
      }else{
        pWriter = pIter->pInsert;
      }

      for(i=0; i<pIter->nCol; i++){












        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);
      }
      if( pIter->zIdx==0
       && (pIter->eType==OTA_PK_VTAB || pIter->eType==OTA_PK_NONE) 
      ){
        /* For a virtual table, or a table with no primary key, the 







>
>
>
>
>
>
>
>
>
>
>
>



>







1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
      if( eType==OTA_IDX_DELETE || eType==OTA_DELETE ){
        pWriter = pIter->pDelete;
      }else{
        pWriter = pIter->pInsert;
      }

      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);
      }
      if( pIter->zIdx==0
       && (pIter->eType==OTA_PK_VTAB || pIter->eType==OTA_PK_NONE) 
      ){
        /* For a virtual table, or a table with no primary key, the 
1379
1380
1381
1382
1383
1384
1385

1386
1387
1388
1389
1390
1391
1392
      }
    }else{
      /* no-op */
      assert( eType==OTA_DELETE && pIter->zIdx );
    }
  }


  return p->rc;
}

/*
** Increment the schema cookie of the main database opened by p->db.
*/
static void otaIncrSchemaCookie(sqlite3ota *p){







>







1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
      }
    }else{
      /* no-op */
      assert( eType==OTA_DELETE && pIter->zIdx );
    }
  }

 step_out:
  return p->rc;
}

/*
** Increment the schema cookie of the main database opened by p->db.
*/
static void otaIncrSchemaCookie(sqlite3ota *p){
Changes to src/btree.c.
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  Pgno iTab = 0;
  BtLock *pLock;

  /* If this database is not shareable, or if the client is reading
  ** and has the read-uncommitted flag set, then no lock is required. 
  ** Return true immediately.
  */
  if( (pBtree->db->flags & SQLITE_OtaMode)
   || (pBtree->sharable==0)
   || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommitted))
  ){
    return 1;
  }

  /* If the client is reading  or writing an index and the schema is
  ** not loaded, then it is too difficult to actually check to see if







<
|







147
148
149
150
151
152
153

154
155
156
157
158
159
160
161
  Pgno iTab = 0;
  BtLock *pLock;

  /* If this database is not shareable, or if the client is reading
  ** and has the read-uncommitted flag set, then no lock is required. 
  ** Return true immediately.
  */

  if( (pBtree->sharable==0)
   || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommitted))
  ){
    return 1;
  }

  /* If the client is reading  or writing an index and the schema is
  ** not loaded, then it is too difficult to actually check to see if
Changes to src/delete.c.
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
  int r1 = -1;       /* Register holding an index key */
  int iPartIdxLabel; /* Jump destination for skipping partial index entries */
  Index *pIdx;       /* Current index */
  Index *pPrior = 0; /* Prior index */
  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){
    assert( iIdxCur+i!=iDataCur || pPk==pIdx );
    if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
    if( pIdx==pPk ) continue;
    VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));







<
<
<







726
727
728
729
730
731
732



733
734
735
736
737
738
739
  int r1 = -1;       /* Register holding an index key */
  int iPartIdxLabel; /* Jump destination for skipping partial index entries */
  Index *pIdx;       /* Current index */
  Index *pPrior = 0; /* Prior index */
  Vdbe *v;           /* The prepared statement under construction */
  Index *pPk;        /* PRIMARY KEY index, or NULL for rowid tables */




  v = pParse->pVdbe;
  pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
  for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
    assert( iIdxCur+i!=iDataCur || pPk==pIdx );
    if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
    if( pIdx==pPk ) continue;
    VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
Changes to src/insert.c.
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
  */
  for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){
    int regIdx;          /* Range of registers hold conent for pIdx */
    int regR;            /* Range of registers holding conflicting PK */
    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);
      bAffinityDone = 1;
    }
    iThisCur = iIdxCur+ix;
    addrUniqueOk = sqlite3VdbeMakeLabel(v);







<
<
<
<







1361
1362
1363
1364
1365
1366
1367




1368
1369
1370
1371
1372
1373
1374
  */
  for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){
    int regIdx;          /* Range of registers hold conent for pIdx */
    int regR;            /* Range of registers holding conflicting PK */
    int iThisCur;        /* Cursor for this UNIQUE index */
    int addrUniqueOk;    /* Jump here if the UNIQUE constraint is satisfied */





    if( aRegIdx[ix]==0 ) continue;  /* Skip indices that do not change */
    if( bAffinityDone==0 ){
      sqlite3TableAffinity(v, pTab, regNewData+1);
      bAffinityDone = 1;
    }
    iThisCur = iIdxCur+ix;
    addrUniqueOk = sqlite3VdbeMakeLabel(v);
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
  u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */

  v = sqlite3GetVdbe(pParse);
  assert( v!=0 );
  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);
      VdbeCoverage(v);
    }
    sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]);
    pik_flags = 0;







<
<
<
<
<
<
<
<
<







1552
1553
1554
1555
1556
1557
1558









1559
1560
1561
1562
1563
1564
1565
  u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */

  v = sqlite3GetVdbe(pParse);
  assert( v!=0 );
  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;









    bAffinityDone = 1;
    if( pIdx->pPartIdxWhere ){
      sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
      VdbeCoverage(v);
    }
    sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]);
    pik_flags = 0;
Changes to src/main.c.
3650
3651
3652
3653
3654
3655
3656







































3657
3658
3659
3660
3661
3662
3663
      db->init.newTnum = va_arg(ap,int);
      if( db->init.busy==0 && db->init.newTnum>0 ){
        sqlite3ResetAllSchemasOfConnection(db);
      }
      sqlite3_mutex_leave(db->mutex);
      break;
    }







































  }
  va_end(ap);
#endif /* SQLITE_OMIT_BUILTIN_TEST */
  return rc;
}

/*







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
      db->init.newTnum = va_arg(ap,int);
      if( db->init.busy==0 && db->init.newTnum>0 ){
        sqlite3ResetAllSchemasOfConnection(db);
      }
      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 */
  return rc;
}

/*
Changes to src/pragma.c.
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
    /* ePragTyp:  */ PragTyp_PAGE_COUNT,
    /* ePragFlag: */ PragFlag_NeedSchema,
    /* iArg:      */ 0 },
  { /* zName:     */ "mmap_size",
    /* 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,
    /* iArg:      */ 0 },
  { /* zName:     */ "page_size",
    /* ePragTyp:  */ PragTyp_PAGE_SIZE,
    /* ePragFlag: */ 0,







<
<
<
<
<
<
<
<







316
317
318
319
320
321
322








323
324
325
326
327
328
329
    /* ePragTyp:  */ PragTyp_PAGE_COUNT,
    /* ePragFlag: */ PragFlag_NeedSchema,
    /* iArg:      */ 0 },
  { /* zName:     */ "mmap_size",
    /* ePragTyp:  */ PragTyp_MMAP_SIZE,
    /* ePragFlag: */ 0,
    /* iArg:      */ 0 },








  { /* zName:     */ "page_count",
    /* ePragTyp:  */ PragTyp_PAGE_COUNT,
    /* ePragFlag: */ PragFlag_NeedSchema,
    /* iArg:      */ 0 },
  { /* zName:     */ "page_size",
    /* ePragTyp:  */ PragTyp_PAGE_SIZE,
    /* ePragFlag: */ 0,
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
  { /* zName:     */ "writable_schema",
    /* ePragTyp:  */ PragTyp_FLAG,
    /* ePragFlag: */ 0,
    /* iArg:      */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
#endif
};
/* Number of pragmas: 59 on by default, 74 total. */
/* End of the automatically generated pragma table.
***************************************************************************/

/*
** Interpret the given string as a safety level.  Return 0 for OFF,
** 1 for ON or NORMAL and 2 for FULL.  Return 1 for an empty or 
** unrecognized string argument.  The FULL option is disallowed







|







484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
  { /* zName:     */ "writable_schema",
    /* ePragTyp:  */ PragTyp_FLAG,
    /* ePragFlag: */ 0,
    /* iArg:      */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
#endif
};
/* Number of pragmas: 59 on by default, 73 total. */
/* End of the automatically generated pragma table.
***************************************************************************/

/*
** Interpret the given string as a safety level.  Return 0 for OFF,
** 1 for ON or NORMAL and 2 for FULL.  Return 1 for an empty or 
** unrecognized string argument.  The FULL option is disallowed
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
        }
        if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
          k = 0;
        }else if( pPk==0 ){
          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);
      }
    }
  }
  break;







<
<
<







1533
1534
1535
1536
1537
1538
1539



1540
1541
1542
1543
1544
1545
1546
        }
        if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
          k = 0;
        }else if( pPk==0 ){
          k = 1;
        }else{
          for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){}



        }
        sqlite3VdbeAddOp2(v, OP_Integer, k, 6);
        sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
      }
    }
  }
  break;
Changes to src/sqlite.h.in.
6262
6263
6264
6265
6266
6267
6268

6269
6270
6271
6272
6273
6274
6275
6276
#define SQLITE_TESTCTRL_EXPLAIN_STMT            19  /* NOT USED */
#define SQLITE_TESTCTRL_NEVER_CORRUPT           20
#define SQLITE_TESTCTRL_VDBE_COVERAGE           21
#define SQLITE_TESTCTRL_BYTEORDER               22
#define SQLITE_TESTCTRL_ISINIT                  23
#define SQLITE_TESTCTRL_SORTER_MMAP             24
#define SQLITE_TESTCTRL_IMPOSTER                25

#define SQLITE_TESTCTRL_LAST                    25

/*
** CAPI3REF: SQLite Runtime Status
**
** ^This interface is used to retrieve runtime status information
** about the performance of SQLite, and optionally to reset various
** highwater marks.  ^The first argument is an integer code for







>
|







6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
#define SQLITE_TESTCTRL_EXPLAIN_STMT            19  /* NOT USED */
#define SQLITE_TESTCTRL_NEVER_CORRUPT           20
#define SQLITE_TESTCTRL_VDBE_COVERAGE           21
#define SQLITE_TESTCTRL_BYTEORDER               22
#define SQLITE_TESTCTRL_ISINIT                  23
#define SQLITE_TESTCTRL_SORTER_MMAP             24
#define SQLITE_TESTCTRL_IMPOSTER                25
#define SQLITE_TESTCTRL_TBLTYPE                 26
#define SQLITE_TESTCTRL_LAST                    26

/*
** CAPI3REF: SQLite Runtime Status
**
** ^This interface is used to retrieve runtime status information
** about the performance of SQLite, and optionally to reset various
** highwater marks.  ^The first argument is an integer code for
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
** ^Zero all [sqlite3_stmt_scanstatus()] related event counters.
**
** This API is only available if the library is built with pre-processor
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
*/
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.
**
** An incremental checkpoint handle is opened using the sqlite3_ckpt_open()
** API. To begin a new checkpoint, the second and third arguments should both
** be passed zero. To resume an earlier checkpoint, the second and third
** arguments should specify a buffer returned by an earlier call to







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







7582
7583
7584
7585
7586
7587
7588




























































7589
7590
7591
7592
7593
7594
7595
** ^Zero all [sqlite3_stmt_scanstatus()] related event counters.
**
** This API is only available if the library is built with pre-processor
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
*/
SQLITE_EXPERIMENTAL void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);





























































/*
** Incremental checkpoint API.
**
** An incremental checkpoint handle is opened using the sqlite3_ckpt_open()
** API. To begin a new checkpoint, the second and third arguments should both
** be passed zero. To resume an earlier checkpoint, the second and third
** arguments should specify a buffer returned by an earlier call to
Changes to src/sqliteInt.h.
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
#define SQLITE_PreferBuiltin  0x00200000  /* Preference to built-in funcs */
#define SQLITE_LoadExtension  0x00400000  /* Enable load_extension */
#define SQLITE_EnableTrigger  0x00800000  /* True to enable triggers */
#define SQLITE_DeferFKs       0x01000000  /* Defer all FK constraints */
#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
** selectively disable various optimizations.
*/
#define SQLITE_QueryFlattener 0x0001   /* Query flattening */
#define SQLITE_ColumnCache    0x0002   /* Column cache */







<
<
<
<
<
<







1203
1204
1205
1206
1207
1208
1209






1210
1211
1212
1213
1214
1215
1216
#define SQLITE_PreferBuiltin  0x00200000  /* Preference to built-in funcs */
#define SQLITE_LoadExtension  0x00400000  /* Enable load_extension */
#define SQLITE_EnableTrigger  0x00800000  /* True to enable triggers */
#define SQLITE_DeferFKs       0x01000000  /* Defer all FK constraints */
#define SQLITE_QueryOnly      0x02000000  /* Disable database changes */
#define SQLITE_VdbeEQP        0x04000000  /* Debug EXPLAIN QUERY PLAN */







/*
** Bits of the sqlite3.dbOptFlags field that are used by the
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
** selectively disable various optimizations.
*/
#define SQLITE_QueryFlattener 0x0001   /* Query flattening */
#define SQLITE_ColumnCache    0x0002   /* Column cache */
Changes to src/test1.c.
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929

6930
6931
6932
6933
6934
6935
6936
     { "sorter_test_sort4_helper", sorter_test_sort4_helper },
#ifdef SQLITE_USER_AUTHENTICATION
     { "sqlite3_user_authenticate", test_user_authenticate, 0 },
     { "sqlite3_user_add",          test_user_add,          0 },
     { "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;
  int i;
  extern int sqlite3_sync_count, sqlite3_fullsync_count;
  extern int sqlite3_opentemp_count;
  extern int sqlite3_like_count;







<




>







6918
6919
6920
6921
6922
6923
6924

6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
     { "sorter_test_sort4_helper", sorter_test_sort4_helper },
#ifdef SQLITE_USER_AUTHENTICATION
     { "sqlite3_user_authenticate", test_user_authenticate, 0 },
     { "sqlite3_user_add",          test_user_add,          0 },
     { "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;
  int i;
  extern int sqlite3_sync_count, sqlite3_fullsync_count;
  extern int sqlite3_opentemp_count;
  extern int sqlite3_like_count;
Changes to src/trigger.c.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
** triggers on pTab in the TEMP schema.  This routine prepends all
** TEMP triggers on pTab to the beginning of the pTab->pTrigger list
** and returns the combined list.
**
** 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;
  }

  if( pTmpSchema!=pTab->pSchema ){
    HashElem *p;
    assert( sqlite3SchemaMutexHeld(pParse->db, 0, pTmpSchema) );
    for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
      Trigger *pTrig = (Trigger *)sqliteHashData(p);
      if( pTrig->pTabSchema==pTab->pSchema
       && 0==sqlite3StrICmp(pTrig->table, pTab->zName) 
      ){
        pTrig->pNext = ((pList || bOta) ? pList : pTab->pTrigger);
        pList = pTrig;
      }
    }
  }

  return ((pList || bOta) ? pList : pTab->pTrigger);
}

/*
** This is called by the parser when it sees a CREATE TRIGGER statement
** up to the point of the BEGIN before the trigger actions.  A Trigger
** structure is generated based on the information available and stored
** in pParse->pNewTrigger.  After the trigger actions have been parsed, the







<
<
<




<













|





|







39
40
41
42
43
44
45



46
47
48
49

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
** triggers on pTab in the TEMP schema.  This routine prepends all
** TEMP triggers on pTab to the beginning of the pTab->pTrigger list
** and returns the combined list.
**
** 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.



*/
Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
  Schema * const pTmpSchema = pParse->db->aDb[1].pSchema;
  Trigger *pList = 0;                  /* List of triggers to return */


  if( pParse->disableTriggers ){
    return 0;
  }

  if( pTmpSchema!=pTab->pSchema ){
    HashElem *p;
    assert( sqlite3SchemaMutexHeld(pParse->db, 0, pTmpSchema) );
    for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
      Trigger *pTrig = (Trigger *)sqliteHashData(p);
      if( pTrig->pTabSchema==pTab->pSchema
       && 0==sqlite3StrICmp(pTrig->table, pTab->zName) 
      ){
        pTrig->pNext = (pList ? pList : pTab->pTrigger);
        pList = pTrig;
      }
    }
  }

  return (pList ? pList : pTab->pTrigger);
}

/*
** This is called by the parser when it sees a CREATE TRIGGER statement
** up to the point of the BEGIN before the trigger actions.  A Trigger
** structure is generated based on the information available and stored
** in pParse->pNewTrigger.  After the trigger actions have been parsed, the
Changes to src/vdbeblob.c.
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649

  rc = sqlite3ApiExit(db, rc);
  assert( rc==SQLITE_OK || p->pStmt==0 );
  sqlite3_mutex_leave(db->mutex);
  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 */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

463
464
465
466
467
468
469



















































































































































































470

  rc = sqlite3ApiExit(db, rc);
  assert( rc==SQLITE_OK || p->pStmt==0 );
  sqlite3_mutex_leave(db->mutex);
  return rc;
}




















































































































































































#endif /* #ifndef SQLITE_OMIT_INCRBLOB */
Changes to tool/mkpragmatab.tcl.
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
  IF:   defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)

  NAME: soft_heap_limit

  NAME: threads

  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 {}
set type {}
set if {}
set flags {}







<
<
<
<
<







313
314
315
316
317
318
319





320
321
322
323
324
325
326
  IF:   defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)

  NAME: soft_heap_limit

  NAME: threads

  NAME: pager_ota_mode





  IF:   defined(SQLITE_ENABLE_OTA)
}
fconfigure stdout -translation lf
set name {}
set type {}
set if {}
set flags {}