Skip to content

Commit ee84102

Browse files
authored
A test for UDT/composite_type support (#329)
The test is essentially a cut-n-paste of the long example in the docs.
1 parent 525b442 commit ee84102

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

plrust/src/tests.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,90 @@ mod tests {
12631263

12641264
Ok(())
12651265
}
1266+
1267+
#[pg_test]
1268+
fn test_udt() -> spi::Result<()> {
1269+
Spi::run(
1270+
r#"
1271+
CREATE TYPE person AS (
1272+
name text,
1273+
age float8
1274+
);
1275+
1276+
create function make_person(name text, age float8) returns person
1277+
strict parallel safe
1278+
language plrust as
1279+
$$
1280+
// create the Heap Tuple representation of the SQL type `person`
1281+
let mut p = PgHeapTuple::new_composite_type("person")?;
1282+
1283+
// set a few of its attributes
1284+
//
1285+
// Runtime errors can occur if the attribute name is invalid or if the Rust type of the value
1286+
// is not compatible with the backing SQL type for that attribute. Hence the use of the `?` operator
1287+
p.set_by_name("name", name)?;
1288+
p.set_by_name("age", age)?;
1289+
1290+
// return the `person`
1291+
Ok(Some(p))
1292+
$$;
1293+
1294+
create function get_person_name(p person) returns text
1295+
strict parallel safe
1296+
language plrust as
1297+
$$
1298+
// `p` is a `PgHeapTuple` over the underlying data for `person`
1299+
Ok(p.get_by_name("name")?)
1300+
$$;
1301+
1302+
create function get_person_age(p person) returns float8
1303+
strict parallel safe
1304+
language plrust as
1305+
$$
1306+
// `p` is a `PgHeapTuple` over the underlying data for `person`
1307+
Ok(p.get_by_name("age")?)
1308+
$$;
1309+
1310+
create function get_person_attribute(p person, attname text) returns text
1311+
strict parallel safe
1312+
language plrust as
1313+
$$
1314+
match attname.to_lowercase().as_str() {
1315+
"age" => {
1316+
let age:Option<f64> = p.get_by_name("age")?;
1317+
Ok(age.map(|v| v.to_string()))
1318+
},
1319+
"name" => {
1320+
Ok(p.get_by_name("name")?)
1321+
},
1322+
_ => panic!("unknown attribute: `{attname}`")
1323+
}
1324+
$$;
1325+
1326+
create operator ->> (function = get_person_attribute, leftarg = person, rightarg = text);
1327+
1328+
create table people
1329+
(
1330+
id serial8 not null primary key,
1331+
p person
1332+
);
1333+
1334+
insert into people (p) values (make_person('Johnny', 46.24));
1335+
insert into people (p) values (make_person('Joe', 99.09));
1336+
insert into people (p) values (make_person('Dr. Beverly Crusher of the Starship Enterprise', 32.0));
1337+
"#,
1338+
)?;
1339+
1340+
let johnny = Spi::get_one::<PgHeapTuple<AllocatedByRust>>(
1341+
"SELECT p FROM people WHERE p->>'name' = 'Johnny';",
1342+
)?
1343+
.expect("SPI result was null");
1344+
1345+
let age = johnny.get_by_name::<f64>("age")?.expect("age was null");
1346+
assert_eq!(age, 46.24);
1347+
1348+
Ok(())
1349+
}
12661350
}
12671351

12681352
#[cfg(any(test, feature = "pg_test"))]

0 commit comments

Comments
 (0)