From: dan Date: Tue, 3 Feb 2015 18:43:42 +0000 (+0000) Subject: Fix some problems surrounding WITHOUT ROWID tables with DESC primary key indexes X-Git-Tag: version-3.8.11~252^2~58 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e2863b607463c1270a3dcd3a77340af37492a8b2;p=thirdparty%2Fsqlite.git Fix some problems surrounding WITHOUT ROWID tables with DESC primary key indexes . FossilOrigin-Name: a21fefb79a161e6bb057ae4f6ba554f659706ac1 --- diff --git a/ext/ota/ota1.test b/ext/ota/ota1.test index 0b2da1a60e..afb5fd5865 100644 --- a/ext/ota/ota1.test +++ b/ext/ota/ota1.test @@ -148,6 +148,39 @@ foreach {tn2 cmd} {1 run_ota 2 step_ota 3 step_ota_uri} { CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c)); CREATE INDEX i1 ON t1(b); } + + 10 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX i1 ON t1(b DESC); + } + + 11 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX i1 ON t1(b DESC, a ASC, c DESC); + } + + 12 { + CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c) WITHOUT ROWID; + } + + 13 { + CREATE TABLE t1(a INT, b, c, PRIMARY KEY(a DESC)) WITHOUT ROWID; + } + + 14 { + CREATE TABLE t1(a, b, c, PRIMARY KEY(a DESC, c)) WITHOUT ROWID; + CREATE INDEX i1 ON t1(b); + } + + 15 { + CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c DESC)) WITHOUT ROWID; + CREATE INDEX i1 ON t1(b); + } + + 16 { + CREATE TABLE t1(a, b, c, PRIMARY KEY(c DESC, a)) WITHOUT ROWID; + CREATE INDEX i1 ON t1(b DESC, c, a); + } } { reset_db execsql $schema @@ -157,15 +190,23 @@ foreach {tn2 cmd} {1 run_ota 2 step_ota 3 step_ota_uri} { $cmd test.db ota.db } {SQLITE_DONE} - do_execsql_test 1.$tn2.$tn.2 { - SELECT * FROM t1 ORDER BY a ASC; - } { + do_execsql_test 1.$tn2.$tn.2 { SELECT * FROM t1 ORDER BY a ASC } { 1 2 3 2 two three 3 {} 8.2 } + do_execsql_test 1.$tn2.$tn.3 { SELECT * FROM t1 ORDER BY b ASC } { + 3 {} 8.2 + 1 2 3 + 2 two three + } + do_execsql_test 1.$tn2.$tn.4 { SELECT * FROM t1 ORDER BY c ASC } { + 1 2 3 + 3 {} 8.2 + 2 two three + } - do_execsql_test 1.$tn2.$tn.3 { PRAGMA integrity_check } ok + do_execsql_test 1.$tn2.$tn.5 { PRAGMA integrity_check } ok } } @@ -277,6 +318,19 @@ foreach {tn2 cmd} {1 run_ota 2 step_ota} { CREATE INDEX i2 ON t1(c, b); CREATE INDEX i3 ON t1(c, b, c); } + + 6 { + CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c); + CREATE INDEX i1 ON t1(b DESC); + CREATE INDEX i2 ON t1(c, b); + CREATE INDEX i3 ON t1(c DESC, b, c); + } + 7 { + CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c) WITHOUT ROWID; + CREATE INDEX i1 ON t1(b); + CREATE INDEX i2 ON t1(c, b); + CREATE INDEX i3 ON t1(c, b, c); + } } { reset_db execsql $schema diff --git a/ext/ota/sqlite3ota.c b/ext/ota/sqlite3ota.c index ae45db032b..c7f3afec12 100644 --- a/ext/ota/sqlite3ota.c +++ b/ext/ota/sqlite3ota.c @@ -645,8 +645,9 @@ static char *otaObjIterGetIndexCols( } 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); + int bDesc = sqlite3_column_int(pXInfo, 3); + const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); const char *zCol; const char *zType; @@ -669,7 +670,8 @@ static char *otaObjIterGetIndexCols( 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); + const char *zOrder = (bDesc ? " DESC" : ""); + zImpPK = sqlite3_mprintf("%z%sc%d%s", zImpPK, zCom, nBind, zOrder); } zImpCols = sqlite3_mprintf( "%z%sc%d %s COLLATE %Q", zImpCols, zCom, nBind, zType, zCollate @@ -839,6 +841,46 @@ static char *otaObjIterGetBindlist(sqlite3ota *p, int nBind){ return zRet; } +/* +** The iterator currently points to a table (not index) of type +** OTA_PK_WITHOUT_ROWID. This function creates the PRIMARY KEY +** declaration for the corresponding imposter table. For example, +** if the iterator points to a table created as: +** +** CREATE TABLE t1(a, b, c, PRIMARY KEY(b, a DESC)) WITHOUT ROWID +** +** this function returns: +** +** PRIMARY KEY("b", "a" DESC) +*/ +static char *otaWithoutRowidPK(sqlite3ota *p, OtaObjIter *pIter){ + char *z = 0; + assert( pIter->zIdx==0 ); + if( p->rc==SQLITE_OK ){ + const char *zSep = "PRIMARY KEY("; + sqlite3_stmt *pXInfo = 0; /* PRAGMA index_xinfo = (pIter->zTbl) */ + int rc; /* sqlite3_finalize() return code */ + + p->rc = prepareFreeAndCollectError(p->db, &pXInfo, &p->zErrmsg, + sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zTbl) + ); + while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ + if( sqlite3_column_int(pXInfo, 5) ){ + /* int iCid = sqlite3_column_int(pXInfo, 0); */ + const char *zCol = (const char*)sqlite3_column_text(pXInfo, 2); + const char *zDesc = sqlite3_column_int(pXInfo, 3) ? " DESC" : ""; + z = otaMPrintfAndCollectError(p, "%z%s\"%w\"%s", z, zSep, zCol, zDesc); + zSep = ", "; + } + } + z = otaMPrintfAndCollectError(p, "%z)", z); + + rc = sqlite3_finalize(pXInfo); + if( p->rc==SQLITE_OK ) p->rc = rc; + } + return z; +} + /* ** If an error has already occurred when this function is called, it ** immediately returns zero (without doing any work). Or, if an error @@ -876,30 +918,31 @@ static void otaCreateImposterTable(sqlite3ota *p, OtaObjIter *pIter){ sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1); for(iCol=0; p->rc==SQLITE_OK && iColnTblCol; iCol++){ + const char *zPk = ""; 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 + + if( pIter->eType==OTA_PK_IPK && pIter->abTblPk[iCol] ){ + /* If the target table column is an "INTEGER PRIMARY KEY", add + ** "PRIMARY KEY" to the imposter table column declaration. */ + zPk = "PRIMARY KEY "; + } + zSql = otaMPrintfAndCollectError(p, "%z%s\"%w\" %s %sCOLLATE %s", + zSql, zComma, zCol, pIter->azTblType[iDataCol], zPk, 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; iColnTblCol; iCol++){ - if( pIter->abTblPk[iCol] ){ - zSql = otaMPrintfAndCollectError(p, "%z%s\"%w\"", - zSql, zComma, pIter->azTblCol[iCol] - ); - zComma = ", "; - } + if( pIter->eType==OTA_PK_WITHOUT_ROWID ){ + char *zPk = otaWithoutRowidPK(p, pIter); + if( zPk ){ + zSql = otaMPrintfAndCollectError(p, "%z, %z", zSql, zPk); } - zSql = otaMPrintfAndCollectError(p, "%z)", zSql); } zSql = otaMPrintfAndCollectError(p, "CREATE TABLE ota_imposter(%z)%s", diff --git a/manifest b/manifest index 0a49c2b2a1..39ded5aeaa 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\s"PRAGMA\sota_mode". -D 2015-02-03T15:56:08.271 +C Fix\ssome\sproblems\ssurrounding\sWITHOUT\sROWID\stables\swith\sDESC\sprimary\skey\sindexes\n. +D 2015-02-03T18:43:42.428 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5407a688f4d77a05c18a8142be8ae5a2829dd610 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -125,7 +125,7 @@ F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/ota/README.txt 78d4a9f78f567d4bf826cf0f02df6254902562ca F ext/ota/ota.c c11a85af71dccc45976622fe7a51169a481caa91 -F ext/ota/ota1.test d76b9ec77437759e9da0ff4abe9c070bb9f4eae1 +F ext/ota/ota1.test 719854e444dff2ead58ff6b62d8315954bd7762a F ext/ota/ota10.test ab815dff9cef7248c504f06b888627d236f25e9c F ext/ota/ota2.test 2829bc08ffbb71b605392a68fedfd554763356a7 F ext/ota/ota3.test a77efbce7723332eb688d2b28bf18204fc9614d7 @@ -136,7 +136,7 @@ F ext/ota/ota7.test 1fe2c5761705374530e29f70c39693076028221a F ext/ota/ota8.test cd70e63a0c29c45c0906692827deafa34638feda F ext/ota/ota9.test d3eee95dd836824d07a22e5efcdb7bf6e869358b F ext/ota/otafault.test 508ba87c83d632670ac0f94371a465d4bb4d49dd -F ext/ota/sqlite3ota.c 52c91eec41b8fbb5ed12a8f0a2159bc5ec16498f +F ext/ota/sqlite3ota.c de2e605697871de02fd9ea717a57c00bf022a27e F ext/ota/sqlite3ota.h ce378c0c503f625611713133f9c79704ea4ee7a4 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 F ext/rtree/rtree.c 14e6239434d4e3f65d3e90320713f26aa24e167f @@ -238,7 +238,7 @@ F src/parse.y c5d0d964f9ac023e8154cad512e54b0b6058e086 F src/pcache.c d210cf90d04365a74f85d21374dded65af67b0cb F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8 F src/pcache1.c 1e77432b40b7d3288327d9cdf399dcdfd2b6d3bf -F src/pragma.c 26fc55619109828c9b7add4cfa8a961b6f4c456d +F src/pragma.c e39954ff47e287f88bdf9e9adb123da029e83d9f F src/prepare.c 173a5a499138451b2561614ecb87d78f9f4644b9 F src/printf.c 05edc41450d0eb2c05ef7db113bf32742ae65325 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 @@ -1254,7 +1254,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P cdaeab467f6aa3217be161377a9b78a4eec37093 -R 2703aba199c695992db82956950982ca +P 1c111447a07687c30ed4ad5a6c27a169c85b7ea6 +R 544935f49f95af3db3c849fcc1fc392c U dan -Z fae9dc4e5e5c1a2d2a162b422a05ccf9 +Z 5f7217c8a4b7a144888c5aa7b5260598 diff --git a/manifest.uuid b/manifest.uuid index 0e07d68cdf..66e6bbaaef 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1c111447a07687c30ed4ad5a6c27a169c85b7ea6 \ No newline at end of file +a21fefb79a161e6bb057ae4f6ba554f659706ac1 \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index 61c721f4d2..fc39a5476c 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1581,6 +1581,10 @@ void sqlite3Pragma( Index *pIdx; Table *pTab; pIdx = sqlite3FindIndex(db, zRight, zDb); + if( pIdx==0 ){ + pTab = sqlite3FindTable(db, zRight, zDb); + if( pTab && !HasRowid(pTab) ) pIdx = sqlite3PrimaryKeyIndex(pTab); + } if( pIdx ){ int i; int mx = pPragma->iArg ? pIdx->nColumn : pIdx->nKeyCol;