Thread: Inconsistency: varchar is equivalent to varchar(255) and also not equivalent?
Inconsistency: varchar is equivalent to varchar(255) and also not equivalent?
From
Boszormenyi Zoltan
Date:
Hi, here is the testcase: create type mytype as (id integer, t varchar(255)); create table mytest (id serial, t1 varchar(255), t2 varchar(255)); create or replace function myfunc () returns setof mytype as $$ begin return query select id, (t1 || t2)::varchar from mytest; end;$$ language plpgsql; Now the problem is: select * from myfunc(); ERROR: structure of query does not match function result type DETAIL: Returned type text does not match expected type character varying(255) in column 2. CONTEXT: PL/pgSQL function "myfunc" line 2 at RETURN QUERY But the types are said to be the same: create cast (varchar as varchar(255)) without function; ERROR: source data type and target data type are the same create cast (varchar as varchar(255)) with inout; ERROR: source data type and target data type are the same This cast already exists: create cast (varchar as varchar(255)) with function pg_catalog.varchar(varchar, integer, boolean); ERROR: cast from type character varying to type character varying already exists I know, explicit cast to ::varchar(255) in the function solves this problem. But I would like to know why isn't the type conversion from unlimited varchar to varchar(255) invoked in the pl/pgsql function? Thanks in advance, Zoltán Böszörményi -- ---------------------------------- Zoltán Böszörményi Cybertec Schönig & Schönig GmbH Gröhrmühlgasse 26 A-2700 Wiener Neustadt, Austria Web: http://www.postgresql-support.de http://www.postgresql.at/
Re: Inconsistency: varchar is equivalent to varchar(255) and also not equivalent?
From
Boszormenyi Zoltan
Date:
2011-10-03 18:12 keltezéssel, Boszormenyi Zoltan írta: > Hi, > > here is the testcase: > > create type mytype as (id integer, t varchar(255)); > create table mytest (id serial, t1 varchar(255), t2 varchar(255)); > create or replace function myfunc () returns setof mytype as $$ > begin > return query select id, (t1 || t2)::varchar from mytest; > end;$$ language plpgsql; > > Now the problem is: > > select * from myfunc(); > ERROR: structure of query does not match function result type > DETAIL: Returned type text does not match expected type character varying(255) in column 2. > CONTEXT: PL/pgSQL function "myfunc" line 2 at RETURN QUERY > > But the types are said to be the same: > > create cast (varchar as varchar(255)) without function; > ERROR: source data type and target data type are the same > > create cast (varchar as varchar(255)) with inout; > ERROR: source data type and target data type are the same > > This cast already exists: > create cast (varchar as varchar(255)) with function pg_catalog.varchar(varchar, integer, > boolean); > ERROR: cast from type character varying to type character varying already exists > > I know, explicit cast to ::varchar(255) in the function solves this problem. > But I would like to know why isn't the type conversion from unlimited varchar > to varchar(255) invoked in the pl/pgsql function? Two additions: create function myfunc1() returns setof varchar(255) as $$ begin return query select (t1 || t2)::varchar from mytest; end;$$ language plpgsql; select * from myfunc1(); myfunc1 --------- (0 rows) create or replace function myfunc2(out id integer, out t varchar(255)) returns setof record as $$ begin return query select mytest.id, (t1 || t2)::varchar from mytest; end;$$ language plpgsql; select * from myfunc2(); id | t ----+--- (0 rows) Only the conversion from anonymous record to composite type causes a problem, individual output parameters or single-value return values get the implicit cast. > > Thanks in advance, > Zoltán Böszörményi > -- ---------------------------------- Zoltán Böszörményi Cybertec Schönig & Schönig GmbH Gröhrmühlgasse 26 A-2700 Wiener Neustadt, Austria Web: http://www.postgresql-support.de http://www.postgresql.at/
Re: Inconsistency: varchar is equivalent to varchar(255) and also not equivalent?
From
Scott Ribe
Date:
On Oct 3, 2011, at 10:12 AM, Boszormenyi Zoltan wrote: > But I would like to know why isn't the type conversion from unlimited varchar > to varchar(255) invoked in the pl/pgsql function? What if t1 || t2 is longer than 255? You need to explicitly specify. -- Scott Ribe scott_ribe@elevated-dev.com http://www.elevated-dev.com/ (303) 722-0567 voice
Re: Inconsistency: varchar is equivalent to varchar(255) and also not equivalent?
From
Alban Hertroys
Date:
On 3 Oct 2011, at 18:12, Boszormenyi Zoltan wrote: > Hi, > > here is the testcase: > > create type mytype as (id integer, t varchar(255)); > create table mytest (id serial, t1 varchar(255), t2 varchar(255)); > create or replace function myfunc () returns setof mytype as $$ > begin > return query select id, (t1 || t2)::varchar from mytest; > end;$$ language plpgsql; > > Now the problem is: > > select * from myfunc(); > ERROR: structure of query does not match function result type > DETAIL: Returned type text does not match expected type character varying(255) in column 2. > CONTEXT: PL/pgSQL function "myfunc" line 2 at RETURN QUERY Yes, of course. It's safe to cast a varchar(255) to a varchar, but the other way around it could get truncated. > But the types are said to be the same: > > create cast (varchar as varchar(255)) without function; > ERROR: source data type and target data type are the same They are the same type, but one version has a length constraint and the other does not. The above is not a safe cast without specifying what to do with varchars that contain more than 255 chars. But... you'realso specifying the cast without function. > create cast (varchar as varchar(255)) with inout; > ERROR: source data type and target data type are the same If I understand the meaning of inout type casts correctly, this also doesn't create a safe type-cast. It doesn't preventaccidental truncating. If that's why the errors occur, they're at least a bit misleading. I can't say I have been creating casts so far, so I'mguessing a bit here. If you create a cast WITH function, does that work? Alban Hertroys -- Screwing up is an excellent way to attach something to the ceiling.
Re: Inconsistency: varchar is equivalent to varchar(255) and also not equivalent?
From
Boszormenyi Zoltan
Date:
2011-10-03 19:17 keltezéssel, Scott Ribe írta: > On Oct 3, 2011, at 10:12 AM, Boszormenyi Zoltan wrote: > >> But I would like to know why isn't the type conversion from unlimited varchar >> to varchar(255) invoked in the pl/pgsql function? > What if t1 || t2 is longer than 255? You need to explicitly specify. Yes, but then explicit casting would be needed everywhere and it's not the case. My question is more like: why the record -> record type conversion doesn't try to match individual elements of the two record types? -- ---------------------------------- Zoltán Böszörményi Cybertec Schönig & Schönig GmbH Gröhrmühlgasse 26 A-2700 Wiener Neustadt, Austria Web: http://www.postgresql-support.de http://www.postgresql.at/
Re: Inconsistency: varchar is equivalent to varchar(255) and also not equivalent?
From
Boszormenyi Zoltan
Date:
2011-10-03 19:31 keltezéssel, Boszormenyi Zoltan írta: > 2011-10-03 18:12 keltezéssel, Boszormenyi Zoltan írta: >> Hi, >> >> here is the testcase: >> >> create type mytype as (id integer, t varchar(255)); >> create table mytest (id serial, t1 varchar(255), t2 varchar(255)); >> create or replace function myfunc () returns setof mytype as $$ >> begin >> return query select id, (t1 || t2)::varchar from mytest; >> end;$$ language plpgsql; >> >> Now the problem is: >> >> select * from myfunc(); >> ERROR: structure of query does not match function result type >> DETAIL: Returned type text does not match expected type character varying(255) in column 2. >> CONTEXT: PL/pgSQL function "myfunc" line 2 at RETURN QUERY >> >> But the types are said to be the same: >> >> create cast (varchar as varchar(255)) without function; >> ERROR: source data type and target data type are the same >> >> create cast (varchar as varchar(255)) with inout; >> ERROR: source data type and target data type are the same >> >> This cast already exists: >> create cast (varchar as varchar(255)) with function pg_catalog.varchar(varchar, integer, >> boolean); >> ERROR: cast from type character varying to type character varying already exists >> >> I know, explicit cast to ::varchar(255) in the function solves this problem. >> But I would like to know why isn't the type conversion from unlimited varchar >> to varchar(255) invoked in the pl/pgsql function? > Two additions: > > create function myfunc1() returns setof varchar(255) as $$ > begin > return query select (t1 || t2)::varchar from mytest; > end;$$ language plpgsql; > > select * from myfunc1(); > myfunc1 > --------- > (0 rows) > > create or replace function myfunc2(out id integer, out t varchar(255)) returns setof > record as $$ > begin > return query select mytest.id, (t1 || t2)::varchar from mytest; > end;$$ language plpgsql; > > select * from myfunc2(); > id | t > ----+--- > (0 rows) > > Only the conversion from anonymous record to composite type > causes a problem, individual output parameters or single-value return > values get the implicit cast. They actually don't. Let's add a row ensuring t1||t2 is longer than 255: =# insert into mytest (t1, t2) values (repeat('a', 250), repeat('b', 250)); INSERT 0 1 =# select length(t1), length(t2) from mytest; length | length --------+-------- 250 | 250 (1 row) =# select length(myfunc1) from myfunc1(); length -------- 500 (1 row) =# select length(t) from myfunc2(); length -------- 500 (1 row) So, although the functions look like they accept and would perform the implicit type conversion, they actually do not. But: =# select 'aaaa'::varchar(3); varchar --------- aaa (1 row) I would expect either the accepted type conversion implicitly truncates or gives me a runtime error just like this below: zozo=# insert into mytest (t1, t2) values (now()::text, ''); INSERT 0 1 zozo=# select t1::timestamp from mytest where id = 2; t1 ---------------------------- 2011-10-03 21:23:52.423667 (1 row) zozo=# select t1::timestamp from mytest; ERROR: invalid input syntax for type timestamp: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" I forgot to report the version: =# select version(); version ----------------------------------------------------------------------------------------------------------------- PostgreSQL 9.0.4 on x86_64-redhat-linux-gnu, compiled by GCC gcc (GCC) 4.6.0 20110530 (Red Hat 4.6.0-9), 64-bit (1 row) This is on Fedora 15. I just checked, it's the same on 9.1.1 compiled fresh. Of course, the explicit type conversion truncates correctly. =# select id, length((t1 || t2)::varchar(255)) from mytest; id | length ----+-------- 1 | 255 2 | 29 (2 rows) Now I start to think that pl/pgsql simply lacks some type checks and should be stricter. -- ---------------------------------- Zoltán Böszörményi Cybertec Schönig & Schönig GmbH Gröhrmühlgasse 26 A-2700 Wiener Neustadt, Austria Web: http://www.postgresql-support.de http://www.postgresql.at/