Attribute Macro pgx_macros::pg_extern

source ·
#[pg_extern]
Expand description

Declare a function as #[pg_extern] to indicate that it can be used by Postgres as a UDF.

Optionally accepts the following attributes:

  • immutable: Corresponds to IMMUTABLE.
  • strict: Corresponds to STRICT.
    • In most cases, #[pg_extern] can detect when no Option<T>s are used, and automatically set this.
  • stable: Corresponds to STABLE.
  • volatile: Corresponds to VOLATILE.
  • raw: Corresponds to RAW.
  • parallel_safe: Corresponds to PARALLEL SAFE.
  • parallel_unsafe: Corresponds to PARALLEL UNSAFE.
  • parallel_restricted: Corresponds to PARALLEL RESTRICTED.
  • no_guard: Do not use #[pg_guard] with the function.
  • sql: Same arguments as #[pgx(sql = ..)].
  • name: Specifies target function name. Defaults to Rust function name.

Functions can accept and return any type which pgx supports. pgx supports many PostgreSQL types by default. New types can be defined via PostgresType or PostgresEnum.

Without any arguments or returns:

use pgx::*;
#[pg_extern]
fn foo() { todo!() }

Arguments

It’s possible to pass even complex arguments:

use pgx::*;
#[pg_extern]
fn boop(
    a: i32,
    b: Option<i32>,
    c: Vec<i32>,
    d: Option<Vec<Option<i32>>>
) { todo!() }

It’s possible to set argument defaults, set by PostgreSQL when the function is invoked:

use pgx::*;
#[pg_extern]
fn boop(a: default!(i32, 11111)) { todo!() }
#[pg_extern]
fn doop(
    a: default!(Vec<Option<&str>>, "ARRAY[]::text[]"),
    b: default!(String, "'note the inner quotes!'")
) { todo!() }

The default!() macro may only be used in argument position.

It accepts 2 arguments:

  • A type
  • A bool, numeric, or SQL string to represent the default. "NULL" is a possible value, as is "'string'"

If the default SQL entity created by the extension: ensure it is added to requires as a dependency:

use pgx::*;
#[pg_extern]
fn default_value() -> i32 { todo!() }

#[pg_extern(
    requires = [ default_value, ],
)]
fn do_it(
    a: default!(i32, "default_value()"),
) { todo!() }

Returns

It’s possible to return even complex values, as well:

use pgx::*;
#[pg_extern]
fn boop() -> i32 { todo!() }
#[pg_extern]
fn doop() -> Option<i32> { todo!() }
#[pg_extern]
fn swoop() -> Option<Vec<Option<i32>>> { todo!() }
#[pg_extern]
fn floop() -> (i32, i32) { todo!() }

Like in PostgreSQL, it’s possible to return tables using iterators and the name!() macro:

use pgx::*;
#[pg_extern]
fn floop<'a>() -> TableIterator<'a, (name!(a, i32), name!(b, i32))> {
    TableIterator::new(None.into_iter())
}

#[pg_extern]
fn singular_floop() -> (name!(a, i32), name!(b, i32)) {
    todo!()
}

The name!() macro may only be used in return position inside the T of a TableIterator<'a, T>.

It accepts 2 arguments:

  • A name, such as example
  • A type

Special Cases

pg_sys::Oid is a special cased type alias, in order to use it as an argument or return it must be passed with it’s full module path (pg_sys::Oid) in order to be resolved.

use pgx::*;

#[pg_extern]
fn example_arg(animals: pg_sys::Oid) {
    todo!()
}

#[pg_extern]
fn example_return() -> pg_sys::Oid {
    todo!()
}