Re: The suppress_redundant_updates_trigger() works incorrectly - Mailing list pgsql-hackers

From Andrew Dunstan
Subject Re: The suppress_redundant_updates_trigger() works incorrectly
Date
Msg-id 4911DE31.2040001@dunslane.net
Whole thread Raw
In response to Re: The suppress_redundant_updates_trigger() works incorrectly  (Andrew Dunstan <andrew@dunslane.net>)
Responses Re: The suppress_redundant_updates_trigger() works incorrectly  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers

Andrew Dunstan wrote:
> KaiGai Kohei wrote:
>
>> Hi,
>>
>> The suppress_redundant_updates_trigger() works incorrectly
>> on the table defined with "WITH_OIDS" option.
>>
>>
>>
>
> Good catch!
>
> I think ideally we'd just adjust the comparison to avoid the system
> attributes.
>
> I'll have a look to see if it can be done simply.
>
>
>

The attached patch sets the OID to InvalidOid for the duration of the
memcmp if the HEAP_HASOID flag is set, and restores it afterwards.

That seems to handle the problem.

There's also an added regression test for the Oids case.

If there's no objection I'll apply this shortly.

cheers

andrew
Index: src/backend/utils/adt/trigfuncs.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/trigfuncs.c,v
retrieving revision 1.2
diff -c -r1.2 trigfuncs.c
*** src/backend/utils/adt/trigfuncs.c    4 Nov 2008 00:29:39 -0000    1.2
--- src/backend/utils/adt/trigfuncs.c    5 Nov 2008 17:30:26 -0000
***************
*** 30,35 ****
--- 30,36 ----
      TriggerData *trigdata = (TriggerData *) fcinfo->context;
      HeapTuple   newtuple, oldtuple, rettuple;
      HeapTupleHeader newheader, oldheader;
+     Oid oldoid = InvalidOid;

      /* make sure it's called as a trigger */
      if (!CALLED_AS_TRIGGER(fcinfo))
***************
*** 62,67 ****
--- 63,74 ----
      newheader = newtuple->t_data;
      oldheader = oldtuple->t_data;

+      if (oldheader->t_infomask & HEAP_HASOID)
+     {
+         oldoid = HeapTupleHeaderGetOid(oldheader);
+         HeapTupleHeaderSetOid(oldheader, InvalidOid);
+     }
+
      /* if the tuple payload is the same ... */
      if (newtuple->t_len == oldtuple->t_len &&
          newheader->t_hoff == oldheader->t_hoff &&
***************
*** 76,81 ****
--- 83,93 ----
          /* ... then suppress the update */
          rettuple = NULL;
      }
+      else if (oldheader->t_infomask & HEAP_HASOID)
+     {
+         HeapTupleHeaderSetOid(oldheader, oldoid);
+     }
+

      return PointerGetDatum(rettuple);
  }
Index: src/test/regress/expected/triggers.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/triggers.out,v
retrieving revision 1.25
diff -c -r1.25 triggers.out
*** src/test/regress/expected/triggers.out    3 Nov 2008 20:17:20 -0000    1.25
--- src/test/regress/expected/triggers.out    5 Nov 2008 17:30:27 -0000
***************
*** 542,551 ****
--- 542,559 ----
      f1    text,
      f2 int,
      f3 int);
+ CREATE TABLE min_updates_test_oids (
+     f1    text,
+     f2 int,
+     f3 int) WITH OIDS;
  INSERT INTO min_updates_test VALUES ('a',1,2),('b','2',null);
+ INSERT INTO min_updates_test_oids VALUES ('a',1,2),('b','2',null);
  CREATE TRIGGER z_min_update
  BEFORE UPDATE ON min_updates_test
  FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
+ CREATE TRIGGER z_min_update
+ BEFORE UPDATE ON min_updates_test_oids
+ FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
  \set QUIET false
  UPDATE min_updates_test SET f1 = f1;
  UPDATE 0
***************
*** 553,558 ****
--- 561,572 ----
  UPDATE 2
  UPDATE min_updates_test SET f3 = 2 WHERE f3 is null;
  UPDATE 1
+ UPDATE min_updates_test_oids SET f1 = f1;
+ UPDATE 0
+ UPDATE min_updates_test_oids SET f2 = f2 + 1;
+ UPDATE 2
+ UPDATE min_updates_test_oids SET f3 = 2 WHERE f3 is null;
+ UPDATE 1
  \set QUIET true
  SELECT * FROM min_updates_test;
   f1 | f2 | f3
***************
*** 561,564 ****
--- 575,586 ----
   b  |  3 |  2
  (2 rows)

+ SELECT * FROM min_updates_test_oids;
+  f1 | f2 | f3
+ ----+----+----
+  a  |  2 |  2
+  b  |  3 |  2
+ (2 rows)
+
  DROP TABLE min_updates_test;
+ DROP TABLE min_updates_test_oids;
Index: src/test/regress/sql/triggers.sql
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/sql/triggers.sql,v
retrieving revision 1.14
diff -c -r1.14 triggers.sql
*** src/test/regress/sql/triggers.sql    3 Nov 2008 20:17:21 -0000    1.14
--- src/test/regress/sql/triggers.sql    5 Nov 2008 17:30:27 -0000
***************
*** 424,435 ****
--- 424,446 ----
      f2 int,
      f3 int);

+ CREATE TABLE min_updates_test_oids (
+     f1    text,
+     f2 int,
+     f3 int) WITH OIDS;
+
  INSERT INTO min_updates_test VALUES ('a',1,2),('b','2',null);

+ INSERT INTO min_updates_test_oids VALUES ('a',1,2),('b','2',null);
+
  CREATE TRIGGER z_min_update
  BEFORE UPDATE ON min_updates_test
  FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();

+ CREATE TRIGGER z_min_update
+ BEFORE UPDATE ON min_updates_test_oids
+ FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
+
  \set QUIET false

  UPDATE min_updates_test SET f1 = f1;
***************
*** 438,446 ****
--- 449,467 ----

  UPDATE min_updates_test SET f3 = 2 WHERE f3 is null;

+ UPDATE min_updates_test_oids SET f1 = f1;
+
+ UPDATE min_updates_test_oids SET f2 = f2 + 1;
+
+ UPDATE min_updates_test_oids SET f3 = 2 WHERE f3 is null;
+
  \set QUIET true

  SELECT * FROM min_updates_test;

+ SELECT * FROM min_updates_test_oids;
+
  DROP TABLE min_updates_test;

+ DROP TABLE min_updates_test_oids;
+

pgsql-hackers by date:

Previous
From: Tom Lane
Date:
Subject: Re: pg_standby could not open wal file after selecting new timeline
Next
From: Tom Lane
Date:
Subject: Re: pg_standby could not open wal file after selecting new timeline