BUG #7730: intarray representation of empty arrays

Started by eleinover 13 years ago6 messagesbugs
Jump to latest
#1elein
elein@varlena.com

The following bug has been logged on the website:

Bug reference: 7730
Logged by: elein
Email address: elein@varlena.com
PostgreSQL version: 9.2.1
Operating system: Linux
Description:

select NULLIF('{1,2,3}'::integer[] - '{3,2,1}'::integer[], '{}'::integer[]);
This returns an empty array. It should return NULL.

Per RhodiumToad: the core code represents '{}' as an array with 0
dimensions, whereas intarray represents it as an array with 1 dimension but
0 elements

intarray should use the same standards as the core code if possible. I
peered at the code and don't see anything untoward but did not have time to
spend on it.

--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

#2Bruce Momjian
bruce@momjian.us
In reply to: elein (#1)
Re: BUG #7730: intarray representation of empty arrays

On Wed, Dec 5, 2012 at 12:44:39AM +0000, elein@varlena.com wrote:

The following bug has been logged on the website:

Bug reference: 7730
Logged by: elein
Email address: elein@varlena.com
PostgreSQL version: 9.2.1
Operating system: Linux
Description:

select NULLIF('{1,2,3}'::integer[] - '{3,2,1}'::integer[], '{}'::integer[]);
This returns an empty array. It should return NULL.

Per RhodiumToad: the core code represents '{}' as an array with 0
dimensions, whereas intarray represents it as an array with 1 dimension but
0 elements

intarray should use the same standards as the core code if possible. I
peered at the code and don't see anything untoward but did not have time to
spend on it.

I just got time to look at this, and it is certainly easier to see when
you use array_dims():

SELECT '{1,2,3}'::integer[] - '{3,2,1}'::integer[];
?column?
----------
{}

SELECT array_dims('{1,2,3}'::integer[] - '{3,2,1}'::integer[]);
array_dims
------------
[1:0]

SELECT array_dims('{}'::integer[]);
array_dims
------------
(null)

This is part of the larger TODO item of how to handle empty

=1-dimensional empty arrays vs. zero-dimensional empty arrays, which is

discussed here:

https://wiki.postgresql.org/wiki/Todo#Arrays
Improve handling of empty arrays

In that thread, no one could find a way to create a 1-dimensional empty
array at the SQL level, but thanks to intarray, you found a way. It is
natural that intarray, being mostly used for one-dimensional arrays,
would return a 1-dimensional empty array. However, besides being
inconsistent, as you mentioned, there is also no way to dump/restore
one-dimensional empty arrays, which is a larger concern.

I have developed the attached patch to force empty intarray results to
be zero-dimensional empty arrays, rather than 1-dimensional empty
arrays. With this patch, a zero-dimensional empty array is returned:

SELECT array_dims('{1,2,3}'::integer[] - '{3,2,1}'::integer[]);
array_dims
------------
(null)

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

Attachments:

array.difftext/x-diff; charset=us-asciiDownload+7-0
#3Bruce Momjian
bruce@momjian.us
In reply to: Bruce Momjian (#2)
Re: BUG #7730: intarray representation of empty arrays

Applied.

---------------------------------------------------------------------------

On Wed, Sep 4, 2013 at 03:01:50PM -0400, Bruce Momjian wrote:

On Wed, Dec 5, 2012 at 12:44:39AM +0000, elein@varlena.com wrote:

The following bug has been logged on the website:

Bug reference: 7730
Logged by: elein
Email address: elein@varlena.com
PostgreSQL version: 9.2.1
Operating system: Linux
Description:

select NULLIF('{1,2,3}'::integer[] - '{3,2,1}'::integer[], '{}'::integer[]);
This returns an empty array. It should return NULL.

Per RhodiumToad: the core code represents '{}' as an array with 0
dimensions, whereas intarray represents it as an array with 1 dimension but
0 elements

intarray should use the same standards as the core code if possible. I
peered at the code and don't see anything untoward but did not have time to
spend on it.

I just got time to look at this, and it is certainly easier to see when
you use array_dims():

SELECT '{1,2,3}'::integer[] - '{3,2,1}'::integer[];
?column?
----------
{}

SELECT array_dims('{1,2,3}'::integer[] - '{3,2,1}'::integer[]);
array_dims
------------
[1:0]

SELECT array_dims('{}'::integer[]);
array_dims
------------
(null)

This is part of the larger TODO item of how to handle empty

=1-dimensional empty arrays vs. zero-dimensional empty arrays, which is

discussed here:

https://wiki.postgresql.org/wiki/Todo#Arrays
Improve handling of empty arrays

In that thread, no one could find a way to create a 1-dimensional empty
array at the SQL level, but thanks to intarray, you found a way. It is
natural that intarray, being mostly used for one-dimensional arrays,
would return a 1-dimensional empty array. However, besides being
inconsistent, as you mentioned, there is also no way to dump/restore
one-dimensional empty arrays, which is a larger concern.

I have developed the attached patch to force empty intarray results to
be zero-dimensional empty arrays, rather than 1-dimensional empty
arrays. With this patch, a zero-dimensional empty array is returned:

SELECT array_dims('{1,2,3}'::integer[] - '{3,2,1}'::integer[]);
array_dims
------------
(null)

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

diff --git a/contrib/intarray/_int_tool.c b/contrib/intarray/_int_tool.c
new file mode 100644
index 8635576..fc462b2
*** a/contrib/intarray/_int_tool.c
--- b/contrib/intarray/_int_tool.c
*************** resize_intArrayType(ArrayType *a, int nu
*** 246,251 ****
--- 246,258 ----
int			nbytes = ARR_DATA_OFFSET(a) + sizeof(int) * num;
int			i;
+ 	/* if no elements, return a zero-dimensional array */
+ 	if (num == 0)
+ 	{
+ 		ARR_NDIM(a) = 0;
+ 		return a;
+ 	}
+ 
if (num == ARRNELEMS(a))
return a;

--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

#4elein
elein@varlena.com
In reply to: Bruce Momjian (#3)
Re: BUG #7730: intarray representation of empty arrays

Thanks for looking into this. Finally I'll get to test existing columns filled with a variety of array[0], '{}' and array[0]-array[0] or Null. Sorry it took so long.

What is the target production release?

A. Elein Mustain
Elein@varlena.com
510-637-9106

On Sep 7, 2013, at 8:44 AM, Bruce Momjian <bruce@momjian.us> wrote:

Applied.

---------------------------------------------------------------------------

On Wed, Sep 4, 2013 at 03:01:50PM -0400, Bruce Momjian wrote:

On Wed, Dec 5, 2012 at 12:44:39AM +0000, elein@varlena.com wrote:
The following bug has been logged on the website:

Bug reference: 7730
Logged by: elein
Email address: elein@varlena.com
PostgreSQL version: 9.2.1
Operating system: Linux
Description:

select NULLIF('{1,2,3}'::integer[] - '{3,2,1}'::integer[], '{}'::integer[]);
This returns an empty array. It should return NULL.

Per RhodiumToad: the core code represents '{}' as an array with 0
dimensions, whereas intarray represents it as an array with 1 dimension but
0 elements

intarray should use the same standards as the core code if possible. I
peered at the code and don't see anything untoward but did not have time to
spend on it.

I just got time to look at this, and it is certainly easier to see when
you use array_dims():

SELECT '{1,2,3}'::integer[] - '{3,2,1}'::integer[];
?column?
----------
{}

SELECT array_dims('{1,2,3}'::integer[] - '{3,2,1}'::integer[]);
array_dims
------------
[1:0]

SELECT array_dims('{}'::integer[]);
array_dims
------------
(null)

This is part of the larger TODO item of how to handle empty

=1-dimensional empty arrays vs. zero-dimensional empty arrays, which is

discussed here:

https://wiki.postgresql.org/wiki/Todo#Arrays
Improve handling of empty arrays

In that thread, no one could find a way to create a 1-dimensional empty
array at the SQL level, but thanks to intarray, you found a way. It is
natural that intarray, being mostly used for one-dimensional arrays,
would return a 1-dimensional empty array. However, besides being
inconsistent, as you mentioned, there is also no way to dump/restore
one-dimensional empty arrays, which is a larger concern.

I have developed the attached patch to force empty intarray results to
be zero-dimensional empty arrays, rather than 1-dimensional empty
arrays. With this patch, a zero-dimensional empty array is returned:

SELECT array_dims('{1,2,3}'::integer[] - '{3,2,1}'::integer[]);
array_dims
------------
(null)

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

diff --git a/contrib/intarray/_int_tool.c b/contrib/intarray/_int_tool.c
new file mode 100644
index 8635576..fc462b2
*** a/contrib/intarray/_int_tool.c
--- b/contrib/intarray/_int_tool.c
*************** resize_intArrayType(ArrayType *a, int nu
*** 246,251 ****
--- 246,258 ----
int            nbytes = ARR_DATA_OFFSET(a) + sizeof(int) * num;
int            i;
+    /* if no elements, return a zero-dimensional array */
+    if (num == 0)
+    {
+        ARR_NDIM(a) = 0;
+        return a;
+    }
+ 
if (num == ARRNELEMS(a))
return a;

--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

#5Bruce Momjian
bruce@momjian.us
In reply to: elein (#4)
Re: BUG #7730: intarray representation of empty arrays

On Sun, Jan 19, 2014 at 04:21:42PM -0800, Elein wrote:

Thanks for looking into this. Finally I'll get to test existing columns filled with a variety of array[0], '{}' and array[0]-array[0] or Null. Sorry it took so long.

What is the target production release?

Well, I think we are going to close patching for 9.4 beta in about 1-2
months.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ Everyone has their own god. +

--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

#6Bruce Momjian
bruce@momjian.us
In reply to: elein (#4)
Re: BUG #7730: intarray representation of empty arrays

On Sun, Jan 19, 2014 at 04:21:42PM -0800, Elein wrote:

Thanks for looking into this. Finally I'll get to test existing columns filled with a variety of array[0], '{}' and array[0]-array[0] or Null. Sorry it took so long.

What is the target production release?

FYI, it has been committed; I just need testing help:

commit c155f654b4f755b4111bd9adb60559fe22526a10
Author: Bruce Momjian <bruce@momjian.us>
Date: Sat Sep 7 11:44:33 2013 -0400

intarray: return empty zero-dimensional array for an empty array

Previously a one-dimensional empty array was returned, but its text
representation matched a zero-dimensional array, and there is no way to
dump/reload a one-dimensional empty array.

BACKWARD INCOMPATIBILITY

Per report from elein

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ Everyone has their own god. +

--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs