1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Code to automatically create eponymous virtual tables for read-only pragmas.

Compiles, but does not yet work.

FossilOrigin-Name: 988a61e8b03f302c69d11898d1ea95f002cba1a5
This commit is contained in:
drh
2016-12-15 20:59:03 +00:00
parent c232aca184
commit 2fcc1590c4
8 changed files with 391 additions and 58 deletions

View File

@@ -1,5 +1,5 @@
C Do\smore\spragma\sprocessing\sfrom\stables\srather\sthan\sin-line\scode. C Code\sto\sautomatically\screate\seponymous\svirtual\stables\sfor\sread-only\spragmas.\nCompiles,\sbut\sdoes\snot\syet\swork.
D 2016-12-15T16:01:17.867 D 2016-12-15T20:59:03.895
F Makefile.in c194b58fe00c370a48ac6ae6945e92a7781db1c8 F Makefile.in c194b58fe00c370a48ac6ae6945e92a7781db1c8
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da
@@ -334,7 +334,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
F src/btree.c b2055dff0b94e03eaad48a760984a2d8e39244e6 F src/btree.c b2055dff0b94e03eaad48a760984a2d8e39244e6
F src/btree.h 2349a588abcd7e0c04f984e15c5c777b61637583 F src/btree.h 2349a588abcd7e0c04f984e15c5c777b61637583
F src/btreeInt.h 10c4b77c2fb399580babbcc7cf652ac10dba796e F src/btreeInt.h 10c4b77c2fb399580babbcc7cf652ac10dba796e
F src/build.c e2b32766847eb16d4314c99067571ae08b888dfe F src/build.c 43c9c2bde195267364e92833b36e78f6c5afc66a
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 9f2296a4e5d26ebf0e0d95a0af4628f1ea694e7a F src/ctime.c 9f2296a4e5d26ebf0e0d95a0af4628f1ea694e7a
@@ -381,8 +381,8 @@ F src/parse.y 29153738a7322054359320eb00b5a4cd44389f20
F src/pcache.c 51070ec9b8251bbf9c6ea3d35fd96a458752929e F src/pcache.c 51070ec9b8251bbf9c6ea3d35fd96a458752929e
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490 F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953 F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953
F src/pragma.c 78f85cf6c668b084702bb305bd4980b4813afa70 F src/pragma.c b2421f23af876cb7a2f9aca09e803e207a4750f1
F src/pragma.h 7dff1007ade3aabf8b2e467107b4506940c0ad86 F src/pragma.h f9b221b2c8949ea941dbee49934299e4ed5af41c
F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
F src/printf.c f94da4935d1dd25420ac50c6745db1deb35e07c1 F src/printf.c f94da4935d1dd25420ac50c6745db1deb35e07c1
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
@@ -393,7 +393,7 @@ F src/shell.c f1c7fde7a83421e6ed620df41d200674a2327e65
F src/sqlite.h.in e8e2d108d82647f0a812fdb74accf91c1ec08ddc F src/sqlite.h.in e8e2d108d82647f0a812fdb74accf91c1ec08ddc
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
F src/sqliteInt.h 657a892d885253768c82f1e04e8053468b13cb6a F src/sqliteInt.h adbe80409c2926d91e5485789e5bf69313cd54b0
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247 F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1 F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
@@ -464,7 +464,7 @@ F src/vdbeblob.c f4f98ea672b242f807c08c92c7faaa79e5091b65
F src/vdbemem.c d3fd85b7b7ef3eb75de29c6d7e1d10d3ca78b4fd F src/vdbemem.c d3fd85b7b7ef3eb75de29c6d7e1d10d3ca78b4fd
F src/vdbesort.c bb34eed4fb52e11ac037dccea4ee3190594c7f9e F src/vdbesort.c bb34eed4fb52e11ac037dccea4ee3190594c7f9e
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834 F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
F src/vtab.c 2d5db3fd68c41c5a7476e43e79eb54181fa01713 F src/vtab.c 24f3412e26511701cda951a32b7b33b693cdf450
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344 F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71 F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
@@ -1474,7 +1474,7 @@ F tool/mkmsvcmin.tcl 2f12f7fa8858bbe61cf81820a2da96c79ed1ca8d
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl a01d2c1d8a6205b03fc635adf3735b4c523befd3 F tool/mkopcodeh.tcl a01d2c1d8a6205b03fc635adf3735b4c523befd3
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl 999d7da2b77e83f24de01c3c8f90dc66411ce6d2 F tool/mkpragmatab.tcl a30ee93515135466fc49ae881f75da07ebcafd19
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
F tool/mksqlite3c.tcl 06b2e6a0f21cc0a5d70fbbd136b3e0a96470645e F tool/mksqlite3c.tcl 06b2e6a0f21cc0a5d70fbbd136b3e0a96470645e
@@ -1536,10 +1536,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 9cae4c2e300e20304ced0dc8c1415c4922185928 P a88ca3524b97f296dffc68335466b3767a681747
R d8e6c9c98262f0aea48f528b484866a4 R 23c19e6ab9e9f56bda2263bb45958620
T *branch * table-driven-pragma T *branch * pragma-as-vtab
T *sym-table-driven-pragma * T *sym-pragma-as-vtab *
T -sym-trunk * T -sym-table-driven-pragma *
U drh U drh
Z 7260d2e6fdce7485555b88e6d856ce9f Z 91a2192a11c3bfa409136450c9378cb1

