*
* NOTE: if we get a NULL result from a subscript expression, we return NULL
* when it's an array reference, or raise an error when it's an assignment.
- *
- * NOTE: we deliberately refrain from applying DatumGetArrayTypeP() here,
- * even though that might seem natural, because this code needs to support
- * both varlena arrays and fixed-length array types. DatumGetArrayTypeP()
- * only works for the varlena kind. The routines we call in arrayfuncs.c
- * have to know the difference (that's what they need refattrlength for).
*----------
*/
static Datum
ExprDoneCond *isDone)
{
ArrayRef *arrayRef = (ArrayRef *) astate->xprstate.expr;
- ArrayType *array_source;
- ArrayType *resultArray;
+ Datum array_source;
bool isAssignment = (arrayRef->refassgnexpr != NULL);
bool eisnull;
ListCell *l;
lower;
int *lIndex;
- array_source = (ArrayType *)
- DatumGetPointer(ExecEvalExpr(astate->refexpr,
- econtext,
- isNull,
- isDone));
+ array_source = ExecEvalExpr(astate->refexpr,
+ econtext,
+ isNull,
+ isDone);
/*
* If refexpr yields NULL, and it's a fetch, then result is NULL. In the
}
else if (lIndex == NULL)
{
- econtext->caseValue_datum = array_ref(array_source, i,
- upper.indx,
- astate->refattrlength,
- astate->refelemlength,
- astate->refelembyval,
- astate->refelemalign,
- &econtext->caseValue_isNull);
+ econtext->caseValue_datum =
+ array_get_element(array_source, i,
+ upper.indx,
+ astate->refattrlength,
+ astate->refelemlength,
+ astate->refelembyval,
+ astate->refelemalign,
+ &econtext->caseValue_isNull);
}
else
{
- resultArray = array_get_slice(array_source, i,
- upper.indx, lower.indx,
- astate->refattrlength,
- astate->refelemlength,
- astate->refelembyval,
- astate->refelemalign);
- econtext->caseValue_datum = PointerGetDatum(resultArray);
+ econtext->caseValue_datum =
+ array_get_slice(array_source, i,
+ upper.indx, lower.indx,
+ astate->refattrlength,
+ astate->refelemlength,
+ astate->refelembyval,
+ astate->refelemalign);
econtext->caseValue_isNull = false;
}
}
*/
if (astate->refattrlength > 0) /* fixed-length array? */
if (eisnull || *isNull)
- return PointerGetDatum(array_source);
+ return array_source;
/*
* For assignment to varlena arrays, we handle a NULL original array
*/
if (*isNull)
{
- array_source = construct_empty_array(arrayRef->refelemtype);
+ array_source = PointerGetDatum(construct_empty_array(arrayRef->refelemtype));
*isNull = false;
}
if (lIndex == NULL)
- resultArray = array_set(array_source, i,
- upper.indx,
- sourceData,
- eisnull,
- astate->refattrlength,
- astate->refelemlength,
- astate->refelembyval,
- astate->refelemalign);
+ return array_set_element(array_source, i,
+ upper.indx,
+ sourceData,
+ eisnull,
+ astate->refattrlength,
+ astate->refelemlength,
+ astate->refelembyval,
+ astate->refelemalign);
else
- resultArray = array_set_slice(array_source, i,
- upper.indx, lower.indx,
- (ArrayType *) DatumGetPointer(sourceData),
- eisnull,
- astate->refattrlength,
- astate->refelemlength,
- astate->refelembyval,
- astate->refelemalign);
- return PointerGetDatum(resultArray);
+ return array_set_slice(array_source, i,
+ upper.indx, lower.indx,
+ sourceData,
+ eisnull,
+ astate->refattrlength,
+ astate->refelemlength,
+ astate->refelembyval,
+ astate->refelemalign);
}
if (lIndex == NULL)
- return array_ref(array_source, i, upper.indx,
- astate->refattrlength,
- astate->refelemlength,
- astate->refelembyval,
- astate->refelemalign,
- isNull);
+ return array_get_element(array_source, i,
+ upper.indx,
+ astate->refattrlength,
+ astate->refelemlength,
+ astate->refelembyval,
+ astate->refelemalign,
+ isNull);
else
- {
- resultArray = array_get_slice(array_source, i,
- upper.indx, lower.indx,
- astate->refattrlength,
- astate->refelemlength,
- astate->refelembyval,
- astate->refelemalign);
- return PointerGetDatum(resultArray);
- }
+ return array_get_slice(array_source, i,
+ upper.indx, lower.indx,
+ astate->refattrlength,
+ astate->refelemlength,
+ astate->refelembyval,
+ astate->refelemalign);
}
/*
/*
- * array_ref :
- * This routine takes an array pointer and a subscript array and returns
+ * array_get_element :
+ * This routine takes an array datum and a subscript array and returns
* the referenced item as a Datum. Note that for a pass-by-reference
* datatype, the returned Datum is a pointer into the array object.
*
* This handles both ordinary varlena arrays and fixed-length arrays.
*
* Inputs:
- * array: the array object (mustn't be NULL)
+ * arraydatum: the array object (mustn't be NULL)
* nSubscripts: number of subscripts supplied
* indx[]: the subscript values
* arraytyplen: pg_type.typlen for the array type
* *isNull is set to indicate whether the element is NULL.
*/
Datum
-array_ref(ArrayType *array,
- int nSubscripts,
- int *indx,
- int arraytyplen,
- int elmlen,
- bool elmbyval,
- char elmalign,
- bool *isNull)
+array_get_element(Datum arraydatum,
+ int nSubscripts,
+ int *indx,
+ int arraytyplen,
+ int elmlen,
+ bool elmbyval,
+ char elmalign,
+ bool *isNull)
{
+ ArrayType *array;
int i,
ndim,
*dim,
fixedLb[0] = 0;
dim = fixedDim;
lb = fixedLb;
- arraydataptr = (char *) array;
+ arraydataptr = (char *) DatumGetPointer(arraydatum);
arraynullsptr = NULL;
}
else
{
/* detoast input array if necessary */
- array = DatumGetArrayTypeP(PointerGetDatum(array));
+ array = DatumGetArrayTypeP(arraydatum);
ndim = ARR_NDIM(array);
dim = ARR_DIMS(array);
* This handles both ordinary varlena arrays and fixed-length arrays.
*
* Inputs:
- * array: the array object (mustn't be NULL)
+ * arraydatum: the array object (mustn't be NULL)
* nSubscripts: number of subscripts supplied (must be same for upper/lower)
* upperIndx[]: the upper subscript values
* lowerIndx[]: the lower subscript values
* NOTE: we assume it is OK to scribble on the provided subscript arrays
* lowerIndx[] and upperIndx[]. These are generally just temporaries.
*/
-ArrayType *
-array_get_slice(ArrayType *array,
+Datum
+array_get_slice(Datum arraydatum,
int nSubscripts,
int *upperIndx,
int *lowerIndx,
bool elmbyval,
char elmalign)
{
+ ArrayType *array;
ArrayType *newarray;
int i,
ndim,
dim = fixedDim;
lb = fixedLb;
elemtype = InvalidOid; /* XXX */
- arraydataptr = (char *) array;
+ arraydataptr = (char *) DatumGetPointer(arraydatum);
arraynullsptr = NULL;
}
else
{
/* detoast input array if necessary */
- array = DatumGetArrayTypeP(PointerGetDatum(array));
+ array = DatumGetArrayTypeP(arraydatum);
ndim = ARR_NDIM(array);
dim = ARR_DIMS(array);
* slice, return an empty array.
*/
if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)
- return construct_empty_array(elemtype);
+ return PointerGetDatum(construct_empty_array(elemtype));
for (i = 0; i < nSubscripts; i++)
{
if (upperIndx[i] >= (dim[i] + lb[i]))
upperIndx[i] = dim[i] + lb[i] - 1;
if (lowerIndx[i] > upperIndx[i])
- return construct_empty_array(elemtype);
+ return PointerGetDatum(construct_empty_array(elemtype));
}
/* fill any missing subscript positions with full array range */
for (; i < ndim; i++)
lowerIndx[i] = lb[i];
upperIndx[i] = dim[i] + lb[i] - 1;
if (lowerIndx[i] > upperIndx[i])
- return construct_empty_array(elemtype);
+ return PointerGetDatum(construct_empty_array(elemtype));
}
mda_get_range(ndim, span, lowerIndx, upperIndx);
lowerIndx, upperIndx,
elmlen, elmbyval, elmalign);
- return newarray;
+ return PointerGetDatum(newarray);
}
/*
- * array_set :
- * This routine sets the value of an array element (specified by
+ * array_set_element :
+ * This routine sets the value of one array element (specified by
* a subscript array) to a new value specified by "dataValue".
*
* This handles both ordinary varlena arrays and fixed-length arrays.
*
* Inputs:
- * array: the initial array object (mustn't be NULL)
+ * arraydatum: the initial array object (mustn't be NULL)
* nSubscripts: number of subscripts supplied
* indx[]: the subscript values
* dataValue: the datum to be inserted at the given position
* NOTE: For assignments, we throw an error for invalid subscripts etc,
* rather than returning a NULL as the fetch operations do.
*/
-ArrayType *
-array_set(ArrayType *array,
- int nSubscripts,
- int *indx,
- Datum dataValue,
- bool isNull,
- int arraytyplen,
- int elmlen,
- bool elmbyval,
- char elmalign)
+Datum
+array_set_element(Datum arraydatum,
+ int nSubscripts,
+ int *indx,
+ Datum dataValue,
+ bool isNull,
+ int arraytyplen,
+ int elmlen,
+ bool elmbyval,
+ char elmalign)
{
+ ArrayType *array;
ArrayType *newarray;
int i,
ndim,
* fixed-length arrays -- these are assumed to be 1-d, 0-based. We
* cannot extend them, either.
*/
+ char *resultarray;
+
if (nSubscripts != 1)
ereport(ERROR,
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("cannot assign null value to an element of a fixed-length array")));
- newarray = (ArrayType *) palloc(arraytyplen);
- memcpy(newarray, array, arraytyplen);
- elt_ptr = (char *) newarray + indx[0] * elmlen;
+ resultarray = (char *) palloc(arraytyplen);
+ memcpy(resultarray, DatumGetPointer(arraydatum), arraytyplen);
+ elt_ptr = (char *) resultarray + indx[0] * elmlen;
ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, elt_ptr);
- return newarray;
+ return PointerGetDatum(resultarray);
}
if (nSubscripts <= 0 || nSubscripts > MAXDIM)
dataValue = PointerGetDatum(PG_DETOAST_DATUM(dataValue));
/* detoast input array if necessary */
- array = DatumGetArrayTypeP(PointerGetDatum(array));
+ array = DatumGetArrayTypeP(arraydatum);
ndim = ARR_NDIM(array);
lb[i] = indx[i];
}
- return construct_md_array(&dataValue, &isNull, nSubscripts,
- dim, lb, elmtype,
- elmlen, elmbyval, elmalign);
+ return PointerGetDatum(construct_md_array(&dataValue, &isNull,
+ nSubscripts, dim, lb,
+ elmtype,
+ elmlen, elmbyval, elmalign));
}
if (ndim != nSubscripts)
}
}
- return newarray;
+ return PointerGetDatum(newarray);
}
/*
* This handles both ordinary varlena arrays and fixed-length arrays.
*
* Inputs:
- * array: the initial array object (mustn't be NULL)
+ * arraydatum: the initial array object (mustn't be NULL)
* nSubscripts: number of subscripts supplied (must be same for upper/lower)
* upperIndx[]: the upper subscript values
* lowerIndx[]: the lower subscript values
- * srcArray: the source for the inserted values
- * isNull: indicates whether srcArray is NULL
+ * srcArrayDatum: the source for the inserted values
+ * isNull: indicates whether srcArrayDatum is NULL
* arraytyplen: pg_type.typlen for the array type
* elmlen: pg_type.typlen for the array's element type
* elmbyval: pg_type.typbyval for the array's element type
* NOTE: For assignments, we throw an error for silly subscripts etc,
* rather than returning a NULL or empty array as the fetch operations do.
*/
-ArrayType *
-array_set_slice(ArrayType *array,
+Datum
+array_set_slice(Datum arraydatum,
int nSubscripts,
int *upperIndx,
int *lowerIndx,
- ArrayType *srcArray,
+ Datum srcArrayDatum,
bool isNull,
int arraytyplen,
int elmlen,
bool elmbyval,
char elmalign)
{
+ ArrayType *array;
+ ArrayType *srcArray;
ArrayType *newarray;
int i,
ndim,
/* Currently, assignment from a NULL source array is a no-op */
if (isNull)
- return array;
+ return arraydatum;
if (arraytyplen > 0)
{
}
/* detoast arrays if necessary */
- array = DatumGetArrayTypeP(PointerGetDatum(array));
- srcArray = DatumGetArrayTypeP(PointerGetDatum(srcArray));
+ array = DatumGetArrayTypeP(arraydatum);
+ srcArray = DatumGetArrayTypeP(srcArrayDatum);
/* note: we assume srcArray contains no toasted elements */
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
errmsg("source array too small")));
- return construct_md_array(dvalues, dnulls, nSubscripts,
- dim, lb, elmtype,
- elmlen, elmbyval, elmalign);
+ return PointerGetDatum(construct_md_array(dvalues, dnulls, nSubscripts,
+ dim, lb, elmtype,
+ elmlen, elmbyval, elmalign));
}
if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)
}
}
- return newarray;
+ return PointerGetDatum(newarray);
+}
+
+/*
+ * array_ref : backwards compatibility wrapper for array_get_element
+ *
+ * This only works for detoasted/flattened varlena arrays, since the array
+ * argument is declared as "ArrayType *". However there's enough code like
+ * that to justify preserving this API.
+ */
+Datum
+array_ref(ArrayType *array, int nSubscripts, int *indx,
+ int arraytyplen, int elmlen, bool elmbyval, char elmalign,
+ bool *isNull)
+{
+ return array_get_element(PointerGetDatum(array), nSubscripts, indx,
+ arraytyplen, elmlen, elmbyval, elmalign,
+ isNull);
+}
+
+/*
+ * array_set : backwards compatibility wrapper for array_set_element
+ *
+ * This only works for detoasted/flattened varlena arrays, since the array
+ * argument and result are declared as "ArrayType *". However there's enough
+ * code like that to justify preserving this API.
+ */
+ArrayType *
+array_set(ArrayType *array, int nSubscripts, int *indx,
+ Datum dataValue, bool isNull,
+ int arraytyplen, int elmlen, bool elmbyval, char elmalign)
+{
+ return DatumGetArrayTypeP(array_set_element(PointerGetDatum(array),
+ nSubscripts, indx,
+ dataValue, isNull,
+ arraytyplen,
+ elmlen, elmbyval, elmalign));
}
/*
extern Datum array_replace(PG_FUNCTION_ARGS);
extern Datum width_bucket_array(PG_FUNCTION_ARGS);
+extern Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx,
+ int arraytyplen, int elmlen, bool elmbyval, char elmalign,
+ bool *isNull);
+extern Datum array_set_element(Datum arraydatum, int nSubscripts, int *indx,
+ Datum dataValue, bool isNull,
+ int arraytyplen, int elmlen, bool elmbyval, char elmalign);
+extern Datum array_get_slice(Datum arraydatum, int nSubscripts,
+ int *upperIndx, int *lowerIndx,
+ int arraytyplen, int elmlen, bool elmbyval, char elmalign);
+extern Datum array_set_slice(Datum arraydatum, int nSubscripts,
+ int *upperIndx, int *lowerIndx,
+ Datum srcArrayDatum, bool isNull,
+ int arraytyplen, int elmlen, bool elmbyval, char elmalign);
+
extern Datum array_ref(ArrayType *array, int nSubscripts, int *indx,
int arraytyplen, int elmlen, bool elmbyval, char elmalign,
bool *isNull);
extern ArrayType *array_set(ArrayType *array, int nSubscripts, int *indx,
Datum dataValue, bool isNull,
int arraytyplen, int elmlen, bool elmbyval, char elmalign);
-extern ArrayType *array_get_slice(ArrayType *array, int nSubscripts,
- int *upperIndx, int *lowerIndx,
- int arraytyplen, int elmlen, bool elmbyval, char elmalign);
-extern ArrayType *array_set_slice(ArrayType *array, int nSubscripts,
- int *upperIndx, int *lowerIndx,
- ArrayType *srcArray, bool isNull,
- int arraytyplen, int elmlen, bool elmbyval, char elmalign);
extern Datum array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType,
ArrayMapState *amstate);