Function Anatomy

A PL/Rust function is Rust code embedded in an SQL CREATE FUNCTION statement. Behind the scenes, PL/Rust injects the function body into a true Rust function, automatically creating the wrapper function signature along with applying a set of lints.

It's important to understand the surrounding code environment of an individual LANGUAGE plrust function, and this environment is different depending on certain properties of the function itself. The important differences arise around whether the function is declared as STRICT. This is discussed in the STRICT and NULL chapter.

Using a PL/Rust function that converts a TEXT datum to lowercase:


PL/Rust then generates the following Rust code:

fn main() {
mod forbidden {
       use pgrx::prelude::*;
       fn plrust_fn_oid_16384_16404<'a>(
           s: Option<&'a str>,
       ) -> ::std::result::Result<
           Box<dyn std::error::Error + Send + Sync + 'static>,
       > {

mod forbidden {}

Every PL/Rust function is wrapped with this module and cannot be influenced by users. It exists so that PL/Rust can apply lints to the user's code which will detect forbidden code patterns and idioms at compile time.


These are the lints that, if triggered, will fail compilation. These lints are only applied here and are not applied to external dependencies.

use pgrx::prelude::*

A default set of types and traits available to every PL/Rust function. Despite the name, these originate from plrust-trusted-pgrx. plrust-trusted-pgrx is a very small subset of pgrx, the crate upon which PL/Rust and LANGUAGE plrust functions are based.

fn plrust_fn_oid_16384_16404(...) -> ... {}

The function in which the LANGUAGE plrust function body is injected. The naming convention is the literal string plrust_fn_oid_, then the database's OID, an underscore, and the function's OID.

A PL/Rust function author does not need to know this function name and would never have a reason to call it directly, but it's important to know how the name is generated.

Generation of the function's arguments and return type are discussed in more detail in their respective sections.


The function body itself. This is injected, unchanged, directly from the body of the CREATE FUNCTION statement.

It's worth nothing that the function body is parsed for syntactic correctness by the Rust crate syn prior to generating the entire block of code outlined here. This means PL/Rust doesn't rely on the compiler for syntax checking -- it happens up-front. As such, syntax errors may report error messages that are sometimes unhelpful.