View File

@@ -1 +1 @@
a88ca3524b97f296dffc68335466b3767a681747 988a61e8b03f302c69d11898d1ea95f002cba1a5

View File

@@ -352,6 +352,9 @@ Table *sqlite3LocateTable(
** CREATE, then check to see if it is the name of an virtual table that ** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */ ** can be an eponymous virtual table. */
Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName); Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName);
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlite3PragmaVtabRegister(pParse->db, zName);
}
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
return pMod->pEpoTab; return pMod->pEpoTab;
} }

View File

@@ -167,7 +167,7 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){
*/ */
static void setPragmaResultColumnNames( static void setPragmaResultColumnNames(
Vdbe *v, /* The query under construction */ Vdbe *v, /* The query under construction */
const struct sPragmaNames *pPragma /* The pragma */ const PragmaName *pPragma /* The pragma */
){ ){
u8 n = pPragma->nPragCName; u8 n = pPragma->nPragCName;
sqlite3VdbeSetNumCols(v, n==0 ? 1 : n); sqlite3VdbeSetNumCols(v, n==0 ? 1 : n);
@@ -275,6 +275,26 @@ const char *sqlite3JournalModename(int eMode){
return azModeName[eMode]; return azModeName[eMode];
} }
/*
** Locate a pragma in the aPragmaName[] array.
*/
static const PragmaName *pragmaLocate(const char *zName){
int upr, lwr, mid, rc;
lwr = 0;
upr = ArraySize(aPragmaName)-1;
while( lwr<=upr ){
mid = (lwr+upr)/2;
rc = sqlite3_stricmp(zName, aPragmaName[mid].zName);
if( rc==0 ) break;
if( rc<0 ){
upr = mid - 1;
}else{
lwr = mid + 1;
}
}
return lwr>upr ? 0 : &aPragmaName[mid];
}
/* /*
** Process a pragma statement. ** Process a pragma statement.
** **
@@ -303,12 +323,11 @@ void sqlite3Pragma(
Token *pId; /* Pointer to <id> token */ Token *pId; /* Pointer to <id> token */
char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */ char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */
int iDb; /* Database index for <database> */ int iDb; /* Database index for <database> */
int lwr, upr, mid = 0; /* Binary search bounds */
int rc; /* return value form SQLITE_FCNTL_PRAGMA */ int rc; /* return value form SQLITE_FCNTL_PRAGMA */
sqlite3 *db = pParse->db; /* The database connection */ sqlite3 *db = pParse->db; /* The database connection */
Db *pDb; /* The specific database being pragmaed */ Db *pDb; /* The specific database being pragmaed */
Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */ Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */
const struct sPragmaNames *pPragma; const PragmaName *pPragma; /* The pragma */
if( v==0 ) return; if( v==0 ) return;
sqlite3VdbeRunOnlyOnce(v); sqlite3VdbeRunOnlyOnce(v);
@@ -380,20 +399,8 @@ void sqlite3Pragma(
} }
/* Locate the pragma in the lookup table */ /* Locate the pragma in the lookup table */
lwr = 0; pPragma = pragmaLocate(zLeft);
upr = ArraySize(aPragmaNames)-1; if( pPragma==0 ) goto pragma_out;
while( lwr<=upr ){
mid = (lwr+upr)/2;
rc = sqlite3_stricmp(zLeft, aPragmaNames[mid].zName);
if( rc==0 ) break;
if( rc<0 ){
upr = mid - 1;
}else{
lwr = mid + 1;
}
}
if( lwr>upr ) goto pragma_out;
pPragma = &aPragmaNames[mid];
/* Make sure the database schema is loaded if the pragma requires that */ /* Make sure the database schema is loaded if the pragma requires that */
if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){ if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){
@@ -1950,5 +1957,302 @@ pragma_out:
sqlite3DbFree(db, zLeft); sqlite3DbFree(db, zLeft);
sqlite3DbFree(db, zRight); sqlite3DbFree(db, zRight);
} }
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*****************************************************************************
** Implementation of an eponymous virtual table that runs a pragma.
**
*/
typedef struct PragmaVtab PragmaVtab;
typedef struct PragmaVtabCursor PragmaVtabCursor;
struct PragmaVtab {
sqlite3_vtab base; /* Base class. Must be first */
sqlite3 *db; /* The database connection to which it belongs */
const PragmaName *pName; /* Name of the pragma */
u8 nHidden; /* Number of hidden columns */
u8 iHidden; /* Index of the first hidden column */
};
struct PragmaVtabCursor {
sqlite3_vtab_cursor base; /* Base class. Must be first */
sqlite3_stmt *pPragma; /* The pragma statement to run */
sqlite_int64 iRowid; /* Current rowid */
char *azArg[2]; /* Value of the argument and schema */
};
/*
** Pragma virtual table module xConnect method.
*/
static int pragmaVtabConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
const PragmaName *pPragma = (const PragmaName*)pAux;
PragmaVtab *pTab = 0;
int rc;
int i, j;
char cSep = '(';
StrAccum acc;
char zBuf[200];
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
sqlite3StrAccumAppendAll(&acc, "CREATE TABLE x");
for(i=0, j=pPragma->iPragCName; i<pPragma->nPragCName; i++, j++){
sqlite3StrAccumAppend(&acc, &cSep, 1);
sqlite3StrAccumAppendAll(&acc, pragCName[j]);
cSep = ',';
}
j = 0;
if( pPragma->mPragFlg & PragFlg_Result1 ){
sqlite3StrAccumAppendAll(&acc, ",arg HIDDEN");
j++;
}
if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){
sqlite3StrAccumAppendAll(&acc, ",schema HIDDEN");
j++;
}
sqlite3StrAccumAppend(&acc, ")", 1);
sqlite3StrAccumFinish(&acc);
assert( strlen(zBuf) < sizeof(zBuf)-1 );
rc = sqlite3_declare_vtab(db, zBuf);
if( rc==SQLITE_OK ){
pTab = (PragmaVtab*)sqlite3_malloc(sizeof(PragmaVtab));
if( pTab==0 ){
rc = SQLITE_NOMEM;
}else{
memset(pTab, 0, sizeof(PragmaVtab));
pTab->pName = pPragma;
pTab->db = db;
pTab->iHidden = i;
pTab->nHidden = j;
}
}else{
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}
*ppVtab = (sqlite3_vtab*)pTab;
return rc;
}
/*
** Pragma virtual table module xDisconnect method.
*/
static int pragmaVtabDisconnect(sqlite3_vtab *pVtab){
PragmaVtab *pTab = (PragmaVtab*)pVtab;
sqlite3_free(pTab);
return SQLITE_OK;
}
/* Figure out the best index to use to search a pragma virtual table.
**
** There are not really any index choices. But we want to encourage the
** query planner to give == constraints on as many hidden parameters as
** possible, and especially on the first hidden parameter. So return a
** high cost if hidden parameters are unconstrained.
*/
static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
PragmaVtab *pTab = (PragmaVtab*)tab;
const struct sqlite3_index_constraint *pConstraint;
int i, j;
int seen[2];
if( pTab->nHidden==0 ){ return SQLITE_OK; }
pConstraint = pIdxInfo->aConstraint;
seen[0] = 0;
seen[1] = 0;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
if( pConstraint->usable==0 ) continue;
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pConstraint->iColumn < pTab->iHidden ) continue;
j = pConstraint->iColumn - pTab->iHidden;
assert( j < 2 );
if( seen[j] ) continue;
seen[j] = i;
}
if( seen[0]==0 ){
pIdxInfo->estimatedCost = (double)2147483647;
pIdxInfo->estimatedRows = 2147483647;
return SQLITE_OK;
}
j = seen[0];
pIdxInfo->aConstraintUsage[j].argvIndex = 1;
pIdxInfo->aConstraintUsage[j].omit = 1;
if( seen[1]==0 ) return SQLITE_OK;
pIdxInfo->estimatedCost = (double)20;
pIdxInfo->estimatedRows = 20;
j = seen[1];
pIdxInfo->aConstraintUsage[j].argvIndex = 2;
pIdxInfo->aConstraintUsage[j].omit = 1;
return SQLITE_OK;
}
/* Create a new cursor for the pragma virtual table */
static int pragmaVtabOpen(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){
PragmaVtabCursor *pCsr;
pCsr = (PragmaVtabCursor*)sqlite3_malloc(sizeof(*pCsr));
if( pCsr==0 ) return SQLITE_NOMEM;
memset(pCsr, 0, sizeof(PragmaVtabCursor));
pCsr->base.pVtab = pVtab;
*ppCursor = &pCsr->base;
return SQLITE_OK;
}
/* Clear all content from pragma virtual table cursor. */
static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){
int i;
sqlite3_finalize(pCsr->pPragma);
pCsr->pPragma = 0;
for(i=0; i<ArraySize(pCsr->azArg); i++){
sqlite3_free(pCsr->azArg[i]);
pCsr->azArg[i] = 0;
}
}
/* Close a pragma virtual table cursor */
static int pragmaVtabClose(sqlite3_vtab_cursor *cur){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)cur;
pragmaVtabCursorClear(pCsr);
return SQLITE_OK;
}
/* Advance the pragma virtual table cursor to the next row */
static int pragmaVtabNext(sqlite3_vtab_cursor *pVtabCursor){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
int rc = SQLITE_OK;
/* Increment the xRowid value */
pCsr->iRowid++;
if( pCsr->pPragma ){
if( SQLITE_ROW!=sqlite3_step(pCsr->pPragma) ){
rc = sqlite3_finalize(pCsr->pPragma);
pCsr->pPragma = 0;
pragmaVtabCursorClear(pCsr);
}
}
return rc;
}
/*
** Pragma virtual table module xFilter method.
*/
static int pragmaVtabFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab);
int rc;
int i;
StrAccum acc;
char *zSql;
pragmaVtabCursorClear(pCsr);
for(i=0; i<argc; i++){
assert( i<ArraySize(pCsr->azArg) );
pCsr->azArg[i] = sqlite3_mprintf("%s", sqlite3_value_text(argv[i]));
if( pCsr->azArg[i]==0 ){
return SQLITE_NOMEM;
}
}
sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_MAX_SQL_LENGTH]);
sqlite3StrAccumAppendAll(&acc, "PRAGMA ");
if( pCsr->azArg[1] ){
sqlite3XPrintf(&acc, "%Q.", pCsr->azArg[1]);
}
sqlite3StrAccumAppendAll(&acc, pTab->pName->zName);
if( pCsr->azArg[0] ){
sqlite3XPrintf(&acc, "=%Q", pCsr->azArg[0]);
}
zSql = sqlite3StrAccumFinish(&acc);
if( zSql==0 ) return SQLITE_NOMEM;
rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pPragma, 0);
sqlite3_free(zSql);
if( rc!=SQLITE_OK ){
pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
return rc;
}
return pragmaVtabNext(pVtabCursor);
}
/*
** Pragma virtual table module xEof method.
*/
static int pragmaVtabEof(sqlite3_vtab_cursor *pVtabCursor){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
return (pCsr->pPragma==0);
}
/* The xColumn method simply returns the corresponding column from
** the PRAGMA.
*/
static int pragmaVtabColumn(
sqlite3_vtab_cursor *pVtabCursor,
sqlite3_context *ctx,
int i
){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab);
if( i<pTab->iHidden ){
sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pPragma, i));
}else{
sqlite3_result_text(ctx, pCsr->azArg[i-pTab->iHidden],-1,SQLITE_TRANSIENT);
}
return SQLITE_OK;
}
/*
** Pragma virtual table module xRowid method.
*/
static int pragmaVtabRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *p){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
*p = pCsr->iRowid;
return SQLITE_OK;
}
/* The pragma virtual table object */
static const sqlite3_module pragmaVtabModule = {
0, /* iVersion */
0, /* xCreate - create a table */
pragmaVtabConnect, /* xConnect - connect to an existing table */
pragmaVtabBestIndex, /* xBestIndex - Determine search strategy */
pragmaVtabDisconnect, /* xDisconnect - Disconnect from a table */
0, /* xDestroy - Drop a table */
pragmaVtabOpen, /* xOpen - open a cursor */
pragmaVtabClose, /* xClose - close a cursor */
pragmaVtabFilter, /* xFilter - configure scan constraints */
pragmaVtabNext, /* xNext - advance a cursor */
pragmaVtabEof, /* xEof */
pragmaVtabColumn, /* xColumn - read data */
pragmaVtabRowid, /* xRowid - read data */
0, /* xUpdate - write data */
0, /* xBegin - begin transaction */
0, /* xSync - sync transaction */
0, /* xCommit - commit transaction */
0, /* xRollback - rollback transaction */
0, /* xFindFunction - function overloading */
0, /* xRename - rename the table */
0, /* xSavepoint */
0, /* xRelease */
0 /* xRollbackTo */
};
/*
** Check to see if zTabName is really the name of a pragma. If it is,
** then register an eponymous virtual table for that pragma and return
** a pointer to the Module object for the new virtual table.
*/
Module *sqlite3PragmaVtabRegister(sqlite3 *db, const char *zName){
const PragmaName *pName;
assert( sqlite3_strnicmp(zName, "pragma_", 7)==0 );
pName = pragmaLocate(zName+7);
if( pName==0 ) return 0;
if( (pName->mPragFlg & (PragFlg_Result0|PragFlg_Result1))==0 ) return 0;
assert( sqlite3HashFind(&db->aModule, zName)==0 );
return sqlite3VtabCreateModule(db, zName, &pragmaVtabModule, 0, 0);
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#endif /* SQLITE_OMIT_PRAGMA */ #endif /* SQLITE_OMIT_PRAGMA */

View File

@@ -114,14 +114,15 @@ static const char *const pragCName[] = {
}; };
/* Definitions of all built-in pragmas */ /* Definitions of all built-in pragmas */
static const struct sPragmaNames { typedef struct PragmaName {
const char *const zName; /* Name of pragma */ const char *const zName; /* Name of pragma */
u8 ePragTyp; /* PragTyp_XXX value */ u8 ePragTyp; /* PragTyp_XXX value */
u8 mPragFlg; /* Zero or more PragFlg_XXX values */ u8 mPragFlg; /* Zero or more PragFlg_XXX values */
u8 iPragCName; /* Start of column names in pragCName[] */ u8 iPragCName; /* Start of column names in pragCName[] */
u8 nPragCName; /* Num of col names. 0 means use pragma name */ u8 nPragCName; /* Num of col names. 0 means use pragma name */
u32 iArg; /* Extra argument */ u32 iArg; /* Extra argument */
} aPragmaNames[] = { } PragmaName;
static const PragmaName aPragmaName[] = {
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
{/* zName: */ "activate_extensions", {/* zName: */ "activate_extensions",
/* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS, /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,

View File

@@ -3563,6 +3563,9 @@ u32 sqlite3ExprListFlags(const ExprList*);
int sqlite3Init(sqlite3*, char**); int sqlite3Init(sqlite3*, char**);
int sqlite3InitCallback(void*, int, char**, char**); int sqlite3InitCallback(void*, int, char**, char**);
void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
#ifndef SQLITE_OMIT_VIRTUALTABLE
Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
#endif
void sqlite3ResetAllSchemasOfConnection(sqlite3*); void sqlite3ResetAllSchemasOfConnection(sqlite3*);
void sqlite3ResetOneSchema(sqlite3*,int); void sqlite3ResetOneSchema(sqlite3*,int);
void sqlite3CollapseDatabaseArray(sqlite3*); void sqlite3CollapseDatabaseArray(sqlite3*);
@@ -4077,6 +4080,13 @@ void sqlite3AutoLoadExtensions(sqlite3*);
int sqlite3VtabSavepoint(sqlite3 *, int, int); int sqlite3VtabSavepoint(sqlite3 *, int, int);
void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*); void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
VTable *sqlite3GetVTable(sqlite3*, Table*); VTable *sqlite3GetVTable(sqlite3*, Table*);
Module *sqlite3VtabCreateModule(
sqlite3*,
const char*,
const sqlite3_module*,
void*,
void(*)(void*)
);
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif #endif
int sqlite3VtabEponymousTableInit(Parse*,Module*); int sqlite3VtabEponymousTableInit(Parse*,Module*);

View File

@@ -29,26 +29,19 @@ struct VtabCtx {
}; };
/* /*
** The actual function that does the work of creating a new module. ** Construct and install a Module object for a virtual table. When this
** This function implements the sqlite3_create_module() and ** routine is called, it is guaranteed that all appropriate locks are held
** sqlite3_create_module_v2() interfaces. ** and the module is not already part of the connection.
*/ */
static int createModule( Module *sqlite3VtabCreateModule(
sqlite3 *db, /* Database in which module is registered */ sqlite3 *db, /* Database in which module is registered */
const char *zName, /* Name assigned to this module */ const char *zName, /* Name assigned to this module */
const sqlite3_module *pModule, /* The definition of the module */ const sqlite3_module *pModule, /* The definition of the module */
void *pAux, /* Context pointer for xCreate/xConnect */ void *pAux, /* Context pointer for xCreate/xConnect */
void (*xDestroy)(void *) /* Module destructor function */ void (*xDestroy)(void *) /* Module destructor function */
){ ){
int rc = SQLITE_OK;
int nName;
sqlite3_mutex_enter(db->mutex);
nName = sqlite3Strlen30(zName);
if( sqlite3HashFind(&db->aModule, zName) ){
rc = SQLITE_MISUSE_BKPT;
}else{
Module *pMod; Module *pMod;
int nName = sqlite3Strlen30(zName);
pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1); pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1);
if( pMod ){ if( pMod ){
Module *pDel; Module *pDel;
@@ -66,10 +59,31 @@ static int createModule(
sqlite3DbFree(db, pDel); sqlite3DbFree(db, pDel);
} }
} }
return pMod;
}
/*
** The actual function that does the work of creating a new module.
** This function implements the sqlite3_create_module() and
** sqlite3_create_module_v2() interfaces.
*/
static int createModule(
sqlite3 *db, /* Database in which module is registered */
const char *zName, /* Name assigned to this module */
const sqlite3_module *pModule, /* The definition of the module */
void *pAux, /* Context pointer for xCreate/xConnect */
void (*xDestroy)(void *) /* Module destructor function */
){
int rc = SQLITE_OK;
sqlite3_mutex_enter(db->mutex);
if( sqlite3HashFind(&db->aModule, zName) ){
rc = SQLITE_MISUSE_BKPT;
}else{
(void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy);
} }
rc = sqlite3ApiExit(db, rc); rc = sqlite3ApiExit(db, rc);
if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux); if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux);
sqlite3_mutex_leave(db->mutex); sqlite3_mutex_leave(db->mutex);
return rc; return rc;
} }

