As committed, gen_node_support.pl excludes CallContext and InlineCodeBlock from getting unneeded support functions via some very ad-hoc code. (Right now, there are some other node types that are handled similarly, but I'm looking to drive that set to empty.) After looking at the situation a bit, I think the problem is that these nodes are declared in parsenodes.h even though they have exactly nothing to do with parse trees. What they are is function-calling API infrastructure, so it seems like the most natural home for them is fmgr.h. A weaker case could be made for funcapi.h, perhaps.
So I tried moving them to fmgr.h, and it blew up because they need typedef NodeTag while fmgr.h does not #include nodes.h. I feel that the most reasonable approach is to just give up on that bit of micro-optimization and let fmgr.h include nodes.h. It was already doing a bit of hackery to compile "Node *" references without that inclusion, so this seems more clean not less so. Hence, I propose the attached. (The changes in the PL files are just to align them on a common best practice for an InlineCodeBlock argument.) regards, tom lane
diff --git a/src/backend/nodes/Makefile b/src/backend/nodes/Makefile index 79ce0a532f..03c488304e 100644 --- a/src/backend/nodes/Makefile +++ b/src/backend/nodes/Makefile @@ -43,6 +43,7 @@ node_headers = \ nodes/parsenodes.h \ nodes/replnodes.h \ nodes/value.h \ + fmgr.h \ commands/trigger.h \ commands/event_trigger.h \ foreign/fdwapi.h \ diff --git a/src/backend/nodes/gen_node_support.pl b/src/backend/nodes/gen_node_support.pl index 4a7902e6bf..eef2deb2d8 100644 --- a/src/backend/nodes/gen_node_support.pl +++ b/src/backend/nodes/gen_node_support.pl @@ -97,10 +97,8 @@ push @scalar_types, qw(QualCost); # XXX various things we are not publishing right now to stay level # with the manual system -push @no_copy, qw(CallContext InlineCodeBlock); -push @no_equal, qw(CallContext InlineCodeBlock); push @no_read_write, - qw(AccessPriv AlterTableCmd CallContext CreateOpClassItem FunctionParameter InferClause InlineCodeBlock ObjectWithArgs OnConflictClause PartitionCmd RoleSpec VacuumRelation); + qw(AccessPriv AlterTableCmd CreateOpClassItem FunctionParameter InferClause ObjectWithArgs OnConflictClause PartitionCmd RoleSpec VacuumRelation); push @no_read, qw(A_ArrayExpr A_Indices A_Indirection AlterStatsStmt CollateClause ColumnDef ColumnRef CreateForeignTableStmt CreateStatsStmt CreateStmt FuncCall ImportForeignSchemaStmt IndexElem IndexStmt @@ -298,7 +296,7 @@ foreach my $infile (@ARGV) # Nodes from these files don't need support functions, # just node tags. if (elem basename($infile), - qw(execnodes.h trigger.h event_trigger.h amapi.h tableam.h + qw(execnodes.h fmgr.h trigger.h event_trigger.h amapi.h tableam.h tsmapi.h fdwapi.h tuptable.h replnodes.h supportnodes.h) ) { diff --git a/src/include/fmgr.h b/src/include/fmgr.h index 5314b73705..dfbf24897e 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -18,8 +18,9 @@ #ifndef FMGR_H #define FMGR_H -/* We don't want to include primnodes.h here, so make some stub references */ -typedef struct Node *fmNodePtr; +#include "nodes/nodes.h" + +/* We don't want to include primnodes.h here, so make a stub reference */ typedef struct Aggref *fmAggrefPtr; /* Likewise, avoid including execnodes.h here */ @@ -63,7 +64,7 @@ typedef struct FmgrInfo unsigned char fn_stats; /* collect stats if track_functions > this */ void *fn_extra; /* extra space for use by handler */ MemoryContext fn_mcxt; /* memory context to store fn_extra in */ - fmNodePtr fn_expr; /* expression parse tree for call, or NULL */ + Node *fn_expr; /* expression parse tree for call, or NULL */ } FmgrInfo; /* @@ -85,8 +86,8 @@ typedef struct FmgrInfo typedef struct FunctionCallInfoBaseData { FmgrInfo *flinfo; /* ptr to lookup info used for this call */ - fmNodePtr context; /* pass info about context of call */ - fmNodePtr resultinfo; /* pass or return extra info about result */ + Node *context; /* pass info about context of call */ + Node *resultinfo; /* pass or return extra info about result */ Oid fncollation; /* collation for function to use */ #define FIELDNO_FUNCTIONCALLINFODATA_ISNULL 4 bool isnull; /* function must set true if result is NULL */ @@ -708,9 +709,9 @@ extern const Pg_finfo_record *fetch_finfo_record(void *filehandle, const char *f extern Oid fmgr_internal_function(const char *proname); extern Oid get_fn_expr_rettype(FmgrInfo *flinfo); extern Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum); -extern Oid get_call_expr_argtype(fmNodePtr expr, int argnum); +extern Oid get_call_expr_argtype(Node *expr, int argnum); extern bool get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum); -extern bool get_call_expr_arg_stable(fmNodePtr expr, int argnum); +extern bool get_call_expr_arg_stable(Node *expr, int argnum); extern bool get_fn_expr_variadic(FmgrInfo *flinfo); extern bytea *get_fn_opclass_options(FmgrInfo *flinfo); extern bool has_fn_opclass_options(FmgrInfo *flinfo); @@ -751,6 +752,37 @@ extern void AggRegisterCallback(FunctionCallInfo fcinfo, fmExprContextCallbackFunction func, Datum arg); +/* + * Support for DO blocks + * + * If a procedural language supports DO, it will provide a "laninline" + * handler function. DO invokes that function passing an InlineCodeBlock + * node as the single argument. + */ +typedef struct InlineCodeBlock +{ + NodeTag type; + char *source_text; /* source text of anonymous code block */ + Oid langOid; /* OID of selected language */ + bool langIsTrusted; /* trusted property of the language */ + bool atomic; /* atomic execution context? */ +} InlineCodeBlock; + +/* + * Support for procedures + * + * Procedures are called using the same low-level mechanism as functions, + * but the fcinfo->context field is a CallContext node. This lets the + * callee know that it is being called via CALL rather than function + * syntax, and provides information about whether the semantic context + * is atomic or non-atomic. + */ +typedef struct CallContext +{ + NodeTag type; + bool atomic; /* atomic execution context? */ +} CallContext; + /* * We allow plugin modules to hook function entry/exit. This is intended * as support for loadable security policy modules, which may want to diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 0b6a7bb365..8011224d22 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -3370,8 +3370,6 @@ typedef struct AlterFunctionStmt /* ---------------------- * DO Statement - * - * DoStmt is the raw parser output, InlineCodeBlock is the execution-time API * ---------------------- */ typedef struct DoStmt @@ -3380,15 +3378,6 @@ typedef struct DoStmt List *args; /* List of DefElem nodes */ } DoStmt; -typedef struct InlineCodeBlock -{ - NodeTag type; - char *source_text; /* source text of anonymous code block */ - Oid langOid; /* OID of selected language */ - bool langIsTrusted; /* trusted property of the language */ - bool atomic; /* atomic execution context */ -} InlineCodeBlock; - /* ---------------------- * CALL statement * @@ -3406,12 +3395,6 @@ typedef struct CallStmt List *outargs; /* transformed output-argument expressions */ } CallStmt; -typedef struct CallContext -{ - NodeTag type; - bool atomic; -} CallContext; - /* ---------------------- * Alter Object Rename Statement * ---------------------- diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index edb93ec1c4..62c74a6da0 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -1881,7 +1881,7 @@ Datum plperl_inline_handler(PG_FUNCTION_ARGS) { LOCAL_FCINFO(fake_fcinfo, 0); - InlineCodeBlock *codeblock = (InlineCodeBlock *) PG_GETARG_POINTER(0); + InlineCodeBlock *codeblock = castNode(InlineCodeBlock, PG_GETARG_POINTER(0)); FmgrInfo flinfo; plperl_proc_desc desc; plperl_call_data *volatile save_call_data = current_call_data; diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c index 190d286f1c..cee393e4e0 100644 --- a/src/pl/plpgsql/src/pl_handler.c +++ b/src/pl/plpgsql/src/pl_handler.c @@ -315,7 +315,7 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS) { LOCAL_FCINFO(fake_fcinfo, 0); - InlineCodeBlock *codeblock = castNode(InlineCodeBlock, DatumGetPointer(PG_GETARG_DATUM(0))); + InlineCodeBlock *codeblock = castNode(InlineCodeBlock, PG_GETARG_POINTER(0)); PLpgSQL_function *func; FmgrInfo flinfo; EState *simple_eval_estate; diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c index 0bce106495..a7012c6c5b 100644 --- a/src/pl/plpython/plpy_main.c +++ b/src/pl/plpython/plpy_main.c @@ -265,7 +265,7 @@ Datum plpython3_inline_handler(PG_FUNCTION_ARGS) { LOCAL_FCINFO(fake_fcinfo, 0); - InlineCodeBlock *codeblock = (InlineCodeBlock *) DatumGetPointer(PG_GETARG_DATUM(0)); + InlineCodeBlock *codeblock = castNode(InlineCodeBlock, PG_GETARG_POINTER(0)); FmgrInfo flinfo; PLyProcedure proc; PLyExecutionContext *exec_ctx; diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm index b8b1728df7..80d90294ba 100644 --- a/src/tools/msvc/Solution.pm +++ b/src/tools/msvc/Solution.pm @@ -855,6 +855,7 @@ EOF nodes/parsenodes.h nodes/replnodes.h nodes/value.h + fmgr.h commands/trigger.h commands/event_trigger.h foreign/fdwapi.h