diff --git a/doc/src/sgml/array.sgml b/doc/src/sgml/array.sgml index bb4657e..dc7b6f4 100644 --- a/doc/src/sgml/array.sgml +++ b/doc/src/sgml/array.sgml @@ -224,7 +224,9 @@ SELECT name FROM sal_emp WHERE pay_by_quarter[1] <> pay_by_quarter[2]; By default PostgreSQL uses a one-based numbering convention for arrays, that is, an array of n elements starts with array[1] and - ends with array[n]. + ends with array[n]. Negative + array subscript numbers indicate that the position of the element is calculated from + the end of the array, with -1 indicating the last element in the array. @@ -242,6 +244,34 @@ SELECT pay_by_quarter[3] FROM sal_emp; + This query retrieves the last quarter pay of all employees: + + +SELECT pay_by_quarter[-1] FROM sal_emp; + + pay_by_quarter +---------------- + 10000 + 25000 +(2 rows) + + + + + This query retrieves the pay of all employees for the last three quarters: + +SELECT pay_by_quarter[-3:4] FROM sal_emp; + + pay_by_quarter +--------------------- + {10000,10000,10000} + {25000,25000,25000} +(2 rows) + + + + + We can also access arbitrary rectangular slices of an array, or subarrays. An array slice is denoted by writing lower-bound:upper-bound diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index fb4cbce..9d6c3f1 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -1786,6 +1786,8 @@ array_ref(ArrayType *array, } for (i = 0; i < ndim; i++) { + if (indx[i] < 0) /* A negative index number indicates a position calculated from the end of the array */ + indx[i] = dim[i] + indx[i] + lb[i]; if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i])) { *isNull = true; @@ -1914,6 +1916,10 @@ array_get_slice(ArrayType *array, for (i = 0; i < nSubscripts; i++) { + if (lowerIndx[i] < 0) /* A negative index number indicates a position calculated from the end of the array */ + lowerIndx[i] = dim[i] + lowerIndx[i] + lb[i]; + if (upperIndx[i] < 0) /* A negative index number indicates a position calculated from the end of the array */ + upperIndx[i] = dim[i] + upperIndx[i] + lb[i]; if (lowerIndx[i] < lb[i]) lowerIndx[i] = lb[i]; if (upperIndx[i] >= (dim[i] + lb[i]))