pgrx icon indicating copy to clipboard operation
pgrx copied to clipboard

Help returning SetOf PgHeapTuple

Open SiwonP opened this issue 2 months ago • 2 comments

Hello,

I am trying to fiddle with pgrx but I can't figure out how to return a SetOf PgHeapTuple. The primary purpose is to be able to return a SETOF with an unknown number of columns (and unknown column types and name) at compile time. I thought of using Tupdesc like this

#[pg_extern]
fn test() -> SetOfIterator<'static, PgHeapTuple<'static, AllocatedByRust>> {
    // 1) Tuple descriptor
    let tupdesc = unsafe {
        let tupdesc = pg_sys::CreateTemplateTupleDesc(1);
        let cname1 = std::ffi::CString::new("id").unwrap();
        pg_sys::TupleDescInitEntry(tupdesc, 1, cname1.as_ptr(), pg_sys::INT8OID, -1, 0);
        pg_sys::BlessTupleDesc(tupdesc)
    };

    let tupdesc = unsafe { PgTupleDesc::from_pg(tupdesc)};

    let heaptuple = unsafe {
        PgHeapTuple::from_datums(tupdesc, vec![1i64.into_datum()])
            .expect("Fail in PgHeapTuple")
    };
    
    SetOfIterator::new(vec![heaptuple].into_iter())
}   

But I get this :

thread 'main' panicked at /home/simon/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-sql-entity-graph-0.16.1/src/pg_extern/entity/mod.rs:215:128:
called `Option::unwrap()` on a `None` value

with the stack backstrace :

