зеркало из https://github.com/mozilla/pjs.git
Update to sqlite 3.2.1, r=me
This commit is contained in:
Родитель
2297a8a082
Коммит
9cdb31d07c
|
@ -48,7 +48,7 @@ LIBRARY_NAME = sqlite3_s
|
|||
MODULE_NAME = sqlite3
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
VERSION = 3.2.0
|
||||
VERSION = 3.2.1
|
||||
|
||||
EXPORTS = sqlite3.h
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
** This file contains C code routines that used to generate VDBE code
|
||||
** that implements the ALTER TABLE command.
|
||||
**
|
||||
** $Id: alter.c,v 1.1 2005-03-22 23:10:06 vladimir%pobox.com Exp $
|
||||
** $Id: alter.c,v 1.2 2005-03-30 21:49:20 vladimir%pobox.com Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
|
@ -449,7 +449,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
|
|||
}
|
||||
sqlite3NestedParse(pParse,
|
||||
"UPDATE %Q.%s SET "
|
||||
"sql = substr(sql,0,%d) || ', ' || %Q || substr(sql,%d,length(sql)) "
|
||||
"sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d,length(sql)) "
|
||||
"WHERE type = 'table' AND name = %Q",
|
||||
zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
|
||||
zTab
|
||||
|
@ -521,7 +521,9 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
|
|||
if( !pNew ) goto exit_begin_add_column;
|
||||
pParse->pNewTable = pNew;
|
||||
pNew->nCol = pTab->nCol;
|
||||
nAlloc = ((pNew->nCol)/8)+8;
|
||||
assert( pNew->nCol>0 );
|
||||
nAlloc = (((pNew->nCol-1)/8)*8)+8;
|
||||
assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
|
||||
pNew->aCol = (Column *)sqliteMalloc(sizeof(Column)*nAlloc);
|
||||
pNew->zName = sqliteStrDup(pTab->zName);
|
||||
if( !pNew->aCol || !pNew->zName ){
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.253 2005/03/21 04:04:02 danielk1977 Exp $
|
||||
** $Id: btree.c,v 1.256 2005/03/29 13:17:46 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
|
@ -3757,7 +3757,8 @@ static int balance_quick(MemPage *pPage, MemPage *pParent){
|
|||
static int balance_nonroot(MemPage *pPage){
|
||||
MemPage *pParent; /* The parent of pPage */
|
||||
Btree *pBt; /* The whole database */
|
||||
int nCell = 0; /* Number of cells in aCell[] */
|
||||
int nCell = 0; /* Number of cells in apCell[] */
|
||||
int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */
|
||||
int nOld; /* Number of pages in apOld[] */
|
||||
int nNew; /* Number of pages in apNew[] */
|
||||
int nDiv; /* Number of cells in apDiv[] */
|
||||
|
@ -3771,7 +3772,6 @@ static int balance_nonroot(MemPage *pPage){
|
|||
int pageFlags; /* Value of pPage->aData[0] */
|
||||
int subtotal; /* Subtotal of bytes in cells on one page */
|
||||
int iSpace = 0; /* First unused byte of aSpace[] */
|
||||
int mxCellPerPage; /* Maximum number of cells in one page */
|
||||
MemPage *apOld[NB]; /* pPage and up to two siblings */
|
||||
Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */
|
||||
MemPage *apCopy[NB]; /* Private copies of apOld[] pages */
|
||||
|
@ -3781,7 +3781,7 @@ static int balance_nonroot(MemPage *pPage){
|
|||
u8 *apDiv[NB]; /* Divider cells in pParent */
|
||||
int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */
|
||||
int szNew[NB+2]; /* Combined size of cells place on i-th page */
|
||||
u8 **apCell; /* All cells begin balanced */
|
||||
u8 **apCell = 0; /* All cells begin balanced */
|
||||
int *szCell; /* Local size of all cells in apCell[] */
|
||||
u8 *aCopy[NB]; /* Space for holding data of apCopy[] */
|
||||
u8 *aSpace; /* Space to hold copies of dividers cells */
|
||||
|
@ -3825,31 +3825,6 @@ static int balance_nonroot(MemPage *pPage){
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Allocate space for memory structures
|
||||
*/
|
||||
mxCellPerPage = MX_CELL(pBt);
|
||||
apCell = sqliteMallocRaw(
|
||||
(mxCellPerPage+2)*NB*(sizeof(u8*)+sizeof(int))
|
||||
+ sizeof(MemPage)*NB
|
||||
+ pBt->psAligned*(5+NB)
|
||||
+ (ISAUTOVACUUM ? (mxCellPerPage+2)*NN*2 : 0)
|
||||
);
|
||||
if( apCell==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
szCell = (int*)&apCell[(mxCellPerPage+2)*NB];
|
||||
aCopy[0] = (u8*)&szCell[(mxCellPerPage+2)*NB];
|
||||
for(i=1; i<NB; i++){
|
||||
aCopy[i] = &aCopy[i-1][pBt->psAligned+sizeof(MemPage)];
|
||||
}
|
||||
aSpace = &aCopy[NB-1][pBt->psAligned+sizeof(MemPage)];
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum ){
|
||||
aFrom = &aSpace[5*pBt->psAligned];
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Find the cell in the parent page whose left child points back
|
||||
** to pPage. The "idx" variable is the index of that cell. If pPage
|
||||
|
@ -3910,8 +3885,35 @@ static int balance_nonroot(MemPage *pPage){
|
|||
apCopy[i] = 0;
|
||||
assert( i==nOld );
|
||||
nOld++;
|
||||
nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate space for memory structures
|
||||
*/
|
||||
apCell = sqliteMallocRaw(
|
||||
nMaxCells*sizeof(u8*) /* apCell */
|
||||
+ nMaxCells*sizeof(int) /* szCell */
|
||||
+ sizeof(MemPage)*NB /* aCopy */
|
||||
+ pBt->psAligned*(5+NB) /* aSpace */
|
||||
+ (ISAUTOVACUUM ? nMaxCells : 0) /* aFrom */
|
||||
);
|
||||
if( apCell==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto balance_cleanup;
|
||||
}
|
||||
szCell = (int*)&apCell[nMaxCells];
|
||||
aCopy[0] = (u8*)&szCell[nMaxCells];
|
||||
for(i=1; i<NB; i++){
|
||||
aCopy[i] = &aCopy[i-1][pBt->psAligned+sizeof(MemPage)];
|
||||
}
|
||||
aSpace = &aCopy[NB-1][pBt->psAligned+sizeof(MemPage)];
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum ){
|
||||
aFrom = &aSpace[5*pBt->psAligned];
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Make copies of the content of pPage and its siblings into aOld[].
|
||||
** The rest of this function will use data from the copies rather
|
||||
|
@ -3948,6 +3950,7 @@ static int balance_nonroot(MemPage *pPage){
|
|||
MemPage *pOld = apCopy[i];
|
||||
int limit = pOld->nCell+pOld->nOverflow;
|
||||
for(j=0; j<limit; j++){
|
||||
assert( nCell<nMaxCells );
|
||||
apCell[nCell] = findOverflowCell(pOld, j);
|
||||
szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
|
@ -3975,6 +3978,7 @@ static int balance_nonroot(MemPage *pPage){
|
|||
dropCell(pParent, nxDiv, sz);
|
||||
}else{
|
||||
u8 *pTemp;
|
||||
assert( nCell<nMaxCells );
|
||||
szCell[nCell] = sz;
|
||||
pTemp = &aSpace[iSpace];
|
||||
iSpace += sz;
|
||||
|
@ -4020,6 +4024,7 @@ static int balance_nonroot(MemPage *pPage){
|
|||
*/
|
||||
usableSpace = pBt->usableSize - 12 + leafCorrection;
|
||||
for(subtotal=k=i=0; i<nCell; i++){
|
||||
assert( i<nMaxCells );
|
||||
subtotal += szCell[i] + 2;
|
||||
if( subtotal > usableSpace ){
|
||||
szNew[k] = subtotal - szCell[i];
|
||||
|
@ -4051,6 +4056,8 @@ static int balance_nonroot(MemPage *pPage){
|
|||
|
||||
r = cntNew[i-1] - 1;
|
||||
d = r + 1 - leafData;
|
||||
assert( d<nMaxCells );
|
||||
assert( r<nMaxCells );
|
||||
while( szRight==0 || szRight+szCell[d]+2<=szLeft-(szCell[r]+2) ){
|
||||
szRight += szCell[d] + 2;
|
||||
szLeft -= szCell[r] + 2;
|
||||
|
@ -4147,6 +4154,7 @@ static int balance_nonroot(MemPage *pPage){
|
|||
for(i=0; i<nNew; i++){
|
||||
/* Assemble the new sibling page. */
|
||||
MemPage *pNew = apNew[i];
|
||||
assert( j<nMaxCells );
|
||||
assert( pNew->pgno==pgnoNew[i] );
|
||||
assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]);
|
||||
assert( pNew->nCell>0 );
|
||||
|
@ -4160,6 +4168,7 @@ static int balance_nonroot(MemPage *pPage){
|
|||
*/
|
||||
if( pBt->autoVacuum ){
|
||||
for(k=j; k<cntNew[i]; k++){
|
||||
assert( k<nMaxCells );
|
||||
if( aFrom[k]==0xFF || apCopy[aFrom[k]]->pgno!=pNew->pgno ){
|
||||
rc = ptrmapPutOvfl(pNew, k-j);
|
||||
if( rc!=SQLITE_OK ){
|
||||
|
@ -4179,6 +4188,8 @@ static int balance_nonroot(MemPage *pPage){
|
|||
u8 *pCell;
|
||||
u8 *pTemp;
|
||||
int sz;
|
||||
|
||||
assert( j<nMaxCells );
|
||||
pCell = apCell[j];
|
||||
sz = szCell[j] + leafCorrection;
|
||||
if( !pNew->leaf ){
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
** COMMIT
|
||||
** ROLLBACK
|
||||
**
|
||||
** $Id: build.c,v 1.316 2005/03/21 03:53:38 danielk1977 Exp $
|
||||
** $Id: build.c,v 1.318 2005/03/29 03:10:59 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
|
@ -168,7 +168,7 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
|
|||
int i;
|
||||
assert( zName!=0 );
|
||||
assert( (db->flags & SQLITE_Initialized) || db->init.busy );
|
||||
for(i=0; i<db->nDb; i++){
|
||||
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||
if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
|
||||
p = sqlite3HashFind(&db->aDb[j].tblHash, zName, strlen(zName)+1);
|
||||
|
@ -227,7 +227,7 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
|
|||
Index *p = 0;
|
||||
int i;
|
||||
assert( (db->flags & SQLITE_Initialized) || db->init.busy );
|
||||
for(i=0; i<db->nDb; i++){
|
||||
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||
if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue;
|
||||
p = sqlite3HashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1);
|
||||
|
@ -393,12 +393,14 @@ static void sqliteResetColumnNames(Table *pTable){
|
|||
int i;
|
||||
Column *pCol;
|
||||
assert( pTable!=0 );
|
||||
for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){
|
||||
sqliteFree(pCol->zName);
|
||||
sqlite3ExprDelete(pCol->pDflt);
|
||||
sqliteFree(pCol->zType);
|
||||
if( (pCol = pTable->aCol)!=0 ){
|
||||
for(i=0; i<pTable->nCol; i++, pCol++){
|
||||
sqliteFree(pCol->zName);
|
||||
sqlite3ExprDelete(pCol->pDflt);
|
||||
sqliteFree(pCol->zType);
|
||||
}
|
||||
sqliteFree(pTable->aCol);
|
||||
}
|
||||
sqliteFree(pTable->aCol);
|
||||
pTable->aCol = 0;
|
||||
pTable->nCol = 0;
|
||||
}
|
||||
|
@ -535,7 +537,8 @@ static int findDb(sqlite3 *db, Token *pName){
|
|||
if( zName ){
|
||||
n = strlen(zName);
|
||||
for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
|
||||
if( n==strlen(pDb->zName) && 0==sqlite3StrICmp(pDb->zName, zName) ){
|
||||
if( (!OMIT_TEMPDB || i!=1 ) && n==strlen(pDb->zName) &&
|
||||
0==sqlite3StrICmp(pDb->zName, zName) ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -654,12 +657,12 @@ void sqlite3StartTable(
|
|||
*/
|
||||
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
|
||||
if( iDb<0 ) return;
|
||||
if( isTemp && iDb>1 ){
|
||||
if( !OMIT_TEMPDB && isTemp && iDb>1 ){
|
||||
/* If creating a temp table, the name may not be qualified */
|
||||
sqlite3ErrorMsg(pParse, "temporary table name must be unqualified");
|
||||
return;
|
||||
}
|
||||
if( isTemp ) iDb = 1;
|
||||
if( !OMIT_TEMPDB && isTemp ) iDb = 1;
|
||||
|
||||
pParse->sNameToken = *pName;
|
||||
zName = sqlite3NameFromToken(pName);
|
||||
|
@ -677,13 +680,13 @@ void sqlite3StartTable(
|
|||
goto begin_table_error;
|
||||
}
|
||||
if( isView ){
|
||||
if( isTemp ){
|
||||
if( !OMIT_TEMPDB && isTemp ){
|
||||
code = SQLITE_CREATE_TEMP_VIEW;
|
||||
}else{
|
||||
code = SQLITE_CREATE_VIEW;
|
||||
}
|
||||
}else{
|
||||
if( isTemp ){
|
||||
if( !OMIT_TEMPDB && isTemp ){
|
||||
code = SQLITE_CREATE_TEMP_TABLE;
|
||||
}else{
|
||||
code = SQLITE_CREATE_TABLE;
|
||||
|
@ -1374,7 +1377,7 @@ static char *createTableStmt(Table *p){
|
|||
n += 35 + 6*p->nCol;
|
||||
zStmt = sqliteMallocRaw( n );
|
||||
if( zStmt==0 ) return 0;
|
||||
strcpy(zStmt, p->iDb==1 ? "CREATE TEMP TABLE " : "CREATE TABLE ");
|
||||
strcpy(zStmt, !OMIT_TEMPDB&&p->iDb==1 ? "CREATE TEMP TABLE ":"CREATE TABLE ");
|
||||
k = strlen(zStmt);
|
||||
identPut(zStmt, &k, p->zName);
|
||||
zStmt[k++] = '(';
|
||||
|
@ -1863,13 +1866,13 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
|
|||
goto exit_drop_table;
|
||||
}
|
||||
if( isView ){
|
||||
if( iDb==1 ){
|
||||
if( !OMIT_TEMPDB && iDb==1 ){
|
||||
code = SQLITE_DROP_TEMP_VIEW;
|
||||
}else{
|
||||
code = SQLITE_DROP_VIEW;
|
||||
}
|
||||
}else{
|
||||
if( iDb==1 ){
|
||||
if( !OMIT_TEMPDB && iDb==1 ){
|
||||
code = SQLITE_DROP_TEMP_TABLE;
|
||||
}else{
|
||||
code = SQLITE_DROP_TABLE;
|
||||
|
@ -2187,7 +2190,6 @@ void sqlite3CreateIndex(
|
|||
int i, j;
|
||||
Token nullId; /* Fake token for an empty ID list */
|
||||
DbFixer sFix; /* For assigning database names to pTable */
|
||||
int isTemp; /* True for a temporary index */
|
||||
sqlite3 *db = pParse->db;
|
||||
|
||||
int iDb; /* Index of the database that is being written */
|
||||
|
@ -2208,6 +2210,7 @@ void sqlite3CreateIndex(
|
|||
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
|
||||
if( iDb<0 ) goto exit_create_index;
|
||||
|
||||
#ifndef SQLITE_OMIT_TEMPDB
|
||||
/* If the index name was unqualified, check if the the table
|
||||
** is a temp table. If so, set the database to 1.
|
||||
*/
|
||||
|
@ -2215,6 +2218,7 @@ void sqlite3CreateIndex(
|
|||
if( pName2 && pName2->n==0 && pTab && pTab->iDb==1 ){
|
||||
iDb = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
|
||||
sqlite3FixSrcList(&sFix, pTblName)
|
||||
|
@ -2242,7 +2246,6 @@ void sqlite3CreateIndex(
|
|||
goto exit_create_index;
|
||||
}
|
||||
#endif
|
||||
isTemp = pTab->iDb==1;
|
||||
|
||||
/*
|
||||
** Find the name of the index. Make sure there is not already another
|
||||
|
@ -2292,12 +2295,12 @@ void sqlite3CreateIndex(
|
|||
*/
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
{
|
||||
const char *zDb = db->aDb[pTab->iDb].zName;
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
|
||||
const char *zDb = db->aDb[iDb].zName;
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){
|
||||
goto exit_create_index;
|
||||
}
|
||||
i = SQLITE_CREATE_INDEX;
|
||||
if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
|
||||
if( !OMIT_TEMPDB && iDb==1 ) i = SQLITE_CREATE_TEMP_INDEX;
|
||||
if( sqlite3AuthCheck(pParse, i, zName, pTab->zName, zDb) ){
|
||||
goto exit_create_index;
|
||||
}
|
||||
|
@ -2560,7 +2563,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){
|
|||
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
|
||||
goto exit_drop_index;
|
||||
}
|
||||
if( pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX;
|
||||
if( !OMIT_TEMPDB && pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX;
|
||||
if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
|
||||
goto exit_drop_index;
|
||||
}
|
||||
|
@ -2868,7 +2871,7 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
|
|||
if( (pParse->cookieMask & mask)==0 ){
|
||||
pParse->cookieMask |= mask;
|
||||
pParse->cookieValue[iDb] = db->aDb[iDb].schema_cookie;
|
||||
if( iDb==1 ){
|
||||
if( !OMIT_TEMPDB && iDb==1 ){
|
||||
sqlite3OpenTempDatabase(pParse);
|
||||
}
|
||||
}
|
||||
|
@ -2901,7 +2904,7 @@ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
|
|||
if( setStatement && pParse->nested==0 ){
|
||||
sqlite3VdbeAddOp(v, OP_Statement, iDb, 0);
|
||||
}
|
||||
if( iDb!=1 && pParse->db->aDb[1].pBt!=0 ){
|
||||
if( (OMIT_TEMPDB || iDb!=1) && pParse->db->aDb[1].pBt!=0 ){
|
||||
sqlite3BeginWriteOperation(pParse, setStatement, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
** other files are for internal use by SQLite and should not be
|
||||
** accessed by users of the library.
|
||||
**
|
||||
** $Id: main.c,v 1.283 2005/03/21 04:04:03 danielk1977 Exp $
|
||||
** $Id: main.c,v 1.284 2005/03/29 03:10:59 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
|
@ -133,7 +133,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
|||
int meta[10];
|
||||
InitData initData;
|
||||
char const *zMasterSchema;
|
||||
char const *zMasterName;
|
||||
char const *zMasterName = SCHEMA_TABLE(iDb);
|
||||
|
||||
/*
|
||||
** The master database table has a structure like this
|
||||
|
@ -147,6 +147,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
|||
" sql text\n"
|
||||
")"
|
||||
;
|
||||
#ifndef SQLITE_OMIT_TEMPDB
|
||||
static const char temp_master_schema[] =
|
||||
"CREATE TEMP TABLE sqlite_temp_master(\n"
|
||||
" type text,\n"
|
||||
|
@ -156,6 +157,9 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
|||
" sql text\n"
|
||||
")"
|
||||
;
|
||||
#else
|
||||
#define temp_master_schema 0
|
||||
#endif
|
||||
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
|
||||
|
@ -163,13 +167,12 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
|||
** and initialisation script appropriate for the database being
|
||||
** initialised. zMasterName is the name of the master table.
|
||||
*/
|
||||
if( iDb==1 ){
|
||||
if( !OMIT_TEMPDB && iDb==1 ){
|
||||
zMasterSchema = temp_master_schema;
|
||||
zMasterName = TEMP_MASTER_NAME;
|
||||
}else{
|
||||
zMasterSchema = master_schema;
|
||||
zMasterName = MASTER_NAME;
|
||||
}
|
||||
zMasterName = SCHEMA_TABLE(iDb);
|
||||
|
||||
/* Construct the schema tables. */
|
||||
sqlite3SafetyOff(db);
|
||||
|
@ -195,7 +198,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
|||
/* Create a cursor to hold the database open
|
||||
*/
|
||||
if( db->aDb[iDb].pBt==0 ){
|
||||
if( iDb==1 ) DbSetProperty(db, 1, DB_SchemaLoaded);
|
||||
if( !OMIT_TEMPDB && iDb==1 ) DbSetProperty(db, 1, DB_SchemaLoaded);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
rc = sqlite3BtreeCursor(db->aDb[iDb].pBt, MASTER_ROOT, 0, 0, 0, &curMain);
|
||||
|
@ -351,12 +354,14 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
|
|||
** for the TEMP database. This is loaded last, as the TEMP database
|
||||
** schema may contain references to objects in other databases.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_TEMPDB
|
||||
if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
|
||||
rc = sqlite3InitOne(db, 1, pzErrMsg);
|
||||
if( rc ){
|
||||
sqlite3ResetInternalSchema(db, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
db->init.busy = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
|
@ -1205,13 +1210,17 @@ static int openDatabase(
|
|||
db->magic = SQLITE_MAGIC_CLOSED;
|
||||
goto opendb_out;
|
||||
}
|
||||
db->aDb[0].zName = "main";
|
||||
db->aDb[1].zName = "temp";
|
||||
|
||||
/* The default safety_level for the main database is 'full' for the temp
|
||||
** database it is 'NONE'. This matches the pager layer defaults. */
|
||||
/* The default safety_level for the main database is 'full'; for the temp
|
||||
** database it is 'NONE'. This matches the pager layer defaults.
|
||||
*/
|
||||
db->aDb[0].zName = "main";
|
||||
db->aDb[0].safety_level = 3;
|
||||
#ifndef SQLITE_OMIT_TEMPDB
|
||||
db->aDb[1].zName = "temp";
|
||||
db->aDb[1].safety_level = 1;
|
||||
#endif
|
||||
|
||||
|
||||
/* Register all built-in functions, but do not attempt to read the
|
||||
** database schema yet. This is delayed until the first time the database
|
||||
|
|
|
@ -133,3 +133,14 @@
|
|||
#define OP_NotUsed_127 127
|
||||
#define OP_NotUsed_128 128
|
||||
#define OP_NotUsed_129 129
|
||||
|
||||
#define NOPUSH_MASK_0 65144
|
||||
#define NOPUSH_MASK_1 59007
|
||||
#define NOPUSH_MASK_2 63483
|
||||
#define NOPUSH_MASK_3 48975
|
||||
#define NOPUSH_MASK_4 65535
|
||||
#define NOPUSH_MASK_5 52991
|
||||
#define NOPUSH_MASK_6 60410
|
||||
#define NOPUSH_MASK_7 32421
|
||||
#define NOPUSH_MASK_8 0
|
||||
#define NOPUSH_MASK_9 0
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
** file simultaneously, or one process from reading the database while
|
||||
** another is writing.
|
||||
**
|
||||
** @(#) $Id: pager.c,v 1.198 2005/03/21 04:04:02 danielk1977 Exp $
|
||||
** @(#) $Id: pager.c,v 1.201 2005/03/28 18:04:28 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
|
@ -213,9 +213,16 @@ struct PgHistory {
|
|||
|
||||
/*
|
||||
** How big to make the hash table used for locating in-memory pages
|
||||
** by page number.
|
||||
** by page number. This macro looks a little silly, but is evaluated
|
||||
** at compile-time, not run-time (at least for gcc this is true).
|
||||
*/
|
||||
#define N_PG_HASH 2048
|
||||
#define N_PG_HASH (\
|
||||
(MAX_PAGES>1024)?2048: \
|
||||
(MAX_PAGES>512)?1024: \
|
||||
(MAX_PAGES>256)?512: \
|
||||
(MAX_PAGES>128)?256: \
|
||||
(MAX_PAGES>64)?128:64 \
|
||||
)
|
||||
|
||||
/*
|
||||
** Hash a page number
|
||||
|
@ -906,6 +913,7 @@ static int pager_unwritelock(Pager *pPager){
|
|||
pPager->dirtyCache = 0;
|
||||
pPager->nRec = 0;
|
||||
}else{
|
||||
assert( pPager->aInJournal==0 );
|
||||
assert( pPager->dirtyCache==0 || pPager->useJournal==0 );
|
||||
}
|
||||
rc = sqlite3OsUnlock(&pPager->fd, SHARED_LOCK);
|
||||
|
@ -1978,6 +1986,7 @@ int sqlite3pager_close(Pager *pPager){
|
|||
if( pPager->journalOpen ){
|
||||
sqlite3OsClose(&pPager->jfd);
|
||||
}
|
||||
sqliteFree(pPager->aInJournal);
|
||||
if( pPager->stmtOpen ){
|
||||
sqlite3OsClose(&pPager->stfd);
|
||||
}
|
||||
|
@ -2611,6 +2620,7 @@ static int pager_open_journal(Pager *pPager){
|
|||
assert( pPager->state>=PAGER_RESERVED );
|
||||
assert( pPager->journalOpen==0 );
|
||||
assert( pPager->useJournal );
|
||||
assert( pPager->aInJournal==0 );
|
||||
sqlite3pager_pagecount(pPager);
|
||||
pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 );
|
||||
if( pPager->aInJournal==0 ){
|
||||
|
@ -2634,7 +2644,7 @@ static int pager_open_journal(Pager *pPager){
|
|||
pPager->nRec = 0;
|
||||
if( pPager->errMask!=0 ){
|
||||
rc = pager_errcode(pPager);
|
||||
return rc;
|
||||
goto failed_to_open_journal;
|
||||
}
|
||||
pPager->origDbSize = pPager->dbSize;
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -11,7 +11,7 @@
|
|||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
**
|
||||
** $Id: pragma.c,v 1.90 2005/02/26 18:10:44 drh Exp $
|
||||
** $Id: pragma.c,v 1.91 2005/03/29 03:10:59 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
|
@ -645,6 +645,8 @@ void sqlite3Pragma(
|
|||
HashElem *x;
|
||||
int cnt = 0;
|
||||
|
||||
if( OMIT_TEMPDB && i==1 ) continue;
|
||||
|
||||
sqlite3CodeVerifySchema(pParse, i);
|
||||
|
||||
/* Do an integrity check of the B-Tree
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
** This file contains C code routines that are called by the parser
|
||||
** to handle SELECT statements in SQLite.
|
||||
**
|
||||
** $Id: select.c,v 1.242 2005/03/21 03:53:38 danielk1977 Exp $
|
||||
** $Id: select.c,v 1.243 2005/03/28 03:39:56 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
@ -890,7 +890,11 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
|
|||
zName = sqlite3MPrintf("column%d", i+1);
|
||||
}
|
||||
sqlite3Dequote(zName);
|
||||
if( sqlite3_malloc_failed ) return 0;
|
||||
if( sqlite3_malloc_failed ){
|
||||
sqliteFree(zName);
|
||||
sqlite3DeleteTable(0, pTab);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure the column name is unique. If the name is not unique,
|
||||
** append a integer to the name so that it becomes unique.
|
||||
|
@ -900,6 +904,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
|
|||
if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
|
||||
zName = sqlite3MPrintf("%s:%d", zBasename, ++cnt);
|
||||
j = -1;
|
||||
if( zName==0 ) break;
|
||||
}
|
||||
}
|
||||
if( zBasename!=zName ){
|
||||
|
|
|
@ -686,6 +686,20 @@ const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
|
|||
*/
|
||||
int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
|
||||
|
||||
/*
|
||||
** Given a wildcard parameter name, return the set of indexes of the
|
||||
** variables with that name. If there are no variables with the given
|
||||
** name, return 0. Otherwise, return the number of indexes returned
|
||||
** in *pIndexes. The array should be freed with
|
||||
** sqlite3_free_parameter_indexes.
|
||||
*/
|
||||
int sqlite3_bind_parameter_indexes(
|
||||
sqlite3_stmt *pStmt,
|
||||
const char *zName,
|
||||
int **pIndexes
|
||||
);
|
||||
void sqlite3_free_parameter_indexes(int *pIndexes);
|
||||
|
||||
/*
|
||||
** Set all the parameters in the compiled SQL statement to NULL.
|
||||
**
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.374 2005/03/21 04:04:03 danielk1977 Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.375 2005/03/29 03:10:59 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
|
@ -67,6 +67,17 @@
|
|||
# define TEMP_PAGES 500
|
||||
#endif
|
||||
|
||||
/*
|
||||
** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0
|
||||
** afterward. Having this macro allows us to cause the C compiler
|
||||
** to omit code used by TEMP tables without messy #ifndef statements.
|
||||
*/
|
||||
#ifdef SQLITE_OMIT_TEMPDB
|
||||
#define OMIT_TEMPDB 1
|
||||
#else
|
||||
#define OMIT_TEMPDB 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** If the following macro is set to 1, then NULL values are considered
|
||||
** distinct for the SELECT DISTINCT statement and for UNION or EXCEPT
|
||||
|
@ -292,7 +303,7 @@ extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */
|
|||
/*
|
||||
** The name of the schema table.
|
||||
*/
|
||||
#define SCHEMA_TABLE(x) (x==1?TEMP_MASTER_NAME:MASTER_NAME)
|
||||
#define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME)
|
||||
|
||||
/*
|
||||
** A convenience macro that returns the number of elements in
|
||||
|
|
|
@ -197,9 +197,9 @@ void sqlite3FinishTrigger(
|
|||
sqlite3 *db = pParse->db; /* The database */
|
||||
DbFixer sFix;
|
||||
|
||||
if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup;
|
||||
pTrig = pParse->pNewTrigger;
|
||||
pParse->pNewTrigger = 0;
|
||||
if( pParse->nErr || pTrig==0 ) goto triggerfinish_cleanup;
|
||||
pTrig->step_list = pStepList;
|
||||
while( pStepList ){
|
||||
pStepList->pTrig = pTrig;
|
||||
|
@ -439,7 +439,7 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName){
|
|||
zDb = pName->a[0].zDatabase;
|
||||
zName = pName->a[0].zName;
|
||||
nName = strlen(zName);
|
||||
for(i=0; i<db->nDb; i++){
|
||||
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||
if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue;
|
||||
pTrigger = sqlite3HashFind(&(db->aDb[j].trigHash), zName, nName+1);
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
** in this file for details. If in doubt, do not deviate from existing
|
||||
** commenting and indentation practices when changing or adding code.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.460 2005/03/21 03:53:38 danielk1977 Exp $
|
||||
** $Id: vdbe.c,v 1.463 2005/03/29 13:07:00 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
|
@ -462,6 +462,9 @@ int sqlite3VdbeExec(
|
|||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
int nProgressOps = 0; /* Opcodes executed since progress callback. */
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
Mem *pStackLimit;
|
||||
#endif
|
||||
|
||||
if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
|
||||
assert( db->magic==SQLITE_MAGIC_BUSY );
|
||||
|
@ -533,6 +536,23 @@ int sqlite3VdbeExec(
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* This is to check that the return value of static function
|
||||
** opcodeNoPush() (see vdbeaux.c) returns values that match the
|
||||
** implementation of the virtual machine in this file. If
|
||||
** opcodeNoPush() returns non-zero, then the stack is guarenteed
|
||||
** not to grow when the opcode is executed. If it returns zero, then
|
||||
** the stack may grow by at most 1.
|
||||
**
|
||||
** The global wrapper function sqlite3VdbeOpcodeUsesStack() is not
|
||||
** available if NDEBUG is defined at build time.
|
||||
*/
|
||||
pStackLimit = pTos;
|
||||
if( !sqlite3VdbeOpcodeNoPush(pOp->opcode) ){
|
||||
pStackLimit++;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch( pOp->opcode ){
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -553,6 +573,11 @@ int sqlite3VdbeExec(
|
|||
** case statement is followed by a comment of the form "/# same as ... #/"
|
||||
** that comment is used to determine the particular value of the opcode.
|
||||
**
|
||||
** If a comment on the same line as the "case OP_" construction contains
|
||||
** the word "no-push", then the opcode is guarenteed not to grow the
|
||||
** vdbe stack when it is executed. See function opcode() in
|
||||
** vdbeaux.c for details.
|
||||
**
|
||||
** Documentation about VDBE opcodes is generated by scanning this file
|
||||
** for lines of that contain "Opcode:". That line and all subsequent
|
||||
** comment lines are used in the generation of the opcode.html documentation
|
||||
|
@ -572,7 +597,7 @@ int sqlite3VdbeExec(
|
|||
** the one at index P2 from the beginning of
|
||||
** the program.
|
||||
*/
|
||||
case OP_Goto: {
|
||||
case OP_Goto: { /* no-push */
|
||||
CHECK_FOR_INTERRUPT;
|
||||
pc = pOp->p2 - 1;
|
||||
break;
|
||||
|
@ -588,7 +613,7 @@ case OP_Goto: {
|
|||
** the return address stack will fill up and processing will abort
|
||||
** with a fatal error.
|
||||
*/
|
||||
case OP_Gosub: {
|
||||
case OP_Gosub: { /* no-push */
|
||||
assert( p->returnDepth<sizeof(p->returnStack)/sizeof(p->returnStack[0]) );
|
||||
p->returnStack[p->returnDepth++] = pc+1;
|
||||
pc = pOp->p2 - 1;
|
||||
|
@ -601,7 +626,7 @@ case OP_Gosub: {
|
|||
** OP_Gosub. If an OP_Return has occurred for all OP_Gosubs, then
|
||||
** processing aborts with a fatal error.
|
||||
*/
|
||||
case OP_Return: {
|
||||
case OP_Return: { /* no-push */
|
||||
assert( p->returnDepth>0 );
|
||||
p->returnDepth--;
|
||||
pc = p->returnStack[p->returnDepth] - 1;
|
||||
|
@ -625,7 +650,7 @@ case OP_Return: {
|
|||
** every program. So a jump past the last instruction of the program
|
||||
** is the same as executing Halt.
|
||||
*/
|
||||
case OP_Halt: {
|
||||
case OP_Halt: { /* no-push */
|
||||
p->pTos = pTos;
|
||||
p->rc = pOp->p1;
|
||||
p->pc = pc;
|
||||
|
@ -671,7 +696,7 @@ case OP_Integer: {
|
|||
**
|
||||
** The string value P3 is converted to a real and pushed on to the stack.
|
||||
*/
|
||||
case OP_Real: { /* same as TK_FLOAT */
|
||||
case OP_Real: { /* same as TK_FLOAT, */
|
||||
pTos++;
|
||||
pTos->flags = MEM_Str|MEM_Static|MEM_Term;
|
||||
pTos->z = pOp->p3;
|
||||
|
@ -807,7 +832,7 @@ case OP_Variable: {
|
|||
**
|
||||
** P1 elements are popped off of the top of stack and discarded.
|
||||
*/
|
||||
case OP_Pop: {
|
||||
case OP_Pop: { /* no-push */
|
||||
assert( pOp->p1>=0 );
|
||||
popStack(&pTos, pOp->p1);
|
||||
assert( pTos>=&p->aStack[-1] );
|
||||
|
@ -850,7 +875,7 @@ case OP_Dup: {
|
|||
**
|
||||
** See also the Dup instruction.
|
||||
*/
|
||||
case OP_Pull: {
|
||||
case OP_Pull: { /* no-push */
|
||||
Mem *pFrom = &pTos[-pOp->p1];
|
||||
int i;
|
||||
Mem ts;
|
||||
|
@ -882,7 +907,7 @@ case OP_Pull: {
|
|||
** stack (P1==0 is the top of the stack) with the value
|
||||
** of the top of the stack. Then pop the top of the stack.
|
||||
*/
|
||||
case OP_Push: {
|
||||
case OP_Push: { /* no-push */
|
||||
Mem *pTo = &pTos[-pOp->p1];
|
||||
|
||||
assert( pTo>=p->aStack );
|
||||
|
@ -897,7 +922,7 @@ case OP_Push: {
|
|||
** invoke the callback function using the newly formed array as the
|
||||
** 3rd parameter.
|
||||
*/
|
||||
case OP_Callback: {
|
||||
case OP_Callback: { /* no-push */
|
||||
int i;
|
||||
assert( p->nResColumn==pOp->p1 );
|
||||
|
||||
|
@ -1033,11 +1058,11 @@ case OP_Concat: { /* same as TK_CONCAT */
|
|||
** function before the division. Division by zero returns NULL.
|
||||
** If either operand is NULL, the result is NULL.
|
||||
*/
|
||||
case OP_Add: /* same as TK_PLUS */
|
||||
case OP_Subtract: /* same as TK_MINUS */
|
||||
case OP_Multiply: /* same as TK_STAR */
|
||||
case OP_Divide: /* same as TK_SLASH */
|
||||
case OP_Remainder: { /* same as TK_REM */
|
||||
case OP_Add: /* same as TK_PLUS, no-push */
|
||||
case OP_Subtract: /* same as TK_MINUS, no-push */
|
||||
case OP_Multiply: /* same as TK_STAR, no-push */
|
||||
case OP_Divide: /* same as TK_SLASH, no-push */
|
||||
case OP_Remainder: { /* same as TK_REM, no-push */
|
||||
Mem *pNos = &pTos[-1];
|
||||
assert( pNos>=p->aStack );
|
||||
if( ((pTos->flags | pNos->flags) & MEM_Null)!=0 ){
|
||||
|
@ -1117,7 +1142,7 @@ divide_by_zero:
|
|||
** to retrieve the collation sequence set by this opcode is not available
|
||||
** publicly, only to user functions defined in func.c.
|
||||
*/
|
||||
case OP_CollSeq: {
|
||||
case OP_CollSeq: { /* no-push */
|
||||
assert( pOp->p3type==P3_COLLSEQ );
|
||||
break;
|
||||
}
|
||||
|
@ -1235,10 +1260,10 @@ case OP_Function: {
|
|||
** right by N bits where N is the top element on the stack.
|
||||
** If either operand is NULL, the result is NULL.
|
||||
*/
|
||||
case OP_BitAnd: /* same as TK_BITAND */
|
||||
case OP_BitOr: /* same as TK_BITOR */
|
||||
case OP_ShiftLeft: /* same as TK_LSHIFT */
|
||||
case OP_ShiftRight: { /* same as TK_RSHIFT */
|
||||
case OP_BitAnd: /* same as TK_BITAND, no-push */
|
||||
case OP_BitOr: /* same as TK_BITOR, no-push */
|
||||
case OP_ShiftLeft: /* same as TK_LSHIFT, no-push */
|
||||
case OP_ShiftRight: { /* same as TK_RSHIFT, no-push */
|
||||
Mem *pNos = &pTos[-1];
|
||||
int a, b;
|
||||
|
||||
|
@ -1273,7 +1298,7 @@ case OP_ShiftRight: { /* same as TK_RSHIFT */
|
|||
**
|
||||
** To force the top of the stack to be an integer, just add 0.
|
||||
*/
|
||||
case OP_AddImm: {
|
||||
case OP_AddImm: { /* no-push */
|
||||
assert( pTos>=p->aStack );
|
||||
Integerify(pTos);
|
||||
pTos->i += pOp->p1;
|
||||
|
@ -1290,7 +1315,7 @@ case OP_AddImm: {
|
|||
** current value if P1==0, or to the least integer that is strictly
|
||||
** greater than its current value if P1==1.
|
||||
*/
|
||||
case OP_ForceInt: {
|
||||
case OP_ForceInt: { /* no-push */
|
||||
int v;
|
||||
assert( pTos>=p->aStack );
|
||||
applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc);
|
||||
|
@ -1325,7 +1350,7 @@ case OP_ForceInt: {
|
|||
** P1 is 1, then the stack is popped. In all other cases, the depth
|
||||
** of the stack is unchanged.
|
||||
*/
|
||||
case OP_MustBeInt: {
|
||||
case OP_MustBeInt: { /* no-push */
|
||||
assert( pTos>=p->aStack );
|
||||
applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc);
|
||||
if( (pTos->flags & MEM_Int)==0 ){
|
||||
|
@ -1400,12 +1425,12 @@ case OP_MustBeInt: {
|
|||
** the 2nd element down on the stack is greater than or equal to the
|
||||
** top of the stack. See the Eq opcode for additional information.
|
||||
*/
|
||||
case OP_Eq: /* same as TK_EQ */
|
||||
case OP_Ne: /* same as TK_NE */
|
||||
case OP_Lt: /* same as TK_LT */
|
||||
case OP_Le: /* same as TK_LE */
|
||||
case OP_Gt: /* same as TK_GT */
|
||||
case OP_Ge: { /* same as TK_GE */
|
||||
case OP_Eq: /* same as TK_EQ, no-push */
|
||||
case OP_Ne: /* same as TK_NE, no-push */
|
||||
case OP_Lt: /* same as TK_LT, no-push */
|
||||
case OP_Le: /* same as TK_LE, no-push */
|
||||
case OP_Gt: /* same as TK_GT, no-push */
|
||||
case OP_Ge: { /* same as TK_GE, no-push */
|
||||
Mem *pNos;
|
||||
int flags;
|
||||
int res;
|
||||
|
@ -1471,8 +1496,8 @@ case OP_Ge: { /* same as TK_GE */
|
|||
** two values and push the resulting boolean value back onto the
|
||||
** stack.
|
||||
*/
|
||||
case OP_And: /* same as TK_AND */
|
||||
case OP_Or: { /* same as TK_OR */
|
||||
case OP_And: /* same as TK_AND, no-push */
|
||||
case OP_Or: { /* same as TK_OR, no-push */
|
||||
Mem *pNos = &pTos[-1];
|
||||
int v1, v2; /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */
|
||||
|
||||
|
@ -1519,7 +1544,7 @@ case OP_Or: { /* same as TK_OR */
|
|||
** with its absolute value. If the top of the stack is NULL
|
||||
** its value is unchanged.
|
||||
*/
|
||||
case OP_Negative: /* same as TK_UMINUS */
|
||||
case OP_Negative: /* same as TK_UMINUS, no-push */
|
||||
case OP_AbsValue: {
|
||||
assert( pTos>=p->aStack );
|
||||
if( pTos->flags & MEM_Real ){
|
||||
|
@ -1552,7 +1577,7 @@ case OP_AbsValue: {
|
|||
** with its complement. If the top of the stack is NULL its value
|
||||
** is unchanged.
|
||||
*/
|
||||
case OP_Not: { /* same as TK_NOT */
|
||||
case OP_Not: { /* same as TK_NOT, no-push */
|
||||
assert( pTos>=p->aStack );
|
||||
if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
|
||||
Integerify(pTos);
|
||||
|
@ -1568,7 +1593,7 @@ case OP_Not: { /* same as TK_NOT */
|
|||
** with its ones-complement. If the top of the stack is NULL its
|
||||
** value is unchanged.
|
||||
*/
|
||||
case OP_BitNot: { /* same as TK_BITNOT */
|
||||
case OP_BitNot: { /* same as TK_BITNOT, no-push */
|
||||
assert( pTos>=p->aStack );
|
||||
if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
|
||||
Integerify(pTos);
|
||||
|
@ -1583,7 +1608,7 @@ case OP_BitNot: { /* same as TK_BITNOT */
|
|||
** Do nothing. This instruction is often useful as a jump
|
||||
** destination.
|
||||
*/
|
||||
case OP_Noop: {
|
||||
case OP_Noop: { /* no-push */
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1607,8 +1632,8 @@ case OP_Noop: {
|
|||
** If the value popped of the stack is NULL, then take the jump if P1
|
||||
** is true and fall through if P1 is false.
|
||||
*/
|
||||
case OP_If:
|
||||
case OP_IfNot: {
|
||||
case OP_If: /* no-push */
|
||||
case OP_IfNot: { /* no-push */
|
||||
int c;
|
||||
assert( pTos>=p->aStack );
|
||||
if( pTos->flags & MEM_Null ){
|
||||
|
@ -1629,7 +1654,7 @@ case OP_IfNot: {
|
|||
** to P2. Pop the stack P1 times if P1>0. If P1<0 leave the stack
|
||||
** unchanged.
|
||||
*/
|
||||
case OP_IsNull: { /* same as TK_ISNULL */
|
||||
case OP_IsNull: { /* same as TK_ISNULL, no-push */
|
||||
int i, cnt;
|
||||
Mem *pTerm;
|
||||
cnt = pOp->p1;
|
||||
|
@ -1652,7 +1677,7 @@ case OP_IsNull: { /* same as TK_ISNULL */
|
|||
** stack if P1 times if P1 is greater than zero. If P1 is less than
|
||||
** zero then leave the stack unchanged.
|
||||
*/
|
||||
case OP_NotNull: { /* same as TK_NOTNULL */
|
||||
case OP_NotNull: { /* same as TK_NOTNULL, no-push */
|
||||
int i, cnt;
|
||||
cnt = pOp->p1;
|
||||
if( cnt<0 ) cnt = -cnt;
|
||||
|
@ -1673,7 +1698,7 @@ case OP_NotNull: { /* same as TK_NOTNULL */
|
|||
** If OP_KeyAsData is to be applied to cursor P1, it must be executed
|
||||
** before this op-code.
|
||||
*/
|
||||
case OP_SetNumColumns: {
|
||||
case OP_SetNumColumns: { /* no-push */
|
||||
Cursor *pC;
|
||||
assert( (pOp->p1)<p->nCursor );
|
||||
assert( p->apCsr[pOp->p1]!=0 );
|
||||
|
@ -2131,7 +2156,7 @@ case OP_MakeRecord: {
|
|||
** database file has an index of 0 and the file used for temporary tables
|
||||
** has an index of 1.
|
||||
*/
|
||||
case OP_Statement: {
|
||||
case OP_Statement: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Btree *pBt;
|
||||
if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt) && !(db->autoCommit) ){
|
||||
|
@ -2151,7 +2176,7 @@ case OP_Statement: {
|
|||
**
|
||||
** This instruction causes the VM to halt.
|
||||
*/
|
||||
case OP_AutoCommit: {
|
||||
case OP_AutoCommit: { /* no-push */
|
||||
u8 i = pOp->p1;
|
||||
u8 rollback = pOp->p2;
|
||||
|
||||
|
@ -2212,7 +2237,7 @@ case OP_AutoCommit: {
|
|||
**
|
||||
** If P2 is zero, then a read-lock is obtained on the database file.
|
||||
*/
|
||||
case OP_Transaction: {
|
||||
case OP_Transaction: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Btree *pBt;
|
||||
|
||||
|
@ -2275,7 +2300,7 @@ case OP_ReadCookie: {
|
|||
**
|
||||
** A transaction must be started before executing this opcode.
|
||||
*/
|
||||
case OP_SetCookie: {
|
||||
case OP_SetCookie: { /* no-push */
|
||||
Db *pDb;
|
||||
assert( pOp->p2<SQLITE_N_BTREE_META );
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
|
@ -2311,7 +2336,7 @@ case OP_SetCookie: {
|
|||
** to be executed (to establish a read lock) before this opcode is
|
||||
** invoked.
|
||||
*/
|
||||
case OP_VerifyCookie: {
|
||||
case OP_VerifyCookie: { /* no-push */
|
||||
int iMeta;
|
||||
Btree *pBt;
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
|
@ -2371,8 +2396,8 @@ case OP_VerifyCookie: {
|
|||
**
|
||||
** See also OpenRead.
|
||||
*/
|
||||
case OP_OpenRead:
|
||||
case OP_OpenWrite: {
|
||||
case OP_OpenRead: /* no-push */
|
||||
case OP_OpenWrite: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
int p2 = pOp->p2;
|
||||
int wrFlag;
|
||||
|
@ -2460,7 +2485,7 @@ case OP_OpenWrite: {
|
|||
** whereas "Temporary" in the context of CREATE TABLE means for the duration
|
||||
** of the connection to the database. Same word; different meanings.
|
||||
*/
|
||||
case OP_OpenTemp: {
|
||||
case OP_OpenTemp: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pCx;
|
||||
assert( i>=0 );
|
||||
|
@ -2509,7 +2534,7 @@ case OP_OpenTemp: {
|
|||
** A pseudo-table created by this opcode is useful for holding the
|
||||
** NEW or OLD tables in a trigger.
|
||||
*/
|
||||
case OP_OpenPseudo: {
|
||||
case OP_OpenPseudo: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pCx;
|
||||
assert( i>=0 );
|
||||
|
@ -2527,7 +2552,7 @@ case OP_OpenPseudo: {
|
|||
** Close a cursor previously opened as P1. If P1 is not
|
||||
** currently open, this instruction is a no-op.
|
||||
*/
|
||||
case OP_Close: {
|
||||
case OP_Close: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
if( i>=0 && i<p->nCursor ){
|
||||
sqlite3VdbeFreeCursor(p->apCsr[i]);
|
||||
|
@ -2576,10 +2601,10 @@ case OP_Close: {
|
|||
**
|
||||
** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt
|
||||
*/
|
||||
case OP_MoveLt:
|
||||
case OP_MoveLe:
|
||||
case OP_MoveGe:
|
||||
case OP_MoveGt: {
|
||||
case OP_MoveLt: /* no-push */
|
||||
case OP_MoveLe: /* no-push */
|
||||
case OP_MoveGe: /* no-push */
|
||||
case OP_MoveGt: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
|
||||
|
@ -2688,9 +2713,9 @@ case OP_MoveGt: {
|
|||
**
|
||||
** See also: Distinct, Found, MoveTo, NotExists, IsUnique
|
||||
*/
|
||||
case OP_Distinct:
|
||||
case OP_NotFound:
|
||||
case OP_Found: {
|
||||
case OP_Distinct: /* no-push */
|
||||
case OP_NotFound: /* no-push */
|
||||
case OP_Found: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
int alreadyExists = 0;
|
||||
Cursor *pC;
|
||||
|
@ -2739,7 +2764,7 @@ case OP_Found: {
|
|||
**
|
||||
** See also: Distinct, NotFound, NotExists, Found
|
||||
*/
|
||||
case OP_IsUnique: {
|
||||
case OP_IsUnique: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Mem *pNos = &pTos[-1];
|
||||
Cursor *pCx;
|
||||
|
@ -2833,7 +2858,7 @@ case OP_IsUnique: {
|
|||
**
|
||||
** See also: Distinct, Found, MoveTo, NotFound, IsUnique
|
||||
*/
|
||||
case OP_NotExists: {
|
||||
case OP_NotExists: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
|
@ -3036,8 +3061,8 @@ case OP_NewRecno: {
|
|||
**
|
||||
** P1 may not be a pseudo-table opened using the OpenPseudo opcode.
|
||||
*/
|
||||
case OP_PutIntKey:
|
||||
case OP_PutStrKey: {
|
||||
case OP_PutIntKey: /* no-push */
|
||||
case OP_PutStrKey: { /* no-push */
|
||||
Mem *pNos = &pTos[-1];
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
|
@ -3131,7 +3156,7 @@ case OP_PutStrKey: {
|
|||
**
|
||||
** If P1 is a pseudo-table, then this instruction is a no-op.
|
||||
*/
|
||||
case OP_Delete: {
|
||||
case OP_Delete: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
assert( i>=0 && i<p->nCursor );
|
||||
|
@ -3155,7 +3180,7 @@ case OP_Delete: {
|
|||
** change counter (returned by subsequent calls to sqlite3_changes())
|
||||
** before it is reset. This is used by trigger programs.
|
||||
*/
|
||||
case OP_ResetCount: {
|
||||
case OP_ResetCount: { /* no-push */
|
||||
if( pOp->p1 ){
|
||||
sqlite3VdbeSetChanges(db, p->nChange);
|
||||
}
|
||||
|
@ -3170,7 +3195,7 @@ case OP_ResetCount: {
|
|||
** data off of the key rather than the data. This is used for
|
||||
** processing compound selects.
|
||||
*/
|
||||
case OP_KeyAsData: {
|
||||
case OP_KeyAsData: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
assert( i>=0 && i<p->nCursor );
|
||||
|
@ -3346,7 +3371,7 @@ case OP_FullKey: {
|
|||
** that occur while the cursor is on the null row will always push
|
||||
** a NULL onto the stack.
|
||||
*/
|
||||
case OP_NullRow: {
|
||||
case OP_NullRow: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
|
||||
|
@ -3366,7 +3391,7 @@ case OP_NullRow: {
|
|||
** If P2 is 0 or if the table or index is not empty, fall through
|
||||
** to the following instruction.
|
||||
*/
|
||||
case OP_Last: {
|
||||
case OP_Last: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
|
@ -3397,7 +3422,7 @@ case OP_Last: {
|
|||
** If P2 is 0 or if the table or index is not empty, fall through
|
||||
** to the following instruction.
|
||||
*/
|
||||
case OP_Rewind: {
|
||||
case OP_Rewind: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
|
@ -3437,8 +3462,8 @@ case OP_Rewind: {
|
|||
** to the following instruction. But if the cursor backup was successful,
|
||||
** jump immediately to P2.
|
||||
*/
|
||||
case OP_Prev:
|
||||
case OP_Next: {
|
||||
case OP_Prev: /* no-push */
|
||||
case OP_Next: { /* no-push */
|
||||
Cursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
|
||||
|
@ -3479,7 +3504,7 @@ case OP_Next: {
|
|||
** is rolled back. If P3 is not null, then it becomes part of the
|
||||
** error message returned with the SQLITE_CONSTRAINT.
|
||||
*/
|
||||
case OP_IdxPut: {
|
||||
case OP_IdxPut: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
|
@ -3531,7 +3556,7 @@ case OP_IdxPut: {
|
|||
** The top of the stack is an index key built using the MakeIdxKey opcode.
|
||||
** This opcode removes that entry from the index.
|
||||
*/
|
||||
case OP_IdxDelete: {
|
||||
case OP_IdxDelete: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
|
@ -3633,9 +3658,9 @@ case OP_IdxRecno: {
|
|||
** an epsilon prior to the comparison. This makes the opcode work
|
||||
** like IdxLE.
|
||||
*/
|
||||
case OP_IdxLT:
|
||||
case OP_IdxGT:
|
||||
case OP_IdxGE: {
|
||||
case OP_IdxLT: /* no-push */
|
||||
case OP_IdxGT: /* no-push */
|
||||
case OP_IdxGE: { /* no-push */
|
||||
int i= pOp->p1;
|
||||
BtCursor *pCrsr;
|
||||
Cursor *pC;
|
||||
|
@ -3679,7 +3704,7 @@ case OP_IdxGE: {
|
|||
**
|
||||
** The index entry is always popped from the stack.
|
||||
*/
|
||||
case OP_IdxIsNull: {
|
||||
case OP_IdxIsNull: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
int k, n;
|
||||
const char *z;
|
||||
|
@ -3753,7 +3778,7 @@ case OP_Destroy: {
|
|||
**
|
||||
** See also: Destroy
|
||||
*/
|
||||
case OP_Clear: {
|
||||
case OP_Clear: { /* no-push */
|
||||
rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1);
|
||||
break;
|
||||
}
|
||||
|
@ -3811,7 +3836,7 @@ case OP_CreateTable: {
|
|||
** This opcode invokes the parser to create a new virtual machine,
|
||||
** then runs the new virtual machine. It is thus a reentrant opcode.
|
||||
*/
|
||||
case OP_ParseSchema: {
|
||||
case OP_ParseSchema: { /* no-push */
|
||||
char *zSql;
|
||||
int iDb = pOp->p1;
|
||||
const char *zMaster;
|
||||
|
@ -3819,7 +3844,7 @@ case OP_ParseSchema: {
|
|||
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
if( !DbHasProperty(db, iDb, DB_SchemaLoaded) ) break;
|
||||
zMaster = iDb==1 ? TEMP_MASTER_NAME : MASTER_NAME;
|
||||
zMaster = SCHEMA_TABLE(iDb);
|
||||
initData.db = db;
|
||||
initData.pzErrMsg = &p->zErrMsg;
|
||||
zSql = sqlite3MPrintf(
|
||||
|
@ -3843,7 +3868,7 @@ case OP_ParseSchema: {
|
|||
** is dropped in order to keep the internal representation of the
|
||||
** schema consistent with what is on disk.
|
||||
*/
|
||||
case OP_DropTable: {
|
||||
case OP_DropTable: { /* no-push */
|
||||
sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p3);
|
||||
break;
|
||||
}
|
||||
|
@ -3855,7 +3880,7 @@ case OP_DropTable: {
|
|||
** is dropped in order to keep the internal representation of the
|
||||
** schema consistent with what is on disk.
|
||||
*/
|
||||
case OP_DropIndex: {
|
||||
case OP_DropIndex: { /* no-push */
|
||||
sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p3);
|
||||
break;
|
||||
}
|
||||
|
@ -3867,7 +3892,7 @@ case OP_DropIndex: {
|
|||
** is dropped in order to keep the internal representation of the
|
||||
** schema consistent with what is on disk.
|
||||
*/
|
||||
case OP_DropTrigger: {
|
||||
case OP_DropTrigger: { /* no-push */
|
||||
sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3);
|
||||
break;
|
||||
}
|
||||
|
@ -3932,7 +3957,7 @@ case OP_IntegrityCk: {
|
|||
** Write the integer on the top of the stack
|
||||
** into the temporary storage list.
|
||||
*/
|
||||
case OP_ListWrite: {
|
||||
case OP_ListWrite: { /* no-push */
|
||||
Keylist *pKeylist;
|
||||
assert( pTos>=p->aStack );
|
||||
pKeylist = p->pList;
|
||||
|
@ -3956,7 +3981,7 @@ case OP_ListWrite: {
|
|||
**
|
||||
** Rewind the temporary buffer back to the beginning.
|
||||
*/
|
||||
case OP_ListRewind: {
|
||||
case OP_ListRewind: { /* no-push */
|
||||
/* What this opcode codes, really, is reverse the order of the
|
||||
** linked list of Keylist structures so that they are read out
|
||||
** in the same order that they were read in. */
|
||||
|
@ -4003,7 +4028,7 @@ case OP_ListRead: {
|
|||
**
|
||||
** Reset the temporary storage buffer so that it holds nothing.
|
||||
*/
|
||||
case OP_ListReset: {
|
||||
case OP_ListReset: { /* no-push */
|
||||
if( p->pList ){
|
||||
sqlite3VdbeKeylistFree(p->pList);
|
||||
p->pList = 0;
|
||||
|
@ -4018,7 +4043,7 @@ case OP_ListReset: {
|
|||
** AggContextPop opcode.
|
||||
**
|
||||
*/
|
||||
case OP_AggContextPush: {
|
||||
case OP_AggContextPush: { /* no-push */
|
||||
p->pAgg++;
|
||||
assert( p->pAgg<&p->apAgg[p->nAgg] );
|
||||
break;
|
||||
|
@ -4029,7 +4054,7 @@ case OP_AggContextPush: {
|
|||
** Restore the aggregator to the state it was in when AggContextPush
|
||||
** was last called. Any data in the current aggregator is deleted.
|
||||
*/
|
||||
case OP_AggContextPop: {
|
||||
case OP_AggContextPop: { /* no-push */
|
||||
p->pAgg--;
|
||||
assert( p->pAgg>=p->apAgg );
|
||||
break;
|
||||
|
@ -4043,7 +4068,7 @@ case OP_AggContextPop: {
|
|||
** opcode. The context stores the last insert row id, the last statement change
|
||||
** count, and the current statement change count.
|
||||
*/
|
||||
case OP_ContextPush: {
|
||||
case OP_ContextPush: { /* no-push */
|
||||
int i = p->contextStackTop++;
|
||||
Context *pContext;
|
||||
|
||||
|
@ -4068,7 +4093,7 @@ case OP_ContextPush: {
|
|||
** executed. The context stores the last insert row id, the last statement
|
||||
** change count, and the current statement change count.
|
||||
*/
|
||||
case OP_ContextPop: {
|
||||
case OP_ContextPop: { /* no-push */
|
||||
Context *pContext = &p->contextStack[--p->contextStackTop];
|
||||
assert( p->contextStackTop>=0 );
|
||||
db->lastRowid = pContext->lastRowid;
|
||||
|
@ -4085,7 +4110,7 @@ case OP_ContextPop: {
|
|||
** and put them on the sorter. The key and data should have been
|
||||
** made using the MakeRecord opcode.
|
||||
*/
|
||||
case OP_SortPut: {
|
||||
case OP_SortPut: { /* no-push */
|
||||
Mem *pNos = &pTos[-1];
|
||||
Sorter *pSorter;
|
||||
assert( pNos>=p->aStack );
|
||||
|
@ -4109,7 +4134,7 @@ case OP_SortPut: {
|
|||
** mergesort. The P3 argument is a pointer to a KeyInfo structure
|
||||
** that describes the keys to be sorted.
|
||||
*/
|
||||
case OP_Sort: {
|
||||
case OP_Sort: { /* no-push */
|
||||
int i;
|
||||
KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3;
|
||||
Sorter *pElem;
|
||||
|
@ -4171,7 +4196,7 @@ case OP_SortNext: {
|
|||
**
|
||||
** Remove any elements that remain on the sorter.
|
||||
*/
|
||||
case OP_SortReset: {
|
||||
case OP_SortReset: { /* no-push */
|
||||
sqlite3VdbeSorterReset(p);
|
||||
break;
|
||||
}
|
||||
|
@ -4186,7 +4211,7 @@ case OP_SortReset: {
|
|||
** stack is popped once if P2 is 1. If P2 is zero, then
|
||||
** the original data remains on the stack.
|
||||
*/
|
||||
case OP_MemStore: {
|
||||
case OP_MemStore: { /* no-push */
|
||||
assert( pTos>=p->aStack );
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nMem );
|
||||
rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], pTos);
|
||||
|
@ -4225,7 +4250,7 @@ case OP_MemLoad: {
|
|||
** This instruction throws an error if the memory cell is not initially
|
||||
** an integer.
|
||||
*/
|
||||
case OP_MemMax: {
|
||||
case OP_MemMax: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Mem *pMem;
|
||||
assert( pTos>=p->aStack );
|
||||
|
@ -4249,7 +4274,7 @@ case OP_MemMax: {
|
|||
** This instruction throws an error if the memory cell is not initially
|
||||
** an integer.
|
||||
*/
|
||||
case OP_MemIncr: {
|
||||
case OP_MemIncr: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Mem *pMem;
|
||||
assert( i>=0 && i<p->nMem );
|
||||
|
@ -4267,7 +4292,7 @@ case OP_MemIncr: {
|
|||
** If the value of memory cell P1 is 1 or greater, jump to P2. This
|
||||
** opcode assumes that memory cell P1 holds an integer value.
|
||||
*/
|
||||
case OP_IfMemPos: {
|
||||
case OP_IfMemPos: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Mem *pMem;
|
||||
assert( i>=0 && i<p->nMem );
|
||||
|
@ -4289,7 +4314,7 @@ case OP_IfMemPos: {
|
|||
** there is no GROUP BY expression). In this case it is illegal to invoke
|
||||
** OP_AggFocus.
|
||||
*/
|
||||
case OP_AggReset: {
|
||||
case OP_AggReset: { /* no-push */
|
||||
assert( !pOp->p3 || pOp->p3type==P3_KEYINFO );
|
||||
if( pOp->p1 ){
|
||||
rc = sqlite3VdbeAggReset(0, p->pAgg, (KeyInfo *)pOp->p3);
|
||||
|
@ -4313,7 +4338,7 @@ case OP_AggReset: {
|
|||
** The aggregate will operate out of aggregate column P2.
|
||||
** P3 is a pointer to the FuncDef structure for the function.
|
||||
*/
|
||||
case OP_AggInit: {
|
||||
case OP_AggInit: { /* no-push */
|
||||
int i = pOp->p2;
|
||||
assert( i>=0 && i<p->pAgg->nMem );
|
||||
p->pAgg->apFunc[i] = (FuncDef*)pOp->p3;
|
||||
|
@ -4331,7 +4356,7 @@ case OP_AggInit: {
|
|||
** Ideally, this index would be another parameter, but there are
|
||||
** no free parameters left. The integer is popped from the stack.
|
||||
*/
|
||||
case OP_AggFunc: {
|
||||
case OP_AggFunc: { /* no-push */
|
||||
int n = pOp->p2;
|
||||
int i;
|
||||
Mem *pMem, *pRec;
|
||||
|
@ -4389,7 +4414,7 @@ case OP_AggFunc: {
|
|||
** zero or more AggNext operations. You must not execute an AggFocus
|
||||
** in between an AggNext and an AggReset.
|
||||
*/
|
||||
case OP_AggFocus: {
|
||||
case OP_AggFocus: { /* no-push */
|
||||
char *zKey;
|
||||
int nKey;
|
||||
int res;
|
||||
|
@ -4423,7 +4448,7 @@ case OP_AggFocus: {
|
|||
** Move the top of the stack into the P2-th field of the current
|
||||
** aggregate. String values are duplicated into new memory.
|
||||
*/
|
||||
case OP_AggSet: {
|
||||
case OP_AggSet: { /* no-push */
|
||||
AggElem *pFocus;
|
||||
int i = pOp->p2;
|
||||
pFocus = p->pAgg->pCurrent;
|
||||
|
@ -4488,7 +4513,7 @@ case OP_AggGet: {
|
|||
** zero or more AggNext operations. You must not execute an AggFocus
|
||||
** in between an AggNext and an AggReset.
|
||||
*/
|
||||
case OP_AggNext: {
|
||||
case OP_AggNext: { /* no-push */
|
||||
int res;
|
||||
assert( rc==SQLITE_OK );
|
||||
CHECK_FOR_INTERRUPT;
|
||||
|
@ -4549,7 +4574,7 @@ case OP_AggNext: {
|
|||
** machines to be created and run. It may not be called from within
|
||||
** a transaction.
|
||||
*/
|
||||
case OP_Vacuum: {
|
||||
case OP_Vacuum: { /* no-push */
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
rc = sqlite3RunVacuum(&p->zErrMsg, db);
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
|
@ -4565,7 +4590,7 @@ case OP_Vacuum: {
|
|||
** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
|
||||
** then only the currently executing statement is affected.
|
||||
*/
|
||||
case OP_Expire: {
|
||||
case OP_Expire: { /* no-push */
|
||||
if( !pOp->p1 ){
|
||||
sqlite3ExpirePreparedStatements(db);
|
||||
}else{
|
||||
|
@ -4592,6 +4617,9 @@ default: {
|
|||
*****************************************************************************/
|
||||
}
|
||||
|
||||
/* Make sure the stack limit was not exceeded */
|
||||
assert( pTos<=pStackLimit );
|
||||
|
||||
#ifdef VDBE_PROFILE
|
||||
{
|
||||
long long elapse = hwtime() - start;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
** or VDBE. The VDBE implements an abstract machine that runs a
|
||||
** simple program to access and modify the underlying database.
|
||||
**
|
||||
** $Id: vdbe.h,v 1.93 2005/03/09 12:26:51 danielk1977 Exp $
|
||||
** $Id: vdbe.h,v 1.94 2005/03/23 01:48:48 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITE_VDBE_H_
|
||||
#define _SQLITE_VDBE_H_
|
||||
|
@ -78,7 +78,7 @@ typedef struct VdbeOpList VdbeOpList;
|
|||
** from a single sqliteMalloc(). But no copy is made and the calling
|
||||
** function should *not* try to free the KeyInfo.
|
||||
*/
|
||||
#define P3_KEYINFO_HANDOFF (-7)
|
||||
#define P3_KEYINFO_HANDOFF (-9)
|
||||
|
||||
/*
|
||||
** The following macro converts a relative address in the p2 field
|
||||
|
|
|
@ -406,6 +406,7 @@ int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
|
|||
void sqlite3VdbeMemRelease(Mem *p);
|
||||
#ifndef NDEBUG
|
||||
void sqlite3VdbeMemSanity(Mem*, u8);
|
||||
int sqlite3VdbeOpcodeNoPush(u8);
|
||||
#endif
|
||||
int sqlite3VdbeMemTranslate(Mem*, u8);
|
||||
void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf);
|
||||
|
|
|
@ -622,3 +622,15 @@ int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sqlite3_bind_parameter_indexes(
|
||||
sqlite3_stmt *pStmt,
|
||||
const char *zName,
|
||||
int **pIndexes
|
||||
){
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sqlite3_free_parameter_indexes(int *pIndexes)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -57,10 +57,16 @@ void sqlite3VdbeTrace(Vdbe *p, FILE *trace){
|
|||
|
||||
/*
|
||||
** Resize the Vdbe.aOp array so that it contains at least N
|
||||
** elements. If the Vdbe is in VDBE_MAGIC_RUN state, then
|
||||
** the Vdbe.aOp array will be sized to contain exactly N
|
||||
** elements.
|
||||
*/
|
||||
static void resizeOpArray(Vdbe *p, int N){
|
||||
if( p->nOpAlloc<N ){
|
||||
if( p->magic==VDBE_MAGIC_RUN ){
|
||||
assert( N==p->nOp );
|
||||
p->nOpAlloc = N;
|
||||
p->aOp = sqliteRealloc(p->aOp, N*sizeof(Op));
|
||||
}else if( p->nOpAlloc<N ){
|
||||
int oldSize = p->nOpAlloc;
|
||||
p->nOpAlloc = N+100;
|
||||
p->aOp = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op));
|
||||
|
@ -160,25 +166,92 @@ void sqlite3VdbeResolveLabel(Vdbe *p, int x){
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return non-zero if opcode 'op' is guarenteed not to push more values
|
||||
** onto the VDBE stack than it pops off.
|
||||
*/
|
||||
static int opcodeNoPush(u8 op){
|
||||
/* The 10 NOPUSH_MASK_n constants are defined in the automatically
|
||||
** generated header file opcodes.h. Each is a 16-bit bitmask, one
|
||||
** bit corresponding to each opcode implemented by the virtual
|
||||
** machine in vdbe.c. The bit is true if the word "no-push" appears
|
||||
** in a comment on the same line as the "case OP_XXX:" in
|
||||
** sqlite3VdbeExec() in vdbe.c.
|
||||
**
|
||||
** If the bit is true, then the corresponding opcode is guarenteed not
|
||||
** to grow the stack when it is executed. Otherwise, it may grow the
|
||||
** stack by at most one entry.
|
||||
**
|
||||
** NOPUSH_MASK_0 corresponds to opcodes 0 to 15. NOPUSH_MASK_1 contains
|
||||
** one bit for opcodes 16 to 31, and so on.
|
||||
**
|
||||
** 16-bit bitmasks (rather than 32-bit) are specified in opcodes.h
|
||||
** because the file is generated by an awk program. Awk manipulates
|
||||
** all numbers as floating-point and we don't want to risk a rounding
|
||||
** error if someone builds with an awk that uses (for example) 32-bit
|
||||
** IEEE floats.
|
||||
*/
|
||||
static u32 masks[5] = {
|
||||
NOPUSH_MASK_0 + (NOPUSH_MASK_1<<16),
|
||||
NOPUSH_MASK_2 + (NOPUSH_MASK_3<<16),
|
||||
NOPUSH_MASK_4 + (NOPUSH_MASK_5<<16),
|
||||
NOPUSH_MASK_6 + (NOPUSH_MASK_7<<16),
|
||||
NOPUSH_MASK_8 + (NOPUSH_MASK_9<<16)
|
||||
};
|
||||
return (masks[op>>5] & (1<<(op&0x1F)));
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
int sqlite3VdbeOpcodeNoPush(u8 op){
|
||||
return opcodeNoPush(op);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Loop through the program looking for P2 values that are negative.
|
||||
** Each such value is a label. Resolve the label by setting the P2
|
||||
** value to its correct non-zero value.
|
||||
**
|
||||
** This routine is called once after all opcodes have been inserted.
|
||||
**
|
||||
** Variable *pMaxFuncArgs is set to the maximum value of any P1 argument
|
||||
** to an OP_Function or P2 to an OP_AggFunc opcode. This is used by
|
||||
** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array.
|
||||
**
|
||||
** The integer *pMaxStack is set to the maximum number of vdbe stack
|
||||
** entries that static analysis reveals this program might need.
|
||||
*/
|
||||
static void resolveP2Values(Vdbe *p){
|
||||
static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
|
||||
int i;
|
||||
int nMaxArgs = 0;
|
||||
int nMaxStack = p->nOp;
|
||||
Op *pOp;
|
||||
int *aLabel = p->aLabel;
|
||||
if( aLabel==0 ) return;
|
||||
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
|
||||
u8 opcode = pOp->opcode;
|
||||
|
||||
/* Todo: Maybe OP_AggFunc should change to use P1 in the same
|
||||
* way as OP_Function.
|
||||
*/
|
||||
if( opcode==OP_Function ){
|
||||
if( pOp->p1>nMaxArgs ) nMaxArgs = pOp->p1;
|
||||
}else if( opcode==OP_AggFunc ){
|
||||
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
|
||||
}
|
||||
|
||||
if( opcodeNoPush(opcode) ){
|
||||
nMaxStack--;
|
||||
}
|
||||
|
||||
if( pOp->p2>=0 ) continue;
|
||||
assert( -1-pOp->p2<p->nLabel );
|
||||
pOp->p2 = aLabel[-1-pOp->p2];
|
||||
}
|
||||
sqliteFree(p->aLabel);
|
||||
p->aLabel = 0;
|
||||
|
||||
*pMaxFuncArgs = nMaxArgs;
|
||||
*pMaxStack = nMaxStack;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -603,6 +676,13 @@ void sqlite3VdbeMakeReady(
|
|||
*/
|
||||
assert( p->nOp>0 );
|
||||
|
||||
/* Set the magic to VDBE_MAGIC_RUN sooner rather than later. This
|
||||
* is because the call to resizeOpArray() below may shrink the
|
||||
* p->aOp[] array to save memory if called when in VDBE_MAGIC_RUN
|
||||
* state.
|
||||
*/
|
||||
p->magic = VDBE_MAGIC_RUN;
|
||||
|
||||
/* No instruction ever pushes more than a single element onto the
|
||||
** stack. And the stack never grows on successive executions of the
|
||||
** same loop. So the total number of instructions is an upper bound
|
||||
|
@ -611,12 +691,16 @@ void sqlite3VdbeMakeReady(
|
|||
** Allocation all the stack space we will ever need.
|
||||
*/
|
||||
if( p->aStack==0 ){
|
||||
resolveP2Values(p);
|
||||
int nArg; /* Maximum number of args passed to a user function. */
|
||||
int nStack; /* Maximum number of stack entries required */
|
||||
resolveP2Values(p, &nArg, &nStack);
|
||||
resizeOpArray(p, p->nOp);
|
||||
assert( nVar>=0 );
|
||||
n = isExplain ? 10 : p->nOp;
|
||||
assert( nStack<p->nOp );
|
||||
nStack = isExplain ? 10 : nStack;
|
||||
p->aStack = sqliteMalloc(
|
||||
n*sizeof(p->aStack[0]) /* aStack */
|
||||
+ n*sizeof(Mem*) /* apArg */
|
||||
nStack*sizeof(p->aStack[0]) /* aStack */
|
||||
+ nArg*sizeof(Mem*) /* apArg */
|
||||
+ nVar*sizeof(Mem) /* aVar */
|
||||
+ nVar*sizeof(char*) /* azVar */
|
||||
+ nMem*sizeof(Mem) /* aMem */
|
||||
|
@ -624,13 +708,13 @@ void sqlite3VdbeMakeReady(
|
|||
+ nAgg*sizeof(Agg) /* Aggregate contexts */
|
||||
);
|
||||
if( !sqlite3_malloc_failed ){
|
||||
p->aMem = &p->aStack[n];
|
||||
p->aMem = &p->aStack[nStack];
|
||||
p->nMem = nMem;
|
||||
p->aVar = &p->aMem[nMem];
|
||||
p->nVar = nVar;
|
||||
p->okVar = 0;
|
||||
p->apArg = (Mem**)&p->aVar[nVar];
|
||||
p->azVar = (char**)&p->apArg[n];
|
||||
p->azVar = (char**)&p->apArg[nArg];
|
||||
p->apCsr = (Cursor**)&p->azVar[nVar];
|
||||
if( nAgg>0 ){
|
||||
p->nAgg = nAgg;
|
||||
|
|
Загрузка…
Ссылка в новой задаче