Description
pgx
should be able to handle user defined types (such as those defined via CREATE TYPE...
) in function argument and return value position.
Since user defined types can be created, removed, or altered at runtime, the pgx
extension itself cannot possibly know the structure of the type at build time, thus we cannot possibly create some equivalent Rust type and define a mapping between them.
Instead, pgx
needs to determine that some type is a user defined type, and use some UserDefinedType
type which provides some serde_json::Value
-like interface with runtime safety. We can determine the runtime layout of a type via inspecting the result of a query like \dT+ example.type_name
in psql, there are also methods via SPI through the pg_catalog.pg_type
table.
So if the user defined something like:
#[pgx::pg_extern]
fn user_function(
arg: pgx::UserDefinedType
) -> pgx::UserDefinedType {
unimplemented!();
}
However this doesn't communicate enough information to the SQL generator to create a valid function signature (unless we fall back to something like any
, which is undesirable).
In order to augment this information we could use something like a type!()
macro that operates similar to the name!()
macro. We could also consider having some trait pgx::UserDefinedType
which users could do like:
mod pgx {
pub trait UserDefinedType {
const SQL_TYPE: &'static str;
}
}
struct SomeUserType;
impl pgx::UserDefinedType for SomeUserType {
const SQL_TYPE: &'static str = "MySqlType";
}
#[pg_extern]
fn user_function(
arg: SomeUserType
) -> SomeUserType {
unimplemented!();
}
It's important to note though that the struct
does not (and cannot) map directly to the type, instead, the pgx::UserDefinedType
trait would need to provide methods.