]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Merge the pragma-as-vtab enhancement from trunk.
authordrh <drh@noemail.net>
Fri, 16 Dec 2016 21:15:04 +0000 (21:15 +0000)
committerdrh <drh@noemail.net>
Fri, 16 Dec 2016 21:15:04 +0000 (21:15 +0000)
FossilOrigin-Name: 89250777b253f90f133d41f5387671429a562c07

1  2 
manifest
manifest.uuid
src/build.c
src/pragma.c
src/pragma.h
src/sqliteInt.h
tool/mkpragmatab.tcl

diff --cc manifest
index 3ef6b569f94f7ff91fec177414f924984d772cf7,8fda08169ade0274a583be75569dad88491979e6..66417691ad9ec15732cbecae9aecf0e67d8485d1
+++ b/manifest
@@@ -1,5 -1,5 +1,5 @@@
- C Fix\sa\spotential\smemory\sleak\sfollowing\san\sOOM\serror\sin\sthe\spragma\sprocessing.
- D 2016-12-16T21:02:17.940
 -C Add\sthe\s".lint\sfkey-indexes"\scommand\sto\sthe\scommand-line\sshell.
 -D 2016-12-16T18:43:49.329
++C Merge\sthe\spragma-as-vtab\senhancement\sfrom\strunk.
++D 2016-12-16T21:15:04.542
  F Makefile.in c194b58fe00c370a48ac6ae6945e92a7781db1c8
  F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
  F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da
@@@ -331,10 -331,10 +331,10 @@@ F src/auth.c 930b376a9c56998557367e6f7f
  F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
  F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
  F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
 -F src/btree.c b2055dff0b94e03eaad48a760984a2d8e39244e6
 -F src/btree.h 2349a588abcd7e0c04f984e15c5c777b61637583
 +F src/btree.c 7892be7e019565f6e5d2df6bda94befa7d91c9a0
 +F src/btree.h 14931e081909f9b75009b0b5c5ead6b074204705
  F src/btreeInt.h 10c4b77c2fb399580babbcc7cf652ac10dba796e
- F src/build.c 182877f27be4129ffd385b80f3318251a605152b
 -F src/build.c 52970b6cf3cf3107551a5d6dd668b0b261b0b491
++F src/build.c d814cb158ca2ef75c525e4c3f0d47b5666e53c95
  F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
  F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
  F src/ctime.c 9f2296a4e5d26ebf0e0d95a0af4628f1ea694e7a
@@@ -381,8 -381,8 +381,8 @@@ F src/parse.y 5280d00e80f0fb118437ffc3f
  F src/pcache.c 51070ec9b8251bbf9c6ea3d35fd96a458752929e
  F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
  F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953
- F src/pragma.c 59cfc788ba5a678a45d6277a5cd719f0a32ee1db
- F src/pragma.h 74d46e32bdc7abb2d01710162ff96cfb483699b6
 -F src/pragma.c d5adfe89ad7f3f45d4dbd25b96cbf3f6611aea2a
 -F src/pragma.h f9b221b2c8949ea941dbee49934299e4ed5af41c
++F src/pragma.c 10f1418fb9105a32a9bfb001b536110ffa1344b5
++F src/pragma.h e2636093e33f5cc0feffc7ead45ce1268a5524e9
  F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
  F src/printf.c f94da4935d1dd25420ac50c6745db1deb35e07c1
  F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
@@@ -393,7 -393,7 +393,7 @@@ F src/shell.c 9be556ad9c7cf429d0acc48e3
  F src/sqlite.h.in e8e2d108d82647f0a812fdb74accf91c1ec08ddc
  F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
  F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
- F src/sqliteInt.h d4b1e6a694ed35bc669c9c99e0dea35e76e357f8
 -F src/sqliteInt.h adbe80409c2926d91e5485789e5bf69313cd54b0
++F src/sqliteInt.h 9f4111b5743fdb9d6dea6da81485abc94abf01ac
  F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
  F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
  F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
@@@ -1475,7 -1475,7 +1476,7 @@@ F tool/mkmsvcmin.tcl 2f12f7fa8858bbe61c
  F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
  F tool/mkopcodeh.tcl a01d2c1d8a6205b03fc635adf3735b4c523befd3
  F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
- F tool/mkpragmatab.tcl c5ce5c56a8193196efcd195f09572a073445397f
 -F tool/mkpragmatab.tcl a30ee93515135466fc49ae881f75da07ebcafd19
++F tool/mkpragmatab.tcl c4e9c6b70e54e5720a81eeccfb4d739a566be217
  F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
  F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
  F tool/mksqlite3c.tcl 06b2e6a0f21cc0a5d70fbbd136b3e0a96470645e
