@@ -104,6 +104,8 @@ static WorkerTask *get_task(int *idx, char *relschema, char *relname,
104104static void initialize_worker (BackgroundWorker * worker , int task_idx );
105105static void run_worker (BackgroundWorker * worker , WorkerTask * task ,
106106 bool nowait );
107+ static void send_message (WorkerTask * task , int elevel , const char * message ,
108+ const char * detail );
107109
108110static void check_prerequisites (Relation rel );
109111static LogicalDecodingContext * setup_decoding (Relation rel );
@@ -433,6 +435,7 @@ get_task(int *idx, char *relschema, char *relname, bool nowait)
433435
434436 task -> msg [0 ] = '\0' ;
435437 task -> msg_detail [0 ] = '\0' ;
438+ task -> elevel = -1 ;
436439
437440 task -> nowait = nowait ;
438441
@@ -473,6 +476,7 @@ run_worker(BackgroundWorker *worker, WorkerTask *task, bool nowait)
473476 pid_t pid ;
474477 char * msg = NULL ;
475478 char * msg_detail = NULL ;
479+ int elevel = -1 ;
476480
477481 /*
478482 * Start the worker. Avoid leaking the task if the function ends due to
@@ -557,7 +561,10 @@ run_worker(BackgroundWorker *worker, WorkerTask *task, bool nowait)
557561
558562done :
559563 if (strlen (task -> msg ) > 0 )
564+ {
560565 msg = pstrdup (task -> msg );
566+ elevel = task -> elevel ;
567+ }
561568 if (strlen (task -> msg_detail ) > 0 )
562569 msg_detail = pstrdup (task -> msg_detail );
563570
@@ -567,14 +574,39 @@ run_worker(BackgroundWorker *worker, WorkerTask *task, bool nowait)
567574 if (msg )
568575 {
569576 if (msg_detail )
570- ereport (ERROR , (errmsg ("%s" , msg ),
571- errdetail ("%s" , msg_detail )));
577+ ereport (elevel , (errmsg ("%s" , msg ),
578+ errdetail ("%s" , msg_detail )));
572579 else
573- ereport (ERROR , (errmsg ("%s" , msg )));
580+ ereport (elevel , (errmsg ("%s" , msg )));
574581 }
575582
576583}
577584
585+ /*
586+ * Send log message from the worker to the backend that launched it.
587+ *
588+ * Currently we only copy 'message' and 'detail. More fields can be added to
589+ * WorkerTask if needed. Another limitation is that if the worker sends
590+ * multiple messages, the backend only receives the last one.
591+ *
592+ * (Ideally we should use the message queue like parallel workers do, but the
593+ * related PG core functions have some parallel worker specific arguments.)
594+ */
595+ static void
596+ send_message (WorkerTask * task , int elevel , const char * message ,
597+ const char * detail )
598+ {
599+ strlcpy (task -> msg , message , MAX_ERR_MSG_LEN );
600+ task -> elevel = elevel ;
601+ if (detail && strlen (detail ) > 0 )
602+ strlcpy (task -> msg_detail , detail , MAX_ERR_MSG_LEN );
603+ else
604+ /*
605+ * Message with elevel < ERROR could already have been written here.
606+ */
607+ task -> msg_detail [0 ] = '\0' ;
608+ }
609+
578610/* PG >= 14 does define this macro. */
579611#if PG_VERSION_NUM < 140000
580612#define RelationIsPermanent (relation ) \
@@ -776,15 +808,7 @@ rewrite_worker_main(Datum main_arg)
776808
777809 AbortOutOfAnyTransaction ();
778810
779- /*
780- * Currently we only copy 'message' and 'detail.More information can
781- * be added if needed. (Ideally we'd use the message queue like
782- * parallel workers do, but the related PG core functions have some
783- * parallel worker specific arguments.)
784- */
785- strlcpy (task -> msg , edata -> message , MAX_ERR_MSG_LEN );
786- if (edata -> detail && strlen (edata -> detail ) > 0 )
787- strlcpy (task -> msg_detail , edata -> detail , MAX_ERR_MSG_LEN );
811+ send_message (task , ERROR , edata -> message , edata -> detail );
788812
789813 FreeErrorData (edata );
790814 }
@@ -2983,13 +3007,16 @@ dump_fk_constraint(HeapTuple tup, Oid relid_dst, const char *relname_dst,
29833007 {
29843008 /*
29853009 * ALTER TABLE ... ADD CONSTRAINT ... FOREIGN KEY ... NOT VALID is
2986- * currently not supported for partitioned FK table. XXX It might be
2987- * worth a NOTICE message, but how can we propagate the from the
2988- * worker to the launching backend? (Currently we only do that for >=
2989- * ERROR.)
3010+ * currently not supported for partitioned FK table.
29903011 */
29913012 if (get_rel_relkind (relid_dst ) == RELKIND_PARTITIONED_TABLE )
3013+ {
3014+ send_message (MyWorkerTask ,
3015+ NOTICE ,
3016+ "FOREIGN KEY with NOT VALID option cannot be added to partitioned table" ,
3017+ NULL );
29923018 return ;
3019+ }
29933020
29943021 fknsp = get_namespace_name (relid_dst );
29953022 fkrelname = relname_dst ;
0 commit comments