Declare assorted array functions using anycompatible not anyelement.
authorTom Lane <[email protected]>
Wed, 4 Nov 2020 21:09:55 +0000 (16:09 -0500)
committerTom Lane <[email protected]>
Wed, 4 Nov 2020 21:09:55 +0000 (16:09 -0500)
Convert array_append, array_prepend, array_cat, array_position,
array_positions, array_remove, array_replace, and width_bucket
to use anycompatiblearray.  This is a simple extension of commit
5c292e6b9 to hit some other places where there's a pretty obvious
gain in usability from doing so.

Ideally we'd also modify other functions taking multiple old-style
polymorphic arguments.  But most of the remainder are tied into one
or more operator classes, making any such change a much larger can of
worms than I desire to open right now.

Discussion: https://postgr.es/m/77675130-89da-dab1-51dd-492c93dcf5d1@postgresfriends.org

doc/src/sgml/func.sgml
doc/src/sgml/xaggr.sgml
src/include/catalog/catversion.h
src/include/catalog/pg_operator.dat
src/include/catalog/pg_proc.dat
src/test/regress/expected/arrays.out
src/test/regress/expected/polymorphism.out
src/test/regress/sql/arrays.sql
src/test/regress/sql/polymorphism.sql

index 46d6db3cfe01efbee39dd2225e6f9ea5d707f884..7b1dc264f68299395c663391630c5e64f8f30c82 100644 (file)
@@ -1756,7 +1756,7 @@ repeat('Pg', 4) <returnvalue>PgPgPgPg</returnvalue>
 
       <row>
        <entry role="func_table_entry"><para role="func_signature">
-        <function>width_bucket</function> ( <parameter>operand</parameter> <type>anyelement</type>, <parameter>thresholds</parameter> <type>anyarray</type> )
+        <function>width_bucket</function> ( <parameter>operand</parameter> <type>anycompatible</type>, <parameter>thresholds</parameter> <type>anycompatiblearray</type> )
        <returnvalue>integer</returnvalue>
        </para>
        <para>
@@ -17448,29 +17448,31 @@ SELECT NULLIF(value, '(none)') ...
 
       <row>
        <entry role="func_table_entry"><para role="func_signature">
-        <type>anyarray</type> <literal>||</literal> <type>anyarray</type>
-        <returnvalue>anyarray</returnvalue>
+        <type>anycompatiblearray</type> <literal>||</literal> <type>anycompatiblearray</type>
+        <returnvalue>anycompatiblearray</returnvalue>
        </para>
        <para>
         Concatenates the two arrays.  Concatenating a null or empty array is a
         no-op; otherwise the arrays must have the same number of dimensions
         (as illustrated by the first example) or differ in number of
         dimensions by one (as illustrated by the second).
+        If the arrays are not of identical element types, they will be coerced
+        to a common type (see <xref linkend="typeconv-union-case"/>).
        </para>
        <para>
         <literal>ARRAY[1,2,3] || ARRAY[4,5,6,7]</literal>
         <returnvalue>{1,2,3,4,5,6,7}</returnvalue>
        </para>
        <para>
-        <literal>ARRAY[1,2,3] || ARRAY[[4,5,6],[7,8,9]]</literal>
-        <returnvalue>{{1,2,3},{4,5,6},{7,8,9}}</returnvalue>
+        <literal>ARRAY[1,2,3] || ARRAY[[4,5,6],[7,8,9.9]]</literal>
+        <returnvalue>{{1,2,3},{4,5,6},{7,8,9.9}}</returnvalue>
        </para></entry>
       </row>
 
       <row>
        <entry role="func_table_entry"><para role="func_signature">