@@@ -1537,7 -1537,8 +1538,7 @@@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a9
  F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
  F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
  F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
- P 74a0ca1f152d6d8454787557c6e990efe0e47a50
- R 143fd57a2118c35d1d22527b371c3d9a
 -P d66ec5cfb67c6c8134fb642e0c2f72113fe1b7fd 1268dc77712d85de0b62332c88b22f7489f4e87f
 -R 687c3d19b933c4e396bfa9c657e5c87e
 -T +closed 1268dc77712d85de0b62332c88b22f7489f4e87f
++P 396ab8f87ea85a01f7cb73aa83d6572057ae97fc 94689e3bdac2eabbcf1a51d741c2604ed4bd8a40
++R 432a18e22c55218bc78ee74a118ecff2
  U drh
- Z 45c8092d0c1b95e4209c22fb75d70bc1
 -Z fa4bf48b88eaf725bf36396e1a6dc597
++Z f97d4f7f1678bf38b62a5e878154818e
diff --cc manifest.uuid
index e2757ca94d9edf7fc404c91d4c8f710aa799da75,78caff5224b9a878257152f1ec9c2bbcd42f47c5..4b69579d776b9a84e941a377e5364ba1e7914af0
@@@ -1,1 -1,1 +1,1 @@@
- 396ab8f87ea85a01f7cb73aa83d6572057ae97fc
 -94689e3bdac2eabbcf1a51d741c2604ed4bd8a40
++89250777b253f90f133d41f5387671429a562c07
diff --cc src/build.c
Simple merge
diff --cc src/pragma.c
index ae1fde07a64b3c046569d30ae2dffb22e5820bee,d84e1d7929e96c9ac8865120317a7530496ffb7a..0971989bcee46d905000d68a0a469798b314f682
@@@ -305,9 -327,9 +322,9 @@@ void sqlite3Pragma
    sqlite3 *db = pParse->db;    /* The database connection */
    Db *pDb;                     /* The specific database being pragmaed */
    Vdbe *v = sqlite3GetVdbe(pParse);  /* Prepared statement */
