From: drh Date: Thu, 5 Feb 2015 01:49:31 +0000 (+0000) Subject: Figure out the primary-key type of a table using queries of sqlite_master X-Git-Tag: version-3.8.11~252^2~53 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d4ef7c50bb5b270e30437448e75a153c5ce03b60;p=thirdparty%2Fsqlite.git Figure out the primary-key type of a table using queries of sqlite_master and the table_info and index_list pragmas, obviating the need for SQLITE_TESTCTRL_TBLTYPE. FossilOrigin-Name: 50ecdfc443b51e3569c6add2fba5132f959c61cb --- diff --git a/ext/ota/sqlite3ota.c b/ext/ota/sqlite3ota.c index e6882d855d..959622bcf4 100644 --- a/ext/ota/sqlite3ota.c +++ b/ext/ota/sqlite3ota.c @@ -137,12 +137,14 @@ struct OtaObjIter { /* ** Values for OtaObjIter.eType ** +** 0: Table does not exist (error) ** 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_NOTABLE 0 #define OTA_PK_NONE 1 #define OTA_PK_IPK 2 #define OTA_PK_EXTERNAL 3 @@ -449,6 +451,127 @@ static char *otaStrndup(const char *zStr, int nStr, int *pRc){ return zRet; } +/* Determine the type of a table. +** +** 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. +** +** OTA_PK_NOTABLE: No such table. +** OTA_PK_NONE: Table has an implicit rowid. +** OTA_PK_IPK: Table has an explicit IPK column. +** OTA_PK_EXTERNAL: Table has an external PK index. +** OTA_PK_WITHOUT_ROWID: Table is WITHOUT ROWID. +** OTA_PK_VTAB: Table is a virtual table. +** +** Argument *piPk is also of type (int*), and also points to an output +** parameter. Unless the table has an external primary key index +** (i.e. unless *peType is set to 3), then *piPk is set to zero. Or, +** if the table does have an external primary key index, then *piPk +** is set to the root page number of the primary key index before +** returning. +** +** ALGORITHM: +** +** if( no entry exists in sqlite_master ){ +** return OTA_PK_NOTABLE +** }else if( sql for the entry starts with "CREATE VIRTUAL" ){ +** return OTA_PK_VTAB +** }else if( "PRAGMA index_list()" for the table contains a "pk" index ){ +** if( the index that is the pk exists in sqlite_master ){ +** *piPK = rootpage of that index. +** return OTA_PK_EXTERNAL +** }else{ +** return OTA_PK_WITHOUT_ROWID +** } +** }else if( "PRAGMA table_info()" lists one or more "pk" columns ){ +** return OTA_PK_IPK +** }else{ +** return OTA_PK_NONE +** } +*/ +static int otaTableType( + sqlite3 *db, + const char *zTab, + int *peType, + int *piPk +){ + sqlite3_stmt *pStmt = 0; + int rc = SQLITE_OK; + int rc2; + char *zSql = 0; + + *peType = OTA_PK_NOTABLE; + *piPk = 0; + zSql = sqlite3_mprintf( + "SELECT (sql LIKE 'create virtual%%')" + " FROM main.sqlite_master" + " WHERE name=%Q", zTab); + if( zSql==0 ) return SQLITE_NOMEM; + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + zSql = 0; + if( pStmt==0 ) goto otaTableType_end; + if( sqlite3_step(pStmt)!=SQLITE_ROW ){ + goto otaTableType_end; /* no such table */ + } + if( sqlite3_column_int(pStmt,0) ){ + *peType = OTA_PK_VTAB; /* virtual table */ + goto otaTableType_end; + } + rc = sqlite3_finalize(pStmt); + if( rc ) return rc; + zSql = sqlite3_mprintf("PRAGMA index_list=%Q",zTab); + if( zSql==0 ) return SQLITE_NOMEM; + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + zSql = 0; + if( pStmt==0 ) goto otaTableType_end; + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + const unsigned char *zOrig = sqlite3_column_text(pStmt,3); + if( zOrig && zOrig[0]=='p' ){ + zSql = sqlite3_mprintf("SELECT rootpage FROM main.sqlite_master" + " WHERE name=%Q", sqlite3_column_text(pStmt,1)); + if( zSql==0 ){ rc = SQLITE_NOMEM; goto otaTableType_end; } + break; + } + } + rc = sqlite3_finalize(pStmt); + pStmt = 0; + if( rc ) return rc; + if( zSql ){ + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + zSql = 0; + if( pStmt==0 ) goto otaTableType_end; + if( sqlite3_step(pStmt)==SQLITE_ROW ){ + *piPk = sqlite3_column_int(pStmt, 0); + *peType = OTA_PK_EXTERNAL; /* external PK index */ + }else{ + *peType = OTA_PK_WITHOUT_ROWID; /* WITHOUT ROWID table */ + } + }else{ + zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab); + if( zSql==0 ) return SQLITE_NOMEM; + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + zSql = 0; + if( pStmt==0 ) goto otaTableType_end; + *peType = OTA_PK_NONE; /* (default) implicit ROWID */ + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + if( sqlite3_column_int(pStmt,5)>0 ){ + *peType = OTA_PK_IPK; /* explicit IPK column */ + break; + } + } + } + +otaTableType_end: + sqlite3_free(zSql); + rc2 = sqlite3_finalize(pStmt); + return rc ? rc : rc2; +} + /* ** If they are not already populated, populate the pIter->azTblCol[], @@ -470,10 +593,9 @@ static int otaObjIterCacheTableInfo(sqlite3ota *p, OtaObjIter *pIter){ /* 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, - &pIter->iPkTnum - ); + p->rc = otaTableType(p->db, pIter->zTbl, &pIter->eType, &pIter->iPkTnum); + if( p->rc ) return p->rc; + 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 @@ -2105,7 +2227,4 @@ int SqliteOta_Init(Tcl_Interp *interp){ #include int SqliteOta_Init(Tcl_Interp *interp){ return TCL_OK; } # endif -#endif - - - +#endif diff --git a/manifest b/manifest index 6512a12554..44587374cc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sall\schanges\sfrom\sindex_xinfo,\sincluding\sthe\smove\sof\sthe\spragma\stable\ninto\sthe\sseparate\spragma.h\sfile. -D 2015-02-04T23:51:59.867 +C Figure\sout\sthe\sprimary-key\stype\sof\sa\stable\susing\squeries\sof\ssqlite_master\nand\sthe\stable_info\sand\sindex_list\spragmas,\sobviating\sthe\sneed\sfor\nSQLITE_TESTCTRL_TBLTYPE. +D 2015-02-05T01:49:31.187 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -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 41df903106a0107aa70068090b263c93a502da72 +F ext/ota/sqlite3ota.c 0721c7dae5d16624d708ec13ad372c4738f2a23b F ext/ota/sqlite3ota.h ce378c0c503f625611713133f9c79704ea4ee7a4 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 F ext/rtree/rtree.c 14e6239434d4e3f65d3e90320713f26aa24e167f @@ -210,7 +210,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770 F src/loadext.c 86bd4e2fccd520b748cba52492ab60c4a770f660 -F src/main.c 893ca8955539f5dcff8c798b508e94a6d08b6d99 +F src/main.c c4cb192ebf0bcc975648ae05ac40bc1f40018c52 F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987 @@ -247,7 +247,7 @@ F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 1f2087523007c42900ffcbdeaef06a23ad9329fc F src/shell.c 22b4406b0b59efd14b3b351a5809dda517df6d30 -F src/sqlite.h.in 8913937ba11415bf369818431700adf3a921fb18 +F src/sqlite.h.in 4807b024e8d257af774cde0cf178f721ff2406ec F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d F src/sqliteInt.h 57f8f45028598cc2877fc08ac03b402242242c68 @@ -1255,7 +1255,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 c4845a3b591723ff60b7b1da198f44908c12bdfc 3af19f84446ba5fc1ed754d0d73f6a6d7fb2f365 -R f8693fbefe5770ef46252d8013588714 +P 21e95d28a51e56b45a9d4166475972535e53f954 +R 20b83842609fc0bd353b0fba0ba7b9e9 U drh -Z 86d4960217df24559dfd1328c13955b1 +Z ce11446a64cadc5d0eb91c8707e9ad41 diff --git a/manifest.uuid b/manifest.uuid index f5ba861c45..6416dfb803 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -21e95d28a51e56b45a9d4166475972535e53f954 \ No newline at end of file +50ecdfc443b51e3569c6add2fba5132f959c61cb \ No newline at end of file diff --git a/src/main.c b/src/main.c index 0ff49f289b..7bca1e5777 100644 --- a/src/main.c +++ b/src/main.c @@ -3654,59 +3654,6 @@ int sqlite3_test_control(int op, ...){ sqlite3_mutex_leave(db->mutex); break; } - - /* sqlite3_test_control(TESTCTRL_TBLTYPE, db, dbName, zTbl, peType, piPk) - ** - ** 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. - ** - ** Argument *piPk is also of type (int*), and also points to an output - ** parameter. Unless the table has an external primary key index - ** (i.e. unless *peType is set to 3), then *piPk is set to zero. Or, - ** if the table does have an external primary key index, then *piPk - ** is set to the root page number of the primary key index before - ** returning. - */ - 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*); - int *piPk = va_arg(ap, int*); - Table *pTab; - *piPk = 0; - 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); - if( pPk ){ - *peType = 3; - *piPk = pPk->tnum; - }else{ - *peType = 1; - } - } - sqlite3BtreeLeaveAll(db); - sqlite3_mutex_leave(db->mutex); - break; - } } va_end(ap); #endif /* SQLITE_OMIT_BUILTIN_TEST */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 1cba5b1772..cdf5a8c179 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6266,8 +6266,7 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 #define SQLITE_TESTCTRL_IMPOSTER 25 -#define SQLITE_TESTCTRL_TBLTYPE 26 -#define SQLITE_TESTCTRL_LAST 26 +#define SQLITE_TESTCTRL_LAST 25 /* ** CAPI3REF: SQLite Runtime Status