Обсуждение: Descending order Index scan patch

Поиск
Список
Период
Сортировка

Descending order Index scan patch

От
"Hiroshi Inoue"
Дата:
Hi all,

In v6.5
      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.

This patch needs "make clean" .

Regards.

Hiroshi Inoue
Inoue@tpf.co.jp

*** ../../head/pgcurrent/backend/optimizer/plan/planner.c    Mon Jul 26
12:44:55 1999
--- backend/optimizer/plan/planner.c    Mon Aug  9 11:01:49 1999
***************
*** 39,45 **** static Plan *make_groupplan(List *group_tlist, bool tuplePerGroup,                List *groupClause,
AttrNumber*grpColIdx,                Plan *subplan);
 
! static bool need_sortplan(List *sortcls, Plan *plan); static Plan *make_sortplan(List *tlist, List *sortcls, Plan
*plannode);


/***************************************************************************
**
--- 39,45 ---- static Plan *make_groupplan(List *group_tlist, bool tuplePerGroup,                List *groupClause,
AttrNumber*grpColIdx,                Plan *subplan);
 
! static ScanDirection get_dir_to_omit_sortplan(List *sortcls, Plan *plan); static Plan *make_sortplan(List *tlist,
List*sortcls, Plan *plannode);
 


/***************************************************************************
**
***************
*** 303,310 ****     }     else     {
!         if (parse->sortClause && need_sortplan(parse->sortClause,
result_plan))
!             return (make_sortplan(tlist, parse->sortClause, result_plan));         else             return ((Plan *)
result_plan);    }
 
--- 303,319 ----     }     else     {
!         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,828 ****

 /* ----------
!  * Support function for need_sortplan  * ----------  */ static TargetEntry *
--- 831,837 ----

 /* ----------
!  * Support function for get scan direction to omit sortplan  * ----------  */ static TargetEntry *
***************
*** 845,855 ****  * 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.  * ----------  */
! static bool
! need_sortplan(List *sortcls, Plan *plan) {     Relation    indexRel;     IndexScan  *indexScan;
--- 854,866 ----  * Check if a user requested ORDER BY is already satisfied by  * the choosen index scan.  *
!  * Returns the direction of Index scan to omit sort,
!  * if sort is required returns NoMovementScanDirection
!  *  * ----------  */
! static ScanDirection
! get_dir_to_omit_sortplan(List *sortcls, Plan *plan) {     Relation    indexRel;     IndexScan  *indexScan;
***************
*** 858,870 ****     HeapTuple    htup;     Form_pg_index index_tup;     int            key_no = 0;
     /* ----------      * Must be an IndexScan      * ----------      */     if (nodeTag(plan) != T_IndexScan)
!         return TRUE;
     indexScan = (IndexScan *) plan;

--- 869,883 ----     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 nodir;
     indexScan = (IndexScan *) plan;

***************
*** 873,881 ****      * ----------      */     if (plan->lefttree != NULL)
!         return TRUE;     if (plan->righttree != NULL)
!         return TRUE;
     /* ----------      * Must be a single index scan
--- 886,894 ----      * ----------      */     if (plan->lefttree != NULL)
!         return nodir;     if (plan->righttree != NULL)
!         return nodir;
     /* ----------      * Must be a single index scan
***************
*** 882,888 ****      * ----------      */     if (length(indexScan->indxid) != 1)
!         return TRUE;
     /* ----------      * Indices can only have up to 8 attributes. So an ORDER BY using
--- 895,901 ----      * ----------      */     if (length(indexScan->indxid) != 1)
!         return nodir;
     /* ----------      * Indices can only have up to 8 attributes. So an ORDER BY using
***************
*** 890,896 ****      * ----------      */     if (length(sortcls) > 8)
!         return TRUE;
     /* ----------      * The choosen Index must be a btree
--- 903,909 ----      * ----------      */     if (length(sortcls) > 8)
!         return nodir;
     /* ----------      * The choosen Index must be a btree
***************
*** 902,908 ****     if (strcmp(nameout(&(indexRel->rd_am->amname)), "btree") != 0)     {
heap_close(indexRel);
!         return TRUE;     }     heap_close(indexRel);

--- 915,921 ----     if (strcmp(nameout(&(indexRel->rd_am->amname)), "btree") != 0)     {
heap_close(indexRel);
!         return nodir;     }     heap_close(indexRel);

***************
*** 937,943 ****              * Could this happen?              * ----------              */
!             return TRUE;         }         if (nodeTag(tle->expr) != T_Var)         {
--- 950,956 ----              * Could this happen?              * ----------              */
!             return nodir;         }         if (nodeTag(tle->expr) != T_Var)         {
***************
*** 946,952 ****              * cannot be the indexed attribute              * ----------              */
!             return TRUE;         }         var = (Var *) (tle->expr);

--- 959,965 ----              * cannot be the indexed attribute              * ----------              */
!             return nodir;         }         var = (Var *) (tle->expr);

