demetrixbio / FSharp.Data.Npgsql

F# type providers to support statically typed access to input parameters and result set of sql statement in idiomatic F# way. Data modifications via statically typed tables.
Apache License 2.0
128 stars 15 forks source link

Stored procedure with user-defined data types as parameters #105

Closed NickDarvey closed 2 years ago

NickDarvey commented 2 years ago

This might not be supported, in which case I'll close this. I thought it was worth opening anyway as it might help the next person who goes to try it.

Repro

CREATE TYPE example.my_proc_parameter AS (
  id text
);

CREATE PROCEDURE example.my_proc (
  xs example.my_proc_parameter[]
)
LANGUAGE PLPGSQL
AS
$$
BEGIN

DELETE FROM example.things
WHERE id IN (SELECT id FROM unnest(xs));

END;
$$
;
use sql = conn |> db.CreateCommand<"
  CALL example.my_proc(@x)
">

Expected

I'm able to call sql.AsyncExecute() with an my_proc_parameter array.

Actual

The type provider 'FSharp.Data.Npgsql.NpgsqlProviders' reported an error: Couldn't find PostgreSQL type with OID 16559

However, if we lose the user-defined type and pass built-in types like text, it works. (See details.)

```sql CREATE PROCEDURE example.my_proc ( xs text[] ) LANGUAGE PLPGSQL AS $$ BEGIN DELETE FROM example.things WHERE id IN (SELECT * FROM unnest(xs)); END; $$ ; ```
kerams commented 2 years ago

Custom composite types are not supported because in Npgsql 5 they removed dynamic mapping of types (via ExpandoObject). Nowadays you need to define a class in the assembly for the composite yourself (i.e. this would have to become both an erasing and generative TP). I have no idea how to do that, but if anyone could show me (in a PR here) how to emit a real class and then return an instance of it in an erased method, I'd try do resurrect https://github.com/demetrixbio/FSharp.Data.Npgsql/pull/73.

NickDarvey commented 2 years ago

this would have to become both an erasing and generative TP

This is beyond my skills, but thank you for describing why.