Skip to content

Commit e3492fa

Browse files
author
Antonin Houska
committed
Allow the worker to send a message with elevel < ERROR.
1 parent c763195 commit e3492fa

3 files changed

Lines changed: 52 additions & 17 deletions

File tree

expected/pg_rewrite.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ Foreign-key constraints:
325325
"tab1_fk_i_fkey" FOREIGN KEY (i) REFERENCES tab1_pk(i)
326326

327327
SELECT rewrite_table('tab1_fk', 'tab1_fk_new', 'tab1_fk_orig');
328+
NOTICE: FOREIGN KEY with NOT VALID option cannot be added to partitioned table
328329
rewrite_table
329330
---------------
330331

pg_rewrite.c

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ static WorkerTask *get_task(int *idx, char *relschema, char *relname,
104104
static void initialize_worker(BackgroundWorker *worker, int task_idx);
105105
static 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

108110
static void check_prerequisites(Relation rel);
109111
static 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

558562
done:
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;

pg_rewrite.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,20 @@ typedef struct WorkerTask
150150
NameData relschema_dst;
151151
NameData relname_dst;
152152

153-
/* Space for the worker to send an error message to the backend. */
153+
/*
154+
* Space for the worker to send an error message to the backend.
155+
*
156+
* XXX Note that later messages overwrite the earlier ones, so only the
157+
* last message is received. Is it worth using a queue instead?
158+
*/
154159
#define MAX_ERR_MSG_LEN 1024
155160
char msg[MAX_ERR_MSG_LEN];
156161

157162
/* Detailed error message. */
158163
char msg_detail[MAX_ERR_MSG_LEN];
159164

165+
int elevel;
166+
160167
/*
161168
* Should rewrite_table() return w/o waiting for the worker's exit? If
162169
* this flag is set, the worker is responsible for releasing the

0 commit comments

Comments
 (0)