/* * SerializeSingleDatum serializes the given datum value and appends it to the * provided string info buffer. */ static void SerializeSingleDatum(StringInfo datumBuffer, Datum datum, bool datumTypeByValue, int datumTypeLength, char datumTypeAlign) { uint32 datumLength = att_addlength_datum(0, datumTypeLength, datum); uint32 datumLengthAligned = att_align_nominal(datumLength, datumTypeAlign); char *currentDatumDataPointer = NULL; enlargeStringInfo(datumBuffer, datumLengthAligned); currentDatumDataPointer = datumBuffer->data + datumBuffer->len; memset(currentDatumDataPointer, 0, datumLengthAligned); if (datumTypeLength > 0) { if (datumTypeByValue) { store_att_byval(currentDatumDataPointer, datum, datumTypeLength); } else { memcpy(currentDatumDataPointer, DatumGetPointer(datum), datumTypeLength); } } else { Assert(!datumTypeByValue); memcpy(currentDatumDataPointer, DatumGetPointer(datum), datumLength); } datumBuffer->len += datumLengthAligned; }
static jvalue _Array_coerceDatum(Type self, Datum arg) { jvalue result; jsize idx; Type elemType = Type_getElementType(self); int16 elemLength = Type_getLength(elemType); char elemAlign = Type_getAlign(elemType); bool elemByValue = Type_isByValue(elemType); ArrayType* v = DatumGetArrayTypeP(arg); jsize nElems = (jsize)ArrayGetNItems(ARR_NDIM(v), ARR_DIMS(v)); jobjectArray objArray = JNI_newObjectArray(nElems, Type_getJavaClass(elemType), 0); const char* values = ARR_DATA_PTR(v); bits8* nullBitMap = ARR_NULLBITMAP(v); for(idx = 0; idx < nElems; ++idx) { if(arrayIsNull(nullBitMap, idx)) JNI_setObjectArrayElement(objArray, idx, 0); else { Datum value = fetch_att(values, elemByValue, elemLength); jvalue obj = Type_coerceDatum(elemType, value); JNI_setObjectArrayElement(objArray, idx, obj.l); JNI_deleteLocalRef(obj.l); values = att_addlength_datum(values, elemLength, PointerGetDatum(values)); values = (char*)att_align_nominal(values, elemAlign); } } result.l = (jobject)objArray; return result; }
/* * get_flat_size method for expanded arrays */ static Size EA_get_flat_size(ExpandedObjectHeader *eohptr) { ExpandedArrayHeader *eah = (ExpandedArrayHeader *) eohptr; int nelems; int ndims; Datum *dvalues; bool *dnulls; Size nbytes; int i; Assert(eah->ea_magic == EA_MAGIC); /* Easy if we have a valid flattened value */ if (eah->fvalue) return ARR_SIZE(eah->fvalue); /* If we have a cached size value, believe that */ if (eah->flat_size) return eah->flat_size; /* * Compute space needed by examining dvalues/dnulls. Note that the result * array will have a nulls bitmap if dnulls isn't NULL, even if the array * doesn't actually contain any nulls now. */ nelems = eah->nelems; ndims = eah->ndims; Assert(nelems == ArrayGetNItems(ndims, eah->dims)); dvalues = eah->dvalues; dnulls = eah->dnulls; nbytes = 0; for (i = 0; i < nelems; i++) { if (dnulls && dnulls[i]) continue; nbytes = att_addlength_datum(nbytes, eah->typlen, dvalues[i]); nbytes = att_align_nominal(nbytes, eah->typalign); /* check for overflow of total request */ if (!AllocSizeIsValid(nbytes)) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("array size exceeds the maximum allowed (%d)", (int) MaxAllocSize))); } if (dnulls) nbytes += ARR_OVERHEAD_WITHNULLS(ndims, nelems); else nbytes += ARR_OVERHEAD_NONULLS(ndims); /* cache for next time */ eah->flat_size = nbytes; return nbytes; }
/* * heap_compute_data_size * Determine size of the data area of a tuple to be constructed */ Size heap_compute_data_size(TupleDesc tupleDesc, Datum *values, bool *isnull) { Size data_length = 0; int i; int numberOfAttributes = tupleDesc->natts; Form_pg_attribute *att = tupleDesc->attrs; for (i = 0; i < numberOfAttributes; i++) { Datum val; Form_pg_attribute atti; if (isnull[i]) continue; val = values[i]; atti = att[i]; if (ATT_IS_PACKABLE(atti) && VARATT_CAN_MAKE_SHORT(DatumGetPointer(val))) { /* * we're anticipating converting to a short varlena header, so * adjust length and don't count any alignment */ data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val)); } else if (atti->attlen == -1 && VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(val))) { /* * we want to flatten the expanded value so that the constructed * tuple doesn't depend on it */ data_length = att_align_nominal(data_length, atti->attalign); data_length += EOH_get_flat_size(DatumGetEOHP(val)); } else { data_length = att_align_datum(data_length, atti->attalign, atti->attlen, val); data_length = att_addlength_datum(data_length, atti->attlen, val); } } return data_length; }
/* * SerializeDatumArray serializes the non-null elements of the given datum array * into a string info buffer, and then returns this buffer. */ static StringInfo SerializeDatumArray(Datum *datumArray, bool *existsArray, uint32 datumCount, bool datumTypeByValue, int datumTypeLength, char datumTypeAlign) { StringInfo datumBuffer = makeStringInfo(); uint32 datumIndex = 0; for (datumIndex = 0; datumIndex < datumCount; datumIndex++) { Datum datum = datumArray[datumIndex]; uint32 datumLength = 0; uint32 datumLengthAligned = 0; char *currentDatumDataPointer = NULL; if (!existsArray[datumIndex]) { continue; } datumLength = att_addlength_datum(0, datumTypeLength, datum); datumLengthAligned = att_align_nominal(datumLength, datumTypeAlign); enlargeStringInfo(datumBuffer, datumBuffer->len + datumLengthAligned); currentDatumDataPointer = datumBuffer->data + datumBuffer->len; memset(currentDatumDataPointer, 0, datumLengthAligned); if (datumTypeLength > 0) { if (datumTypeByValue) { store_att_byval(currentDatumDataPointer, datum, datumTypeLength); } else { memcpy(currentDatumDataPointer, DatumGetPointer(datum), datumTypeLength); } } else { Assert(!datumTypeByValue); memcpy(currentDatumDataPointer, DatumGetPointer(datum), datumLength); } datumBuffer->len += datumLengthAligned; } return datumBuffer; }
/* Creates a copy of the given datum. */ static Datum DatumCopy(Datum datum, bool datumTypeByValue, int datumTypeLength) { Datum datumCopy = 0; if (datumTypeByValue) { datumCopy = datum; } else { uint32 datumLength = att_addlength_datum(0, datumTypeLength, datum); char *datumData = palloc0(datumLength); memcpy(datumData, DatumGetPointer(datum), datumLength); datumCopy = PointerGetDatum(datumData); } return datumCopy; }
/* * heap_compute_data_size * Determine size of the data area of a tuple to be constructed */ Size heap_compute_data_size(TupleDesc tupleDesc, Datum *values, bool *isnull) { Size data_length = 0; int i; int numberOfAttributes = tupleDesc->natts; Form_pg_attribute *att = tupleDesc->attrs; for (i = 0; i < numberOfAttributes; i++) { Datum val; if (isnull[i]) continue; val = values[i]; if (ATT_IS_PACKABLE(att[i]) && VARATT_CAN_MAKE_SHORT(DatumGetPointer(val))) { /* * we're anticipating converting to a short varlena header, so * adjust length and don't count any alignment */ data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val)); } else { data_length = att_align_datum(data_length, att[i]->attalign, att[i]->attlen, val); data_length = att_addlength_datum(data_length, att[i]->attlen, val); } } return data_length; }