mirror of
https://github.com/php/php-src.git
synced 2025-08-18 23:18:56 +02:00
Upgrade bundled library to 2.8.14 + misc fixes
(http://www.sqlite.org/cvstrac/chngview?cn=1742)
This commit is contained in:
parent
cd732f1a3f
commit
e563b4eafa
43 changed files with 5953 additions and 5559 deletions
|
@ -42,6 +42,9 @@ Select *sqliteSelectNew(
|
|||
sqliteExprDelete(pHaving);
|
||||
sqliteExprListDelete(pOrderBy);
|
||||
}else{
|
||||
if( pEList==0 ){
|
||||
pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL,0,0,0), 0);
|
||||
}
|
||||
pNew->pEList = pEList;
|
||||
pNew->pSrc = pSrc;
|
||||
pNew->pWhere = pWhere;
|
||||
|
@ -335,9 +338,7 @@ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){
|
|||
sqliteExprCode(pParse, pOrderBy->a[i].pExpr);
|
||||
}
|
||||
zSortOrder[pOrderBy->nExpr] = 0;
|
||||
sqliteVdbeAddOp(v, OP_SortMakeKey, pOrderBy->nExpr, 0);
|
||||
sqliteVdbeChangeP3(v, -1, zSortOrder, strlen(zSortOrder));
|
||||
sqliteFree(zSortOrder);
|
||||
sqliteVdbeOp3(v, OP_SortMakeKey, pOrderBy->nExpr, 0, zSortOrder, P3_DYNAMIC);
|
||||
sqliteVdbeAddOp(v, OP_SortPut, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -360,8 +361,7 @@ void sqliteAddKeyType(Vdbe *v, ExprList *pEList){
|
|||
zType[i] = sqliteExprType(pEList->a[i].pExpr)==SQLITE_SO_NUM ? 'n' : 't';
|
||||
}
|
||||
zType[i] = 0;
|
||||
sqliteVdbeChangeP3(v, -1, zType, nColumn);
|
||||
sqliteFree(zType);
|
||||
sqliteVdbeChangeP3(v, -1, zType, P3_DYNAMIC);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -564,18 +564,19 @@ static void generateSortTail(
|
|||
int eDest, /* Write the sorted results here */
|
||||
int iParm /* Optional parameter associated with eDest */
|
||||
){
|
||||
int end = sqliteVdbeMakeLabel(v);
|
||||
int end1 = sqliteVdbeMakeLabel(v);
|
||||
int end2 = sqliteVdbeMakeLabel(v);
|
||||
int addr;
|
||||
if( eDest==SRT_Sorter ) return;
|
||||
sqliteVdbeAddOp(v, OP_Sort, 0, 0);
|
||||
addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end);
|
||||
addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end1);
|
||||
if( p->iOffset>=0 ){
|
||||
sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+4);
|
||||
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
|
||||
}
|
||||
if( p->iLimit>=0 ){
|
||||
sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, end);
|
||||
sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, end2);
|
||||
}
|
||||
switch( eDest ){
|
||||
case SRT_Callback: {
|
||||
|
@ -601,7 +602,7 @@ static void generateSortTail(
|
|||
case SRT_Mem: {
|
||||
assert( nColumn==1 );
|
||||
sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, end);
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, end1);
|
||||
break;
|
||||
}
|
||||
case SRT_Subroutine: {
|
||||
|
@ -619,7 +620,9 @@ static void generateSortTail(
|
|||
}
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
|
||||
sqliteVdbeResolveLabel(v, end);
|
||||
sqliteVdbeResolveLabel(v, end2);
|
||||
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
|
||||
sqliteVdbeResolveLabel(v, end1);
|
||||
sqliteVdbeAddOp(v, OP_SortReset, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -645,9 +648,6 @@ static void generateColumnTypes(
|
|||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int i, j;
|
||||
if( pParse->useCallback && (pParse->db->flags & SQLITE_ReportTypes)==0 ){
|
||||
return;
|
||||
}
|
||||
for(i=0; i<pEList->nExpr; i++){
|
||||
Expr *p = pEList->a[i].pExpr;
|
||||
char *zType = 0;
|
||||
|
@ -672,15 +672,14 @@ static void generateColumnTypes(
|
|||
zType = "NUMERIC";
|
||||
}
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_ColumnName, i + pEList->nExpr, 0);
|
||||
sqliteVdbeChangeP3(v, -1, zType, P3_STATIC);
|
||||
sqliteVdbeOp3(v, OP_ColumnName, i + pEList->nExpr, 0, zType, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code that will tell the VDBE the names of columns
|
||||
** in the result set. This information is used to provide the
|
||||
** azCol[] vaolues in the callback.
|
||||
** azCol[] values in the callback.
|
||||
*/
|
||||
static void generateColumnNames(
|
||||
Parse *pParse, /* Parser context */
|
||||
|
@ -689,21 +688,24 @@ static void generateColumnNames(
|
|||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int i, j;
|
||||
sqlite *db = pParse->db;
|
||||
int fullNames, shortNames;
|
||||
|
||||
assert( v!=0 );
|
||||
if( pParse->colNamesSet || v==0 || sqlite_malloc_failed ) return;
|
||||
pParse->colNamesSet = 1;
|
||||
fullNames = (db->flags & SQLITE_FullColNames)!=0;
|
||||
shortNames = (db->flags & SQLITE_ShortColNames)!=0;
|
||||
for(i=0; i<pEList->nExpr; i++){
|
||||
Expr *p;
|
||||
char *zType = 0;
|
||||
int showFullNames;
|
||||
int p2 = i==pEList->nExpr-1;
|
||||
p = pEList->a[i].pExpr;
|
||||
if( p==0 ) continue;
|
||||
if( pEList->a[i].zName ){
|
||||
char *zName = pEList->a[i].zName;
|
||||
sqliteVdbeAddOp(v, OP_ColumnName, i, 0);
|
||||
sqliteVdbeChangeP3(v, -1, zName, strlen(zName));
|
||||
sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, 0);
|
||||
continue;
|
||||
}
|
||||
showFullNames = (pParse->db->flags & SQLITE_FullColNames)!=0;
|
||||
if( p->op==TK_COLUMN && pTabList ){
|
||||
Table *pTab;
|
||||
char *zCol;
|
||||
|
@ -715,39 +717,31 @@ static void generateColumnNames(
|
|||
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
|
||||
if( iCol<0 ){
|
||||
zCol = "_ROWID_";
|
||||
zType = "INTEGER";
|
||||
}else{
|
||||
zCol = pTab->aCol[iCol].zName;
|
||||
zType = pTab->aCol[iCol].zType;
|
||||
}
|
||||
if( p->span.z && p->span.z[0] && !showFullNames ){
|
||||
int addr = sqliteVdbeAddOp(v,OP_ColumnName, i, 0);
|
||||
sqliteVdbeChangeP3(v, -1, p->span.z, p->span.n);
|
||||
if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){
|
||||
int addr = sqliteVdbeOp3(v,OP_ColumnName, i, p2, p->span.z, p->span.n);
|
||||
sqliteVdbeCompressSpace(v, addr);
|
||||
}else if( pTabList->nSrc>1 || showFullNames ){
|
||||
}else if( fullNames || (!shortNames && pTabList->nSrc>1) ){
|
||||
char *zName = 0;
|
||||
char *zTab;
|
||||
|
||||
zTab = pTabList->a[j].zAlias;
|
||||
if( showFullNames || zTab==0 ) zTab = pTab->zName;
|
||||
if( fullNames || zTab==0 ) zTab = pTab->zName;
|
||||
sqliteSetString(&zName, zTab, ".", zCol, 0);
|
||||
sqliteVdbeAddOp(v, OP_ColumnName, i, 0);
|
||||
sqliteVdbeChangeP3(v, -1, zName, strlen(zName));
|
||||
sqliteFree(zName);
|
||||
sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, P3_DYNAMIC);
|
||||
}else{
|
||||
sqliteVdbeAddOp(v, OP_ColumnName, i, 0);
|
||||
sqliteVdbeChangeP3(v, -1, zCol, 0);
|
||||
sqliteVdbeOp3(v, OP_ColumnName, i, p2, zCol, 0);
|
||||
}
|
||||
}else if( p->span.z && p->span.z[0] ){
|
||||
int addr = sqliteVdbeAddOp(v,OP_ColumnName, i, 0);
|
||||
sqliteVdbeChangeP3(v, -1, p->span.z, p->span.n);
|
||||
int addr = sqliteVdbeOp3(v,OP_ColumnName, i, p2, p->span.z, p->span.n);
|
||||
sqliteVdbeCompressSpace(v, addr);
|
||||
}else{
|
||||
char zName[30];
|
||||
assert( p->op!=TK_COLUMN || pTabList==0 );
|
||||
sprintf(zName, "column%d", i+1);
|
||||
sqliteVdbeAddOp(v, OP_ColumnName, i, 0);
|
||||
sqliteVdbeChangeP3(v, -1, zName, strlen(zName));
|
||||
sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -777,8 +771,9 @@ static int fillInColumnList(Parse*, Select*);
|
|||
*/
|
||||
Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
|
||||
Table *pTab;
|
||||
int i;
|
||||
int i, j;
|
||||
ExprList *pEList;
|
||||
Column *aCol;
|
||||
|
||||
if( fillInColumnList(pParse, pSelect) ){
|
||||
return 0;
|
||||
|
@ -791,17 +786,27 @@ Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
|
|||
pEList = pSelect->pEList;
|
||||
pTab->nCol = pEList->nExpr;
|
||||
assert( pTab->nCol>0 );
|
||||
pTab->aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
|
||||
pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
Expr *p;
|
||||
Expr *p, *pR;
|
||||
if( pEList->a[i].zName ){
|
||||
pTab->aCol[i].zName = sqliteStrDup(pEList->a[i].zName);
|
||||
}else if( (p=pEList->a[i].pExpr)->span.z && p->span.z[0] ){
|
||||
aCol[i].zName = sqliteStrDup(pEList->a[i].zName);
|
||||
}else if( (p=pEList->a[i].pExpr)->op==TK_DOT
|
||||
&& (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
|
||||
int cnt;
|
||||
sqliteSetNString(&aCol[i].zName, pR->token.z, pR->token.n, 0);
|
||||
for(j=cnt=0; j<i; j++){
|
||||
if( sqliteStrICmp(aCol[j].zName, aCol[i].zName)==0 ){
|
||||
int n;
|
||||
char zBuf[30];
|
||||
sprintf(zBuf,"_%d",++cnt);
|
||||
n = strlen(zBuf);
|
||||
sqliteSetNString(&aCol[i].zName, pR->token.z, pR->token.n, zBuf, n,0);
|
||||
j = -1;
|
||||
}
|
||||
}
|
||||
}else if( p->span.z && p->span.z[0] ){
|
||||
sqliteSetNString(&pTab->aCol[i].zName, p->span.z, p->span.n, 0);
|
||||
}else if( p->op==TK_DOT && p->pRight && p->pRight->token.z &&
|
||||
p->pRight->token.z[0] ){
|
||||
sqliteSetNString(&pTab->aCol[i].zName,
|
||||
p->pRight->token.z, p->pRight->token.n, 0);
|
||||
}else{
|
||||
char zBuf[30];
|
||||
sprintf(zBuf, "column%d", i+1);
|
||||
|
@ -1262,7 +1267,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p){
|
|||
** |
|
||||
** `-----> SELECT b FROM t2
|
||||
** |
|
||||
** `------> SELECT c FROM t1
|
||||
** `------> SELECT a FROM t1
|
||||
**
|
||||
** The arrows in the diagram above represent the Select.pPrior pointer.
|
||||
** So if this routine is called with p equal to the t3 query, then
|
||||
|
@ -1485,14 +1490,6 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
|
|||
" do not have the same number of result columns", selectOpName(p->op));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Issue a null callback if that is what the user wants.
|
||||
*/
|
||||
if( eDest==SRT_Callback &&
|
||||
(pParse->useCallback==0 || (pParse->db->flags & SQLITE_NullCallback)!=0)
|
||||
){
|
||||
sqliteVdbeAddOp(v, OP_NullCallback, p->pEList->nExpr, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1512,25 +1509,29 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
|
|||
static void substExprList(ExprList*,int,ExprList*); /* Forward Decl */
|
||||
static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
|
||||
if( pExpr==0 ) return;
|
||||
if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable && pExpr->iColumn>=0 ){
|
||||
Expr *pNew;
|
||||
assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
|
||||
assert( pExpr->pLeft==0 && pExpr->pRight==0 && pExpr->pList==0 );
|
||||
pNew = pEList->a[pExpr->iColumn].pExpr;
|
||||
assert( pNew!=0 );
|
||||
pExpr->op = pNew->op;
|
||||
pExpr->dataType = pNew->dataType;
|
||||
assert( pExpr->pLeft==0 );
|
||||
pExpr->pLeft = sqliteExprDup(pNew->pLeft);
|
||||
assert( pExpr->pRight==0 );
|
||||
pExpr->pRight = sqliteExprDup(pNew->pRight);
|
||||
assert( pExpr->pList==0 );
|
||||
pExpr->pList = sqliteExprListDup(pNew->pList);
|
||||
pExpr->iTable = pNew->iTable;
|
||||
pExpr->iColumn = pNew->iColumn;
|
||||
pExpr->iAgg = pNew->iAgg;
|
||||
sqliteTokenCopy(&pExpr->token, &pNew->token);
|
||||
sqliteTokenCopy(&pExpr->span, &pNew->span);
|
||||
if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
|
||||
if( pExpr->iColumn<0 ){
|
||||
pExpr->op = TK_NULL;
|
||||
}else{
|
||||
Expr *pNew;
|
||||
assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
|
||||
assert( pExpr->pLeft==0 && pExpr->pRight==0 && pExpr->pList==0 );
|
||||
pNew = pEList->a[pExpr->iColumn].pExpr;
|
||||
assert( pNew!=0 );
|
||||
pExpr->op = pNew->op;
|
||||
pExpr->dataType = pNew->dataType;
|
||||
assert( pExpr->pLeft==0 );
|
||||
pExpr->pLeft = sqliteExprDup(pNew->pLeft);
|
||||
assert( pExpr->pRight==0 );
|
||||
pExpr->pRight = sqliteExprDup(pNew->pRight);
|
||||
assert( pExpr->pList==0 );
|
||||
pExpr->pList = sqliteExprListDup(pNew->pList);
|
||||
pExpr->iTable = pNew->iTable;
|
||||
pExpr->iColumn = pNew->iColumn;
|
||||
pExpr->iAgg = pNew->iAgg;
|
||||
sqliteTokenCopy(&pExpr->token, &pNew->token);
|
||||
sqliteTokenCopy(&pExpr->span, &pNew->span);
|
||||
}
|
||||
}else{
|
||||
substExpr(pExpr->pLeft, iTable, pEList);
|
||||
substExpr(pExpr->pRight, iTable, pEList);
|
||||
|
@ -1835,18 +1836,23 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
|||
Vdbe *v;
|
||||
int seekOp;
|
||||
int cont;
|
||||
ExprList eList;
|
||||
ExprList *pEList, *pList, eList;
|
||||
struct ExprList_item eListItem;
|
||||
SrcList *pSrc;
|
||||
|
||||
|
||||
/* Check to see if this query is a simple min() or max() query. Return
|
||||
** zero if it is not.
|
||||
*/
|
||||
if( p->pGroupBy || p->pHaving || p->pWhere ) return 0;
|
||||
if( p->pSrc->nSrc!=1 ) return 0;
|
||||
if( p->pEList->nExpr!=1 ) return 0;
|
||||
pExpr = p->pEList->a[0].pExpr;
|
||||
pSrc = p->pSrc;
|
||||
if( pSrc->nSrc!=1 ) return 0;
|
||||
pEList = p->pEList;
|
||||
if( pEList->nExpr!=1 ) return 0;
|
||||
pExpr = pEList->a[0].pExpr;
|
||||
if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
|
||||
if( pExpr->pList==0 || pExpr->pList->nExpr!=1 ) return 0;
|
||||
pList = pExpr->pList;
|
||||
if( pList==0 || pList->nExpr!=1 ) return 0;
|
||||
if( pExpr->token.n!=3 ) return 0;
|
||||
if( sqliteStrNICmp(pExpr->token.z,"min",3)==0 ){
|
||||
seekOp = OP_Rewind;
|
||||
|
@ -1855,10 +1861,10 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
|||
}else{
|
||||
return 0;
|
||||
}
|
||||
pExpr = pExpr->pList->a[0].pExpr;
|
||||
pExpr = pList->a[0].pExpr;
|
||||
if( pExpr->op!=TK_COLUMN ) return 0;
|
||||
iCol = pExpr->iColumn;
|
||||
pTab = p->pSrc->a[0].pTab;
|
||||
pTab = pSrc->a[0].pTab;
|
||||
|
||||
/* If we get to here, it means the query is of the correct form.
|
||||
** Check to make sure we have an index and make pIdx point to the
|
||||
|
@ -1886,24 +1892,30 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
|||
generateColumnTypes(pParse, p->pSrc, p->pEList);
|
||||
}
|
||||
|
||||
/* If the output is destined for a temporary table, open that table.
|
||||
*/
|
||||
if( eDest==SRT_TempTable ){
|
||||
sqliteVdbeAddOp(v, OP_OpenTemp, iParm, 0);
|
||||
}
|
||||
|
||||
/* Generating code to find the min or the max. Basically all we have
|
||||
** to do is find the first or the last entry in the chosen index. If
|
||||
** the min() or max() is on the INTEGER PRIMARY KEY, then find the first
|
||||
** or last entry in the main table.
|
||||
*/
|
||||
sqliteCodeVerifySchema(pParse, pTab->iDb);
|
||||
base = p->pSrc->a[0].iCursor;
|
||||
base = pSrc->a[0].iCursor;
|
||||
computeLimitRegisters(pParse, p);
|
||||
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
|
||||
sqliteVdbeAddOp(v, OP_OpenRead, base, pTab->tnum);
|
||||
sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
|
||||
if( pSrc->a[0].pSelect==0 ){
|
||||
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
|
||||
sqliteVdbeOp3(v, OP_OpenRead, base, pTab->tnum, pTab->zName, 0);
|
||||
}
|
||||
cont = sqliteVdbeMakeLabel(v);
|
||||
if( pIdx==0 ){
|
||||
sqliteVdbeAddOp(v, seekOp, base, 0);
|
||||
}else{
|
||||
sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
|
||||
sqliteVdbeAddOp(v, OP_OpenRead, base+1, pIdx->tnum);
|
||||
sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
|
||||
sqliteVdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, pIdx->zName, P3_STATIC);
|
||||
sqliteVdbeAddOp(v, seekOp, base+1, 0);
|
||||
sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0);
|
||||
sqliteVdbeAddOp(v, OP_Close, base+1, 0);
|
||||
|
@ -1916,6 +1928,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
|||
selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont);
|
||||
sqliteVdbeResolveLabel(v, cont);
|
||||
sqliteVdbeAddOp(v, OP_Close, base, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1935,7 +1948,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
|||
**
|
||||
** SRT_Union Store results as a key in a temporary table iParm
|
||||
**
|
||||
** SRT_Except Remove results form the temporary table iParm.
|
||||
** SRT_Except Remove results from the temporary table iParm.
|
||||
**
|
||||
** SRT_Table Store results in temporary table iParm
|
||||
**
|
||||
|
@ -2156,14 +2169,6 @@ int sqliteSelect(
|
|||
generateColumnNames(pParse, pTabList, pEList);
|
||||
}
|
||||
|
||||
/* Check for the special case of a min() or max() function by itself
|
||||
** in the result set.
|
||||
*/
|
||||
if( simpleMinMaxQuery(pParse, p, eDest, iParm) ){
|
||||
rc = 0;
|
||||
goto select_end;
|
||||
}
|
||||
|
||||
/* Generate code for all sub-queries in the FROM clause
|
||||
*/
|
||||
for(i=0; i<pTabList->nSrc; i++){
|
||||
|
@ -2193,6 +2198,14 @@ int sqliteSelect(
|
|||
isDistinct = p->isDistinct;
|
||||
}
|
||||
|
||||
/* Check for the special case of a min() or max() function by itself
|
||||
** in the result set.
|
||||
*/
|
||||
if( simpleMinMaxQuery(pParse, p, eDest, iParm) ){
|
||||
rc = 0;
|
||||
goto select_end;
|
||||
}
|
||||
|
||||
/* Check to see if this is a subquery that can be "flattened" into its parent.
|
||||
** If flattening is a possiblity, do so and return immediately.
|
||||
*/
|
||||
|
@ -2262,8 +2275,7 @@ int sqliteSelect(
|
|||
for(i=0; i<pParse->nAgg; i++){
|
||||
FuncDef *pFunc;
|
||||
if( (pFunc = pParse->aAgg[i].pFunc)!=0 && pFunc->xFinalize!=0 ){
|
||||
sqliteVdbeAddOp(v, OP_AggInit, 0, i);
|
||||
sqliteVdbeChangeP3(v, -1, (char*)pFunc, P3_POINTER);
|
||||
sqliteVdbeOp3(v, OP_AggInit, 0, i, (char*)pFunc, P3_POINTER);
|
||||
}
|
||||
}
|
||||
if( pGroupBy==0 ){
|
||||
|
@ -2308,6 +2320,7 @@ int sqliteSelect(
|
|||
** processing.
|
||||
*/
|
||||
else{
|
||||
AggExpr *pAgg;
|
||||
if( pGroupBy ){
|
||||
int lbl1;
|
||||
for(i=0; i<pGroupBy->nExpr; i++){
|
||||
|
@ -2317,29 +2330,27 @@ int sqliteSelect(
|
|||
if( pParse->db->file_format>=4 ) sqliteAddKeyType(v, pGroupBy);
|
||||
lbl1 = sqliteVdbeMakeLabel(v);
|
||||
sqliteVdbeAddOp(v, OP_AggFocus, 0, lbl1);
|
||||
for(i=0; i<pParse->nAgg; i++){
|
||||
if( pParse->aAgg[i].isAgg ) continue;
|
||||
sqliteExprCode(pParse, pParse->aAgg[i].pExpr);
|
||||
for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){
|
||||
if( pAgg->isAgg ) continue;
|
||||
sqliteExprCode(pParse, pAgg->pExpr);
|
||||
sqliteVdbeAddOp(v, OP_AggSet, 0, i);
|
||||
}
|
||||
sqliteVdbeResolveLabel(v, lbl1);
|
||||
}
|
||||
for(i=0; i<pParse->nAgg; i++){
|
||||
for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){
|
||||
Expr *pE;
|
||||
int j;
|
||||
if( !pParse->aAgg[i].isAgg ) continue;
|
||||
pE = pParse->aAgg[i].pExpr;
|
||||
int nExpr;
|
||||
FuncDef *pDef;
|
||||
if( !pAgg->isAgg ) continue;
|
||||
assert( pAgg->pFunc!=0 );
|
||||
assert( pAgg->pFunc->xStep!=0 );
|
||||
pDef = pAgg->pFunc;
|
||||
pE = pAgg->pExpr;
|
||||
assert( pE!=0 );
|
||||
assert( pE->op==TK_AGG_FUNCTION );
|
||||
if( pE->pList ){
|
||||
for(j=0; j<pE->pList->nExpr; j++){
|
||||
sqliteExprCode(pParse, pE->pList->a[j].pExpr);
|
||||
}
|
||||
}
|
||||
nExpr = sqliteExprCodeExprList(pParse, pE->pList, pDef->includeTypes);
|
||||
sqliteVdbeAddOp(v, OP_Integer, i, 0);
|
||||
sqliteVdbeAddOp(v, OP_AggFunc, 0, pE->pList ? pE->pList->nExpr : 0);
|
||||
assert( pParse->aAgg[i].pFunc!=0 );
|
||||
assert( pParse->aAgg[i].pFunc->xStep!=0 );
|
||||
sqliteVdbeChangeP3(v, -1, (char*)pParse->aAgg[i].pFunc, P3_POINTER);
|
||||
sqliteVdbeOp3(v, OP_AggFunc, 0, nExpr, (char*)pDef, P3_POINTER);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2375,13 +2386,16 @@ int sqliteSelect(
|
|||
generateSortTail(p, v, pEList->nExpr, eDest, iParm);
|
||||
}
|
||||
|
||||
|
||||
/* Issue a null callback if that is what the user wants.
|
||||
/* If this was a subquery, we have now converted the subquery into a
|
||||
** temporary table. So delete the subquery structure from the parent
|
||||
** to prevent this subquery from being evaluated again and to force the
|
||||
** the use of the temporary table.
|
||||
*/
|
||||
if( eDest==SRT_Callback &&
|
||||
(pParse->useCallback==0 || (pParse->db->flags & SQLITE_NullCallback)!=0)
|
||||
){
|
||||
sqliteVdbeAddOp(v, OP_NullCallback, pEList->nExpr, 0);
|
||||
if( pParent ){
|
||||
assert( pParent->pSrc->nSrc>parentTab );
|
||||
assert( pParent->pSrc->a[parentTab].pSelect==p );
|
||||
sqliteSelectDelete(p);
|
||||
pParent->pSrc->a[parentTab].pSelect = 0;
|
||||
}
|
||||
|
||||
/* The SELECT was successfully coded. Set the return code to 0
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue