Esempio n. 1
0
Type Type_fromOid(Oid typeId, jobject typeMap)
{
	CacheEntry   ce;
	HeapTuple    typeTup;
	Form_pg_type typeStruct;
	Type         type = Type_fromOidCache(typeId);

	if(type != 0)
		return type;

	typeTup    = PgObject_getValidTuple(TYPEOID, typeId, "type");
	typeStruct = (Form_pg_type)GETSTRUCT(typeTup);

	if(typeStruct->typelem != 0 && typeStruct->typlen == -1)
	{
		type = Type_getArrayType(Type_fromOid(typeStruct->typelem, typeMap), typeId);
		goto finally;
	}

	/* For some reason, the anyarray is *not* an array with anyelement as the
	 * element type. We'd like to see it that way though.
	 */
	if(typeId == ANYARRAYOID)
	{
		type = Type_getArrayType(Type_fromOid(ANYELEMENTOID, typeMap), typeId);
		goto finally;
	}

	if(typeStruct->typbasetype != 0)
	{
		/* Domain type, recurse using the base type (which in turn may
		 * also be a domain)
		 */
		type = Type_fromOid(typeStruct->typbasetype, typeMap);
		goto finally;
	}

	if(typeMap != 0)
	{
		jobject joid      = Oid_create(typeId);
		jclass  typeClass = (jclass)JNI_callObjectMethod(typeMap, s_Map_get, joid);

		JNI_deleteLocalRef(joid);
		if(typeClass != 0)
		{
			TupleDesc tupleDesc = lookup_rowtype_tupdesc_noerror(typeId, -1, true);
			type = (Type)UDT_registerUDT(typeClass, typeId, typeStruct, tupleDesc, false);
			JNI_deleteLocalRef(typeClass);
			goto finally;
		}
	}

	/* Composite and record types will not have a TypeObtainer registered
	 */
	if(typeStruct->typtype == 'c' || (typeStruct->typtype == 'p' && typeId == RECORDOID))
	{
		type = Composite_obtain(typeId);
		goto finally;
	}

	ce = (CacheEntry)HashMap_getByOid(s_obtainerByOid, typeId);
	if(ce == 0)
		/*
		 * Default to String and standard textin/textout coersion.
		 */
		type = String_obtain(typeId);
	else
	{
		type = ce->type;
		if(type == 0)
			type = ce->obtainer(typeId);
	}

finally:
	ReleaseSysCache(typeTup);
	Type_cacheByOid(typeId, type);
	return type;
}
Esempio n. 2
0
/* Make this datatype available to the postgres system.
 */
UDT UDT_registerUDT(jclass clazz, Oid typeId, Form_pg_type pgType, TupleDesc td, bool isJavaBasedScalar)
{
	jstring jcn;
	MemoryContext currCtx;
	HeapTuple nspTup;
	Form_pg_namespace nspStruct;
	TypeClass udtClass;
	UDT udt;
	Size signatureLen;
	jstring sqlTypeName;
	char* className;
	char* classSignature;
	char* sp;
	const char* cp;
	const char* tp;
	char c;

	Type existing = Type_fromOidCache(typeId);
	if(existing != 0)
	{
		if(existing->typeClass->coerceDatum != _UDT_coerceDatum)
		{
			ereport(ERROR, (
				errcode(ERRCODE_CANNOT_COERCE),
				errmsg("Attempt to register UDT with Oid %d failed. Oid appoints a non UDT type", typeId)));
		}
		return (UDT)existing;
	}

	nspTup = PgObject_getValidTuple(NAMESPACEOID, pgType->typnamespace, "namespace");
	nspStruct = (Form_pg_namespace)GETSTRUCT(nspTup);

	/* Concatenate namespace + '.' + typename
	 */
	cp = NameStr(nspStruct->nspname);
	tp = NameStr(pgType->typname);
	sp = palloc(strlen(cp) + strlen(tp) + 2);
	sprintf(sp, "%s.%s", cp, tp);
	sqlTypeName = String_createJavaStringFromNTS(sp);
	pfree(sp);

	ReleaseSysCache(nspTup);

	/* Create a Java Signature String from the class name
	 */
	jcn = JNI_callObjectMethod(clazz, Class_getName);
	currCtx = MemoryContextSwitchTo(TopMemoryContext);
	className = String_createNTS(jcn);
	JNI_deleteLocalRef(jcn);

	signatureLen = strlen(className) + 2;
	classSignature = palloc(signatureLen + 1);
	MemoryContextSwitchTo(currCtx);

	sp = classSignature;
	cp = className;
	*sp++ = 'L';
	while((c = *cp++) != 0)
	{
		if(c == '.')
			c = '/';
		*sp++ = c;
	}
	*sp++ = ';';
	*sp = 0;

	udtClass = TypeClass_alloc2("type.UDT", sizeof(struct TypeClass_), sizeof(struct UDT_));

	udtClass->JNISignature   = classSignature;
	udtClass->javaTypeName   = className;
	udtClass->javaClass      = JNI_newGlobalRef(clazz);
	udtClass->canReplaceType = _Type_canReplaceType;
	udtClass->coerceDatum    = _UDT_coerceDatum;
	udtClass->coerceObject   = _UDT_coerceObject;

	udt = (UDT)TypeClass_allocInstance2(udtClass, typeId, pgType);
	udt->sqlTypeName = JNI_newGlobalRef(sqlTypeName);
	JNI_deleteLocalRef(sqlTypeName);

	udt->init     = PgObject_getJavaMethod(clazz, "<init>", "()V");

	if(isJavaBasedScalar)
	{
		/* A scalar mapping that is implemented in Java will have the static method:
		 * 
		 *   T parse(String stringRep, String sqlTypeName);
		 * 
		 * and a matching:
		 * 
		 *   String toString();
		 * 
		 * instance method. A pure mapping (i.e. no Java I/O methods) will not have
		 * this.
		 */
		udt->toString = PgObject_getJavaMethod(clazz, "toString", "()Ljava/lang/String;");
	
		/* The parse method is a static method on the class with the signature
		 * (Ljava/lang/String;Ljava/lang/String;)<classSignature>
		 */
		sp = palloc(signatureLen + 40);
		strcpy(sp, "(Ljava/lang/String;Ljava/lang/String;)");
		strcpy(sp + 38, classSignature);
		udt->parse = PgObject_getStaticJavaMethod(clazz, "parse", sp);
		pfree(sp);
	}
	else
	{
		udt->toString = 0;
		udt->parse = 0;
	}

	udt->tupleDesc = td;
	udt->readSQL = PgObject_getJavaMethod(clazz, "readSQL", "(Ljava/sql/SQLInput;Ljava/lang/String;)V");
	udt->writeSQL = PgObject_getJavaMethod(clazz, "writeSQL", "(Ljava/sql/SQLOutput;)V");
	Type_registerType(className, (Type)udt);
	return udt;
}