diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2021-03-03 16:39:57 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2021-03-03 16:39:57 -0500 |
commit | 0a687c8f103d217ff1ca8c34a644b380d89bb0ad (patch) | |
tree | 6406e23e84feca1351f879b7ddaaa9edafb4cf6a /src/backend/utils/adt/arrayfuncs.c | |
parent | 3769e11a31831fc2f3bd4c4a24b4f45c352fb8fb (diff) | |
download | postgresql-0a687c8f103d217ff1ca8c34a644b380d89bb0ad.tar.gz postgresql-0a687c8f103d217ff1ca8c34a644b380d89bb0ad.zip |
Add trim_array() function.
This has been in the SQL spec since 2008. It's a pretty thin
wrapper around the array slice functionality, but the spec
says we should have it, so here it is.
Vik Fearing, reviewed by Dian Fay
Discussion: https://postgr.es/m/fc92ce17-9655-8ff1-c62a-4dc4c8ccd815@postgresfriends.org
Diffstat (limited to 'src/backend/utils/adt/arrayfuncs.c')
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index f7012cc5d98..17a16b4c5cc 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -6631,3 +6631,46 @@ width_bucket_array_variable(Datum operand, return left; } + +/* + * Trim the last N elements from an array by building an appropriate slice. + * Only the first dimension is trimmed. + */ +Datum +trim_array(PG_FUNCTION_ARGS) +{ + ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); + int n = PG_GETARG_INT32(1); + int array_length = ARR_DIMS(v)[0]; + int16 elmlen; + bool elmbyval; + char elmalign; + int lower[MAXDIM]; + int upper[MAXDIM]; + bool lowerProvided[MAXDIM]; + bool upperProvided[MAXDIM]; + Datum result; + + /* Per spec, throw an error if out of bounds */ + if (n < 0 || n > array_length) + ereport(ERROR, + (errcode(ERRCODE_ARRAY_ELEMENT_ERROR), + errmsg("number of elements to trim must be between 0 and %d", + array_length))); + + /* Set all the bounds as unprovided except the first upper bound */ + memset(lowerProvided, false, sizeof(lowerProvided)); + memset(upperProvided, false, sizeof(upperProvided)); + upper[0] = ARR_LBOUND(v)[0] + array_length - n - 1; + upperProvided[0] = true; + + /* Fetch the needed information about the element type */ + get_typlenbyvalalign(ARR_ELEMTYPE(v), &elmlen, &elmbyval, &elmalign); + + /* Get the slice */ + result = array_get_slice(PointerGetDatum(v), 1, + upper, lower, upperProvided, lowerProvided, + -1, elmlen, elmbyval, elmalign); + + PG_RETURN_DATUM(result); +} |