>> There is a tiny problem with this implementation: It returns null for an
>> empty array, not zero. This is because array_lower and/or array_upper
>> return null for an empty array, which makes sense for those cases. We
>> could fix this by putting a coalesce around the expression, but since
>> the array functions return null for all kinds of error cases, this might
>> mask other problems. Or we move to a C implementation.
Hmm... the problem is that an empty array is really zero-dimensional.
So for what values of the second argument ought we to return 0?
It certainly seems inconsistent to say that array_length({}, 6) = 0
and array_length({1}, 6) is null.
We do need a good way to test for an empty array, though. Right now I
think the best ways is array_ndims(x) IS NULL (should it return 0
rather than NULL on an empty array?).
> Basic functionality like this shouldn't be implemented as a SQL function
> anyway. People don't expect that some built-in functions should be
> several orders of magnitude slower than other built-in functions of
> apparently similar complexity.
C implementation attached.
...Robert
Index: doc/src/sgml/array.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/array.sgml,v
retrieving revision 1.67
diff -c -r1.67 array.sgml
*** doc/src/sgml/array.sgml 29 Oct 2008 11:24:52 -0000 1.67
--- doc/src/sgml/array.sgml 7 Nov 2008 03:35:14 -0000
***************
*** 325,330 ****
--- 325,342 ----
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>
Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.455
diff -c -r1.455 func.sgml
*** doc/src/sgml/func.sgml 4 Nov 2008 14:49:11 -0000 1.455
--- doc/src/sgml/func.sgml 7 Nov 2008 03:35:24 -0000
***************
*** 9411,9416 ****
--- 9411,9427 ----
<row>
<entry>
<literal>
+ <function>array_length</function>(<type>anyarray</type>, <type>int</type>)
+ </literal>
+ </entry>
+ <entry><type>int</type></entry>
+ <entry>returns 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>
Index: src/backend/utils/adt/arrayfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v
retrieving revision 1.148
diff -c -r1.148 arrayfuncs.c
*** src/backend/utils/adt/arrayfuncs.c 4 Nov 2008 14:49:11 -0000 1.148
--- src/backend/utils/adt/arrayfuncs.c 7 Nov 2008 03:35:28 -0000
***************
*** 1641,1646 ****
--- 1641,1675 ----
}
/*
+ * array_length :
+ * returns the length, of the DIM 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,
+ *lb;
+ 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
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.524
diff -c -r1.524 pg_proc.h
*** src/include/catalog/pg_proc.h 4 Nov 2008 14:49:11 -0000 1.524
--- src/include/catalog/pg_proc.h 7 Nov 2008 03:35:37 -0000
***************
*** 996,1001 ****
--- 996,1003 ----
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 = 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_ ));
Index: src/include/utils/array.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/utils/array.h,v
retrieving revision 1.69
diff -c -r1.69 array.h
*** src/include/utils/array.h 4 Nov 2008 14:49:12 -0000 1.69
--- src/include/utils/array.h 7 Nov 2008 03:35:38 -0000
***************
*** 199,204 ****
--- 199,205 ----
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);
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers