@@ -1263,6 +1263,90 @@ mod tests {
1263
1263
1264
1264
Ok ( ( ) )
1265
1265
}
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
+ }
1266
1350
}
1267
1351
1268
1352
#[ cfg( any( test, feature = "pg_test" ) ) ]
0 commit comments