diff options
Diffstat (limited to 'ext/sqlite/libsqlite/src/select.c')
-rw-r--r-- | ext/sqlite/libsqlite/src/select.c | 254 |
1 files changed, 134 insertions, 120 deletions
diff --git a/ext/sqlite/libsqlite/src/select.c b/ext/sqlite/libsqlite/src/select.c index c7525b3b6b..871f2e2c71 100644 --- a/ext/sqlite/libsqlite/src/select.c +++ b/ext/sqlite/libsqlite/src/select.c @@ -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 |