canon-pathkeys-as-rbtree-3-ctxdiff.patch

application/octet-stream

Filename: canon-pathkeys-as-rbtree-3-ctxdiff.patch
Type: application/octet-stream
Part: 0
Message: Re: plan time of MASSIVE partitioning ...

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: context
File+
src/backend/nodes/Makefile 1 1
src/backend/nodes/outfuncs.c 21 1
src/backend/nodes/tree.c 65 0
src/backend/optimizer/path/pathkeys.c 73 14
src/backend/optimizer/plan/planmain.c 4 2
src/backend/optimizer/plan/planner.c 1 0
src/include/nodes/nodes.h 5 0
src/include/nodes/pg_tree.h 50 0
src/include/nodes/primnodes.h 1 0
src/include/nodes/relation.h 1 1
src/include/optimizer/paths.h 4 0
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