]> granicus.if.org Git - postgresql/commitdiff
Fix handling of empty arrays in array_fill().
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 5 Jan 2017 16:33:51 +0000 (11:33 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 5 Jan 2017 16:33:51 +0000 (11:33 -0500)
array_fill(..., array[0]) produced an empty array, which is probably
what users expect, but it was a one-dimensional zero-length array
which is not our standard representation of empty arrays.  Also, for
no very good reason, it rejected empty input arrays; that case should
be allowed and produce an empty output array.

In passing, remove the restriction that the input array(s) have lower
bound 1.  That seems rather pointless, and it would have needed extra
complexity to make the check deal with empty input arrays.

Per bug #14487 from Andrew Gierth.  It's been broken all along, so
back-patch to all supported branches.

Discussion: https://postgr.es/m/20170105152156.10135.64195@wrigleys.postgresql.org

src/backend/utils/adt/arrayfuncs.c
src/test/regress/expected/arrays.out
src/test/regress/sql/arrays.sql

index 1db7bf0a35b0749f68399ede2a943ded3540d0df..5b2ca61c78c2ba1fb3b983ceba3568948440f9e0 100644 (file)
@@ -5734,25 +5734,19 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs,
        /*
         * Params checks
         */
-       if (ARR_NDIM(dims) != 1)
+       if (ARR_NDIM(dims) > 1)
                ereport(ERROR,
                                (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                                 errmsg("wrong number of array subscripts"),
                                 errdetail("Dimension array must be one dimensional.")));
 
-       if (ARR_LBOUND(dims)[0] != 1)
-               ereport(ERROR,
-                               (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
-                                errmsg("wrong range of array subscripts"),
-                                errdetail("Lower bound of dimension array must be one.")));
-
        if (array_contains_nulls(dims))
                ereport(ERROR,
                                (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
                                 errmsg("dimension values cannot be null")));
 
        dimv = (int *) ARR_DATA_PTR(dims);
-       ndims = ARR_DIMS(dims)[0];
+       ndims = (ARR_NDIM(dims) > 0) ? ARR_DIMS(dims)[0] : 0;
 
        if (ndims < 0)                          /* we do allow zero-dimension arrays */
                ereport(ERROR,
@@ -5766,24 +5760,18 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs,
 
        if (lbs != NULL)
        {
-               if (ARR_NDIM(lbs) != 1)
+               if (ARR_NDIM(lbs) > 1)
                        ereport(ERROR,
                                        (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                                         errmsg("wrong number of array subscripts"),
                                         errdetail("Dimension array must be one dimensional.")));
 
-               if (ARR_LBOUND(lbs)[0] != 1)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
-                                        errmsg("wrong range of array subscripts"),
-                                 errdetail("Lower bound of dimension array must be one.")));
-
                if (array_contains_nulls(lbs))
                        ereport(ERROR,
                                        (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
                                         errmsg("dimension values cannot be null")));
 
-               if (ARR_DIMS(lbs)[0] != ndims)
+               if (ndims != ((ARR_NDIM(lbs) > 0) ? ARR_DIMS(lbs)[0] : 0))
                        ereport(ERROR,
                                        (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                                         errmsg("wrong number of array subscripts"),
@@ -5801,12 +5789,12 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs,
                lbsv = deflbs;
        }
 
+       nitems = ArrayGetNItems(ndims, dimv);
+
        /* fast track for empty array */
-       if (ndims == 0)
+       if (nitems <= 0)
                return construct_empty_array(elmtype);
 
-       nitems = ArrayGetNItems(ndims, dimv);
-
        /*
         * We arrange to look up info about element type only once per series of
         * calls, assuming the element type doesn't change underneath us.
index 59e4472e4fd5c40ccfecdef31dd42d8e9b95fa68..8c5050577bffb02343f9371e0e605c47ad2e1053 100644 (file)
@@ -1553,16 +1553,43 @@ select array_fill('juhu'::text, array[3,3]);
  {{juhu,juhu,juhu},{juhu,juhu,juhu},{juhu,juhu,juhu}}
 (1 row)
 
+select a, a = '{}' as is_eq, array_dims(a)
+  from (select array_fill(42, array[0]) as a) ss;
+ a  | is_eq | array_dims 
+----+-------+------------
+ {} | t     | 
+(1 row)
+
+select a, a = '{}' as is_eq, array_dims(a)
+  from (select array_fill(42, '{}') as a) ss;
+ a  | is_eq | array_dims 
+----+-------+------------
+ {} | t     | 
+(1 row)
+
+select a, a = '{}' as is_eq, array_dims(a)
+  from (select array_fill(42, '{}', '{}') as a) ss;
+ a  | is_eq | array_dims 
+----+-------+------------
+ {} | t     | 
+(1 row)
+
 -- raise exception
 select array_fill(1, null, array[2,2]);
 ERROR:  dimension array or low bound array cannot be null
 select array_fill(1, array[2,2], null);
 ERROR:  dimension array or low bound array cannot be null
+select array_fill(1, array[2,2], '{}');
+ERROR:  wrong number of array subscripts
+DETAIL:  Low bound array has different size than dimensions array.
 select array_fill(1, array[3,3], array[1,1,1]);
 ERROR:  wrong number of array subscripts
 DETAIL:  Low bound array has different size than dimensions array.
 select array_fill(1, array[1,2,null]);
 ERROR:  dimension values cannot be null
+select array_fill(1, array[[1,2],[3,4]]);
+ERROR:  wrong number of array subscripts
+DETAIL:  Dimension array must be one dimensional.
 select string_to_array('1|2|3', '|');
  string_to_array 
 -----------------
index 2fbc699f6049b47fab7509430ff92ad07c523041..9de720756317b9c01388d4f47cf9bb191f1e3bfe 100644 (file)
@@ -482,11 +482,19 @@ select array_fill(7, array[3,3],array[2,2]);
 select array_fill(7, array[3,3]);
 select array_fill('juhu'::text, array[3,3],array[2,2]);
 select array_fill('juhu'::text, array[3,3]);
+select a, a = '{}' as is_eq, array_dims(a)
+  from (select array_fill(42, array[0]) as a) ss;
+select a, a = '{}' as is_eq, array_dims(a)
+  from (select array_fill(42, '{}') as a) ss;
+select a, a = '{}' as is_eq, array_dims(a)
+  from (select array_fill(42, '{}', '{}') as a) ss;
 -- raise exception
 select array_fill(1, null, array[2,2]);
 select array_fill(1, array[2,2], null);
+select array_fill(1, array[2,2], '{}');
 select array_fill(1, array[3,3], array[1,1,1]);
 select array_fill(1, array[1,2,null]);
+select array_fill(1, array[[1,2],[3,4]]);
 
 select string_to_array('1|2|3', '|');
 select string_to_array('1|2|3|', '|');