@@ -16,10 +16,23 @@ static void exitHook(int code, Datum arg);
1616
1717void * serializePlanState (FdwPlanState * state );
1818FdwExecState * initializeExecState (void * internalstate );
19+
20+ static void
21+ steampipe_fdw_ProcessUtility (PlannedStmt * pstmt ,
22+ const char * queryString ,
23+ bool readOnlyTree ,
24+ ProcessUtilityContext context ,
25+ ParamListInfo params ,
26+ QueryEnvironment * queryEnv ,
27+ DestReceiver * dest ,
28+ QueryCompletion * qc );
29+
1930// Required by postgres, doing basic checks to ensure compatibility,
2031// such as being compiled against the correct major version.
2132PG_MODULE_MAGIC ;
2233
34+ static ProcessUtility_hook_type next_ProcessUtility_hook = NULL ;
35+
2336// Define the handler function for signal 16
2437void signal_handler (int sig ) {
2538// elog(NOTICE, "Caught signal %d", sig);
@@ -63,6 +76,9 @@ void _PG_init(void)
6376 on_proc_exit (& exitHook , PointerGetDatum (NULL ));
6477 RegisterXactCallback (pgfdw_xact_callback , NULL );
6578
79+ /* Hook ProcessUtility for adding comments to foreign tables */
80+ next_ProcessUtility_hook = ProcessUtility_hook ;
81+ ProcessUtility_hook = steampipe_fdw_ProcessUtility ;
6682}
6783
6884/*
@@ -88,6 +104,71 @@ void exitHook(int code, Datum arg)
88104 goFdwShutdown ();
89105}
90106
107+ static void
108+ steampipe_fdw_ProcessUtility (PlannedStmt * pstmt ,
109+ const char * queryString ,
110+ bool readOnlyTree ,
111+ ProcessUtilityContext context ,
112+ ParamListInfo params ,
113+ QueryEnvironment * queryEnv ,
114+ DestReceiver * dest ,
115+ QueryCompletion * qc ) {
116+ List * cmd_list = NULL ;
117+ if (IsA (pstmt -> utilityStmt , CreateForeignTableStmt ) && context == PROCESS_UTILITY_SUBCOMMAND && dest == None_Receiver ) {
118+ const CreateForeignTableStmt * cstmt = (const CreateForeignTableStmt * )pstmt -> utilityStmt ;
119+ ForeignServer * server = GetForeignServerByName (cstmt -> servername , true);
120+ if (server != NULL ) {
121+ ForeignDataWrapper * wrapper = GetForeignDataWrapper (server -> fdwid );
122+ if (wrapper != NULL && wrapper -> fdwname != NULL && strcmp (wrapper -> fdwname , STEAMPIPE_DATAWRAPPER_NAME ) == 0 ) {
123+ cmd_list = goFdwGetForeignTableComments (cstmt -> servername , cstmt -> base .relation -> schemaname , cstmt -> base .relation -> relname );
124+ }
125+ }
126+ }
127+
128+ if (next_ProcessUtility_hook ) {
129+ next_ProcessUtility_hook (pstmt , queryString , readOnlyTree , context , params , queryEnv , dest , qc );
130+ } else {
131+ standard_ProcessUtility (pstmt , queryString , readOnlyTree , context , params , queryEnv , dest , qc );
132+ }
133+
134+ if (cmd_list != NULL ) {
135+ ListCell * lc ;
136+ foreach (lc , cmd_list ) {
137+ char * cmd = (char * )lfirst (lc );
138+ List * raw_parsetree_list = pg_parse_query (cmd );
139+
140+ ListCell * lc2 ;
141+ foreach (lc2 , raw_parsetree_list ) {
142+ RawStmt * rs = lfirst_node (RawStmt , lc2 );
143+ CommentStmt * comment_stmt = (CommentStmt * )rs -> stmt ;
144+
145+ if (!IsA (comment_stmt , CommentStmt )) {
146+ elog (ERROR , "unexpected statement type %d where CommentStmt expected" , (int )nodeTag (comment_stmt ));
147+ }
148+
149+ #if PG_VERSION_NUM < 120000
150+ // Be sure to advance the command counter between subcommands
151+ // Not needed in PG 12+ because standard_ProcessUtility already does this
152+ CommandCounterIncrement ();
153+ #endif
154+
155+ pstmt = makeNode (PlannedStmt );
156+ pstmt -> commandType = CMD_UTILITY ;
157+ pstmt -> canSetTag = false;
158+ pstmt -> utilityStmt = (Node * ) comment_stmt ;
159+ pstmt -> stmt_location = rs -> stmt_location ;
160+ pstmt -> stmt_len = rs -> stmt_len ;
161+
162+ /* Execute statement */
163+ ProcessUtility (pstmt , cmd , false,
164+ PROCESS_UTILITY_SUBCOMMAND , NULL , NULL ,
165+ None_Receiver , NULL );
166+ }
167+ }
168+
169+ }
170+ }
171+
91172static bool fdwIsForeignScanParallelSafe (PlannerInfo * root , RelOptInfo * rel , RangeTblEntry * rte ) {
92173 return getenv ("STEAMPIPE_FDW_PARALLEL_SAFE" ) != NULL ;
93174}
0 commit comments