简体   繁体   中英

How to insert stored functions and triggers in a Postgres container

I have a containerized Postgres database and I am trying to create a function and a trigger: a simple notification on a new row insertion.

It may seem stupid but I am unable to find how to write the code, where should I push it to the Postgres container, and how to programmatically insert the code inside the container.

I can see the following file structure

Database/Schemas/public/
|---tables
|  |___requests (tablename)
|  |__Triggers
|
|___Functions
 

I only (vaguely) found a way to copy the code inside when using the /docker-entrypoint-initdb.d/ folder (a COPY in the Dockerfile).

This injection works only - as per the Docker/Postgres documentation - when a database is created. This means I have to drop and recreate the database. This is wrong as I can't make any change to a production database.

Furthermore, when I adjoin the other SQL commands to the CREATE TABLE command in the .sql file, then the order of execution of these commands leads to errors (unknown table...).

My init.sql file programmatically copied into the /docker-entrypoint-initdb.d/ folder is:

-- init_table.sql
CREATE TABLE IF NOT EXISTS public.requests (
    id serial PRIMARY KEY,
    ...,
);

-- create_function_notify.sql
CREATE OR REPLACE FUNCTION notify_insert() RETURNS trigger AS
$$
   BEGIN
      PERFORM pg_notify('new_notif', row_to_json(NEW)::text);
      RETURN NEW;
   END;
$$ LANGUAGE plpgsql;


-- create_trigger_new_event.sql
CREATE TRIGGER new_event
   AFTER INSERT
   ON public.requests
   FOR EACH ROW
   EXECUTE PROCEDURE notify_insert();

LANGUAGE plpgsql;

I also tried a "sh" version (dixit PG docs) without success: it throws an error around "$$".

#/bin/sh

set -e

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
  CREATE OR REPLACE FUNCTION notify_insert() RETURNS trigger AS
$$
  LANGUAGE plpgsql;
EOSQL

在此处输入图像描述

A Dockerfile instruction COPY./pg_notify.sql /docker-entrypoint-initdb.d/ sets up the desired trigger and notification related function to the containerized Postgres database (on creation only).

Following Bergi's remark, the correct code is:


-- pg_notify.sql

CREATE TABLE IF NOT EXISTS public.requests (
    id serial PRIMARY KEY,
    app varchar,
    url varchar,
    ip varchar,
    host varchar,
    req_at VARCHAR,
    d BIGINT
);


CREATE OR REPLACE FUNCTION notify_insert() RETURNS trigger 
LANGUAGE plpgsql
AS $$
   BEGIN
      PERFORM pg_notify('new_notification', row_to_json(NEW)::text);
      RETURN NEW;
   END;
$$;

CREATE TRIGGER new_event
   AFTER INSERT
   ON requests
   FOR EACH ROW
   EXECUTE PROCEDURE notify_insert();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM