static jobject coerceTupleDatum(UDT udt, Datum arg) { jobject result = JNI_newObject(Type_getJavaClass((Type)udt), udt->init); jobject inputStream = SQLInputFromTuple_create(DatumGetHeapTupleHeader(arg), udt->tupleDesc); JNI_callVoidMethod(result, udt->readSQL, inputStream, udt->sqlTypeName); JNI_deleteLocalRef(inputStream); 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; }
void Invocation_popInvocation(bool wasException) { CallLocal* cl; Invocation* ctx = currentInvocation->previous; if(currentInvocation->invocation != 0) { if(!wasException) JNI_callVoidMethod(currentInvocation->invocation, s_Invocation_onExit); JNI_deleteGlobalRef(currentInvocation->invocation); } /* * Check for any DualState objects that became unreachable and can be freed. */ pljava_DualState_cleanEnqueuedInstances(); if(currentInvocation->hasConnected) SPI_finish(); JNI_popLocalFrame(0); if(ctx != 0) { PG_TRY(); { Backend_setJavaSecurity(ctx->trusted); } PG_CATCH(); { elog(FATAL, "Failed to reinstate untrusted security after a trusted call or vice versa"); } PG_END_TRY(); MemoryContextSwitchTo(ctx->upperContext); } /** * Reset all local wrappers that has been allocated during this call. Yank them * from the double linked list but do *not* remove them. */ cl = currentInvocation->callLocals; if(cl != 0) { CallLocal* first = cl; do { cl->pointer = 0; cl->invocation = 0; cl = cl->next; } while(cl != first); } currentInvocation = ctx; --s_callLevel; }
static jobject coerceTupleDatum(UDT udt, Datum arg) { jobject result = JNI_newObject(Type_getJavaClass((Type)udt), udt->init); Oid typeId = ((Type)udt)->typeId; TupleDesc tupleDesc = lookup_rowtype_tupdesc_noerror(typeId, -1, true); jobject inputStream = SQLInputFromTuple_create(DatumGetHeapTupleHeader(arg), tupleDesc); ReleaseTupleDesc(tupleDesc); JNI_callVoidMethod(result, udt->readSQL, inputStream, udt->sqlTypeName); JNI_deleteLocalRef(inputStream); return result; }
static Datum coerceTupleObject(UDT self, jobject value) { Datum result = 0; if(value != 0) { HeapTuple tuple; jobject sqlOutput = SQLOutputToTuple_create(self->tupleDesc); JNI_callVoidMethod(value, self->writeSQL, sqlOutput); tuple = SQLOutputToTuple_getTuple(sqlOutput); if(tuple != 0) result = HeapTupleGetDatum(tuple); } return result; }
static Datum coerceTupleObject(UDT self, jobject value) { Datum result = 0; if(value != 0) { HeapTuple tuple; Oid typeId = ((Type)self)->typeId; TupleDesc tupleDesc = lookup_rowtype_tupdesc_noerror(typeId, -1, true); jobject sqlOutput = SQLOutputToTuple_create(tupleDesc); ReleaseTupleDesc(tupleDesc); JNI_callVoidMethod(value, self->writeSQL, sqlOutput); tuple = SQLOutputToTuple_getTuple(sqlOutput); if(tuple != 0) result = HeapTupleGetDatum(tuple); } return result; }
static Datum _byte_array_coerceObject(Type self, jobject byteArray) { bytea* bytes = 0; if(byteArray == 0) return 0; if(JNI_isInstanceOf(byteArray, s_byteArray_class)) { jsize length = JNI_getArrayLength((jarray)byteArray); int32 byteaSize = length + VARHDRSZ; bytes = (bytea*)palloc(byteaSize); #if (PGSQL_MAJOR_VER == 8 && PGSQL_MINOR_VER < 3) VARATT_SIZEP(bytes) = byteaSize; #else SET_VARSIZE(bytes, byteaSize); #endif JNI_getByteArrayRegion((jbyteArray)byteArray, 0, length, (jbyte*)VARDATA(bytes)); } else if(JNI_isInstanceOf(byteArray, s_BlobValue_class)) { jobject byteBuffer; int32 byteaSize; jlong length = JNI_callLongMethod(byteArray, s_BlobValue_length); byteaSize = (int32)(length + VARHDRSZ); bytes = (bytea*)palloc(byteaSize); #if (PGSQL_MAJOR_VER == 8 && PGSQL_MINOR_VER < 3) VARATT_SIZEP(bytes) = byteaSize; #else SET_VARSIZE(bytes, byteaSize); #endif byteBuffer = JNI_newDirectByteBuffer((void*)VARDATA(bytes), length); if(byteBuffer != 0) JNI_callVoidMethod(byteArray, s_BlobValue_getContents, byteBuffer); JNI_deleteLocalRef(byteBuffer); } else { Exception_throwIllegalArgument("Not coercable to bytea"); } PG_RETURN_BYTEA_P(bytes); }
static jvalue Timestamp_coerceDatumTZ_dd(Type self, Datum arg, bool tzAdjust) { jlong mSecs; jint uSecs; jvalue result; double ts = DatumGetFloat8(arg); int tz = Timestamp_getTimeZone_dd(ts); /* Expect <seconds since Jan 01 2000>.<fractions of seconds> */ if(tzAdjust) ts += tz; /* Adjust from local time to UTC */ ts += EPOCH_DIFF; /* Adjust for diff between Postgres and Java (Unix) */ mSecs = (jlong) floor(ts * 1000.0); /* Convert to millisecs */ uSecs = (jint) ((ts - floor(ts)) * 1000000.0); /* Preserve microsecs */ result.l = JNI_newObject(s_Timestamp_class, s_Timestamp_init, mSecs); if(uSecs != 0) JNI_callVoidMethod(result.l, s_Timestamp_setNanos, uSecs * 1000); return result; }
static jvalue Timestamp_coerceDatumTZ_id(Type self, Datum arg, bool tzAdjust) { jvalue result; int64 ts = DatumGetInt64(arg); int tz = Timestamp_getTimeZone_id(ts); /* Expect number of microseconds since 01 Jan 2000 */ jlong mSecs = ts / 1000; /* Convert to millisecs */ jint uSecs = (jint)(ts % 1000000); /* preserve microsecs */ if(tzAdjust) mSecs += tz * 1000; /* Adjust from local time to UTC */ /* Adjust for diff between Postgres and Java (Unix) */ mSecs += ((jlong)EPOCH_DIFF) * 1000L; result.l = JNI_newObject(s_Timestamp_class, s_Timestamp_init, mSecs); if(uSecs != 0) JNI_callVoidMethod(result.l, s_Timestamp_setNanos, uSecs * 1000); return result; }
void SQLInputFromChunk_close(jobject stream) { JNI_callVoidMethod(stream, s_SQLInputFromChunk_close); }
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; }