postgres icon indicating copy to clipboard operation
postgres copied to clipboard

Custom Types does not work with DOMAIN

Open Louis-Tian opened this issue 2 years ago • 7 comments

Custom type conversion does not seem to work with Domain.

I want to create a custom id field based on int4, but that id field is to be represented as base32 encoded string in javascript land.

create domain appId as int4 not null;
create table app (
	id appId
);
select oid from pg_catelog.pg_type where typname = 'appId'; // returns 17842
const sql = postgres({
  user: 'postgres',
  pass: 'password',
  types: {
   appId: {
      to: 17842,
      from: [17842],
      serialize: (value: string) => parseInt(value, 32),
      parse: (value: string) => { 
         console.log("parsing") // never invoked
         return parseInt(value).toString(32)
      }
    }
  },
});
console.log(await sql`select id from app`) // -> Result(1) [ { id: 1262438631 } ]

the id will still return as an number because the parse function is never invokes.

Now if we change the 17842 (oid of appId) to 23 (oid of int4), then the parse function does get invoked as expected.

Louis-Tian avatar Nov 03 '23 00:11 Louis-Tian

Found this old thread https://www.postgresql.org/message-id/flat/D71A1574-A772-11D7-913D-0030656EE7B2%40icx.net

Looks like a (IMO bad) decision was made 20 years ago. The RowDescription always uses a baseType oid for domain types.

Louis-Tian avatar Nov 04 '23 01:11 Louis-Tian

As an alternative, I wonder whether if it's possible to expose to the table oid and attribute name returned by the RowDescription in the parser function?

Louis-Tian avatar Nov 04 '23 01:11 Louis-Tian

@Louis-Tian Perhaps we could include these oid "aliases" in the array type fetch? https://github.com/porsager/postgres/blob/61c4d5b1d840ed1e3e0f8e84556544a33ee04149/src/connection.js#L744-L755

I've been wanting to allow setting custom types by name as well, so maybe there's two birds to aim for here :)

porsager avatar Nov 05 '23 12:11 porsager

Ah, wrote to quickly - that of course won't help as we don't get the real oid..

About including the column info in the parser call, that's a great idea! We're already doing that for the transform helpers - I'm gonna add that 👍

porsager avatar Nov 05 '23 12:11 porsager

I think supporting the parser with column information is as simple as adding the column to the function calls at https://github.com/porsager/postgres/blob/61c4d5b1d840ed1e3e0f8e84556544a33ee04149/src/connection.js#L498-L499

But, It's not obvious how to support the same in the serializer, since the serialisation is done on the binding parameters which, if I am not mistaken, is completely context free from table and column it is associated with in the query statement.

There is a fundamental problem. Even if the PostgreSQL does returns the Domain's own oid in the RowDescription, we will still have same problem for serializing it on the way back.

Louis-Tian avatar Nov 06 '23 02:11 Louis-Tian

Hey there, took me a while to figure this out, is it ok if I add a small text on custom types mentioning the problem, this issue and the maillist link https://www.postgresql.org/message-id/flat/D71A1574-A772-11D7-913D-0030656EE7B2%40icx.net ? Would for sure be useful for some people

MaoHolden avatar Aug 06 '24 22:08 MaoHolden

What's up, what about referencing types either by oid or by typname, if its a string then its a typname. Would you be open to a PR for this? I can't find any way to differentiate between my domains currently.

MaoHolden avatar Aug 07 '24 00:08 MaoHolden