-        <type>anyelement</type> <literal>||</literal> <type>anyarray</type>
-        <returnvalue>anyarray</returnvalue>
+        <type>anycompatible</type> <literal>||</literal> <type>anycompatiblearray</type>
+        <returnvalue>anycompatiblearray</returnvalue>
        </para>
        <para>
         Concatenates an element onto the front of an array (which must be
@@ -17484,8 +17486,8 @@ SELECT NULLIF(value, '(none)') ...
 
       <row>
        <entry role="func_table_entry"><para role="func_signature">
-        <type>anyarray</type> <literal>||</literal> <type>anyelement</type>
-        <returnvalue>anyarray</returnvalue>
+        <type>anycompatiblearray</type> <literal>||</literal> <type>anycompatible</type>
+        <returnvalue>anycompatiblearray</returnvalue>
        </para>
        <para>
         Concatenates an element onto the end of an array (which must be
@@ -17535,12 +17537,12 @@ SELECT NULLIF(value, '(none)') ...
         <indexterm>
          <primary>array_append</primary>
         </indexterm>
-        <function>array_append</function> ( <type>anyarray</type>, <type>anyelement</type> )
-        <returnvalue>anyarray</returnvalue>
+        <function>array_append</function> ( <type>anycompatiblearray</type>, <type>anycompatible</type> )
+        <returnvalue>anycompatiblearray</returnvalue>
        </para>
        <para>
         Appends an element to the end of an array (same as
-        the <type>anyarray</type> <literal>||</literal> <type>anyelement</type>
+        the <type>anycompatiblearray</type> <literal>||</literal> <type>anycompatible</type>
         operator).
        </para>
        <para>
@@ -17554,12 +17556,12 @@ SELECT NULLIF(value, '(none)') ...
         <indexterm>
          <primary>array_cat</primary>
         </indexterm>
-        <function>array_cat</function> ( <type>anyarray</type>, <type>anyarray</type> )
-        <returnvalue>anyarray</returnvalue>
+        <function>array_cat</function> ( <type>anycompatiblearray</type>, <type>anycompatiblearray</type> )
+        <returnvalue>anycompatiblearray</returnvalue>
        </para>
        <para>
         Concatenates two arrays (same as
-        the <type>anyarray</type> <literal>||</literal> <type>anyarray</type>
+        the <type>anycompatiblearray</type> <literal>||</literal> <type>anycompatiblearray</type>
         operator).
        </para>
        <para>
@@ -17666,7 +17668,7 @@ SELECT NULLIF(value, '(none)') ...
         <indexterm>
          <primary>array_position</primary>
         </indexterm>
-        <function>array_position</function> ( <type>anyarray</type>, <type>anyelement</type> <optional>, <type>integer</type> </optional> )
+        <function>array_position</function> ( <type>anycompatiblearray</type>, <type>anycompatible</type> <optional>, <type>integer</type> </optional> )
         <returnvalue>integer</returnvalue>
        </para>
        <para>
@@ -17688,7 +17690,7 @@ SELECT NULLIF(value, '(none)') ...
         <indexterm>
          <primary>array_positions</primary>
         </indexterm>
-        <function>array_positions</function> ( <type>anyarray</type>, <type>anyelement</type> )
+        <function>array_positions</function> ( <type>anycompatiblearray</type>, <type>anycompatible</type> )
         <returnvalue>integer[]</returnvalue>
        </para>
        <para>
@@ -17712,12 +17714,12 @@ SELECT NULLIF(value, '(none)') ...
         <indexterm>
          <primary>array_prepend</primary>
         </indexterm>
-        <function>array_prepend</function> ( <type>anyelement</type>, <type>anyarray</type> )
-        <returnvalue>anyarray</returnvalue>
+        <function>array_prepend</function> ( <type>anycompatible</type>, <type>anycompatiblearray</type> )
+        <returnvalue>anycompatiblearray</returnvalue>
        </para>
        <para>
         Prepends an element to the beginning of an array (same as
-        the <type>anyelement</type> <literal>||</literal> <type>anyarray</type>
+        the <type>anycompatible</type> <literal>||</literal> <type>anycompatiblearray</type>
         operator).
        </para>
        <para>
@@ -17731,8 +17733,8 @@ SELECT NULLIF(value, '(none)') ...
         <indexterm>
          <primary>array_remove</primary>
         </indexterm>
-        <function>array_remove</function> ( <type>anyarray</type>, <type>anyelement</type> )
-        <returnvalue>anyarray</returnvalue>
+        <function>array_remove</function> ( <type>anycompatiblearray</type>, <type>anycompatible</type> )
+        <returnvalue>anycompatiblearray</returnvalue>
        </para>
        <para>
         Removes all elements equal to the given value from the array.
@@ -17751,8 +17753,8 @@ SELECT NULLIF(value, '(none)') ...
         <indexterm>
          <primary>array_replace</primary>
         </indexterm>
-        <function>array_replace</function> ( <type>anyarray</type>, <type>anyelement</type>, <type>anyelement</type> )
-        <returnvalue>anyarray</returnvalue>
+        <function>array_replace</function> ( <type>anycompatiblearray</type>, <type>anycompatible</type>, <type>anycompatible</type> )
+        <returnvalue>anycompatiblearray</returnvalue>
        </para>
        <para>
         Replaces each array element equal to the second argument with the
index 36c2d21101b9f7c57a02d929b6d6d4fada31ee51..93f1155ab972ee78fd75ae2f0955aacfdd63059c 100644 (file)
@@ -298,10 +298,10 @@ FROM (VALUES (1, 1.0e20::float8),
    Here is an example of a polymorphic aggregate:
 
 <programlisting>
-CREATE AGGREGATE array_accum (anyelement)
+CREATE AGGREGATE array_accum (anycompatible)
 (
     sfunc = array_append,
-    stype = anyarray,
+    stype = anycompatiblearray,
     initcond = '{}'
 );
 </programlisting>
index 77102bab8db4132fe4729b601a8c84305565722c..aa85dc301533ec3377e3366177dda96cf642b41d 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202011043
+#define CATALOG_VERSION_NO 202011044
 
 #endif
index feb8edece5508a81d0396a071a2a6a56225e635a..ede7bb96ab38d0f9177ed8e4e551b280edea32c5 100644 (file)
   oprcode => 'textnename', oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
 
 { oid => '349', descr => 'append element onto end of array',
-  oprname => '||', oprleft => 'anyarray', oprright => 'anyelement',
-  oprresult => 'anyarray', oprcode => 'array_append' },
+  oprname => '||', oprleft => 'anycompatiblearray', oprright => 'anycompatible',
+  oprresult => 'anycompatiblearray', oprcode => 'array_append' },
 { oid => '374', descr => 'prepend element onto front of array',
-  oprname => '||', oprleft => 'anyelement', oprright => 'anyarray',
-  oprresult => 'anyarray', oprcode => 'array_prepend' },
+  oprname => '||', oprleft => 'anycompatible', oprright => 'anycompatiblearray',
+  oprresult => 'anycompatiblearray', oprcode => 'array_prepend' },
 { oid => '375', descr => 'concatenate',
-  oprname => '||', oprleft => 'anyarray', oprright => 'anyarray',
-  oprresult => 'anyarray', oprcode => 'array_cat' },
+  oprname => '||', oprleft => 'anycompatiblearray',
+  oprright => 'anycompatiblearray', oprresult => 'anycompatiblearray',
+  oprcode => 'array_cat' },
 
 { oid => '352', descr => 'equal',
   oprname => '=', oprcanhash => 't', oprleft => 'xid', oprright => 'xid',
index 9acdb28d939059c3edadceb2ae40a8f81fded7a7..c01da4bf01e3a20a5849bad91d4e95fe0e7080fb 100644 (file)
   proname => 'cardinality', prorettype => 'int4', proargtypes => 'anyarray',
   prosrc => 'array_cardinality' },
 { oid => '378', descr => 'append element onto end of array',
-  proname => 'array_append', proisstrict => 'f', prorettype => 'anyarray',
-  proargtypes => 'anyarray anyelement', prosrc => 'array_append' },
+  proname => 'array_append', proisstrict => 'f',
+  prorettype => 'anycompatiblearray',
+  proargtypes => 'anycompatiblearray anycompatible', prosrc => 'array_append' },
 { oid => '379', descr => 'prepend element onto front of array',
-  proname => 'array_prepend', proisstrict => 'f', prorettype => 'anyarray',
-  proargtypes => 'anyelement anyarray', prosrc => 'array_prepend' },
+  proname => 'array_prepend', proisstrict => 'f',
+  prorettype => 'anycompatiblearray',
+  proargtypes => 'anycompatible anycompatiblearray',
+  prosrc => 'array_prepend' },
 { oid => '383',
-  proname => 'array_cat', proisstrict => 'f', prorettype => 'anyarray',
-  proargtypes => 'anyarray anyarray', prosrc => 'array_cat' },
+  proname => 'array_cat', proisstrict => 'f',
+  prorettype => 'anycompatiblearray',
+  proargtypes => 'anycompatiblearray anycompatiblearray',
+  prosrc => 'array_cat' },
 { oid => '394', descr => 'split delimited text',
   proname => 'string_to_array', proisstrict => 'f', prorettype => '_text',
   proargtypes => 'text text', prosrc => 'text_to_array' },
   proargtypes => 'anyarray anyarray', prosrc => 'array_smaller' },
 { oid => '3277', descr => 'returns an offset of value in array',
   proname => 'array_position', proisstrict => 'f', prorettype => 'int4',
-  proargtypes => 'anyarray anyelement', prosrc => 'array_position' },
+  proargtypes => 'anycompatiblearray anycompatible',
+  prosrc => 'array_position' },
 { oid => '3278',
   descr => 'returns an offset of value in array with start index',
   proname => 'array_position', proisstrict => 'f', prorettype => 'int4',
-  proargtypes => 'anyarray anyelement int4', prosrc => 'array_position_start' },
+  proargtypes => 'anycompatiblearray anycompatible int4',
+  prosrc => 'array_position_start' },
 { oid => '3279',
   descr => 'returns an array of offsets of some value in array',
   proname => 'array_positions', proisstrict => 'f', prorettype => '_int4',
-  proargtypes => 'anyarray anyelement', prosrc => 'array_positions' },
+  proargtypes => 'anycompatiblearray anycompatible',
+  prosrc => 'array_positions' },
 { oid => '1191', descr => 'array subscripts generator',
   proname => 'generate_subscripts', prorows => '1000', proretset => 't',
   prorettype => 'int4', proargtypes => 'anyarray int4 bool',
   proargtypes => 'internal', prosrc => 'array_unnest_support' },
 { oid => '3167',
   descr => 'remove any occurrences of an element from an array',
-  proname => 'array_remove', proisstrict => 'f', prorettype => 'anyarray',
-  proargtypes => 'anyarray anyelement', prosrc => 'array_remove' },
+  proname => 'array_remove', proisstrict => 'f',
+  prorettype => 'anycompatiblearray',
+  proargtypes => 'anycompatiblearray anycompatible', prosrc => 'array_remove' },
 { oid => '3168', descr => 'replace any occurrences of an element in an array',
-  proname => 'array_replace', proisstrict => 'f', prorettype => 'anyarray',
-  proargtypes => 'anyarray anyelement anyelement', prosrc => 'array_replace' },
+  proname => 'array_replace', proisstrict => 'f',
+  prorettype => 'anycompatiblearray',
+  proargtypes => 'anycompatiblearray anycompatible anycompatible',
+  prosrc => 'array_replace' },
 { oid => '2333', descr => 'aggregate transition function',
   proname => 'array_agg_transfn', proisstrict => 'f', prorettype => 'internal',
   proargtypes => 'internal anynonarray', prosrc => 'array_agg_transfn' },
 { oid => '3218',
   descr => 'bucket number of operand given a sorted array of bucket lower bounds',
   proname => 'width_bucket', prorettype => 'int4',
-  proargtypes => 'anyelement anyarray', prosrc => 'width_bucket_array' },
+  proargtypes => 'anycompatible anycompatiblearray',
+  prosrc => 'width_bucket_array' },
 { oid => '3816', descr => 'array typanalyze',
   proname => 'array_typanalyze', provolatile => 's', prorettype => 'bool',
   proargtypes => 'internal', prosrc => 'array_typanalyze' },
index f9d9ad6aef904b113de76eeb9f506edfbb8e6800..5abfeb6773bfebe235f54af98df5bd1aa851e448 100644 (file)
@@ -726,6 +726,12 @@ SELECT 0 || ARRAY[1,2] || 3 AS "{0,1,2,3}";
  {0,1,2,3}
 (1 row)
 
+SELECT ARRAY[1.1] || ARRAY[2,3,4];
+  ?column?   
+-------------
+ {1.1,2,3,4}
+(1 row)
+
 SELECT * FROM array_op_test WHERE i @> '{32}' ORDER BY seqno;
  seqno |                i                |                                                                 t                                                                  
 -------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------
@@ -2146,6 +2152,12 @@ select array_remove(array['A','CC','D','C','RR'], 'RR');
  {A,CC,D,C}
 (1 row)
 
+select array_remove(array[1.0, 2.1, 3.3], 1);
+ array_remove 
+--------------
+ {2.1,3.3}
+(1 row)
+
 select array_remove('{{1,2,2},{1,4,3}}', 2); -- not allowed
 ERROR:  removing elements from multidimensional arrays is not supported
 select array_remove(array['X','X','X'], 'X') = '{}';
index 1ff40764d9a1744b9fdfd48e9a7921869642ad3f..2c3bb0a60b0250a7d1ce9dba9acb76b867623a32 100644 (file)
@@ -729,10 +729,10 @@ select q2, sql_if(q2 > 0, q2, q2 + 1) from int8_tbl;
 (5 rows)
 
 -- another sort of polymorphic aggregate
-CREATE AGGREGATE array_cat_accum (anyarray)
+CREATE AGGREGATE array_cat_accum (anycompatiblearray)
 (
     sfunc = array_cat,
-    stype = anyarray,
+    stype = anycompatiblearray,
     initcond = '{}'
 );
 SELECT array_cat_accum(i)
@@ -786,16 +786,16 @@ create aggregate build_group(int8, integer) (
   STYPE = int8[]
 );
 -- check proper resolution of data types for polymorphic transfn/finalfn
-create function first_el(anyarray) returns anyelement as
+create function first_el(anycompatiblearray) returns anycompatible as
 'select $1[1]' language sql strict immutable;
 create aggregate first_el_agg_f8(float8) (
   SFUNC = array_append,
   STYPE = float8[],
   FINALFUNC = first_el
 );
-create aggregate first_el_agg_any(anyelement) (
+create aggregate first_el_agg_any(anycompatible) (
   SFUNC = array_append,
-  STYPE = anyarray,
+  STYPE = anycompatiblearray,
   FINALFUNC = first_el
 );
 select first_el_agg_f8(x::float8) from generate_series(1,10) x;
index 2b689ae88f5988e9f9b87c41c6ce28db1158e4c0..906fd712b718f9108410ae8f6fcbd850b7c746e2 100644 (file)
@@ -311,6 +311,7 @@ SELECT ARRAY[[['hello','world']]] || ARRAY[[['happy','birthday']]] AS "ARRAY";
 SELECT ARRAY[[1,2],[3,4]] || ARRAY[5,6] AS "{{1,2},{3,4},{5,6}}";
 SELECT ARRAY[0,0] || ARRAY[1,1] || ARRAY[2,2] AS "{0,0,1,1,2,2}";
 SELECT 0 || ARRAY[1,2] || 3 AS "{0,1,2,3}";
+SELECT ARRAY[1.1] || ARRAY[2,3,4];
 
 SELECT * FROM array_op_test WHERE i @> '{32}' ORDER BY seqno;
 SELECT * FROM array_op_test WHERE i && '{32}' ORDER BY seqno;
@@ -616,6 +617,7 @@ select array_remove(array[1,2,2,3], 2);
 select array_remove(array[1,2,2,3], 5);
 select array_remove(array[1,NULL,NULL,3], NULL);
 select array_remove(array['A','CC','D','C','RR'], 'RR');
+select array_remove(array[1.0, 2.1, 3.3], 1);
 select array_remove('{{1,2,2},{1,4,3}}', 2); -- not allowed
 select array_remove(array['X','X','X'], 'X') = '{}';
 select array_replace(array[1,2,5,4],5,3);
index e5222f1f81ff5bef7942232475090c8bad4aa188..70a21c8978068895a703f2f0dbde1b3789803228 100644 (file)
@@ -498,10 +498,10 @@ select q2, sql_if(q2 > 0, q2, q2 + 1) from int8_tbl;
 
 -- another sort of polymorphic aggregate
 
-CREATE AGGREGATE array_cat_accum (anyarray)
+CREATE AGGREGATE array_cat_accum (anycompatiblearray)
 (
     sfunc = array_cat,
-    stype = anyarray,
+    stype = anycompatiblearray,
     initcond = '{}'
 );
 
@@ -549,7 +549,7 @@ create aggregate build_group(int8, integer) (
 
 -- check proper resolution of data types for polymorphic transfn/finalfn
 
-create function first_el(anyarray) returns anyelement as
+create function first_el(anycompatiblearray) returns anycompatible as
 'select $1[1]' language sql strict immutable;
 
 create aggregate first_el_agg_f8(float8) (
@@ -558,9 +558,9 @@ create aggregate first_el_agg_f8(float8) (
   FINALFUNC = first_el
 );
 
-create aggregate first_el_agg_any(anyelement) (
+create aggregate first_el_agg_any(anycompatible) (
   SFUNC = array_append,
-  STYPE = anyarray,
+  STYPE = anycompatiblearray,
   FINALFUNC = first_el
 );