use pgx::prelude::*;
#[pgx::pg_schema]
mod test_schema {
use pgx::pgx_sql_entity_graph::{PgxSql, SqlGraphEntity};
use pgx::prelude::*;
use serde::{Deserialize, Serialize};
#[pg_extern]
fn func_in_diff_schema() {}
#[pg_extern(sql = false)]
fn func_elided_from_schema() {}
#[pg_extern(sql = generate_function)]
fn func_generated_with_custom_sql() {}
#[derive(Debug, PostgresType, Serialize, Deserialize)]
pub struct TestType(pub u64);
#[derive(Debug, PostgresType, Serialize, Deserialize)]
#[pgx(sql = false)]
pub struct ElidedType(pub u64);
#[derive(Debug, PostgresType, Serialize, Deserialize)]
#[pgx(sql = generate_type)]
pub struct OtherType(pub u64);
#[derive(Debug, PostgresType, Serialize, Deserialize)]
#[pgx(sql = "CREATE TYPE test_schema.ManuallyRenderedType;")]
pub struct OverriddenType(pub u64);
fn generate_function(
entity: &SqlGraphEntity,
_context: &PgxSql,
) -> Result<String, Box<dyn std::error::Error + Send + Sync + 'static>> {
if let SqlGraphEntity::Function(ref func) = entity {
Ok(format!(
"\
CREATE FUNCTION test_schema.\"func_generated_with_custom_name\"() RETURNS void\n\
LANGUAGE c /* Rust */\n\
AS 'MODULE_PATHNAME', '{unaliased_name}_wrapper';\
",
unaliased_name = func.name,
))
} else {
panic!("expected extern function entity, got {:?}", entity);
}
}
fn generate_type(
entity: &SqlGraphEntity,
_context: &PgxSql,
) -> Result<String, Box<dyn std::error::Error + Send + Sync + 'static>> {
if let SqlGraphEntity::Type(ref ty) = entity {
Ok(format!(
"\n\
CREATE TYPE test_schema.Custom{name};\
",
name = ty.name,
))
} else {
panic!("expected type entity, got {:?}", entity);
}
}
}
#[pg_extern(schema = "test_schema")]
fn func_in_diff_schema2() {}
#[pg_extern]
fn type_in_diff_schema() -> test_schema::TestType {
test_schema::TestType(1)
}
#[cfg(any(test, feature = "pg_test"))]
#[pgx::pg_schema]
mod tests {
#[allow(unused_imports)]
use crate as pgx_tests;
use pgx::prelude::*;
#[pg_test]
fn test_in_different_schema() {
Spi::run("SELECT test_schema.func_in_diff_schema();").expect("SPI failed");
}
#[pg_test]
fn test_in_different_schema2() {
Spi::run("SELECT test_schema.func_in_diff_schema2();").expect("SPI failed");
}
#[pg_test]
fn test_type_in_different_schema() {
Spi::run("SELECT type_in_diff_schema();").expect("SPI failed");
}
#[pg_test]
fn elided_extern_is_elided() {
let result = Spi::get_one::<bool>(
"SELECT exists(SELECT 1 FROM pg_proc WHERE proname = 'func_in_diff_schema');",
);
assert_eq!(result, Ok(Some(true)));
let result = Spi::get_one::<bool>(
"SELECT exists(SELECT 1 FROM pg_proc WHERE proname = 'func_elided_from_schema');",
);
assert_eq!(result, Ok(Some(false)));
}
#[pg_test]
fn elided_type_is_elided() {
let result = Spi::get_one::<bool>(
"SELECT exists(SELECT 1 FROM pg_type WHERE typname = 'testtype');",
);
assert_eq!(result, Ok(Some(true)));
let result = Spi::get_one::<bool>(
"SELECT exists(SELECT 1 FROM pg_type WHERE typname = 'elidedtype');",
);
assert_eq!(result, Ok(Some(false)));
}
#[pg_test]
fn custom_to_sql_extern() {
let result = Spi::get_one::<bool>("SELECT exists(SELECT 1 FROM pg_proc WHERE proname = 'func_generated_with_custom_name');");
assert_eq!(result, Ok(Some(true)));
Spi::run("SELECT test_schema.func_generated_with_custom_name();").expect("SPI failed");
}
#[pg_test]
fn custom_to_sql_type() {
let result = Spi::get_one::<bool>(
"SELECT exists(SELECT 1 FROM pg_type WHERE typname = 'customothertype');",
);
assert_eq!(result, Ok(Some(true)));
}
#[pg_test]
fn custom_handwritten_to_sql_type() {
let result = Spi::get_one::<bool>(
"SELECT exists(SELECT 1 FROM pg_type WHERE typname = 'manuallyrenderedtype');",
);
assert_eq!(result, Ok(Some(true)));
}
}