-   const struct sPragmaNames *pPragma;
+   const PragmaName *pPragma;   /* The pragma */
  
 -  if( v==0 ) return;
 +  if( v==0 ) goto pragma_out;
    sqlite3VdbeRunOnlyOnce(v);
    pParse->nMem = 2;
  
      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 ){
-       static const char *azCol[] = {
-          "seqno", "cid", "name", "desc", "coll", "key"
-       };
        int i;
        int mx;
        if( pPragma->iArg ){
    }
    break;
  
-     static const char *azCol[] = { "est" };
 +  /*
 +  **   PRAGMA est_row_cnt(<table-or-index>,<fraction>);
 +  **
 +  ** Seek in <table-or-index> through the first <fraction> of rows and
 +  ** estimate the total number of rows based on the path back up to the
 +  ** root.
 +  */
 +  case PragTyp_EST_COUNT: {
 +    Index *pIdx;
 +    Table *pTab = 0;
 +    Pgno iRoot = 0;
 +    const char *zName = 0;
 +    int regResult;
 +    double r;
-     setAllColumnNames(v, 1, azCol);
 +    if( (pIdx = sqlite3FindIndex(db, zRight, zDb))!=0 ){
 +      iRoot = pIdx->tnum;
 +      zName = pIdx->zName;
 +    }else if( (pTab = sqlite3FindTable(db, zRight, zDb))!=0 ){
 +      zName = pTab->zName;
 +      if( HasRowid(pTab) ){
 +        iRoot = pTab->tnum;
 +      }else{
 +        pIdx = sqlite3PrimaryKeyIndex(pTab);
 +        iRoot = pIdx->tnum;
 +      }
 +    }else{
 +      break;
 +    }
 +    sqlite3TableLock(pParse, iDb, iRoot, 0, zName);
 +    regResult = ++pParse->nMem;
 +    if( pValues->nId>=2 ){
 +      const char *z = pValues->a[1].zName;
 +      sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
 +    }else{
 +      r = 0.5;
 +    }
 +    if( r<0.0 ) r = 0.0;
 +    if( r>1.0 ) r = 1.0;
 +    sqlite3CodeVerifySchema(pParse, iDb);
 +    pParse->nTab++;
 +    sqlite3VdbeAddOp4Int(v, OP_OpenRead, 0, iRoot, iDb, 1);
 +    if( pIdx ) sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
 +    sqlite3VdbeAddOp3(v, OP_EstRowCnt, 0, regResult, (int)(r*1000000000));
 +    sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1);
 +  }
 +  break;
 +
 +  /*
 +  **   PRAGMA btree_sample(<table-or-index>,<fraction>,<limit>);
 +  **
 +  ** Seek in <table-or-index> through the first <fraction> of rows and
 +  ** then begin returning rows, one by one.  A max of <limit> rows will
 +  ** be returned.
 +  */
 +  case PragTyp_BTREE_SAMPLE: {
 +    Index *pIdx;
 +    Table *pTab = 0;
 +    Pgno iRoot = 0;
 +    Pgno iLock = 0;
 +    int nCol = 0;
 +    const char *zName = 0;
 +    int iLimit = 10;
 +    int i;
 +    int regResult;
 +    int regLimit;
 +    int addrTop;
 +    int addrJmp;
 +    int addrSkip;
 +    double r;
 +    if( (pIdx = sqlite3FindIndex(db, zRight, zDb))!=0 ){
 +      iRoot = pIdx->tnum;
 +      iLock = pIdx->pTable->tnum;
 +      zName = pIdx->zName;
 +      nCol = pIdx->nColumn;
 +    }else if( (pTab = sqlite3FindTable(db, zRight, zDb))!=0 ){
 +      zName = pTab->zName;
 +      if( HasRowid(pTab) ){
 +        iLock = iRoot = pTab->tnum;
 +        nCol = pTab->nCol;
 +      }else{
 +        pIdx = sqlite3PrimaryKeyIndex(pTab);
 +        iLock = iRoot = pIdx->tnum;
 +        nCol = pIdx->nColumn;
 +      }
 +    }else{
 +      break;
 +    }
 +    sqlite3VdbeSetNumCols(v, nCol);
 +    for(i=0; i<nCol; i++){
 +      char zCol[30];
 +      sqlite3_snprintf(sizeof(zCol),zCol,"c%06d",i);
 +      sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
 +    }
 +    if( pValues->nId>=2 ){
 +      const char *z = pValues->a[1].zName;
 +      sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
 +    }else{
 +      r = 0.5;
 +    }
 +    if( r<0.0 ) r = 0.0;
 +    if( r>1.0 ) r = 1.0;
 +    if( pValues->nId>=3 ){
 +      iLimit = sqlite3Atoi(pValues->a[2].zName);
 +    }
 +    pParse->nTab++;
 +    sqlite3TableLock(pParse, iDb, iLock, 0, zName);
 +    sqlite3CodeVerifySchema(pParse, iDb);
 +    sqlite3VdbeAddOp4Int(v, OP_OpenRead, 0, iRoot, iDb, nCol);
 +    if( pIdx ) sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
 +    regLimit = ++pParse->nMem;
 +    regResult = pParse->nMem+1;
 +    pParse->nMem += nCol;
 +    sqlite3VdbeAddOp2(v, OP_Integer, iLimit, regLimit);
 +    addrSkip = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
 +    sqlite3VdbeAddOp3(v, OP_EstRowCnt, 0, regResult, (int)(r*1000000000));
 +    addrTop = sqlite3VdbeCurrentAddr(v);
 +    for(i=0; i<nCol; i++){
 +      sqlite3VdbeAddOp3(v, OP_Column, 0, i, regResult+i);
 +    }
 +    sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nCol);
 +    addrJmp = sqlite3VdbeAddOp1(v, OP_DecrJumpZero, regLimit); VdbeCoverage(v);
 +    sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop); VdbeCoverage(v);
 +    sqlite3VdbeJumpHere(v, addrJmp);
 +    sqlite3VdbeJumpHere(v, addrSkip);
 +  }
 +  break;
 +
  #ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
  # define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
  #endif
  
  pragma_out:
    sqlite3DbFree(db, zLeft);
 -  sqlite3DbFree(db, zRight);
 +  sqlite3IdListDelete(db, pValues);
  }
+ #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++){
+     sqlite3XPrintf(&acc, "%c\"%s\"", cSep, pragCName[j]);
+     cSep = ',';
+   }
+   if( i==0 ){
+     sqlite3XPrintf(&acc, "(\"%s\"", pPragma->zName);
+     cSep = ',';
+     i++;
+   }
+   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];
+   pIdxInfo->estimatedCost = (double)1;
+   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 );
+     seen[j] = i+1;
+   }
+   if( seen[0]==0 ){
+     pIdxInfo->estimatedCost = (double)2147483647;
+     pIdxInfo->estimatedRows = 2147483647;
+     return SQLITE_OK;
+   }
+   j = seen[0]-1;
+   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]-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);
+   sqlite3_free(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++;
+   assert( 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, j;
+   StrAccum acc;
+   char *zSql;
+   pragmaVtabCursorClear(pCsr);
+   j = (pTab->pName->mPragFlg & PragFlg_Result1)!=0 ? 0 : 1;
+   for(i=0; i<argc; i++, j++){
+     assert( j<ArraySize(pCsr->azArg) );
+     pCsr->azArg[j] = sqlite3_mprintf("%s", sqlite3_value_text(argv[i]));
+     if( pCsr->azArg[j]==0 ){
+       return SQLITE_NOMEM;
+     }
+   }
+   sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_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, (void*)pName, 0);
+ }
+ #endif /* SQLITE_OMIT_VIRTUALTABLE */
  
  #endif /* SQLITE_OMIT_PRAGMA */
diff --cc src/pragma.h
index ab70897f55ae81ab91f9a5fd680866e1da2b572b,b854b4f38cd962c156d19fa1604fd8cdbc770f29..9713252afb81ec4117ced59e201aef7697c3a8b5
  #define PragTyp_HEADER_VALUE                   0
  #define PragTyp_AUTO_VACUUM                    1
  #define PragTyp_FLAG                           2
 -#define PragTyp_BUSY_TIMEOUT                   3
 -#define PragTyp_CACHE_SIZE                     4
 -#define PragTyp_CACHE_SPILL                    5
 -#define PragTyp_CASE_SENSITIVE_LIKE            6
 -#define PragTyp_COLLATION_LIST                 7
 -#define PragTyp_COMPILE_OPTIONS                8
 -#define PragTyp_DATA_STORE_DIRECTORY           9
 -#define PragTyp_DATABASE_LIST                 10
 -#define PragTyp_DEFAULT_CACHE_SIZE            11
 -#define PragTyp_ENCODING                      12
 -#define PragTyp_FOREIGN_KEY_CHECK             13
 -#define PragTyp_FOREIGN_KEY_LIST              14
 -#define PragTyp_INCREMENTAL_VACUUM            15
 -#define PragTyp_INDEX_INFO                    16
 -#define PragTyp_INDEX_LIST                    17
 -#define PragTyp_INTEGRITY_CHECK               18
 -#define PragTyp_JOURNAL_MODE                  19
 -#define PragTyp_JOURNAL_SIZE_LIMIT            20
 -#define PragTyp_LOCK_PROXY_FILE               21
 -#define PragTyp_LOCKING_MODE                  22
 -#define PragTyp_PAGE_COUNT                    23
 -#define PragTyp_MMAP_SIZE                     24
 -#define PragTyp_PAGE_SIZE                     25
 -#define PragTyp_SECURE_DELETE                 26
 -#define PragTyp_SHRINK_MEMORY                 27
 -#define PragTyp_SOFT_HEAP_LIMIT               28
 -#define PragTyp_STATS                         29
 -#define PragTyp_SYNCHRONOUS                   30
 -#define PragTyp_TABLE_INFO                    31
 -#define PragTyp_TEMP_STORE                    32
 -#define PragTyp_TEMP_STORE_DIRECTORY          33
 -#define PragTyp_THREADS                       34
 -#define PragTyp_WAL_AUTOCHECKPOINT            35
 -#define PragTyp_WAL_CHECKPOINT                36
 -#define PragTyp_ACTIVATE_EXTENSIONS           37
 -#define PragTyp_HEXKEY                        38
 -#define PragTyp_KEY                           39
 -#define PragTyp_REKEY                         40
 -#define PragTyp_LOCK_STATUS                   41
 -#define PragTyp_PARSER_TRACE                  42
 +#define PragTyp_BTREE_SAMPLE                   3
 +#define PragTyp_BUSY_TIMEOUT                   4
 +#define PragTyp_CACHE_SIZE                     5
 +#define PragTyp_CACHE_SPILL                    6
 +#define PragTyp_CASE_SENSITIVE_LIKE            7
 +#define PragTyp_COLLATION_LIST                 8
 +#define PragTyp_COMPILE_OPTIONS                9
 +#define PragTyp_DATA_STORE_DIRECTORY          10
 +#define PragTyp_DATABASE_LIST                 11
 +#define PragTyp_DEFAULT_CACHE_SIZE            12
 +#define PragTyp_ENCODING                      13
 +#define PragTyp_EST_COUNT                     14
 +#define PragTyp_FOREIGN_KEY_CHECK             15
 +#define PragTyp_FOREIGN_KEY_LIST              16
 +#define PragTyp_INCREMENTAL_VACUUM            17
 +#define PragTyp_INDEX_INFO                    18
 +#define PragTyp_INDEX_LIST                    19
 +#define PragTyp_INTEGRITY_CHECK               20
 +#define PragTyp_JOURNAL_MODE                  21
 +#define PragTyp_JOURNAL_SIZE_LIMIT            22
 +#define PragTyp_LOCK_PROXY_FILE               23
 +#define PragTyp_LOCKING_MODE                  24
 +#define PragTyp_PAGE_COUNT                    25
 +#define PragTyp_MMAP_SIZE                     26
 +#define PragTyp_PAGE_SIZE                     27
 +#define PragTyp_SECURE_DELETE                 28
 +#define PragTyp_SHRINK_MEMORY                 29
 +#define PragTyp_SOFT_HEAP_LIMIT               30
 +#define PragTyp_STATS                         31
 +#define PragTyp_SYNCHRONOUS                   32
 +#define PragTyp_TABLE_INFO                    33
 +#define PragTyp_TEMP_STORE                    34
 +#define PragTyp_TEMP_STORE_DIRECTORY          35
 +#define PragTyp_THREADS                       36
 +#define PragTyp_WAL_AUTOCHECKPOINT            37
 +#define PragTyp_WAL_CHECKPOINT                38
 +#define PragTyp_ACTIVATE_EXTENSIONS           39
 +#define PragTyp_HEXKEY                        40
 +#define PragTyp_KEY                           41
 +#define PragTyp_REKEY                         42
 +#define PragTyp_LOCK_STATUS                   43
 +#define PragTyp_PARSER_TRACE                  44
