On 1/19/14, 9:12 AM, Dean Rasheed wrote:
On 18 January 2014 03:07, Marko Tiikkaja <ma...@joh.to> wrote:
Here's the patch as promised. Thoughts?
A couple of points:
The answer for empty (zero dimensional) arrays is wrong --- you need
special case handling for this case to return 0.
How embarrassing. I don't know why I removed that check or how I didn't
catch the clearly wrong answer in the test output.
In fact why not
simply use ArrayGetNItems()?
Even better. Changed.
In the docs, in the table of array functions, I think it would
probably be useful to make the entry for array_length say "see also
cardinality", otherwise people might just stop reading there. I
suspect that in over 90% of cases, cardinality will be the more
appropriate function to use rather than array_length.
I don't see this as a huge improvement, but even worse, I don't see a
way to naturally fit it into the description.
New version attached, without the doc change.
Regards,
Marko Tiikkaja
*** a/doc/src/sgml/array.sgml
--- b/doc/src/sgml/array.sgml
***************
*** 338,343 **** SELECT array_length(schedule, 1) FROM sal_emp WHERE name =
'Carol';
--- 338,356 ----
2
(1 row)
</programlisting>
+
+ <function>cardinality</function> returns the total number of elements in an
+ array across all dimensions. It is effectively the number of rows a call to
+ <function>unnest</function> would yield:
+
+ <programlisting>
+ SELECT cardinality(schedule) FROM sal_emp WHERE name = 'Carol';
+
+ cardinality
+ -------------
+ 4
+ (1 row)
+ </programlisting>
</para>
</sect2>
*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
***************
*** 11009,11014 **** SELECT NULLIF(value, '(none)') ...
--- 11009,11017 ----
<primary>array_upper</primary>
</indexterm>
<indexterm>
+ <primary>cardinality</primary>
+ </indexterm>
+ <indexterm>
<primary>string_to_array</primary>
</indexterm>
<indexterm>
***************
*** 11167,11172 **** SELECT NULLIF(value, '(none)') ...
--- 11170,11186 ----
<row>
<entry>
<literal>
+ <function>cardinality</function>(<type>anyarray</type>)
+ </literal>
+ </entry>
+ <entry><type>int</type></entry>
+ <entry>returns the total number of elements in the array, or 0 if the
array is empty</entry>
+ <entry><literal>cardinality(ARRAY[[1,2],[3,4]])</literal></entry>
+ <entry><literal>4</literal></entry>
+ </row>
+ <row>
+ <entry>
+ <literal>
<function>string_to_array</function>(<type>text</type>,
<type>text</type> <optional>, <type>text</type></optional>)
</literal>
</entry>
*** a/src/backend/utils/adt/arrayfuncs.c
--- b/src/backend/utils/adt/arrayfuncs.c
***************
*** 1740,1745 **** array_length(PG_FUNCTION_ARGS)
--- 1740,1757 ----
}
/*
+ * array_cardinality:
+ * returns the total number of elements in an array
+ */
+ Datum
+ array_cardinality(PG_FUNCTION_ARGS)
+ {
+ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
+ PG_RETURN_INT32(ArrayGetNItems(ARR_NDIM(v), ARR_DIMS(v)));
+ }
+
+
+ /*
* array_ref :
* This routine takes an array pointer and a subscript array and returns
* the referenced item as a Datum. Note that for a pass-by-reference
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 840,845 **** DATA(insert OID = 2092 ( array_upper PGNSP PGUID 12 1 0 0
0 f f f f t f i 2
--- 840,847 ----
DESCR("array upper dimension");
DATA(insert OID = 2176 ( array_length PGNSP PGUID 12 1 0 0 0 f f f
f t f i 2 0 23 "2277 23" _null_ _null_ _null_ _null_ array_length _null_ _null_
_null_ ));
DESCR("array length");
+ DATA(insert OID = 3179 ( cardinality PGNSP PGUID 12 1 0 0 0 f f f f t f i
1 0 23 "2277" _null_ _null_ _null_ _null_ array_cardinality _null_ _null_
_null_ ));
+ DESCR("array cardinality");
DATA(insert OID = 378 ( array_append PGNSP PGUID 12 1 0 0 0 f f f f f f i
2 0 2277 "2277 2283" _null_ _null_ _null_ _null_ array_push _null_ _null_
_null_ ));
DESCR("append element onto end of array");
DATA(insert OID = 379 ( array_prepend PGNSP PGUID 12 1 0 0 0 f f f
f f f i 2 0 2277 "2283 2277" _null_ _null_ _null_ _null_ array_push _null_
_null_ _null_ ));
*** a/src/include/utils/array.h
--- b/src/include/utils/array.h
***************
*** 204,209 **** extern Datum array_dims(PG_FUNCTION_ARGS);
--- 204,210 ----
extern Datum array_lower(PG_FUNCTION_ARGS);
extern Datum array_upper(PG_FUNCTION_ARGS);
extern Datum array_length(PG_FUNCTION_ARGS);
+ extern Datum array_cardinality(PG_FUNCTION_ARGS);
extern Datum array_larger(PG_FUNCTION_ARGS);
extern Datum array_smaller(PG_FUNCTION_ARGS);
extern Datum generate_subscripts(PG_FUNCTION_ARGS);
*** a/src/test/regress/expected/arrays.out
--- b/src/test/regress/expected/arrays.out
***************
*** 1455,1460 **** select array_length(array[[1,2,3], [4,5,6]], 3);
--- 1455,1502 ----
(1 row)
+ select cardinality(NULL::int[]);
+ cardinality
+ -------------
+
+ (1 row)
+
+ select cardinality('{}'::int[]);
+ cardinality
+ -------------
+ 0
+ (1 row)
+
+ select cardinality(array[1,2,3]);
+ cardinality
+ -------------
+ 3
+ (1 row)
+
+ select cardinality('[2:4]={5,6,7}'::int[]);
+ cardinality
+ -------------
+ 3
+ (1 row)
+
+ select cardinality('{{1,2}}'::int[]);
+ cardinality
+ -------------
+ 2
+ (1 row)
+
+ select cardinality('{{1,2},{3,4},{5,6}}'::int[]);
+ cardinality
+ -------------
+ 6
+ (1 row)
+
+ select cardinality('{{{1}},{{2,3},{3,4}}}'::int[]);
+ cardinality
+ -------------
+ 8
+ (1 row)
+
select array_agg(unique1) from (select unique1 from tenk1 where unique1 < 15
order by unique1) ss;
array_agg
--------------------------------------
*** a/src/test/regress/sql/arrays.sql
--- b/src/test/regress/sql/arrays.sql
***************
*** 419,424 **** select array_length(array[[1,2,3], [4,5,6]], 1);
--- 419,432 ----
select array_length(array[[1,2,3], [4,5,6]], 2);
select array_length(array[[1,2,3], [4,5,6]], 3);
+ select cardinality(NULL::int[]);
+ select cardinality('{}'::int[]);
+ select cardinality(array[1,2,3]);
+ select cardinality('[2:4]={5,6,7}'::int[]);
+ select cardinality('{{1,2}}'::int[]);
+ select cardinality('{{1,2},{3,4},{5,6}}'::int[]);
+ select cardinality('{{{1}},{{2,3},{3,4}}}'::int[]);
+
select array_agg(unique1) from (select unique1 from tenk1 where unique1 < 15
order by unique1) ss;
select array_agg(ten) from (select ten from tenk1 where unique1 < 15 order by
unique1) ss;
select array_agg(nullif(ten, 4)) from (select ten from tenk1 where unique1 <
15 order by unique1) ss;
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers