Re: Composite type versus Domain constraints. - Mailing list pgsql-general

From Tom Lane
Subject Re: Composite type versus Domain constraints.
Date
Msg-id 7708.1113407441@sss.pgh.pa.us
Whole thread Raw
In response to Re: Composite type versus Domain constraints.  (James Robinson <jlrobins@socialserve.com>)
Responses Re: Composite type versus Domain constraints.
List pgsql-general
James Robinson <jlrobins@socialserve.com> writes:
> Thank you for the great info. If I may, here's another question. I am in
> the need of new scalar types, essentially domain'd smallints, hence
> why my composite type had but one composite member. Domain'd
> smallints would be great, but it seems when they get returned in a
> result set to the client, they come shipped with the oid of smallint
> (21 on my box), not the oid of the domain.

Yeah.  IIRC that was a deliberate decision on the grounds that most
client software would probably break if we sent the domain OID.
Maybe we should reconsider, but I think the answer would be the same.

> Is there an easy path to creating (many) scalar types which piggyback
> on int2's functions. Naive experimentation fails:

> social=# create type MyType (
>      INTERNALLENGTH = 2,
>      INPUT = int2in,
>     OUTPUT = int2out
> );
> ERROR:  function int2out(mytype) does not exist

> Which is reasonable.

What you'd have to do is also create dummy I/O functions as aliases
for the internal int2in/out functions.

regression=# create function mytypein(cstring) returns mytype
regression-# as 'int2in' language internal strict immutable;
NOTICE:  type "mytype" is not yet defined
DETAIL:  Creating a shell type definition.
CREATE FUNCTION
regression=# create function mytypeout(mytype) returns cstring
regression-# as 'int2out' language internal strict immutable;
NOTICE:  argument type mytype is only a shell
CREATE FUNCTION
regression=# create type mytype( input = mytypein, output = mytypeout,
regression(# internallength = 2, passedbyvalue, alignment = int2 );
CREATE TYPE
regression=# select '42'::mytype;
 mytype
--------
 42
(1 row)

regression=#

Note that it's absolutely critical that you get the size/alignment/byval
properties right ;-)

With suitable casts to/from int2 (probably implicit to int2, but not
implicit from), this would probably work fairly well.

regression=# select '42'::mytype + '42'::mytype;
ERROR:  operator does not exist: mytype + mytype
HINT:  No operator matches the given name and argument type(s). You may need to add explicit type casts.
regression=# create cast (mytype as int2) without function as implicit;
CREATE CAST
regression=# select '42'::mytype + '42'::mytype;
 ?column?
----------
       84
(1 row)

regression=# create table zit(f1 mytype primary key);
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "zit_pkey" for table "zit"
CREATE TABLE
regression=# \d zit
     Table "public.zit"
 Column |  Type  | Modifiers
--------+--------+-----------
 f1     | mytype | not null
Indexes:
    "zit_pkey" PRIMARY KEY, btree (f1 int2_ops)

regression=#

Sweet ... I wasn't actually expecting the index to work without more
hacking than that ...

            regards, tom lane

pgsql-general by date:

Previous
From: Ying Lu
Date:
Subject: About ERROR: could not convert UTF-8 character 0x00e9 to ISO8859-1
Next
From: Alvaro Herrera
Date:
Subject: Re: psql vs perl prepared inserts