pgcentralfoundation / pgrx

Build Postgres Extensions with Rust!
Other
3.71k stars 249 forks source link

Returning an array of Postgres custom types #1860

Closed ccleve closed 2 months ago

ccleve commented 2 months ago

I'm getting an "ERROR: type <my_custom_type> does not exist" when I return a Vec of custom types from a #[pg_extern] function.

I'm guessing I'm just using the wrong syntax, or missing something simple.


#[derive(Serialize, Deserialize, PostgresType, Debug, Clone)]
pub struct MyThing {
    thing: String,
}

#[pg_extern]
fn get_mything() -> MyThing {
    MyThing {
        thing: "hello world".to_string(),
    }
}

#[pg_extern]
fn get_mything_vec() -> Vec<MyThing> {
    let mut my_vec = vec![];
    my_vec.push(MyThing {
        thing: "hello world".to_string(),
    });
    my_vec
}

#[pg_extern]
fn get_numbers_vec() -> Vec<i32> {
    let mut my_vec = vec![];
    my_vec.push(42);
    my_vec
}

Output:

# select rdb.get_mything();
       get_mything       
-------------------------
 {"thing":"hello world"}
(1 row)

# select rdb.get_mything_vec();
ERROR:  type "mything" does not exist

# select rdb.get_numbers_vec();
 get_numbers_vec 
-----------------
 {42}
(1 row)

So, custom types work, and vecs work, but not the combination.

The error message says "mything", lowercase. Maybe it's an uppercase / lowercase thing?

workingjubilee commented 2 months ago
$ cargo pgrx run pg16
       Using CliArgument("pg16") and `pg_config` from /home/jubilee/.pgrx/16.4/pgrx-install/bin/pg_config
    Building extension with features pg16
     Running command "/home/jubilee/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/cargo" "build" "--lib" "--features" "pg16" "--no-default-features" "--message-format=json-render-diagnostics"
   Compiling unicode-width v0.1.13
   Compiling bindgen v0.70.1
   Compiling yansi-term v0.1.2
   Compiling pgrx-sql-entity-graph v0.12.4
   Compiling pgrx-pg-config v0.12.4
   Compiling annotate-snippets v0.9.2
   Compiling pgrx-bindgen v0.12.4
   Compiling pgrx-macros v0.12.4
   Compiling pgrx-pg-sys v0.12.4
   Compiling pgrx v0.12.4
   Compiling my_thing v0.0.0 (/home/jubilee/pgrx/pgrx-examples/my_thing)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 19.03s
  Installing extension
     Copying control file to /home/jubilee/.pgrx/16.4/pgrx-install/share/postgresql/extension/my_thing.control
     Copying shared library to /home/jubilee/.pgrx/16.4/pgrx-install/lib/postgresql/my_thing.so
  Discovered 6 SQL entities: 0 schemas (0 unique), 5 functions, 1 types, 0 enums, 0 sqls, 0 ords, 0 hashes, 0 aggregates, 0 triggers
  Rebuilding pgrx_embed, in debug mode, for SQL generation with features pg16
   Compiling my_thing v0.0.0 (/home/jubilee/pgrx/pgrx-examples/my_thing)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.61s
     Writing SQL entities to /home/jubilee/.pgrx/16.4/pgrx-install/share/postgresql/extension/my_thing--0.0.0.sql
    Finished installing my_thing
    Starting Postgres v16 on port 28816
     Creating database my_thing
psql (16.4)
Type "help" for help.

my_thing=# CREATE EXTENSION my_thing;
CREATE EXTENSION
my_thing=# SELECT get_mything();
       get_mything       
-------------------------
 {"thing":"hello world"}
(1 row)

my_thing=# SELECT get_mything_vec();
         get_mything_vec         
---------------------------------
 {"{\"thing\":\"hello world\"}"}
(1 row)

my_thing=# 

No repro?

ccleve commented 2 months ago

Curious. When I run the code in my main project, I get the error. When I copy the code to a standalone project, it runs fine.

The debugger says that the panic occurs in <... pgrx::datum::into::IntoDatum>::type_oid. I'll have to expand the macro to see what is failing exactly.

I dumped the schema for both projects and see no significant differences. All the MyThing stuff is getting created in the same order.

This requires a bit more investigation.

eeeebbbbrrrr commented 2 months ago

This might be a search_path problem. In fact, this is the exact reason why pgrx supports setting that on the #[pg_extern] definition.

I think you need to make sure functions that use that type include your extension’s schema as part of the search_path.

ccleve commented 2 months ago

Bingo!

I see this in pgrx-examples/arrays/src/lib.rs:

#[pg_extern]
#[search_path(@extschema@)]
fn return_vec_of_customtype() -> Vec<SomeStruct> {
vec![SomeStruct {}]
}

When I add the search_path line it works perfectly.

Dude, it's Sunday. You're a hero.

On Sun, Sep 15, 2024 at 11:41 AM Eric Ridge @.***> wrote:

This might be a search_path problem. In fact, this is the exact reason why pgrx supports setting that on the #[pg_extern] definition.

I think you need to make sure functions that use that type include your extension’s schema as part of the search_path.

— Reply to this email directly, view it on GitHub https://github.com/pgcentralfoundation/pgrx/issues/1860#issuecomment-2351669964, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAITHKWPGKITJMHZYNTWH73ZWW2ERAVCNFSM6AAAAABOFYLNIGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGNJRGY3DSOJWGQ . You are receiving this because you authored the thread.Message ID: @.***>

eeeebbbbrrrr commented 2 months ago

I forget the history around the "why" but there's some reason why our schema machinery can't find your custom type if it's used in a Vec (as a Postgres array of that type).

I don't have it in me today to dig into why, but I feel like it was some kind of legitimate reason from years ago. It could be that things are different in 2024 and now it's just a bug.