summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Haas2014-01-21 17:38:53 +0000
committerRobert Haas2014-01-21 17:38:53 +0000
commit01f7808b3eafcae1f6077f2f61e13b4c132ccd47 (patch)
tree744e328b7dddbdd7294e341f6165d58e51024cdd
parent033b2343fae9d8c9df124cde62087dcb481c9c5e (diff)
Add a cardinality function for arrays.
Unlike our other array functions, this considers the total number of elements across all dimensions, and returns 0 rather than NULL when the array has no elements. But it seems that both of those behaviors are almost universally disliked, so hopefully that's OK. Marko Tiikkaja, reviewed by Dean Rasheed and Pavel Stehule
-rw-r--r--doc/src/sgml/array.sgml13
-rw-r--r--doc/src/sgml/func.sgml14
-rw-r--r--src/backend/utils/adt/arrayfuncs.c12
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_proc.h2
-rw-r--r--src/include/utils/array.h1
-rw-r--r--src/test/regress/expected/arrays.out42
-rw-r--r--src/test/regress/sql/arrays.sql8
8 files changed, 93 insertions, 1 deletions
diff --git a/doc/src/sgml/array.sgml b/doc/src/sgml/array.sgml
index 8b36d4ab85f..9ea10682a56 100644
--- a/doc/src/sgml/array.sgml
+++ b/doc/src/sgml/array.sgml
@@ -338,6 +338,19 @@ SELECT array_length(schedule, 1) FROM sal_emp WHERE name = 'Carol';
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>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index c76d357df24..53021c227d7 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -11009,6 +11009,9 @@ SELECT NULLIF(value, '(none)') ...
<primary>array_upper</primary>
</indexterm>
<indexterm>
+ <primary>cardinality</primary>
+ </indexterm>
+ <indexterm>
<primary>string_to_array</primary>
</indexterm>
<indexterm>
@@ -11167,6 +11170,17 @@ SELECT NULLIF(value, '(none)') ...
<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>
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index d52101663a1..311d0c22f06 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -1740,6 +1740,18 @@ array_length(PG_FUNCTION_ARGS)
}
/*
+ * 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
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 89eb7018f67..0aca05741c1 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201312231
+#define CATALOG_VERSION_NO 201401211
#endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index ab05c460c53..ad9774c2856 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -840,6 +840,8 @@ DATA(insert OID = 2092 ( array_upper PGNSP PGUID 12 1 0 0 0 f f f f t f i 2
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_ ));
diff --git a/src/include/utils/array.h b/src/include/utils/array.h
index f6135a6cbb6..9bbfaae85ef 100644
--- a/src/include/utils/array.h
+++ b/src/include/utils/array.h
@@ -204,6 +204,7 @@ extern Datum array_dims(PG_FUNCTION_ARGS);
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);
diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out
index 23b3902017b..e1b9d7f0a84 100644
--- a/src/test/regress/expected/arrays.out
+++ b/src/test/regress/expected/arrays.out
@@ -1455,6 +1455,48 @@ select array_length(array[[1,2,3], [4,5,6]], 3);
(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
--------------------------------------
diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql
index e4f9f316ce4..64630d9ab78 100644
--- a/src/test/regress/sql/arrays.sql
+++ b/src/test/regress/sql/arrays.sql
@@ -419,6 +419,14 @@ select array_length(array[[1,2,3], [4,5,6]], 1);
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;