From 7d4d96e68f9e6740c7034acc9da5e511001c2aa7 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 14 Jul 2009 02:25:18 +0200
Subject: [PATCH] Support a 'geqo_seed' GUC to make planning via GEQO repeatable.

---
 src/backend/optimizer/geqo/Makefile             |    1 +
 src/backend/optimizer/geqo/geqo_copy.c          |    4 +-
 src/backend/optimizer/geqo/geqo_cx.c            |    6 +-
 src/backend/optimizer/geqo/geqo_erx.c           |   47 ++++++------
 src/backend/optimizer/geqo/geqo_eval.c          |   28 ++++----
 src/backend/optimizer/geqo/geqo_main.c          |   90 ++++++++++++-----------
 src/backend/optimizer/geqo/geqo_mutation.c      |   10 +-
 src/backend/optimizer/geqo/geqo_ox1.c           |    8 +-
 src/backend/optimizer/geqo/geqo_ox2.c           |    7 +-
 src/backend/optimizer/geqo/geqo_pmx.c           |    7 +-
 src/backend/optimizer/geqo/geqo_pool.c          |   23 +++---
 src/backend/optimizer/geqo/geqo_px.c            |    8 +-
 src/backend/optimizer/geqo/geqo_random.c        |   42 +++++++++++
 src/backend/optimizer/geqo/geqo_recombination.c |    9 +-
 src/backend/optimizer/geqo/geqo_selection.c     |   19 +++--
 src/backend/optimizer/path/allpaths.c           |    2 +
 src/backend/utils/misc/guc.c                    |    9 ++
 src/include/nodes/relation.h                    |    3 +
 src/include/optimizer/geqo.h                    |   17 ++---
 src/include/optimizer/geqo_copy.h               |    3 +-
 src/include/optimizer/geqo_mutation.h           |    3 +-
 src/include/optimizer/geqo_pool.h               |   14 ++--
 src/include/optimizer/geqo_random.h             |    9 +-
 src/include/optimizer/geqo_recombination.h      |   33 +++++---
 src/include/optimizer/geqo_selection.h          |    4 +-
 25 files changed, 244 insertions(+), 162 deletions(-)
 create mode 100644 src/backend/optimizer/geqo/geqo_random.c

diff --git a/src/backend/optimizer/geqo/Makefile b/src/backend/optimizer/geqo/Makefile
index dbc6c28..e5a01d7 100644
*** a/src/backend/optimizer/geqo/Makefile
--- b/src/backend/optimizer/geqo/Makefile
*************** top_builddir = ../../../..
*** 14,19 ****
--- 14,20 ----
  include $(top_builddir)/src/Makefile.global
  
  OBJS =	geqo_copy.o geqo_eval.o geqo_main.o geqo_misc.o \
+ 	geqo_random.o \
  	geqo_mutation.o geqo_pool.o geqo_recombination.o \
  	geqo_selection.o \
  	geqo_erx.o geqo_pmx.o geqo_cx.o geqo_px.o geqo_ox1.o geqo_ox2.o
diff --git a/src/backend/optimizer/geqo/geqo_copy.c b/src/backend/optimizer/geqo/geqo_copy.c
index 83af33a..373a924 100644
*** a/src/backend/optimizer/geqo/geqo_copy.c
--- b/src/backend/optimizer/geqo/geqo_copy.c
***************
*** 35,40 ****
--- 35,41 ----
  
  #include "postgres.h"
  #include "optimizer/geqo_copy.h"
+ #include "optimizer/geqo_copy.h"
  
  /* geqo_copy
   *
***************
*** 42,48 ****
   *
   */
  void
