summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Eisentraut2008-11-12 13:09:28 +0000
committerPeter Eisentraut2008-11-12 13:09:28 +0000
commit89d8bd3e2275229a0d3168e5e4cb4af51791f935 (patch)
treec0bec90ee374e1c2e24b69c8f595ff189e1d8cdc
parent3c9f4290e2814cdf70a5ca3eb9cd0fa67752e744 (diff)
array_length() function, and for SQL compatibility also cardinality()
function as a special case. This version still has the suspicious behavior of returning null for an empty array (rather than zero), but this may need a wholesale revision of empty array behavior, currently under discussion. Jim Nasby, Robert Haas, Peter Eisentraut
-rw-r--r--doc/src/sgml/array.sgml12
-rw-r--r--doc/src/sgml/func.sgml24
-rw-r--r--src/backend/utils/adt/arrayfuncs.c28
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_proc.h4
-rw-r--r--src/include/utils/array.h1
-rw-r--r--src/test/regress/expected/arrays.out50
-rw-r--r--src/test/regress/sql/arrays.sql9
8 files changed, 129 insertions, 1 deletions
diff --git a/doc/src/sgml/array.sgml b/doc/src/sgml/array.sgml
index 32fd58138b..84f3ea591a 100644
--- a/doc/src/sgml/array.sgml
+++ b/doc/src/sgml/array.sgml
@@ -325,6 +325,18 @@ SELECT array_upper(schedule, 1) FROM sal_emp WHERE name = 'Carol';
2
(1 row)
</programlisting>
+
+ <function>array_length</function> will return the length of a specified
+ array dimension:
+
+<programlisting>
+SELECT array_length(schedule, 1) FROM sal_emp WHERE name = 'Carol';
+
+ array_length
+--------------
+ 2
+(1 row)
+</programlisting>
</para>
</sect2>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 07dcb9baf6..393d4357b3 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -9411,6 +9411,17 @@ SELECT NULLIF(value, '(none)') ...
<row>
<entry>
<literal>
+ <function>array_length</function>(<type>anyarray</type>, <type>int</type>)
+ </literal>
+ </entry>
+ <entry><type>int</type></entry>
+ <entry>returns the length of the requested array dimension</entry>
+ <entry><literal>array_length(array[1,2,3], 1)</literal></entry>
+ <entry><literal>3</literal></entry>
+ </row>
+ <row>
+ <entry>
+ <literal>
<function>array_lower</function>(<type>anyarray</type>, <type>int</type>)
</literal>
</entry>
@@ -9455,6 +9466,19 @@ SELECT NULLIF(value, '(none)') ...
<row>
<entry>
<literal>
+ <function>cardinality</function>(<type>anyarray</type>)
+ </literal>
+ </entry>
+ <entry><type>int</type></entry>
+ <entry>returns the length of the first dimension of the array
+ (special case of <function>array_length</function> for SQL
+ compatibility)</entry>
+ <entry><literal>cardinality(array[1,2,3])</literal></entry>
+ <entry><literal>3</literal></entry>
+ </row>
+ <row>
+ <entry>
+ <literal>
<function>string_to_array</function>(<type>text</type>, <type>text</type>)
</literal>
</entry>
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 497d066389..4b32c7a762 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -1641,6 +1641,34 @@ array_upper(PG_FUNCTION_ARGS)
}
/*
+ * array_length :
+ * returns the length, of the dimension requested, for
+ * the array pointed to by "v", as an int4
+ */
+Datum
+array_length(PG_FUNCTION_ARGS)
+{
+ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
+ int reqdim = PG_GETARG_INT32(1);
+ int *dimv;
+ int result;
+
+ /* Sanity check: does it look like an array at all? */
+ if (ARR_NDIM(v) <= 0 || ARR_NDIM(v) > MAXDIM)
+ PG_RETURN_NULL();
+
+ /* Sanity check: was the requested dim valid */
+ if (reqdim <= 0 || reqdim > ARR_NDIM(v))
+ PG_RETURN_NULL();
+
+ dimv = ARR_DIMS(v);
+
+ result = dimv[reqdim - 1];
+
+ PG_RETURN_INT32(result);
+}
+
+/*
* 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 9bb3c681ae..0860b52f6b 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200811091
+#define CATALOG_VERSION_NO 200811121
#endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index fe20b01e75..6c8b07a9c2 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -996,6 +996,10 @@ DATA(insert OID = 2091 ( array_lower PGNSP PGUID 12 1 0 0 f f t f i 2 23 "22
DESCR("array lower dimension");
DATA(insert OID = 2092 ( array_upper PGNSP PGUID 12 1 0 0 f f t f i 2 23 "2277 23" _null_ _null_ _null_ array_upper _null_ _null_ _null_ ));
DESCR("array upper dimension");
+DATA(insert OID = 2176 ( array_length PGNSP PGUID 12 1 0 0 f f t f i 2 23 "2277 23" _null_ _null_ _null_ array_length _null_ _null_ _null_ ));
+DESCR("array length");
+DATA(insert OID = 2179 ( cardinality PGNSP PGUID 14 1 0 0 f f t f i 1 23 "2277" _null_ _null_ _null_ "select array_length($1, 1)" _null_ _null_ _null_ ));
+DESCR("array length");
DATA(insert OID = 378 ( array_append PGNSP PGUID 12 1 0 0 f f f f i 2 2277 "2277 2283" _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 f f f f i 2 2277 "2283 2277" _null_ _null_ _null_ array_push _null_ _null_ _null_ ));
diff --git a/src/include/utils/array.h b/src/include/utils/array.h
index 500966de65..a26d733f24 100644
--- a/src/include/utils/array.h
+++ b/src/include/utils/array.h
@@ -199,6 +199,7 @@ extern Datum array_ndims(PG_FUNCTION_ARGS);
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_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 c538fad621..804d52b798 100644
--- a/src/test/regress/expected/arrays.out
+++ b/src/test/regress/expected/arrays.out
@@ -1075,3 +1075,53 @@ select array_to_string(string_to_array('1|2|3', '|'), '|');
1|2|3
(1 row)
+select array_length(array[1,2,3], 1);
+ array_length
+--------------
+ 3
+(1 row)
+
+select array_length(array[[1,2,3], [4,5,6]], 0);
+ array_length
+--------------
+
+(1 row)
+
+select array_length(array[[1,2,3], [4,5,6]], 1);
+ array_length
+--------------
+ 2
+(1 row)
+
+select array_length(array[[1,2,3], [4,5,6]], 2);
+ array_length
+--------------
+ 3
+(1 row)
+
+select array_length(array[[1,2,3], [4,5,6]], 3);
+ array_length
+--------------
+
+(1 row)
+
+select cardinality(array[1,2,3]);
+ cardinality
+-------------
+ 3
+(1 row)
+
+select cardinality(array[[1,2,3], [4,5,6]]);
+ cardinality
+-------------
+ 2
+(1 row)
+
+select c, cardinality(c), d, cardinality(d) from arrtest;
+ c | cardinality | d | cardinality
+-------------------+-------------+---------------+-------------
+ {} | | {} |
+ {foobar,new_word} | 2 | {{elt1,elt2}} | 1
+ {foo,new_word} | 2 | {bar,foo} | 2
+(3 rows)
+
diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql
index a15b81ab28..04b19a4ace 100644
--- a/src/test/regress/sql/arrays.sql
+++ b/src/test/regress/sql/arrays.sql
@@ -386,3 +386,12 @@ select string_to_array('1|2|3', NULL);
select string_to_array(NULL, '|');
select array_to_string(string_to_array('1|2|3', '|'), '|');
+
+select array_length(array[1,2,3], 1);
+select array_length(array[[1,2,3], [4,5,6]], 0);
+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(array[1,2,3]);
+select cardinality(array[[1,2,3], [4,5,6]]);
+select c, cardinality(c), d, cardinality(d) from arrtest;