Commit a34fa8ee authored by Tom Lane's avatar Tom Lane

Initial code review for CustomScan patch.

Get rid of the pernicious entanglement between planner and executor headers
introduced by commit 0b03e595.

Also, rearrange the CustomFoo struct/typedef definitions so that all the
typedef names are seen as used by the compiler.  Without this pgindent
will mess things up a bit, which is not so important perhaps, but it also
removes a bizarre discrepancy between the declaration arrangement used for
CustomExecMethods and that used for CustomScanMethods and
CustomPathMethods.

Clean up the commentary around ExecSupportsMarkRestore to reflect the
rather large change in its API.

Const-ify register_custom_path_provider's argument.  This necessitates
casting away const in the function, but that seems better than forcing
callers of the function to do so (or else not const-ify their method
pointer structs, which was sort of the whole point).

De-export fix_expr_common.  I don't like the exporting of fix_scan_expr
or replace_nestloop_params either, but this one surely has got little
excuse.
parent 081a6048
...@@ -381,11 +381,14 @@ ExecRestrPos(PlanState *node) ...@@ -381,11 +381,14 @@ ExecRestrPos(PlanState *node)
} }
/* /*
* ExecSupportsMarkRestore - does a plan type support mark/restore? * ExecSupportsMarkRestore - does a Path support mark/restore?
*
* This is used during planning and so must accept a Path, not a Plan.
* We keep it here to be adjacent to the routines above, which also must
* know which plan types support mark/restore.
* *
* XXX Ideally, all plan node types would support mark/restore, and this * XXX Ideally, all plan node types would support mark/restore, and this
* wouldn't be needed. For now, this had better match the routines above. * wouldn't be needed. For now, this had better match the routines above.
* But note the test is on Plan nodetype, not PlanState nodetype.
* *
* (However, since the only present use of mark/restore is in mergejoin, * (However, since the only present use of mark/restore is in mergejoin,
* there is no need to support mark/restore in any plan type that is not * there is no need to support mark/restore in any plan type that is not
...@@ -395,6 +398,11 @@ ExecRestrPos(PlanState *node) ...@@ -395,6 +398,11 @@ ExecRestrPos(PlanState *node)
bool bool
ExecSupportsMarkRestore(Path *pathnode) ExecSupportsMarkRestore(Path *pathnode)
{ {
/*
* For consistency with the routines above, we do not examine the nodeTag
* but rather the pathtype, which is the Plan node type the Path would
* produce.
*/
switch (pathnode->pathtype) switch (pathnode->pathtype)
{ {
case T_SeqScan: case T_SeqScan:
...@@ -406,27 +414,23 @@ ExecSupportsMarkRestore(Path *pathnode) ...@@ -406,27 +414,23 @@ ExecSupportsMarkRestore(Path *pathnode)
case T_Sort: case T_Sort:
return true; return true;
case T_CustomScan:
Assert(IsA(pathnode, CustomPath));
if (((CustomPath *) pathnode)->flags & CUSTOMPATH_SUPPORT_MARK_RESTORE)
return true;
return false;
case T_Result: case T_Result:
/* /*
* T_Result only supports mark/restore if it has a child plan that * Although Result supports mark/restore if it has a child plan
* does, so we do not have enough information to give a really * that does, we presently come here only for ResultPath nodes,
* correct answer. However, for current uses it's enough to * which represent Result plans without a child plan. So there is
* always say "false", because this routine is not asked about * nothing to recurse to and we can just say "false".
* gating Result plans, only base-case Results.
*/ */
Assert(IsA(pathnode, ResultPath));
return false; return false;
case T_CustomScan:
{
CustomPath *cpath = (CustomPath *) pathnode;
Assert(IsA(cpath, CustomPath));
if (cpath->flags & CUSTOMPATH_SUPPORT_MARK_RESTORE)
return true;
}
break;
default: default:
break; break;
} }
...@@ -491,10 +495,10 @@ ExecSupportsBackwardScan(Plan *node) ...@@ -491,10 +495,10 @@ ExecSupportsBackwardScan(Plan *node)
case T_CustomScan: case T_CustomScan:
{ {
uint32 flags = ((CustomScan *) node)->flags; uint32 flags = ((CustomScan *) node)->flags;
if (TargetListSupportsBackwardScan(node->targetlist) && if ((flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN) &&
(flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN) != 0) TargetListSupportsBackwardScan(node->targetlist))
return true; return true;
} }
return false; return false;
......
...@@ -78,8 +78,8 @@ static WorkTableScan *create_worktablescan_plan(PlannerInfo *root, Path *best_pa ...@@ -78,8 +78,8 @@ static WorkTableScan *create_worktablescan_plan(PlannerInfo *root, Path *best_pa
static ForeignScan *create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path, static ForeignScan *create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
List *tlist, List *scan_clauses); List *tlist, List *scan_clauses);
static Plan *create_customscan_plan(PlannerInfo *root, static Plan *create_customscan_plan(PlannerInfo *root,
CustomPath *best_path, CustomPath *best_path,
List *tlist, List *scan_clauses); List *tlist, List *scan_clauses);
static NestLoop *create_nestloop_plan(PlannerInfo *root, NestPath *best_path, static NestLoop *create_nestloop_plan(PlannerInfo *root, NestPath *best_path,
Plan *outer_plan, Plan *inner_plan); Plan *outer_plan, Plan *inner_plan);
static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path, static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path,
...@@ -1083,52 +1083,6 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path) ...@@ -1083,52 +1083,6 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path)
return plan; return plan;
} }
/*
* create_custom_plan
*
* Transform a CustomPath into a Plan.
*/
static Plan *
create_customscan_plan(PlannerInfo *root, CustomPath *best_path,
List *tlist, List *scan_clauses)
{
Plan *plan;
RelOptInfo *rel = best_path->path.parent;
/*
* Right now, all we can support is CustomScan node which is associated
* with a particular base relation to be scanned.
*/
Assert(rel && rel->reloptkind == RELOPT_BASEREL);
/*
* Sort clauses into the best execution order, although custom-scan
* provider can reorder them again.
*/
scan_clauses = order_qual_clauses(root, scan_clauses);
/*
* Create a CustomScan (or its inheritance) node according to
* the supplied CustomPath.
*/
plan = best_path->methods->PlanCustomPath(root, rel, best_path, tlist,
scan_clauses);
/*
* NOTE: unlike create_foreignscan_plan(), it is responsibility of
* the custom plan provider to replace outer-relation variables
* with nestloop params, because we cannot know how many expression
* trees are held in the private fields.
*/
/*
* Copy cost data from Path to Plan; no need to make custom-plan
* providers do this
*/
copy_path_costsize(plan, &best_path->path);
return plan;
}
/***************************************************************************** /*****************************************************************************
* *
...@@ -2063,6 +2017,53 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path, ...@@ -2063,6 +2017,53 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
return scan_plan; return scan_plan;
} }
/*
* create_custom_plan
*
* Transform a CustomPath into a Plan.
*/
static Plan *
create_customscan_plan(PlannerInfo *root, CustomPath *best_path,
List *tlist, List *scan_clauses)
{
Plan *plan;
RelOptInfo *rel = best_path->path.parent;
/*
* Right now, all we can support is CustomScan node which is associated
* with a particular base relation to be scanned.
*/
Assert(rel && rel->reloptkind == RELOPT_BASEREL);
/*
* Sort clauses into the best execution order, although custom-scan
* provider can reorder them again.
*/
scan_clauses = order_qual_clauses(root, scan_clauses);
/*
* Invoke custom plan provider to create the Plan node represented by the
* CustomPath.
*/
plan = best_path->methods->PlanCustomPath(root, rel, best_path, tlist,
scan_clauses);
/*
* NOTE: unlike create_foreignscan_plan(), it is the responsibility of the
* custom plan provider to replace outer-relation variables with nestloop
* params, because we cannot know what expression trees may be held in
* private fields.
*/
/*
* Copy cost data from Path to Plan; no need to make custom-plan providers
* do this
*/
copy_path_costsize(plan, &best_path->path);
return plan;
}
/***************************************************************************** /*****************************************************************************
* *
......
...@@ -587,12 +587,13 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) ...@@ -587,12 +587,13 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
fix_scan_list(root, cscan->scan.plan.targetlist, rtoffset); fix_scan_list(root, cscan->scan.plan.targetlist, rtoffset);
cscan->scan.plan.qual = cscan->scan.plan.qual =
fix_scan_list(root, cscan->scan.plan.qual, rtoffset); fix_scan_list(root, cscan->scan.plan.qual, rtoffset);
/* /*
* The core implementation applies the routine to fixup * The core implementation applies the routine to fixup varno
* varno on the target-list and scan qualifier. * on the target-list and scan qualifier. If custom-scan has
* If custom-scan has additional expression nodes on its * additional expression nodes on its private fields, it has
* private fields, it has to apply same fixup on them. * to apply same fixup on them. Otherwise, the custom-plan
* Otherwise, the custom-plan provider can skip this callback. * provider can skip this callback.
*/ */
if (cscan->methods->SetCustomScanRef) if (cscan->methods->SetCustomScanRef)
cscan->methods->SetCustomScanRef(root, cscan, rtoffset); cscan->methods->SetCustomScanRef(root, cscan, rtoffset);
...@@ -1083,7 +1084,7 @@ copyVar(Var *var) ...@@ -1083,7 +1084,7 @@ copyVar(Var *var)
* We assume it's okay to update opcode info in-place. So this could possibly * We assume it's okay to update opcode info in-place. So this could possibly
* scribble on the planner's input data structures, but it's OK. * scribble on the planner's input data structures, but it's OK.
*/ */
void static void
fix_expr_common(PlannerInfo *root, Node *node) fix_expr_common(PlannerInfo *root, Node *node)
{ {
/* We assume callers won't call us on a NULL pointer */ /* We assume callers won't call us on a NULL pointer */
......
...@@ -1929,10 +1929,10 @@ reparameterize_path(PlannerInfo *root, Path *path, ...@@ -1929,10 +1929,10 @@ reparameterize_path(PlannerInfo *root, Path *path,
} }
/***************************************************************************** /*****************************************************************************
* creation of custom-plan paths * creation of custom-plan paths
*****************************************************************************/ *****************************************************************************/
static List *custom_path_providers = NIL; static List *custom_path_providers = NIL;
/* /*
* register_custom_path_provider * register_custom_path_provider
...@@ -1942,12 +1942,13 @@ static List *custom_path_providers = NIL; ...@@ -1942,12 +1942,13 @@ static List *custom_path_providers = NIL;
* methods of scanning a relation. * methods of scanning a relation.
*/ */
void void
register_custom_path_provider(CustomPathMethods *cpp_methods) register_custom_path_provider(const CustomPathMethods *cpp_methods)
{ {
MemoryContext oldcxt; MemoryContext oldcxt;
oldcxt = MemoryContextSwitchTo(TopMemoryContext); oldcxt = MemoryContextSwitchTo(TopMemoryContext);
custom_path_providers = lappend(custom_path_providers, cpp_methods); custom_path_providers = lappend(custom_path_providers,
(void *) cpp_methods);
MemoryContextSwitchTo(oldcxt); MemoryContextSwitchTo(oldcxt);
} }
...@@ -1963,9 +1964,9 @@ create_customscan_paths(PlannerInfo *root, ...@@ -1963,9 +1964,9 @@ create_customscan_paths(PlannerInfo *root,
RelOptInfo *baserel, RelOptInfo *baserel,
RangeTblEntry *rte) RangeTblEntry *rte)
{ {
ListCell *cell; ListCell *cell;
foreach (cell, custom_path_providers) foreach(cell, custom_path_providers)
{ {
const CustomPathMethods *cpp_methods = lfirst(cell); const CustomPathMethods *cpp_methods = lfirst(cell);
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "executor/execdesc.h" #include "executor/execdesc.h"
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "nodes/relation.h"
#include "utils/lockwaitpolicy.h" #include "utils/lockwaitpolicy.h"
...@@ -101,10 +100,12 @@ extern PGDLLIMPORT ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook; ...@@ -101,10 +100,12 @@ extern PGDLLIMPORT ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook;
/* /*
* prototypes from functions in execAmi.c * prototypes from functions in execAmi.c
*/ */
struct Path; /* avoid including relation.h here */
extern void ExecReScan(PlanState *node); extern void ExecReScan(PlanState *node);
extern void ExecMarkPos(PlanState *node); extern void ExecMarkPos(PlanState *node);
extern void ExecRestrPos(PlanState *node); extern void ExecRestrPos(PlanState *node);
extern bool ExecSupportsMarkRestore(Path *pathnode); extern bool ExecSupportsMarkRestore(struct Path *pathnode);
extern bool ExecSupportsBackwardScan(Plan *node); extern bool ExecSupportsBackwardScan(Plan *node);
extern bool ExecMaterializesOutput(NodeTag plantype); extern bool ExecMaterializesOutput(NodeTag plantype);
......
...@@ -11,14 +11,14 @@ ...@@ -11,14 +11,14 @@
*/ */
#ifndef NODECUSTOM_H #ifndef NODECUSTOM_H
#define NODECUSTOM_H #define NODECUSTOM_H
#include "nodes/plannodes.h"
#include "nodes/execnodes.h" #include "nodes/execnodes.h"
/* /*
* General executor code * General executor code
*/ */
extern CustomScanState *ExecInitCustomScan(CustomScan *custom_scan, extern CustomScanState *ExecInitCustomScan(CustomScan *custom_scan,
EState *estate, int eflags); EState *estate, int eflags);
extern TupleTableSlot *ExecCustomScan(CustomScanState *node); extern TupleTableSlot *ExecCustomScan(CustomScanState *node);
extern Node *MultiExecCustomScan(CustomScanState *node); extern Node *MultiExecCustomScan(CustomScanState *node);
extern void ExecEndCustomScan(CustomScanState *node); extern void ExecEndCustomScan(CustomScanState *node);
...@@ -27,4 +27,4 @@ extern void ExecReScanCustomScan(CustomScanState *node); ...@@ -27,4 +27,4 @@ extern void ExecReScanCustomScan(CustomScanState *node);
extern void ExecCustomMarkPos(CustomScanState *node); extern void ExecCustomMarkPos(CustomScanState *node);
extern void ExecCustomRestrPos(CustomScanState *node); extern void ExecCustomRestrPos(CustomScanState *node);
#endif /* NODECUSTOM_H */ #endif /* NODECUSTOM_H */
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include "executor/instrument.h" #include "executor/instrument.h"
#include "nodes/params.h" #include "nodes/params.h"
#include "nodes/plannodes.h" #include "nodes/plannodes.h"
#include "nodes/relation.h"
#include "utils/reltrigger.h" #include "utils/reltrigger.h"
#include "utils/sortsupport.h" #include "utils/sortsupport.h"
#include "utils/tuplestore.h" #include "utils/tuplestore.h"
...@@ -1512,39 +1511,39 @@ typedef struct ForeignScanState ...@@ -1512,39 +1511,39 @@ typedef struct ForeignScanState
* CustomScan nodes are used to execute custom code within executor. * CustomScan nodes are used to execute custom code within executor.
* ---------------- * ----------------
*/ */
struct CustomExecMethods; struct ExplainState; /* avoid including explain.h here */
struct ExplainState; /* to avoid to include explain.h here */ struct CustomScanState;
typedef struct CustomScanState
{
ScanState ss;
uint32 flags; /* mask of CUSTOMPATH_* flags defined in relation.h*/
const struct CustomExecMethods *methods;
} CustomScanState;
typedef struct CustomExecMethods typedef struct CustomExecMethods
{ {
const char *CustomName; const char *CustomName;
/* EXECUTOR methods */ /* EXECUTOR methods */
void (*BeginCustomScan)(CustomScanState *node, void (*BeginCustomScan) (struct CustomScanState *node,
EState *estate, EState *estate,
int eflags); int eflags);
TupleTableSlot *(*ExecCustomScan)(CustomScanState *node); TupleTableSlot *(*ExecCustomScan) (struct CustomScanState *node);
void (*EndCustomScan)(CustomScanState *node); void (*EndCustomScan) (struct CustomScanState *node);
void (*ReScanCustomScan)(CustomScanState *node); void (*ReScanCustomScan) (struct CustomScanState *node);
void (*MarkPosCustomScan)(CustomScanState *node); void (*MarkPosCustomScan) (struct CustomScanState *node);
void (*RestrPosCustomScan)(CustomScanState *node); void (*RestrPosCustomScan) (struct CustomScanState *node);
/* EXPLAIN support */ /* EXPLAIN support */
void (*ExplainCustomScan)(CustomScanState *node, void (*ExplainCustomScan) (struct CustomScanState *node,
List *ancestors, List *ancestors,
struct ExplainState *es); struct ExplainState *es);
Node *(*GetSpecialCustomVar)(CustomScanState *node, Node *(*GetSpecialCustomVar) (struct CustomScanState *node,
Var *varnode, Var *varnode,
PlanState **child_ps); PlanState **child_ps);
} CustomExecMethods; } CustomExecMethods;
typedef struct CustomScanState
{
ScanState ss;
uint32 flags; /* mask of CUSTOMPATH_* flags, see relation.h */
const CustomExecMethods *methods;
} CustomScanState;
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* Join State Information * Join State Information
* ---------------------------------------------------------------- * ----------------------------------------------------------------
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "lib/stringinfo.h" #include "lib/stringinfo.h"
#include "nodes/bitmapset.h" #include "nodes/bitmapset.h"
#include "nodes/primnodes.h" #include "nodes/primnodes.h"
#include "nodes/relation.h"
#include "utils/lockwaitpolicy.h" #include "utils/lockwaitpolicy.h"
...@@ -486,33 +485,36 @@ typedef struct ForeignScan ...@@ -486,33 +485,36 @@ typedef struct ForeignScan
} ForeignScan; } ForeignScan;
/* ---------------- /* ----------------
* CustomScan node * CustomScan node
* ---------------- * ----------------
*/ */
struct CustomScanMethods; struct PlannerInfo; /* avoid including relation.h here */
struct CustomScan;
typedef struct CustomScan
{
Scan scan;
uint32 flags; /* mask of CUSTOMPATH_* flags defined in relation.h */
struct CustomScanMethods *methods;
} CustomScan;
typedef struct CustomScanMethods typedef struct CustomScanMethods
{ {
const char *CustomName; const char *CustomName;
void (*SetCustomScanRef)(struct PlannerInfo *root,
CustomScan *cscan, void (*SetCustomScanRef) (struct PlannerInfo *root,
int rtoffset); struct CustomScan *cscan,
void (*FinalizeCustomScan)(struct PlannerInfo *root, int rtoffset);
CustomScan *cscan, void (*FinalizeCustomScan) (struct PlannerInfo *root,
bool (*finalize_primnode)(), struct CustomScan *cscan,
void *finalize_context); bool (*finalize_primnode) (),
Node *(*CreateCustomScanState)(CustomScan *cscan); void *finalize_context);
void (*TextOutCustomScan)(StringInfo str, const CustomScan *node); Node *(*CreateCustomScanState) (struct CustomScan *cscan);
CustomScan *(*CopyCustomScan)(const CustomScan *from); void (*TextOutCustomScan) (StringInfo str,
const struct CustomScan *node);
struct CustomScan *(*CopyCustomScan) (const struct CustomScan *from);
} CustomScanMethods; } CustomScanMethods;
typedef struct CustomScan
{
Scan scan;
uint32 flags; /* mask of CUSTOMPATH_* flags, see relation.h */
const CustomScanMethods *methods;
} CustomScan;
/* /*
* ========== * ==========
* Join nodes * Join nodes
...@@ -864,7 +866,7 @@ typedef struct PlanRowMark ...@@ -864,7 +866,7 @@ typedef struct PlanRowMark
Index prti; /* range table index of parent relation */ Index prti; /* range table index of parent relation */
Index rowmarkId; /* unique identifier for resjunk columns */ Index rowmarkId; /* unique identifier for resjunk columns */
RowMarkType markType; /* see enum above */ RowMarkType markType; /* see enum above */
LockWaitPolicy waitPolicy; /* NOWAIT and SKIP LOCKED options */ LockWaitPolicy waitPolicy; /* NOWAIT and SKIP LOCKED options */
bool isParent; /* true if this is a "dummy" parent entry */ bool isParent; /* true if this is a "dummy" parent entry */
} PlanRowMark; } PlanRowMark;
......
...@@ -897,34 +897,34 @@ typedef struct ForeignPath ...@@ -897,34 +897,34 @@ typedef struct ForeignPath
* the structure declared here; providers are expected to make it the first * the structure declared here; providers are expected to make it the first
* element in a larger structure. * element in a larger structure.
*/ */
struct CustomPath;
struct CustomPathMethods;
struct Plan; /* not to include plannodes.h here */
#define CUSTOMPATH_SUPPORT_BACKWARD_SCAN 0x0001 #define CUSTOMPATH_SUPPORT_BACKWARD_SCAN 0x0001
#define CUSTOMPATH_SUPPORT_MARK_RESTORE 0x0002 #define CUSTOMPATH_SUPPORT_MARK_RESTORE 0x0002
typedef struct CustomPath
{
Path path;
uint32 flags;
const struct CustomPathMethods *methods;
} CustomPath;
typedef struct CustomPathMethods typedef struct CustomPathMethods
{ {
const char *CustomName; const char *CustomName;
void (*CreateCustomScanPath)(PlannerInfo *root,
RelOptInfo *baserel, void (*CreateCustomScanPath) (PlannerInfo *root,
RangeTblEntry *rte); RelOptInfo *baserel,
struct Plan *(*PlanCustomPath)(PlannerInfo *root, RangeTblEntry *rte);
RelOptInfo *rel, struct Plan *(*PlanCustomPath) (PlannerInfo *root,
CustomPath *best_path, RelOptInfo *rel,
List *tlist, struct CustomPath *best_path,
List *clauses); List *tlist,
void (*TextOutCustomPath)(StringInfo str, const CustomPath *node); List *clauses);
void (*TextOutCustomPath) (StringInfo str,
const struct CustomPath *node);
} CustomPathMethods; } CustomPathMethods;
typedef struct CustomPath
{
Path path;
uint32 flags; /* mask of CUSTOMPATH_* flags, see above */
const CustomPathMethods *methods;
} CustomPath;
/* /*
* AppendPath represents an Append plan, ie, successive execution of * AppendPath represents an Append plan, ie, successive execution of
* several member plans. * several member plans.
......
...@@ -131,11 +131,11 @@ extern Path *reparameterize_path(PlannerInfo *root, Path *path, ...@@ -131,11 +131,11 @@ extern Path *reparameterize_path(PlannerInfo *root, Path *path,
/* /*
* Interface definition of custom-scan providers * Interface definition of custom-scan providers
*/ */
extern void register_custom_path_provider(CustomPathMethods *cpp_methods); extern void register_custom_path_provider(const CustomPathMethods *cpp_methods);
extern void create_customscan_paths(PlannerInfo *root, extern void create_customscan_paths(PlannerInfo *root,
RelOptInfo *baserel, RelOptInfo *baserel,
RangeTblEntry *rte); RangeTblEntry *rte);
/* /*
* prototypes for relnode.c * prototypes for relnode.c
......
...@@ -130,9 +130,8 @@ extern bool query_is_distinct_for(Query *query, List *colnos, List *opids); ...@@ -130,9 +130,8 @@ extern bool query_is_distinct_for(Query *query, List *colnos, List *opids);
* prototypes for plan/setrefs.c * prototypes for plan/setrefs.c
*/ */
extern Plan *set_plan_references(PlannerInfo *root, Plan *plan); extern Plan *set_plan_references(PlannerInfo *root, Plan *plan);
extern void fix_opfuncids(Node *node);
extern Node *fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset); extern Node *fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset);
extern void fix_expr_common(PlannerInfo *root, Node *node); extern void fix_opfuncids(Node *node);
extern void set_opfuncid(OpExpr *opexpr); extern void set_opfuncid(OpExpr *opexpr);
extern void set_sa_opfuncid(ScalarArrayOpExpr *opexpr); extern void set_sa_opfuncid(ScalarArrayOpExpr *opexpr);
extern void record_plan_function_dependency(PlannerInfo *root, Oid funcid); extern void record_plan_function_dependency(PlannerInfo *root, Oid funcid);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment