> > Prevent sorting if result is already sorted
> > > > was implemented by Jan Wieck. > > His work is for ascending order cases. > > > > Here is a patch to prevent sorting also in descending > > order cases. > > Because I had already changed _bt_first() to position > > backward correctly before v6.5,this patch would work. > > Hiroshi Inoue Inoue@tpf.co.jp
This commit is contained in:
parent
5efe31214a
commit
158fd5f1c4
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994-5, Regents of the University of California
|
* Copyright (c) 1994-5, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: explain.c,v 1.43 1999/07/17 20:16:52 momjian Exp $
|
* $Id: explain.c,v 1.44 1999/08/09 06:20:21 momjian Exp $
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -200,6 +200,8 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
|
|||||||
switch (nodeTag(plan))
|
switch (nodeTag(plan))
|
||||||
{
|
{
|
||||||
case T_IndexScan:
|
case T_IndexScan:
|
||||||
|
if (ScanDirectionIsBackward(((IndexScan *)plan)->indxorderdir))
|
||||||
|
appendStringInfo(str, " Backward");
|
||||||
appendStringInfo(str, " using ");
|
appendStringInfo(str, " using ");
|
||||||
i = 0;
|
i = 0;
|
||||||
foreach(l, ((IndexScan *) plan)->indxid)
|
foreach(l, ((IndexScan *) plan)->indxid)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.40 1999/07/16 04:58:50 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.41 1999/08/09 06:20:22 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -99,6 +99,13 @@ IndexNext(IndexScan *node)
|
|||||||
*/
|
*/
|
||||||
estate = node->scan.plan.state;
|
estate = node->scan.plan.state;
|
||||||
direction = estate->es_direction;
|
direction = estate->es_direction;
|
||||||
|
if (ScanDirectionIsBackward(node->indxorderdir))
|
||||||
|
{
|
||||||
|
if (ScanDirectionIsForward(direction))
|
||||||
|
direction = BackwardScanDirection;
|
||||||
|
else if (ScanDirectionIsBackward(direction))
|
||||||
|
direction = ForwardScanDirection;
|
||||||
|
}
|
||||||
snapshot = estate->es_snapshot;
|
snapshot = estate->es_snapshot;
|
||||||
scanstate = node->scan.scanstate;
|
scanstate = node->scan.scanstate;
|
||||||
indexstate = node->indxstate;
|
indexstate = node->indxstate;
|
||||||
@ -316,6 +323,8 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
|
|||||||
indxqual = node->indxqual;
|
indxqual = node->indxqual;
|
||||||
numScanKeys = indexstate->iss_NumScanKeys;
|
numScanKeys = indexstate->iss_NumScanKeys;
|
||||||
indexstate->iss_IndexPtr = -1;
|
indexstate->iss_IndexPtr = -1;
|
||||||
|
if (ScanDirectionIsBackward(node->indxorderdir))
|
||||||
|
indexstate->iss_IndexPtr = numIndices;
|
||||||
|
|
||||||
/* If this is re-scanning of PlanQual ... */
|
/* If this is re-scanning of PlanQual ... */
|
||||||
if (estate->es_evTuple != NULL &&
|
if (estate->es_evTuple != NULL &&
|
||||||
@ -966,6 +975,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
indexstate->iss_NumIndices = numIndices;
|
indexstate->iss_NumIndices = numIndices;
|
||||||
|
if (ScanDirectionIsBackward(node->indxorderdir))
|
||||||
|
indexPtr = numIndices;
|
||||||
indexstate->iss_IndexPtr = indexPtr;
|
indexstate->iss_IndexPtr = indexPtr;
|
||||||
indexstate->iss_ScanKeys = scanKeys;
|
indexstate->iss_ScanKeys = scanKeys;
|
||||||
indexstate->iss_NumScanKeys = numScanKeys;
|
indexstate->iss_NumScanKeys = numScanKeys;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.89 1999/07/27 03:51:07 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.90 1999/08/09 06:20:23 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -238,6 +238,7 @@ _copyIndexScan(IndexScan *from)
|
|||||||
newnode->indxid = listCopy(from->indxid);
|
newnode->indxid = listCopy(from->indxid);
|
||||||
Node_Copy(from, newnode, indxqual);
|
Node_Copy(from, newnode, indxqual);
|
||||||
Node_Copy(from, newnode, indxqualorig);
|
Node_Copy(from, newnode, indxqualorig);
|
||||||
|
newnode->indxorderdir = from->indxorderdir;
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.45 1999/07/29 02:45:36 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.46 1999/08/09 06:20:24 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -437,6 +437,9 @@ _equalIndexScan(IndexScan *a, IndexScan *b)
|
|||||||
if (a->scan.scanrelid != b->scan.scanrelid)
|
if (a->scan.scanrelid != b->scan.scanrelid)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (a->indxorderdir != b->indxorderdir)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!equali(a->indxid, b->indxid))
|
if (!equali(a->indxid, b->indxid))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: outfuncs.c,v 1.91 1999/07/24 23:21:07 tgl Exp $
|
* $Id: outfuncs.c,v 1.92 1999/08/09 06:20:24 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Every (plan) node in POSTGRES has an associated "out" routine which
|
* Every (plan) node in POSTGRES has an associated "out" routine which
|
||||||
@ -445,6 +445,7 @@ _outIndexScan(StringInfo str, IndexScan *node)
|
|||||||
appendStringInfo(str, " :indxqualorig ");
|
appendStringInfo(str, " :indxqualorig ");
|
||||||
_outNode(str, node->indxqualorig);
|
_outNode(str, node->indxqualorig);
|
||||||
|
|
||||||
|
appendStringInfo(str, " :indxorderdir %d ", node->indxorderdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.70 1999/07/24 23:21:08 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.71 1999/08/09 06:20:24 momjian Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Most of the read functions for plan nodes are tested. (In fact, they
|
* Most of the read functions for plan nodes are tested. (In fact, they
|
||||||
@ -532,6 +532,11 @@ _readIndexScan()
|
|||||||
token = lsptok(NULL, &length); /* eat :indxqualorig */
|
token = lsptok(NULL, &length); /* eat :indxqualorig */
|
||||||
local_node->indxqualorig = nodeRead(true); /* now read it */
|
local_node->indxqualorig = nodeRead(true); /* now read it */
|
||||||
|
|
||||||
|
token = lsptok(NULL, &length); /* eat :indxorderdir */
|
||||||
|
token = lsptok(NULL, &length); /* get indxorderdir */
|
||||||
|
|
||||||
|
local_node->indxorderdir = atoi(token);
|
||||||
|
|
||||||
return local_node;
|
return local_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.67 1999/08/09 01:01:42 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.68 1999/08/09 06:20:26 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1024,6 +1024,7 @@ make_indexscan(List *qptlist,
|
|||||||
node->indxid = indxid;
|
node->indxid = indxid;
|
||||||
node->indxqual = indxqual;
|
node->indxqual = indxqual;
|
||||||
node->indxqualorig = indxqualorig;
|
node->indxqualorig = indxqualorig;
|
||||||
|
node->indxorderdir = NoMovementScanDirection;
|
||||||
node->scan.scanstate = (CommonScanState *) NULL;
|
node->scan.scanstate = (CommonScanState *) NULL;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.61 1999/07/17 20:17:15 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.62 1999/08/09 06:20:26 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -39,7 +39,7 @@ static List *make_subplanTargetList(Query *parse, List *tlist,
|
|||||||
static Plan *make_groupplan(List *group_tlist, bool tuplePerGroup,
|
static Plan *make_groupplan(List *group_tlist, bool tuplePerGroup,
|
||||||
List *groupClause, AttrNumber *grpColIdx,
|
List *groupClause, AttrNumber *grpColIdx,
|
||||||
Plan *subplan);
|
Plan *subplan);
|
||||||
static bool need_sortplan(List *sortcls, Plan *plan);
|
static ScanDirection get_dir_to_omit_sortplan(List *sortcls, Plan *plan);
|
||||||
static Plan *make_sortplan(List *tlist, List *sortcls, Plan *plannode);
|
static Plan *make_sortplan(List *tlist, List *sortcls, Plan *plannode);
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@ -303,8 +303,17 @@ union_planner(Query *parse)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (parse->sortClause && need_sortplan(parse->sortClause, result_plan))
|
if (parse->sortClause)
|
||||||
return (make_sortplan(tlist, parse->sortClause, result_plan));
|
{
|
||||||
|
ScanDirection dir = get_dir_to_omit_sortplan(parse->sortClause, result_plan);
|
||||||
|
if (ScanDirectionIsNoMovement(dir))
|
||||||
|
return (make_sortplan(tlist, parse->sortClause, result_plan));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
((IndexScan *)result_plan)->indxorderdir = dir;
|
||||||
|
return ((Plan *) result_plan);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return ((Plan *) result_plan);
|
return ((Plan *) result_plan);
|
||||||
}
|
}
|
||||||
@ -822,7 +831,7 @@ pg_checkretval(Oid rettype, List *queryTreeList)
|
|||||||
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Support function for need_sortplan
|
* Support function for get scan direction to omit sortplan
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
static TargetEntry *
|
static TargetEntry *
|
||||||
@ -845,11 +854,13 @@ get_matching_tle(Plan *plan, Resdom *resdom)
|
|||||||
* Check if a user requested ORDER BY is already satisfied by
|
* Check if a user requested ORDER BY is already satisfied by
|
||||||
* the choosen index scan.
|
* the choosen index scan.
|
||||||
*
|
*
|
||||||
* Returns TRUE if sort is required, FALSE if can be omitted.
|
* Returns the direction of Index scan to omit sort,
|
||||||
|
* if sort is required returns NoMovementScanDirection
|
||||||
|
*
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
static bool
|
static ScanDirection
|
||||||
need_sortplan(List *sortcls, Plan *plan)
|
get_dir_to_omit_sortplan(List *sortcls, Plan *plan)
|
||||||
{
|
{
|
||||||
Relation indexRel;
|
Relation indexRel;
|
||||||
IndexScan *indexScan;
|
IndexScan *indexScan;
|
||||||
@ -858,13 +869,15 @@ need_sortplan(List *sortcls, Plan *plan)
|
|||||||
HeapTuple htup;
|
HeapTuple htup;
|
||||||
Form_pg_index index_tup;
|
Form_pg_index index_tup;
|
||||||
int key_no = 0;
|
int key_no = 0;
|
||||||
|
ScanDirection dir, nodir = NoMovementScanDirection;
|
||||||
|
|
||||||
|
dir = nodir;
|
||||||
/* ----------
|
/* ----------
|
||||||
* Must be an IndexScan
|
* Must be an IndexScan
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
if (nodeTag(plan) != T_IndexScan)
|
if (nodeTag(plan) != T_IndexScan)
|
||||||
return TRUE;
|
return nodir;
|
||||||
|
|
||||||
indexScan = (IndexScan *) plan;
|
indexScan = (IndexScan *) plan;
|
||||||
|
|
||||||
@ -873,16 +886,16 @@ need_sortplan(List *sortcls, Plan *plan)
|
|||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
if (plan->lefttree != NULL)
|
if (plan->lefttree != NULL)
|
||||||
return TRUE;
|
return nodir;
|
||||||
if (plan->righttree != NULL)
|
if (plan->righttree != NULL)
|
||||||
return TRUE;
|
return nodir;
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Must be a single index scan
|
* Must be a single index scan
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
if (length(indexScan->indxid) != 1)
|
if (length(indexScan->indxid) != 1)
|
||||||
return TRUE;
|
return nodir;
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Indices can only have up to 8 attributes. So an ORDER BY using
|
* Indices can only have up to 8 attributes. So an ORDER BY using
|
||||||
@ -890,7 +903,7 @@ need_sortplan(List *sortcls, Plan *plan)
|
|||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
if (length(sortcls) > 8)
|
if (length(sortcls) > 8)
|
||||||
return TRUE;
|
return nodir;
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* The choosen Index must be a btree
|
* The choosen Index must be a btree
|
||||||
@ -902,7 +915,7 @@ need_sortplan(List *sortcls, Plan *plan)
|
|||||||
if (strcmp(nameout(&(indexRel->rd_am->amname)), "btree") != 0)
|
if (strcmp(nameout(&(indexRel->rd_am->amname)), "btree") != 0)
|
||||||
{
|
{
|
||||||
heap_close(indexRel);
|
heap_close(indexRel);
|
||||||
return TRUE;
|
return nodir;
|
||||||
}
|
}
|
||||||
heap_close(indexRel);
|
heap_close(indexRel);
|
||||||
|
|
||||||
@ -937,7 +950,7 @@ need_sortplan(List *sortcls, Plan *plan)
|
|||||||
* Could this happen?
|
* Could this happen?
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
return TRUE;
|
return nodir;
|
||||||
}
|
}
|
||||||
if (nodeTag(tle->expr) != T_Var)
|
if (nodeTag(tle->expr) != T_Var)
|
||||||
{
|
{
|
||||||
@ -946,7 +959,7 @@ need_sortplan(List *sortcls, Plan *plan)
|
|||||||
* cannot be the indexed attribute
|
* cannot be the indexed attribute
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
return TRUE;
|
return nodir;
|
||||||
}
|
}
|
||||||
var = (Var *) (tle->expr);
|
var = (Var *) (tle->expr);
|
||||||
|
|
||||||
@ -957,7 +970,7 @@ need_sortplan(List *sortcls, Plan *plan)
|
|||||||
* that of the index
|
* that of the index
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
return TRUE;
|
return nodir;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (var->varattno != index_tup->indkey[key_no])
|
if (var->varattno != index_tup->indkey[key_no])
|
||||||
@ -966,7 +979,7 @@ need_sortplan(List *sortcls, Plan *plan)
|
|||||||
* It isn't the indexed attribute.
|
* It isn't the indexed attribute.
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
return TRUE;
|
return nodir;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oprid(oper("<", resdom->restype, resdom->restype, FALSE)) != sortcl->opoid)
|
if (oprid(oper("<", resdom->restype, resdom->restype, FALSE)) != sortcl->opoid)
|
||||||
@ -975,7 +988,19 @@ need_sortplan(List *sortcls, Plan *plan)
|
|||||||
* Sort order isn't in ascending order.
|
* Sort order isn't in ascending order.
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
return TRUE;
|
if (ScanDirectionIsForward(dir))
|
||||||
|
return nodir;
|
||||||
|
dir = BackwardScanDirection;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* ----------
|
||||||
|
* Sort order is in ascending order.
|
||||||
|
* ----------
|
||||||
|
*/
|
||||||
|
if (ScanDirectionIsBackward(dir))
|
||||||
|
return nodir;
|
||||||
|
dir = ForwardScanDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
key_no++;
|
key_no++;
|
||||||
@ -985,5 +1010,5 @@ need_sortplan(List *sortcls, Plan *plan)
|
|||||||
* Index matches ORDER BY - sort not required
|
* Index matches ORDER BY - sort not required
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
return FALSE;
|
return dir;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: plannodes.h,v 1.28 1999/07/15 23:03:55 momjian Exp $
|
* $Id: plannodes.h,v 1.29 1999/08/09 06:20:27 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -175,6 +175,7 @@ typedef struct IndexScan
|
|||||||
List *indxid;
|
List *indxid;
|
||||||
List *indxqual;
|
List *indxqual;
|
||||||
List *indxqualorig;
|
List *indxqualorig;
|
||||||
|
ScanDirection indxorderdir;
|
||||||
IndexScanState *indxstate;
|
IndexScanState *indxstate;
|
||||||
} IndexScan;
|
} IndexScan;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user