- #define PragFlag_NeedSchema           0x01
- #define PragFlag_ReadOnly             0x02
- static const struct sPragmaNames {
-   const char *const zName;  /* Name of pragma */
-   u8 ePragTyp;              /* PragTyp_XXX value */
-   u8 mPragFlag;             /* Zero or more PragFlag_XXX values */
-   u32 iArg;                 /* Extra argument */
- } aPragmaNames[] = {
+ /* Property flags associated with various pragma. */
+ #define PragFlg_NeedSchema 0x01 /* Force schema load before running */
+ #define PragFlg_NoColumns  0x02 /* OP_ResultRow called with zero columns */
+ #define PragFlg_ReadOnly   0x04 /* Read-only HEADER_VALUE */
+ #define PragFlg_Result0    0x08 /* Acts as query when no argument */
+ #define PragFlg_Result1    0x10 /* Acts as query when has one argument */
+ #define PragFlg_SchemaOpt  0x20 /* Schema restricts name search if present */
+ #define PragFlg_SchemaReq  0x40 /* Schema required - "main" is default */
+ /* Names of columns for pragmas that return multi-column result
+ ** or that return single-column results where the name of the
+ ** result column is different from the name of the pragma
+ */
+ static const char *const pragCName[] = {
+   /*   0 */ "cache_size",  /* Used by: default_cache_size */
+   /*   1 */ "cid",         /* Used by: table_info */
+   /*   2 */ "name",       
+   /*   3 */ "type",       
+   /*   4 */ "notnull",    
+   /*   5 */ "dflt_value", 
+   /*   6 */ "pk",         
+   /*   7 */ "table",       /* Used by: stats */
+   /*   8 */ "index",      
+   /*   9 */ "width",      
+   /*  10 */ "height",     
+   /*  11 */ "seqno",       /* Used by: index_info */
+   /*  12 */ "cid",        
+   /*  13 */ "name",       
+   /*  14 */ "seqno",       /* Used by: index_xinfo */
+   /*  15 */ "cid",        
+   /*  16 */ "name",       
+   /*  17 */ "desc",       
+   /*  18 */ "coll",       
+   /*  19 */ "key",        
+   /*  20 */ "seq",         /* Used by: index_list */
+   /*  21 */ "name",       
+   /*  22 */ "unique",     
+   /*  23 */ "origin",     
+   /*  24 */ "partial",    
+   /*  25 */ "seq",         /* Used by: database_list */
+   /*  26 */ "name",       
+   /*  27 */ "file",       
+   /*  28 */ "seq",         /* Used by: collation_list */
+   /*  29 */ "name",       
+   /*  30 */ "id",          /* Used by: foreign_key_list */
+   /*  31 */ "seq",        
+   /*  32 */ "table",      
+   /*  33 */ "from",       
+   /*  34 */ "to",         
+   /*  35 */ "on_update",  
+   /*  36 */ "on_delete",  
+   /*  37 */ "match",      
+   /*  38 */ "table",       /* Used by: foreign_key_check */
+   /*  39 */ "rowid",      
+   /*  40 */ "parent",     
+   /*  41 */ "fkid",       
+   /*  42 */ "busy",        /* Used by: wal_checkpoint */
+   /*  43 */ "log",        
+   /*  44 */ "checkpointed",
+   /*  45 */ "timeout",     /* Used by: busy_timeout */
+   /*  46 */ "database",    /* Used by: lock_status */
+   /*  47 */ "status",     
+ };
+ /* Definitions of all built-in pragmas */
+ typedef struct PragmaName {
+   const char *const zName; /* Name of pragma */
+   u8 ePragTyp;             /* PragTyp_XXX value */
+   u8 mPragFlg;             /* Zero or more PragFlg_XXX values */
+   u8 iPragCName;           /* Start of column names in pragCName[] */
+   u8 nPragCName;           /* Num of col names. 0 means use pragma name */
+   u32 iArg;                /* Extra argument */
+ } PragmaName;
+ static const PragmaName aPragmaName[] = {
  #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
-   { /* zName:     */ "activate_extensions",
-     /* ePragTyp:  */ PragTyp_ACTIVATE_EXTENSIONS,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ 0 },
+  {/* zName:     */ "activate_extensions",
+   /* ePragTyp:  */ PragTyp_ACTIVATE_EXTENSIONS,
+   /* ePragFlg:  */ 0,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ 0 },
  #endif
  #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
-   { /* zName:     */ "application_id",
-     /* ePragTyp:  */ PragTyp_HEADER_VALUE,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ BTREE_APPLICATION_ID },
+  {/* zName:     */ "application_id",
+   /* ePragTyp:  */ PragTyp_HEADER_VALUE,
+   /* ePragFlg:  */ PragFlg_Result0,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ BTREE_APPLICATION_ID },
  #endif
  #if !defined(SQLITE_OMIT_AUTOVACUUM)
-   { /* zName:     */ "auto_vacuum",
-     /* ePragTyp:  */ PragTyp_AUTO_VACUUM,
-     /* ePragFlag: */ PragFlag_NeedSchema,
-     /* iArg:      */ 0 },
+  {/* zName:     */ "auto_vacuum",
+   /* ePragTyp:  */ PragTyp_AUTO_VACUUM,
+   /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ 0 },
  #endif
  #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
  #if !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
-   { /* zName:     */ "automatic_index",
-     /* ePragTyp:  */ PragTyp_FLAG,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ SQLITE_AutoIndex },
- #endif
- #endif
-   { /* zName:     */ "btree_sample",
-     /* ePragTyp:  */ PragTyp_BTREE_SAMPLE,
-     /* ePragFlag: */ PragFlag_NeedSchema,
-     /* iArg:      */ 0 },
-   { /* zName:     */ "busy_timeout",
-     /* ePragTyp:  */ PragTyp_BUSY_TIMEOUT,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ 0 },
+  {/* zName:     */ "automatic_index",
+   /* ePragTyp:  */ PragTyp_FLAG,
+   /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ SQLITE_AutoIndex },
+ #endif
+ #endif
++ {/* zName:     */ "btree_sample",
++  /* ePragTyp:  */ PragTyp_BTREE_SAMPLE,
++  /* ePragFlg:  */ PragFlg_NeedSchema,
++  /* ColNames:  */ 0, 0,
++  /* iArg:      */ 0 },
+  {/* zName:     */ "busy_timeout",
+   /* ePragTyp:  */ PragTyp_BUSY_TIMEOUT,
+   /* ePragFlg:  */ PragFlg_Result0,
+   /* ColNames:  */ 45, 1,
+   /* iArg:      */ 0 },
  #if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
-   { /* zName:     */ "cache_size",
-     /* ePragTyp:  */ PragTyp_CACHE_SIZE,
-     /* ePragFlag: */ PragFlag_NeedSchema,
-     /* iArg:      */ 0 },
+  {/* zName:     */ "cache_size",
+   /* ePragTyp:  */ PragTyp_CACHE_SIZE,
+   /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ 0 },
  #endif
  #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-   { /* zName:     */ "cache_spill",
-     /* ePragTyp:  */ PragTyp_CACHE_SPILL,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ 0 },
- #endif
-   { /* zName:     */ "case_sensitive_like",
-     /* ePragTyp:  */ PragTyp_CASE_SENSITIVE_LIKE,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ 0 },
-   { /* zName:     */ "cell_size_check",
-     /* ePragTyp:  */ PragTyp_FLAG,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ SQLITE_CellSizeCk },
+  {/* zName:     */ "cache_spill",
+   /* ePragTyp:  */ PragTyp_CACHE_SPILL,
+   /* ePragFlg:  */ PragFlg_Result0|PragFlg_SchemaReq,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ 0 },
+ #endif
+  {/* zName:     */ "case_sensitive_like",
+   /* ePragTyp:  */ PragTyp_CASE_SENSITIVE_LIKE,
+   /* ePragFlg:  */ 0,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ 0 },
+  {/* zName:     */ "cell_size_check",
+   /* ePragTyp:  */ PragTyp_FLAG,
+   /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ SQLITE_CellSizeCk },
  #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-   { /* zName:     */ "checkpoint_fullfsync",
-     /* ePragTyp:  */ PragTyp_FLAG,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ SQLITE_CkptFullFSync },
+  {/* zName:     */ "checkpoint_fullfsync",
+   /* ePragTyp:  */ PragTyp_FLAG,
+   /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ SQLITE_CkptFullFSync },
  #endif
  #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-   { /* zName:     */ "collation_list",
