Example #1
0
Datum UDT_output(UDT udt, PG_FUNCTION_ARGS)
{
	char* txt;

	if(!UDT_isScalar(udt))
		ereport(ERROR, (
			errcode(ERRCODE_CANNOT_COERCE),
			errmsg("UDT with Oid %d is not scalar", Type_getOid((Type)udt))));

	if(Type_getLength((Type)udt) == -2)
	{
		txt = PG_GETARG_CSTRING(0);
		if(txt != 0)
			txt = pstrdup(txt);
	}
	else
	{
		jobject value = _UDT_coerceDatum((Type)udt, PG_GETARG_DATUM(0)).l;
		jstring jstr  = (jstring)JNI_callObjectMethod(value, udt->toString);

		MemoryContext currCtx = Invocation_switchToUpperContext();
		txt = String_createNTS(jstr);
		MemoryContextSwitchTo(currCtx);

		JNI_deleteLocalRef(value);
		JNI_deleteLocalRef(jstr);
	}
	PG_RETURN_CSTRING(txt);
}
Example #2
0
Datum UDT_input(UDT udt, PG_FUNCTION_ARGS)
{
	jstring jstr;
	jobject obj;
	char* txt;

	if(!UDT_isScalar(udt))
		ereport(ERROR, (
			errcode(ERRCODE_CANNOT_COERCE),
			errmsg("UDT with Oid %d is not scalar", Type_getOid((Type)udt))));

	txt = PG_GETARG_CSTRING(0);

	if(Type_getLength((Type)udt) == -2)
	{
		if(txt != 0)
			txt = pstrdup(txt);
		PG_RETURN_CSTRING(txt);
	}
	jstr = String_createJavaStringFromNTS(txt);
	obj  = JNI_callStaticObjectMethod(Type_getJavaClass((Type)udt), udt->parse, jstr, udt->sqlTypeName);
	JNI_deleteLocalRef(jstr);

	return _UDT_coerceObject((Type)udt, obj);
}
Example #3
0
Datum UDT_send(UDT udt, PG_FUNCTION_ARGS)
{
	StringInfoData buf;
	int32 dataLen = Type_getLength((Type)udt);

	if(!UDT_isScalar(udt))
		ereport(ERROR, (
			errcode(ERRCODE_CANNOT_COERCE),
			errmsg("UDT with Oid %d is not scalar", Type_getOid((Type)udt))));

	if(dataLen == -1)
		return byteasend(fcinfo);

	if(dataLen == -2)
		return unknownsend(fcinfo);

	pq_begintypsend(&buf);
	appendBinaryStringInfo(&buf, PG_GETARG_POINTER(0), dataLen);
    PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
Example #4
0
static void setupFunctionParams(Function self, ParseResult info, Form_pg_proc procStruct, PG_FUNCTION_ARGS)
{
	Oid* paramOids;
	MemoryContext ctx = GetMemoryChunkContext(self);
	int32 top = (int32)procStruct->pronargs;;

	self->func.nonudt.numParams = top;
	self->func.nonudt.isMultiCall = procStruct->proretset;
	self->func.nonudt.returnType = Type_fromOid(procStruct->prorettype, self->func.nonudt.typeMap);

	if(top > 0)
	{
		int idx;
		paramOids = PARAM_OIDS(procStruct);
		self->func.nonudt.paramTypes = (Type*)MemoryContextAlloc(ctx, top * sizeof(Type));

		for(idx = 0; idx < top; ++idx)
			self->func.nonudt.paramTypes[idx] = Type_fromOid(paramOids[idx], self->func.nonudt.typeMap);
	}
	else
	{
		self->func.nonudt.paramTypes = 0;
		paramOids = 0;
	}

	if(info->parameters != 0)
		parseParameters(self, paramOids, info->parameters);

	if(info->returnType != 0)
	{
		const char* jtName = Type_getJavaTypeName(self->func.nonudt.returnType);
		if(strcmp(jtName, info->returnType) != 0)
		{
			Type repl = Type_fromJavaType(Type_getOid(self->func.nonudt.returnType), info->returnType);
			if(!Type_canReplaceType(repl, self->func.nonudt.returnType))
				repl = Type_getCoerceOut(repl, self->func.nonudt.returnType);
			self->func.nonudt.returnType = repl;
		}
	}
}
Example #5
0
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);
}
Example #6
0
Datum UDT_receive(UDT udt, PG_FUNCTION_ARGS)
{
	StringInfo buf;
	char* tmp;
	int32 dataLen = Type_getLength((Type)udt);

	if(!UDT_isScalar(udt))
		ereport(ERROR, (
			errcode(ERRCODE_CANNOT_COERCE),
			errmsg("UDT with Oid %d is not scalar", Type_getOid((Type)udt))));

	if(dataLen == -1)
		return bytearecv(fcinfo);

	if(dataLen == -2)
		return unknownrecv(fcinfo);

	buf = (StringInfo)PG_GETARG_POINTER(0);
	tmp = palloc(dataLen);
	pq_copymsgbytes(buf, tmp, dataLen);
	PG_RETURN_POINTER(tmp);
}
Example #7
0
/*
 * Fail openly rather than mysteriously if an INPUT or RECEIVE function is
 * called with a non-default typmod. It seems possible that, aside from COPY
 * operations, that doesn't happen much, and values are usually produced as if
 * with no typmod, then fed through a typmod application cast. So even
 * without this implemented, there may be usable typmod capability except for
 * COPY.
 */
static void noTypmodYet(UDT udt, PG_FUNCTION_ARGS)
{
	Oid toid;
	int mod;

	if ( 3 > PG_NARGS() )
		return;

	toid = PG_GETARG_OID(1);
	mod  = PG_GETARG_INT32(2);

	if ( -1 != mod )
		ereport(ERROR, (
			errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
			errmsg(
				"PL/Java UDT with non-default type modifier not yet supported")
			));

	if ( Type_getOid((Type)udt) != toid )
		ereport(ERROR, (
			errcode(ERRCODE_INTERNAL_ERROR),
			errmsg("Unexpected type Oid %d passed to PL/Java UDT", toid)));
}
Example #8
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;
}