More SqlDelight (Triggers with PostgreSql)
25 Sep 2025Initial support for CREATE TRIGGER in SqlDelight 2.2.0-SNAPSHOT
Limited support for Pg/PlSql to implement basic trigger functions e.g IF ELSEIF ELSE
conditionals and trigger variables TG_OP
.
Example
https://github.com/griffio/sqldelight-postgres-trigger-function
Schema
CREATE TABLE accounts(
id INTEGER GENERATED ALWAYS AS IDENTITY,
balance REAL
);
CREATE TABLE accounts_audit (
account_id INTEGER,
balance REAL,
changed_on TIMESTAMP NOT NULL
);
CREATE OR REPLACE FUNCTION account_audit_update()
RETURNS TRIGGER LANGUAGE PLPGSQL AS
$$
BEGIN
IF new.balance <> old.balance THEN
INSERT INTO accounts_audit(account_id, balance, changed_on)
VALUES (old.id, old.balance, NOW());
END IF;
RETURN new;
END;
$$;
CREATE OR REPLACE TRIGGER account_audit_update
BEFORE UPDATE OF balance
ON accounts
FOR EACH ROW
EXECUTE FUNCTION account_audit_update();
CREATE TABLE organizations (
id INTEGER GENERATED ALWAYS AS IDENTITY,
name TEXT NOT NULL,
updated_at TIMESTAMP DEFAULT NOW() NOT NULL
);
CREATE OR REPLACE FUNCTION organizations_set_updated_at()
RETURNS TRIGGER LANGUAGE PLPGSQL AS
$$
BEGIN
new.updated_at := NOW();
RETURN new;
END;
$$;
CREATE TRIGGER organizations_set_updated_at
BEFORE UPDATE
ON organizations
FOR EACH ROW
EXECUTE FUNCTION organizations_set_updated_at();
CREATE TABLE user_profile (
username TEXT NOT NULL UNIQUE,
password TEXT NOT NULL,
password_strength TEXT
);
CREATE OR REPLACE FUNCTION user_profile_password_strength()
RETURNS TRIGGER LANGUAGE PLPGSQL AS
$$
BEGIN
IF TG_OP = 'UPDATE' AND new.password IS NOT DISTINCT FROM old.password THEN
RETURN new;
END IF;
IF length(new.password) < 7 THEN
new.password_strength := 'weak';
ELSIF length(new.password) < 12 THEN
new.password_strength := 'medium';
ELSE
new.password_strength := 'strong';
END IF;
RETURN new;
END;
$$;
CREATE TRIGGER user_profile_password_strength
BEFORE INSERT OR UPDATE OF password
ON user_profile
FOR EACH ROW
EXECUTE FUNCTION user_profile_password_strength();
CREATE TABLE emp (
empname TEXT NOT NULL,
salary INTEGER
);
CREATE TABLE emp_audit(
operation CHAR(1) NOT NULL,
stamp TIMESTAMP NOT NULL,
userid TEXT NOT NULL,
empname TEXT NOT NULL,
salary INTEGER
);
CREATE OR REPLACE FUNCTION process_emp_audit()
RETURNS TRIGGER LANGUAGE PLPGSQL AS $$
BEGIN
--
-- Create a row in emp_audit to reflect the operation performed on emp,
-- making use of the special variable TG_OP to work out the operation.
--
IF (TG_OP = 'DELETE') THEN
INSERT INTO emp_audit SELECT 'D', NOW(), CURRENT_USER, old.empname, old.salary;
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO emp_audit SELECT 'U', NOW(), CURRENT_USER, new.empname, new.salary;
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO emp_audit SELECT 'I', NOW(), CURRENT_USER, new.empname, new.salary;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
$$;
CREATE TRIGGER process_emp_audit
AFTER INSERT OR UPDATE OR DELETE
ON emp
FOR EACH ROW EXECUTE FUNCTION process_emp_audit();