Postgres trigger-based insert redirection without breaking RETURNING

后端 未结 2 1185
自闭症患者
自闭症患者 2020-12-18 10:54

I\'m using table inheritance in postgres, but the trigger I\'m using to partition data into the child tables isn\'t quite behaving right. For example, this query returns nil

2条回答
  •  北海茫月
    2020-12-18 11:21

    @pozs provided a correct answer but didn't quite provide the code for a full working implementation. I tried to include the code in an edit on his question, but it was not accepted. He instead suggested yet another approach, which looks cleaner, but may have some drawbacks (in the case where you re-use your trigger function elsewhere).

    Including my solution here for reference:

    CREATE TABLE base_flags (
      id integer NOT NULL,
      flaggable_type character varying(255) NOT NULL,
      flaggable_id integer NOT NULL,
      body text
    );
    
    ALTER TABLE ONLY base_flags
      ADD CONSTRAINT base_flags_pkey PRIMARY KEY (id);
    
    CREATE SEQUENCE base_flags_id_seq
      START WITH 1
      INCREMENT BY 1
      NO MINVALUE
      NO MAXVALUE
      CACHE 1;
    
    ALTER SEQUENCE base_flags_id_seq OWNED BY base_flags.id;
    
    CREATE OR REPLACE VIEW flags AS SELECT * FROM base_flags;
    
    CREATE TABLE "comment_flags" (
      CHECK ("flaggable_type" = 'Comment'),
      PRIMARY KEY ("id"),
      FOREIGN KEY ("flaggable_id") REFERENCES "comments"("id")
    ) INHERITS ("flags");
    
    CREATE TABLE "profile_flags" (
      CHECK ("flaggable_type" = 'Profile'),
      PRIMARY KEY ("id"),
      FOREIGN KEY ("flaggable_id") REFERENCES "profiles"("id")
    ) INHERITS ("flags");
    
    CREATE OR REPLACE FUNCTION flag_insert_trigger_fun() RETURNS TRIGGER AS $BODY$
      BEGIN
        IF NEW.id IS NULL THEN
          NEW.id := nextval('base_flags_id_seq');
        END IF; 
        IF (NEW."flaggable_type" = 'Comment') THEN
          INSERT INTO comment_flags VALUES (NEW.*);
        ELSIF (NEW."flaggable_type" = 'Profile') THEN
          INSERT INTO profile_flags VALUES (NEW.*);
        ELSE
          RAISE EXCEPTION 'Wrong "flaggable_type"="%", fix flag_insert_trigger_fun() function', NEW."flaggable_type";
        END IF;
        RETURN NEW;
      END;
    $BODY$
    LANGUAGE plpgsql;
    
    CREATE TRIGGER flag_insert_trigger
      INSTEAD OF INSERT ON base_flags
      FOR EACH ROW EXECUTE PROCEDURE flag_insert_trigger_fun();
    

提交回复
热议问题