From: | Joe Conway <mail(at)joeconway(dot)com> |
---|---|
To: | Greg Stark <gsstark(at)mit(dot)edu> |
Cc: | pgsql-hackers(at)postgresql(dot)org |
Subject: | Re: Inconsistent behavior on Array & Is Null? |
Date: | 2004-04-02 05:43:23 |
Message-ID: | 406CFD7B.5060504@joeconway.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Greg Stark wrote:
> length(a) != array_upper(a)-array_lower(a)
[You really meant "array_upper(a) - array_lower(a) + 1" I'd guess]
length(A) is a missing function at the moment; the spec actually calls
it CARDINALITY. Once available, you would use it to determine array
length. SQL2003 says:
The result of <cardinality expression> is the number of elements of
the result of the <collection value expression>.
So, when A is an empty array, CARDINALITY(A) = 0, by definition.
> array_upper(a||b) == array_upper(a)+length(b)
Same here; this would be:
array_upper(a || b) == array_upper(a) + CARDINALITY(b)
and would work just fine. Note that if array-a is NULL, then the spec
defines a || b as NULL. See section 6.35:
2) If <array concatenation> is specified, then let AV1 be the value of
<array value expression 1> and let AV2 be the value of
<array primary>.
Case:
a) If either AV1 or AV2 is the null value, then the result of the
<array concatenation> is the null value.
b) If the sum of the cardinality of AV1 and the cardinality of AV2
is greater than IMDC, then an exception condition is raised:
data exception — array data, right truncation.
c) Otherwise, the result is the array comprising every element of
AV1 followed by every element of AV2.
> If someone implements pop and push it sure makes things weird that push
> doesn't always increment the length pop doesn't decrement the length until 0.
I have no idea what you're trying to say here. Current behavior
certainly increments length by one when you push an element (which is
what "array || element" effectively does). An empty array has length 0
before pushing an element on to it, and length 1 afterward. Pushing an
element onto a NULL array yields NULL, which is not explicitly defined
by the spec (that I can find), but is certainly consistent with the above.
As far as array_pop is concerned, we discussed the fact that it makes no
sense in the context of Postgres arrays -- see the archives from last
year in May.
> Perhaps you're worried that you have pick an arbitrary lower and upper bound
> and, strangely, that the upper bound would actually be one less than the lower
> bound such as [1,0]. However this isn't really any different than the normal
> case. All arrays in postgres have arbitrary lower bounds.
Again, I have no idea what you mean here.
> Fwiw, the int_aggregate function from int_aggregate.c in the contrib section
> makes arrays that don't violate these invariants. For empty arrays the
> dimensions are [0,-1].
Seems rather arbitrary to me. As I said to Josh, an empty array has
undefined bounds, literally.
> This isn't hypothetical for me. Whenever I end up replacing int_aggregate with
> a standard function that constructs your style arrays my app would break. I
> guess I'll have to add a coalesce(...,0) to my array_length() function to work
> around it. Which only seems like strong evidence it's the wrong behaviour.
Sorry, but these are not "my style" arrays, they are "Berkley style" ;-).
Anyway, CARDINALITY is what you really need -- hopefully I'll be able to
find time to address that and some ather array items before the 7.5
freeze. In the meantime, if you have a custom array_length function
already, why not make it return 0 for empty arrays -- then your problems
disappear:
create or replace function array_length(anyarray)
returns int as '
select
case
when $1 = ''{}'' then 0
else array_upper($1, 1) - array_lower($1, 1) + 1
end
' language sql;
CREATE FUNCTION
regression=# select array_length(array[1,2,3]);
array_length
--------------
3
(1 row)
regression=# select array_length('{}'::int4[]);
array_length
--------------
0
(1 row)
regression=# select array[1,2,3] || '{}'::int4[];
?column?
----------
{1,2,3}
(1 row)
regression=# select array_upper(array[1,2,3], 1) +
array_length('{}'::int4[]);
?column?
----------
3
(1 row)
HTH,
Joe
From | Date | Subject | |
---|---|---|---|
Next Message | Greg Stark | 2004-04-02 06:00:51 | Re: Inconsistent behavior on Array & Is Null? |
Previous Message | BARTKO, Zoltan | 2004-04-02 05:21:16 | i18n of PostgreSQL - part 1 |