1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Support FETCH FIRST WITH TIES

WITH TIES is an option to the FETCH FIRST N ROWS clause (the SQL
standard's spelling of LIMIT), where you additionally get rows that
compare equal to the last of those N rows by the columns in the
mandatory ORDER BY clause.

There was a proposal by Andrew Gierth to implement this functionality in
a more powerful way that would yield more features, but the other patch
had not been finished at this time, so we decided to use this one for
now in the spirit of incremental development.

Author: Surafel Temesgen <surafel3000@gmail.com>
Reviewed-by: Álvaro Herrera <alvherre@alvh.no-ip.org>
Reviewed-by: Tomas Vondra <tomas.vondra@2ndquadrant.com>
Discussion: https://postgr.es/m/CALAY4q9ky7rD_A4vf=FVQvCGngm3LOes-ky0J6euMrg=_Se+ag@mail.gmail.com
Discussion: https://postgr.es/m/87o8wvz253.fsf@news-spur.riddles.org.uk
This commit is contained in:
Alvaro Herrera
2020-04-07 16:22:13 -04:00
parent 26a944cf29
commit 357889eb17
25 changed files with 616 additions and 75 deletions

View File

@ -2378,7 +2378,9 @@ create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path)
plan = (Plan *) make_limit(plan,
subparse->limitOffset,
subparse->limitCount);
subparse->limitCount,
subparse->limitOption,
0, NULL, NULL, NULL);
/* Must apply correct cost/width data to Limit node */
plan->startup_cost = mminfo->path->startup_cost;
@ -2688,13 +2690,43 @@ create_limit_plan(PlannerInfo *root, LimitPath *best_path, int flags)
{
Limit *plan;
Plan *subplan;
int numUniqkeys = 0;
AttrNumber *uniqColIdx = NULL;
Oid *uniqOperators = NULL;
Oid *uniqCollations = NULL;
/* Limit doesn't project, so tlist requirements pass through */
subplan = create_plan_recurse(root, best_path->subpath, flags);
/* Extract information necessary for comparing rows for WITH TIES. */
if (best_path->limitOption == LIMIT_OPTION_WITH_TIES)
{
Query *parse = root->parse;
ListCell *l;
numUniqkeys = list_length(parse->sortClause);
uniqColIdx = (AttrNumber *) palloc(numUniqkeys * sizeof(AttrNumber));
uniqOperators = (Oid *) palloc(numUniqkeys * sizeof(Oid));
uniqCollations = (Oid *) palloc(numUniqkeys * sizeof(Oid));
numUniqkeys = 0;
foreach(l, parse->sortClause)
{
SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
TargetEntry *tle = get_sortgroupclause_tle(sortcl, parse->targetList);
uniqColIdx[numUniqkeys] = tle->resno;
uniqOperators[numUniqkeys] = sortcl->eqop;
uniqCollations[numUniqkeys] = exprCollation((Node *) tle->expr);
numUniqkeys++;
}
}
plan = make_limit(subplan,
best_path->limitOffset,
best_path->limitCount);
best_path->limitCount,
best_path->limitOption,
numUniqkeys, uniqColIdx, uniqOperators, uniqCollations);
copy_generic_path_info(&plan->plan, (Path *) best_path);
@ -6672,7 +6704,9 @@ make_lockrows(Plan *lefttree, List *rowMarks, int epqParam)
* Build a Limit plan node
*/
Limit *
make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount)
make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount,
LimitOption limitOption, int uniqNumCols, AttrNumber *uniqColIdx,
Oid *uniqOperators, Oid *uniqCollations)
{
Limit *node = makeNode(Limit);
Plan *plan = &node->plan;
@ -6684,6 +6718,11 @@ make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount)
node->limitOffset = limitOffset;
node->limitCount = limitCount;
node->limitOption = limitOption;
node->uniqNumCols = uniqNumCols;
node->uniqColIdx = uniqColIdx;
node->uniqOperators = uniqOperators;
node->uniqCollations = uniqCollations;
return node;
}