/* * double primitive type. */ static Datum _asDatum(jdouble v) { MemoryContext currCtx = Invocation_switchToUpperContext(); Datum ret = Float8GetDatum(v); MemoryContextSwitchTo(currCtx); return ret; }
Datum Function_invokeTrigger(Function self, PG_FUNCTION_ARGS) { jvalue arg; Datum ret; arg.l = TriggerData_create((TriggerData*)fcinfo->context); if(arg.l == 0) return 0; currentInvocation->function = self; Type_invoke(self->func.nonudt.returnType, self->clazz, self->func.nonudt.method, &arg, fcinfo); fcinfo->isnull = false; if(JNI_exceptionCheck()) ret = 0; else { /* A new Tuple may or may not be created here. If it is, ensure that * it is created in the upper SPI context. */ MemoryContext currCtx = Invocation_switchToUpperContext(); ret = PointerGetDatum(TriggerData_getTriggerReturnTuple(arg.l, &fcinfo->isnull)); /* Triggers are not allowed to set the fcinfo->isnull, even when * they return null. */ fcinfo->isnull = false; MemoryContextSwitchTo(currCtx); } JNI_deleteLocalRef(arg.l); return ret; }
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); }
ArrayType* createArrayType(jsize nElems, size_t elemSize, Oid elemType, bool withNulls) { ArrayType* v; Size nBytes = elemSize * nElems; MemoryContext currCtx = Invocation_switchToUpperContext(); Size dataoffset; if(withNulls) { dataoffset = ARR_OVERHEAD_WITHNULLS(1, nElems); nBytes += dataoffset; } else { dataoffset = 0; /* marker for no null bitmap */ nBytes += ARR_OVERHEAD_NONULLS(1); } v = (ArrayType*)palloc0(nBytes); AssertVariableIsOfType(v->dataoffset, int32); v->dataoffset = (int32)dataoffset; MemoryContextSwitchTo(currCtx); SET_VARSIZE(v, nBytes); ARR_NDIM(v) = 1; ARR_ELEMTYPE(v) = elemType; *((int*)ARR_DIMS(v)) = nElems; *((int*)ARR_LBOUND(v)) = 1; return v; }
Datum _Type_invoke(Type self, jclass cls, jmethodID method, jvalue* args, PG_FUNCTION_ARGS) { MemoryContext currCtx; Datum ret; jobject value = JNI_callStaticObjectMethodA(cls, method, args); if(value == 0) { fcinfo->isnull = true; return 0; } /* The return value cannot be created in the current context since it * goes out of scope when SPI_finish is called. */ currCtx = Invocation_switchToUpperContext(); ret = self->typeClass->coerceObject(self, value); MemoryContextSwitchTo(currCtx); JNI_deleteLocalRef(value); return ret; }
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; }