Thread: User defined data type

User defined data type

From
Don Y
Date:
Hi,

I'll hope this is the correct list for these questions... :-/

I need to define several unique data types.  As my "make one
to throw away" exercise, I rewrote the ISBN data type in
the contrib directory (hopefully bringing it "up to date"
as well as adding stricter checks in the parser and shrinking
the INTERNALSIZE of the type).

It seems to work well -- though I have yet to beat on it
with a brass hammer.  :-/

I've tried perusing the documentation looking for a boilerplate
approach to this but haven't yet found one (I'm running 8.0.3).
I notice the 8.2devel docmentation seems to fill in some of the
missing holes (though still not in a straightforward "do this"
template  :-/  )

So, a couple of questions:

- I assume I don't have to check the return value from
   palloc()?  (All of the src/backend/utils datatypes
   seem to trust it implicitly)  BTW, where is the interface
   to palloc() et al. documented (or, is it a case of "Use
   the Source, Luke"?)
- *Somewhere*, I saw a reference claiming functions (and
   the sources thereof?) had to fit in an 8KB "page" (?)
   as they are stored in the database.  But, empirical
   observation seems to refute that (perhaps it was true
   in an older release?)  Are there any such limits?
- Aside from the in and out functions, all I've defined
   for *this* data type are the <, <=, =, >=, >, <> operators
   and a comparison function.  It is my understanding that
   these are needed to support keys/indexes on that data type.
   Is this true?  I.e. if can I discard some of these if I
   am willing to live without keys, etc.?  Are there other
   things that I need to add (or should consider adding)?
- How do I create functions to perform typecasts?  For
   example, *assume* an int4 could be cast to an "isbn"...
   where would that function be implemented?
- This data type contains some redundant information not
   needed for the various operators mentioned above.  Does
   that get in the way of anything?  I.e. it is my understanding
   that the in and out routines are *all* that is needed to
   preserve/transport that "redundant" information to a new
   table/database/etc.
- If not explicitly listed, does the server *assume* things
   like NEGATOR of <= is >?  Or, COMMUTATOR of <= is >=?  Or,
   are these attributes simply "not present" unless explicitly
   defined?
- Can *_in() be ever invoked with a NULL argument?  Or, can I
   safely assume that the pointer I am passed is valid?
- Wish list item:  errdetail(va_list arg) et al. functions (Yeah,
   I can write my own... but it would be nice if this was part
   of the error reporting routines).

If necessary, I could post the source and .sql files but
they may waste a fair bit of bandwidth (about 20KB) -- mainly
due to embedded commentary, etc.

Thanks for any pointers.  And, apologies if this was the
*wrong* list for this post!  :-(

--don

Re: User defined data type

From
Martijn van Oosterhout
Date:
On Thu, Mar 30, 2006 at 11:51:41AM -0700, Don Y wrote:
> - I assume I don't have to check the return value from
>   palloc()?  (All of the src/backend/utils datatypes
>   seem to trust it implicitly)  BTW, where is the interface
>   to palloc() et al. documented (or, is it a case of "Use
>   the Source, Luke"?)

You don't have to check.

src/backend/utils/mmgr/README

> - *Somewhere*, I saw a reference claiming functions (and
>   the sources thereof?) had to fit in an 8KB "page" (?)
>   as they are stored in the database.  But, empirical
>   observation seems to refute that (perhaps it was true
>   in an older release?)  Are there any such limits?

Maybe a long time ago, but not any longer.

> - Aside from the in and out functions, all I've defined
>   for *this* data type are the <, <=, =, >=, >, <> operators
>   and a comparison function.  It is my understanding that
>   these are needed to support keys/indexes on that data type.
>   Is this true?  I.e. if can I discard some of these if I
>   am willing to live without keys, etc.?  Are there other
>   things that I need to add (or should consider adding)?

They're needed for btree indexes. If you don't want them, you don't
need them.

> - How do I create functions to perform typecasts?  For
>   example, *assume* an int4 could be cast to an "isbn"...
>   where would that function be implemented?

Create the function and then use CREATE CAST.

> - This data type contains some redundant information not
>   needed for the various operators mentioned above.  Does
>   that get in the way of anything?  I.e. it is my understanding
>   that the in and out routines are *all* that is needed to
>   preserve/transport that "redundant" information to a new
>   table/database/etc.

Yes. You specify the size or use a varlena structure. PostgreSQL
doesn't try to look inside it.

> - If not explicitly listed, does the server *assume* things
>   like NEGATOR of <= is >?  Or, COMMUTATOR of <= is >=?  Or,
>   are these attributes simply "not present" unless explicitly
>   defined?

Nope, you need to specify, see the CREATE OPERATOR documentation.

> - Can *_in() be ever invoked with a NULL argument?  Or, can I
>   safely assume that the pointer I am passed is valid?

You can't get a NULL there. Yes, the pointer is valid cstring.

> - Wish list item:  errdetail(va_list arg) et al. functions (Yeah,
>   I can write my own... but it would be nice if this was part
>   of the error reporting routines).

Can't help you there.

Tip: there are various README files scattered around the source tree.
Read them.

Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
> tool for doing 5% of the work and then sitting around waiting for someone
> else to do the other 95% so you can sue them.

Attachment

Re: User defined data type

From
Tom Lane
Date:
Martijn van Oosterhout <kleptog@svana.org> writes:
> On Thu, Mar 30, 2006 at 11:51:41AM -0700, Don Y wrote:
>> - Can *_in() be ever invoked with a NULL argument?  Or, can I
>> safely assume that the pointer I am passed is valid?

> You can't get a NULL there. Yes, the pointer is valid cstring.

To be sure about that, make sure you mark the function STRICT
when you define it.  Otherwise you can get burnt by direct user
invocation
    select int4in(null::cstring);
not to mention that we were recently considering letting non-strict
input functions get invoked on nulls in the normal course of events.

            regards, tom lane

Re: User defined data type

From
Don Y
Date:
Martijn van Oosterhout wrote:
> On Thu, Mar 30, 2006 at 11:51:41AM -0700, Don Y wrote:

[snipped questions and answers]

Thanks!

>> - Wish list item:  errdetail(va_list arg) et al. functions (Yeah,
>>   I can write my own... but it would be nice if this was part
>>   of the error reporting routines).
>
> Can't help you there.

No problem.  I can cobble something in.

> Tip: there are various README files scattered around the source tree.
> Read them.

Yeah, I was hoping someone would have built a template for
new types that trimmed everything down to a single page/file
instead of having to snoop the source tree.  :-(

Thanks!
--don

Re: User defined data type

From
Don Y
Date:
Tom Lane wrote:
> Martijn van Oosterhout <kleptog@svana.org> writes:
>> On Thu, Mar 30, 2006 at 11:51:41AM -0700, Don Y wrote:
>>> - Can *_in() be ever invoked with a NULL argument?  Or, can I
>>> safely assume that the pointer I am passed is valid?
>
>> You can't get a NULL there. Yes, the pointer is valid cstring.

Yes, STRICT IMMUTABLE, in my case, so not a problem.

> To be sure about that, make sure you mark the function STRICT
> when you define it.  Otherwise you can get burnt by direct user
> invocation
>     select int4in(null::cstring);
> not to mention that we were recently considering letting non-strict
> input functions get invoked on nulls in the normal course of events.

Thanks!
--don

Re: User defined data type

From
Tom Lane
Date:
Don Y <pgsql@DakotaCom.Net> writes:
> Yeah, I was hoping someone would have built a template for
> new types that trimmed everything down to a single page/file
> instead of having to snoop the source tree.  :-(

The various new types in contrib/ are there in part to serve as models.
You could also look on pgfoundry and gborg to see other examples.

            regards, tom lane

Re: User defined data type

From
Don Y
Date:
Tom Lane wrote:
> Don Y <pgsql@DakotaCom.Net> writes:
>> Yeah, I was hoping someone would have built a template for
>> new types that trimmed everything down to a single page/file
>> instead of having to snoop the source tree.  :-(
>
> The various new types in contrib/ are there in part to serve as models.

Yes, but they don't appear to be maintained.  E.g., I had to stumble
on the proper usage of:

PG_FUNCTION_INFO_V1(foo)
Datum foo(PG_FUNCTION_ARGS)
PG_GETARG_*(#)
PG_RETURN_*(baz)
errdetail
ERRCODE_INVALID_TEXT_REPRESENTATION (vs. the error code used in
the contributed code)

In addition to requiring clarification of the questions posed
previously.

No big deal.  But, it would have saved a little time and
gone a long way towards improving my confidence that my
first implementation would work "as is"...

Obviously, the goal is (should be?) to produce code that can
be contributed back "as is" without having someone spend time
tweeking it to fit the "right" way of doing things.  :-/

I'll see what else I can learn in the remaining data types
that I have to build and then cobble together a template
or an article to hopefully make this a bit more straightforward
(at least so that it tells folks what information they need
to ferret out of man pages, etc.)

> You could also look on pgfoundry and gborg to see other examples.

Ah, haven't even poked around in those areas!  Thnks!
--don