Thread: analyze-error: "cannot compare arrays of different element types" revisited

analyze-error: "cannot compare arrays of different element types" revisited

From
"Florian G. Pflug"
Date:
Hi

A few weeks ago, I reported that ANALYZE gives the error
"cannot compare arrays of different element types"
in one of my databases.

I now constructed a small testcase that is able to reproduce the problem:
---------------------------------------------------------------------------
-- The database was created as:
-- create database array_testcase with owner fgp encoding 'utf-8' ;

-- We use the "-" - operator from contrib/intarray
-- For testing, we just import the "-" operator,
-- not everything from contrib/intarray
create function intarray_del_elem(int4[], int4)
   returns int[]
   as '$libdir/_int' language 'c' with (isStrict, isCachable)
;

create operator - (
    leftarg = int4[],
    rightarg = int4,
    procedure = intarray_del_elem
);

-- Create two domains and a table.
create domain myint as int8 ;
create domain mylist as int8[] ;
create table mytable (value myint, list mylist) ;

-- Insert testdata
insert into mytable values (1::myint, array[1]::mylist) ;
insert into mytable values (2::myint, array[2]::mylist) ;
select * from mytable ;

-- Generate empty array
update mytable set list = list::int4[] - 1::myint::int4 where value =
1::myint ;
select * from mytable ;

-- Reinsert element
update mytable set list = (list::int8[] || 1::myint::int8) where value =
1::myint;

-- It's broken now (Strange large numbers)
select * from mytable ;

-- This gives "ERROR:  cannot compare arrays of different element types"
analyze mytable ;

-- Drop everything
drop table mytable ;
drop domain mylist ;
drop domain myint ;
drop operator - (int4[], int4) ;
drop function intarray_del_elem(int4[], int4) ;
---------------------------------------------------------------------------

Note that this is quite hackish, and I realize it will fail if the
entries of mylist grow beyong 2^31-1, but I guess it still shouldn't
make anaylze fail, or produce random numbers ;-)

Since postgres disallows empty array literals (array[] gives an syntax
error), I guess creating empty array by removing the last element is
quite hackish too... Will empty arrays be eventually supported, or will
they be forbidden entirely (e.g, making "array[1] - 1" return null)?

greetings, Florian Pflug

Attachment

Re: analyze-error: "cannot compare arrays of different

From
"Florian G. Pflug"
Date:
Florian G. Pflug wrote:
> A few weeks ago, I reported that ANALYZE gives the error
> "cannot compare arrays of different element types"
> in one of my databases.
>
> I now constructed a small testcase that is able to reproduce the problem:
> ---------------------------------------------------------------------------
<snipped my testcase>
> ---------------------------------------------------------------------------

Sorry for replying to myself - I forgot to mention, that the problem
occurs on 7.4.5, 7.4.6 and 8.0.0beta5. I haven't try 8.0.0rc1, or any
Version prior to 7.4.5

greetings, Florian Pflug

Attachment
"Florian G. Pflug" <fgp@phlo.org> writes:
> A few weeks ago, I reported that ANALYZE gives the error
> "cannot compare arrays of different element types"
> in one of my databases.

> I now constructed a small testcase that is able to reproduce the problem:

Thanks for the example.  It turns out array_map() thought it could just
return an empty input array unmodified, so the implicit coercion from
int4[] to int8[] didn't do what it was supposed to, and then things go
downhill :-(.  array_map() was correct when it was written, but it
didn't get updated properly when we added type OIDs to array headers.
Here's the patch against 7.4, if you need it.

            regards, tom lane

Index: arrayfuncs.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v
retrieving revision 1.100.2.1
diff -c -r1.100.2.1 arrayfuncs.c
*** arrayfuncs.c    8 Jun 2004 20:28:29 -0000    1.100.2.1
--- arrayfuncs.c    17 Dec 2004 20:48:49 -0000
***************
*** 2063,2069 ****

      /* Check for empty array */
      if (nitems <= 0)
!         PG_RETURN_ARRAYTYPE_P(v);

      /*
       * We arrange to look up info about input and return element types
--- 2063,2075 ----

      /* Check for empty array */
      if (nitems <= 0)
!     {
!         /* Return empty array */
!         result = (ArrayType *) palloc0(sizeof(ArrayType));
!         result->size = sizeof(ArrayType);
!         result->elemtype = retType;
!         PG_RETURN_ARRAYTYPE_P(result);
!     }

      /*
       * We arrange to look up info about input and return element types

"Florian G. Pflug" <fgp@phlo.org> writes:
> Since postgres disallows empty array literals (array[] gives an syntax
> error), I guess creating empty array by removing the last element is
> quite hackish too... Will empty arrays be eventually supported, or will
> they be forbidden entirely (e.g, making "array[1] - 1" return null)?

They're supported now, but you have to write something like
    '{}'::int8[]
since "array[]" doesn't provide any context for guessing the intended
array element type.

            regards, tom lane