1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-14 00:22:38 +03:00

Merge the latest trunk changes into the sessions branch.

FossilOrigin-Name: 4c5e276c902e0b93cfc05bf2e1db966ecdac0ed0
This commit is contained in:
drh
2011-06-20 10:44:10 +00:00
74 changed files with 5921 additions and 2271 deletions

View File

@@ -157,13 +157,6 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
pOp->p3 = p3;
pOp->p4.p = 0;
pOp->p4type = P4_NOTUSED;
p->expired = 0;
if( op==OP_ParseSchema ){
/* Any program that uses the OP_ParseSchema opcode needs to lock
** all btrees. */
int j;
for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
}
#ifdef SQLITE_DEBUG
pOp->zComment = 0;
if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
@@ -202,6 +195,20 @@ int sqlite3VdbeAddOp4(
return addr;
}
/*
** Add an OP_ParseSchema opcode. This routine is broken out from
** sqlite3VdbeAddOp4() since it needs to also local all btrees.
**
** The zWhere string must have been obtained from sqlite3_malloc().
** This routine will take ownership of the allocated memory.
*/
void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
int j;
int addr = sqlite3VdbeAddOp3(p, OP_ParseSchema, iDb, 0, 0);
sqlite3VdbeChangeP4(p, addr, zWhere, P4_DYNAMIC);
for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
}
/*
** Add an opcode that includes the p4 value as an integer.
*/
@@ -1392,34 +1399,13 @@ static void *allocSpace(
}
/*
** Prepare a virtual machine for execution. This involves things such
** as allocating stack space and initializing the program counter.
** After the VDBE has be prepped, it can be executed by one or more
** calls to sqlite3VdbeExec().
**
** This is the only way to move a VDBE from VDBE_MAGIC_INIT to
** VDBE_MAGIC_RUN.
**
** This function may be called more than once on a single virtual machine.
** The first call is made while compiling the SQL statement. Subsequent
** calls are made as part of the process of resetting a statement to be
** re-executed (from a call to sqlite3_reset()). The nVar, nMem, nCursor
** and isExplain parameters are only passed correct values the first time
** the function is called. On subsequent calls, from sqlite3_reset(), nVar
** is passed -1 and nMem, nCursor and isExplain are all passed zero.
** Rewind the VDBE back to the beginning in preparation for
** running it.
*/
void sqlite3VdbeMakeReady(
Vdbe *p, /* The VDBE */
int nVar, /* Number of '?' see in the SQL statement */
int nMem, /* Number of memory cells to allocate */
int nCursor, /* Number of cursors to allocate */
int nArg, /* Maximum number of args in SubPrograms */
int isExplain, /* True if the EXPLAIN keywords is present */
int usesStmtJournal /* True to set Vdbe.usesStmtJournal */
){
int n;
sqlite3 *db = p->db;
void sqlite3VdbeRewind(Vdbe *p){
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
int i;
#endif
assert( p!=0 );
assert( p->magic==VDBE_MAGIC_INIT );
@@ -1430,6 +1416,71 @@ void sqlite3VdbeMakeReady(
/* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
p->magic = VDBE_MAGIC_RUN;
#ifdef SQLITE_DEBUG
for(i=1; i<p->nMem; i++){
assert( p->aMem[i].db==p->db );
}
#endif
p->pc = -1;
p->rc = SQLITE_OK;
p->errorAction = OE_Abort;
p->magic = VDBE_MAGIC_RUN;
p->nChange = 0;
p->cacheCtr = 1;
p->minWriteFileFormat = 255;
p->iStatement = 0;
p->nFkConstraint = 0;
#ifdef VDBE_PROFILE
for(i=0; i<p->nOp; i++){
p->aOp[i].cnt = 0;
p->aOp[i].cycles = 0;
}
#endif
}
/*
** Prepare a virtual machine for execution for the first time after
** creating the virtual machine. This involves things such
** as allocating stack space and initializing the program counter.
** After the VDBE has be prepped, it can be executed by one or more
** calls to sqlite3VdbeExec().
**
** This function may be called exact once on a each virtual machine.
** After this routine is called the VM has been "packaged" and is ready
** to run. After this routine is called, futher calls to
** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects
** the Vdbe from the Parse object that helped generate it so that the
** the Vdbe becomes an independent entity and the Parse object can be
** destroyed.
**
** Use the sqlite3VdbeRewind() procedure to restore a virtual machine back
** to its initial state after it has been run.
*/
void sqlite3VdbeMakeReady(
Vdbe *p, /* The VDBE */
Parse *pParse /* Parsing context */
){
sqlite3 *db; /* The database connection */
int nVar; /* Number of parameters */
int nMem; /* Number of VM memory registers */
int nCursor; /* Number of cursors required */
int nArg; /* Number of arguments in subprograms */
int n; /* Loop counter */
u8 *zCsr; /* Memory available for allocation */
u8 *zEnd; /* First byte past allocated memory */
int nByte; /* How much extra memory is needed */
assert( p!=0 );
assert( p->nOp>0 );
assert( pParse!=0 );
assert( p->magic==VDBE_MAGIC_INIT );
db = p->db;
assert( db->mallocFailed==0 );
nVar = pParse->nVar;
nMem = pParse->nMem;
nCursor = pParse->nTab;
nArg = pParse->nMaxArg;
/* For each cursor required, also allocate a memory cell. Memory
** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
** the vdbe program. Instead they are used to allocate space for
@@ -1442,91 +1493,68 @@ void sqlite3VdbeMakeReady(
nMem += nCursor;
/* Allocate space for memory registers, SQL variables, VDBE cursors and
** an array to marshal SQL function arguments in. This is only done the
** first time this function is called for a given VDBE, not when it is
** being called from sqlite3_reset() to reset the virtual machine.
** an array to marshal SQL function arguments in.
*/
if( nVar>=0 && ALWAYS(db->mallocFailed==0) ){
u8 *zCsr = (u8 *)&p->aOp[p->nOp]; /* Memory avaliable for alloation */
u8 *zEnd = (u8 *)&p->aOp[p->nOpAlloc]; /* First byte past available mem */
int nByte; /* How much extra memory needed */
zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */
zEnd = (u8*)&p->aOp[p->nOpAlloc]; /* First byte past end of zCsr[] */
resolveP2Values(p, &nArg);
p->usesStmtJournal = (u8)usesStmtJournal;
if( isExplain && nMem<10 ){
nMem = 10;
resolveP2Values(p, &nArg);
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
if( pParse->explain && nMem<10 ){
nMem = 10;
}
memset(zCsr, 0, zEnd-zCsr);
zCsr += (zCsr - (u8*)0)&7;
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
/* Memory for registers, parameters, cursor, etc, is allocated in two
** passes. On the first pass, we try to reuse unused space at the
** end of the opcode array. If we are unable to satisfy all memory
** requirements by reusing the opcode array tail, then the second
** pass will fill in the rest using a fresh allocation.
**
** This two-pass approach that reuses as much memory as possible from
** the leftover space at the end of the opcode array can significantly
** reduce the amount of memory held by a prepared statement.
*/
do {
nByte = 0;
p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
&zCsr, zEnd, &nByte);
if( nByte ){
p->pFree = sqlite3DbMallocZero(db, nByte);
}
memset(zCsr, 0, zEnd-zCsr);
zCsr += (zCsr - (u8*)0)&7;
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
zCsr = p->pFree;
zEnd = &zCsr[nByte];
}while( nByte && !db->mallocFailed );
/* Memory for registers, parameters, cursor, etc, is allocated in two
** passes. On the first pass, we try to reuse unused space at the
** end of the opcode array. If we are unable to satisfy all memory
** requirements by reusing the opcode array tail, then the second
** pass will fill in the rest using a fresh allocation.
**
** This two-pass approach that reuses as much memory as possible from
** the leftover space at the end of the opcode array can significantly
** reduce the amount of memory held by a prepared statement.
*/
do {
nByte = 0;
p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
&zCsr, zEnd, &nByte);
if( nByte ){
p->pFree = sqlite3DbMallocZero(db, nByte);
}
zCsr = p->pFree;
zEnd = &zCsr[nByte];
}while( nByte && !db->mallocFailed );
p->nCursor = (u16)nCursor;
if( p->aVar ){
p->nVar = (ynVar)nVar;
for(n=0; n<nVar; n++){
p->aVar[n].flags = MEM_Null;
p->aVar[n].db = db;
}
}
if( p->aMem ){
p->aMem--; /* aMem[] goes from 1..nMem */
p->nMem = nMem; /* not from 0..nMem-1 */
for(n=1; n<=nMem; n++){
p->aMem[n].flags = MEM_Null;
p->aMem[n].db = db;
}
p->nCursor = (u16)nCursor;
if( p->aVar ){
p->nVar = (ynVar)nVar;
for(n=0; n<nVar; n++){
p->aVar[n].flags = MEM_Null;
p->aVar[n].db = db;
}
}
#ifdef SQLITE_DEBUG
for(n=1; n<p->nMem; n++){
assert( p->aMem[n].db==db );
if( p->azVar ){
p->nzVar = pParse->nzVar;
memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0]));
memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0]));
}
#endif
p->pc = -1;
p->rc = SQLITE_OK;
p->errorAction = OE_Abort;
p->explain |= isExplain;
p->magic = VDBE_MAGIC_RUN;
p->nChange = 0;
p->cacheCtr = 1;
p->minWriteFileFormat = 255;
p->iStatement = 0;
p->nFkConstraint = 0;
#ifdef VDBE_PROFILE
{
int i;
for(i=0; i<p->nOp; i++){
p->aOp[i].cnt = 0;
p->aOp[i].cycles = 0;
if( p->aMem ){
p->aMem--; /* aMem[] goes from 1..nMem */
p->nMem = nMem; /* not from 0..nMem-1 */
for(n=1; n<=nMem; n++){
p->aMem[n].flags = MEM_Null;
p->aMem[n].db = db;
}
}
#endif
p->explain = pParse->explain;
sqlite3VdbeRewind(p);
}
/*
@@ -2400,6 +2428,7 @@ void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
*/
void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
SubProgram *pSub, *pNext;
int i;
assert( p->db==0 || p->db==db );
releaseMemArray(p->aVar, p->nVar);
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
@@ -2408,6 +2437,7 @@ void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
sqlite3DbFree(db, pSub);
}
for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
vdbeFreeOpArray(db, p->aOp, p->nOp);
sqlite3DbFree(db, p->aLabel);
sqlite3DbFree(db, p->aColName);
@@ -2853,7 +2883,7 @@ UnpackedRecord *sqlite3VdbeRecordUnpack(
idx += getVarint32(&aKey[idx], serial_type);
pMem->enc = pKeyInfo->enc;
pMem->db = pKeyInfo->db;
pMem->flags = 0;
/* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */
pMem->zMalloc = 0;
pMem->z = 0;
d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
@@ -2869,6 +2899,7 @@ UnpackedRecord *sqlite3VdbeRecordUnpack(
** This routine destroys a UnpackedRecord object.
*/
void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
#ifdef SQLITE_DEBUG
int i;
Mem *pMem;
@@ -2882,6 +2913,7 @@ void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
*/
if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem);
}
#endif
if( p->flags & UNPACKED_NEED_FREE ){
sqlite3DbFree(p->pKeyInfo->db, p);
}