** populated epheremal table.
** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be
** implemented as a sequence of comparisons.
**
** An existing b-tree might be used if the RHS expression pX is a simple
** subquery such as:
**
** SELECT <column> FROM <table>
**
** If the RHS of the IN operator is a list or a more complex subquery, then
** an ephemeral table might need to be generated from the RHS and then
** pX->iTable made to point to the ephemeral table instead of an
** existing table.
**
** The inFlags parameter must contain exactly one of the bits
................................................................................
** IN_INDEX_MEMBERSHIP, then the generated table will be used for a
** fast membership test. When the IN_INDEX_LOOP bit is set, the
** IN index will be used to loop over all values of the RHS of the
** IN operator.
**
** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate
** through the set members) then the b-tree must not contain duplicates.
** An epheremal table must be used unless the selected <column> is guaranteed
** to be unique - either because it is an INTEGER PRIMARY KEY or it
** has a UNIQUE constraint or UNIQUE index.
**
** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used
** for fast set membership tests) then an epheremal table must
** be used unless <column> is an INTEGER PRIMARY KEY or an index can
** be found with <column> as its left-most column.
**
** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and
** if the RHS of the IN operator is a list (not a subquery) then this
** routine might decide that creating an ephemeral b-tree for membership
** testing is too expensive and return IN_INDEX_NOOP. In that case, the
** calling routine should implement the IN operator using a sequence
** of Eq or Ne comparison operations.
................................................................................
** to *prRhsHasNull. If there is no chance that the (...) contains a
** NULL value, then *prRhsHasNull is left unchanged.
**
** If a register is allocated and its location stored in *prRhsHasNull, then
** the value in that register will be NULL if the b-tree contains one or more
** NULL values, and it will be some non-NULL value if the b-tree contains no
** NULL values.
*/
#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3FindInIndex(
Parse *pParse,
Expr *pX,
u32 inFlags,
int *prRhsHasNull,
................................................................................
n = sqlite3ExprVectorSize(pX->pLeft);
for(i=0; i<n; i++) aiMap[i] = i;
}
return eType;
}
#endif
static char *exprINAffinity(Parse *pParse, Expr *pExpr){
Expr *pLeft = pExpr->pLeft;
int nVal = sqlite3ExprVectorSize(pLeft);
char *zRet;
zRet = sqlite3DbMallocZero(pParse->db, nVal+1);
if( zRet ){
int i;
for(i=0; i<nVal; i++){
Expr *pA;
char a;
if( nVal==1 && 0 ){
pA = pLeft;
}else{pA = exprVectorField(pLeft, i);
}
a = sqlite3ExprAffinity(pA); zRet[i] = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[i].pExpr, a);
}
zRet[nVal] = '\0';
}
return zRet;
}
#ifndef SQLITE_OMIT_SUBQUERY
................................................................................
case TK_IN: {
int addr; /* Address of OP_OpenEphemeral instruction */
Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
KeyInfo *pKeyInfo = 0; /* Key information */
int nVal; /* Size of vector pLeft */
nVal = sqlite3ExprVectorSize(pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
** expression it is handled the same way. An ephemeral table is
** filled with single-field index keys representing the results
** from the SELECT or the <exprlist>.
**
** If the 'x' expression 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
** SELECT... statement are columns, then numeric affinity is used
** if either column has NUMERIC or INTEGER affinity. If neither
** 'x' nor the SELECT... statement are columns, then numeric affinity
................................................................................
int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */
int eType; /* Type of the RHS */
int r1; /* Temporary use register */
Vdbe *v; /* Statement under construction */
int *aiMap = 0; /* Map from vector field to index column */
char *zAff = 0; /* Affinity string for comparisons */
int nVector; /* Size of vectors for this IN(...) op */
int regSelect = 0;
Expr *pLeft = pExpr->pLeft;
int i;
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
nVector = sqlite3ExprVectorSize(pExpr->pLeft);
aiMap = (int*)sqlite3DbMallocZero(
pParse->db, nVector*(sizeof(int) + sizeof(char)) + 1
);
if( !aiMap ) return;
zAff = (char*)&aiMap[nVector];
/* Attempt to compute the RHS. After this step, if anything other than
** IN_INDEX_NOOP is returned, the table opened ith cursor pExpr->iTable
** contains the values that make up the RHS. If IN_INDEX_NOOP is returned,
** the RHS has not yet been coded. */
v = pParse->pVdbe;
assert( v!=0 ); /* OOM detected prior to this routine */
................................................................................
/* Code the LHS, the <expr> from "<expr> IN (...)". If the LHS is a
** vector, then it is stored in an array of nVector registers starting
** at r1.
*/
r1 = sqlite3GetTempRange(pParse, nVector);
sqlite3ExprCachePush(pParse);
if( nVector>1 && (pLeft->flags & EP_xIsSelect) ){
regSelect = sqlite3CodeSubselect(pParse, pLeft, 0, 0);
}
for(i=0; i<nVector; i++){
int iCol = aiMap[i]; Expr *pLhs = exprVectorField(pLeft, i); if( regSelect ){ sqlite3VdbeAddOp3(v, OP_Copy, regSelect+i, r1+iCol, 0); }else{
sqlite3ExprCode(pParse, pLhs, r1+iCol);
} zAff[iCol] = sqlite3ExprAffinity(pLhs); if( pExpr->flags & EP_xIsSelect ){ zAff[iCol] = sqlite3CompareAffinity( pExpr->x.pSelect->pEList->a[iCol].pExpr, zAff[iCol] );
}
}
/* If sqlite3FindInIndex() did not find or create an index that is
** suitable for evaluating the IN operator, then evaluate using a
** sequence of comparisons.
*/
................................................................................
sqlite3VdbeJumpHere(v, addr1);
}
}
}
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ExprCachePop(pParse);
sqlite3DbFree(pParse->db, aiMap);
VdbeComment((v, "end IN expr"));
}
#endif /* SQLITE_OMIT_SUBQUERY */
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Generate an instruction that will put the floating point