-     /* ePragTyp:  */ PragTyp_COLLATION_LIST,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ 0 },
+  {/* zName:     */ "collation_list",
+   /* ePragTyp:  */ PragTyp_COLLATION_LIST,
+   /* ePragFlg:  */ PragFlg_Result0,
+   /* ColNames:  */ 28, 2,
+   /* iArg:      */ 0 },
  #endif
  #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
-   { /* zName:     */ "compile_options",
-     /* ePragTyp:  */ PragTyp_COMPILE_OPTIONS,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ 0 },
+  {/* zName:     */ "compile_options",
+   /* ePragTyp:  */ PragTyp_COMPILE_OPTIONS,
+   /* ePragFlg:  */ PragFlg_Result0,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ 0 },
  #endif
  #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-   { /* zName:     */ "count_changes",
-     /* ePragTyp:  */ PragTyp_FLAG,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ SQLITE_CountRows },
+  {/* zName:     */ "count_changes",
+   /* ePragTyp:  */ PragTyp_FLAG,
+   /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ SQLITE_CountRows },
  #endif
  #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
-   { /* zName:     */ "data_store_directory",
-     /* ePragTyp:  */ PragTyp_DATA_STORE_DIRECTORY,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ 0 },
+  {/* zName:     */ "data_store_directory",
+   /* ePragTyp:  */ PragTyp_DATA_STORE_DIRECTORY,
+   /* ePragFlg:  */ 0,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ 0 },
  #endif
  #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
-   { /* zName:     */ "data_version",
-     /* ePragTyp:  */ PragTyp_HEADER_VALUE,
-     /* ePragFlag: */ PragFlag_ReadOnly,
-     /* iArg:      */ BTREE_DATA_VERSION },
+  {/* zName:     */ "data_version",
+   /* ePragTyp:  */ PragTyp_HEADER_VALUE,
+   /* ePragFlg:  */ PragFlg_Result0|PragFlg_ReadOnly,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ BTREE_DATA_VERSION },
  #endif
  #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
-   { /* zName:     */ "database_list",
-     /* ePragTyp:  */ PragTyp_DATABASE_LIST,
-     /* ePragFlag: */ PragFlag_NeedSchema,
-     /* iArg:      */ 0 },
+  {/* zName:     */ "database_list",
+   /* ePragTyp:  */ PragTyp_DATABASE_LIST,
+   /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0,
+   /* ColNames:  */ 25, 3,
+   /* iArg:      */ 0 },
  #endif
  #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
-   { /* zName:     */ "default_cache_size",
-     /* ePragTyp:  */ PragTyp_DEFAULT_CACHE_SIZE,
-     /* ePragFlag: */ PragFlag_NeedSchema,
-     /* iArg:      */ 0 },
+  {/* zName:     */ "default_cache_size",
+   /* ePragTyp:  */ PragTyp_DEFAULT_CACHE_SIZE,
+   /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
+   /* ColNames:  */ 0, 1,
+   /* iArg:      */ 0 },
  #endif
  #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
  #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
  #endif
  #endif
  #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-   { /* zName:     */ "empty_result_callbacks",
-     /* ePragTyp:  */ PragTyp_FLAG,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ SQLITE_NullCallback },
+  {/* zName:     */ "empty_result_callbacks",
+   /* ePragTyp:  */ PragTyp_FLAG,
+   /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ SQLITE_NullCallback },
  #endif
  #if !defined(SQLITE_OMIT_UTF16)
-   { /* zName:     */ "encoding",
-     /* ePragTyp:  */ PragTyp_ENCODING,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ 0 },
- #endif
-   { /* zName:     */ "est_count",
-     /* ePragTyp:  */ PragTyp_EST_COUNT,
-     /* ePragFlag: */ PragFlag_NeedSchema,
-     /* iArg:      */ 0 },
+  {/* zName:     */ "encoding",
+   /* ePragTyp:  */ PragTyp_ENCODING,
+   /* ePragFlg:  */ PragFlg_Result0,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ 0 },
+ #endif
++ {/* zName:     */ "est_count",
++  /* ePragTyp:  */ PragTyp_EST_COUNT,
++  /* ePragFlg:  */ PragFlg_NeedSchema,
++  /* ColNames:  */ 0, 0,
++  /* iArg:      */ 0 },
  #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
