diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 460fdcc1f91254bf14094acd438fc8910b8c1319..31a8d9d3679fb91cb3df4f22ad8d933364899785 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -4,7 +4,7 @@ * * 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)) { case T_IndexScan: + if (ScanDirectionIsBackward(((IndexScan *)plan)->indxorderdir)) + appendStringInfo(str, " Backward"); appendStringInfo(str, " using "); i = 0; foreach(l, ((IndexScan *) plan)->indxid) diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 0a35cf2cf8c360797476d3327452880533b57634..7be2f1b8c99a40f23929155a547fc513e061309b 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -7,7 +7,7 @@ * * * 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; direction = estate->es_direction; + if (ScanDirectionIsBackward(node->indxorderdir)) + { + if (ScanDirectionIsForward(direction)) + direction = BackwardScanDirection; + else if (ScanDirectionIsBackward(direction)) + direction = ForwardScanDirection; + } snapshot = estate->es_snapshot; scanstate = node->scan.scanstate; indexstate = node->indxstate; @@ -316,6 +323,8 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent) indxqual = node->indxqual; numScanKeys = indexstate->iss_NumScanKeys; indexstate->iss_IndexPtr = -1; + if (ScanDirectionIsBackward(node->indxorderdir)) + indexstate->iss_IndexPtr = numIndices; /* If this is re-scanning of PlanQual ... */ if (estate->es_evTuple != NULL && @@ -966,6 +975,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) } indexstate->iss_NumIndices = numIndices; + if (ScanDirectionIsBackward(node->indxorderdir)) + indexPtr = numIndices; indexstate->iss_IndexPtr = indexPtr; indexstate->iss_ScanKeys = scanKeys; indexstate->iss_NumScanKeys = numScanKeys; diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index db97c2ed39bb57ef47f85492ca96d625286f55fa..ca2bd33a2c1c94348693202835cb0ad160180d2e 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -7,7 +7,7 @@ * * * 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); Node_Copy(from, newnode, indxqual); Node_Copy(from, newnode, indxqualorig); + newnode->indxorderdir = from->indxorderdir; return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 576601faf57021958405b59fced01cada4c1496a..337e63a61561b67172763e65010ddd5a052099df 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -7,7 +7,7 @@ * * * 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) return false; + if (a->indxorderdir != b->indxorderdir) + return false; + if (!equali(a->indxid, b->indxid)) return false; return true; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 4272bf04cc5208e6e0b6d5858d18a5618761c850..5c9f4599deb7fd3df1ebb2b9ea37b961c6f75984 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -5,7 +5,7 @@ * * 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 * Every (plan) node in POSTGRES has an associated "out" routine which @@ -445,6 +445,7 @@ _outIndexScan(StringInfo str, IndexScan *node) appendStringInfo(str, " :indxqualorig "); _outNode(str, node->indxqualorig); + appendStringInfo(str, " :indxorderdir %d ", node->indxorderdir); } /* diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index e16398fb85481b10b9dc20d3d162094bec38133e..c49ad053f1bcf12051111db5be6ad699ce1f40df 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -7,7 +7,7 @@ * * * 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 * Most of the read functions for plan nodes are tested. (In fact, they @@ -532,6 +532,11 @@ _readIndexScan() token = lsptok(NULL, &length); /* eat :indxqualorig */ 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; } diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index d3d79f6ef8a137369450f2ebc4d4b15748389d77..dbc6ac9d289e0b6feb4ac1f92a6357ae042d5370 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -7,7 +7,7 @@ * * * 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->indxqual = indxqual; node->indxqualorig = indxqualorig; + node->indxorderdir = NoMovementScanDirection; node->scan.scanstate = (CommonScanState *) NULL; return node; diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 41bb025e286f279b9c27d9633c056fe2e610b686..17ad449839b24496fe8efa6dc7b330d02afdc973 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -7,7 +7,7 @@ * * * 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, List *groupClause, AttrNumber *grpColIdx, 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); /***************************************************************************** @@ -303,8 +303,17 @@ union_planner(Query *parse) } else { - if (parse->sortClause && need_sortplan(parse->sortClause, result_plan)) - return (make_sortplan(tlist, parse->sortClause, result_plan)); + if (parse->sortClause) + { + 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 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 * @@ -845,11 +854,13 @@ get_matching_tle(Plan *plan, Resdom *resdom) * Check if a user requested ORDER BY is already satisfied by * 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 -need_sortplan(List *sortcls, Plan *plan) +static ScanDirection +get_dir_to_omit_sortplan(List *sortcls, Plan *plan) { Relation indexRel; IndexScan *indexScan; @@ -858,13 +869,15 @@ need_sortplan(List *sortcls, Plan *plan) HeapTuple htup; Form_pg_index index_tup; int key_no = 0; + ScanDirection dir, nodir = NoMovementScanDirection; + dir = nodir; /* ---------- * Must be an IndexScan * ---------- */ if (nodeTag(plan) != T_IndexScan) - return TRUE; + return nodir; indexScan = (IndexScan *) plan; @@ -873,16 +886,16 @@ need_sortplan(List *sortcls, Plan *plan) * ---------- */ if (plan->lefttree != NULL) - return TRUE; + return nodir; if (plan->righttree != NULL) - return TRUE; + return nodir; /* ---------- * Must be a single index scan * ---------- */ if (length(indexScan->indxid) != 1) - return TRUE; + return nodir; /* ---------- * 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) - return TRUE; + return nodir; /* ---------- * 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) { heap_close(indexRel); - return TRUE; + return nodir; } heap_close(indexRel); @@ -937,7 +950,7 @@ need_sortplan(List *sortcls, Plan *plan) * Could this happen? * ---------- */ - return TRUE; + return nodir; } if (nodeTag(tle->expr) != T_Var) { @@ -946,7 +959,7 @@ need_sortplan(List *sortcls, Plan *plan) * cannot be the indexed attribute * ---------- */ - return TRUE; + return nodir; } var = (Var *) (tle->expr); @@ -957,7 +970,7 @@ need_sortplan(List *sortcls, Plan *plan) * that of the index * ---------- */ - return TRUE; + return nodir; } if (var->varattno != index_tup->indkey[key_no]) @@ -966,7 +979,7 @@ need_sortplan(List *sortcls, Plan *plan) * It isn't the indexed attribute. * ---------- */ - return TRUE; + return nodir; } 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. * ---------- */ - 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++; @@ -985,5 +1010,5 @@ need_sortplan(List *sortcls, Plan *plan) * Index matches ORDER BY - sort not required * ---------- */ - return FALSE; + return dir; } diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 3d319a66ff7c078d33b1b055025e9fab1a92fdc1..532be5196bf8f4a877972f537be7d831db8bb255 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -6,7 +6,7 @@ * * 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 *indxqual; List *indxqualorig; + ScanDirection indxorderdir; IndexScanState *indxstate; } IndexScan;