***************
*** 957,963 ****              * that of the index              * ----------              */
!             return TRUE;         }
         if (var->varattno != index_tup->indkey[key_no])
--- 970,976 ----              * that of the index              * ----------              */
!             return nodir;         }
         if (var->varattno != index_tup->indkey[key_no])
***************
*** 966,972 ****              * It isn't the indexed attribute.              * ----------              */
!             return TRUE;         }
         if (oprid(oper("<", resdom->restype, resdom->restype, FALSE)) !=
sortcl->opoid)
--- 979,985 ----              * It isn't the indexed attribute.              * ----------              */
!             return nodir;         }
         if (oprid(oper("<", resdom->restype, resdom->restype, FALSE)) !=
sortcl->opoid)
***************
*** 975,982 ****              * Sort order isn't in ascending order.              * ----------              */
!             return TRUE;         }
         key_no++;     }
--- 988,1007 ----              * Sort order isn't in ascending order.              * ----------              */
!             if (ScanDirectionIsForward(dir))
!                 return nodir;
!             dir = BackwardScanDirection;         }
+         else
+         {
+             /* ----------
+              * Sort order is in ascending order.
+              * ----------
+             */
+             if (ScanDirectionIsBackward(dir))
+                 return nodir;
+             dir = ForwardScanDirection;
+         }
         key_no++;     }
***************
*** 985,989 ****      * Index matches ORDER BY - sort not required      * ----------      */
!     return FALSE; }
--- 1010,1014 ----      * Index matches ORDER BY - sort not required      * ----------      */
!     return dir; }
*** ../../head/pgcurrent/backend/executor/nodeIndexscan.c    Mon Jul 26
12:44:47 1999
--- backend/executor/nodeIndexscan.c    Mon Aug  9 10:54:23 1999
***************
*** 99,104 ****
--- 99,111 ----      */     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,321 ****
--- 323,330 ----     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,971 ****
--- 975,982 ----     }
     indexstate->iss_NumIndices = numIndices;
+     if (ScanDirectionIsBackward(node->indxorderdir))
+         indexPtr = numIndices;     indexstate->iss_IndexPtr = indexPtr;     indexstate->iss_ScanKeys = scanKeys;
indexstate->iss_NumScanKeys= numScanKeys;
 
*** ../../head/pgcurrent/backend/optimizer/plan/createplan.c    Mon Aug  9
11:31:33 1999
--- backend/optimizer/plan/createplan.c    Mon Aug  9 11:48:55 1999
***************
*** 1024,1029 ****
--- 1024,1030 ----     node->indxid = indxid;     node->indxqual = indxqual;     node->indxqualorig = indxqualorig;
+     node->indxorderdir = NoMovementScanDirection;     node->scan.scanstate = (CommonScanState *) NULL;
     return node;
*** ../../head/pgcurrent/backend/nodes/copyfuncs.c    Wed Jul 28 15:25:51 1999
--- backend/nodes/copyfuncs.c    Mon Aug  9 10:55:00 1999
***************
*** 238,243 ****
--- 238,244 ----     newnode->indxid = listCopy(from->indxid);     Node_Copy(from, newnode, indxqual);
Node_Copy(from,newnode, indxqualorig);
 
+     newnode->indxorderdir = from->indxorderdir;
     return newnode; }
*** ../../head/pgcurrent/backend/nodes/readfuncs.c    Mon Jul 26 14:45:56 1999
--- backend/nodes/readfuncs.c    Mon Aug  9 11:00:47 1999
***************
*** 532,537 ****
--- 532,542 ----     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; }

*** ../../head/pgcurrent/backend/nodes/outfuncs.c    Mon Jul 26 14:45:56 1999
--- backend/nodes/outfuncs.c    Mon Aug  9 10:55:28 1999
***************
*** 445,450 ****
--- 445,451 ----     appendStringInfo(str, " :indxqualorig ");     _outNode(str, node->indxqualorig);

