Module pgx::trigger_support
source · Expand description
Support for writing Rust trigger functions
A “no-op” trigger that gets the current [PgHeapTuple
][crate::PgHeapTuple],
panicking (into a PostgreSQL error) if it doesn’t exist:
use pgx::prelude::*;
#[pg_trigger]
fn trigger_example<'a>(trigger: &'a PgTrigger<'a>) -> Result<
Option<PgHeapTuple<'a, impl WhoAllocated>>,
PgHeapTupleError,
> {
Ok(Some(trigger.old().expect("No current HeapTuple")))
}
Trigger functions only accept one argument, a [PgTrigger
], and they return a Result
containing
either a [PgHeapTuple
][crate::PgHeapTuple] or any error that implements impl std::error::Error
.
Use from SQL
The trigger_example
example above would generate something like the following SQL:
-- pgx-examples/triggers/src/lib.rs:25
-- triggers::trigger_example
CREATE FUNCTION "trigger_example"()
RETURNS TRIGGER
LANGUAGE c
AS 'MODULE_PATHNAME', 'trigger_example_wrapper';
Users could then use it like so:
CREATE TABLE test (
id serial8 NOT NULL PRIMARY KEY,
title varchar(50),
description text,
payload jsonb
);
CREATE TRIGGER test_trigger
BEFORE INSERT ON test
FOR EACH ROW
EXECUTE PROCEDURE trigger_example();
INSERT INTO test (title, description, payload)
VALUES ('Fox', 'a description', '{"key": "value"}');
This can also be done via the extension_sql
attribute:
pgx::extension_sql!(
r#"
CREATE TABLE test (
id serial8 NOT NULL PRIMARY KEY,
title varchar(50),
description text,
payload jsonb
);
*
CREATE TRIGGER test_trigger BEFORE INSERT ON test FOR EACH ROW EXECUTE PROCEDURE trigger_example();
INSERT INTO test (title, description, payload) VALUES ('Fox', 'a description', '{"key": "value"}');
"#,
name = "create_trigger",
requires = [ trigger_example ]
);
Working with WhoAllocated
Trigger functions can return [PgHeapTuple
][crate::PgHeapTuple]s which are AllocatedByRust
or AllocatedByPostgres
. In most cases, it can be inferred by the compiler using
impl WhoAllocated<pg_sys::HeapTupleData>>
.
When it can’t, the function definition permits for it to be specified:
use pgx::prelude::*;
#[pg_trigger]
fn example_allocated_by_rust<'a>(trigger: &'a PgTrigger<'a>) -> Result<
Option<PgHeapTuple<'a, AllocatedByRust>>,
PgHeapTupleError,
> {
let current = trigger.old().expect("No current HeapTuple");
Ok(Some(current.into_owned()))
}
#[pg_trigger]
fn example_allocated_by_postgres<'a>(trigger: &'a PgTrigger<'a>) -> Result<
Option<PgHeapTuple<'a, AllocatedByPostgres>>,
PgHeapTupleError,
> {
let current = trigger.old().expect("No current HeapTuple");
Ok(Some(current))
}
Error Handling
Trigger functions can return any impl std::error::Error
. Returned errors
become PostgreSQL errors.
use pgx::prelude::*;
#[derive(thiserror::Error, Debug)]
enum CustomTriggerError {
#[error("No current HeapTuple")]
NoCurrentHeapTuple,
#[error("pgx::PgHeapTupleError: {0}")]
PgHeapTuple(PgHeapTupleError),
}
#[pg_trigger]
fn example_custom_error<'a>(trigger: &'a PgTrigger<'a>) -> Result<
Option<PgHeapTuple<'a, impl WhoAllocated>>,
CustomTriggerError,
> {
trigger.old().map(|t| Some(t)).ok_or(CustomTriggerError::NoCurrentHeapTuple)
}
Lifetimes
Triggers are free to use lifetimes to hone their code, the generated wrapper is as generous as possible.
use pgx::prelude::*;
#[derive(thiserror::Error, Debug)]
enum CustomTriggerError<'a> {
#[error("No current HeapTuple")]
NoCurrentHeapTuple,
#[error("pgx::PgHeapTupleError: {0}")]
PgHeapTuple(PgHeapTupleError),
#[error("A borrowed error variant: {0}")]
SomeStr(&'a str),
}
#[pg_trigger]
fn example_lifetimes<'a, 'b>(trigger: &'a PgTrigger<'a>) -> Result<
Option<PgHeapTuple<'a, AllocatedByRust>>,
CustomTriggerError<'b>,
> {
return Err(CustomTriggerError::SomeStr("Oopsie"))
}
Escape hatches
Unsafe pgx::pg_sys::FunctionCallInfo
and
pgx::pg_sys::TriggerData
(include its contained
pgx::pg_sys::Trigger
) accessors are available..
Re-exports
pub use pg_trigger::PgTrigger;
pub use pg_trigger_error::PgTriggerError;
pub use pg_trigger_level::PgTriggerLevel;
pub use pg_trigger_option::PgTriggerOperation;
pub use pg_trigger_when::PgTriggerWhen;
Structs
- Represents the event that fired a trigger.
Enums
- Indicates which trigger tuple to convert into a [crate::PgHeapTuple].