2015-03-21 0:27 GMT+01:00 Jim Nasby <jim.na...@bluetreble.com>: > On 3/20/15 2:48 PM, Pavel Stehule wrote: > >> >> >> 2015-03-20 18:47 GMT+01:00 Tom Lane <t...@sss.pgh.pa.us >> <mailto:t...@sss.pgh.pa.us>>: >> >> Alvaro Herrera <alvhe...@2ndquadrant.com >> <mailto:alvhe...@2ndquadrant.com>> writes: >> > Pavel Stehule wrote: >> >> I am thinking, so it is ok - it returns a offset, not position. >> >> > So you can't use it as a subscript? That sounds unfriendly. Almost >> > every function using this will be subtly broken. >> >> I concur; perhaps "offset" was the design intention, but it's wrong. >> The result should be a subscript. >> >> >> do you have any idea about name for this function? array_position is ok? >> > > +1 on array_position. It's possible at some point we'll actually want > array_offset that does what it claims. >
additional implementation of array_position needs few lines more > > On another note, you mentioned elsewhere that it's not possible to return > anything other than an integer. Why can't there be a variation of this > function that returns an array of ndims-1 that is the slice where a value > was found? We talked about it, when we talked about MD searching - and we moved it to next stage. I am thinking so array_postions can support MD arrays due returning a array Regards Pavel > > > -- > Jim Nasby, Data Architect, Blue Treble Consulting > Data in Trouble? Get it in Treble! http://BlueTreble.com >
commit 8ceb761fcd4bca3859c0ec371ec783a36795dd49 Author: Pavel Stehule <pavel.steh...@gooddata.com> Date: Sat Mar 21 07:01:51 2015 +0100 initial diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c index 57074e0..91e2824 100644 --- a/src/backend/utils/adt/array_userfuncs.c +++ b/src/backend/utils/adt/array_userfuncs.c @@ -19,8 +19,8 @@ #include "utils/typcache.h" -static Datum array_offset_common(FunctionCallInfo fcinfo); - +static Datum array_offset_common(FunctionCallInfo fcinfo, bool expected_position); +static Datum array_offsets_common(FunctionCallInfo fcinfo, bool expected_position); /* * fetch_array_arg_replace_nulls @@ -669,13 +669,33 @@ array_agg_array_finalfn(PG_FUNCTION_ARGS) Datum array_offset(PG_FUNCTION_ARGS) { - return array_offset_common(fcinfo); + return array_offset_common(fcinfo, false); } Datum array_offset_start(PG_FUNCTION_ARGS) { - return array_offset_common(fcinfo); + return array_offset_common(fcinfo, false); +} + +/*----------------------------------------------------------------------------- + * array_positiob, array_position_start : + * return the position of a value in an array. + * + * IS NOT DISTINCT FROM semantics are used for comparisons. Return NULL when + * the value is not found. + *----------------------------------------------------------------------------- + */ +Datum +array_position(PG_FUNCTION_ARGS) +{ + return array_offset_common(fcinfo, true); +} + +Datum +array_position_start(PG_FUNCTION_ARGS) +{ + return array_offset_common(fcinfo, true); } /* @@ -686,7 +706,7 @@ array_offset_start(PG_FUNCTION_ARGS) * They are not strict so we have to test for null inputs explicitly. */ static Datum -array_offset_common(FunctionCallInfo fcinfo) +array_offset_common(FunctionCallInfo fcinfo, bool expected_positions) { ArrayType *array; Oid collation = PG_GET_COLLATION(); @@ -701,6 +721,7 @@ array_offset_common(FunctionCallInfo fcinfo) ArrayMetaState *my_extra; bool null_search; ArrayIterator array_iterator; + int lb = 1; if (PG_ARGISNULL(0)) PG_RETURN_NULL(); @@ -731,6 +752,8 @@ array_offset_common(FunctionCallInfo fcinfo) null_search = false; } + lb = expected_positions ? (ARR_LBOUND(array))[0] : 1; + /* figure out where to start */ if (PG_NARGS() == 3) { @@ -739,7 +762,7 @@ array_offset_common(FunctionCallInfo fcinfo) (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("initial offset should not be NULL"))); - offset_min = PG_GETARG_INT32(2); + offset_min = PG_GETARG_INT32(2) - lb + 1; } else offset_min = 1; @@ -818,9 +841,25 @@ array_offset_common(FunctionCallInfo fcinfo) if (!found) PG_RETURN_NULL(); - PG_RETURN_INT32(offset); + PG_RETURN_INT32(offset + lb - 1); +} + +/* + * simple wrappers over array_offsets_common + */ +Datum +array_offsets(PG_FUNCTION_ARGS) +{ + return array_offsets_common(fcinfo, false); } +Datum +array_positions(PG_FUNCTION_ARGS) +{ + return array_offsets_common(fcinfo, true); +} + + /*----------------------------------------------------------------------------- * array_offsets : * return an array of offsets of a value in an array. @@ -833,7 +872,7 @@ array_offset_common(FunctionCallInfo fcinfo) *----------------------------------------------------------------------------- */ Datum -array_offsets(PG_FUNCTION_ARGS) +array_offsets_common(FunctionCallInfo fcinfo, bool expected_positions) { ArrayType *array; Oid collation = PG_GET_COLLATION(); @@ -847,6 +886,7 @@ array_offsets(PG_FUNCTION_ARGS) bool null_search; ArrayIterator array_iterator; ArrayBuildState *astate = NULL; + int lb; if (PG_ARGISNULL(0)) PG_RETURN_NULL(); @@ -879,6 +919,8 @@ array_offsets(PG_FUNCTION_ARGS) null_search = false; } + lb = expected_positions ? (ARR_LBOUND(array))[0] : 1; + /* * We arrange to look up type info for array_create_iterator only once per * series of calls, assuming the element type doesn't change underneath us. @@ -937,7 +979,7 @@ array_offsets(PG_FUNCTION_ARGS) if (DatumGetBool(FunctionCall2Coll(&my_extra->proc, collation, searched_element, value))) astate = - accumArrayResult(astate, Int32GetDatum(offset), false, + accumArrayResult(astate, Int32GetDatum(offset + lb - 1), false, INT4OID, CurrentMemoryContext); } diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 3c218a3..64e768c 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -901,6 +901,12 @@ DATA(insert OID = 3278 ( array_offset PGNSP PGUID 12 1 0 0 0 f f f f f f i DESCR("returns a offset of value in array with start index"); DATA(insert OID = 3279 ( array_offsets PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 1007 "2277 2283" _null_ _null_ _null_ _null_ array_offsets _null_ _null_ _null_ )); DESCR("returns a array of offsets of some value in array"); +DATA(insert OID = 3394 ( array_position PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 23 "2277 2283" _null_ _null_ _null_ _null_ array_position _null_ _null_ _null_ )); +DESCR("returns a position of value in array"); +DATA(insert OID = 3395 ( array_position PGNSP PGUID 12 1 0 0 0 f f f f f f i 3 0 23 "2277 2283 23" _null_ _null_ _null_ _null_ array_position_start _null_ _null_ _null_ )); +DESCR("returns a position of value in array with start index"); +DATA(insert OID = 3396 ( array_positions PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 1007 "2277 2283" _null_ _null_ _null_ _null_ array_positions _null_ _null_ _null_ )); +DESCR("returns a array of positions of some value in array"); DATA(insert OID = 1191 ( generate_subscripts PGNSP PGUID 12 1 1000 0 0 f f f f t t i 3 0 23 "2277 23 16" _null_ _null_ _null_ _null_ generate_subscripts _null_ _null_ _null_ )); DESCR("array subscripts generator"); DATA(insert OID = 1192 ( generate_subscripts PGNSP PGUID 12 1 1000 0 0 f f f f t t i 2 0 23 "2277 23" _null_ _null_ _null_ _null_ generate_subscripts_nodir _null_ _null_ _null_ )); diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out index 14d6d32..5c46719 100644 --- a/src/test/regress/expected/arrays.out +++ b/src/test/regress/expected/arrays.out @@ -466,6 +466,18 @@ $$ LANGUAGE plpgsql; NOTICE: 2 NOTICE: 4 NOTICE: 7 +SELECT array_position('[2:4]={1,2,3}'::int[], 1); + array_position +---------------- + 2 +(1 row) + +SELECT array_positions('[2:4]={1,2,3}'::int[], 1); + array_positions +----------------- + {2} +(1 row) + -- operators SELECT a FROM arrtest WHERE b = ARRAY[[[113,142],[1,147]]]; a diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql index 40950a2..435e242 100644 --- a/src/test/regress/sql/arrays.sql +++ b/src/test/regress/sql/arrays.sql @@ -218,6 +218,9 @@ BEGIN END $$ LANGUAGE plpgsql; +SELECT array_position('[2:4]={1,2,3}'::int[], 1); +SELECT array_positions('[2:4]={1,2,3}'::int[], 1); + -- operators SELECT a FROM arrtest WHERE b = ARRAY[[[113,142],[1,147]]]; SELECT NOT ARRAY[1.1,1.2,1.3] = ARRAY[1.1,1.2,1.3] AS "FALSE";
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers