mirror of
https://github.com/php/php-src.git
synced 2025-08-20 17:34:35 +02:00
Update bundled SQLite to 3.5.6
This commit is contained in:
parent
184173fccc
commit
5a86313123
106 changed files with 32603 additions and 22274 deletions
|
@ -14,18 +14,12 @@
|
|||
** $Id$
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
#include <ctype.h>
|
||||
|
||||
/* Ignore this whole file if pragmas are disabled
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER)
|
||||
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
# include "pager.h"
|
||||
# include "btree.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Interpret the given string as a safety level. Return 0 for OFF,
|
||||
** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
|
||||
|
@ -73,6 +67,23 @@ static int getLockingMode(const char *z){
|
|||
return PAGER_LOCKINGMODE_QUERY;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
/*
|
||||
** Interpret the given string as an auto-vacuum mode value.
|
||||
**
|
||||
** The following strings, "none", "full" and "incremental" are
|
||||
** acceptable, as are their numeric equivalents: 0, 1 and 2 respectively.
|
||||
*/
|
||||
static int getAutoVacuum(const char *z){
|
||||
int i;
|
||||
if( 0==sqlite3StrICmp(z, "none") ) return BTREE_AUTOVACUUM_NONE;
|
||||
if( 0==sqlite3StrICmp(z, "full") ) return BTREE_AUTOVACUUM_FULL;
|
||||
if( 0==sqlite3StrICmp(z, "incremental") ) return BTREE_AUTOVACUUM_INCR;
|
||||
i = atoi(z);
|
||||
return ((i>=0&&i<=2)?i:0);
|
||||
}
|
||||
#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */
|
||||
|
||||
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
|
||||
/*
|
||||
** Interpret the given string as a temp db location. Return 1 for file
|
||||
|
@ -136,12 +147,13 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){
|
|||
*/
|
||||
static void returnSingleInt(Parse *pParse, const char *zLabel, int value){
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
sqlite3VdbeAddOp(v, OP_Integer, value, 0);
|
||||
int mem = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, value, mem);
|
||||
if( pParse->explain==0 ){
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, P4_STATIC);
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_FLAG_PRAGMAS
|
||||
|
@ -155,15 +167,17 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
|
|||
const char *zName; /* Name of the pragma */
|
||||
int mask; /* Mask for the db->flags value */
|
||||
} aPragma[] = {
|
||||
{ "vdbe_trace", SQLITE_VdbeTrace },
|
||||
{ "sql_trace", SQLITE_SqlTrace },
|
||||
{ "vdbe_listing", SQLITE_VdbeListing },
|
||||
{ "full_column_names", SQLITE_FullColNames },
|
||||
{ "short_column_names", SQLITE_ShortColNames },
|
||||
{ "count_changes", SQLITE_CountRows },
|
||||
{ "empty_result_callbacks", SQLITE_NullCallback },
|
||||
{ "legacy_file_format", SQLITE_LegacyFileFmt },
|
||||
{ "fullfsync", SQLITE_FullFSync },
|
||||
#ifdef SQLITE_DEBUG
|
||||
{ "sql_trace", SQLITE_SqlTrace },
|
||||
{ "vdbe_listing", SQLITE_VdbeListing },
|
||||
{ "vdbe_trace", SQLITE_VdbeTrace },
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_CHECK
|
||||
{ "ignore_check_constraints", SQLITE_IgnoreChecks },
|
||||
#endif
|
||||
|
@ -191,8 +205,15 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
|
|||
}else{
|
||||
db->flags &= ~p->mask;
|
||||
}
|
||||
|
||||
/* Many of the flag-pragmas modify the code generated by the SQL
|
||||
** compiler (eg. count_changes). So add an opcode to expire all
|
||||
** compiled SQL statements after modifying a pragma value.
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -229,8 +250,9 @@ void sqlite3Pragma(
|
|||
int iDb; /* Database index for <database> */
|
||||
sqlite3 *db = pParse->db;
|
||||
Db *pDb;
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db);
|
||||
if( v==0 ) return;
|
||||
pParse->nMem = 2;
|
||||
|
||||
/* Interpret the [database.] part of the pragma statement. iDb is the
|
||||
** index of the database this pragma is being applied to in db.aDb[]. */
|
||||
|
@ -245,12 +267,12 @@ void sqlite3Pragma(
|
|||
return;
|
||||
}
|
||||
|
||||
zLeft = sqlite3NameFromToken(pId);
|
||||
zLeft = sqlite3NameFromToken(db, pId);
|
||||
if( !zLeft ) return;
|
||||
if( minusFlag ){
|
||||
zRight = sqlite3MPrintf("-%T", pValue);
|
||||
zRight = sqlite3MPrintf(db, "-%T", pValue);
|
||||
}else{
|
||||
zRight = sqlite3NameFromToken(pValue);
|
||||
zRight = sqlite3NameFromToken(db, pValue);
|
||||
}
|
||||
|
||||
zDb = ((iDb>0)?pDb->zName:0);
|
||||
|
@ -277,32 +299,34 @@ void sqlite3Pragma(
|
|||
*/
|
||||
if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){
|
||||
static const VdbeOpList getCacheSize[] = {
|
||||
{ OP_ReadCookie, 0, 2, 0}, /* 0 */
|
||||
{ OP_AbsValue, 0, 0, 0},
|
||||
{ OP_Dup, 0, 0, 0},
|
||||
{ OP_Integer, 0, 0, 0},
|
||||
{ OP_Ne, 0, 6, 0},
|
||||
{ OP_Integer, 0, 0, 0}, /* 5 */
|
||||
{ OP_Callback, 1, 0, 0},
|
||||
{ OP_ReadCookie, 0, 1, 2}, /* 0 */
|
||||
{ OP_IfPos, 1, 6, 0},
|
||||
{ OP_Integer, 0, 2, 0},
|
||||
{ OP_Subtract, 1, 2, 1},
|
||||
{ OP_IfPos, 1, 6, 0},
|
||||
{ OP_Integer, 0, 1, 0}, /* 5 */
|
||||
{ OP_ResultRow, 1, 1, 0},
|
||||
};
|
||||
int addr;
|
||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
if( !zRight ){
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P4_STATIC);
|
||||
pParse->nMem += 2;
|
||||
addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
|
||||
sqlite3VdbeChangeP1(v, addr, iDb);
|
||||
sqlite3VdbeChangeP1(v, addr+5, MAX_PAGES);
|
||||
sqlite3VdbeChangeP1(v, addr+5, SQLITE_DEFAULT_CACHE_SIZE);
|
||||
}else{
|
||||
int size = atoi(zRight);
|
||||
if( size<0 ) size = -size;
|
||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||
sqlite3VdbeAddOp(v, OP_Integer, size, 0);
|
||||
sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 2);
|
||||
addr = sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Ge, 0, addr+3);
|
||||
sqlite3VdbeAddOp(v, OP_Negative, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 2);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, size, 1);
|
||||
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 2, 2);
|
||||
addr = sqlite3VdbeAddOp2(v, OP_IfPos, 2, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, -size, 1);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 2, 1);
|
||||
pDb->pSchema->cache_size = size;
|
||||
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
|
||||
}
|
||||
|
@ -323,10 +347,36 @@ void sqlite3Pragma(
|
|||
int size = pBt ? sqlite3BtreeGetPageSize(pBt) : 0;
|
||||
returnSingleInt(pParse, "page_size", size);
|
||||
}else{
|
||||
sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1);
|
||||
/* Malloc may fail when setting the page-size, as there is an internal
|
||||
** buffer that the pager module resizes using sqlite3_realloc().
|
||||
*/
|
||||
if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1) ){
|
||||
db->mallocFailed = 1;
|
||||
}
|
||||
}
|
||||
}else
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]max_page_count
|
||||
** PRAGMA [database.]max_page_count=N
|
||||
**
|
||||
** The first form reports the current setting for the
|
||||
** maximum number of pages in the database file. The
|
||||
** second form attempts to change this setting. Both
|
||||
** forms return the current setting.
|
||||
*/
|
||||
if( sqlite3StrICmp(zLeft,"max_page_count")==0 ){
|
||||
Btree *pBt = pDb->pBt;
|
||||
int newMax = 0;
|
||||
if( zRight ){
|
||||
newMax = atoi(zRight);
|
||||
}
|
||||
if( pBt ){
|
||||
newMax = sqlite3BtreeMaxPageCount(pBt, newMax);
|
||||
}
|
||||
returnSingleInt(pParse, "max_page_count", newMax);
|
||||
}else
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]locking_mode
|
||||
** PRAGMA [database.]locking_mode = (normal|exclusive)
|
||||
|
@ -369,9 +419,9 @@ void sqlite3Pragma(
|
|||
zRet = "exclusive";
|
||||
}
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", P3_STATIC);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, zRet, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", P4_STATIC);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zRet, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
|
||||
|
||||
|
@ -384,16 +434,75 @@ void sqlite3Pragma(
|
|||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( sqlite3StrICmp(zLeft,"auto_vacuum")==0 ){
|
||||
Btree *pBt = pDb->pBt;
|
||||
if( sqlite3ReadSchema(pParse) ){
|
||||
goto pragma_out;
|
||||
}
|
||||
if( !zRight ){
|
||||
int auto_vacuum =
|
||||
pBt ? sqlite3BtreeGetAutoVacuum(pBt) : SQLITE_DEFAULT_AUTOVACUUM;
|
||||
returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
|
||||
}else{
|
||||
sqlite3BtreeSetAutoVacuum(pBt, getBoolean(zRight));
|
||||
int eAuto = getAutoVacuum(zRight);
|
||||
db->nextAutovac = eAuto;
|
||||
if( eAuto>=0 ){
|
||||
/* Call SetAutoVacuum() to set initialize the internal auto and
|
||||
** incr-vacuum flags. This is required in case this connection
|
||||
** creates the database file. It is important that it is created
|
||||
** as an auto-vacuum capable db.
|
||||
*/
|
||||
int rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
|
||||
if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
|
||||
/* When setting the auto_vacuum mode to either "full" or
|
||||
** "incremental", write the value of meta[6] in the database
|
||||
** file. Before writing to meta[6], check that meta[3] indicates
|
||||
** that this really is an auto-vacuum capable database.
|
||||
*/
|
||||
static const VdbeOpList setMeta6[] = {
|
||||
{ OP_Transaction, 0, 1, 0}, /* 0 */
|
||||
{ OP_ReadCookie, 0, 1, 3}, /* 1 */
|
||||
{ OP_If, 1, 0, 0}, /* 2 */
|
||||
{ OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
|
||||
{ OP_Integer, 0, 1, 0}, /* 4 */
|
||||
{ OP_SetCookie, 0, 6, 1}, /* 5 */
|
||||
};
|
||||
int iAddr;
|
||||
iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
|
||||
sqlite3VdbeChangeP1(v, iAddr, iDb);
|
||||
sqlite3VdbeChangeP1(v, iAddr+1, iDb);
|
||||
sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
|
||||
sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
|
||||
sqlite3VdbeChangeP1(v, iAddr+5, iDb);
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else
|
||||
#endif
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]incremental_vacuum(N)
|
||||
**
|
||||
** Do N steps of incremental vacuuming on a database.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( sqlite3StrICmp(zLeft,"incremental_vacuum")==0 ){
|
||||
int iLimit, addr;
|
||||
if( sqlite3ReadSchema(pParse) ){
|
||||
goto pragma_out;
|
||||
}
|
||||
if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
|
||||
iLimit = 0x7fffffff;
|
||||
}
|
||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1);
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb);
|
||||
sqlite3VdbeAddOp1(v, OP_ResultRow, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
|
||||
sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}else
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
|
||||
/*
|
||||
** PRAGMA [database.]cache_size
|
||||
|
@ -455,12 +564,14 @@ void sqlite3Pragma(
|
|||
if( sqlite3_temp_directory ){
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
|
||||
"temp_store_directory", P3_STATIC);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, sqlite3_temp_directory, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
|
||||
"temp_store_directory", P4_STATIC);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_temp_directory, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
|
||||
}
|
||||
}else{
|
||||
if( zRight[0] && !sqlite3OsIsDirWritable(zRight) ){
|
||||
if( zRight[0]
|
||||
&& !sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE)
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "not a writable directory");
|
||||
goto pragma_out;
|
||||
}
|
||||
|
@ -470,7 +581,7 @@ void sqlite3Pragma(
|
|||
){
|
||||
invalidateTempStorage(pParse);
|
||||
}
|
||||
sqliteFree(sqlite3_temp_directory);
|
||||
sqlite3_free(sqlite3_temp_directory);
|
||||
if( zRight[0] ){
|
||||
sqlite3_temp_directory = zRight;
|
||||
zRight = 0;
|
||||
|
@ -530,29 +641,35 @@ void sqlite3Pragma(
|
|||
pTab = sqlite3FindTable(db, zRight, zDb);
|
||||
if( pTab ){
|
||||
int i;
|
||||
int nHidden = 0;
|
||||
Column *pCol;
|
||||
sqlite3VdbeSetNumCols(v, 6);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", P3_STATIC);
|
||||
pParse->nMem = 6;
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", P4_STATIC);
|
||||
sqlite3ViewGetColumnNames(pParse, pTab);
|
||||
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
||||
const Token *pDflt;
|
||||
sqlite3VdbeAddOp(v, OP_Integer, i, 0);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, pCol->zName, 0);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0,
|
||||
pCol->zType ? pCol->zType : "", 0);
|
||||
sqlite3VdbeAddOp(v, OP_Integer, pCol->notNull, 0);
|
||||
if( pCol->pDflt && (pDflt = &pCol->pDflt->span)->z ){
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, (char*)pDflt->z, pDflt->n);
|
||||
}else{
|
||||
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
||||
if( IsHiddenColumn(pCol) ){
|
||||
nHidden++;
|
||||
continue;
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_Integer, pCol->isPrimKey, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 6, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i-nHidden, 1);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pCol->zName, 0);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
|
||||
pCol->zType ? pCol->zType : "", 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pCol->notNull, 4);
|
||||
if( pCol->pDflt && (pDflt = &pCol->pDflt->span)->z ){
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pDflt->z, pDflt->n);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pCol->isPrimKey, 6);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
|
||||
}
|
||||
}
|
||||
}else
|
||||
|
@ -566,16 +683,17 @@ void sqlite3Pragma(
|
|||
int i;
|
||||
pTab = pIdx->pTable;
|
||||
sqlite3VdbeSetNumCols(v, 3);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", P3_STATIC);
|
||||
pParse->nMem = 3;
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", P4_STATIC);
|
||||
for(i=0; i<pIdx->nColumn; i++){
|
||||
int cnum = pIdx->aiColumn[i];
|
||||
sqlite3VdbeAddOp(v, OP_Integer, i, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Integer, cnum, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2);
|
||||
assert( pTab->nCol>cnum );
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[cnum].zName, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 3, 0);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
|
||||
}
|
||||
}
|
||||
}else
|
||||
|
@ -591,14 +709,15 @@ void sqlite3Pragma(
|
|||
if( pIdx ){
|
||||
int i = 0;
|
||||
sqlite3VdbeSetNumCols(v, 3);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", P3_STATIC);
|
||||
pParse->nMem = 3;
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", P4_STATIC);
|
||||
while(pIdx){
|
||||
sqlite3VdbeAddOp(v, OP_Integer, i, 0);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, pIdx->zName, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 3, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
|
||||
++i;
|
||||
pIdx = pIdx->pNext;
|
||||
}
|
||||
|
@ -610,17 +729,18 @@ void sqlite3Pragma(
|
|||
int i;
|
||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||
sqlite3VdbeSetNumCols(v, 3);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", P3_STATIC);
|
||||
pParse->nMem = 3;
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", P4_STATIC);
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( db->aDb[i].pBt==0 ) continue;
|
||||
assert( db->aDb[i].zName!=0 );
|
||||
sqlite3VdbeAddOp(v, OP_Integer, i, 0);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, 0);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0,
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, db->aDb[i].zName, 0);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
|
||||
sqlite3BtreeGetFilename(db->aDb[i].pBt), 0);
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 3, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
|
||||
}
|
||||
}else
|
||||
|
||||
|
@ -628,13 +748,14 @@ void sqlite3Pragma(
|
|||
int i = 0;
|
||||
HashElem *p;
|
||||
sqlite3VdbeSetNumCols(v, 2);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC);
|
||||
pParse->nMem = 2;
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC);
|
||||
for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){
|
||||
CollSeq *pColl = (CollSeq *)sqliteHashData(p);
|
||||
sqlite3VdbeAddOp(v, OP_Integer, i++, 0);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, pColl->zName, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 2, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i++, 1);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pColl->zName, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
|
||||
}
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */
|
||||
|
@ -651,22 +772,23 @@ void sqlite3Pragma(
|
|||
if( pFK ){
|
||||
int i = 0;
|
||||
sqlite3VdbeSetNumCols(v, 5);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", P3_STATIC);
|
||||
pParse->nMem = 5;
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", P4_STATIC);
|
||||
while(pFK){
|
||||
int j;
|
||||
for(j=0; j<pFK->nCol; j++){
|
||||
char *zCol = pFK->aCol[j].zCol;
|
||||
sqlite3VdbeAddOp(v, OP_Integer, i, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Integer, j, 0);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, pFK->zTo, 0);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0,
|
||||
pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
|
||||
sqlite3VdbeOp3(v, zCol ? OP_String8 : OP_Null, 0, 0, zCol, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 5, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, j, 2);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pFK->zTo, 0);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0,
|
||||
pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
|
||||
sqlite3VdbeAddOp4(v, zCol ? OP_String8 : OP_Null, 0, 5, 0, zCol, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5);
|
||||
}
|
||||
++i;
|
||||
pFK = pFK->pNextFrom;
|
||||
|
@ -678,7 +800,6 @@ void sqlite3Pragma(
|
|||
|
||||
#ifndef NDEBUG
|
||||
if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
|
||||
extern void sqlite3ParserTrace(FILE*, char *);
|
||||
if( zRight ){
|
||||
if( getBoolean(zRight) ){
|
||||
sqlite3ParserTrace(stderr, "parser: ");
|
||||
|
@ -703,7 +824,13 @@ void sqlite3Pragma(
|
|||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){
|
||||
/* Pragma "quick_check" is an experimental reduced version of
|
||||
** integrity_check designed to detect most database corruption
|
||||
** without most of the overhead of a full integrity-check.
|
||||
*/
|
||||
if( sqlite3StrICmp(zLeft, "integrity_check")==0
|
||||
|| sqlite3StrICmp(zLeft, "quick_check")==0
|
||||
){
|
||||
int i, j, addr, mxErr;
|
||||
|
||||
/* Code that appears at the end of the integrity check. If no error
|
||||
|
@ -711,17 +838,19 @@ void sqlite3Pragma(
|
|||
** error message
|
||||
*/
|
||||
static const VdbeOpList endCode[] = {
|
||||
{ OP_MemLoad, 0, 0, 0},
|
||||
{ OP_Integer, 0, 0, 0},
|
||||
{ OP_Ne, 0, 0, 0}, /* 2 */
|
||||
{ OP_String8, 0, 0, "ok"},
|
||||
{ OP_Callback, 1, 0, 0},
|
||||
{ OP_AddImm, 1, 0, 0}, /* 0 */
|
||||
{ OP_IfNeg, 1, 0, 0}, /* 1 */
|
||||
{ OP_String8, 0, 3, 0}, /* 2 */
|
||||
{ OP_ResultRow, 3, 1, 0},
|
||||
};
|
||||
|
||||
int isQuick = (zLeft[0]=='q');
|
||||
|
||||
/* Initialize the VDBE program */
|
||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||
pParse->nMem = 6;
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", P4_STATIC);
|
||||
|
||||
/* Set the maximum error count */
|
||||
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
|
||||
|
@ -731,7 +860,7 @@ void sqlite3Pragma(
|
|||
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_MemInt, mxErr, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */
|
||||
|
||||
/* Do an integrity check on each database file */
|
||||
for(i=0; i<db->nDb; i++){
|
||||
|
@ -742,100 +871,115 @@ void sqlite3Pragma(
|
|||
if( OMIT_TEMPDB && i==1 ) continue;
|
||||
|
||||
sqlite3CodeVerifySchema(pParse, i);
|
||||
addr = sqlite3VdbeAddOp(v, OP_IfMemPos, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */
|
||||
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
|
||||
/* Do an integrity check of the B-Tree
|
||||
**
|
||||
** Begin by filling registers 2, 3, ... with the root pages numbers
|
||||
** for all tables and indices in the database.
|
||||
*/
|
||||
pTbls = &db->aDb[i].pSchema->tblHash;
|
||||
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
||||
Table *pTab = sqliteHashData(x);
|
||||
Index *pIdx;
|
||||
sqlite3VdbeAddOp(v, OP_Integer, pTab->tnum, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt);
|
||||
cnt++;
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
sqlite3VdbeAddOp(v, OP_Integer, pIdx->tnum, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 2+cnt);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
if( cnt==0 ) continue;
|
||||
sqlite3VdbeAddOp(v, OP_IntegrityCk, 0, i);
|
||||
addr = sqlite3VdbeAddOp(v, OP_IsNull, -1, 0);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0,
|
||||
sqlite3MPrintf("*** in database %s ***\n", db->aDb[i].zName),
|
||||
P3_DYNAMIC);
|
||||
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Concat, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
|
||||
|
||||
/* Make sure sufficient number of registers have been allocated */
|
||||
if( pParse->nMem < cnt+3 ){
|
||||
pParse->nMem = cnt+3;
|
||||
}
|
||||
|
||||
/* Do the b-tree integrity checks */
|
||||
sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1);
|
||||
sqlite3VdbeChangeP5(v, i);
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
|
||||
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
|
||||
P4_DYNAMIC);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 2);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
|
||||
/* Make sure all the indices are constructed correctly.
|
||||
*/
|
||||
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
||||
for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){
|
||||
Table *pTab = sqliteHashData(x);
|
||||
Index *pIdx;
|
||||
int loopTop;
|
||||
|
||||
if( pTab->pIndex==0 ) continue;
|
||||
addr = sqlite3VdbeAddOp(v, OP_IfMemPos, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */
|
||||
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
|
||||
sqlite3VdbeAddOp(v, OP_MemInt, 0, 1);
|
||||
loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, 1, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, 2); /* reg(2) will count entries */
|
||||
loopTop = sqlite3VdbeAddOp2(v, OP_Rewind, 1, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, 2, 1); /* increment entry count */
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
int jmp2;
|
||||
static const VdbeOpList idxErr[] = {
|
||||
{ OP_MemIncr, -1, 0, 0},
|
||||
{ OP_String8, 0, 0, "rowid "},
|
||||
{ OP_Rowid, 1, 0, 0},
|
||||
{ OP_String8, 0, 0, " missing from index "},
|
||||
{ OP_String8, 0, 0, 0}, /* 4 */
|
||||
{ OP_Concat, 2, 0, 0},
|
||||
{ OP_Callback, 1, 0, 0},
|
||||
{ OP_AddImm, 1, -1, 0},
|
||||
{ OP_String8, 0, 3, 0}, /* 1 */
|
||||
{ OP_Rowid, 1, 4, 0},
|
||||
{ OP_String8, 0, 5, 0}, /* 3 */
|
||||
{ OP_String8, 0, 6, 0}, /* 4 */
|
||||
{ OP_Concat, 4, 3, 3},
|
||||
{ OP_Concat, 5, 3, 3},
|
||||
{ OP_Concat, 6, 3, 3},
|
||||
{ OP_ResultRow, 3, 1, 0},
|
||||
};
|
||||
sqlite3GenerateIndexKey(v, pIdx, 1);
|
||||
jmp2 = sqlite3VdbeAddOp(v, OP_Found, j+2, 0);
|
||||
sqlite3GenerateIndexKey(pParse, pIdx, 1, 3);
|
||||
jmp2 = sqlite3VdbeAddOp3(v, OP_Found, j+2, 0, 3);
|
||||
addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
|
||||
sqlite3VdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
|
||||
sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC);
|
||||
sqlite3VdbeChangeP4(v, addr+3, " missing from index ", P4_STATIC);
|
||||
sqlite3VdbeChangeP4(v, addr+4, pIdx->zName, P4_STATIC);
|
||||
sqlite3VdbeJumpHere(v, jmp2);
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_Next, 1, loopTop+1);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop+1);
|
||||
sqlite3VdbeJumpHere(v, loopTop);
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
static const VdbeOpList cntIdx[] = {
|
||||
{ OP_MemInt, 0, 2, 0},
|
||||
{ OP_Integer, 0, 3, 0},
|
||||
{ OP_Rewind, 0, 0, 0}, /* 1 */
|
||||
{ OP_MemIncr, 1, 2, 0},
|
||||
{ OP_AddImm, 3, 1, 0},
|
||||
{ OP_Next, 0, 0, 0}, /* 3 */
|
||||
{ OP_MemLoad, 1, 0, 0},
|
||||
{ OP_MemLoad, 2, 0, 0},
|
||||
{ OP_Eq, 0, 0, 0}, /* 6 */
|
||||
{ OP_MemIncr, -1, 0, 0},
|
||||
{ OP_String8, 0, 0, "wrong # of entries in index "},
|
||||
{ OP_String8, 0, 0, 0}, /* 9 */
|
||||
{ OP_Concat, 0, 0, 0},
|
||||
{ OP_Callback, 1, 0, 0},
|
||||
{ OP_Eq, 2, 0, 3}, /* 4 */
|
||||
{ OP_AddImm, 1, -1, 0},
|
||||
{ OP_String8, 0, 2, 0}, /* 6 */
|
||||
{ OP_String8, 0, 3, 0}, /* 7 */
|
||||
{ OP_Concat, 3, 2, 2},
|
||||
{ OP_ResultRow, 2, 1, 0},
|
||||
};
|
||||
if( pIdx->tnum==0 ) continue;
|
||||
addr = sqlite3VdbeAddOp(v, OP_IfMemPos, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
|
||||
sqlite3VdbeChangeP1(v, addr+1, j+2);
|
||||
sqlite3VdbeChangeP2(v, addr+1, addr+4);
|
||||
sqlite3VdbeChangeP1(v, addr+3, j+2);
|
||||
sqlite3VdbeChangeP2(v, addr+3, addr+2);
|
||||
sqlite3VdbeJumpHere(v, addr+6);
|
||||
sqlite3VdbeChangeP3(v, addr+9, pIdx->zName, P3_STATIC);
|
||||
sqlite3VdbeJumpHere(v, addr+4);
|
||||
sqlite3VdbeChangeP4(v, addr+6,
|
||||
"wrong # of entries in index ", P4_STATIC);
|
||||
sqlite3VdbeChangeP4(v, addr+7, pIdx->zName, P4_STATIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
|
||||
sqlite3VdbeChangeP1(v, addr+1, mxErr);
|
||||
sqlite3VdbeJumpHere(v, addr+2);
|
||||
sqlite3VdbeChangeP2(v, addr, -mxErr);
|
||||
sqlite3VdbeJumpHere(v, addr+1);
|
||||
sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC);
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||
|
||||
|
@ -844,7 +988,7 @@ void sqlite3Pragma(
|
|||
** PRAGMA encoding
|
||||
** PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be"
|
||||
**
|
||||
** In it's first form, this pragma returns the encoding of the main
|
||||
** In its first form, this pragma returns the encoding of the main
|
||||
** database. If the database is not initialized, it is initialized now.
|
||||
**
|
||||
** The second form of this pragma is a no-op if the main database file
|
||||
|
@ -881,15 +1025,15 @@ void sqlite3Pragma(
|
|||
if( !zRight ){ /* "PRAGMA encoding" */
|
||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", P3_STATIC);
|
||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", P4_STATIC);
|
||||
sqlite3VdbeAddOp2(v, OP_String8, 0, 1);
|
||||
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
|
||||
if( pEnc->enc==ENC(pParse->db) ){
|
||||
sqlite3VdbeChangeP3(v, -1, pEnc->zName, P3_STATIC);
|
||||
sqlite3VdbeChangeP4(v, -1, pEnc->zName, P4_STATIC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
|
||||
}else{ /* "PRAGMA encoding = XXX" */
|
||||
/* Only change the value of sqlite.enc if the database handle is not
|
||||
** initialized. If the main database exists, the new sqlite.enc value
|
||||
|
@ -940,22 +1084,33 @@ void sqlite3Pragma(
|
|||
** The user-version is not used internally by SQLite. It may be used by
|
||||
** applications for any purpose.
|
||||
*/
|
||||
if( sqlite3StrICmp(zLeft, "schema_version")==0 ||
|
||||
sqlite3StrICmp(zLeft, "user_version")==0 ){
|
||||
if( sqlite3StrICmp(zLeft, "schema_version")==0
|
||||
|| sqlite3StrICmp(zLeft, "user_version")==0
|
||||
|| sqlite3StrICmp(zLeft, "freelist_count")==0
|
||||
){
|
||||
|
||||
int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */
|
||||
if( zLeft[0]=='s' || zLeft[0]=='S' ){
|
||||
iCookie = 0;
|
||||
}else{
|
||||
iCookie = 5;
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
switch( zLeft[0] ){
|
||||
case 's': case 'S':
|
||||
iCookie = 0;
|
||||
break;
|
||||
case 'f': case 'F':
|
||||
iCookie = 1;
|
||||
iDb = (-1*(iDb+1));
|
||||
assert(iDb<=0);
|
||||
break;
|
||||
default:
|
||||
iCookie = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
if( zRight ){
|
||||
if( zRight && iDb>=0 ){
|
||||
/* Write the specified cookie value */
|
||||
static const VdbeOpList setCookie[] = {
|
||||
{ OP_Transaction, 0, 1, 0}, /* 0 */
|
||||
{ OP_Integer, 0, 0, 0}, /* 1 */
|
||||
{ OP_SetCookie, 0, 0, 0}, /* 2 */
|
||||
{ OP_Integer, 0, 1, 0}, /* 1 */
|
||||
{ OP_SetCookie, 0, 0, 1}, /* 2 */
|
||||
};
|
||||
int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie);
|
||||
sqlite3VdbeChangeP1(v, addr, iDb);
|
||||
|
@ -965,14 +1120,14 @@ void sqlite3Pragma(
|
|||
}else{
|
||||
/* Read the specified cookie value */
|
||||
static const VdbeOpList readCookie[] = {
|
||||
{ OP_ReadCookie, 0, 0, 0}, /* 0 */
|
||||
{ OP_Callback, 1, 0, 0}
|
||||
{ OP_ReadCookie, 0, 1, 0}, /* 0 */
|
||||
{ OP_ResultRow, 1, 1, 0}
|
||||
};
|
||||
int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie);
|
||||
sqlite3VdbeChangeP1(v, addr, iDb);
|
||||
sqlite3VdbeChangeP2(v, addr, iCookie);
|
||||
sqlite3VdbeChangeP3(v, addr, iCookie);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, P3_TRANSIENT);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, P4_TRANSIENT);
|
||||
}
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
|
||||
|
@ -988,22 +1143,25 @@ void sqlite3Pragma(
|
|||
int i;
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
sqlite3VdbeSetNumCols(v, 2);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", P3_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", P3_STATIC);
|
||||
pParse->nMem = 2;
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", P4_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", P4_STATIC);
|
||||
for(i=0; i<db->nDb; i++){
|
||||
Btree *pBt;
|
||||
Pager *pPager;
|
||||
const char *zState = "unknown";
|
||||
int j;
|
||||
if( db->aDb[i].zName==0 ) continue;
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, P3_STATIC);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC);
|
||||
pBt = db->aDb[i].pBt;
|
||||
if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, "closed", P3_STATIC);
|
||||
}else{
|
||||
int j = sqlite3PagerLockstate(pPager);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0,
|
||||
(j>=0 && j<=4) ? azLockName[j] : "unknown", P3_STATIC);
|
||||
zState = "closed";
|
||||
}else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0,
|
||||
SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
|
||||
zState = azLockName[j];
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 2, 0);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
|
||||
}
|
||||
}else
|
||||
#endif
|
||||
|
@ -1048,7 +1206,7 @@ void sqlite3Pragma(
|
|||
** the VDBE implementing the pragma to expire. Most (all?) pragmas
|
||||
** are only valid for a single execution.
|
||||
*/
|
||||
sqlite3VdbeAddOp(v, OP_Expire, 1, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Expire, 1, 0);
|
||||
|
||||
/*
|
||||
** Reset the safety level, in case the fullfsync flag or synchronous
|
||||
|
@ -1062,8 +1220,8 @@ void sqlite3Pragma(
|
|||
#endif
|
||||
}
|
||||
pragma_out:
|
||||
sqliteFree(zLeft);
|
||||
sqliteFree(zRight);
|
||||
sqlite3_free(zLeft);
|
||||
sqlite3_free(zRight);
|
||||
}
|
||||
|
||||
#endif /* SQLITE_OMIT_PRAGMA || SQLITE_OMIT_PARSER */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue