** * the table itself,
** * each index of the table (zero or more points to visit), and
** * a special "cleanup table" state.
+**
+** abIndexed:
+** If the table has no indexes on it, abIndexed is set to NULL. Otherwise,
+** it points to an array of flags nTblCol elements in size. The flag is
+** set for each column that is either a part of the PK or a part of an
+** index. Or clear otherwise.
+**
*/
struct OtaObjIter {
sqlite3_stmt *pTblIter; /* Iterate through tables */
int *aiSrcOrder; /* src table col -> target table col */
u8 *abTblPk; /* Array of flags, set on target PK columns */
u8 *abNotNull; /* Array of flags, set on NOT NULL columns */
+ u8 *abIndexed; /* Array of flags, set on indexed & PK cols */
int eType; /* Table type - an OTA_PK_XXX value */
/* Output variables. zTbl==0 implies EOF. */
** error code in the OTA handle passed as the first argument.
*/
static void otaAllocateIterArrays(sqlite3ota *p, OtaObjIter *pIter, int nCol){
- int nByte = (2*sizeof(char*) + sizeof(int) + 2*sizeof(u8)) * nCol;
+ int nByte = (2*sizeof(char*) + sizeof(int) + 3*sizeof(u8)) * nCol;
char **azNew;
azNew = (char**)otaMalloc(p, nByte);
pIter->aiSrcOrder = (int*)&pIter->azTblType[nCol];
pIter->abTblPk = (u8*)&pIter->aiSrcOrder[nCol];
pIter->abNotNull = (u8*)&pIter->abTblPk[nCol];
+ pIter->abIndexed = (u8*)&pIter->abNotNull[nCol];
}
}
}
}
+/*
+** This is a helper function for otaObjIterCacheTableInfo(). It populates
+** the pIter->abIndexed[] array.
+*/
+static void otaObjIterCacheIndexedCols(sqlite3ota *p, OtaObjIter *pIter){
+ sqlite3_stmt *pList = 0;
+ int bIndex = 0;
+
+ if( p->rc==SQLITE_OK ){
+ memcpy(pIter->abIndexed, pIter->abTblPk, sizeof(u8)*pIter->nTblCol);
+ p->rc = prepareFreeAndCollectError(p->dbMain, &pList, &p->zErrmsg,
+ sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl)
+ );
+ }
+
+ while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pList) ){
+ const char *zIdx = (const char*)sqlite3_column_text(pList, 1);
+ sqlite3_stmt *pXInfo = 0;
+ if( zIdx==0 ) break;
+ p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg,
+ sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx)
+ );
+ while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
+ int iCid = sqlite3_column_int(pXInfo, 1);
+ if( iCid>=0 ) pIter->abIndexed[iCid] = 1;
+ }
+ otaFinalize(p, pXInfo);
+ bIndex = 1;
+ }
+
+ otaFinalize(p, pList);
+ if( bIndex==0 ) pIter->abIndexed = 0;
+}
+
/*
** If they are not already populated, populate the pIter->azTblCol[],
}
otaFinalize(p, pStmt);
+ otaObjIterCacheIndexedCols(p, pIter);
+ assert( pIter->eType!=OTA_PK_VTAB || pIter->abIndexed==0 );
}
return p->rc;
/*
** This function is used to create a SELECT list (the list of SQL
** expressions that follows a SELECT keyword) for a SELECT statement
-** used to read from an ota_xxx table while updating the index object
-** currently indicated by the iterator object passed as the second
-** argument. A "PRAGMA index_xinfo = <idxname>" statement is used to
-** obtain the required information.
+** used to read from an data_xxx or ota_tmp_xxx table while updating the
+** index object currently indicated by the iterator object passed as the
+** second argument. A "PRAGMA index_xinfo = <idxname>" statement is used
+** to obtain the required information.
**
** If the index is of the following form:
**
const char *zObj
){
char *zList = 0;
- if( p->rc==SQLITE_OK ){
+ if( p->rc==SQLITE_OK && pIter->abIndexed ){
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);
+ if( pIter->abIndexed[i] ){
+ const char *zCol = pIter->azTblCol[i];
+ zList = sqlite3_mprintf("%z%s%s.\"%w\"", zList, zS, zObj, zCol);
+ }else{
+ zList = sqlite3_mprintf("%z%sNULL", zList, zS);
+ }
zS = ", ";
if( zList==0 ){
p->rc = SQLITE_NOMEM;
);
}
- if( pIter->eType!=OTA_PK_VTAB ){
+ if( pIter->abIndexed ){
const char *zOtaRowid = "";
if( pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_NONE ){
zOtaRowid = ", ota_rowid";
/* Clean up the ota_tmp_xxx table for the previous table. It
** cannot be dropped as there are currently active SQL statements.
** But the contents can be deleted. */
- if( pIter->eType!=OTA_PK_VTAB ){
+ if( pIter->abIndexed ){
const char *zTbl = pIter->zTbl;
otaMPrintfExec(p, p->dbOta, "DELETE FROM 'ota_tmp_%q'", zTbl);
}
-C Fix\sa\sbroken\sassert()\sin\sthe\sota\smodule.
-D 2015-03-23T17:10:51.066
+C When\sthe\sOTA\smodule\supdates\sor\sdeletes\sa\srow,\ssave\sonly\sthose\sfields\sthat\sare\spart\sof\san\sindex\sor\sprimary\skey\sto\sthe\sota\supdate\sdatabase.
+D 2015-03-24T18:03:29.870
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2f643d6968dfc0b82d2e546a0525a39079f9e928
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F ext/ota/otacrash.test a078d34e2edbcedac5f894e3e7d08d452a327007
F ext/ota/otafault.test 8c43586c2b96ca16bbce00b5d7e7d67316126db8
F ext/ota/otafault2.test fa202a98ca221faec318f3e5c5f39485b1256561
-F ext/ota/sqlite3ota.c 1d3b605c27622efdc288a3ac94ab199d1c8b5ea0
+F ext/ota/sqlite3ota.c 9c16cd3bf99d2591a8a0b56b114ebbf839d42399
F ext/ota/sqlite3ota.h f1a9dd98b00fa622c7e2eb68e580ee02e194c4d6
F ext/ota/test_ota.c e34c801c665d64b4b9e00b71f1acf8c652404b2b
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 52e73eeca063bb30092ce600068bf487641399a0
-R a9aebe9b51af54f1535cb011847cd5d2
+P 858de8a5e7925bd96d7b9c0f00bc16358cf3b295
+R 8b55a1f50bfcaf2003b1038217883d03
U dan
-Z 141e2fc0ed2825bfcd2784386daf5cbd
+Z 9f88de65f5585dc798e54fceff613e97