typmod is always -1

Started by Pavel Stehulealmost 17 years ago8 messages
#1Pavel Stehule
pavel.stehule@gmail.com

Hello

I am playing with custom typmod. I did simple wrapper over varchar type.

PG_FUNCTION_INFO_V1(mvarcharin);

Datum
mvarcharin(PG_FUNCTION_ARGS)
{
elog(NOTICE, ">>>>>>>>%d", PG_GETARG_INT32(2));
return DirectFunctionCall3(varchar,
DirectFunctionCall3(varcharin,

PG_GETARG_DATUM(0),

PG_GETARG_DATUM(1),

Int32GetDatum(-1)),
PG_GETARG_DATUM(2),
/* original typmod */
BoolGetDatum(true));
/* explit casting, quite truncate */
}

CREATE TYPE mvarchar (
INPUT = mvarcharin,
OUTPUT = mvarcharout,
LIKE = pg_catalog.varchar,
typmod_in = pg_catalog.varchartypmodin,
typmod_out = pg_catalog.varchartypmodout
);

I have a problem - every call of mvarcharin is with typmod = -1.

postgres=# create table x(a mvarchar(3));
CREATE TABLE
Time: 29,930 ms
postgres=# \d x
Table "public.x"
┌────────┬─────────────┬───────────┐
│ Column │ Type │ Modifiers │
├────────┴─────────────┴───────────┤
│ a │ mvarchar(3) │ │
└──────────────────────────────────┘

postgres=# INSERT INTO x values('abcdef');
NOTICE: >>>>>>>>-1
INSERT 0 1
Time: 2,244 ms
postgres=#

can somebody navigate me?

