Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 659f681

Browse files
committed
Change array comparison rules to consider dimensionality information,
not only the array contents, before claiming two arrays are equal. Per recent discussion.
1 parent daea4d8 commit 659f681

File tree

2 files changed

+47
-10
lines changed

2 files changed

+47
-10
lines changed

doc/src/sgml/func.sgml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.294 2005/11/19 01:50:08 tgl Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.295 2005/11/19 19:44:54 tgl Exp $
33
PostgreSQL documentation
44
-->
55

@@ -7403,6 +7403,19 @@ SELECT NULLIF(value, '(none)') ...
74037403
</tgroup>
74047404
</table>
74057405

7406+
<para>
7407+
Array comparisons compare the array contents element-by-element,
7408+
using the default btree comparison function for the element data type.
7409+
In multidimensional arrays the elements are visited in row-major order
7410+
(last subscript varies most rapidly).
7411+
If the contents of two arrays are equal but the dimensionality is
7412+
different, the first difference in the dimensionality information
7413+
determines the sort order. (This is a change from versions of
7414+
<productname>PostgreSQL</> prior to 8.2: older versions would claim
7415+
that two arrays with the same contents were equal, even if the
7416+
number of dimensions or subscript ranges were different.)
7417+
</para>
7418+
74067419
<para>
74077420
See <xref linkend="arrays"> for more details about array operator
74087421
behavior.

src/backend/utils/adt/arrayfuncs.c

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.124 2005/11/17 22:14:52 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.125 2005/11/19 19:44:55 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -2965,10 +2965,9 @@ array_eq(PG_FUNCTION_ARGS)
29652965
int ndims2 = ARR_NDIM(array2);
29662966
int *dims1 = ARR_DIMS(array1);
29672967
int *dims2 = ARR_DIMS(array2);
2968-
int nitems1 = ArrayGetNItems(ndims1, dims1);
2969-
int nitems2 = ArrayGetNItems(ndims2, dims2);
29702968
Oid element_type = ARR_ELEMTYPE(array1);
29712969
bool result = true;
2970+
int nitems;
29722971
TypeCacheEntry *typentry;
29732972
int typlen;
29742973
bool typbyval;
@@ -2986,8 +2985,9 @@ array_eq(PG_FUNCTION_ARGS)
29862985
(errcode(ERRCODE_DATATYPE_MISMATCH),
29872986
errmsg("cannot compare arrays of different element types")));
29882987

2989-
/* fast path if the arrays do not have the same number of elements */
2990-
if (nitems1 != nitems2)
2988+
/* fast path if the arrays do not have the same dimensionality */
2989+
if (ndims1 != ndims2 ||
2990+
memcmp(dims1, dims2, 2 * ndims1 * sizeof(int)) != 0)
29912991
result = false;
29922992
else
29932993
{
@@ -3021,13 +3021,14 @@ array_eq(PG_FUNCTION_ARGS)
30213021
NULL, NULL);
30223022

30233023
/* Loop over source data */
3024+
nitems = ArrayGetNItems(ndims1, dims1);
30243025
ptr1 = ARR_DATA_PTR(array1);
30253026
ptr2 = ARR_DATA_PTR(array2);
30263027
bitmap1 = ARR_NULLBITMAP(array1);
30273028
bitmap2 = ARR_NULLBITMAP(array2);
30283029
bitmask = 1; /* use same bitmask for both arrays */
30293030

3030-
for (i = 0; i < nitems1; i++)
3031+
for (i = 0; i < nitems; i++)
30313032
{
30323033
Datum elt1;
30333034
Datum elt2;
@@ -3221,13 +3222,13 @@ array_cmp(FunctionCallInfo fcinfo)
32213222
NULL, NULL);
32223223

32233224
/* Loop over source data */
3225+
min_nitems = Min(nitems1, nitems2);
32243226
ptr1 = ARR_DATA_PTR(array1);
32253227
ptr2 = ARR_DATA_PTR(array2);
32263228
bitmap1 = ARR_NULLBITMAP(array1);
32273229
bitmap2 = ARR_NULLBITMAP(array2);
32283230
bitmask = 1; /* use same bitmask for both arrays */
32293231

3230-
min_nitems = Min(nitems1, nitems2);
32313232
for (i = 0; i < min_nitems; i++)
32323233
{
32333234
Datum elt1;
@@ -3317,8 +3318,31 @@ array_cmp(FunctionCallInfo fcinfo)
33173318
}
33183319
}
33193320

3320-
if ((result == 0) && (nitems1 != nitems2))
3321-
result = (nitems1 < nitems2) ? -1 : 1;
3321+
/*
3322+
* If arrays contain same data (up to end of shorter one), apply additional
3323+
* rules to sort by dimensionality. The relative significance of the
3324+
* different bits of information is historical; mainly we just care that
3325+
* we don't say "equal" for arrays of different dimensionality.
3326+
*/
3327+
if (result == 0)
3328+
{
3329+
if (nitems1 != nitems2)
3330+
result = (nitems1 < nitems2) ? -1 : 1;
3331+
else if (ndims1 != ndims2)
3332+
result = (ndims1 < ndims2) ? -1 : 1;
3333+
else
3334+
{
3335+
/* this relies on LB array immediately following DIMS array */
3336+
for (i = 0; i < ndims1 * 2; i++)
3337+
{
3338+
if (dims1[i] != dims2[i])
3339+
{
3340+
result = (dims1[i] < dims2[i]) ? -1 : 1;
3341+
break;
3342+
}
3343+
}
3344+
}
3345+
}
33223346

33233347
/* Avoid leaking memory when handed toasted input. */
33243348
PG_FREE_IF_COPY(array1, 0);

0 commit comments

Comments
 (0)