]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Experimental merge of the est_count_pragma and the pragma-as-vtab branches. est-count-pragma-vtab
authordrh <drh@noemail.net>
Fri, 16 Dec 2016 16:49:11 +0000 (16:49 +0000)
committerdrh <drh@noemail.net>
Fri, 16 Dec 2016 16:49:11 +0000 (16:49 +0000)
FossilOrigin-Name: 4b73ee33f31281886256663a0e4a6397d3c8efc5

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

diff --cc manifest
index 4d0b8539bfce1567f0688683967a9df694579a6b,9f2f0544a071e58b98c8eef5e8fdf789cc7142de..eb6084f069c14f2c263e53a1b60cdb40112e7a8f
+++ b/manifest
@@@ -1,5 -1,5 +1,5 @@@
- C Fix\san\serror\sin\sthe\sway\sthe\s"schema"\sargument\sto\ssome\spragma\svirtual\stables\nis\shandled.
- D 2016-12-16T04:20:27.559
 -C Merge\srecent\strunk\senhancements.
 -D 2016-12-16T15:57:40.254
++C Experimental\smerge\sof\sthe\sest_count_pragma\sand\sthe\spragma-as-vtab\sbranches.
++D 2016-12-16T16:49:11.848
  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 52970b6cf3cf3107551a5d6dd668b0b261b0b491
 -F src/build.c 182877f27be4129ffd385b80f3318251a605152b
++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 d5adfe89ad7f3f45d4dbd25b96cbf3f6611aea2a
- F src/pragma.h f9b221b2c8949ea941dbee49934299e4ed5af41c
 -F src/pragma.c 6ca8fb0a4da012c4ec4e92c76d868dca97ac6a03
 -F src/pragma.h 74d46e32bdc7abb2d01710162ff96cfb483699b6
++F src/pragma.c 850bee0057697e817c337c8141e12f74c64eb8f4
++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 f1c7fde7a83421e6ed620df41
  F src/sqlite.h.in e8e2d108d82647f0a812fdb74accf91c1ec08ddc
  F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
  F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
- F src/sqliteInt.h adbe80409c2926d91e5485789e5bf69313cd54b0
 -F src/sqliteInt.h d4b1e6a694ed35bc669c9c99e0dea35e76e357f8
++F src/sqliteInt.h 9f4111b5743fdb9d6dea6da81485abc94abf01ac
  F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
  F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
  F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
@@@ -1474,7 -1475,7 +1475,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 a30ee93515135466fc49ae881f75da07ebcafd19
 -F tool/mkpragmatab.tcl c5ce5c56a8193196efcd195f09572a073445397f
++F tool/mkpragmatab.tcl c4e9c6b70e54e5720a81eeccfb4d739a566be217
  F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
  F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
  F tool/mksqlite3c.tcl 06b2e6a0f21cc0a5d70fbbd136b3e0a96470645e
@@@ -1536,7 -1537,7 +1537,10 @@@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a9
  F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
  F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
  F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
- P 01afc515970a868c6a36d9a598453d0fde9e39ca
- R a742a8093b3e07485d2949a360f59e06
 -P dc006e08b80758b8ac3addd98a532b074b5ca132 053a149cc8244a7f85137129cfcb8622efe90306
 -R 622e5a34bc63b8a2c15e428113c053e3
++P 546821e29edb0282a4b1d8f49512e36027a6bf6d 74a0ca1f152d6d8454787557c6e990efe0e47a50
++R 04f447c00e247ed4618fbb5b48ddcec6
++T *branch * est-count-pragma-vtab
++T *sym-est-count-pragma-vtab *
++T -sym-pragma-as-vtab *
  U drh
- Z b26c88cbc10f1352d564598308e683f5
 -Z 935fedef2d7541845766cdea56b5f368
++Z f94f7d33b2ad68dbdfa8be480e10347f
diff --cc manifest.uuid
index e8e79b2cfbc7662874b2f54eb2db58ae7c1e49f1,babbdd40c0004b05de8ef153a40a1eac79a7ac0f..50c1300a4e36ab2cd2cc89e124e28c0c31b3b850
@@@ -1,1 -1,1 +1,1 @@@
- 546821e29edb0282a4b1d8f49512e36027a6bf6d
 -74a0ca1f152d6d8454787557c6e990efe0e47a50
++4b73ee33f31281886256663a0e4a6397d3c8efc5
diff --cc src/build.c
Simple merge
diff --cc src/pragma.c
index d84e1d7929e96c9ac8865120317a7530496ffb7a,e725b6cef0fef53add3dc23f35ce83c05f6350cf..4a024848d6fd4b300ce16c0f0f7a148b8d881573
@@@ -327,9 -305,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 b854b4f38cd962c156d19fa1604fd8cdbc770f29,ab70897f55ae81ab91f9a5fd680866e1da2b572b..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 07156092c9c7c00c8f71cad27c520713f02ddf34,8a3d92ea6dd546814096e3cb36c4d856095abc7f..640f5cfdc6e608938a00142f1bf4bd0a6b16a563
@@@ -3562,10 -3562,7 +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 d9e100366cc3dba807f72a8caf7bd625d0dc7a42,cac776d668ceb7127059eda15438569fbb6fa0fc..3428a946a869c5247e0a788013aca4c94db56e51
@@@ -277,8 -251,13 +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