I rewrote a patch a bit.
I made function make_one_rel_by_joins also non-static,
so that the optimizer in plugin can reuse the dynamic
optimizer.
I also reorganized the code and put all the changes
to paths.h and allpaths.c files only. It seems to me more
appropriate that the hook should belong to this place only.
Thanks
Julo
Julius Stroffek wrote:
Attached is the patch for the optimizer hook as discussed in
http://archives.postgresql.org/pgsql-hackers/2007-08/msg00362.php
The hook declaration and definition to the same places as the planner_hook
is located since the optimizer_hook relates to the part of the planner and
I find it good to have the planner related hooks on one place.
The optimizer_hook is called in make_one_rel and the plugin replaces
the function 'make_rel_from_joinlist'. I have created a macro
standard_optimizer just for better readability of the code in plugins
and I did not want to change function names.
I also tried to dig out the dynamic programming optimizer and to compile
it and use it as a plugin just to be sure that all the functions necessary
to write the optimizer as a plugin are non-static. I placed all the code
in joinrels.c, make_one_rel_by_joins and make_rel_from_joinlist functions.
Of cause, I renamed all non-static symbols.
Sure, I ran 'make check' without failures.
Is there anything else I should take care? Thanks.
Regards
Julo Stroffek
------------------------------------------------------------------------
*** ./src/backend/optimizer/path/allpaths.c.orig Sat May 26 20:23:01 2007
--- ./src/backend/optimizer/path/allpaths.c Tue Aug 14 17:26:39 2007
***************
*** 52,58 ****
RangeTblEntry *rte);
static void set_values_pathlist(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *rte);
! static RelOptInfo *make_rel_from_joinlist(PlannerInfo *root, List *joinlist);
static RelOptInfo *make_one_rel_by_joins(PlannerInfo *root, int levels_needed,
List *initial_rels);
static bool subquery_is_pushdown_safe(Query *subquery, Query *topquery,
--- 52,58 ----
RangeTblEntry *rte);
static void set_values_pathlist(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *rte);
! RelOptInfo *make_rel_from_joinlist(PlannerInfo *root, List *joinlist);
static RelOptInfo *make_one_rel_by_joins(PlannerInfo *root, int levels_needed,
List *initial_rels);
static bool subquery_is_pushdown_safe(Query *subquery, Query *topquery,
***************
*** 87,93 ****
/*
* Generate access paths for the entire join tree.
*/
! rel = make_rel_from_joinlist(root, joinlist);
/*
* The result should join all and only the query's base rels.
--- 87,96 ----
/*
* Generate access paths for the entire join tree.
*/
! if (optimizer_hook)
! rel = optimizer_hook(root, joinlist);
! else
! rel = make_rel_from_joinlist(root, joinlist);
/*
* The result should join all and only the query's base rels.
***************
*** 612,618 ****
* See comments for deconstruct_jointree() for definition of the joinlist
* data structure.
*/
! static RelOptInfo *
make_rel_from_joinlist(PlannerInfo *root, List *joinlist)
{
int levels_needed;
--- 615,621 ----
* See comments for deconstruct_jointree() for definition of the joinlist
* data structure.
*/
! RelOptInfo *
make_rel_from_joinlist(PlannerInfo *root, List *joinlist)
{
int levels_needed;
*** ./src/backend/optimizer/plan/planner.c.orig Sat May 26 20:23:01 2007
--- ./src/backend/optimizer/plan/planner.c Wed Aug 15 15:31:21 2007
***************
*** 45,50 ****
--- 45,52 ----
/* Hook for plugins to get control in planner() */
planner_hook_type planner_hook = NULL;
+ /* Hook for plugins to get control in make_one_rel() */
+ optimizer_hook_type optimizer_hook = NULL;
/* Expression kind codes for preprocess_expression */
#define EXPRKIND_QUAL 0
*** ./src/include/optimizer/planner.h.orig Wed Jul 25 14:22:53 2007
--- ./src/include/optimizer/planner.h Wed Aug 15 11:17:00 2007
***************
*** 17,22 ****
--- 17,24 ----
#include "nodes/plannodes.h"
#include "nodes/relation.h"
+ /* A macro pointing to the standard optimizer function. */
+ #define standard_optimizer make_rel_from_joinlist
/* Hook for plugins to get control in planner() */
typedef PlannedStmt * (*planner_hook_type) (Query *parse,
***************
*** 24,29 ****
--- 26,35 ----
ParamListInfo boundParams);
extern PGDLLIMPORT planner_hook_type planner_hook;
+ /* Hook for plugins to get control in make_one_rel() */
+ typedef RelOptInfo * (*optimizer_hook_type) (PlannerInfo * root,
+
List * joinlist);
+ extern PGDLLIMPORT optimizer_hook_type optimizer_hook;
extern PlannedStmt *planner(Query *parse, int cursorOptions,
ParamListInfo boundParams);
------------------------------------------------------------------------
---------------------------(end of broadcast)---------------------------
TIP 4: Have you searched our list archives?
http://archives.postgresql.org
*** ./src/backend/optimizer/path/allpaths.c.orig Sat May 26 20:23:01 2007
--- ./src/backend/optimizer/path/allpaths.c Thu Aug 23 15:29:28 2007
***************
*** 37,43 ****
--- 37,45 ----
bool enable_geqo = false; /* just in case GUC doesn't set it */
int geqo_threshold;
+ optimizer_hook_type optimizer_hook = NULL;
+
static void set_base_rel_pathlists(PlannerInfo *root);
static void set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
Index rti, RangeTblEntry *rte);
***************
*** 52,60 ****
RangeTblEntry *rte);
static void set_values_pathlist(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *rte);
- static RelOptInfo *make_rel_from_joinlist(PlannerInfo *root, List *joinlist);
- static RelOptInfo *make_one_rel_by_joins(PlannerInfo *root, int levels_needed,
- List *initial_rels);
static bool subquery_is_pushdown_safe(Query *subquery, Query *topquery,
bool *differentTypes);
static bool recurse_pushdown_safe(Node *setOp, Query *topquery,
--- 54,59 ----
***************
*** 87,93 ****
/*
* Generate access paths for the entire join tree.
*/
! rel = make_rel_from_joinlist(root, joinlist);
/*
* The result should join all and only the query's base rels.
--- 86,95 ----
/*
* Generate access paths for the entire join tree.
*/
! if (optimizer_hook)
! rel = optimizer_hook(root, joinlist);
! else
! rel = make_rel_from_joinlist(root, joinlist);
/*
* The result should join all and only the query's base rels.
***************
*** 612,618 ****
* See comments for deconstruct_jointree() for definition of the joinlist
* data structure.
*/
! static RelOptInfo *
make_rel_from_joinlist(PlannerInfo *root, List *joinlist)
{
int levels_needed;
--- 614,620 ----
* See comments for deconstruct_jointree() for definition of the joinlist
* data structure.
*/
! RelOptInfo *
make_rel_from_joinlist(PlannerInfo *root, List *joinlist)
{
int levels_needed;
***************
*** 695,701 ****
* Returns the final level of join relations, i.e., the relation that is
* the result of joining all the original relations together.
*/
! static RelOptInfo *
make_one_rel_by_joins(PlannerInfo *root, int levels_needed, List *initial_rels)
{
List **joinitems;
--- 697,703 ----
* Returns the final level of join relations, i.e., the relation that is
* the result of joining all the original relations together.
*/
! RelOptInfo *
make_one_rel_by_joins(PlannerInfo *root, int levels_needed, List *initial_rels)
{
List **joinitems;
*** ./src/include/optimizer/paths.h.orig Tue May 22 03:40:33 2007
--- ./src/include/optimizer/paths.h Thu Aug 23 15:20:56 2007
***************
*** 23,30 ****
extern bool enable_geqo;
extern int geqo_threshold;
! extern RelOptInfo *make_one_rel(PlannerInfo *root, List *joinlist);
#ifdef OPTIMIZER_DEBUG
extern void debug_print_rel(PlannerInfo *root, RelOptInfo *rel);
#endif
--- 23,46 ----
extern bool enable_geqo;
extern int geqo_threshold;
! /* A macro pointing to the standard optimizer function. */
! #define standard_optimizer make_rel_from joinlist
+ /* Hook for plugins to get control in make_one_rel() */
+ typedef RelOptInfo * (*optimizer_hook_type) (PlannerInfo * root,
+ List * joinlist);
+ extern PGDLLIMPORT optimizer_hook_type optimizer_hook;
+
+ /*
+ * Functions related to searching the space
+ * of all possible join orders.
+ */
+ extern RelOptInfo *make_one_rel(PlannerInfo *root, List *joinlist);
+ extern RelOptInfo *make_rel_from_joinlist(PlannerInfo *root,
+ List *joinlist);
+ extern RelOptInfo *make_one_rel_by_joins(PlannerInfo *root,
+ int levels_needed,
+ List *initial_rels);
#ifdef OPTIMIZER_DEBUG
extern void debug_print_rel(PlannerInfo *root, RelOptInfo *rel);
#endif
---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?
http://www.postgresql.org/docs/faq