diff -dcrpN postgresql-9.0rc1.orig/src/backend/nodes/Makefile postgresql-9.0rc1/src/backend/nodes/Makefile *** postgresql-9.0rc1.orig/src/backend/nodes/Makefile 2008-02-19 11:30:07.000000000 +0100 --- postgresql-9.0rc1/src/backend/nodes/Makefile 2010-09-07 10:20:24.000000000 +0200 *************** subdir = src/backend/nodes *** 12,18 **** top_builddir = ../../.. include $(top_builddir)/src/Makefile.global ! OBJS = nodeFuncs.o nodes.o list.o bitmapset.o tidbitmap.o \ copyfuncs.o equalfuncs.o makefuncs.o \ outfuncs.o readfuncs.o print.o read.o params.o value.o --- 12,18 ---- top_builddir = ../../.. include $(top_builddir)/src/Makefile.global ! OBJS = nodeFuncs.o nodes.o list.o tree.o bitmapset.o tidbitmap.o \ copyfuncs.o equalfuncs.o makefuncs.o \ outfuncs.o readfuncs.o print.o read.o params.o value.o diff -dcrpN postgresql-9.0rc1.orig/src/backend/nodes/outfuncs.c postgresql-9.0rc1/src/backend/nodes/outfuncs.c *** postgresql-9.0rc1.orig/src/backend/nodes/outfuncs.c 2010-08-18 17:22:00.000000000 +0200 --- postgresql-9.0rc1/src/backend/nodes/outfuncs.c 2010-09-07 10:18:00.000000000 +0200 *************** _outList(StringInfo str, List *node) *** 175,180 **** --- 175,198 ---- appendStringInfoChar(str, ')'); } + static void + _outTree(StringInfo str, Tree *node) + { + TreeCell *element; + + appendStringInfoChar(str, '('); + + rb_begin_iterate(node->tree, LeftRightWalk); + element = (TreeCell *)rb_iterate(node->tree); + while (element) + { + _outNode(str, element->node); + element = (TreeCell *)rb_iterate(node->tree); + } + + appendStringInfoChar(str, ')'); + } + /* * _outBitmapset - * converts a bitmap set of integers *************** _outPlannerInfo(StringInfo str, PlannerI *** 1545,1551 **** WRITE_NODE_FIELD(init_plans); WRITE_NODE_FIELD(cte_plan_ids); WRITE_NODE_FIELD(eq_classes); ! WRITE_NODE_FIELD(canon_pathkeys); WRITE_NODE_FIELD(left_join_clauses); WRITE_NODE_FIELD(right_join_clauses); WRITE_NODE_FIELD(full_join_clauses); --- 1563,1569 ---- WRITE_NODE_FIELD(init_plans); WRITE_NODE_FIELD(cte_plan_ids); WRITE_NODE_FIELD(eq_classes); ! WRITE_NODE_FIELD(rb_canon_pathkeys); WRITE_NODE_FIELD(left_join_clauses); WRITE_NODE_FIELD(right_join_clauses); WRITE_NODE_FIELD(full_join_clauses); *************** _outNode(StringInfo str, void *obj) *** 2451,2456 **** --- 2469,2476 ---- appendStringInfo(str, "<>"); else if (IsA(obj, List) ||IsA(obj, IntList) || IsA(obj, OidList)) _outList(str, obj); + else if (IsA(obj, Tree)) + _outTree(str, obj); else if (IsA(obj, Integer) || IsA(obj, Float) || IsA(obj, String) || diff -dcrpN postgresql-9.0rc1.orig/src/backend/nodes/tree.c postgresql-9.0rc1/src/backend/nodes/tree.c *** postgresql-9.0rc1.orig/src/backend/nodes/tree.c 1970-01-01 01:00:00.000000000 +0100 --- postgresql-9.0rc1/src/backend/nodes/tree.c 2010-09-07 14:06:42.000000000 +0200 *************** *** 0 **** --- 1,65 ---- + /*------------------------------------------------------------------------- + * + * tree.c + * implementation for PostgreSQL generic rbtree package + * + * + * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $PostgreSQL: pgsql/src/backend/nodes/list.c,v 1.74 2010/02/13 02:34:11 tgl Exp $ + * + *------------------------------------------------------------------------- + */ + #include "postgres.h" + + #include "nodes/pg_tree.h" + #include "utils/rbtree.h" + + RBNode *tree_allocfunc(void *arg) + { + return (RBNode *)palloc(sizeof(TreeCell)); + } + + /* + * Return a freshly allocated Tree. + */ + Tree * + new_tree(rb_comparator comparator, rb_allocfunc allocfunc, void *arg) + { + Tree *tree = makeNode(Tree); + + tree->tree = rb_create(sizeof(TreeCell), comparator, NULL, allocfunc, NULL, arg); + + return tree; + } + + Node * + tree_find(Tree *tree, Node *node) + { + TreeCell *cell = palloc(sizeof(TreeCell)); + TreeCell *result; + + cell->node = node; + + result = (TreeCell *)rb_find(tree->tree, (RBNode *)cell); + + pfree(cell); + + if (result == NULL) + return NULL; + + return result->node; + } + + void + tree_add(Tree *tree, Node *node) + { + TreeCell *rbnode = palloc(sizeof(TreeCell)); + bool isNew; + + rbnode->node = node; + rb_insert(tree->tree, (RBNode *)rbnode, &isNew); + } diff -dcrpN postgresql-9.0rc1.orig/src/backend/optimizer/path/pathkeys.c postgresql-9.0rc1/src/backend/optimizer/path/pathkeys.c *** postgresql-9.0rc1.orig/src/backend/optimizer/path/pathkeys.c 2010-02-26 03:00:45.000000000 +0100 --- postgresql-9.0rc1/src/backend/optimizer/path/pathkeys.c 2010-09-07 15:41:49.000000000 +0200 *************** makePathKey(EquivalenceClass *eclass, Oi *** 71,76 **** --- 71,137 ---- return pk; } + RBNode * + pathkeys_allocfunc(void *arg) + { + PlannerInfo *root = arg; + MemoryContext oldcontext; + RBNode *node; + + oldcontext = MemoryContextSwitchTo(root->planner_cxt); + + node = palloc(sizeof(TreeCell)); + + MemoryContextSwitchTo(oldcontext); + + return node; + } + + int + pathkeys_comparator(const RBNode *a, const RBNode *b, void *arg) + { + TreeCell *left = (TreeCell *)a; + TreeCell *right = (TreeCell *)b; + PathKey *pk_left = (PathKey *)left->node; + PathKey *pk_right = (PathKey *)right->node; + long val1, val2; + + Assert((pk_left != NULL)); + Assert((pk_right != NULL)); + + val1 = (long)pk_left->pk_eclass; + val2 = (long)pk_right->pk_eclass; + + if (val1 < val2) + return -1; + else if (val1 > val2) + return 1; + + if (pk_left->pk_opfamily < pk_right->pk_opfamily) + return -1; + else if (pk_left->pk_opfamily > pk_right->pk_opfamily) + return 1; + + if (pk_left->pk_strategy < pk_right->pk_strategy) + return -1; + else if (pk_left->pk_strategy > pk_right->pk_strategy) + return 1; + + if (pk_left->pk_nulls_first < pk_right->pk_nulls_first) + return -1; + else if (pk_left->pk_nulls_first > pk_right->pk_nulls_first) + return 1; + + if (pk_left == NULL) + elog(ERROR, "pk_left NULL"); + if (pk_right == NULL) + elog(ERROR, "pk_right NULL"); + + return 0; + } + + + /* * make_canonical_pathkey * Given the parameters for a PathKey, find any pre-existing matching *************** make_canonical_pathkey(PlannerInfo *root *** 85,119 **** EquivalenceClass *eclass, Oid opfamily, int strategy, bool nulls_first) { ! PathKey *pk; ! ListCell *lc; MemoryContext oldcontext; /* The passed eclass might be non-canonical, so chase up to the top */ while (eclass->ec_merged) eclass = eclass->ec_merged; - foreach(lc, root->canon_pathkeys) - { - pk = (PathKey *) lfirst(lc); - if (eclass == pk->pk_eclass && - opfamily == pk->pk_opfamily && - strategy == pk->pk_strategy && - nulls_first == pk->pk_nulls_first) - return pk; - } - /* * Be sure canonical pathkeys are allocated in the main planning context. * Not an issue in normal planning, but it is for GEQO. */ oldcontext = MemoryContextSwitchTo(root->planner_cxt); ! pk = makePathKey(eclass, opfamily, strategy, nulls_first); ! root->canon_pathkeys = lappend(root->canon_pathkeys, pk); MemoryContextSwitchTo(oldcontext); return pk; } --- 146,178 ---- EquivalenceClass *eclass, Oid opfamily, int strategy, bool nulls_first) { ! PathKey *pk, *pk_new; MemoryContext oldcontext; /* The passed eclass might be non-canonical, so chase up to the top */ while (eclass->ec_merged) eclass = eclass->ec_merged; /* * Be sure canonical pathkeys are allocated in the main planning context. * Not an issue in normal planning, but it is for GEQO. */ oldcontext = MemoryContextSwitchTo(root->planner_cxt); ! pk_new = makePathKey(eclass, opfamily, strategy, nulls_first); MemoryContextSwitchTo(oldcontext); + pk = (PathKey *) tree_find(root->rb_canon_pathkeys, (Node *)pk_new); + + if (pk) + pfree(pk_new); + else + { + tree_add(root->rb_canon_pathkeys, (Node *)pk_new); + pk = pk_new; + } + return pk; } diff -dcrpN postgresql-9.0rc1.orig/src/backend/optimizer/plan/planmain.c postgresql-9.0rc1/src/backend/optimizer/plan/planmain.c *** postgresql-9.0rc1.orig/src/backend/optimizer/plan/planmain.c 2010-07-06 21:18:56.000000000 +0200 --- postgresql-9.0rc1/src/backend/optimizer/plan/planmain.c 2010-09-07 14:29:40.000000000 +0200 *************** *** 20,31 **** --- 20,33 ---- */ #include "postgres.h" + #include "nodes/pg_tree.h" #include "optimizer/cost.h" #include "optimizer/pathnode.h" #include "optimizer/paths.h" #include "optimizer/placeholder.h" #include "optimizer/planmain.h" #include "optimizer/tlist.h" + #include "utils/rbtree.h" #include "utils/selfuncs.h" *************** query_planner(PlannerInfo *root, List *t *** 116,122 **** * We still are required to canonicalize any pathkeys, in case it's * something like "SELECT 2+2 ORDER BY 1". */ ! root->canon_pathkeys = NIL; root->query_pathkeys = canonicalize_pathkeys(root, root->query_pathkeys); root->group_pathkeys = canonicalize_pathkeys(root, --- 118,124 ---- * We still are required to canonicalize any pathkeys, in case it's * something like "SELECT 2+2 ORDER BY 1". */ ! root->rb_canon_pathkeys = new_tree(pathkeys_comparator, pathkeys_allocfunc, root); root->query_pathkeys = canonicalize_pathkeys(root, root->query_pathkeys); root->group_pathkeys = canonicalize_pathkeys(root, *************** query_planner(PlannerInfo *root, List *t *** 144,150 **** root->join_rel_hash = NULL; root->join_rel_level = NULL; root->join_cur_level = 0; ! root->canon_pathkeys = NIL; root->left_join_clauses = NIL; root->right_join_clauses = NIL; root->full_join_clauses = NIL; --- 146,152 ---- root->join_rel_hash = NULL; root->join_rel_level = NULL; root->join_cur_level = 0; ! root->rb_canon_pathkeys = new_tree(pathkeys_comparator, pathkeys_allocfunc, root); root->left_join_clauses = NIL; root->right_join_clauses = NIL; root->full_join_clauses = NIL; diff -dcrpN postgresql-9.0rc1.orig/src/backend/optimizer/plan/planner.c postgresql-9.0rc1/src/backend/optimizer/plan/planner.c *** postgresql-9.0rc1.orig/src/backend/optimizer/plan/planner.c 2010-03-30 23:58:10.000000000 +0200 --- postgresql-9.0rc1/src/backend/optimizer/plan/planner.c 2010-09-07 14:12:39.000000000 +0200 *************** subquery_planner(PlannerGlobal *glob, Qu *** 305,310 **** --- 305,311 ---- root->init_plans = NIL; root->cte_plan_ids = NIL; root->eq_classes = NIL; + root->rb_canon_pathkeys = new_tree(pathkeys_comparator, pathkeys_allocfunc, root); root->append_rel_list = NIL; root->rowMarks = NIL; root->hasInheritedTarget = false; diff -dcrpN postgresql-9.0rc1.orig/src/include/nodes/nodes.h postgresql-9.0rc1/src/include/nodes/nodes.h *** postgresql-9.0rc1.orig/src/include/nodes/nodes.h 2010-03-29 00:59:33.000000000 +0200 --- postgresql-9.0rc1/src/include/nodes/nodes.h 2010-09-06 13:11:47.000000000 +0200 *************** typedef enum NodeTag *** 252,257 **** --- 252,262 ---- T_OidList, /* + * TAGS FOR TREE NODES (pg_tree.h) + */ + T_Tree, + + /* * TAGS FOR STATEMENT NODES (mostly in parsenodes.h) */ T_Query = 700, diff -dcrpN postgresql-9.0rc1.orig/src/include/nodes/pg_tree.h postgresql-9.0rc1/src/include/nodes/pg_tree.h *** postgresql-9.0rc1.orig/src/include/nodes/pg_tree.h 1970-01-01 01:00:00.000000000 +0100 --- postgresql-9.0rc1/src/include/nodes/pg_tree.h 2010-09-07 14:06:09.000000000 +0200 *************** *** 0 **** --- 1,50 ---- + /*------------------------------------------------------------------------- + * + * pg_tree.h + * interface for PostgreSQL generic rbtree package + * + * This package implements rbtree of Node * elements of the same type. + * It is a replacement of List for dealing with O(n^2) behaviour + * found with long lists. + * + * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + #ifndef PG_TREE_H + #define PG_TREE_H + + #include "nodes/nodes.h" + #include "utils/rbtree.h" + + typedef struct TreeCell + { + RBNode treenode; + Node *node; + } TreeCell; + + + typedef struct Tree + { + NodeTag type; /* T_Tree */ + RBTree *tree; + } Tree; + + extern RBNode *tree_allocfunc(void *arg); + + extern Tree *new_tree(rb_comparator comparator, rb_allocfunc allocfunc, void *arg); + extern Node *tree_find(Tree *tree, Node *node); + extern void tree_add(Tree *tree, Node *node); + + /* + * tforeach - + * a convenience macro which loops through the tree elements + * in "inorder" walk to make it look like a list + */ + #define tforeach(cell, t) \ + for (rb_begin_iterate(t, LeftRightWalk) , (cell) = (TreeCell *)rb_iterate(t); (cell) != NULL; (cell) = (TreeCell *)rb_iterate(t)) + + #endif /* PG_TREE_H */ diff -dcrpN postgresql-9.0rc1.orig/src/include/nodes/primnodes.h postgresql-9.0rc1/src/include/nodes/primnodes.h *** postgresql-9.0rc1.orig/src/include/nodes/primnodes.h 2010-02-26 03:01:25.000000000 +0100 --- postgresql-9.0rc1/src/include/nodes/primnodes.h 2010-09-07 10:16:45.000000000 +0200 *************** *** 19,24 **** --- 19,25 ---- #include "access/attnum.h" #include "nodes/pg_list.h" + #include "nodes/pg_tree.h" /* ---------------------------------------------------------------- diff -dcrpN postgresql-9.0rc1.orig/src/include/nodes/relation.h postgresql-9.0rc1/src/include/nodes/relation.h *** postgresql-9.0rc1.orig/src/include/nodes/relation.h 2010-07-06 21:19:00.000000000 +0200 --- postgresql-9.0rc1/src/include/nodes/relation.h 2010-09-07 14:31:16.000000000 +0200 *************** typedef struct PlannerInfo *** 160,166 **** List *eq_classes; /* list of active EquivalenceClasses */ ! List *canon_pathkeys; /* list of "canonical" PathKeys */ List *left_join_clauses; /* list of RestrictInfos for * mergejoinable outer join clauses --- 160,166 ---- List *eq_classes; /* list of active EquivalenceClasses */ ! Tree *rb_canon_pathkeys; /* tree of "canonical" PathKeys */ List *left_join_clauses; /* list of RestrictInfos for * mergejoinable outer join clauses diff -dcrpN postgresql-9.0rc1.orig/src/include/optimizer/paths.h postgresql-9.0rc1/src/include/optimizer/paths.h *** postgresql-9.0rc1.orig/src/include/optimizer/paths.h 2010-01-02 17:58:07.000000000 +0100 --- postgresql-9.0rc1/src/include/optimizer/paths.h 2010-09-07 14:11:28.000000000 +0200 *************** *** 15,20 **** --- 15,21 ---- #define PATHS_H #include "nodes/relation.h" + #include "utils/rbtree.h" /* *************** typedef enum *** 152,157 **** --- 153,161 ---- PATHKEYS_DIFFERENT /* neither pathkey includes the other */ } PathKeysComparison; + extern RBNode *pathkeys_allocfunc(void *arg); + extern int pathkeys_comparator(const RBNode *a, const RBNode *b, void *arg); + extern List *canonicalize_pathkeys(PlannerInfo *root, List *pathkeys); extern PathKeysComparison compare_pathkeys(List *keys1, List *keys2); extern bool pathkeys_contained_in(List *keys1, List *keys2); Binary files postgresql-9.0rc1.orig/src/timezone/gmon.out and postgresql-9.0rc1/src/timezone/gmon.out differ