use sqlx::PgPool;
use umbral::inspect::{IntrospectedSchema, introspect_pool_pg};
use umbral::orm::SqlType;
#[test]
fn pg_pool_typechecks_against_introspect_pool_pg() {
#[allow(dead_code)]
async fn _unreachable(
pg_pool: &PgPool,
) -> Result<IntrospectedSchema, umbral::inspect::InspectError> {
introspect_pool_pg(pg_pool).await
}
}
#[tokio::test]
#[ignore = "needs UMBRAL_TEST_POSTGRES_URL pointing at a Postgres server"]
async fn full_round_trip_against_real_postgres() {
let url = std::env::var("UMBRAL_TEST_POSTGRES_URL")
.expect("UMBRAL_TEST_POSTGRES_URL must be set to run the ignored Postgres test");
let pool = PgPool::connect(&url)
.await
.expect("connect to Postgres at UMBRAL_TEST_POSTGRES_URL");
sqlx::query("DROP TABLE IF EXISTS umbral_phase3_kitchen_sink")
.execute(&pool)
.await
.expect("drop prior table");
sqlx::query(
"CREATE TABLE umbral_phase3_kitchen_sink ( \
id BIGSERIAL PRIMARY KEY, \
small SMALLINT NOT NULL, \
medium INTEGER NOT NULL, \
big BIGINT NOT NULL, \
real_v REAL NOT NULL, \
double_v DOUBLE PRECISION NOT NULL, \
flag BOOLEAN NOT NULL, \
note TEXT NOT NULL, \
varchar_note VARCHAR(64), \
day DATE NOT NULL, \
clock TIME NOT NULL, \
at TIMESTAMP WITH TIME ZONE, \
uid UUID NOT NULL \
)",
)
.execute(&pool)
.await
.expect("create kitchen sink table");
let schema = introspect_pool_pg(&pool)
.await
.expect("introspect_pool_pg should succeed");
let table = schema
.tables
.iter()
.find(|t| t.table == "umbral_phase3_kitchen_sink")
.expect("kitchen sink table should appear in the introspected schema");
let by_name: std::collections::HashMap<&str, &umbral::inspect::IntrospectedColumn> =
table.columns.iter().map(|c| (c.name.as_str(), c)).collect();
let id = by_name.get("id").expect("id column");
assert!(id.primary_key);
assert!(!id.nullable);
assert_eq!(id.ty, SqlType::BigInt);
let cases: &[(&str, SqlType)] = &[
("small", SqlType::SmallInt),
("medium", SqlType::Integer),
("big", SqlType::BigInt),
("real_v", SqlType::Real),
("double_v", SqlType::Double),
("flag", SqlType::Boolean),
("note", SqlType::Text),
("varchar_note", SqlType::Text),
("day", SqlType::Date),
("clock", SqlType::Time),
("at", SqlType::Timestamptz),
("uid", SqlType::Uuid),
];
for (name, ty) in cases {
let col = by_name
.get(name)
.unwrap_or_else(|| panic!("introspection missed `{name}`"));
assert_eq!(col.ty, *ty, "type mismatch on `{name}`: got {:?}", col.ty);
}
assert!(by_name["varchar_note"].nullable, "VARCHAR is nullable");
assert!(by_name["at"].nullable, "timestamptz is nullable");
assert!(!by_name["small"].nullable);
assert!(!by_name["note"].nullable);
}