
#include "postgres.h"

#include "fmgr.h"
#include "optimizer/geqo.h"
#include "optimizer/paths.h"
#include "optimizer/pathnode.h"


PG_MODULE_MAGIC;

void	_PG_init(void);
void	_PG_fini(void);

typedef RelOptInfo * (*jos_function_type) (PlannerInfo *root, int levels_needed, List* initial_rels);

static
RelOptInfo *
jos_search(PlannerInfo *root, List *joinlist, jos_function_type jos_function)
{
     int         levels_needed;
     List       *initial_rels;
     ListCell   *jl;
 
     /*
      * Count the number of child joinlist nodes.  This is the depth of the
      * dynamic-programming algorithm we must employ to consider all ways of
      * joining the child nodes.
      */
     levels_needed = list_length(joinlist);
 
     if (levels_needed <= 0)
         return NULL;            /* nothing to do? */
 
     /*
      * Construct a list of rels corresponding to the child joinlist nodes.
      * This may contain both base rels and rels constructed according to
      * sub-joinlists.
      */
     initial_rels = NIL;
     foreach(jl, joinlist)
     {
         Node       *jlnode = (Node *) lfirst(jl);
         RelOptInfo *thisrel;
 
         if (IsA(jlnode, RangeTblRef))
         {
             int         varno = ((RangeTblRef *) jlnode)->rtindex;
 
             thisrel = find_base_rel(root, varno);
         }
         else if (IsA(jlnode, List))
         {
             /* Recurse to handle subproblem */
             thisrel = jos_search(root, (List *) jlnode, jos_function);
         }
         else
         {
             elog(ERROR, "unrecognized joinlist node type: %d",
                  (int) nodeTag(jlnode));
             thisrel = NULL;     /* keep compiler quiet */
         }
 
         initial_rels = lappend(initial_rels, thisrel);
     }
 
     if (levels_needed == 1)
     {
         /*
          * Single joinlist node, so we're done.
          */
         return (RelOptInfo *) linitial(initial_rels);
     }
     else
     {
         jos_function(root, levels_needed, initial_rels);
     }
}


static
RelOptInfo *
jos_dummy(PlannerInfo *root, List *joinlist)
{
	RelOptInfo *dynamic_result, *geqo_result;
	List *copy;
	Cost dynamic_cost, geqo_cost;

	copy = list_copy(joinlist);
	elog(LOG, "Starting a join order search \"geqo\"...");
	geqo_result = jos_search(root, copy, geqo);
//	geqo_result = jos_search(root, copy, make_one_rel_by_joins);
	geqo_cost = geqo_result->cheapest_total_path->total_cost;

	copy = list_copy(joinlist);
	elog(LOG, "Starting a join order search \"dynamic\"...");
	dynamic_result = jos_search(root, copy, make_one_rel_by_joins);
//	dynamic_result = jos_search(root, copy, geqo);
	dynamic_cost = dynamic_result->cheapest_total_path->total_cost;


	printf("GEQO cost: %f\n", geqo_cost);
	printf("Dynamic programming cost: %f\n", dynamic_cost);
	
	if (geqo_cost < dynamic_cost)
		return geqo_result;
	else
		return dynamic_result;
}


void
_PG_init(void)
{
	join_order_search_hook = jos_dummy;
}

void
_PG_fini(void)
{
	join_order_search_hook = 0;
}

