Merge sqlite-release(3.27.2) into prerelease-integration

This commit is contained in:
Stephen Lombardo
2019-02-25 15:00:57 -05:00
14 changed files with 184 additions and 98 deletions
+7 -33
View File
@@ -2552,14 +2552,11 @@ int sqlite3FindInIndex(
eType = IN_INDEX_EPH;
if( inFlags & IN_INDEX_LOOP ){
pParse->nQueryLoop = 0;
if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
eType = IN_INDEX_ROWID;
}
}else if( prRhsHasNull ){
*prRhsHasNull = rMayHaveNull = ++pParse->nMem;
}
assert( pX->op==TK_IN );
sqlite3CodeRhsOfIN(pParse, pX, iTab, eType==IN_INDEX_ROWID);
sqlite3CodeRhsOfIN(pParse, pX, iTab);
if( rMayHaveNull ){
sqlite3SetHasNullFlag(v, iTab, rMayHaveNull);
}
@@ -2660,12 +2657,6 @@ void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
** however the cursor number returned might not be the same, as it might
** have been duplicated using OP_OpenDup.
**
** If parameter isRowid is non-zero, then LHS of the IN operator is guaranteed
** to be a non-null integer. In this case, the ephemeral table can be an
** table B-Tree that keyed by only integers. The more general cases uses
** an index B-Tree which can have arbitrary keys, but is slower to both
** read and write.
**
** If the LHS expression ("x" in the examples) is a column value, or
** the SELECT statement returns a column value, then the affinity of that
** column is used to build the index keys. If both 'x' and the
@@ -2677,8 +2668,7 @@ void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
void sqlite3CodeRhsOfIN(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* The IN operator */
int iTab, /* Use this cursor number */
int isRowid /* If true, LHS is a rowid */
int iTab /* Use this cursor number */
){
int addrOnce = 0; /* Address of the OP_Once instruction at top */
int addr; /* Address of OP_OpenEphemeral instruction */
@@ -2731,14 +2721,12 @@ void sqlite3CodeRhsOfIN(
/* Check to see if this is a vector IN operator */
pLeft = pExpr->pLeft;
nVal = sqlite3ExprVectorSize(pLeft);
assert( !isRowid || nVal==1 );
/* Construct the ephemeral table that will contain the content of
** RHS of the IN operator.
*/
pExpr->iTable = iTab;
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral,
pExpr->iTable, (isRowid?0:nVal));
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, nVal);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
VdbeComment((v, "Result of SELECT %u", pExpr->x.pSelect->selId));
@@ -2746,7 +2734,7 @@ void sqlite3CodeRhsOfIN(
VdbeComment((v, "RHS of IN operator"));
}
#endif
pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
/* Case 1: expr IN (SELECT ...)
@@ -2760,7 +2748,6 @@ void sqlite3CodeRhsOfIN(
ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY %d",
addrOnce?"":"CORRELATED ", pSelect->selId
));
assert( !isRowid );
/* If the LHS and RHS of the IN operator do not match, that
** error will have been caught long before we reach this point. */
if( ALWAYS(pEList->nExpr==nVal) ){
@@ -2813,10 +2800,8 @@ void sqlite3CodeRhsOfIN(
/* Loop through each expression in <exprlist>. */
r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3GetTempReg(pParse);
if( isRowid ) sqlite3VdbeAddOp4(v, OP_Blob, 0, r2, 0, "", P4_STATIC);
for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
Expr *pE2 = pItem->pExpr;
int iValToIns;
/* If the expression is not constant then we will need to
** disable the test that was generated above that makes sure
@@ -2829,20 +2814,9 @@ void sqlite3CodeRhsOfIN(
}
/* Evaluate the expression and insert it into the temp table */
if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
sqlite3VdbeAddOp3(v, OP_InsertInt, iTab, r2, iValToIns);
}else{
r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
if( isRowid ){
sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_Insert, iTab, r2, r3);
}else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r3, 1);
}
}
r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r3, 1);
}
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempReg(pParse, r2);
+5 -2
View File
@@ -1919,10 +1919,13 @@ void sqlite3CompleteInsertion(
pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
if( update_flags==0 ){
sqlite3VdbeAddOp4(v, OP_InsertInt,
iIdxCur+i, aRegIdx[i], 0, (char*)pTab, P4_TABLE
int r = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Integer, 0, r);
sqlite3VdbeAddOp4(v, OP_Insert,
iIdxCur+i, aRegIdx[i], r, (char*)pTab, P4_TABLE
);
sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
sqlite3ReleaseTempReg(pParse, r);
}
#endif
}
+36 -13
View File
@@ -1243,6 +1243,38 @@ int sqlite3ResolveOrderGroupBy(
return 0;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** Walker callback for resolveRemoveWindows().
*/
static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){
if( ExprHasProperty(pExpr, EP_WinFunc) ){
Window **pp;
for(pp=&pWalker->u.pSelect->pWin; *pp; pp=&(*pp)->pNextWin){
if( *pp==pExpr->y.pWin ){
*pp = (*pp)->pNextWin;
break;
}
}
}
return WRC_Continue;
}
/*
** Remove any Window objects owned by the expression pExpr from the
** Select.pWin list of Select object pSelect.
*/
static void resolveRemoveWindows(Select *pSelect, Expr *pExpr){
Walker sWalker;
memset(&sWalker, 0, sizeof(Walker));
sWalker.xExprCallback = resolveRemoveWindowsCb;
sWalker.u.pSelect = pSelect;
sqlite3WalkExpr(&sWalker, pExpr);
}
#else
# define resolveRemoveWindows(x,y)
#endif
/*
** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
** The Name context of the SELECT statement is pNC. zType is either
@@ -1309,19 +1341,10 @@ static int resolveOrderGroupBy(
}
for(j=0; j<pSelect->pEList->nExpr; j++){
if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pE, EP_WinFunc) ){
/* Since this window function is being changed into a reference
** to the same window function the result set, remove the instance
** of this window function from the Select.pWin list. */
Window **pp;
for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){
if( *pp==pE->y.pWin ){
*pp = (*pp)->pNextWin;
}
}
}
#endif
/* Since this expresion is being changed into a reference
** to an identical expression in the result set, remove all Window
** objects belonging to the expression from the Select.pWin list. */
resolveRemoveWindows(pSelect, pE);
pItem->u.x.iOrderByCol = j+1;
}
}
+1 -1
View File
@@ -2369,7 +2369,7 @@ int sqlite3_changes(sqlite3*);
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
** are not counted.
**
** This the [sqlite3_total_changes(D)] interface only reports the number
** The [sqlite3_total_changes(D)] interface only reports the number
** of rows that changed due to SQL statement run against database
** connection D. Any changes by other database connections are ignored.
** To detect changes against a database file from other database
+1 -1
View File
@@ -4279,7 +4279,7 @@ void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
int sqlite3GetToken(const unsigned char *, int *);
void sqlite3NestedParse(Parse*, const char*, ...);
void sqlite3ExpirePreparedStatements(sqlite3*, int);
void sqlite3CodeRhsOfIN(Parse*, Expr*, int, int);
void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
int sqlite3CodeSubselect(Parse*, Expr*);
void sqlite3SelectPrep(Parse*, Select*, NameContext*);
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
+6 -18
View File
@@ -4580,14 +4580,7 @@ case OP_NewRowid: { /* out2 */
** This instruction only works on tables. The equivalent instruction
** for indices is OP_IdxInsert.
*/
/* Opcode: InsertInt P1 P2 P3 P4 P5
** Synopsis: intkey=P3 data=r[P2]
**
** This works exactly like OP_Insert except that the key is the
** integer value P3, not the value of the integer stored in register P3.
*/
case OP_Insert:
case OP_InsertInt: {
case OP_Insert: {
Mem *pData; /* MEM cell holding data for the record to be inserted */
Mem *pKey; /* MEM cell holding key for the record */
VdbeCursor *pC; /* Cursor to table into which insert is written */
@@ -4608,16 +4601,11 @@ case OP_InsertInt: {
REGISTER_TRACE(pOp->p2, pData);
sqlite3VdbeIncrWriteCounter(p, pC);
if( pOp->opcode==OP_Insert ){
pKey = &aMem[pOp->p3];
assert( pKey->flags & MEM_Int );
assert( memIsValid(pKey) );
REGISTER_TRACE(pOp->p3, pKey);
x.nKey = pKey->u.i;
}else{
assert( pOp->opcode==OP_InsertInt );
x.nKey = pOp->p3;
}
pKey = &aMem[pOp->p3];
assert( pKey->flags & MEM_Int );
assert( memIsValid(pKey) );
REGISTER_TRACE(pOp->p3, pKey);
x.nKey = pKey->u.i;
if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
assert( pC->iDb>=0 );
+3 -1
View File
@@ -582,7 +582,6 @@ static int codeEqualityTerm(
if( pLoop->aLTerm[i]->pExpr==pX ){
int iOut = iReg + i - iEq;
if( eType==IN_INDEX_ROWID ){
testcase( nEq>1 ); /* Happens with a UNIQUE index on ROWID */
pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
}else{
int iCol = aiMap ? aiMap[iMap++] : 0;
@@ -1344,6 +1343,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg);
VdbeCoverage(v);
pLevel->op = OP_Noop;
if( (pTerm->prereqAll & pLevel->notReady)==0 ){
pTerm->wtFlags |= TERM_CODED;
}
}else if( (pLoop->wsFlags & WHERE_IPK)!=0
&& (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0
){