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
This commit is contained in:
parent
fe9752d934
commit
d4ef7c50bb
@ -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 <tcl.h>
|
||||
int SqliteOta_Init(Tcl_Interp *interp){ return TCL_OK; }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
16
manifest
16
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
|
||||
|
@ -1 +1 @@
|
||||
21e95d28a51e56b45a9d4166475972535e53f954
|
||||
50ecdfc443b51e3569c6add2fba5132f959c61cb
|
53
src/main.c
53
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 */
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user