Tomas Vondra писал 2023-05-25 17:41:

The attached patch does this - I realized we actually have estate in
ExecGetAllUpdatedCols(), so we don't even need a variant with a
different signature. That makes the patch much simpler.

The question is whether we need the signature anyway. There might be a
caller expecting the result to be in CurrentMemoryContext (be it
ExecutorState or something else), and this change might break it. But
I'm not aware of any callers, so maybe that's fine.


Hi.
Unfortunately, this patch has broken trigdata->tg_updatedcols usage in AFTER UPDATE triggers.
Should it be if not fixed, but at least mentioned in documentation?

Attaching sample code. After creating trigger, an issue can be reproduced as this:

create table test (i int, j int);
create function report_update_fields() RETURNS TRIGGER AS '/location/to/trig_test.so' language C; create trigger test_update after update ON test FOR EACH ROW EXECUTE FUNCTION report_update_fields();
insert into test values (1, 12);
update test set j=2;

--
Best regards,
Alexander Pyhalov,
Postgres Professional
#include <postgres.h>
#include <fmgr.h>
#include <funcapi.h>
#include <utils/elog.h>
#include <commands/trigger.h>

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif


void _PG_init()
{
}

PG_FUNCTION_INFO_V1(report_update_fields);

Datum
report_update_fields(PG_FUNCTION_ARGS)
{
	TriggerData *trigdata = (TriggerData *) fcinfo->context;
	int			tgnargs,
				ret;
	char	   *rgids,
			   *gtname,
			   *nspname,
			   *rname;
	HeapTuple	rettuple = NULL;
	List	   *rgidlist = NIL;
	ListCell   *lc;

	if (!CALLED_AS_TRIGGER(fcinfo) || /*!TRIGGER_FIRED_AFTER(trigdata->tg_event) || */ TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event) || !TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
		elog(ERROR, "usage unsupported");
	
	if ((trigdata->tg_trigtuple != NULL) && (trigdata->tg_newtuple != NULL))
	{
        int attnum = -1;
        int num_upd_attrs = 0;
        
        while ((attnum = bms_next_member(trigdata->tg_updatedcols, attnum)) >= 0)
            if (attnum + FirstLowInvalidHeapAttributeNumber > 0)
                num_upd_attrs++;
                
        elog(INFO, "updated %d attrs", num_upd_attrs);
    }
}

Reply via email to