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; }
Datum Function_invoke(Function self, PG_FUNCTION_ARGS) { Datum retVal; int32 top; jvalue* args; Type invokerType; fcinfo->isnull = false; currentInvocation->function = self; if(self->isUDT) return self->func.udt.udtFunction(self->func.udt.udt, fcinfo); if(self->func.nonudt.isMultiCall && SRF_IS_FIRSTCALL()) Invocation_assertDisconnect(); top = self->func.nonudt.numParams; /* Leave room for one extra parameter. Functions that returns unmapped * composite types must have a single row ResultSet as an OUT parameter. */ args = (jvalue*)palloc((top + 1) * sizeof(jvalue)); invokerType = self->func.nonudt.returnType; if(top > 0) { int32 idx; Type* types = self->func.nonudt.paramTypes; /* a class loader or other mechanism might have connected already. This * connection must be dropped since its parent context is wrong. */ if(Type_isDynamic(invokerType)) invokerType = Type_getRealType(invokerType, get_fn_expr_rettype(fcinfo->flinfo), self->func.nonudt.typeMap); for(idx = 0; idx < top; ++idx) { if(PG_ARGISNULL(idx)) /* * Set this argument to zero (or null in case of object) */ args[idx].j = 0L; else { Type paramType = types[idx]; if(Type_isDynamic(paramType)) paramType = Type_getRealType(paramType, get_fn_expr_argtype(fcinfo->flinfo, idx), self->func.nonudt.typeMap); args[idx] = Type_coerceDatum(paramType, PG_GETARG_DATUM(idx)); } } } retVal = self->func.nonudt.isMultiCall ? Type_invokeSRF(invokerType, self->clazz, self->func.nonudt.method, args, fcinfo) : Type_invoke(invokerType, self->clazz, self->func.nonudt.method, args, fcinfo); pfree(args); return retVal; }