regards
Pavel Stehule

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Pavel Stehule (#1)
Re: typmod is always -1

Pavel Stehule <pavel.stehule@gmail.com> writes:

I have a problem - every call of mvarcharin is with typmod = -1.

Sure your typmod_in function works?

Also, there are a bunch of scenarios where we rely on a cast function to
apply the typmod rather than passing it to the input function initially.
I'm not sure if the particular case you're checking here falls into that
category, but you definitely should have a "length conversion cast"
function in pg_cast if you expect to do anything useful with typmod.

regards, tom lane

#3Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#2)
Re: typmod is always -1

2009/3/17 Tom Lane <tgl@sss.pgh.pa.us>:

Pavel Stehule <pavel.stehule@gmail.com> writes:

I have a problem - every call of mvarcharin is with typmod = -1.

Sure your typmod_in function works?

Also, there are a bunch of scenarios where we rely on a cast function to
apply the typmod rather than passing it to the input function initially.
I'm not sure if the particular case you're checking here falls into that
category, but you definitely should have a "length conversion cast"
function in pg_cast if you expect to do anything useful with typmod.

thank you. It is it.

What I understand, this behave is little bit confusing and undocumented :(

regards
Pavel Stehule

Show quoted text

                       regards, tom lane

#4Chapman Flack
chap@anastigmatix.net
In reply to: Tom Lane (#2)

nothing like resurrecting a really old thread ...

Pavel Stehule <pavel(dot)stehule(at)gmail(dot)com> writes:

I have a problem - every call of mvarcharin is with typmod = -1.

2009/3/17 Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>:

Also, there are a bunch of scenarios where we rely on a cast function to
apply the typmod rather than passing it to the input function initially.
I'm not sure if the particular case you're checking here falls into that
category,

Is it possible to name any case that *does not* fall into that category?

I'm in the same boat ... I have an input function I want to test, and so
far I have failed to think of *any* sql construct that causes it to be
invoked with other than -1 for the typmod.

but you definitely should have a "length conversion cast"
function in pg_cast if you expect to do anything useful with typmod.

Ok, that's good to know (and I didn't until now). But back to the
input and recv functions, which are both documented to have 3-arg
forms that get typmods ... how would one test them? Is there any
sql syntax that can be written to make them get passed a typmod?

If I just write them with assert(typmod == -1), will anyone ever
see a failure?

-Chap

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Chapman Flack (#4)
Re: typmod is always -1

Chapman Flack <chap@anastigmatix.net> writes:

I'm in the same boat ... I have an input function I want to test, and so
far I have failed to think of *any* sql construct that causes it to be
invoked with other than -1 for the typmod.

COPY was the first case a quick grep came across.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#6Chapman Flack
chap@anastigmatix.net
In reply to: Tom Lane (#5)
Re: typmod is always -1

On 03/17/16 09:35, Tom Lane wrote:

Chapman Flack <chap@anastigmatix.net> writes:

I'm in the same boat ... I have an input function I want to test, and so
far I have failed to think of *any* sql construct that causes it to be
invoked with other than -1 for the typmod.

COPY was the first case a quick grep came across.

Thanks, that does make a working test. Given a table with a typmod'd
column, COPY FROM exercises the 'input' function with a typmod != -1,
and COPY FROM (FORMAT BINARY) likewise exercises the 'receive' function.

While I'm here, I guess I should check the sense I am getting of what
can and can't be workable semantics for type modifiers.

It seems that a typmod can only be used restrict the set of possible
values of the unmodified type (as clearly seen in the language "length
conversion cast", since certainly a typmod allowing { string | length < N }
is doing nothing but enforcing a subset of { string }. Each element of
the subset is still a valid element of the whole set (naturally, boring)
*and has to be represented the same way* (interesting): the representation
mustn't do clever things that you would need to know the typmod in order to
interpret, because most uses of a value are without access to the typmod.

So, the generalization of "length conversion cast" could be something like
"typmod application cast" and the only things a typmod application cast can
do to a value V are:

1. pass V unchanged if it is in the subset implied by the typmod
2. silently pass some V' that is in that subset and "close to" V
in some sense (longest initial substring shorter than N, nearest
numeric value with no more than N precision digits, etc.)
3. fail

with sometimes the choice of (2) or (3) depending on whether the cast
is explicit or not.

All in all, very like a domain, except a domain can only do (1) or (3),
not (2).

Differences in representation, like short strings getting 1-byte headers,
are only possible as a consequence of a lower layer doing that consistently
to all values that happen to be short, and not as an effect of a typmod.

Am I getting it about right?

-Chap

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Chapman Flack (#6)
Re: typmod is always -1

Chapman Flack <chap@anastigmatix.net> writes:

It seems that a typmod can only be used restrict the set of possible
values of the unmodified type (as clearly seen in the language "length
conversion cast", since certainly a typmod allowing { string | length < N }
is doing nothing but enforcing a subset of { string }. Each element of
the subset is still a valid element of the whole set (naturally, boring)
*and has to be represented the same way* (interesting): the representation
mustn't do clever things that you would need to know the typmod in order to
interpret, because most uses of a value are without access to the typmod.

You do need to be able to interpret values of the type without having
separate access to the typmod, but I don't think it follows that it's as
restrictive as you say. One easy way around that is to store the typmod
in the value.

Practical uses might include compressing the data in different ways
depending on typmod. I'm drawing a blank on other compelling examples
though I'm sure there are some. Have you looked at PostGIS? I'm pretty
sure some of their types make use of typmod in nontrivial ways.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#8Jim Nasby
Jim.Nasby@BlueTreble.com
In reply to: Tom Lane (#7)
Re: typmod is always -1

On 3/17/16 7:40 PM, Tom Lane wrote:

Chapman Flack <chap@anastigmatix.net> writes:

It seems that a typmod can only be used restrict the set of possible
values of the unmodified type (as clearly seen in the language "length
conversion cast", since certainly a typmod allowing { string | length < N }
is doing nothing but enforcing a subset of { string }. Each element of
the subset is still a valid element of the whole set (naturally, boring)
*and has to be represented the same way* (interesting): the representation
mustn't do clever things that you would need to know the typmod in order to
interpret, because most uses of a value are without access to the typmod.

You do need to be able to interpret values of the type without having
separate access to the typmod, but I don't think it follows that it's as
restrictive as you say. One easy way around that is to store the typmod
in the value.

Practical uses might include compressing the data in different ways
depending on typmod. I'm drawing a blank on other compelling examples
though I'm sure there are some. Have you looked at PostGIS? I'm pretty
sure some of their types make use of typmod in nontrivial ways.

If you want a non-trivial use of typmod, take a look at the (work in
progress) variant type I created[1]https://github.com/BlueTreble/variant/blob/master/doc/variant.md#variant-modifier -- Jim Nasby, Data Architect, Blue Treble Consulting, Austin TX Experts in Analytics, Data Architecture and PostgreSQL Data in Trouble? Get it in Treble! http://BlueTreble.com. It allows you pass names of
"registered variants" in via typmod. The idea behind that is to restrict
what types you can actually store in a particular variant field (though
you can also disallow a registered variant from being used in a table
definition).

I did run into some cases where Postgres ignored typmod, so I special
case the default typmod (-1) to a registered variant that's disabled.

[1]: https://github.com/BlueTreble/variant/blob/master/doc/variant.md#variant-modifier -- Jim Nasby, Data Architect, Blue Treble Consulting, Austin TX Experts in Analytics, Data Architecture and PostgreSQL Data in Trouble? Get it in Treble! http://BlueTreble.com
https://github.com/BlueTreble/variant/blob/master/doc/variant.md#variant-modifier
--
Jim Nasby, Data Architect, Blue Treble Consulting, Austin TX
Experts in Analytics, Data Architecture and PostgreSQL
Data in Trouble? Get it in Treble! http://BlueTreble.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers