From: drh Date: Mon, 24 Sep 2012 15:30:54 +0000 (+0000) Subject: Change the internal sqlite3WhereBegin() to report that the ORDER BY clause X-Git-Tag: version-3.7.15~116 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=46ec5b63e2534242a7c608fab9c663eb3af62c81;p=thirdparty%2Fsqlite.git Change the internal sqlite3WhereBegin() to report that the ORDER BY clause is satisfied by indices using the WhereInfo.nOBSat field of the returned structure. FossilOrigin-Name: 22989f3588531efd555cc29d6c576e7a34b7edc4 --- diff --git a/manifest b/manifest index 8f9cec3047..534ea306e5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sdocumentation\sto\sdescribe\sthe\sthreadsafety\sof\s\nsqlite3_enable_shared_cache(). -D 2012-09-24T11:43:43.748 +C Change\sthe\sinternal\ssqlite3WhereBegin()\sto\sreport\sthat\sthe\sORDER\sBY\sclause\nis\ssatisfied\sby\sindices\susing\sthe\sWhereInfo.nOBSat\sfield\sof\sthe\sreturned\nstructure. +D 2012-09-24T15:30:54.533 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f4f26109f9d80829122e0e09f9cda008fa065fb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -174,12 +174,12 @@ F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 9e28280ec98035f31900fdd1db01f86f68ca6c32 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c c2a83ada835d3554a4d724c5358d4475aa7e1e77 +F src/select.c 1fad66b73a69c4004c9969a95b46d1f03390677d F src/shell.c 8ee5a3cb502e2d574f97b43972e6c1e275e7bec7 F src/sqlite.h.in cbe846facaba903654b4136c97e7f57b3ac0bac7 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 -F src/sqliteInt.h 6d02f0bbca677887bbbe1a69c69cdde6f54adb9c +F src/sqliteInt.h 6b17114bb5c6ae30d360aeeef30ab40587afad4e F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -249,7 +249,7 @@ F src/vtab.c d8020c0a0e8ccc490ca449d7e665311b6e9f3ba9 F src/wal.c 5acb3e7bbd31f10ba39acad9ce6b399055337a9d F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6 F src/walker.c 3d75ba73de15e0f8cd0737643badbeb0e002f07b -F src/where.c 3b52eeffab96e6ee3e1593af0967206cde09c221 +F src/where.c af126a6cdb290c2d79ef18bb41bbca949c9cad61 F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 0be144b453e0622a085fae8665c32f5676708e00 @@ -1016,7 +1016,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 67d8a99aceb56384a81b3f30d6c71743146d2cc9 -P 1be4b16b9e900181ae6848f2920ea646f407c9dc -R 0efc5261436fa50b53879d926ef0509e +P e081890cd77ad8de4bf55a8f8cf9d63bfaaf8218 +R 4ad3ce4fdebd545cd663ab5469164871 U drh -Z f86abf9bd38d08dcead454a5f06f2799 +Z 1dbcfbc31e18555fa81506ef779ada01 diff --git a/manifest.uuid b/manifest.uuid index 11bb5536da..79fb09f471 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e081890cd77ad8de4bf55a8f8cf9d63bfaaf8218 \ No newline at end of file +22989f3588531efd555cc29d6c576e7a34b7edc4 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 39787de80a..01fe27694f 100644 --- a/src/select.c +++ b/src/select.c @@ -4098,10 +4098,11 @@ int sqlite3Select( ExprList *pDist = (sDistinct.isTnct ? p->pEList : 0); /* Begin the database scan. */ - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0,0); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0,0); if( pWInfo==0 ) goto select_end; if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut; if( pWInfo->eDistinct ) sDistinct.eTnctType = pWInfo->eDistinct; + if( pOrderBy && pWInfo->nOBSat==pOrderBy->nExpr ) pOrderBy = 0; /* If sorting index that was created by a prior OP_OpenEphemeral ** instruction ended up not being needed, then change the OP_OpenEphemeral @@ -4229,14 +4230,13 @@ int sqlite3Select( ** in the right order to begin with. */ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0, 0); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, 0, 0); if( pWInfo==0 ) goto select_end; - if( pGroupBy==0 ){ + if( pWInfo->nOBSat==pGroupBy->nExpr ){ /* The optimizer is able to deliver rows in group by order so ** we do not have to sort. The OP_OpenEphemeral table will be ** cancelled later because we still need to use the pKeyInfo */ - pGroupBy = p->pGroupBy; groupBySort = 0; }else{ /* Rows are coming out in undetermined order. We have to push @@ -4486,6 +4486,7 @@ int sqlite3Select( u8 flag = minMaxQuery(p); if( flag ){ assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) ); + assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 ); pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0); pDel = pMinMax; if( pMinMax && !db->mallocFailed ){ @@ -4499,13 +4500,13 @@ int sqlite3Select( ** of output. */ resetAccumulator(pParse, &sAggInfo); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax,0,flag,0); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0); if( pWInfo==0 ){ sqlite3ExprListDelete(db, pDel); goto select_end; } updateAccumulator(pParse, &sAggInfo); - if( !pMinMax && flag ){ + if( pWInfo->nOBSat>0 ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak); VdbeComment((v, "%s() by index", (flag==WHERE_ORDERBY_MIN?"min":"max"))); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 7701b6d7cb..7b9894254a 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1982,20 +1982,21 @@ struct WhereLevel { ** into the second half to give some continuity. */ struct WhereInfo { - Parse *pParse; /* Parsing and code generating context */ - u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ - u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */ - u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ - u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */ - SrcList *pTabList; /* List of tables in the join */ - int iTop; /* The very beginning of the WHERE loop */ - int iContinue; /* Jump here to continue with next record */ - int iBreak; /* Jump here to break out of the loop */ - int nLevel; /* Number of nested loop */ - struct WhereClause *pWC; /* Decomposition of the WHERE clause */ - double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ - double nRowOut; /* Estimated number of output rows */ - WhereLevel a[1]; /* Information about each nest loop in WHERE */ + Parse *pParse; /* Parsing and code generating context */ + SrcList *pTabList; /* List of tables in the join */ + u16 nOBSat; /* Number of ORDER BY terms satisfied by indices */ + u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ + u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */ + u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ + u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */ + int iTop; /* The very beginning of the WHERE loop */ + int iContinue; /* Jump here to continue with next record */ + int iBreak; /* Jump here to break out of the loop */ + int nLevel; /* Number of nested loop */ + struct WhereClause *pWC; /* Decomposition of the WHERE clause */ + double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ + double nRowOut; /* Estimated number of output rows */ + WhereLevel a[1]; /* Information about each nest loop in WHERE */ }; /* Allowed values for WhereInfo.eDistinct and DistinctCtx.eTnctType */ @@ -2811,8 +2812,7 @@ Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, #endif void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); -WhereInfo *sqlite3WhereBegin( - Parse*,SrcList*,Expr*,ExprList**,ExprList*,u16,int); +WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); void sqlite3WhereEnd(WhereInfo*); int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); diff --git a/src/where.c b/src/where.c index d5a1f41f80..ba885f1304 100644 --- a/src/where.c +++ b/src/where.c @@ -4667,24 +4667,24 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ ** ** ORDER BY CLAUSE PROCESSING ** -** *ppOrderBy is a pointer to the ORDER BY clause of a SELECT statement, +** pOrderBy is a pointer to the ORDER BY clause of a SELECT statement, ** if there is one. If there is no ORDER BY clause or if this routine -** is called from an UPDATE or DELETE statement, then ppOrderBy is NULL. +** is called from an UPDATE or DELETE statement, then pOrderBy is NULL. ** ** If an index can be used so that the natural output order of the table ** scan is correct for the ORDER BY clause, then that index is used and -** *ppOrderBy is set to NULL. This is an optimization that prevents an -** unnecessary sort of the result set if an index appropriate for the -** ORDER BY clause already exists. +** the returned WhereInfo.nOBSat field is set to pOrderBy->nExpr. This +** is an optimization that prevents an unnecessary sort of the result set +** if an index appropriate for the ORDER BY clause already exists. ** ** If the where clause loops cannot be arranged to provide the correct -** output order, then the *ppOrderBy is unchanged. +** output order, then WhereInfo.nOBSat is 0. */ WhereInfo *sqlite3WhereBegin( Parse *pParse, /* The parser context */ SrcList *pTabList, /* A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ - ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */ + ExprList *pOrderBy, /* An ORDER BY clause, or NULL */ ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */ u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ int iIdxCur /* If WHERE_ONETABLE_ONLY is set, index cursor number */ @@ -4909,7 +4909,7 @@ WhereInfo *sqlite3WhereBegin( for(j=iFrom, pTabItem=&pTabList->a[j]; jjointype & (JT_LEFT|JT_CROSS))!=0; @@ -4920,7 +4920,7 @@ WhereInfo *sqlite3WhereBegin( continue; } mask = (isOptimal ? m : notReady); - pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0); + pOB = (i==0) ? pOrderBy : 0; pDist = (i==0 ? pDistinct : 0); if( pTabItem->pIndex==0 ) nUnconstrained++; @@ -4930,12 +4930,12 @@ WhereInfo *sqlite3WhereBegin( #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTabItem->pTab) ){ sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo; - bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy, + bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOB, &sCost, pp); }else #endif { - bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy, + bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOB, pDist, &sCost); } assert( isOptimal || (sCost.used¬Ready)==0 ); @@ -4995,8 +4995,8 @@ WhereInfo *sqlite3WhereBegin( " with cost=%g and nRow=%g\n", bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow)); /* The ALWAYS() that follows was added to hush up clang scan-build */ - if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 && ALWAYS(ppOrderBy) ){ - *ppOrderBy = 0; + if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 ){ + pWInfo->nOBSat = pOrderBy->nExpr; } if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){ assert( pWInfo->eDistinct==0 ); @@ -5049,8 +5049,8 @@ WhereInfo *sqlite3WhereBegin( /* If the total query only selects a single row, then the ORDER BY ** clause is irrelevant. */ - if( (andFlags & WHERE_UNIQUE)!=0 && ppOrderBy ){ - *ppOrderBy = 0; + if( (andFlags & WHERE_UNIQUE)!=0 && pOrderBy ){ + pWInfo->nOBSat = pOrderBy->nExpr; } /* If the caller is an UPDATE or DELETE statement that is requesting