Merge all the latest trunk changes into the experimental STAT3 branch.

FossilOrigin-Name: 51908c8f2bc6c086570f7493a29b096f0a40ce34
This commit is contained in:
drh
2011-09-16 19:29:58 +00:00
17 changed files with 367 additions and 102 deletions
+1 -1
View File
@@ -664,7 +664,7 @@ static int btreeMoveto(
pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree
);
if( pIdxKey==0 ) return SQLITE_NOMEM;
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey, pIdxKey);
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
}else{
pIdxKey = 0;
}
+8 -9
View File
@@ -901,7 +901,8 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
pNewItem->jointype = pOldItem->jointype;
pNewItem->iCursor = pOldItem->iCursor;
pNewItem->isPopulated = pOldItem->isPopulated;
pNewItem->addrFillSub = pOldItem->addrFillSub;
pNewItem->regReturn = pOldItem->regReturn;
pNewItem->isCorrelated = pOldItem->isCorrelated;
pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
pNewItem->notIndexed = pOldItem->notIndexed;
@@ -1461,8 +1462,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
int iMem = ++pParse->nMem;
int iAddr;
iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
eType = IN_INDEX_ROWID;
@@ -1493,8 +1493,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
char *pKey;
pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
pKey,P4_KEYINFO_HANDOFF);
@@ -1579,6 +1578,7 @@ int sqlite3CodeSubselect(
int rReg = 0; /* Register storing resulting */
Vdbe *v = sqlite3GetVdbe(pParse);
if( NEVER(v==0) ) return 0;
assert( sqlite3VdbeCurrentAddr(v)>0 );
sqlite3ExprCachePush(pParse);
/* This code must be run in its entirety every time it is encountered
@@ -1593,8 +1593,7 @@ int sqlite3CodeSubselect(
*/
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
int mem = ++pParse->nMem;
sqlite3VdbeAddOp1(v, OP_If, mem);
testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
testAddr = sqlite3VdbeAddOp1(v, OP_Once, mem);
assert( testAddr>0 || pParse->db->mallocFailed );
}
@@ -1694,7 +1693,7 @@ int sqlite3CodeSubselect(
** expression we need to rerun this code each time.
*/
if( testAddr && !sqlite3ExprIsConstant(pE2) ){
sqlite3VdbeChangeToNoop(v, testAddr-1, 2);
sqlite3VdbeChangeToNoop(v, testAddr);
testAddr = 0;
}
@@ -1765,7 +1764,7 @@ int sqlite3CodeSubselect(
}
if( testAddr ){
sqlite3VdbeJumpHere(v, testAddr-1);
sqlite3VdbeJumpHere(v, testAddr);
}
sqlite3ExprCachePop(pParse, 1);
+35 -6
View File
@@ -89,6 +89,8 @@ Select *sqlite3SelectNew(
clearSelect(db, pNew);
if( pNew!=&standin ) sqlite3DbFree(db, pNew);
pNew = 0;
}else{
assert( pNew->pSrc!=0 || pParse->nErr>0 );
}
return pNew;
}
@@ -3801,7 +3803,11 @@ int sqlite3Select(
Select *pSub = pItem->pSelect;
int isAggSub;
if( pSub==0 || pItem->isPopulated ) continue;
if( pSub==0 ) continue;
if( pItem->addrFillSub ){
sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
continue;
}
/* Increment Parse.nHeight by the height of the largest expression
** tree refered to by this, the parent select. The child select
@@ -3812,21 +3818,44 @@ int sqlite3Select(
*/
pParse->nHeight += sqlite3SelectExprHeight(p);
/* Check to see if the subquery can be absorbed into the parent. */
isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
/* This subquery can be absorbed into its parent. */
if( isAggSub ){
isAgg = 1;
p->selFlags |= SF_Aggregate;
}
i = -1;
}else{
/* Generate a subroutine that will fill an ephemeral table with
** the content of this subquery. pItem->addrFillSub will point
** to the address of the generated subroutine. pItem->regReturn
** is a register allocated to hold the subroutine return address
*/
int topAddr;
int onceAddr = 0;
int retAddr;
assert( pItem->addrFillSub==0 );
pItem->regReturn = ++pParse->nMem;
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
pItem->addrFillSub = topAddr+1;
VdbeNoopComment((v, "materialize %s", pItem->pTab->zName));
if( pItem->isCorrelated==0 && pParse->pTriggerTab==0 ){
/* If the subquery is no correlated and if we are not inside of
** a trigger, then we only need to compute the value of the subquery
** once. */
int regOnce = ++pParse->nMem;
onceAddr = sqlite3VdbeAddOp1(v, OP_Once, regOnce);
}
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
assert( pItem->isPopulated==0 );
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
pItem->isPopulated = 1;
pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
VdbeComment((v, "end %s", pItem->pTab->zName));
sqlite3VdbeChangeP1(v, topAddr, retAddr);
}
if( /*pParse->nErr ||*/ db->mallocFailed ){
goto select_end;
@@ -3967,7 +3996,7 @@ int sqlite3Select(
** into an OP_Noop.
*/
if( addrSortIndex>=0 && pOrderBy==0 ){
sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
sqlite3VdbeChangeToNoop(v, addrSortIndex);
p->addrOpenEphm[2] = -1;
}
@@ -4250,7 +4279,7 @@ int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
}else{
sqlite3WhereEnd(pWInfo);
sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1);
sqlite3VdbeChangeToNoop(v, addrSortingIdx);
}
/* Output the final row of result
+2 -1
View File
@@ -1872,7 +1872,8 @@ struct SrcList {
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
Table *pTab; /* An SQL table corresponding to zName */
Select *pSelect; /* A SELECT statement used in place of a table name */
u8 isPopulated; /* Temporary table associated with SELECT is populated */
int addrFillSub; /* Address of subroutine to manifest a subquery */
int regReturn; /* Register holding return address of addrFillSub */
u8 jointype; /* Type of join between this able and the previous */
u8 notIndexed; /* True if there is a NOT INDEXED clause */
u8 isCorrelated; /* True if sub-query is correlated */
+17
View File
@@ -2021,6 +2021,16 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
break;
}
/* Opcode: Once P1 P2 * * *
**
** Jump to P2 if the value in register P1 is a not null or zero. If
** the value is NULL or zero, fall through and change the P1 register
** to an integer 1.
**
** When P1 is not used otherwise in a program, this opcode falls through
** once and jumps on all subsequent invocations. It is the equivalent
** of "OP_If P1 P2", followed by "OP_Integer 1 P1".
*/
/* Opcode: If P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is true. The value
@@ -2033,6 +2043,7 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
** is considered true if it has a numeric value of zero. If the value
** in P1 is NULL then take the jump if P3 is true.
*/
case OP_Once: /* jump, in1 */
case OP_If: /* jump, in1 */
case OP_IfNot: { /* jump, in1 */
int c;
@@ -2049,6 +2060,12 @@ case OP_IfNot: { /* jump, in1 */
}
if( c ){
pc = pOp->p2-1;
}else if( pOp->opcode==OP_Once ){
assert( (pIn1->flags & (MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))==0 );
memAboutToChange(p, pIn1);
pIn1->flags = MEM_Int;
pIn1->u.i = 1;
REGISTER_TRACE(pOp->p1, pIn1);
}
break;
}
+1 -1
View File
@@ -180,7 +180,7 @@ void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
void sqlite3VdbeJumpHere(Vdbe*, int addr);
void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
void sqlite3VdbeUsesBtree(Vdbe*, int);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
+6 -9
View File
@@ -670,18 +670,15 @@ void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
}
/*
** Change N opcodes starting at addr to No-ops.
** Change the opcode at addr into OP_Noop
*/
void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
if( p->aOp ){
VdbeOp *pOp = &p->aOp[addr];
sqlite3 *db = p->db;
while( N-- ){
freeP4(db, pOp->p4type, pOp->p4.p);
memset(pOp, 0, sizeof(pOp[0]));
pOp->opcode = OP_Noop;
pOp++;
}
freeP4(db, pOp->p4type, pOp->p4.p);
memset(pOp, 0, sizeof(pOp[0]));
pOp->opcode = OP_Noop;
}
}
@@ -837,7 +834,7 @@ void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
/* C89 specifies that the constant "dummy" will be initialized to all
** zeros, which is correct. MSVC generates a warning, nevertheless. */
static const VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
assert( p->magic==VDBE_MAGIC_INIT );
if( addr<0 ){
#ifdef SQLITE_OMIT_TRACE
+2 -2
View File
@@ -273,7 +273,7 @@ int sqlite3_blob_open(
/* Configure the OP_TableLock instruction */
#ifdef SQLITE_OMIT_SHARED_CACHE
sqlite3VdbeChangeToNoop(v, 2, 1);
sqlite3VdbeChangeToNoop(v, 2);
#else
sqlite3VdbeChangeP1(v, 2, iDb);
sqlite3VdbeChangeP2(v, 2, pTab->tnum);
@@ -283,7 +283,7 @@ int sqlite3_blob_open(
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
** parameter of the other to pTab->tnum. */
sqlite3VdbeChangeToNoop(v, 4 - flags, 1);
sqlite3VdbeChangeToNoop(v, 4 - flags);
sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
sqlite3VdbeChangeP3(v, 3 + flags, iDb);
+22 -47
View File
@@ -160,8 +160,12 @@ static int vdbeSorterIterNext(
int nRec = 0; /* Size of record in bytes */
int iOff = 0; /* Size of serialized size varint in bytes */
nRead = pIter->iEof - pIter->iReadOff;
if( nRead>5 ) nRead = 5;
assert( pIter->iEof>=pIter->iReadOff );
if( pIter->iEof-pIter->iReadOff>5 ){
nRead = 5;
}else{
nRead = (int)(pIter->iEof - pIter->iReadOff);
}
if( nRead<=0 ){
/* This is an EOF condition */
vdbeSorterIterZero(db, pIter);
@@ -298,7 +302,7 @@ static int vdbeSorterIterInit(
** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace
** has been allocated and contains an unpacked record that is used as key2.
*/
static int vdbeSorterCompare(
static void vdbeSorterCompare(
VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
int bOmitRowid, /* Ignore rowid field at end of keys */
void *pKey1, int nKey1, /* Left side of comparison */
@@ -320,14 +324,13 @@ static int vdbeSorterCompare(
for(i=0; i<r2->nField; i++){
if( r2->aMem[i].flags & MEM_Null ){
*pRes = -1;
return SQLITE_OK;
return;
}
}
r2->flags |= UNPACKED_PREFIX_MATCH;
}
*pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
return SQLITE_OK;
}
/*
@@ -362,15 +365,10 @@ static int vdbeSorterDoCompare(VdbeCursor *pCsr, int iOut){
iRes = i1;
}else{
int res;
int rc;
assert( pCsr->pSorter->pUnpacked!=0 ); /* allocated in vdbeSorterMerge() */
rc = vdbeSorterCompare(
vdbeSorterCompare(
pCsr, 0, p1->aKey, p1->nKey, p2->aKey, p2->nKey, &res
);
/* The vdbeSorterCompare() call cannot fail since pCsr->pSorter->pUnpacked
** has already been allocated. */
assert( rc==SQLITE_OK );
if( res<=0 ){
iRes = i1;
}else{
@@ -462,32 +460,22 @@ static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){
}
/*
** Attemp to merge the two sorted lists p1 and p2 into a single list. If no
** error occurs set *ppOut to the head of the new list and return SQLITE_OK.
** Merge the two sorted lists p1 and p2 into a single list.
** Set *ppOut to the head of the new list.
*/
static int vdbeSorterMerge(
sqlite3 *db, /* Database handle */
static void vdbeSorterMerge(
VdbeCursor *pCsr, /* For pKeyInfo */
SorterRecord *p1, /* First list to merge */
SorterRecord *p2, /* Second list to merge */
SorterRecord **ppOut /* OUT: Head of merged list */
){
int rc = SQLITE_OK;
SorterRecord *pFinal = 0;
SorterRecord **pp = &pFinal;
void *pVal2 = p2 ? p2->pVal : 0;
while( p1 && p2 ){
int res;
rc = vdbeSorterCompare(pCsr, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res);
if( rc!=SQLITE_OK ){
*pp = 0;
vdbeSorterRecordFree(db, p1);
vdbeSorterRecordFree(db, p2);
vdbeSorterRecordFree(db, pFinal);
*ppOut = 0;
return rc;
}
vdbeSorterCompare(pCsr, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res);
if( res<=0 ){
*pp = p1;
pp = &p1->pNext;
@@ -502,9 +490,7 @@ static int vdbeSorterMerge(
}
}
*pp = p1 ? p1 : p2;
*ppOut = pFinal;
return SQLITE_OK;
}
/*
@@ -512,8 +498,7 @@ static int vdbeSorterMerge(
** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error
** occurs.
*/
static int vdbeSorterSort(sqlite3 *db, VdbeCursor *pCsr){
int rc = SQLITE_OK;
static int vdbeSorterSort(VdbeCursor *pCsr){
int i;
SorterRecord **aSlot;
SorterRecord *p;
@@ -528,30 +513,22 @@ static int vdbeSorterSort(sqlite3 *db, VdbeCursor *pCsr){
while( p ){
SorterRecord *pNext = p->pNext;
p->pNext = 0;
for(i=0; rc==SQLITE_OK && aSlot[i]; i++){
rc = vdbeSorterMerge(db, pCsr, p, aSlot[i], &p);
for(i=0; aSlot[i]; i++){
vdbeSorterMerge(pCsr, p, aSlot[i], &p);
aSlot[i] = 0;
}
if( rc!=SQLITE_OK ){
vdbeSorterRecordFree(db, pNext);
break;
}
aSlot[i] = p;
p = pNext;
}
p = 0;
for(i=0; i<64; i++){
if( rc==SQLITE_OK ){
rc = vdbeSorterMerge(db, pCsr, p, aSlot[i], &p);
}else{
vdbeSorterRecordFree(db, aSlot[i]);
}
vdbeSorterMerge(pCsr, p, aSlot[i], &p);
}
pSorter->pRecord = p;
sqlite3_free(aSlot);
return rc;
return SQLITE_OK;
}
@@ -577,7 +554,7 @@ static int vdbeSorterListToPMA(sqlite3 *db, VdbeCursor *pCsr){
return rc;
}
rc = vdbeSorterSort(db, pCsr);
rc = vdbeSorterSort(pCsr);
/* If the first temporary PMA file has not been opened, open it now. */
if( rc==SQLITE_OK && pSorter->pTemp1==0 ){
@@ -724,7 +701,7 @@ int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
if( pSorter->nPMA==0 ){
*pbEof = !pSorter->pRecord;
assert( pSorter->aTree==0 );
return vdbeSorterSort(db, pCsr);
return vdbeSorterSort(pCsr);
}
/* Write the current b-tree to a PMA. Close the b-tree cursor. */
@@ -894,14 +871,12 @@ int sqlite3VdbeSorterCompare(
Mem *pVal, /* Value to compare to current sorter key */
int *pRes /* OUT: Result of comparison */
){
int rc;
VdbeSorter *pSorter = pCsr->pSorter;
void *pKey; int nKey; /* Sorter key to compare pVal with */
pKey = vdbeSorterRowkey(pSorter, &nKey);
rc = vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes);
assert( rc!=SQLITE_OK || pVal->db->mallocFailed || (*pRes)<=0 );
return rc;
vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes);
return SQLITE_OK;
}
#endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
+9 -2
View File
@@ -467,11 +467,19 @@ static Bitmask exprListTableUsage(WhereMaskSet *pMaskSet, ExprList *pList){
static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
Bitmask mask = 0;
while( pS ){
SrcList *pSrc = pS->pSrc;
mask |= exprListTableUsage(pMaskSet, pS->pEList);
mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
mask |= exprTableUsage(pMaskSet, pS->pWhere);
mask |= exprTableUsage(pMaskSet, pS->pHaving);
if( ALWAYS(pSrc!=0) ){
int i;
for(i=0; i<pSrc->nSrc; i++){
mask |= exprSelectTableUsage(pMaskSet, pSrc->a[i].pSelect);
mask |= exprTableUsage(pMaskSet, pSrc->a[i].pOn);
}
}
pS = pS->pPrior;
}
return mask;
@@ -1994,8 +2002,7 @@ static void constructAutomaticIndex(
v = pParse->pVdbe;
assert( v!=0 );
regIsInit = ++pParse->nMem;
addrInit = sqlite3VdbeAddOp1(v, OP_If, regIsInit);
sqlite3VdbeAddOp2(v, OP_Integer, 1, regIsInit);
addrInit = sqlite3VdbeAddOp1(v, OP_Once, regIsInit);
/* Count the number of columns that will be added to the index
** and used to match WHERE clause constraints */