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; }
static jobject coerceScalarDatum(UDT self, Datum arg) { jobject result; int32 dataLen = Type_getLength((Type)self); jclass javaClass = Type_getJavaClass((Type)self); bool isJavaBasedScalar = 0 != self->toString; if(dataLen == -2) { /* Data is a zero terminated string */ jstring jstr = String_createJavaStringFromNTS(DatumGetCString(arg)); result = JNI_callStaticObjectMethod(javaClass, self->parse, jstr, self->sqlTypeName); JNI_deleteLocalRef(jstr); } else { char* data; jobject inputStream; if(dataLen == -1) { /* Data is a varlena struct */ bytea* bytes = DatumGetByteaP(arg); dataLen = VARSIZE(bytes) - VARHDRSZ; data = VARDATA(bytes); } else { bool passByValue = Type_isByValue((Type)self); /* Data is a binary chunk of size dataLen */ if (passByValue) { /* pass by value data is stored in the least * significant bits of a Datum. */ #ifdef WORDS_BIGENDIAN data = ((char *)(&arg)) + SIZEOF_DATUM - dataLen; #else data = ((char *)(&arg)); #endif } else { data = DatumGetPointer(arg); } } result = JNI_newObject(javaClass, self->init); inputStream = SQLInputFromChunk_create(data, dataLen, isJavaBasedScalar); JNI_callVoidMethod(result, self->readSQL, inputStream, self->sqlTypeName); SQLInputFromChunk_close(inputStream); } return result; }
static Datum _Array_coerceObject(Type self, jobject objArray) { ArrayType* v; jsize idx; int lowerBound = 1; Type elemType = Type_getElementType(self); int nElems = (int)JNI_getArrayLength((jarray)objArray); Datum* values = (Datum*)palloc(nElems * sizeof(Datum) + nElems * sizeof(bool)); bool* nulls = (bool*)(values + nElems); for(idx = 0; idx < nElems; ++idx) { jobject obj = JNI_getObjectArrayElement(objArray, idx); if(obj == 0) { nulls[idx] = true; values[idx] = 0; } else { nulls[idx] = false; values[idx] = Type_coerceObject(elemType, obj); JNI_deleteLocalRef(obj); } } v = construct_md_array( values, nulls, 1, &nElems, &lowerBound, Type_getOid(elemType), Type_getLength(elemType), Type_isByValue(elemType), Type_getAlign(elemType)); pfree(values); PG_RETURN_ARRAYTYPE_P(v); }
static Datum coerceScalarObject(UDT self, jobject value) { Datum result; int32 dataLen = Type_getLength((Type)self); if(dataLen == -2) { jstring jstr = (jstring)JNI_callObjectMethod(value, self->toString); char* tmp = String_createNTS(jstr); result = CStringGetDatum(tmp); JNI_deleteLocalRef(jstr); } else { jobject outputStream; StringInfoData buffer; bool passByValue = Type_isByValue((Type)self); MemoryContext currCtx = Invocation_switchToUpperContext(); initStringInfo(&buffer); if(dataLen < 0) /* * Reserve space for an int32 at the beginning. We are building * a varlena */ appendBinaryStringInfo(&buffer, (char*)&dataLen, sizeof(int32)); outputStream = SQLOutputToChunk_create(&buffer); JNI_callVoidMethod(value, self->writeSQL, outputStream); SQLOutputToChunk_close(outputStream); MemoryContextSwitchTo(currCtx); if(dataLen < 0) { /* Assign the correct length. */ #if PG_VERSION_NUM < 80300 VARATT_SIZEP(buffer.data) = buffer.len; #else SET_VARSIZE(buffer.data, buffer.len); #endif } else if(dataLen != buffer.len) { ereport(ERROR, ( errcode(ERRCODE_CANNOT_COERCE), errmsg("UDT for Oid %d produced image with incorrect size. Expected %d, was %d", Type_getOid((Type)self), dataLen, buffer.len))); } if (passByValue) { memset(&result, 0, SIZEOF_DATUM); /* pass by value data is stored in the least * significant bits of a Datum. */ #ifdef WORDS_BIGENDIAN memcpy(&result + SIZEOF_DATUM - dataLen, buffer.data, dataLen); #else memcpy(&result, buffer.data, dataLen); #endif } else { result = PointerGetDatum(buffer.data); } } return result; }