+     appendStringInfo(str, " :indxorderdir %d ", node->indxorderdir); }
 /*
*** ../../head/pgcurrent/backend/nodes/equalfuncs.c    Fri Jul 30 17:29:37
1999
--- backend/nodes/equalfuncs.c    Mon Aug  9 10:55:08 1999
***************
*** 437,442 ****
--- 437,445 ----     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;
*** ../../head/pgcurrent/include/nodes/plannodes.h    Mon Jul 26 12:45:39 1999
--- include/nodes/plannodes.h    Mon Aug  9 10:52:54 1999
***************
*** 175,180 ****
--- 175,181 ----     List       *indxid;     List       *indxqual;     List       *indxqualorig;
+     ScanDirection    indxorderdir;     IndexScanState *indxstate; } IndexScan;

*** ../../head/pgcurrent/backend/commands/explain.c    Mon Jul 26 12:44:46
1999
--- backend/commands/explain.c    Mon Aug  9 10:53:44 1999
***************
*** 200,205 ****
--- 200,207 ----     switch (nodeTag(plan))     {         case T_IndexScan:
+             if (ScanDirectionIsBackward(((IndexScan *)plan)->indxorderdir))
+                 appendStringInfo(str, " Backward");             appendStringInfo(str, " using ");             i = 0;
          foreach(l, ((IndexScan *) plan)->indxid)
 



Re: [PATCHES] Descending order Index scan patch

От
Bruce Momjian
Дата:
[Charset iso-8859-1 unsupported, filtering to ASCII...]
> Hi all,
> 
> In v6.5
> 
>        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.
> 
> This patch needs "make clean" .
> 
> Regards.
> 
> Hiroshi Inoue
> Inoue@tpf.co.jp
> 


This patch is broken.  See the wrapping that happened to the /**** line.
Please resubmit.


> *** ../../head/pgcurrent/backend/optimizer/plan/planner.c    Mon Jul 26
> 12:44:55 1999
> --- backend/optimizer/plan/planner.c    Mon Aug  9 11:01:49 1999
> ***************
> *** 39,45 ****
>   static Plan *make_groupplan(List *group_tlist, bool tuplePerGroup,
>                  List *groupClause, AttrNumber *grpColIdx,
>                  Plan *subplan);
> ! static bool need_sortplan(List *sortcls, Plan *plan);
>   static Plan *make_sortplan(List *tlist, List *sortcls, Plan *plannode);
> 
> 
> /***************************************************************************
> **
> --- 39,45 ----
>   static Plan *make_groupplan(List *group_tlist, bool tuplePerGroup,
>                  List *groupClause, AttrNumber *grpColIdx,
>                  Plan *subplan);
> ! static ScanDirection get_dir_to_omit_sortplan(List *sortcls, Plan *plan);
>   static Plan *make_sortplan(List *tlist, List *sortcls, Plan *plannode);
> 
> 
> /***************************************************************************
> **
> ***************
> *** 303,310 ****
>       }
>       else
>       {
> !         if (parse->sortClause && need_sortplan(parse->sortClause,
> result_plan))
> !             return (make_sortplan(tlist, parse->sortClause, result_plan));
>           else
>               return ((Plan *) result_plan);
>       }
> --- 303,319 ----
>       }
>       else
>       {
> !         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,828 ****
> 
> 
>   /* ----------
> !  * Support function for need_sortplan
>    * ----------
>    */
>   static TargetEntry *
> --- 831,837 ----
> 
> 
>   /* ----------
> !  * Support function for get scan direction to omit sortplan
>    * ----------
>    */
>   static TargetEntry *
> ***************
> *** 845,855 ****
>    * 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.
>    * ----------
>    */
> ! static bool
> ! need_sortplan(List *sortcls, Plan *plan)
>   {
>       Relation    indexRel;
>       IndexScan  *indexScan;
> --- 854,866 ----
>    * Check if a user requested ORDER BY is already satisfied by
>    * the choosen index scan.
>    *
> !  * Returns the direction of Index scan to omit sort,
> !  * if sort is required returns NoMovementScanDirection
> !  *
>    * ----------
>    */
> ! static ScanDirection
> ! get_dir_to_omit_sortplan(List *sortcls, Plan *plan)
>   {
>       Relation    indexRel;
>       IndexScan  *indexScan;
> ***************
> *** 858,870 ****
>       HeapTuple    htup;
>       Form_pg_index index_tup;
>       int            key_no = 0;
> 
>       /* ----------
>        * Must be an IndexScan
>        * ----------
>        */
>       if (nodeTag(plan) != T_IndexScan)
> !         return TRUE;
> 
>       indexScan = (IndexScan *) plan;
> 
> --- 869,883 ----
>       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 nodir;
> 
>       indexScan = (IndexScan *) plan;
> 
> ***************
> *** 873,881 ****
>        * ----------
>        */
>       if (plan->lefttree != NULL)
> !         return TRUE;
>       if (plan->righttree != NULL)
> !         return TRUE;
> 
>       /* ----------
>        * Must be a single index scan
> --- 886,894 ----
>        * ----------
>        */
>       if (plan->lefttree != NULL)
> !         return nodir;
>       if (plan->righttree != NULL)
> !         return nodir;
> 
>       /* ----------
>        * Must be a single index scan
> ***************
> *** 882,888 ****
>        * ----------
>        */
>       if (length(indexScan->indxid) != 1)
> !         return TRUE;
> 
>       /* ----------
>        * Indices can only have up to 8 attributes. So an ORDER BY using
> --- 895,901 ----
>        * ----------
>        */
>       if (length(indexScan->indxid) != 1)
> !         return nodir;
> 
>       /* ----------
>        * Indices can only have up to 8 attributes. So an ORDER BY using
> ***************
> *** 890,896 ****
>        * ----------
>        */
>       if (length(sortcls) > 8)
> !         return TRUE;
> 
>       /* ----------
>        * The choosen Index must be a btree
> --- 903,909 ----
>        * ----------
>        */
>       if (length(sortcls) > 8)
> !         return nodir;
> 
>       /* ----------
>        * The choosen Index must be a btree
> ***************
> *** 902,908 ****
>       if (strcmp(nameout(&(indexRel->rd_am->amname)), "btree") != 0)
>       {
>           heap_close(indexRel);
> !         return TRUE;
>       }
>       heap_close(indexRel);
> 
> --- 915,921 ----
>       if (strcmp(nameout(&(indexRel->rd_am->amname)), "btree") != 0)
>       {
>           heap_close(indexRel);
> !         return nodir;
>       }
>       heap_close(indexRel);
> 
> ***************
> *** 937,943 ****
>                * Could this happen?
>                * ----------
>                */
> !             return TRUE;
>           }
>           if (nodeTag(tle->expr) != T_Var)
>           {
> --- 950,956 ----
>                * Could this happen?
>                * ----------
>                */
> !             return nodir;
>           }
>           if (nodeTag(tle->expr) != T_Var)
>           {
> ***************
> *** 946,952 ****
>                * cannot be the indexed attribute
>                * ----------
>                */
> !             return TRUE;
>           }
>           var = (Var *) (tle->expr);
> 
> --- 959,965 ----
>                * cannot be the indexed attribute
>                * ----------
>                */
> !             return nodir;
>           }
>           var = (Var *) (tle->expr);
> 
> ***************
> *** 957,963 ****
>                * that of the index
>                * ----------
>                */
> !             return TRUE;
>           }
> 
>           if (var->varattno != index_tup->indkey[key_no])
> --- 970,976 ----
>                * that of the index
>                * ----------
>                */
> !             return nodir;
>           }
> 
>           if (var->varattno != index_tup->indkey[key_no])
> ***************
> *** 966,972 ****
>                * It isn't the indexed attribute.
>                * ----------
>                */
> !             return TRUE;
>           }
> 
>           if (oprid(oper("<", resdom->restype, resdom->restype, FALSE)) !=
> sortcl->opoid)
> --- 979,985 ----
>                * It isn't the indexed attribute.
>                * ----------
>                */
> !             return nodir;
>           }
> 
>           if (oprid(oper("<", resdom->restype, resdom->restype, FALSE)) !=
> sortcl->opoid)
> ***************
> *** 975,982 ****
>                * Sort order isn't in ascending order.
>                * ----------
>                */
> !             return TRUE;
>           }
> 
>           key_no++;
>       }
> --- 988,1007 ----
>                * Sort order isn't in ascending order.
>                * ----------
>                */
> !             if (ScanDirectionIsForward(dir))
> !                 return nodir;
> !             dir = BackwardScanDirection;
>           }
> +         else
> +         {
> +             /* ----------
> +              * Sort order is in ascending order.
> +              * ----------
> +             */
> +             if (ScanDirectionIsBackward(dir))
> +                 return nodir;
> +             dir = ForwardScanDirection;
> +         }
> 
>           key_no++;
>       }
> ***************
> *** 985,989 ****
>        * Index matches ORDER BY - sort not required
>        * ----------
>        */
> !     return FALSE;
>   }
> --- 1010,1014 ----
>        * Index matches ORDER BY - sort not required
>        * ----------
>        */
> !     return dir;
>   }
> *** ../../head/pgcurrent/backend/executor/nodeIndexscan.c    Mon Jul 26
> 12:44:47 1999
> --- backend/executor/nodeIndexscan.c    Mon Aug  9 10:54:23 1999
> ***************
> *** 99,104 ****
> --- 99,111 ----
>        */
>       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,321 ****
> --- 323,330 ----
>       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,971 ****
> --- 975,982 ----
>       }
> 
>       indexstate->iss_NumIndices = numIndices;
> +     if (ScanDirectionIsBackward(node->indxorderdir))
> +         indexPtr = numIndices;
>       indexstate->iss_IndexPtr = indexPtr;
>       indexstate->iss_ScanKeys = scanKeys;
>       indexstate->iss_NumScanKeys = numScanKeys;
> *** ../../head/pgcurrent/backend/optimizer/plan/createplan.c    Mon Aug  9
> 11:31:33 1999
> --- backend/optimizer/plan/createplan.c    Mon Aug  9 11:48:55 1999
> ***************
> *** 1024,1029 ****
> --- 1024,1030 ----
>       node->indxid = indxid;
>       node->indxqual = indxqual;
>       node->indxqualorig = indxqualorig;
> +     node->indxorderdir = NoMovementScanDirection;
>       node->scan.scanstate = (CommonScanState *) NULL;
> 
>       return node;
> *** ../../head/pgcurrent/backend/nodes/copyfuncs.c    Wed Jul 28 15:25:51 1999
> --- backend/nodes/copyfuncs.c    Mon Aug  9 10:55:00 1999
> ***************
> *** 238,243 ****
> --- 238,244 ----
>       newnode->indxid = listCopy(from->indxid);
>       Node_Copy(from, newnode, indxqual);
>       Node_Copy(from, newnode, indxqualorig);
> +     newnode->indxorderdir = from->indxorderdir;
> 
>       return newnode;
>   }
> *** ../../head/pgcurrent/backend/nodes/readfuncs.c    Mon Jul 26 14:45:56 1999
> --- backend/nodes/readfuncs.c    Mon Aug  9 11:00:47 1999
> ***************
> *** 532,537 ****
> --- 532,542 ----
>       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;
>   }
> 
> *** ../../head/pgcurrent/backend/nodes/outfuncs.c    Mon Jul 26 14:45:56 1999
> --- backend/nodes/outfuncs.c    Mon Aug  9 10:55:28 1999
> ***************
> *** 445,450 ****
> --- 445,451 ----
>       appendStringInfo(str, " :indxqualorig ");
>       _outNode(str, node->indxqualorig);
> 
> +     appendStringInfo(str, " :indxorderdir %d ", node->indxorderdir);
>   }
> 
>   /*
> *** ../../head/pgcurrent/backend/nodes/equalfuncs.c    Fri Jul 30 17:29:37
> 1999
> --- backend/nodes/equalfuncs.c    Mon Aug  9 10:55:08 1999
> ***************
> *** 437,442 ****
> --- 437,445 ----
>       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;
> *** ../../head/pgcurrent/include/nodes/plannodes.h    Mon Jul 26 12:45:39 1999
> --- include/nodes/plannodes.h    Mon Aug  9 10:52:54 1999
> ***************
> *** 175,180 ****
> --- 175,181 ----
>       List       *indxid;
>       List       *indxqual;
>       List       *indxqualorig;
> +     ScanDirection    indxorderdir;
>       IndexScanState *indxstate;
>   } IndexScan;
> 
> *** ../../head/pgcurrent/backend/commands/explain.c    Mon Jul 26 12:44:46
> 1999
> --- backend/commands/explain.c    Mon Aug  9 10:53:44 1999
> ***************
> *** 200,205 ****
> --- 200,207 ----
>       switch (nodeTag(plan))
>       {
>           case T_IndexScan:
> +             if (ScanDirectionIsBackward(((IndexScan *)plan)->indxorderdir))
> +                 appendStringInfo(str, " Backward");
>               appendStringInfo(str, " using ");
>               i = 0;
>               foreach(l, ((IndexScan *) plan)->indxid)
> 
> 
> 


--  Bruce Momjian                        |  http://www.op.net/~candle maillist@candle.pha.pa.us            |  (610)
853-3000+  If your life is a hard drive,     |  830 Blythe Avenue +  Christ can be your backup.        |  Drexel Hill,
Pennsylvania19026