Обсуждение: 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[]
От
 
		    	"Ezequiel Tolnay"
		    Дата:
		        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[]
"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
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