This commit is contained in:
vladimir%pobox.com 2005-03-30 21:49:20 +00:00
Родитель 2297a8a082
Коммит 9cdb31d07c
18 изменённых файлов: 575 добавлений и 372 удалений

Просмотреть файл

@ -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;