stack backtrace:
   0:     0x5ade6d45a712 - std::backtrace_rs::backtrace::libunwind::trace::h9c1aa7b29a521839
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/../../backtrace/src/backtrace/libunwind.rs:117:9
   1:     0x5ade6d45a712 - std::backtrace_rs::backtrace::trace_unsynchronized::hb123c31478ec901c
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/../../backtrace/src/backtrace/mod.rs:66:14
   2:     0x5ade6d45a712 - std::sys::backtrace::_print_fmt::hdda75a118fd2034a
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/sys/backtrace.rs:66:9
   3:     0x5ade6d45a712 - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::hf435e8e9347709a8
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/sys/backtrace.rs:39:26
   4:     0x5ade6d477723 - core::fmt::rt::Argument::fmt::h9802ea71fd88c728
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/core/src/fmt/rt.rs:173:76
   5:     0x5ade6d477723 - core::fmt::write::h0a51fad3804c5e7c
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/core/src/fmt/mod.rs:1465:25
   6:     0x5ade6d458663 - std::io::default_write_fmt::h7e00b0a8732ee2a2
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/io/mod.rs:639:11
   7:     0x5ade6d458663 - std::io::Write::write_fmt::h9759e4151bf4a45e
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/io/mod.rs:1954:13
   8:     0x5ade6d45a562 - std::sys::backtrace::BacktraceLock::print::h1ec5ce5bb8ee285e
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/sys/backtrace.rs:42:9
   9:     0x5ade6d45b5d6 - std::panicking::default_hook::{{closure}}::h5ffefe997a3c75e4
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/panicking.rs:300:27
  10:     0x5ade6d45b3d9 - std::panicking::default_hook::h820c77ba0601d6bb
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/panicking.rs:327:9
  11:     0x5ade6d45be82 - std::panicking::rust_panic_with_hook::h8b29cbe181d50030
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/panicking.rs:833:13
  12:     0x5ade6d45bce6 - std::panicking::begin_panic_handler::{{closure}}::h9f5b6f6dc6fde83e
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/panicking.rs:699:13
  13:     0x5ade6d45ac09 - std::sys::backtrace::__rust_end_short_backtrace::hd7b0c344383b0b61
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/sys/backtrace.rs:168:18
  14:     0x5ade6d45b9ad - __rustc[5224e6b81cd82a8f]::rust_begin_unwind
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/panicking.rs:697:5
  15:     0x5ade6d369420 - core::panicking::panic_fmt::hc49fc28484033487
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/core/src/panicking.rs:75:14
  16:     0x5ade6d3694ac - core::panicking::panic::h239804395728b21f
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/core/src/panicking.rs:145:5
  17:     0x5ade6d369399 - core::option::unwrap_failed::hec54eb4737b382ca
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/core/src/option.rs:2072:5
  18:     0x5ade6d3fdca5 - core::option::Option<T>::unwrap::h8e15c36271be674f
                               at /home/simon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:1005:21
  19:     0x5ade6d3fdca5 - <pgrx_sql_entity_graph::pg_extern::entity::PgExternEntity as pgrx_sql_entity_graph::to_sql::ToSql>::to_sql::h63418e106595c73e
                               at /home/simon/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-sql-entity-graph-0.16.1/src/pg_extern/entity/mod.rs:215:128
  20:     0x5ade6d3e15a4 - <pgrx_sql_entity_graph::SqlGraphEntity as pgrx_sql_entity_graph::to_sql::ToSql>::to_sql::h035345ed78f6a808
                               at /home/simon/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-sql-entity-graph-0.16.1/src/lib.rs:272:26
  21:     0x5ade6d3ebe05 - pgrx_sql_entity_graph::pgrx_sql::PgrxSql::to_sql::h871cbf5e96970ad4
                               at /home/simon/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-sql-entity-graph-0.16.1/src/pgrx_sql.rs:428:32
  22:     0x5ade6d36d176 - pgrx_sql_entity_graph::pgrx_sql::PgrxSql::to_file::h038075d68f29814f
                               at /home/simon/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-sql-entity-graph-0.16.1/src/pgrx_sql.rs:257:30
  23:     0x5ade6d3723a8 - pgrx_embed_pg_datafusion::pgrx_embed::main::h5baf6284bb804583
                               at /tmp/.tmp8LWM5n:1:1539
  24:     0x5ade6d37090b - core::ops::function::FnOnce::call_once::h82fb2985a4b9ad66
                               at /home/simon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
  25:     0x5ade6d38121e - std::sys::backtrace::__rust_begin_short_backtrace::h9a89f23cb6f95050
                               at /home/simon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/backtrace.rs:152:18
  26:     0x5ade6d379bb1 - std::rt::lang_start::{{closure}}::h51e379f2aa336956
                               at /home/simon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:206:18
  27:     0x5ade6d454a00 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::hf19f6f3c4f0cdb1c
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/core/src/ops/function.rs:284:21
  28:     0x5ade6d454a00 - std::panicking::catch_unwind::do_call::hdc689d1fa1f67ace
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/panicking.rs:589:40
  29:     0x5ade6d454a00 - std::panicking::catch_unwind::h1025d97250558c4b
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/panicking.rs:552:19
  30:     0x5ade6d454a00 - std::panic::catch_unwind::h3f76beef3f07b6dc
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/panic.rs:359:14
  31:     0x5ade6d454a00 - std::rt::lang_start_internal::{{closure}}::haf71a34e0fbc4d76
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/rt.rs:175:24
  32:     0x5ade6d454a00 - std::panicking::catch_unwind::do_call::hbd7dad3d92d409ee
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/panicking.rs:589:40
  33:     0x5ade6d454a00 - std::panicking::catch_unwind::h69749cff2ef3daa8
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/panicking.rs:552:19
  34:     0x5ade6d454a00 - std::panic::catch_unwind::ha18d8f0ab15c4858
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/panic.rs:359:14
  35:     0x5ade6d454a00 - std::rt::lang_start_internal::h31bbb7f936fd6b5d
                               at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/rt.rs:171:5
  36:     0x5ade6d379b97 - std::rt::lang_start::h097ed4613240bdf6
                               at /home/simon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:205:5
  37:     0x5ade6d37256e - main
  38:     0x746c8e22a1ca - __libc_start_call_main
                               at ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
  39:     0x746c8e22a28b - __libc_start_main_impl
                               at ./csu/../csu/libc-start.c:360:3
  40:     0x5ade6d369ce5 - _start
  41:                0x0 - <unknown>

Am i missing something ?

Thanks !

SiwonP avatar Oct 04 '25 07:10 SiwonP

I think what you're trying to do is a bit documented here: https://github.com/pgcentralfoundation/pgrx/blob/2e515ae3fe3d350258ce9cd492ce41a7afcbaaef/pgrx-tests/src/tests/heap_tuple.rs#L558-L577

The issue is that returning SetOfIterator<PgHeapTuple> directly doesn't work because the SQL generator can't determine what composite type name to use in the generated RETURNS SETOF clause, i.e. it panics because ty.composite_type is None.

I'm guessing you can either

  1. Use a named composite type with composite_type!("TypeName") if your structure is known at compile time
  2. Override the SQL with #[pg_extern(sql = "...")] to return SETOF RECORD if columns are truly dynamic

charmitro avatar Oct 04 '25 13:10 charmitro

Thank you for your input, and I am sorry for the late answer ! The idea is that columns are not known at compile time. Hence, I will explore the possibility of returning a SETOF RECORD !

SiwonP avatar Oct 17 '25 09:10 SiwonP