Re: Issues with patitionning and triggers - Mailing list pgsql-general

From Samuel Gilbert
Subject Re: Issues with patitionning and triggers
Date
Msg-id 36656139.rbatI8Y9LY@yamium
Whole thread Raw
In response to Re: Issues with patitionning and triggers  (Samuel Gilbert <samuel.gilbert@ec.gc.ca>)
Responses Re: Issues with patitionning and triggers
List pgsql-general
Hello everyone,

Here is a complete example demonstrating the issue I am encountering :

CREATE TABLE parent (
   split INTEGER NOT NULL,
   happiness INTEGER NOT NULL,
   modificationDate TIMESTAMP NOT NULL
);

CREATE TABLE child_split1 ( CHECK (split = 1) ) INHERITS (parent);
CREATE TABLE child_split2 ( CHECK (split = 2) ) INHERITS (parent);

CREATE OR REPLACE FUNCTION parent_dispatcher_trigger()
RETURNS TRIGGER AS $$
BEGIN
   CASE NEW.split
      WHEN 1 THEN INSERT INTO child_split1 VALUES (NEW.*);
      WHEN 2 THEN INSERT INTO child_split2 VALUES (NEW.*);
      ELSE RAISE EXCEPTION 'Partition for % does not exist!',NEW.split;
   END CASE;
   RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_insert_00
   BEFORE INSERT ON parent
   FOR EACH ROW EXECUTE PROCEDURE parent_dispatcher_trigger();

CREATE OR REPLACE FUNCTION set_modificationDate_debug() RETURNS TRIGGER AS $$
BEGIN
   NEW.modificationDate := now();
   RAISE NOTICE 'NEW row is now : (%, %, %)',
      NEW.split, NEW.happiness, NEW.modificationDate;
   RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';

CREATE TRIGGER trigger_insert_00
   BEFORE INSERT ON child_split1
   FOR EACH ROW EXECUTE PROCEDURE set_modificationdate_debug();

CREATE TRIGGER trigger_insert_00
   BEFORE INSERT ON child_split2
   FOR EACH ROW EXECUTE PROCEDURE set_modificationdate_debug();

INSERT INTO parent (split, happiness) VALUES (1, 42);

-- NOTICE:  NEW row is now : (1, 42, 2014-02-19 16:31:07.384151)
-- CONTEXT:  SQL statement "INSERT INTO child_split1 VALUES (NEW.*)"
-- PL/pgSQL function parent_dispatcher_trigger() line 4 at SQL statement
-- ERROR:  null value in column "modificationdate" violates not-null
constraint
-- DETAIL:  Failing row contains (1, 42, null).

INSERT INTO child_split1 (split, happiness) VALUES (1, 42);

-- NOTICE:  NEW row is now : (1, 42, 2014-02-19 16:37:27.134194)
-- INSERT 0 1


So, we clearly see that trigger_insert_00 is called in both cases.  I don't
understand why the query fails on the parent, but works when the INSERT
targets the child table directly.

Regards,
Samuel Gilbert


On 2014-02-18 23:16:31 Samuel Gilbert wrote:
> On 2014-02-18 17:59:35 Tom Lane wrote:
> > Samuel Gilbert <samuel.gilbert@ec.gc.ca> writes:
> > > All of this was done on PostgreSQL 9.2.0 64-bit compiled from the
> > > official
> >
> > > source.  Significant changes in postgresql.conf :
> > Why in the world are you using 9.2.0?  You're missing a year and a half
> > worth of bug fixes, some of them quite serious.
>
> Yes.  I know and I bear the pain and shame not running at least the latest
> revision of the 9.2 branch.  Unfortunately, it's hard to get my manager to
> view the update of software that "just works" as something to prioritize.
>
> The good news is that your reply is a good argument to do so!  :)
>
> Cheers!
>
> > > INSERT ... RETURNING does not work with partitioned tables, since the
> > > trigger function on the parent that dispatches new rows to the children
> > > tables, must return NULL.  If the trigger function on the parent ends
> > > with "RETURN NEW", INSERT ... RETURNING works, but new rows are
> > > duplicated; they are inserted both in the parent and child tables.
> > >
> > > Is there a way to make INSERT ... RETURNING work without duplicating the
> > > rows?
> >
> > Fraid not --- it only shows what got inserted into the parent table, which
> > is nothing if you're using this technique.
> >
> > > The modification date must be updated if any row is modified in any way.
> > > I
> > > first tried to define the triggers on the parent table.  This worked,
> > > but
> > > I
> > > realized that if a queries targets explicitly a child table, it could
> > > modify a row without the date being updated.  I therefore dropped the
> > > triggers on the parent table and defined them for every child.  To my
> > > great surprise, the insert below failed with a message saying that NULLs
> > > are not allowed in the modificationdate column.
> >
> > You'd have to provide a self-contained example for anyone to help you with
> > that.  The most obvious explanation is that you forgot to attach the
> > trigger to the specific child table ...
> >
> >             regards, tom lane


pgsql-general by date:

Previous
From: Alejandro Carrillo
Date:
Subject: Support for Alert
Next
From: "Joshua D. Drake"
Date:
Subject: Re: Support for Alert