View File

@@ -495,7 +495,7 @@ puts $fd "\175;"
# Generate the lookup table # Generate the lookup table
# #
puts $fd "\n/* Definitions of all built-in pragmas */" puts $fd "\n/* Definitions of all built-in pragmas */"
puts $fd "static const struct sPragmaNames \173" puts $fd "typedef struct PragmaName \173"
puts $fd " const char *const zName; /* Name of pragma */" puts $fd " const char *const zName; /* Name of pragma */"
puts $fd " u8 ePragTyp; /* PragTyp_XXX value */" puts $fd " u8 ePragTyp; /* PragTyp_XXX value */"
puts $fd " u8 mPragFlg; /* Zero or more PragFlg_XXX values */" puts $fd " u8 mPragFlg; /* Zero or more PragFlg_XXX values */"
@@ -503,7 +503,8 @@ puts $fd { u8 iPragCName; /* Start of column names in pragCName[] */}
puts $fd " u8 nPragCName; \ puts $fd " u8 nPragCName; \
/* Num of col names. 0 means use pragma name */" /* Num of col names. 0 means use pragma name */"
puts $fd " u32 iArg; /* Extra argument */" puts $fd " u32 iArg; /* Extra argument */"
puts $fd "\175 aPragmaNames\[\] = \173" puts $fd "\175 PragmaName;"
puts $fd "static const PragmaName aPragmaName\[\] = \173"
set current_if {} set current_if {}
set spacer [format { %26s } {}] set spacer [format { %26s } {}]