-   { /* zName:     */ "foreign_key_check",
-     /* ePragTyp:  */ PragTyp_FOREIGN_KEY_CHECK,
-     /* ePragFlag: */ PragFlag_NeedSchema,
-     /* iArg:      */ 0 },
+  {/* zName:     */ "foreign_key_check",
+   /* ePragTyp:  */ PragTyp_FOREIGN_KEY_CHECK,
+   /* ePragFlg:  */ PragFlg_NeedSchema,
+   /* ColNames:  */ 38, 4,
+   /* iArg:      */ 0 },
  #endif
  #if !defined(SQLITE_OMIT_FOREIGN_KEY)
-   { /* zName:     */ "foreign_key_list",
-     /* ePragTyp:  */ PragTyp_FOREIGN_KEY_LIST,
-     /* ePragFlag: */ PragFlag_NeedSchema,
-     /* iArg:      */ 0 },
+  {/* zName:     */ "foreign_key_list",
+   /* ePragTyp:  */ PragTyp_FOREIGN_KEY_LIST,
+   /* ePragFlg:  */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
+   /* ColNames:  */ 30, 8,
+   /* iArg:      */ 0 },
  #endif
  #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
  #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
  #endif
  #endif
  #if !defined(SQLITE_OMIT_WAL)
-   { /* zName:     */ "wal_autocheckpoint",
-     /* ePragTyp:  */ PragTyp_WAL_AUTOCHECKPOINT,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ 0 },
-   { /* zName:     */ "wal_checkpoint",
-     /* ePragTyp:  */ PragTyp_WAL_CHECKPOINT,
-     /* ePragFlag: */ PragFlag_NeedSchema,
-     /* iArg:      */ 0 },
+  {/* zName:     */ "wal_autocheckpoint",
+   /* ePragTyp:  */ PragTyp_WAL_AUTOCHECKPOINT,
+   /* ePragFlg:  */ 0,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ 0 },
+  {/* zName:     */ "wal_checkpoint",
+   /* ePragTyp:  */ PragTyp_WAL_CHECKPOINT,
+   /* ePragFlg:  */ PragFlg_NeedSchema,
+   /* ColNames:  */ 42, 3,
+   /* iArg:      */ 0 },
  #endif
  #if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
-   { /* zName:     */ "writable_schema",
-     /* ePragTyp:  */ PragTyp_FLAG,
-     /* ePragFlag: */ 0,
-     /* iArg:      */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
+  {/* zName:     */ "writable_schema",
+   /* ePragTyp:  */ PragTyp_FLAG,
+   /* ePragFlg:  */ PragFlg_Result0|PragFlg_NoColumns,
+   /* ColNames:  */ 0, 0,
+   /* iArg:      */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
  #endif
  };
 -/* Number of pragmas: 60 on by default, 73 total. */
 +/* Number of pragmas: 62 on by default, 75 total. */
diff --cc src/sqliteInt.h
index 8a3d92ea6dd546814096e3cb36c4d856095abc7f,07156092c9c7c00c8f71cad27c520713f02ddf34..640f5cfdc6e608938a00142f1bf4bd0a6b16a563
@@@ -3562,7 -3562,10 +3562,10 @@@ void sqlite3ExprListDelete(sqlite3*, Ex
  u32 sqlite3ExprListFlags(const ExprList*);
  int sqlite3Init(sqlite3*, char**);
  int sqlite3InitCallback(void*, int, char**, char**);
 -void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
 +void sqlite3Pragma(Parse*,Token*,Token*,IdList*);
+ #ifndef SQLITE_OMIT_VIRTUALTABLE
+ Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
+ #endif
  void sqlite3ResetAllSchemasOfConnection(sqlite3*);
  void sqlite3ResetOneSchema(sqlite3*,int);
  void sqlite3CollapseDatabaseArray(sqlite3*);
index cac776d668ceb7127059eda15438569fbb6fa0fc,d9e100366cc3dba807f72a8caf7bd625d0dc7a42..3428a946a869c5247e0a788013aca4c94db56e51
@@@ -251,13 -277,8 +277,14 @@@ set pragma_def 
    FLAG: NeedSchema
    IF:   !defined(SQLITE_OMIT_INTEGRITY_CHECK)
  
 +  NAME: est_count
 +  FLAG: NeedSchema
 +
 +  NAME: btree_sample
 +  FLAG: NeedSchema
 +
    NAME: encoding
+   FLAG: Result0
    IF:   !defined(SQLITE_OMIT_UTF16)
  
    NAME: schema_version