** populated epheremal table.
** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be
** implemented as a sequence of comparisons.
**
** An existing b-tree might be used if the RHS expression pX is a simple
** subquery such as:
**
** SELECT <column1>, <column2>... FROM <table>
**
** If the RHS of the IN operator is a list or a more complex subquery, then
** an ephemeral table might need to be generated from the RHS and then
** pX->iTable made to point to the ephemeral table instead of an
** existing table.
**
** The inFlags parameter must contain exactly one of the bits
................................................................................
** IN_INDEX_MEMBERSHIP, then the generated table will be used for a
** fast membership test. When the IN_INDEX_LOOP bit is set, the
** IN index will be used to loop over all values of the RHS of the
** IN operator.
**
** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate
** through the set members) then the b-tree must not contain duplicates.
** An epheremal table must be used unless the selected columns are guaranteed
** to be unique - either because it is an INTEGER PRIMARY KEY or due to
** a UNIQUE constraint or index.
**
** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used
** for fast set membership tests) then an epheremal table must
** be used unless <columns> is a single INTEGER PRIMARY KEY column or an
** index can be found with the specified <columns> as its left-most.
**
** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and
** if the RHS of the IN operator is a list (not a subquery) then this
** routine might decide that creating an ephemeral b-tree for membership
** testing is too expensive and return IN_INDEX_NOOP. In that case, the
** calling routine should implement the IN operator using a sequence
** of Eq or Ne comparison operations.
................................................................................
** to *prRhsHasNull. If there is no chance that the (...) contains a
** NULL value, then *prRhsHasNull is left unchanged.
**
** If a register is allocated and its location stored in *prRhsHasNull, then
** the value in that register will be NULL if the b-tree contains one or more
** NULL values, and it will be some non-NULL value if the b-tree contains no
** NULL values.
**** If the aiMap parameter is not NULL, it must point to an array containing** one element for each column returned by the SELECT statement on the RHS** of the IN(...) operator. The i'th entry of the array is populated with the** offset of the index column that matches the i'th column returned by the** SELECT. For example, if the expression and selected index are:**** (?,?,?) IN (SELECT a, b, c FROM t1)** CREATE INDEX i1 ON t1(b, c, a);**** then aiMap[] is populated with {2, 0, 1}.
*/
#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3FindInIndex(
Parse *pParse,
Expr *pX,
u32 inFlags,
int *prRhsHasNull,
................................................................................
n = sqlite3ExprVectorSize(pX->pLeft);
for(i=0; i<n; i++) aiMap[i] = i;
}
return eType;
}
#endif
/*** Argument pExpr is an (?, ?...) IN(...) expression. This ** function allocates and returns a nul-terminated string containing ** the affinities to be used for each column of the comparison.**** It is the responsibility of the caller to ensure that the returned** string is eventually freed using sqlite3DbFree().*/
static char *exprINAffinity(Parse *pParse, Expr *pExpr){
Expr *pLeft = pExpr->pLeft;
int nVal = sqlite3ExprVectorSize(pLeft);
Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0;
char *zRet;
assert( pExpr->op==TK_IN );
zRet = sqlite3DbMallocZero(pParse->db, nVal+1);
if( zRet ){
int i;
for(i=0; i<nVal; i++){
Expr *pA = exprVectorField(pLeft, i);
char a = sqlite3ExprAffinity(pA);
if( pSelect ){
zRet[i] = sqlite3CompareAffinity(pSelect->pEList->a[i].pExpr, a);
}else{
zRet[i] = a;
}
}
zRet[nVal] = '\0';
}
return zRet;
}
#ifndef SQLITE_OMIT_SUBQUERY
................................................................................
case TK_IN: {
int addr; /* Address of OP_OpenEphemeral instruction */
Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
KeyInfo *pKeyInfo = 0; /* Key information */
int nVal; /* Size of vector pLeft */
nVal = sqlite3ExprVectorSize(pLeft);
assert( !isRowid || nVal==1 );
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
** expression it is handled the same way. An ephemeral table is
** filled with index keys representing the results from the
** SELECT or the <exprlist>.
**
** If the 'x' expression 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
** SELECT... statement are columns, then numeric affinity is used
** if either column has NUMERIC or INTEGER affinity. If neither
** 'x' nor the SELECT... statement are columns, then numeric affinity
................................................................................
int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */
int eType; /* Type of the RHS */
int r1; /* Temporary use register */
Vdbe *v; /* Statement under construction */
int *aiMap = 0; /* Map from vector field to index column */
char *zAff = 0; /* Affinity string for comparisons */
int nVector; /* Size of vectors for this IN(...) op */
Expr *pLeft = pExpr->pLeft;
int i;
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
zAff = exprINAffinity(pParse, pExpr);
nVector = sqlite3ExprVectorSize(pExpr->pLeft);
aiMap = (int*)sqlite3DbMallocZero(
pParse->db, nVector*(sizeof(int) + sizeof(char)) + 1
);
if( !zAff || !aiMap ){ sqlite3DbFree(pParse->db, aiMap); return;
}
/* Attempt to compute the RHS. After this step, if anything other than
** IN_INDEX_NOOP is returned, the table opened ith cursor pExpr->iTable
** contains the values that make up the RHS. If IN_INDEX_NOOP is returned,
** the RHS has not yet been coded. */
v = pParse->pVdbe;
assert( v!=0 ); /* OOM detected prior to this routine */
................................................................................
/* Code the LHS, the <expr> from "<expr> IN (...)". If the LHS is a
** vector, then it is stored in an array of nVector registers starting
** at r1.
*/
r1 = sqlite3GetTempRange(pParse, nVector);
sqlite3ExprCachePush(pParse);
if( nVector>1 && (pLeft->flags & EP_xIsSelect) ){
int regSelect = sqlite3CodeSubselect(pParse, pLeft, 0, 0);
for(i=0; i<nVector; i++){
sqlite3VdbeAddOp3(v, OP_Copy, regSelect+i, r1+aiMap[i], 0); }
}else{
for(i=0; i<nVector; i++){ Expr *pLhs = exprVectorField(pLeft, i);
sqlite3ExprCode(pParse, pLhs, r1+aiMap[i]);
}
}
/* If sqlite3FindInIndex() did not find or create an index that is
** suitable for evaluating the IN operator, then evaluate using a
** sequence of comparisons.
*/
................................................................................
sqlite3VdbeJumpHere(v, addr1);
}
}
}
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ExprCachePop(pParse);
sqlite3DbFree(pParse->db, aiMap);
sqlite3DbFree(pParse->db, zAff);
VdbeComment((v, "end IN expr"));
}
#endif /* SQLITE_OMIT_SUBQUERY */
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Generate an instruction that will put the floating point

}
}
if( pLoop->nOut > nRow-iReduce ) pLoop->nOut = nRow - iReduce;
}
/*
** Term pTerm is a vector range comparison operation. The first comparison
** in the vector can be optimized using column nEq of the index. This** function returns the total number of vector elements that can be used** as part of the range comparison.**** For example, if the query is:**** WHERE a = ? AND (b, c, d) > (?, ?, ?)**** and the index:**** CREATE INDEX ... ON (a, b, c, d, e)**** then this function would be invoked with nEq=1. The value returned in** this case is 3.
*/
int whereRangeVectorLen(
Parse *pParse, int iCur, Index *pIdx, int nEq, WhereTerm *pTerm
){
int nCmp = sqlite3ExprVectorSize(pTerm->pExpr->pLeft);
int i;