Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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);
}
Example #8
0
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;
}
Example #9
0
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;
}
Example #10
0
void SQLInputFromChunk_close(jobject stream)
{
	JNI_callVoidMethod(stream, s_SQLInputFromChunk_close);
}
Example #11
0
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;
}