! geqo_copy(Chromosome *chromo1, Chromosome *chromo2, int string_length)
  {
  	int			i;
  
--- 43,50 ----
   *
   */
  void
! geqo_copy(PlannerInfo *root, Chromosome *chromo1, Chromosome *chromo2,
! 		  int string_length)
  {
  	int			i;
  
diff --git a/src/backend/optimizer/geqo/geqo_cx.c b/src/backend/optimizer/geqo/geqo_cx.c
index 3d5102f..ad861ce 100644
*** a/src/backend/optimizer/geqo/geqo_cx.c
--- b/src/backend/optimizer/geqo/geqo_cx.c
***************
*** 35,40 ****
--- 35,41 ----
  
  
  #include "postgres.h"
+ #include "optimizer/geqo.h"
  #include "optimizer/geqo_recombination.h"
  #include "optimizer/geqo_random.h"
  
***************
*** 44,50 ****
   *	 cycle crossover
   */
  int
! cx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
  {
  
  	int			i,
--- 45,52 ----
   *	 cycle crossover
   */
  int
! cx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring,
!    int num_gene, City *city_table)
  {
  
  	int			i,
*************** cx(Gene *tour1, Gene *tour2, Gene *offsp
*** 62,68 ****
  	}
  
  	/* choose random cycle starting position */
! 	start_pos = geqo_randint(num_gene - 1, 0);
  
  	/* child inherits first city  */
  	offspring[start_pos] = tour1[start_pos];
--- 64,70 ----
  	}
  
  	/* choose random cycle starting position */
! 	start_pos = geqo_randint(root, num_gene - 1, 0);
  
  	/* child inherits first city  */
  	offspring[start_pos] = tour1[start_pos];
diff --git a/src/backend/optimizer/geqo/geqo_erx.c b/src/backend/optimizer/geqo/geqo_erx.c
index 35e1a28..5bae059 100644
*** a/src/backend/optimizer/geqo/geqo_erx.c
--- b/src/backend/optimizer/geqo/geqo_erx.c
***************
*** 36,46 ****
  #include "optimizer/geqo_random.h"
  
  
! static int	gimme_edge(Gene gene1, Gene gene2, Edge *edge_table);
! static void remove_gene(Gene gene, Edge edge, Edge *edge_table);
! static Gene gimme_gene(Edge edge, Edge *edge_table);
  
! static Gene edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene);
  
  
  /* alloc_edge_table
--- 36,46 ----
  #include "optimizer/geqo_random.h"
  
  
! static int	gimme_edge(PlannerInfo *root, Gene gene1, Gene gene2, Edge *edge_table);
! static void remove_gene(PlannerInfo *root, Gene gene, Edge edge, Edge *edge_table);
! static Gene gimme_gene(PlannerInfo *root, Edge edge, Edge *edge_table);
  
! static Gene edge_failure(PlannerInfo *root, Gene *gene, int index, Edge *edge_table, int num_gene);
  
  
  /* alloc_edge_table
*************** static Gene edge_failure(Gene *gene, int
*** 50,56 ****
   */
  
  Edge *
! alloc_edge_table(int num_gene)
  {
  	Edge	   *edge_table;
  
--- 50,56 ----
   */
  
  Edge *
! alloc_edge_table(PlannerInfo *root, int num_gene)
  {
  	Edge	   *edge_table;
  
*************** alloc_edge_table(int num_gene)
*** 70,76 ****
   *
   */
  void
! free_edge_table(Edge *edge_table)
  {
  	pfree(edge_table);
  }
--- 70,76 ----
   *
   */
  void
! free_edge_table(PlannerInfo *root, Edge *edge_table)
  {
  	pfree(edge_table);
  }
*************** free_edge_table(Edge *edge_table)
*** 89,95 ****
   *
   */
  float
! gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table)
  {
  	int			i,
  				index1,
--- 89,96 ----
   *
   */
  float
! gimme_edge_table(PlannerInfo *root, Gene *tour1, Gene *tour2,
! 				 int num_gene, Edge *edge_table)
  {
  	int			i,
  				index1,
*************** gimme_edge_table(Gene *tour1, Gene *tour
*** 121,131 ****
  		 * twice per edge
  		 */
  
! 		edge_total += gimme_edge(tour1[index1], tour1[index2], edge_table);
! 		gimme_edge(tour1[index2], tour1[index1], edge_table);
  
! 		edge_total += gimme_edge(tour2[index1], tour2[index2], edge_table);
! 		gimme_edge(tour2[index2], tour2[index1], edge_table);
  	}
  
  	/* return average number of edges per index */
--- 122,132 ----
  		 * twice per edge
  		 */
  
! 		edge_total += gimme_edge(root, tour1[index1], tour1[index2], edge_table);
! 		gimme_edge(root, tour1[index2], tour1[index1], edge_table);
  
! 		edge_total += gimme_edge(root, tour2[index1], tour2[index2], edge_table);
! 		gimme_edge(root, tour2[index2], tour2[index1], edge_table);
  	}
  
  	/* return average number of edges per index */
*************** gimme_edge_table(Gene *tour1, Gene *tour
*** 147,153 ****
   *			  0 if edge was already registered and edge_table is unchanged
   */
  static int
! gimme_edge(Gene gene1, Gene gene2, Edge *edge_table)
  {
  	int			i;
  	int			edges;
--- 148,154 ----
   *			  0 if edge was already registered and edge_table is unchanged
   */
  static int
! gimme_edge(PlannerInfo *root, Gene gene1, Gene gene2, Edge *edge_table)
  {
  	int			i;
  	int			edges;
*************** gimme_edge(Gene gene1, Gene gene2, Edge 
*** 189,200 ****
   *
   */
  int
! gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene)
  {
  	int			i;
  	int			edge_failures = 0;
  
! 	new_gene[0] = (Gene) geqo_randint(num_gene, 1);		/* choose int between 1
  														 * and num_gene */
  
  	for (i = 1; i < num_gene; i++)
--- 190,201 ----
   *
   */
  int
! gimme_tour(PlannerInfo *root, Edge *edge_table, Gene *new_gene, int num_gene)
  {
  	int			i;
  	int			edge_failures = 0;
  
! 	new_gene[0] = (Gene) geqo_randint(root, num_gene, 1);		/* choose int between 1
  														 * and num_gene */
  
  	for (i = 1; i < num_gene; i++)
*************** gimme_tour(Edge *edge_table, Gene *new_g
*** 204,221 ****
  		 * table
  		 */
  
! 		remove_gene(new_gene[i - 1], edge_table[(int) new_gene[i - 1]], edge_table);
  
  		/* find destination for the newly entered point */
  
  		if (edge_table[new_gene[i - 1]].unused_edges > 0)
! 			new_gene[i] = gimme_gene(edge_table[(int) new_gene[i - 1]], edge_table);
  
  		else
  		{						/* cope with fault */
  			edge_failures++;
  
! 			new_gene[i] = edge_failure(new_gene, i - 1, edge_table, num_gene);
  		}
  
  		/* mark this node as incorporated */
--- 205,222 ----
  		 * table
  		 */
  
! 		remove_gene(root, new_gene[i - 1], edge_table[(int) new_gene[i - 1]], edge_table);
  
  		/* find destination for the newly entered point */
  
  		if (edge_table[new_gene[i - 1]].unused_edges > 0)
! 			new_gene[i] = gimme_gene(root, edge_table[(int) new_gene[i - 1]], edge_table);
  
  		else
  		{						/* cope with fault */
  			edge_failures++;
  
! 			new_gene[i] = edge_failure(root, new_gene, i - 1, edge_table, num_gene);
  		}
  
  		/* mark this node as incorporated */
*************** gimme_tour(Edge *edge_table, Gene *new_g
*** 235,241 ****
   *
   */
  static void
! remove_gene(Gene gene, Edge edge, Edge *edge_table)
  {
  	int			i,
  				j;
--- 236,242 ----
   *
   */
  static void
! remove_gene(PlannerInfo *root, Gene gene, Edge edge, Edge *edge_table)
  {
  	int			i,
  				j;
*************** remove_gene(Gene gene, Edge edge, Edge *
*** 277,283 ****
   *
   */
  static Gene
! gimme_gene(Edge edge, Edge *edge_table)
  {
  	int			i;
  	Gene		friend;
--- 278,284 ----
   *
   */
  static Gene
! gimme_gene(PlannerInfo *root, Edge edge, Edge *edge_table)
  {
  	int			i;
  	Gene		friend;
*************** gimme_gene(Edge edge, Edge *edge_table)
*** 340,346 ****
  
  
  	/* random decision of the possible candidates to use */
! 	rand_decision = (int) geqo_randint(minimum_count - 1, 0);
  
  
  	for (i = 0; i < edge.unused_edges; i++)
--- 341,347 ----
  
  
  	/* random decision of the possible candidates to use */
! 	rand_decision = geqo_randint(root, minimum_count - 1, 0);
  
  
  	for (i = 0; i < edge.unused_edges; i++)
*************** gimme_gene(Edge edge, Edge *edge_table)
*** 368,374 ****
   *
   */
  static Gene
! edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene)
  {
  	int			i;
  	Gene		fail_gene = gene[index];
--- 369,375 ----
   *
   */
  static Gene
! edge_failure(PlannerInfo *root, Gene *gene, int index, Edge *edge_table, int num_gene)
  {
  	int			i;
  	Gene		fail_gene = gene[index];
*************** edge_failure(Gene *gene, int index, Edge
*** 401,407 ****
  	if (four_count != 0)
  	{
  
! 		rand_decision = (int) geqo_randint(four_count - 1, 0);
  
  		for (i = 1; i <= num_gene; i++)
  		{
--- 402,408 ----
  	if (four_count != 0)
  	{
  
! 		rand_decision = geqo_randint(root, four_count - 1, 0);
  
  		for (i = 1; i <= num_gene; i++)
  		{
*************** edge_failure(Gene *gene, int index, Edge
*** 423,429 ****
  	else if (remaining_edges != 0)
  	{
  		/* random decision of the gene with remaining edges */
! 		rand_decision = (int) geqo_randint(remaining_edges - 1, 0);
  
  		for (i = 1; i <= num_gene; i++)
  		{
--- 424,430 ----
  	else if (remaining_edges != 0)
  	{
  		/* random decision of the gene with remaining edges */
! 		rand_decision = geqo_randint(root, remaining_edges - 1, 0);
  
  		for (i = 1; i <= num_gene; i++)
  		{
diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c
index 04b3bfe..11903a5 100644
*** a/src/backend/optimizer/geqo/geqo_eval.c
--- b/src/backend/optimizer/geqo/geqo_eval.c
*************** static bool desirable_join(PlannerInfo *
*** 42,48 ****
   * Returns cost of a query tree as an individual of the population.
   */
  Cost
! geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata)
  {
  	MemoryContext mycontext;
  	MemoryContext oldcxt;
--- 42,48 ----
   * Returns cost of a query tree as an individual of the population.
   */
  Cost
! geqo_eval(PlannerInfo *root, Gene *tour, int num_gene)
  {
  	MemoryContext mycontext;
  	MemoryContext oldcxt;
*************** geqo_eval(Gene *tour, int num_gene, Geqo
*** 94,106 ****
  	 * (If we are dealing with enough join rels, which we very likely are, a
  	 * new hash table will get built and used locally.)
  	 */
! 	savelength = list_length(evaldata->root->join_rel_list);
! 	savehash = evaldata->root->join_rel_hash;
  
! 	evaldata->root->join_rel_hash = NULL;
  
  	/* construct the best path for the given combination of relations */
! 	joinrel = gimme_tree(tour, num_gene, evaldata);
  
  	/*
  	 * compute fitness
--- 94,106 ----
  	 * (If we are dealing with enough join rels, which we very likely are, a
  	 * new hash table will get built and used locally.)
  	 */
! 	savelength = list_length(root->join_rel_list);
! 	savehash = root->join_rel_hash;
  
! 	root->join_rel_hash = NULL;
  
  	/* construct the best path for the given combination of relations */
! 	joinrel = gimme_tree(root, tour, num_gene);
  
  	/*
  	 * compute fitness
*************** geqo_eval(Gene *tour, int num_gene, Geqo
*** 117,125 ****
  	 * Restore join_rel_list to its former state, and put back original
  	 * hashtable if any.
  	 */
! 	evaldata->root->join_rel_list = list_truncate(evaldata->root->join_rel_list,
! 												  savelength);
! 	evaldata->root->join_rel_hash = savehash;
  
  	/* release all the memory acquired within gimme_tree */
  	MemoryContextSwitchTo(oldcxt);
--- 117,125 ----
  	 * Restore join_rel_list to its former state, and put back original
  	 * hashtable if any.
  	 */
! 	root->join_rel_list = list_truncate(root->join_rel_list,
! 										savelength);
! 	root->join_rel_hash = savehash;
  
  	/* release all the memory acquired within gimme_tree */
  	MemoryContextSwitchTo(oldcxt);
*************** geqo_eval(Gene *tour, int num_gene, Geqo
*** 134,140 ****
   *	  order.
   *
   *	 'tour' is the proposed join order, of length 'num_gene'
-  *	 'evaldata' contains the context we need
   *
   * Returns a new join relation whose cheapest path is the best plan for
   * this join order.  NB: will return NULL if join order is invalid.
--- 134,139 ----
*************** geqo_eval(Gene *tour, int num_gene, Geqo
*** 153,159 ****
   * plans.
   */
  RelOptInfo *
! gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata)
  {
  	RelOptInfo **stack;
  	int			stack_depth;
--- 152,158 ----
   * plans.
   */
  RelOptInfo *
! gimme_tree(PlannerInfo *root, Gene *tour, int num_gene)
  {
  	RelOptInfo **stack;
  	int			stack_depth;
*************** gimme_tree(Gene *tour, int num_gene, Geq
*** 193,200 ****
  
  		/* Get the next input relation and push it */
  		cur_rel_index = (int) tour[rel_count];
! 		stack[stack_depth] = (RelOptInfo *) list_nth(evaldata->initial_rels,
! 													 cur_rel_index - 1);
  		stack_depth++;
  
  		/*
--- 192,200 ----
  
  		/* Get the next input relation and push it */
  		cur_rel_index = (int) tour[rel_count];
! 		stack[stack_depth] = (RelOptInfo *) list_nth(
! 			((GeqoPrivateData*)root->join_search_private)->initial_rels,
! 			cur_rel_index - 1);
  		stack_depth++;
  
  		/*
*************** gimme_tree(Gene *tour, int num_gene, Geq
*** 211,217 ****
  			 * have exhausted the input, the heuristics can't prevent popping.
  			 */
  			if (rel_count < num_gene - 1 &&
! 				!desirable_join(evaldata->root, outer_rel, inner_rel))
  				break;
  
  			/*
--- 211,217 ----
  			 * have exhausted the input, the heuristics can't prevent popping.
  			 */
  			if (rel_count < num_gene - 1 &&
! 				!desirable_join(root, outer_rel, inner_rel))
  				break;
  
  			/*
*************** gimme_tree(Gene *tour, int num_gene, Geq
*** 220,226 ****
  			 * root->join_rel_list yet, and so the paths constructed for it
  			 * will only include the ones we want.
  			 */
! 			joinrel = make_join_rel(evaldata->root, outer_rel, inner_rel);
  
  			/* Can't pop stack here if join order is not valid */
  			if (!joinrel)
--- 220,226 ----
  			 * root->join_rel_list yet, and so the paths constructed for it
  			 * will only include the ones we want.
  			 */
! 			joinrel = make_join_rel(root, outer_rel, inner_rel);
  
  			/* Can't pop stack here if join order is not valid */
  			if (!joinrel)
diff --git a/src/backend/optimizer/geqo/geqo_main.c b/src/backend/optimizer/geqo/geqo_main.c
index 72b0b57..10f64f4 100644
*** a/src/backend/optimizer/geqo/geqo_main.c
--- b/src/backend/optimizer/geqo/geqo_main.c
***************
*** 29,34 ****
--- 29,35 ----
  #include "optimizer/geqo_misc.h"
  #include "optimizer/geqo_pool.h"
  #include "optimizer/geqo_selection.h"
+ #include "optimizer/geqo_random.h"
  
  
  /*
*************** int			Geqo_effort;
*** 38,43 ****
--- 39,45 ----
  int			Geqo_pool_size;
  int			Geqo_generations;
  double		Geqo_selection_bias;
+ double		Geqo_seed;
  
  
  static int	gimme_pool_size(int nr_rel);
*************** static int	gimme_number_generations(int 
*** 63,69 ****
  RelOptInfo *
  geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
  {
- 	GeqoEvalData evaldata;
  	int			generation;
  	Chromosome *momma;
  	Chromosome *daddy;
--- 65,70 ----
*************** geqo(PlannerInfo *root, int number_of_re
*** 88,96 ****
  	int			mutations = 0;
  #endif
  
! /* set up evaldata */
! 	evaldata.root = root;
! 	evaldata.initial_rels = initial_rels;
  
  /* set GA parameters */
  	pool_size = gimme_pool_size(number_of_rels);
--- 89,102 ----
  	int			mutations = 0;
  #endif
  
! /* setup private information */
! 	root->join_search_private = (GeqoPrivateData*)palloc0(sizeof(GeqoPrivateData));
! 	((GeqoPrivateData*)root->join_search_private)->initial_rels = initial_rels;
! 
! /* initialize private number generator */
! 	if(Geqo_seed != 0){
! 		geqo_seed(root, Geqo_seed);
! 	}
  
  /* set GA parameters */
  	pool_size = gimme_pool_size(number_of_rels);
*************** geqo(PlannerInfo *root, int number_of_re
*** 98,110 ****
  	status_interval = 10;
  
  /* allocate genetic pool memory */
! 	pool = alloc_pool(pool_size, number_of_rels);
  
  /* random initialization of the pool */
! 	random_init_pool(pool, &evaldata);
  
  /* sort the pool according to cheapest path as fitness */
! 	sort_pool(pool);			/* we have to do it only one time, since all
  								 * kids replace the worst individuals in
  								 * future (-> geqo_pool.c:spread_chromo ) */
  
--- 104,116 ----
  	status_interval = 10;
  
  /* allocate genetic pool memory */
! 	pool = alloc_pool(root, pool_size, number_of_rels);
  
  /* random initialization of the pool */
! 	random_init_pool(root, pool);
  
  /* sort the pool according to cheapest path as fitness */
! 	sort_pool(root, pool);			/* we have to do it only one time, since all
  								 * kids replace the worst individuals in
  								 * future (-> geqo_pool.c:spread_chromo ) */
  
*************** geqo(PlannerInfo *root, int number_of_re
*** 116,164 ****
  #endif
  
  /* allocate chromosome momma and daddy memory */
! 	momma = alloc_chromo(pool->string_length);
! 	daddy = alloc_chromo(pool->string_length);
  
  #if defined (ERX)
  #ifdef GEQO_DEBUG
  	elog(DEBUG2, "using edge recombination crossover [ERX]");
  #endif
  /* allocate edge table memory */
! 	edge_table = alloc_edge_table(pool->string_length);
  #elif defined(PMX)
  #ifdef GEQO_DEBUG
  	elog(DEBUG2, "using partially matched crossover [PMX]");
  #endif
  /* allocate chromosome kid memory */
! 	kid = alloc_chromo(pool->string_length);
  #elif defined(CX)
  #ifdef GEQO_DEBUG
  	elog(DEBUG2, "using cycle crossover [CX]");
  #endif
  /* allocate city table memory */
! 	kid = alloc_chromo(pool->string_length);
! 	city_table = alloc_city_table(pool->string_length);
  #elif defined(PX)
  #ifdef GEQO_DEBUG
  	elog(DEBUG2, "using position crossover [PX]");
  #endif
  /* allocate city table memory */
! 	kid = alloc_chromo(pool->string_length);
! 	city_table = alloc_city_table(pool->string_length);
  #elif defined(OX1)
  #ifdef GEQO_DEBUG
  	elog(DEBUG2, "using order crossover [OX1]");
  #endif
  /* allocate city table memory */
  	kid = alloc_chromo(pool->string_length);
! 	city_table = alloc_city_table(pool->string_length);
  #elif defined(OX2)
  #ifdef GEQO_DEBUG
  	elog(DEBUG2, "using order crossover [OX2]");
  #endif
  /* allocate city table memory */
  	kid = alloc_chromo(pool->string_length);
! 	city_table = alloc_city_table(pool->string_length);
  #endif
  
  
--- 122,170 ----
  #endif
  
  /* allocate chromosome momma and daddy memory */
! 	momma = alloc_chromo(root, pool->string_length);
! 	daddy = alloc_chromo(root, pool->string_length);
  
  #if defined (ERX)
  #ifdef GEQO_DEBUG
  	elog(DEBUG2, "using edge recombination crossover [ERX]");
  #endif
  /* allocate edge table memory */
! 	edge_table = alloc_edge_table(root, pool->string_length);
  #elif defined(PMX)
  #ifdef GEQO_DEBUG
  	elog(DEBUG2, "using partially matched crossover [PMX]");
  #endif
  /* allocate chromosome kid memory */
! 	kid = alloc_chromo(root, pool->string_length);
  #elif defined(CX)
  #ifdef GEQO_DEBUG
  	elog(DEBUG2, "using cycle crossover [CX]");
  #endif
  /* allocate city table memory */
! 	kid = alloc_chromo(root, pool->string_length);
! 	city_table = alloc_city_table(root, pool->string_length);
  #elif defined(PX)
  #ifdef GEQO_DEBUG
  	elog(DEBUG2, "using position crossover [PX]");
  #endif
  /* allocate city table memory */
! 	kid = alloc_chromo(root, pool->string_length);
! 	city_table = alloc_city_table(root, pool->string_length);
  #elif defined(OX1)
  #ifdef GEQO_DEBUG
  	elog(DEBUG2, "using order crossover [OX1]");
  #endif
  /* allocate city table memory */
  	kid = alloc_chromo(pool->string_length);
! 	city_table = alloc_city_table(root, pool->string_length);
  #elif defined(OX2)
  #ifdef GEQO_DEBUG
  	elog(DEBUG2, "using order crossover [OX2]");
  #endif
  /* allocate city table memory */
  	kid = alloc_chromo(pool->string_length);
! 	city_table = alloc_city_table(root, pool->string_length);
  #endif
  
  
*************** geqo(PlannerInfo *root, int number_of_re
*** 168,212 ****
  	for (generation = 0; generation < number_generations; generation++)
  	{
  		/* SELECTION: using linear bias function */
! 		geqo_selection(momma, daddy, pool, Geqo_selection_bias);
  
  #if defined (ERX)
  		/* EDGE RECOMBINATION CROSSOVER */
! 		difference = gimme_edge_table(momma->string, daddy->string, pool->string_length, edge_table);
  
  		kid = momma;
  
  		/* are there any edge failures ? */
! 		edge_failures += gimme_tour(edge_table, kid->string, pool->string_length);
  #elif defined(PMX)
  		/* PARTIALLY MATCHED CROSSOVER */
! 		pmx(momma->string, daddy->string, kid->string, pool->string_length);
  #elif defined(CX)
  		/* CYCLE CROSSOVER */
! 		cycle_diffs = cx(momma->string, daddy->string, kid->string, pool->string_length, city_table);
  		/* mutate the child */
  		if (cycle_diffs == 0)
  		{
  			mutations++;
! 			geqo_mutation(kid->string, pool->string_length);
  		}
  #elif defined(PX)
  		/* POSITION CROSSOVER */
! 		px(momma->string, daddy->string, kid->string, pool->string_length, city_table);
  #elif defined(OX1)
  		/* ORDER CROSSOVER */
! 		ox1(momma->string, daddy->string, kid->string, pool->string_length, city_table);
  #elif defined(OX2)
  		/* ORDER CROSSOVER */
! 		ox2(momma->string, daddy->string, kid->string, pool->string_length, city_table);
  #endif
  
  
  		/* EVALUATE FITNESS */
! 		kid->worth = geqo_eval(kid->string, pool->string_length, &evaldata);
  
  		/* push the kid into the wilderness of life according to its worth */
! 		spread_chromo(kid, pool);
  
  
  #ifdef GEQO_DEBUG
--- 174,218 ----
  	for (generation = 0; generation < number_generations; generation++)
  	{
  		/* SELECTION: using linear bias function */
! 		geqo_selection(root, momma, daddy, pool, Geqo_selection_bias);
  
  #if defined (ERX)
  		/* EDGE RECOMBINATION CROSSOVER */
! 		difference = gimme_edge_table(root, momma->string, daddy->string, pool->string_length, edge_table);
  
  		kid = momma;
  
  		/* are there any edge failures ? */
! 		edge_failures += gimme_tour(root, edge_table, kid->string, pool->string_length);
  #elif defined(PMX)
  		/* PARTIALLY MATCHED CROSSOVER */
! 		pmx(root, momma->string, daddy->string, kid->string, pool->string_length);
  #elif defined(CX)
  		/* CYCLE CROSSOVER */
! 		cycle_diffs = cx(root, momma->string, daddy->string, kid->string, pool->string_length, city_table);
  		/* mutate the child */
  		if (cycle_diffs == 0)
  		{
  			mutations++;
! 			geqo_mutation(root, kid->string, pool->string_length);
  		}
  #elif defined(PX)
  		/* POSITION CROSSOVER */
! 		px(root, momma->string, daddy->string, kid->string, pool->string_length, city_table);
  #elif defined(OX1)
  		/* ORDER CROSSOVER */
! 		ox1(root, momma->string, daddy->string, kid->string, pool->string_length, city_table);
  #elif defined(OX2)
  		/* ORDER CROSSOVER */
! 		ox2(root, momma->string, daddy->string, kid->string, pool->string_length, city_table);
  #endif
  
  
  		/* EVALUATE FITNESS */
! 		kid->worth = geqo_eval(root, kid->string, pool->string_length);
  
  		/* push the kid into the wilderness of life according to its worth */
! 		spread_chromo(root, kid, pool);
  
  
  #ifdef GEQO_DEBUG
*************** geqo(PlannerInfo *root, int number_of_re
*** 249,255 ****
  	 */
  	best_tour = (Gene *) pool->data[0].string;
  
! 	best_rel = gimme_tree(best_tour, pool->string_length, &evaldata);
  
  	if (best_rel == NULL)
  		elog(ERROR, "failed to make a valid plan");
--- 255,261 ----
  	 */
  	best_tour = (Gene *) pool->data[0].string;
  
! 	best_rel = gimme_tree(root, best_tour, pool->string_length);
  
  	if (best_rel == NULL)
  		elog(ERROR, "failed to make a valid plan");
*************** geqo(PlannerInfo *root, int number_of_re
*** 260,287 ****
  #endif
  
  	/* ... free memory stuff */
! 	free_chromo(momma);
! 	free_chromo(daddy);
  
  #if defined (ERX)
! 	free_edge_table(edge_table);
  #elif defined(PMX)
! 	free_chromo(kid);
  #elif defined(CX)
! 	free_chromo(kid);
! 	free_city_table(city_table);
  #elif defined(PX)
! 	free_chromo(kid);
! 	free_city_table(city_table);
  #elif defined(OX1)
! 	free_chromo(kid);
! 	free_city_table(city_table);
  #elif defined(OX2)
! 	free_chromo(kid);
! 	free_city_table(city_table);
  #endif
  
! 	free_pool(pool);
  
  	return best_rel;
  }
--- 266,293 ----
  #endif
  
  	/* ... free memory stuff */
! 	free_chromo(root, momma);
! 	free_chromo(root, daddy);
  
  #if defined (ERX)
! 	free_edge_table(root, edge_table);
  #elif defined(PMX)
! 	free_chromo(root, kid);
  #elif defined(CX)
! 	free_chromo(root, kid);
! 	free_city_table(root, city_table);
  #elif defined(PX)
! 	free_chromo(root, kid);
! 	free_city_table(root, city_table);
  #elif defined(OX1)
! 	free_chromo(root, kid);
! 	free_city_table(root, city_table);
  #elif defined(OX2)
! 	free_chromo(root, kid);
! 	free_city_table(root, city_table);
  #endif
  
! 	free_pool(root, pool);
  
  	return best_rel;
  }
diff --git a/src/backend/optimizer/geqo/geqo_mutation.c b/src/backend/optimizer/geqo/geqo_mutation.c
index 899410c..acf3b34 100644
*** a/src/backend/optimizer/geqo/geqo_mutation.c
--- b/src/backend/optimizer/geqo/geqo_mutation.c
***************
*** 36,56 ****
  #include "optimizer/geqo_random.h"
  
  void
! geqo_mutation(Gene *tour, int num_gene)
  {
  	int			swap1;
  	int			swap2;
! 	int			num_swaps = geqo_randint(num_gene / 3, 0);
  	Gene		temp;
  
  
  	while (num_swaps > 0)
  	{
! 		swap1 = geqo_randint(num_gene - 1, 0);
! 		swap2 = geqo_randint(num_gene - 1, 0);
  
  		while (swap1 == swap2)
! 			swap2 = geqo_randint(num_gene - 1, 0);
  
  		temp = tour[swap1];
  		tour[swap1] = tour[swap2];
--- 36,56 ----
  #include "optimizer/geqo_random.h"
  
  void
! geqo_mutation(PlannerInfo *root, Gene *tour, int num_gene)
  {
  	int			swap1;
  	int			swap2;
! 	int			num_swaps = geqo_randint(root, num_gene / 3, 0);
  	Gene		temp;
  
  
  	while (num_swaps > 0)
  	{
! 		swap1 = geqo_randint(root, num_gene - 1, 0);
! 		swap2 = geqo_randint(root, num_gene - 1, 0);
  
  		while (swap1 == swap2)
! 			swap2 = geqo_randint(root, num_gene - 1, 0);
  
  		temp = tour[swap1];
  		tour[swap1] = tour[swap2];
diff --git a/src/backend/optimizer/geqo/geqo_ox1.c b/src/backend/optimizer/geqo/geqo_ox1.c
index cd979df..d292e98 100644
*** a/src/backend/optimizer/geqo/geqo_ox1.c
--- b/src/backend/optimizer/geqo/geqo_ox1.c
***************
*** 34,39 ****
--- 34,40 ----
  /*************************************************************/
  
  #include "postgres.h"
+ #include "optimizer/geqo.h"
  #include "optimizer/geqo_random.h"
  #include "optimizer/geqo_recombination.h"
  
***************
*** 43,49 ****
   *	 position crossover
   */
  void
! ox1(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
  {
  	int			left,
  				right,
--- 44,51 ----
   *	 position crossover
   */
  void
! ox1(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene,
! 	City *city_table)
  {
  	int			left,
  				right,
*************** ox1(Gene *tour1, Gene *tour2, Gene *offs
*** 56,63 ****
  		city_table[k].used = 0;
  
  	/* select portion to copy from tour1 */
! 	left = geqo_randint(num_gene - 1, 0);
! 	right = geqo_randint(num_gene - 1, 0);
  
  	if (left > right)
  	{
--- 58,65 ----
  		city_table[k].used = 0;
  
  	/* select portion to copy from tour1 */
! 	left = geqo_randint(root, num_gene - 1, 0);
! 	right = geqo_randint(root, num_gene - 1, 0);
  
  	if (left > right)
  	{
diff --git a/src/backend/optimizer/geqo/geqo_ox2.c b/src/backend/optimizer/geqo/geqo_ox2.c
index 0d2e0de..a2fdfe8 100644
*** a/src/backend/optimizer/geqo/geqo_ox2.c
--- b/src/backend/optimizer/geqo/geqo_ox2.c
***************
*** 34,39 ****
--- 34,40 ----
  /*************************************************************/
  
  #include "postgres.h"
+ #include "optimizer/geqo.h"
  #include "optimizer/geqo_random.h"
  #include "optimizer/geqo_recombination.h"
  
***************
*** 43,49 ****
   *	 position crossover
   */
  void
! ox2(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
  {
  	int			k,
  				j,
--- 44,50 ----
   *	 position crossover
   */
  void
! ox2(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
  {
  	int			k,
  				j,
*************** ox2(Gene *tour1, Gene *tour2, Gene *offs
*** 60,71 ****
  	}
  
  	/* determine the number of positions to be inherited from tour1  */
! 	num_positions = geqo_randint(2 * num_gene / 3, num_gene / 3);
  
  	/* make a list of selected cities */
  	for (k = 0; k < num_positions; k++)
  	{
! 		pos = geqo_randint(num_gene - 1, 0);
  		city_table[pos].select_list = (int) tour1[pos];
  		city_table[(int) tour1[pos]].used = 1;	/* mark used */
  	}
--- 61,72 ----
  	}
  
  	/* determine the number of positions to be inherited from tour1  */
! 	num_positions = geqo_randint(root, 2 * num_gene / 3, num_gene / 3);
  
  	/* make a list of selected cities */
  	for (k = 0; k < num_positions; k++)
  	{
! 		pos = geqo_randint(root, num_gene - 1, 0);
  		city_table[pos].select_list = (int) tour1[pos];
  		city_table[(int) tour1[pos]].used = 1;	/* mark used */
  	}
diff --git a/src/backend/optimizer/geqo/geqo_pmx.c b/src/backend/optimizer/geqo/geqo_pmx.c
index fe9d4b4..a8d18c5 100644
*** a/src/backend/optimizer/geqo/geqo_pmx.c
--- b/src/backend/optimizer/geqo/geqo_pmx.c
***************
*** 34,39 ****
--- 34,40 ----
  /*************************************************************/
  
  #include "postgres.h"
+ #include "optimizer/geqo.h"
  #include "optimizer/geqo_random.h"
  #include "optimizer/geqo_recombination.h"
  
***************
*** 43,49 ****
   *	 partially matched crossover
   */
  void
! pmx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene)
  {
  	int		   *failed = (int *) palloc((num_gene + 1) * sizeof(int));
  	int		   *from = (int *) palloc((num_gene + 1) * sizeof(int));
--- 44,50 ----
   *	 partially matched crossover
   */
  void
! pmx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene)
  {
  	int		   *failed = (int *) palloc((num_gene + 1) * sizeof(int));
  	int		   *from = (int *) palloc((num_gene + 1) * sizeof(int));
*************** pmx(Gene *tour1, Gene *tour2, Gene *offs
*** 71,78 ****
  	}
  
  /* locate crossover points */
! 	left = geqo_randint(num_gene - 1, 0);
! 	right = geqo_randint(num_gene - 1, 0);
  
  	if (left > right)
  	{
--- 72,79 ----
  	}
  
  /* locate crossover points */
! 	left = geqo_randint(root, num_gene - 1, 0);
! 	right = geqo_randint(root, num_gene - 1, 0);
  
  	if (left > right)
  	{
diff --git a/src/backend/optimizer/geqo/geqo_pool.c b/src/backend/optimizer/geqo/geqo_pool.c
index 72eb34f..64e23ba 100644
*** a/src/backend/optimizer/geqo/geqo_pool.c
--- b/src/backend/optimizer/geqo/geqo_pool.c
*************** static int	compare(const void *arg1, con
*** 39,45 ****
   *		allocates memory for GA pool
   */
  Pool *
! alloc_pool(int pool_size, int string_length)
  {
  	Pool	   *new_pool;
  	Chromosome *chromo;
--- 39,45 ----
   *		allocates memory for GA pool
   */
  Pool *
! alloc_pool(PlannerInfo *root, int pool_size, int string_length)
  {
  	Pool	   *new_pool;
  	Chromosome *chromo;
*************** alloc_pool(int pool_size, int string_len
*** 66,72 ****
   *		deallocates memory for GA pool
   */
  void
! free_pool(Pool *pool)
  {
  	Chromosome *chromo;
  	int			i;
--- 66,72 ----
   *		deallocates memory for GA pool
   */
  void
! free_pool(PlannerInfo *root, Pool *pool)
  {
  	Chromosome *chromo;
  	int			i;
*************** free_pool(Pool *pool)
*** 88,94 ****
   *		initialize genetic pool
   */
  void
! random_init_pool(Pool *pool, GeqoEvalData *evaldata)
  {
  	Chromosome *chromo = (Chromosome *) pool->data;
  	int			i;
--- 88,94 ----
   *		initialize genetic pool
   */
  void
! random_init_pool(PlannerInfo *root, Pool *pool)
  {
  	Chromosome *chromo = (Chromosome *) pool->data;
  	int			i;
*************** random_init_pool(Pool *pool, GeqoEvalDat
*** 105,114 ****
  	i = 0;
  	while (i < pool->size)
  	{
! 		init_tour(chromo[i].string, pool->string_length);
! 		pool->data[i].worth = geqo_eval(chromo[i].string,
! 										pool->string_length,
! 										evaldata);
  		if (pool->data[i].worth < DBL_MAX)
  			i++;
  		else
--- 105,113 ----
  	i = 0;
  	while (i < pool->size)
  	{
! 		init_tour(root, chromo[i].string, pool->string_length);
! 		pool->data[i].worth = geqo_eval(root, chromo[i].string,
! 										pool->string_length);
  		if (pool->data[i].worth < DBL_MAX)
  			i++;
  		else
*************** random_init_pool(Pool *pool, GeqoEvalDat
*** 133,139 ****
   *	 maybe you have to change compare() for different ordering ...
   */
  void
! sort_pool(Pool *pool)
  {
  	qsort(pool->data, pool->size, sizeof(Chromosome), compare);
  }
--- 132,138 ----
   *	 maybe you have to change compare() for different ordering ...
   */
  void
! sort_pool(PlannerInfo *root, Pool *pool)
  {
  	qsort(pool->data, pool->size, sizeof(Chromosome), compare);
  }
*************** compare(const void *arg1, const void *ar
*** 160,166 ****
   *	  allocates a chromosome and string space
   */
  Chromosome *
! alloc_chromo(int string_length)
  {
  	Chromosome *chromo;
  
--- 159,165 ----
   *	  allocates a chromosome and string space
   */
  Chromosome *
! alloc_chromo(PlannerInfo *root, int string_length)
  {
  	Chromosome *chromo;
  
*************** alloc_chromo(int string_length)
*** 174,180 ****
   *	  deallocates a chromosome and string space
   */
  void
! free_chromo(Chromosome *chromo)
  {
  	pfree(chromo->string);
  	pfree(chromo);
--- 173,179 ----
   *	  deallocates a chromosome and string space
   */
  void
! free_chromo(PlannerInfo *root, Chromosome *chromo)
  {
  	pfree(chromo->string);
  	pfree(chromo);
*************** free_chromo(Chromosome *chromo)
*** 185,191 ****
   *	 assumes best->worst = smallest->largest
   */
  void
! spread_chromo(Chromosome *chromo, Pool *pool)
  {
  	int			top,
  				mid,
--- 184,190 ----
   *	 assumes best->worst = smallest->largest
   */
  void
! spread_chromo(PlannerInfo *root, Chromosome *chromo, Pool *pool)
  {
  	int			top,
  				mid,
*************** spread_chromo(Chromosome *chromo, Pool *
*** 247,253 ****
  	 * copy new gene into pool storage; always replace worst gene in pool
  	 */
  
! 	geqo_copy(&pool->data[pool->size - 1], chromo, pool->string_length);
  
  	swap_chromo.string = pool->data[pool->size - 1].string;
  	swap_chromo.worth = pool->data[pool->size - 1].worth;
--- 246,252 ----
  	 * copy new gene into pool storage; always replace worst gene in pool
  	 */
  
! 	geqo_copy(root, &pool->data[pool->size - 1], chromo, pool->string_length);
  
  	swap_chromo.string = pool->data[pool->size - 1].string;
  	swap_chromo.worth = pool->data[pool->size - 1].worth;
diff --git a/src/backend/optimizer/geqo/geqo_px.c b/src/backend/optimizer/geqo/geqo_px.c
index 07f41cd..9e9cee2 100644
*** a/src/backend/optimizer/geqo/geqo_px.c
--- b/src/backend/optimizer/geqo/geqo_px.c
***************
*** 34,39 ****
--- 34,40 ----
  /*************************************************************/
  
  #include "postgres.h"
+ #include "optimizer/geqo.h"
  #include "optimizer/geqo_random.h"
  #include "optimizer/geqo_recombination.h"
  
***************
*** 43,49 ****
   *	 position crossover
   */
  void
! px(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
  {
  
  	int			num_positions;
--- 44,51 ----
   *	 position crossover
   */
  void
! px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene,
!    City *city_table)
  {
  
  	int			num_positions;
*************** px(Gene *tour1, Gene *tour2, Gene *offsp
*** 57,68 ****
  		city_table[i].used = 0;
  
  	/* choose random positions that will be inherited directly from parent */
! 	num_positions = geqo_randint(2 * num_gene / 3, num_gene / 3);
  
  	/* choose random position */
  	for (i = 0; i < num_positions; i++)
  	{
! 		pos = geqo_randint(num_gene - 1, 0);
  
  		offspring[pos] = tour1[pos];	/* transfer cities to child */
  		city_table[(int) tour1[pos]].used = 1;	/* mark city used */
--- 59,70 ----
  		city_table[i].used = 0;
  
  	/* choose random positions that will be inherited directly from parent */
! 	num_positions = geqo_randint(root, 2 * num_gene / 3, num_gene / 3);
  
  	/* choose random position */
  	for (i = 0; i < num_positions; i++)
  	{
! 		pos = geqo_randint(root, num_gene - 1, 0);
  
  		offspring[pos] = tour1[pos];	/* transfer cities to child */
  		city_table[(int) tour1[pos]].used = 1;	/* mark city used */
diff --git a/src/backend/optimizer/geqo/geqo_random.c b/src/backend/optimizer/geqo/geqo_random.c
index ...59d5e42 .
*** a/src/backend/optimizer/geqo/geqo_random.c
--- b/src/backend/optimizer/geqo/geqo_random.c
***************
*** 0 ****
--- 1,42 ----
+ /*------------------------------------------------------------------------
+  *
+  * geqo_misc.c
+  *	   misc. printout and debug stuff
+  *
+  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  * $PostgreSQL$
+  *
+  *-------------------------------------------------------------------------
+  */
+ 
+ #include "postgres.h"
+ 
+ #include "optimizer/geqo.h"
+ #include "optimizer/geqo_random.h"
+ 
+ 
+ static unsigned short global_random_state[3];
+ 
+ void geqo_seed(PlannerInfo *root, double seed){
+ 	GeqoPrivateData *private = (GeqoPrivateData*)root->join_search_private;
+ 
+ 	private->random_state = palloc(sizeof(global_random_state));
+ 
+ 	/*
+ 	 * XXX. This seeding algorithm could certainly be improved - but
+ 	 * it is not critical to do so.
+ 	 */
+ 	memcpy(private->random_state,
+ 		   &seed,
+ 		   Min(sizeof(global_random_state),
+ 			   sizeof(seed))
+ 		);
+ }
+ 
+ double geqo_rand(PlannerInfo *root){
+ 	if(!((GeqoPrivateData*)root->join_search_private)->random_state)
+ 		return erand48(global_random_state);
+ 	return erand48(((GeqoPrivateData*)root->join_search_private)->random_state);
+ };
diff --git a/src/backend/optimizer/geqo/geqo_recombination.c b/src/backend/optimizer/geqo/geqo_recombination.c
index 3972fb1..e2b69a3 100644
*** a/src/backend/optimizer/geqo/geqo_recombination.c
--- b/src/backend/optimizer/geqo/geqo_recombination.c
***************
*** 20,25 ****
--- 20,26 ----
  
  #include "postgres.h"
  
+ #include "optimizer/geqo.h"
  #include "optimizer/geqo_random.h"
  #include "optimizer/geqo_recombination.h"
  
***************
*** 35,41 ****
   *	 and the procedure repeated.
   */
  void
! init_tour(Gene *tour, int num_gene)
  {
  	Gene	   *tmp;
  	int			remainder;
--- 36,42 ----
   *	 and the procedure repeated.
   */
  void
! init_tour(PlannerInfo *root, Gene *tour, int num_gene)
  {
  	Gene	   *tmp;
  	int			remainder;
*************** init_tour(Gene *tour, int num_gene)
*** 53,59 ****
  	for (i = 0; i < num_gene; i++)
  	{
  		/* choose value between 0 and remainder inclusive */
! 		next = (int) geqo_randint(remainder, 0);
  		/* output that element of the tmp array */
  		tour[i] = tmp[next];
  		/* and delete it */
--- 54,60 ----
  	for (i = 0; i < num_gene; i++)
  	{
  		/* choose value between 0 and remainder inclusive */
! 		next = (int) geqo_randint(root, remainder, 0);
  		/* output that element of the tmp array */
  		tour[i] = tmp[next];
  		/* and delete it */
*************** init_tour(Gene *tour, int num_gene)
*** 81,87 ****
   *	 allocate memory for city table
   */
  City *
! alloc_city_table(int num_gene)
  {
  	City	   *city_table;
  
--- 82,88 ----
   *	 allocate memory for city table
   */
  City *
! alloc_city_table(PlannerInfo *root, int num_gene)
  {
  	City	   *city_table;
  
*************** alloc_city_table(int num_gene)
*** 99,105 ****
   *	  deallocate memory of city table
   */
  void
! free_city_table(City *city_table)
  {
  	pfree(city_table);
  }
--- 100,106 ----
   *	  deallocate memory of city table
   */
  void
! free_city_table(PlannerInfo *root, City *city_table)
  {
  	pfree(city_table);
  }
diff --git a/src/backend/optimizer/geqo/geqo_selection.c b/src/backend/optimizer/geqo/geqo_selection.c
index d4f2c4d..2cd7402 100644
*** a/src/backend/optimizer/geqo/geqo_selection.c
--- b/src/backend/optimizer/geqo/geqo_selection.c
***************
*** 42,48 ****
  #include "optimizer/geqo_random.h"
  #include "optimizer/geqo_selection.h"
  
! static int	linear(int max, double bias);
  
  
  /*
--- 42,48 ----
  #include "optimizer/geqo_random.h"
  #include "optimizer/geqo_selection.h"
  
! static int	linear(PlannerInfo *root, int max, double bias);
  
  
  /*
*************** static int	linear(int max, double bias);
*** 51,72 ****
   *	 first and second genes are selected from the pool
   */
  void
! geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias)
  {
  	int			first,
  				second;
  
! 	first = linear(pool->size, bias);
! 	second = linear(pool->size, bias);
  
  	if (pool->size > 1)
  	{
  		while (first == second)
! 			second = linear(pool->size, bias);
  	}
  
! 	geqo_copy(momma, &pool->data[first], pool->string_length);
! 	geqo_copy(daddy, &pool->data[second], pool->string_length);
  }
  
  /*
--- 51,73 ----
   *	 first and second genes are selected from the pool
   */
  void
! geqo_selection(PlannerInfo *root, Chromosome *momma, Chromosome *daddy,
! 			   Pool *pool, double bias)
  {
  	int			first,
  				second;
  
! 	first = linear(root, pool->size, bias);
! 	second = linear(root, pool->size, bias);
  
  	if (pool->size > 1)
  	{
  		while (first == second)
! 			second = linear(root, pool->size, bias);
  	}
  
! 	geqo_copy(root, momma, &pool->data[first], pool->string_length);
! 	geqo_copy(root, daddy, &pool->data[second], pool->string_length);
  }
  
  /*
*************** geqo_selection(Chromosome *momma, Chromo
*** 78,84 ****
   *			 bias = (prob of first rule) / (prob of middle rule)
   */
  static int
! linear(int pool_size, double bias)		/* bias is y-intercept of linear
  										 * distribution */
  {
  	double		index;			/* index between 0 and pop_size */
--- 79,85 ----
   *			 bias = (prob of first rule) / (prob of middle rule)
   */
  static int
! linear(PlannerInfo *root, int pool_size, double bias)		/* bias is y-intercept of linear
  										 * distribution */
  {
  	double		index;			/* index between 0 and pop_size */
*************** linear(int pool_size, double bias)		/* b
*** 95,101 ****
  	{
  		double		sqrtval;
  
! 		sqrtval = (bias * bias) - 4.0 * (bias - 1.0) * geqo_rand();
  		if (sqrtval > 0.0)
  			sqrtval = sqrt(sqrtval);
  		index = max * (bias - sqrtval) / 2.0 / (bias - 1.0);
--- 96,102 ----
  	{
  		double		sqrtval;
  
! 		sqrtval = (bias * bias) - 4.0 * (bias - 1.0) * geqo_rand(root);
  		if (sqrtval > 0.0)
  			sqrtval = sqrt(sqrtval);
  		index = max * (bias - sqrtval) / 2.0 / (bias - 1.0);
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index b375902..777d75d 100644
*** a/src/backend/optimizer/path/allpaths.c
--- b/src/backend/optimizer/path/allpaths.c
*************** standard_join_search(PlannerInfo *root, 
*** 901,906 ****
--- 901,908 ----
  	int			lev;
  	RelOptInfo *rel;
  
+ 	Assert(root->join_search_private == 0);
+ 
  	/*
  	 * We employ a simple "dynamic programming" algorithm: we first find all
  	 * ways to build joins of two jointree items, then all ways to build joins
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 2430185..4126516 100644
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
*************** static struct config_real ConfigureNames
*** 2026,2031 ****
--- 2026,2040 ----
  		DEFAULT_GEQO_SELECTION_BIAS, MIN_GEQO_SELECTION_BIAS,
  		MAX_GEQO_SELECTION_BIAS, NULL, NULL
  	},
+ 	{
+ 		{"geqo_seed", PGC_USERSET, QUERY_TUNING_GEQO,
+ 			gettext_noop("GEQO: seed for random path selection for repeatable plan generation."),
+ 			gettext_noop("If zero planning will not be repeatable"),
+ 			GUC_NOT_IN_SAMPLE
+ 		},
+ 		&Geqo_seed,
+ 		0, 0, 1, NULL, NULL
+ 	},
  
  	{
  		{"bgwriter_lru_multiplier", PGC_SIGHUP, RESOURCES,
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index ea48889..8f82d71 100644
*** a/src/include/nodes/relation.h
--- b/src/include/nodes/relation.h
*************** typedef struct PlannerInfo
*** 192,197 ****
--- 192,200 ----
  	/* These fields are used only when hasRecursion is true: */
  	int			wt_param_id;	/* PARAM_EXEC ID for the work table */
  	struct Plan *non_recursive_plan;	/* plan for non-recursive term */
+ 
+ 	/* private data for join-order implementation, i.e. GEQO */
+ 	void		*join_search_private;
  } PlannerInfo;
  
  
diff --git a/src/include/optimizer/geqo.h b/src/include/optimizer/geqo.h
index ea4c812..7a9b6a4 100644
*** a/src/include/optimizer/geqo.h
--- b/src/include/optimizer/geqo.h
*************** extern int	Geqo_pool_size;		/* 2 .. inf,
*** 59,88 ****
  extern int	Geqo_generations;	/* 1 .. inf, or 0 to use default */
  
  extern double Geqo_selection_bias;
  
  #define DEFAULT_GEQO_SELECTION_BIAS 2.0
  #define MIN_GEQO_SELECTION_BIAS 1.5
  #define MAX_GEQO_SELECTION_BIAS 2.0
  
  
- /*
-  * Data structure to encapsulate information needed for building plan trees
-  * (i.e., geqo_eval and gimme_tree).
-  */
  typedef struct
  {
! 	PlannerInfo *root;			/* the query we are planning */
! 	List	   *initial_rels;	/* the base relations */
! } GeqoEvalData;
! 
  
  /* routines in geqo_main.c */
  extern RelOptInfo *geqo(PlannerInfo *root,
  	 int number_of_rels, List *initial_rels);
  
  /* routines in geqo_eval.c */
! extern Cost geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata);
! extern RelOptInfo *gimme_tree(Gene *tour, int num_gene,
! 		   GeqoEvalData *evaldata);
  
  #endif   /* GEQO_H */
--- 59,83 ----
  extern int	Geqo_generations;	/* 1 .. inf, or 0 to use default */
  
  extern double Geqo_selection_bias;
+ extern double Geqo_seed;
  
  #define DEFAULT_GEQO_SELECTION_BIAS 2.0
  #define MIN_GEQO_SELECTION_BIAS 1.5
  #define MAX_GEQO_SELECTION_BIAS 2.0
  
  
  typedef struct
  {
! 	List *initial_rels;
! 	unsigned short *random_state;
! } GeqoPrivateData;
  
  /* routines in geqo_main.c */
  extern RelOptInfo *geqo(PlannerInfo *root,
  	 int number_of_rels, List *initial_rels);
  
  /* routines in geqo_eval.c */
! extern Cost geqo_eval(PlannerInfo *root, Gene *tour, int num_geneo);
! extern RelOptInfo *gimme_tree(PlannerInfo *root, Gene *tour, int num_gene);
  
  #endif   /* GEQO_H */
diff --git a/src/include/optimizer/geqo_copy.h b/src/include/optimizer/geqo_copy.h
index ae13059..63b7c83 100644
*** a/src/include/optimizer/geqo_copy.h
--- b/src/include/optimizer/geqo_copy.h
***************
*** 22,29 ****
  #ifndef GEQO_COPY_H
  #define GEQO_COPY_H
  
  #include "optimizer/geqo_gene.h"
  
! extern void geqo_copy(Chromosome *chromo1, Chromosome *chromo2, int string_length);
  
  #endif   /* GEQO_COPY_H */
--- 22,30 ----
  #ifndef GEQO_COPY_H
  #define GEQO_COPY_H
  
+ #include "optimizer/geqo.h"
  #include "optimizer/geqo_gene.h"
  
! extern void geqo_copy(PlannerInfo *root, Chromosome *chromo1, Chromosome *chromo2, int string_length);
  
  #endif   /* GEQO_COPY_H */
diff --git a/src/include/optimizer/geqo_mutation.h b/src/include/optimizer/geqo_mutation.h
index 0384de8..3ada430 100644
*** a/src/include/optimizer/geqo_mutation.h
--- b/src/include/optimizer/geqo_mutation.h
***************
*** 22,29 ****
  #ifndef GEQO_MUTATION_H
  #define GEQO_MUTATION_H
  
  #include "optimizer/geqo_gene.h"
  
! extern void geqo_mutation(Gene *tour, int num_gene);
  
  #endif   /* GEQO_MUTATION_H */
--- 22,30 ----
  #ifndef GEQO_MUTATION_H
  #define GEQO_MUTATION_H
  
+ #include "optimizer/geqo.h"
  #include "optimizer/geqo_gene.h"
  
! extern void geqo_mutation(PlannerInfo *root, Gene *tour, int num_gene);
  
  #endif   /* GEQO_MUTATION_H */
diff --git a/src/include/optimizer/geqo_pool.h b/src/include/optimizer/geqo_pool.h
index 950e667..dbc6a01 100644
*** a/src/include/optimizer/geqo_pool.h
--- b/src/include/optimizer/geqo_pool.h
***************
*** 26,40 ****
  #include "optimizer/geqo.h"
  
  
! extern Pool *alloc_pool(int pool_size, int string_length);
! extern void free_pool(Pool *pool);
  
! extern void random_init_pool(Pool *pool, GeqoEvalData *evaldata);
! extern Chromosome *alloc_chromo(int string_length);
! extern void free_chromo(Chromosome *chromo);
  
! extern void spread_chromo(Chromosome *chromo, Pool *pool);
  
! extern void sort_pool(Pool *pool);
  
  #endif   /* GEQO_POOL_H */
--- 26,40 ----
  #include "optimizer/geqo.h"
  
  
! extern Pool *alloc_pool(PlannerInfo *root, int pool_size, int string_length);
! extern void free_pool(PlannerInfo *root, Pool *pool);
  
! extern void random_init_pool(PlannerInfo *root, Pool *pool);
! extern Chromosome *alloc_chromo(PlannerInfo *root, int string_length);
! extern void free_chromo(PlannerInfo *root, Chromosome *chromo);
  
! extern void spread_chromo(PlannerInfo *root, Chromosome *chromo, Pool *pool);
  
! extern void sort_pool(PlannerInfo *root, Pool *pool);
  
  #endif   /* GEQO_POOL_H */
diff --git a/src/include/optimizer/geqo_random.h b/src/include/optimizer/geqo_random.h
index fab0728..6fcfa7f 100644
*** a/src/include/optimizer/geqo_random.h
--- b/src/include/optimizer/geqo_random.h
***************
*** 27,38 ****
  #include <math.h>
  
  /* geqo_rand returns a random float value between 0 and 1 inclusive */
! 
! #define geqo_rand() ((double) random() / (double) MAX_RANDOM_VALUE)
  
  /* geqo_randint returns integer value between lower and upper inclusive */
! 
! #define geqo_randint(upper,lower) \
! 	( (int) floor( geqo_rand()*(((upper)-(lower))+0.999999) ) + (lower) )
  
  #endif   /* GEQO_RANDOM_H */
--- 27,37 ----
  #include <math.h>
  
  /* geqo_rand returns a random float value between 0 and 1 inclusive */
! double geqo_rand(PlannerInfo *root);
! void geqo_seed(PlannerInfo *root, double);
  
  /* geqo_randint returns integer value between lower and upper inclusive */
! #define geqo_randint(root, upper,lower)						\
! 	( (int) floor( geqo_rand(root)*(((upper)-(lower))+0.999999) ) + (lower) )
  
  #endif   /* GEQO_RANDOM_H */
diff --git a/src/include/optimizer/geqo_recombination.h b/src/include/optimizer/geqo_recombination.h
index 2c4a338..2484259 100644
*** a/src/include/optimizer/geqo_recombination.h
--- b/src/include/optimizer/geqo_recombination.h
***************
*** 24,32 ****
  #ifndef GEQO_RECOMBINATION_H
  #define GEQO_RECOMBINATION_H
  
  #include "optimizer/geqo_gene.h"
  
! extern void init_tour(Gene *tour, int num_gene);
  
  
  /* edge recombination crossover [ERX] */
--- 24,33 ----
  #ifndef GEQO_RECOMBINATION_H
  #define GEQO_RECOMBINATION_H
  
+ #include "optimizer/geqo.h"
  #include "optimizer/geqo_gene.h"
  
! extern void init_tour(PlannerInfo *root, Gene *tour, int num_gene);
  
  
  /* edge recombination crossover [ERX] */
*************** typedef struct Edge
*** 38,49 ****
  	int			unused_edges;
  } Edge;
  
! extern Edge *alloc_edge_table(int num_gene);
! extern void free_edge_table(Edge *edge_table);
  
! extern float gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table);
  
! extern int	gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene);
  
  
  /* partially matched crossover [PMX] */
--- 39,52 ----
  	int			unused_edges;
  } Edge;
  
! extern Edge *alloc_edge_table(PlannerInfo *root, int num_gene);
! extern void free_edge_table(PlannerInfo *root, Edge *edge_table);
  
! extern float gimme_edge_table(PlannerInfo *root, Gene *tour1, Gene *tour2,
! 							  int num_gene, Edge *edge_table);
  
! extern int	gimme_tour(PlannerInfo *root, Edge *edge_table, Gene *new_gene,
! 					   int num_gene);
  
  
  /* partially matched crossover [PMX] */
*************** extern int	gimme_tour(Edge *edge_table, 
*** 51,57 ****
  #define DAD 1					/* indicator for gene from dad */
  #define MOM 0					/* indicator for gene from mom */
  
! extern void pmx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene);
  
  
  typedef struct City
--- 54,62 ----
  #define DAD 1					/* indicator for gene from dad */
  #define MOM 0					/* indicator for gene from mom */
  
! extern void pmx(PlannerInfo *root,
! 				Gene *tour1, Gene *tour2,
! 				Gene *offspring, int num_gene);
  
  
  typedef struct City
*************** typedef struct City
*** 62,80 ****
  	int			select_list;
  } City;
  
! extern City *alloc_city_table(int num_gene);
! extern void free_city_table(City *city_table);
  
  /* cycle crossover [CX] */
! extern int	cx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table);
  
  /* position crossover [PX] */
! extern void px(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table);
  
  /* order crossover [OX1] according to Davis */
! extern void ox1(Gene *mom, Gene *dad, Gene *offspring, int num_gene, City *city_table);
  
  /* order crossover [OX2] according to Syswerda */
! extern void ox2(Gene *mom, Gene *dad, Gene *offspring, int num_gene, City *city_table);
  
  #endif   /* GEQO_RECOMBINATION_H */
--- 67,89 ----
  	int			select_list;
  } City;
  
! extern City *alloc_city_table(PlannerInfo *root, int num_gene);
! extern void free_city_table(PlannerInfo *root, City *city_table);
  
  /* cycle crossover [CX] */
! extern int	cx(PlannerInfo *root, Gene *tour1, Gene *tour2,
! 			   Gene *offspring, int num_gene, City *city_table);
  
  /* position crossover [PX] */
! extern void px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring,
! 			   int num_gene, City *city_table);
  
  /* order crossover [OX1] according to Davis */
! extern void ox1(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring,
! 				int num_gene, City *city_table);
  
  /* order crossover [OX2] according to Syswerda */
! extern void ox2(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring,
! 				int num_gene, City *city_table);
  
  #endif   /* GEQO_RECOMBINATION_H */
diff --git a/src/include/optimizer/geqo_selection.h b/src/include/optimizer/geqo_selection.h
index 4b336d1..7e93cb4 100644
*** a/src/include/optimizer/geqo_selection.h
--- b/src/include/optimizer/geqo_selection.h
***************
*** 25,30 ****
  
  #include "optimizer/geqo_gene.h"
  
! extern void geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias);
  
  #endif   /* GEQO_SELECTION_H */
--- 25,32 ----
  
  #include "optimizer/geqo_gene.h"
  
! extern void geqo_selection(PlannerInfo *root,
! 						   Chromosome *momma, Chromosome *daddy,
! 						   Pool *pool, double bias);
  
  #endif   /* GEQO_SELECTION_H */
-- 
1.6.3.3.335.ge09a8

