Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit99114a2

Browse files
author
Neil Conway
committed
Per recent discussion on -hackers, we should sometimes reorder the
columns of the grouping clause to avoid redundant sorts. The optimizeris not currently capable of doing this, so this patch implements asimple hack in the analysis phase (transformGroupClause): if anysubset of the GROUP BY clause matches a prefix of the ORDER BY list,that prefix is moved to the front of the GROUP BY clause. Thisshouldn't change the semantics of the query, and allows a redundantsort to be avoided for queries like "GROUP BY a, b ORDER BY b".
1 parentf9520ac commit99114a2

File tree

1 file changed

+85
-41
lines changed

1 file changed

+85
-41
lines changed

‎src/backend/parser/parse_clause.c

Lines changed: 85 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.146 2006/03/0515:58:33 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.147 2006/03/0521:34:34 neilc Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1296,78 +1296,122 @@ findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause)
12961296
returntarget_result;
12971297
}
12981298

1299+
staticGroupClause*
1300+
make_group_clause(TargetEntry*tle,List*targetlist,Oidsortop)
1301+
{
1302+
GroupClause*result;
1303+
1304+
result=makeNode(GroupClause);
1305+
result->tleSortGroupRef=assignSortGroupRef(tle,targetlist);
1306+
result->sortop=sortop;
1307+
returnresult;
1308+
}
12991309

13001310
/*
13011311
* transformGroupClause -
13021312
* transform a GROUP BY clause
13031313
*
13041314
* GROUP BY items will be added to the targetlist (as resjunk columns)
13051315
* if not already present, so the targetlist must be passed by reference.
1316+
*
1317+
* The order of the elements of the grouping clause does not affect
1318+
* the semantics of the query. However, the optimizer is not currently
1319+
* smart enough to reorder the grouping clause, so we try to do some
1320+
* primitive reordering here.
13061321
*/
13071322
List*
13081323
transformGroupClause(ParseState*pstate,List*grouplist,
13091324
List**targetlist,List*sortClause)
13101325
{
1311-
List*glist=NIL;
1312-
ListCell*gl;
1313-
ListCell*sortItem;
1314-
1315-
sortItem=list_head(sortClause);
1326+
List*result=NIL;
1327+
List*tle_list=NIL;
1328+
ListCell*l;
13161329

1317-
foreach(gl,grouplist)
1330+
/* Preprocess the grouping clause, lookup TLEs */
1331+
foreach (l,grouplist)
13181332
{
13191333
TargetEntry*tle;
1320-
Oidrestype;
1321-
Oidordering_op;
1322-
GroupClause*grpcl;
1334+
Oidrestype;
13231335

1324-
tle=findTargetlistEntry(pstate,lfirst(gl),
1336+
tle=findTargetlistEntry(pstate,lfirst(l),
13251337
targetlist,GROUP_CLAUSE);
13261338

1327-
/* avoid making duplicate grouplist entries */
1328-
if (targetIsInSortList(tle,glist))
1329-
continue;
1330-
13311339
/* if tlist item is an UNKNOWN literal, change it to TEXT */
13321340
restype=exprType((Node*)tle->expr);
13331341

13341342
if (restype==UNKNOWNOID)
1335-
{
13361343
tle->expr= (Expr*)coerce_type(pstate, (Node*)tle->expr,
13371344
restype,TEXTOID,-1,
13381345
COERCION_IMPLICIT,
13391346
COERCE_IMPLICIT_CAST);
1340-
restype=TEXTOID;
1341-
}
13421347

1343-
/*
1344-
* If the GROUP BY clause matches the ORDER BY clause, we want to
1345-
* adopt the ordering operators from the latter rather than using the
1346-
* default ops. This allows "GROUP BY foo ORDER BY foo DESC" to be
1347-
* done with only one sort step. Note we are assuming that any
1348-
* user-supplied ordering operator will bring equal values together,
1349-
* which is all that GROUP BY needs.
1350-
*/
1351-
if (sortItem&&
1352-
((SortClause*)lfirst(sortItem))->tleSortGroupRef==
1353-
tle->ressortgroupref)
1354-
{
1355-
ordering_op= ((SortClause*)lfirst(sortItem))->sortop;
1356-
sortItem=lnext(sortItem);
1357-
}
1358-
else
1348+
tle_list=lappend(tle_list,tle);
1349+
}
1350+
1351+
/*
1352+
* Now iterate through the ORDER BY clause. If we find a grouping
1353+
* element that matches the ORDER BY element, append the grouping
1354+
* element to the result set immediately. Otherwise, stop
1355+
* iterating. The effect of this is to look for a prefix of the
1356+
* ORDER BY list in the grouping clauses, and to move that prefix
1357+
* to the front of the GROUP BY.
1358+
*/
1359+
foreach (l,sortClause)
1360+
{
1361+
SortClause*sc= (SortClause*)lfirst(l);
1362+
ListCell*prev=NULL;
1363+
ListCell*tl;
1364+
boolfound= false;
1365+
1366+
foreach (tl,tle_list)
13591367
{
1360-
ordering_op=ordering_oper_opid(restype);
1361-
sortItem=NULL;/* disregard ORDER BY once match fails */
1368+
TargetEntry*tle= (TargetEntry*)lfirst(tl);
1369+
1370+
if (sc->tleSortGroupRef==tle->ressortgroupref)
1371+
{
1372+
GroupClause*gc;
1373+
1374+
tle_list=list_delete_cell(tle_list,tl,prev);
1375+
1376+
/* Use the sort clause's sorting operator */
1377+
gc=make_group_clause(tle,*targetlist,sc->sortop);
1378+
result=lappend(result,gc);
1379+
found= true;
1380+
break;
1381+
}
1382+
1383+
prev=tl;
13621384
}
13631385

1364-
grpcl=makeNode(GroupClause);
1365-
grpcl->tleSortGroupRef=assignSortGroupRef(tle,*targetlist);
1366-
grpcl->sortop=ordering_op;
1367-
glist=lappend(glist,grpcl);
1386+
/* As soon as we've failed to match an ORDER BY element, stop */
1387+
if (!found)
1388+
break;
13681389
}
13691390

1370-
returnglist;
1391+
/*
1392+
* Now add any remaining elements of the GROUP BY list in the
1393+
* order we received them.
1394+
*
1395+
* XXX: are there any additional criteria to consider when
1396+
* ordering grouping clauses?
1397+
*/
1398+
foreach(l,tle_list)
1399+
{
1400+
TargetEntry*tle= (TargetEntry*)lfirst(l);
1401+
GroupClause*gc;
1402+
Oidsort_op;
1403+
1404+
/* avoid making duplicate grouplist entries */
1405+
if (targetIsInSortList(tle,result))
1406+
continue;
1407+
1408+
sort_op=ordering_oper_opid(exprType((Node*)tle->expr));
1409+
gc=make_group_clause(tle,*targetlist,sort_op);
1410+
result=lappend(result,gc);
1411+
}
1412+
1413+
list_free(tle_list);
1414+
returnresult;
13711415
}
13721416

13731417
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp