Thread: BUG #1532: typecast problem between arrays of an int8 derived datatype and varchar[]
BUG #1532: typecast problem between arrays of an int8 derived datatype and varchar[]
From
"Ezequiel Tolnay"
Date:
The following bug has been logged online: Bug reference: 1532 Logged by: Ezequiel Tolnay Email address: mail@etolnay.com.ar PostgreSQL version: 8.0.1 Operating system: Windows 2003 Server Description: typecast problem between arrays of an int8 derived datatype and varchar[] Details: I've created the cardnumber_t datatype, which is an int8, to provide implicit typecasting with varchar padding the result with zeroes. Conversions work as expected between int4, int8, cardnumber_t and varchar. They also work fine between int4[], int8[] and cardnumber_t[], but when an attempt is made to convert a cardnumber_t[] to a varchar[], the connection is dropped. The code used to create the cardnumber_t is the following: CREATE OR REPLACE FUNCTION cardnumber_t_in(cstring) RETURNS cardnumber_t AS 'int8in' LANGUAGE INTERNAL IMMUTABLE WITH (isstrict); CREATE OR REPLACE FUNCTION cardnumber_t_out(cardnumber_t) RETURNS cstring AS 'int8out' LANGUAGE INTERNAL IMMUTABLE WITH (isstrict); CREATE TYPE cardnumber_t ( INTERNALLENGTH = 8, INPUT = cardnumber_t_in, OUTPUT = cardnumber_t_out, STORAGE = plain, ALIGNMENT = double ); CREATE OR REPLACE FUNCTION to_int8(cardnumber_t) RETURNS int8 AS 'int8up' LANGUAGE INTERNAL IMMUTABLE WITH (isstrict); CREATE CAST (cardnumber_t AS int8) WITH FUNCTION to_int8(cardnumber_t) AS IMPLICIT; CREATE OR REPLACE FUNCTION to_cardnumber_t(int8) RETURNS cardnumber_t AS 'int8up' LANGUAGE INTERNAL IMMUTABLE WITH (isstrict); CREATE CAST (int8 AS cardnumber_t) WITH FUNCTION to_cardnumber_t(int8) AS IMPLICIT; CREATE OR REPLACE FUNCTION to_cardnumber_t(int4) RETURNS cardnumber_t AS 'int48' LANGUAGE INTERNAL IMMUTABLE WITH (isstrict); CREATE CAST (int4 AS cardnumber_t) WITH FUNCTION to_cardnumber_t(int4) AS IMPLICIT; CREATE DOMAIN cardnumber AS cardnumber_t CONSTRAINT ch_cardnumber_range CHECK (VALUE between 1 AND 9999999999999999); CREATE OR REPLACE FUNCTION fc_cardnumber_t_to_varchar (cn cardnumber_t) RETURNS varchar AS $$ BEGIN RETURN substring((10000000000000000::int8+cn)::varchar, 2, 16); END; $$ LANGUAGE plpgsql; CREATE CAST (cardnumber_t as varchar) WITH FUNCTION fc_cardnumber_t_to_varchar(cardnumber_t) AS IMPLICIT; The following are successful typecast tests: SELECT 10::int4::int8::cardnumber_t::varchar SELECT ((ARRAY[1,2,3])::int8[])::cardnumber_t[] The following fails and drops the connection SELECT ((ARRAY[1,2,3])::cardnumber_t[])::varchar[]
Re: BUG #1532: typecast problem between arrays of an int8 derived datatype and varchar[]
From
Tom Lane
Date:
"Ezequiel Tolnay" <mail@etolnay.com.ar> writes: > I've created the cardnumber_t datatype, which is an int8, to provide > implicit typecasting with varchar padding the result with zeroes. > Conversions work as expected between int4, int8, cardnumber_t and varchar. > They also work fine between int4[], int8[] and cardnumber_t[], but when an > attempt is made to convert a cardnumber_t[] to a varchar[], the connection > is dropped. What's going on here is that array_map thinks it can use fn_extra of the passed FmgrInfo for its own purposes. That means that if the function to be called tries to use fn_extra for *its* own purposes, we have a conflict that is going to lead to core dumps in most cases. In other words, array_map pretty much doesn't work for calling anything except built-in functions. I think the best solution to this is to require array_map's caller to provide the state storage array_map wants, instead of doing it locally. Both of the existing callers can easily incorporate array_map's state data into their own state structs. Joe, you have any better ideas? regards, tom lane
Tom Lane wrote: > "Ezequiel Tolnay" <mail@etolnay.com.ar> writes: >>I've created the cardnumber_t datatype, which is an int8, to provide >>implicit typecasting with varchar padding the result with zeroes. >>Conversions work as expected between int4, int8, cardnumber_t and varchar. >>They also work fine between int4[], int8[] and cardnumber_t[], but when an >>attempt is made to convert a cardnumber_t[] to a varchar[], the connection >>is dropped. > > What's going on here is that array_map thinks it can use fn_extra of the > passed FmgrInfo for its own purposes. That means that if the function > to be called tries to use fn_extra for *its* own purposes, we have a > conflict that is going to lead to core dumps in most cases. In other > words, array_map pretty much doesn't work for calling anything except > built-in functions. > > I think the best solution to this is to require array_map's caller to > provide the state storage array_map wants, instead of doing it locally. > Both of the existing callers can easily incorporate array_map's state > data into their own state structs. Joe, you have any better ideas? > That certainly looks like the least invasive fix for 8.0.x and 7.4.x. I have thought before that we were overloading fn_extra a bit too much. Is there any merit in having more than one "extra" member in FmgrInfo going forward? Joe
Re: BUG #1532: typecast problem between arrays of an int8 derived datatype and varchar[]
From
Tom Lane
Date:
Joe Conway <mail@joeconway.com> writes: > I have thought before that we were overloading fn_extra a bit too much. > Is there any merit in having more than one "extra" member in FmgrInfo > going forward? Not sure what --- how would you decide which to use, and what stops there being a conflict on one of them anyway? The basic rule is that "fn_extra belongs to the called function", and array_map was definitely breaking that rule. So I don't think this bug is a symptom of a system-wide issue. regards, tom lane