On Mon, Nov 4, 2024 at 7:34 PM Dean Rasheed <dean.a.rash...@gmail.com> wrote: > > Testing this with an array with non-default lower bounds, it fails to > preserve the array bounds, which I think it should (note: > array_reverse() and array_shuffle() do preserve the bounds): > > SELECT array_reverse(a), array_shuffle(a), array_sort(a) > FROM (VALUES ('[10:12][20:21]={{1,2},{10,20},{3,4}}'::int[])) v(a); > > -[ RECORD 1 ]-+------------------------------------- > array_reverse | [10:12][20:21]={{3,4},{10,20},{1,2}} > array_shuffle | [10:12][20:21]={{10,20},{3,4},{1,2}} > array_sort | [1:3][20:21]={{1,2},{3,4},{10,20}} >
if i understand it correctly, array_create_iterator cannot cope with top dimension bound information. since input array arguments already have dims, lbs information. so at the end of array_sort directly copy from the input array argument to astate. tuplesort_performsort won't need array bounds, we should be safe? v12-0001 same as v11-0001-general-purpose-array_sort.patch, only resolve git conflict v12-0002 preserve array bound information. v12-0003 cache ArrayMetaState. after v12-0003 now typedef struct ArraySortCachedInfo { TypeCacheEntry *typentry; TypeCacheEntry *array_typentry; ArrayMetaState array_meta; } ArraySortCachedInfo; function array_create_iterator, get_typlenbyvalalign will do cache search, we can cache ArrayMetaState. so multiple array_create_iterator calls won't need to call get_typlenbyvalalign. every time. 0002, I also have a 3 dimensional array test. create table t(a int[]); insert into t values ('[-1:-0]={7,1}'::int[]), ('[-2:-0][20:21]={{1,2},{10,20},{1,-4}}'), ('[-2:-0][20:22]={{-11,2,-1},{-11,2, 1},{-11,-4, 10}}'), ('[-13:-10][0:1][20:22]={ {{1,2,112},{1,2,-123}}, {{10,-20,1},{11,123,3}}, {{10,-20,1},{11,-123,-9}}, {{1,2,-11},{1,2,211}}}'::int[]); SELECT array_sort(t.a) from t; SELECT array_sort((t.a) [-13:-10][0:1][21:22]) from t where array_ndims(a) = 3; SELECT array_sort((t.a) [-13:-11][0:1][21:22]) from t where array_ndims(a) = 3; SELECT array_sort((t.a) [-13:-11][0:0][20:21]) from t where array_ndims(a) = 3; The test output is ok to me.
From caa24ca549c01e99b3873860dcffe0d8161345d4 Mon Sep 17 00:00:00 2001 From: jian he <jian.universality@gmail.com> Date: Tue, 5 Nov 2024 14:34:02 +0800 Subject: [PATCH v12 3/3] array_sort cache ArrayMetaState --- src/backend/utils/adt/array_userfuncs.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c index 436f761614..c14ef1ed90 100644 --- a/src/backend/utils/adt/array_userfuncs.c +++ b/src/backend/utils/adt/array_userfuncs.c @@ -1804,6 +1804,7 @@ typedef struct ArraySortCachedInfo { TypeCacheEntry *typentry; TypeCacheEntry *array_typentry; + ArrayMetaState array_meta; } ArraySortCachedInfo; /* @@ -1848,6 +1849,7 @@ array_sort(PG_FUNCTION_ARGS) sizeof(ArraySortCachedInfo)); cache_info->typentry = NULL; cache_info->array_typentry = NULL; + memset(&cache_info->array_meta, 0, sizeof(ArrayMetaState)); fcinfo->flinfo->fn_extra = (void *) cache_info; } @@ -1864,6 +1866,10 @@ array_sort(PG_FUNCTION_ARGS) errmsg("could not identify ordering operator for type %s", format_type_be(elmtyp)))); cache_info->typentry = typentry; + cache_info->array_meta.element_type = elmtyp; + cache_info->array_meta.typlen = typentry->typlen; + cache_info->array_meta.typbyval = typentry->typbyval; + cache_info->array_meta.typalign = typentry->typalign; } } else @@ -1886,6 +1892,11 @@ array_sort(PG_FUNCTION_ARGS) format_type_be(array_type)))); cache_info->array_typentry = typentry; } + cache_info->array_meta.element_type = elmtyp; + get_typlenbyvalalign(elmtyp, + &cache_info->array_meta.typlen, + &cache_info->array_meta.typbyval, + &cache_info->array_meta.typalign); } tuplesortstate = tuplesort_begin_datum(typentry->type_id, @@ -1893,7 +1904,7 @@ array_sort(PG_FUNCTION_ARGS) collation, false, work_mem, NULL, false); - array_iterator = array_create_iterator(array, ndim - 1, NULL); + array_iterator = array_create_iterator(array, ndim - 1, &cache_info->array_meta); while (array_iterate(array_iterator, &value, &isnull)) { tuplesort_putdatum(tuplesortstate, value, isnull); -- 2.34.1
From d7c2956893222bb025822810860a01539ca3ec85 Mon Sep 17 00:00:00 2001 From: jian he <jian.universality@gmail.com> Date: Tue, 5 Nov 2024 14:53:42 +0800 Subject: [PATCH v12 2/3] array_sort preserve array dimenion and bound info --- src/backend/utils/adt/array_userfuncs.c | 30 +++++++++++++-- src/backend/utils/adt/arrayfuncs.c | 3 +- src/include/utils/array.h | 1 + src/test/regress/expected/arrays.out | 49 +++++++++++++++++++++++++ src/test/regress/sql/arrays.sql | 18 ++++++++- 5 files changed, 96 insertions(+), 5 deletions(-) diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c index a45586c892..436f761614 100644 --- a/src/backend/utils/adt/array_userfuncs.c +++ b/src/backend/utils/adt/array_userfuncs.c @@ -1826,8 +1826,18 @@ array_sort(PG_FUNCTION_ARGS) Datum value; bool isnull; ArrayBuildStateAny *astate = NULL; + int ndim, + *dims, + *lbs; - if (ARR_NDIM(array) < 1) + ndim = ARR_NDIM(array); + dims = ARR_DIMS(array); + lbs = ARR_LBOUND(array); + + if (ndim < 1) + PG_RETURN_ARRAYTYPE_P(array); + + if(dims[0] < 2) PG_RETURN_ARRAYTYPE_P(array); elmtyp = ARR_ELEMTYPE(array); @@ -1841,7 +1851,7 @@ array_sort(PG_FUNCTION_ARGS) fcinfo->flinfo->fn_extra = (void *) cache_info; } - if (ARR_NDIM(array) == 1) + if (ndim == 1) { /* Finds the ordering operator for the type for 1-D arrays */ typentry = cache_info->typentry; @@ -1883,7 +1893,7 @@ array_sort(PG_FUNCTION_ARGS) collation, false, work_mem, NULL, false); - array_iterator = array_create_iterator(array, ARR_NDIM(array) - 1, NULL); + array_iterator = array_create_iterator(array, ndim - 1, NULL); while (array_iterate(array_iterator, &value, &isnull)) { tuplesort_putdatum(tuplesortstate, value, isnull); @@ -1903,6 +1913,20 @@ array_sort(PG_FUNCTION_ARGS) tuplesort_end(tuplesortstate); + if (astate->arraystate != NULL) + { + memcpy(astate->arraystate->dims, dims, ndim * sizeof(int)); + memcpy(astate->arraystate->lbs, lbs, ndim * sizeof(int)); + Assert(ndim == astate->arraystate->ndims); + } + else + { + astate->scalarstate->lbs = lbs[0]; + + /* zero dimension won't reach here */ + Assert(ndim == 1); + } + /* Avoid leaking memory when handed toasted input */ PG_FREE_IF_COPY(array, 0); PG_RETURN_DATUM(makeArrayResultAny(astate, CurrentMemoryContext, true)); diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index a715e7e0b8..ffdf3449e9 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -5335,6 +5335,7 @@ initArrayResultWithSize(Oid element_type, MemoryContext rcontext, &astate->typbyval, &astate->typalign); + astate->lbs = 1; /* default lower-bound value set to 1, see array_in also */ return astate; } @@ -5867,7 +5868,7 @@ makeArrayResultAny(ArrayBuildStateAny *astate, /* If no elements were presented, we want to create an empty array */ ndims = (astate->scalarstate->nelems > 0) ? 1 : 0; dims[0] = astate->scalarstate->nelems; - lbs[0] = 1; + lbs[0] = astate->scalarstate->lbs; result = makeMdArrayResult(astate->scalarstate, ndims, dims, lbs, rcontext, release); diff --git a/src/include/utils/array.h b/src/include/utils/array.h index 157cc0e4c6..7b7937d494 100644 --- a/src/include/utils/array.h +++ b/src/include/utils/array.h @@ -193,6 +193,7 @@ typedef struct ArrayBuildState int nelems; /* number of valid entries in above arrays */ Oid element_type; /* data type of the Datums */ int16 typlen; /* needed info about datatype */ + int lbs; /* one dimension, one lower-bound is OK*/ bool typbyval; char typalign; bool private_cxt; /* use private memory context */ diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out index 846d6acd85..9e371902d3 100644 --- a/src/test/regress/expected/arrays.out +++ b/src/test/regress/expected/arrays.out @@ -2735,6 +2735,18 @@ SELECT array_reverse('{{1,2},{3,4},{5,6},{7,8}}'::int[]); (1 row) -- array_sort +SELECT array_sort('{1}'::int[]); + array_sort +------------ + {1} +(1 row) + +SELECT array_sort('{{2,1}}'::int[]); + array_sort +------------ + {{2,1}} +(1 row) + SELECT array_sort('{}'::int[]); array_sort ------------ @@ -2772,3 +2784,40 @@ SELECT array_sort(ARRAY[[2,4],[2,1],[6,5]]); {{2,1},{2,4},{6,5}} (1 row) +create table t(a int[]); +insert into t values ('[-1:-0]={7,1}'::int[]), +('[-2:-0][20:21]={{1,2},{10,20},{1,-4}}'), +('[-2:-0][20:22]={{-11,2,-1},{-11,2, 1},{-11,-4, 10}}'), +('[-13:-10][0:1][20:22]={ +{{1,2,112},{1,2,-123}}, +{{10,-20,1},{11,123,3}}, +{{10,-20,1},{11,-123,-9}}, +{{1,2,-11},{1,2,211}}}'::int[]); +SELECT array_sort(t.a) from t; + array_sort +------------------------------------------------------------------------------------------------------------------------ + [-1:0]={1,7} + [-2:0][20:21]={{1,-4},{1,2},{10,20}} + [-2:0][20:22]={{-11,-4,10},{-11,2,-1},{-11,2,1}} + [-13:-10][0:1][20:22]={{{1,2,-11},{1,2,211}},{{1,2,112},{1,2,-123}},{{10,-20,1},{11,-123,-9}},{{10,-20,1},{11,123,3}}} +(4 rows) + +SELECT array_sort((t.a) [-13:-10][0:1][21:22]) from t where array_ndims(a) = 3; + array_sort +------------------------------------------------------------------------------ + {{{-20,1},{-123,-9}},{{-20,1},{123,3}},{{2,-11},{2,211}},{{2,112},{2,-123}}} +(1 row) + +SELECT array_sort((t.a) [-13:-11][0:1][21:22]) from t where array_ndims(a) = 3; + array_sort +------------------------------------------------------------ + {{{-20,1},{-123,-9}},{{-20,1},{123,3}},{{2,112},{2,-123}}} +(1 row) + +SELECT array_sort((t.a) [-13:-11][0:0][20:21]) from t where array_ndims(a) = 3; + array_sort +--------------------------------- + {{{1,2}},{{10,-20}},{{10,-20}}} +(1 row) + +drop table t; diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql index 17205f483b..2a40c401b5 100644 --- a/src/test/regress/sql/arrays.sql +++ b/src/test/regress/sql/arrays.sql @@ -836,6 +836,8 @@ SELECT array_reverse('{1,2,3,NULL,4,5,6}'::int[]); SELECT array_reverse('{{1,2},{3,4},{5,6},{7,8}}'::int[]); -- array_sort +SELECT array_sort('{1}'::int[]); +SELECT array_sort('{{2,1}}'::int[]); SELECT array_sort('{}'::int[]); SELECT array_sort('{1,3,5,2,4,6}'::int[]); SELECT array_sort('{1.1,3.3,5.5,2.2,4.4,6.6}'::numeric[]); @@ -843,4 +845,18 @@ SELECT array_sort('{foo,bar,CCC,Abc,bbc}'::text[] COLLATE "C"); SELECT array_sort('{foo,bar,null,CCC,Abc,bbc}'::text[] COLLATE "C"); -- multidimensional array tests -SELECT array_sort(ARRAY[[2,4],[2,1],[6,5]]); \ No newline at end of file +SELECT array_sort(ARRAY[[2,4],[2,1],[6,5]]); +create table t(a int[]); +insert into t values ('[-1:-0]={7,1}'::int[]), +('[-2:-0][20:21]={{1,2},{10,20},{1,-4}}'), +('[-2:-0][20:22]={{-11,2,-1},{-11,2, 1},{-11,-4, 10}}'), +('[-13:-10][0:1][20:22]={ +{{1,2,112},{1,2,-123}}, +{{10,-20,1},{11,123,3}}, +{{10,-20,1},{11,-123,-9}}, +{{1,2,-11},{1,2,211}}}'::int[]); +SELECT array_sort(t.a) from t; +SELECT array_sort((t.a) [-13:-10][0:1][21:22]) from t where array_ndims(a) = 3; +SELECT array_sort((t.a) [-13:-11][0:1][21:22]) from t where array_ndims(a) = 3; +SELECT array_sort((t.a) [-13:-11][0:0][20:21]) from t where array_ndims(a) = 3; +drop table t; \ No newline at end of file -- 2.34.1
From ea85acab5039ef8d23e1e994c9d1d4ae79bdb29e Mon Sep 17 00:00:00 2001 From: jian he <jian.universality@gmail.com> Date: Tue, 5 Nov 2024 14:40:56 +0800 Subject: [PATCH v12 1/3] general purpose array_sort Sorts anyarray on its first dimension. The sort order is determined by the "<" operator. Signed-off-by: Junwang Zhao <zhjwpku@gmail.com> --- doc/src/sgml/func.sgml | 18 +++ src/backend/utils/adt/array_userfuncs.c | 110 ++++++++++++++++++ src/include/catalog/pg_proc.dat | 3 + src/test/regress/expected/arrays.out | 38 ++++++ .../regress/expected/collate.icu.utf8.out | 13 +++ src/test/regress/sql/arrays.sql | 10 ++ src/test/regress/sql/collate.icu.utf8.sql | 4 + src/tools/pgindent/typedefs.list | 1 + 8 files changed, 197 insertions(+) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 73979f20ff..748611dee5 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -20438,6 +20438,24 @@ SELECT NULLIF(value, '(none)') ... </para></entry> </row> + <row> + <entry role="func_table_entry"><para role="func_signature"> + <indexterm> + <primary>array_sort</primary> + </indexterm> + <function>array_sort</function> ( <type>anyarray</type> ) + <returnvalue>anyarray</returnvalue> + </para> + <para> + Sorts the first dimension of the array. The sort order is determined by the <literal><</literal> operator of the element type, nulls will appear after non-null values. + The collation to use can be forced by adding a <literal>COLLATE</literal> clause to any of the arguments. + </para> + <para> + <literal>array_sort(ARRAY[[2,4],[2,1],[6,5]])</literal> + <returnvalue>{{2,1},{2,4},{6,5}}</returnvalue> + </para></entry> + </row> + <row> <entry role="func_table_entry"><para role="func_signature"> <indexterm id="function-array-to-string"> diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c index d053808f6e..a45586c892 100644 --- a/src/backend/utils/adt/array_userfuncs.c +++ b/src/backend/utils/adt/array_userfuncs.c @@ -16,11 +16,13 @@ #include "common/int.h" #include "common/pg_prng.h" #include "libpq/pqformat.h" +#include "miscadmin.h" #include "port/pg_bitutils.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/datum.h" #include "utils/lsyscache.h" +#include "utils/tuplesort.h" #include "utils/typcache.h" /* @@ -1797,3 +1799,111 @@ array_reverse(PG_FUNCTION_ARGS) PG_RETURN_ARRAYTYPE_P(result); } + +typedef struct ArraySortCachedInfo +{ + TypeCacheEntry *typentry; + TypeCacheEntry *array_typentry; +} ArraySortCachedInfo; + +/* + * array_sort + * + * Sorts the first dimension of the array. + * The sort order is determined by the "<" operator of the element type. + */ +Datum +array_sort(PG_FUNCTION_ARGS) +{ + ArrayType *array = PG_GETARG_ARRAYTYPE_P(0); + Oid elmtyp; + Oid array_type; + Oid collation = PG_GET_COLLATION(); + ArraySortCachedInfo *cache_info; + TypeCacheEntry *typentry; + Tuplesortstate *tuplesortstate; + ArrayIterator array_iterator; + Datum value; + bool isnull; + ArrayBuildStateAny *astate = NULL; + + if (ARR_NDIM(array) < 1) + PG_RETURN_ARRAYTYPE_P(array); + + elmtyp = ARR_ELEMTYPE(array); + cache_info = (ArraySortCachedInfo *) fcinfo->flinfo->fn_extra; + if (cache_info == NULL) + { + cache_info = (ArraySortCachedInfo *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, + sizeof(ArraySortCachedInfo)); + cache_info->typentry = NULL; + cache_info->array_typentry = NULL; + fcinfo->flinfo->fn_extra = (void *) cache_info; + } + + if (ARR_NDIM(array) == 1) + { + /* Finds the ordering operator for the type for 1-D arrays */ + typentry = cache_info->typentry; + if (typentry == NULL || typentry->type_id != elmtyp) + { + typentry = lookup_type_cache(elmtyp, TYPECACHE_LT_OPR); + if (!OidIsValid(typentry->lt_opr)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("could not identify ordering operator for type %s", + format_type_be(elmtyp)))); + cache_info->typentry = typentry; + } + } + else + { + /* Finds the ordering operator for the array type for multi-D arrays */ + typentry = cache_info->array_typentry; + if (typentry == NULL || typentry->typelem != elmtyp) + { + array_type = get_array_type(elmtyp); + if (!OidIsValid(array_type)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("could not find array type for data type %s", + format_type_be(elmtyp)))); + typentry = lookup_type_cache(array_type, TYPECACHE_LT_OPR); + if (!OidIsValid(typentry->lt_opr)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("could not identify ordering operator for type %s", + format_type_be(array_type)))); + cache_info->array_typentry = typentry; + } + } + + tuplesortstate = tuplesort_begin_datum(typentry->type_id, + typentry->lt_opr, + collation, + false, work_mem, NULL, false); + + array_iterator = array_create_iterator(array, ARR_NDIM(array) - 1, NULL); + while (array_iterate(array_iterator, &value, &isnull)) + { + tuplesort_putdatum(tuplesortstate, value, isnull); + } + array_free_iterator(array_iterator); + + /* + * Do the sort. + */ + tuplesort_performsort(tuplesortstate); + + while (tuplesort_getdatum(tuplesortstate, true, false, &value, &isnull, NULL)) + { + astate = accumArrayResultAny(astate, value, isnull, + typentry->type_id, CurrentMemoryContext); + } + + tuplesort_end(tuplesortstate); + + /* Avoid leaking memory when handed toasted input */ + PG_FREE_IF_COPY(array, 0); + PG_RETURN_DATUM(makeArrayResultAny(astate, CurrentMemoryContext, true)); +} diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index f23321a41f..54ebbbd135 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -1744,6 +1744,9 @@ { oid => '8686', descr => 'reverse array', proname => 'array_reverse', prorettype => 'anyarray', proargtypes => 'anyarray', prosrc => 'array_reverse' }, +{ oid => '8810', descr => 'sort array', + proname => 'array_sort', prorettype => 'anyarray', + proargtypes => 'anyarray', prosrc => 'array_sort'}, { 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 0b61fb5bb7..846d6acd85 100644 --- a/src/test/regress/expected/arrays.out +++ b/src/test/regress/expected/arrays.out @@ -2734,3 +2734,41 @@ SELECT array_reverse('{{1,2},{3,4},{5,6},{7,8}}'::int[]); {{7,8},{5,6},{3,4},{1,2}} (1 row) +-- array_sort +SELECT array_sort('{}'::int[]); + array_sort +------------ + {} +(1 row) + +SELECT array_sort('{1,3,5,2,4,6}'::int[]); + array_sort +--------------- + {1,2,3,4,5,6} +(1 row) + +SELECT array_sort('{1.1,3.3,5.5,2.2,4.4,6.6}'::numeric[]); + array_sort +--------------------------- + {1.1,2.2,3.3,4.4,5.5,6.6} +(1 row) + +SELECT array_sort('{foo,bar,CCC,Abc,bbc}'::text[] COLLATE "C"); + array_sort +----------------------- + {Abc,CCC,bar,bbc,foo} +(1 row) + +SELECT array_sort('{foo,bar,null,CCC,Abc,bbc}'::text[] COLLATE "C"); + array_sort +---------------------------- + {Abc,CCC,bar,bbc,foo,NULL} +(1 row) + +-- multidimensional array tests +SELECT array_sort(ARRAY[[2,4],[2,1],[6,5]]); + array_sort +--------------------- + {{2,1},{2,4},{6,5}} +(1 row) + diff --git a/src/test/regress/expected/collate.icu.utf8.out b/src/test/regress/expected/collate.icu.utf8.out index faa376e060..aa5fd75e6e 100644 --- a/src/test/regress/expected/collate.icu.utf8.out +++ b/src/test/regress/expected/collate.icu.utf8.out @@ -1338,6 +1338,19 @@ SELECT 'abc' <= 'ABC' COLLATE case_insensitive, 'abc' >= 'ABC' COLLATE case_inse t | t (1 row) +-- tests with array_sort +SELECT array_sort('{a,B}'::text[] COLLATE case_insensitive); + array_sort +------------ + {a,B} +(1 row) + +SELECT array_sort('{a,B}'::text[] COLLATE "C"); + array_sort +------------ + {B,a} +(1 row) + -- test language tags CREATE COLLATION lt_insensitive (provider = icu, locale = 'en-u-ks-level1', deterministic = false); SELECT 'aBcD' COLLATE lt_insensitive = 'AbCd' COLLATE lt_insensitive; diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql index 03cc8cfcd9..17205f483b 100644 --- a/src/test/regress/sql/arrays.sql +++ b/src/test/regress/sql/arrays.sql @@ -834,3 +834,13 @@ SELECT array_reverse('{1}'::int[]); SELECT array_reverse('{1,2}'::int[]); SELECT array_reverse('{1,2,3,NULL,4,5,6}'::int[]); SELECT array_reverse('{{1,2},{3,4},{5,6},{7,8}}'::int[]); + +-- array_sort +SELECT array_sort('{}'::int[]); +SELECT array_sort('{1,3,5,2,4,6}'::int[]); +SELECT array_sort('{1.1,3.3,5.5,2.2,4.4,6.6}'::numeric[]); +SELECT array_sort('{foo,bar,CCC,Abc,bbc}'::text[] COLLATE "C"); +SELECT array_sort('{foo,bar,null,CCC,Abc,bbc}'::text[] COLLATE "C"); + +-- multidimensional array tests +SELECT array_sort(ARRAY[[2,4],[2,1],[6,5]]); \ No newline at end of file diff --git a/src/test/regress/sql/collate.icu.utf8.sql b/src/test/regress/sql/collate.icu.utf8.sql index 80f28a97d7..3c739d332b 100644 --- a/src/test/regress/sql/collate.icu.utf8.sql +++ b/src/test/regress/sql/collate.icu.utf8.sql @@ -536,6 +536,10 @@ CREATE COLLATION case_insensitive (provider = icu, locale = '@colStrength=second SELECT 'abc' <= 'ABC' COLLATE case_sensitive, 'abc' >= 'ABC' COLLATE case_sensitive; SELECT 'abc' <= 'ABC' COLLATE case_insensitive, 'abc' >= 'ABC' COLLATE case_insensitive; +-- tests with array_sort +SELECT array_sort('{a,B}'::text[] COLLATE case_insensitive); +SELECT array_sort('{a,B}'::text[] COLLATE "C"); + -- test language tags CREATE COLLATION lt_insensitive (provider = icu, locale = 'en-u-ks-level1', deterministic = false); SELECT 'aBcD' COLLATE lt_insensitive = 'AbCd' COLLATE lt_insensitive; diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 1847bbfa95..e740e449f5 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -150,6 +150,7 @@ ArrayIOData ArrayIterator ArrayMapState ArrayMetaState +ArraySortCachedInfo ArraySubWorkspace ArrayToken ArrayType -- 2.34.1