diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-11-04 16:09:55 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-11-04 16:09:55 -0500 |
commit | 9e38c2bb5093ceb0c04d6315ccd8975bd17add66 (patch) | |
tree | 78afafa32e3f4a615281401b37890ac4775dfffc | |
parent | 5c292e6b90433c760a3e15027646c7b94afd0cdd (diff) | |
download | postgresql-9e38c2bb5093ceb0c04d6315ccd8975bd17add66.tar.gz postgresql-9e38c2bb5093ceb0c04d6315ccd8975bd17add66.zip |
Declare assorted array functions using anycompatible not anyelement.
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
-rw-r--r-- | doc/src/sgml/func.sgml | 50 | ||||
-rw-r--r-- | doc/src/sgml/xaggr.sgml | 4 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_operator.dat | 13 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.dat | 40 | ||||
-rw-r--r-- | src/test/regress/expected/arrays.out | 12 | ||||
-rw-r--r-- | src/test/regress/expected/polymorphism.out | 10 | ||||
-rw-r--r-- | src/test/regress/sql/arrays.sql | 2 | ||||
-rw-r--r-- | src/test/regress/sql/polymorphism.sql | 10 |
9 files changed, 86 insertions, 57 deletions
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 46d6db3cfe0..7b1dc264f68 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -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 diff --git a/doc/src/sgml/xaggr.sgml b/doc/src/sgml/xaggr.sgml index 36c2d21101b..93f1155ab97 100644 --- a/doc/src/sgml/xaggr.sgml +++ b/doc/src/sgml/xaggr.sgml @@ -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> diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 77102bab8db..aa85dc30153 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202011043 +#define CATALOG_VERSION_NO 202011044 #endif diff --git a/src/include/catalog/pg_operator.dat b/src/include/catalog/pg_operator.dat index feb8edece55..ede7bb96ab3 100644 --- a/src/include/catalog/pg_operator.dat +++ b/src/include/catalog/pg_operator.dat @@ -168,14 +168,15 @@ 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', diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 9acdb28d939..c01da4bf01e 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -1548,14 +1548,19 @@ 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' }, @@ -1587,15 +1592,18 @@ 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', @@ -1620,11 +1628,14 @@ 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' }, @@ -1650,7 +1661,8 @@ { 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' }, diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out index f9d9ad6aef9..5abfeb6773b 100644 --- a/src/test/regress/expected/arrays.out +++ b/src/test/regress/expected/arrays.out @@ -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') = '{}'; diff --git a/src/test/regress/expected/polymorphism.out b/src/test/regress/expected/polymorphism.out index 1ff40764d9a..2c3bb0a60b0 100644 --- a/src/test/regress/expected/polymorphism.out +++ b/src/test/regress/expected/polymorphism.out @@ -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; diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql index 2b689ae88f5..906fd712b71 100644 --- a/src/test/regress/sql/arrays.sql +++ b/src/test/regress/sql/arrays.sql @@ -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); diff --git a/src/test/regress/sql/polymorphism.sql b/src/test/regress/sql/polymorphism.sql index e5222f1f81f..70a21c89780 100644 --- a/src/test/regress/sql/polymorphism.sql +++ b/src/test/regress/sql/polymorphism.sql @@ -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 ); |