pgcentralfoundation / pgrx

Build Postgres Extensions with Rust!
Other
3.58k stars 242 forks source link

Add docs on macros #705

Open ccleve opened 2 years ago

ccleve commented 2 years ago

I was looking for a way to specify a different name for a function using #[pg_extern] and could not find documentation on the parameters that it accepts. I eventually found name="some_name" by looking at example code.

It would be nice to have a "usage" page for macros that describes what they do and what parameters they accept.

and any others I've missed.

ccleve commented 2 years ago

I had no idea this existed:

https://docs.rs/pgrx-macros/latest/pgrx_macros/

Really valuable. Should have a link to it in the main readme.

NotGyro commented 7 months ago

After going through our macros and their documentation, I have taken some notes.

In need of documentation improvements:

#[pg_test] - This is mostly well-documented already, except the equivalent to should_panic, which is #[pg_test(error = “expected thing went wrong”)], should be described here. We could potentially also mention that Spi can be called into in this context.

#[derive(PostgresGucEnum)] - Make it clear that GUC is “Grand Unified Configuration, the PostgreSQL subsystem that handles server configuration” i.e. settings you can define in postgresql.conf or “ALTER SYSTEM” or “ALTER DATABASE” command.


#[derive(PostgresType)] - This is mostly already fine except in/out functions should be clearly described as serialize/deserialize functions, since it's easy to see "in/out functions" and assume that's synonymous with "getters and setters".

#[pg_guard] - There is documentation present, but it assumes a lot of background knowledge. Firstly, this can be used on either an extern “C” function or an extern “C” block. Two ways it can be used: Pgrx's bindgen process wraps C functions from Postgres, and pgrx takes care of tedious FFI error handling for calling into Postgres. Rust code can panic and Postgres can panic but Postgres doesn’t throw exceptions using unwinding, it throws exceptions using longjmp. We call a setjmp wrapper at the boundary of Postgres. Rust's model never has two possible points of return from control-flow - Rust cannot comprehend that kind of exception-handling. This wrapper sets up a boundary so that's mutually comprehensible. The OTHER way it can work is passing callbacks that can contain Rust code. It’s an extern “C” function, because Postgres expects the C ABI, but it’s Rust. #[pg_guard] translates exception handling both ways.


#[pg_operator] - The purpose is simple/clear but this macro probably needs more detail on how to use it, since the syntax is not documented (nor has examples provided) at all at the level of the macro itself. Luckily pgrx-examples/operators already exists and is pretty much exactly what we’d want:

#[derive(PostgresType, Serialize, Deserialize, Eq, PartialEq)]
pub struct MyType {
    value: i32,
}

#[pg_operator]
#[opname(=)]
fn my_eq(left: MyType, right: MyType) -> bool {
    left == right
}


#[pg_trigger] This links to postgres docs on trigger functions but doesn’t describe the syntax. pgrx/trigger_support/mod.rs does have much better docs for this macro. Docs are in module comments. These should probably either be rearranged to be on the macro itself, or be copied to reside in both locations.

Already well-documented

#[pg_extern] #[pg_schema]#[derive(PostgresEq)] #[derive(PostgresOrd)]
 #[derive(PostgresHash)] 
#[derive(PostgresEnum)]

Triaged since it's likely to be refactored soon:

#[pg_aggregate] - Has (limited) docs, should explain what it means to have a type be usable by Postgres as an aggregate and also “Functions inside the impl may use the #[pgrx]attribute.” - on the #[pgrx] attribute docs, states “In this position, it takes the same args as #[pg_extern], and those args have the same effect.” This should probably also be on pg_aggregate. “aggregate” is a term usually applied to functions in a postgres context it seems. “Aggregate functions compute a single result from a set of input values.” https://www.postgresql.org/docs/current/functions-aggregate.html What are the requirements for a type with this attribute to compile?

It seems this is mostly documented on the crate_level docs but not in the macro-level docs.

So the struct this trait is implemented on ends up being the state for the aggregate function and the implementation block produces the function.

The name!(ident, Type) macro can be used to set the name of an argument