arrayfuncs.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 2,484 行 · 第 1/5 页
C
2,484 行
bitmap = ARR_NULLBITMAP(v); bitmask = 1; for (i = 0; i < nitems; i++) { /* Get source element, checking for NULL */ if (bitmap && (*bitmap & bitmask) == 0) { /* -1 length means a NULL */ pq_sendint(&buf, -1, 4); } else { Datum itemvalue; bytea *outputbytes; itemvalue = fetch_att(p, typbyval, typlen); outputbytes = SendFunctionCall(&my_extra->proc, itemvalue); pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4); pq_sendbytes(&buf, VARDATA(outputbytes), VARSIZE(outputbytes) - VARHDRSZ); pfree(outputbytes); p = att_addlength_pointer(p, typlen, p); p = (char *) att_align_nominal(p, typalign); } /* advance bitmap pointer if any */ if (bitmap) { bitmask <<= 1; if (bitmask == 0x100) { bitmap++; bitmask = 1; } } } PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/* * array_dims : * returns the dimensions of the array pointed to by "v", as a "text" */Datumarray_dims(PG_FUNCTION_ARGS){ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); text *result; char *p; int nbytes, i; int *dimv, *lb; /* Sanity check: does it look like an array at all? */ if (ARR_NDIM(v) <= 0 || ARR_NDIM(v) > MAXDIM) PG_RETURN_NULL(); nbytes = ARR_NDIM(v) * 33 + 1; /* * 33 since we assume 15 digits per number + ':' +'[]' * * +1 allows for temp trailing null */ result = (text *) palloc(nbytes + VARHDRSZ); p = VARDATA(result); dimv = ARR_DIMS(v); lb = ARR_LBOUND(v); for (i = 0; i < ARR_NDIM(v); i++) { sprintf(p, "[%d:%d]", lb[i], dimv[i] + lb[i] - 1); p += strlen(p); } SET_VARSIZE(result, strlen(VARDATA(result)) + VARHDRSZ); PG_RETURN_TEXT_P(result);}/* * array_lower : * returns the lower dimension, of the DIM requested, for * the array pointed to by "v", as an int4 */Datumarray_lower(PG_FUNCTION_ARGS){ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); int reqdim = PG_GETARG_INT32(1); int *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(); lb = ARR_LBOUND(v); result = lb[reqdim - 1]; PG_RETURN_INT32(result);}/* * array_upper : * returns the upper dimension, of the DIM requested, for * the array pointed to by "v", as an int4 */Datumarray_upper(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(); lb = ARR_LBOUND(v); dimv = ARR_DIMS(v); result = dimv[reqdim - 1] + lb[reqdim - 1] - 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 * 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) * nSubscripts: number of subscripts supplied * indx[]: the subscript values * 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 * elmalign: pg_type.typalign for the array's element type * * Outputs: * The return value is the element Datum. * *isNull is set to indicate whether the element is NULL. */Datumarray_ref(ArrayType *array, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull){ int i, ndim, *dim, *lb, offset, fixedDim[1], fixedLb[1]; char *arraydataptr, *retptr; bits8 *arraynullsptr; if (arraytyplen > 0) { /* * fixed-length arrays -- these are assumed to be 1-d, 0-based */ ndim = 1; fixedDim[0] = arraytyplen / elmlen; fixedLb[0] = 0; dim = fixedDim; lb = fixedLb; arraydataptr = (char *) array; arraynullsptr = NULL; } else { /* detoast input array if necessary */ array = DatumGetArrayTypeP(PointerGetDatum(array)); ndim = ARR_NDIM(array); dim = ARR_DIMS(array); lb = ARR_LBOUND(array); arraydataptr = ARR_DATA_PTR(array); arraynullsptr = ARR_NULLBITMAP(array); } /* * Return NULL for invalid subscript */ if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM) { *isNull = true; return (Datum) 0; } for (i = 0; i < ndim; i++) { if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i])) { *isNull = true; return (Datum) 0; } } /* * Calculate the element number */ offset = ArrayGetOffset(nSubscripts, dim, lb, indx); /* * Check for NULL array element */ if (array_get_isnull(arraynullsptr, offset)) { *isNull = true; return (Datum) 0; } /* * OK, get the element */ *isNull = false; retptr = array_seek(arraydataptr, 0, arraynullsptr, offset, elmlen, elmbyval, elmalign); return ArrayCast(retptr, elmbyval, elmlen);}/* * array_get_slice : * This routine takes an array and a range of indices (upperIndex and * lowerIndx), creates a new array structure for the referred elements * and returns a pointer to it. * * This handles both ordinary varlena arrays and fixed-length arrays. * * Inputs: * array: 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 * 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 * elmalign: pg_type.typalign for the array's element type * * Outputs: * The return value is the new array Datum (it's never NULL) * * 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, int nSubscripts, int *upperIndx, int *lowerIndx, int arraytyplen, int elmlen, bool elmbyval, char elmalign){ ArrayType *newarray; int i, ndim, *dim, *lb, *newlb; int fixedDim[1], fixedLb[1]; Oid elemtype; char *arraydataptr; bits8 *arraynullsptr; int32 dataoffset; int bytes, span[MAXDIM]; if (arraytyplen > 0) { /* * fixed-length arrays -- currently, cannot slice these because parser * labels output as being of the fixed-length array type! Code below * shows how we could support it if the parser were changed to label * output as a suitable varlena array type. */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("slices of fixed-length arrays not implemented"))); /* * fixed-length arrays -- these are assumed to be 1-d, 0-based * * XXX where would we get the correct ELEMTYPE from? */ ndim = 1; fixedDim[0] = arraytyplen / elmlen; fixedLb[0] = 0; dim = fixedDim; lb = fixedLb; elemtype = InvalidOid; /* XXX */ arraydataptr = (char *) array; arraynullsptr = NULL; } else { /* detoast input array if necessary */ array = DatumGetArrayTypeP(PointerGetDatum(array)); ndim = ARR_NDIM(array); dim = ARR_DIMS(array); lb = ARR_LBOUND(array); elemtype = ARR_ELEMTYPE(array); arraydataptr = ARR_DATA_PTR(array); arraynullsptr = ARR_NULLBITMAP(array); } /* * Check provided subscripts. A slice exceeding the current array limits * is silently truncated to the array limits. If we end up with an empty * slice, return an empty array. */ if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM) return construct_empty_array(elemtype); for (i = 0; i < nSubscripts; i++) { if (lowerIndx[i] < lb[i]) lowerIndx[i] = lb[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); } /* 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); } mda_get_range(ndim, span, lowerIndx, upperIndx); bytes = array_slice_size(arraydataptr, arraynullsptr, ndim, dim, lb, lowerIndx, upperIndx, elmlen, elmbyval, elmalign); /* * Currently, we put a null bitmap in the result if the source has one; * could be smarter ... */ if (arraynullsptr) { dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, ArrayGetNItems(ndim, span)); bytes += dataoffset; } else { dataoffset = 0; /* marker for no null bitmap */ bytes += ARR_OVERHEAD_NONULLS(ndim); } newarray = (ArrayType *) palloc(bytes); SET_VARSIZE(newarray, bytes); newarray->ndim = ndim; newarray->dataoffset = dataoffset; newarray->elemtype = elemtype; memcpy(ARR_DIMS(newarray), span, ndim * sizeof(int)); /* * Lower bounds of the new array are set to 1. Formerly (before 7.3) we * copied the given lowerIndx values ... but that seems confusing. */ newlb = ARR_LBOUND(newarray); for (i = 0; i < ndim; i++) newlb[i] = 1; array_extract_slice(newarray, ndim, dim, lb, arraydataptr, arraynullsptr, lowerIndx, upperIndx, elmlen, elmbyval, elmalign); return newarray;}/* * array_set : * This routine sets the value of an 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) * nSubscripts: number of subscripts supplied * indx[]: the subscript values * dataValue: the datum to be inserted at the given position * isNull: whether dataValue 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 * elmalign: pg_type.typalign for the array's element type * * Result: * A new array is returned, just like the old except for the one * modified entry. The original array object is not changed. * * For one-dimensional arrays only, we allow the array to be extended * by assigning to a position outside the existing subscript range; any * positions between the existing elements and the new one are set to NULLs. * (XXX TODO: allow a corresponding behavior for multidimensional arrays) * * 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){ ArrayType *newarray; int i, ndim, dim[MAXDIM], lb[MAXDIM], offset; char *elt_ptr; bool newhasnulls; bits8 *oldnullbitmap; int oldnitems, newnitems, olddatasize, newsize, olditemlen, newitemlen, overheadlen, oldoverheadlen, addedbefore, addedafter, lenbefore, lenafter; if (arraytyplen > 0) { /* * fixed-length arrays -- these are assumed to be 1-d, 0-based. We * cannot extend them, either. */ if (nSubscripts != 1) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); if (indx[0] < 0 || indx[0] * elmlen >= arraytyplen) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("array subscript out of range"))); if (isNull) ereport(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; ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, elt_ptr);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?