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); }
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; }
char *InstallHelper_hello() { char pathbuf[MAXPGPATH]; Invocation ctx; jstring nativeVer; jstring user; jstring dbname; jstring clustername; jstring ddir; jstring ldir; jstring sdir; jstring edir; jstring greeting; char *greetingC; char const *clusternameC = pljavaClusterName(); Invocation_pushBootContext(&ctx); nativeVer = String_createJavaStringFromNTS(SO_VERSION_STRING); user = String_createJavaStringFromNTS(MyProcPort->user_name); dbname = String_createJavaStringFromNTS(MyProcPort->database_name); if ( '\0' == *clusternameC ) clustername = NULL; else clustername = String_createJavaStringFromNTS(clusternameC); ddir = String_createJavaStringFromNTS(DataDir); get_pkglib_path(my_exec_path, pathbuf); ldir = String_createJavaStringFromNTS(pathbuf); get_share_path(my_exec_path, pathbuf); sdir = String_createJavaStringFromNTS(pathbuf); get_etc_path(my_exec_path, pathbuf); edir = String_createJavaStringFromNTS(pathbuf); greeting = JNI_callStaticObjectMethod( s_InstallHelper_class, s_InstallHelper_hello, nativeVer, user, dbname, clustername, ddir, ldir, sdir, edir); JNI_deleteLocalRef(nativeVer); JNI_deleteLocalRef(user); JNI_deleteLocalRef(dbname); if ( NULL != clustername ) JNI_deleteLocalRef(clustername); JNI_deleteLocalRef(ddir); JNI_deleteLocalRef(ldir); JNI_deleteLocalRef(sdir); JNI_deleteLocalRef(edir); greetingC = String_createNTS(greeting); JNI_deleteLocalRef(greeting); Invocation_popBootContext(); return greetingC; }
static void Function_init(Function self, ParseResult info, Form_pg_proc procStruct, PG_FUNCTION_ARGS) { StringInfoData sign; jobject loader; jstring className; /* Get the ClassLoader for the schema that this function belongs to */ jstring schemaName = getSchemaName(procStruct->pronamespace); /* Install the type map for the current schema. This must be done ASAP since * many other functions (including obtaining the loader) depends on it. */ jobject tmp = JNI_callStaticObjectMethod(s_Loader_class, s_Loader_getTypeMap, schemaName); self->func.nonudt.typeMap = JNI_newGlobalRef(tmp); JNI_deleteLocalRef(tmp); self->readOnly = (procStruct->provolatile != PROVOLATILE_VOLATILE); self->isUDT = info->isUDT; currentInvocation->function = self; /* Get the ClassLoader for the schema that this function belongs to */ loader = JNI_callStaticObjectMethod(s_Loader_class, s_Loader_getSchemaLoader, schemaName); JNI_deleteLocalRef(schemaName); elog(DEBUG1, "Loading class %s", info->className); className = String_createJavaStringFromNTS(info->className); tmp = JNI_callObjectMethod(loader, s_ClassLoader_loadClass, className); JNI_deleteLocalRef(loader); JNI_deleteLocalRef(className); self->clazz = (jclass)JNI_newGlobalRef(tmp); JNI_deleteLocalRef(tmp); if(self->isUDT) { setupUDT(self, info, procStruct); return; } if(CALLED_AS_TRIGGER(fcinfo)) { self->func.nonudt.typeMap = 0; setupTriggerParams(self, info); } else { setupFunctionParams(self, info, procStruct, fcinfo); } initStringInfo(&sign); buildSignature(self, &sign, self->func.nonudt.returnType, false); elog(DEBUG1, "Obtaining method %s.%s %s", info->className, info->methodName, sign.data); self->func.nonudt.method = JNI_getStaticMethodIDOrNull(self->clazz, info->methodName, sign.data); if(self->func.nonudt.method == 0) { char* origSign = sign.data; Type altType = 0; Type realRetType = self->func.nonudt.returnType; elog(DEBUG1, "Method %s.%s %s not found", info->className, info->methodName, origSign); if(Type_isPrimitive(self->func.nonudt.returnType)) { /* * One valid reason for not finding the method is when * the return type used in the signature is a primitive and * the true return type of the method is the object class that * corresponds to that primitive. */ altType = Type_getObjectType(self->func.nonudt.returnType); realRetType = altType; } else if(strcmp(Type_getJavaTypeName(self->func.nonudt.returnType), "java.sql.ResultSet") == 0) { /* * Another reason might be that we expected a ResultSetProvider * but the implementation returns a ResultSetHandle that needs to be * wrapped. The wrapping is internal so we retain the original * return type anyway. */ altType = realRetType; } if(altType != 0) { JNI_exceptionClear(); initStringInfo(&sign); buildSignature(self, &sign, altType, true); elog(DEBUG1, "Obtaining method %s.%s %s", info->className, info->methodName, sign.data); self->func.nonudt.method = JNI_getStaticMethodIDOrNull(self->clazz, info->methodName, sign.data); if(self->func.nonudt.method != 0) self->func.nonudt.returnType = realRetType; } if(self->func.nonudt.method == 0) PgObject_throwMemberError(self->clazz, info->methodName, origSign, true, true); if(sign.data != origSign) pfree(origSign); } pfree(sign.data); }