2
* Copyright (c) 2004, 2005 TADA AB - Taby Sweden
3
* Distributed under the terms shown in the file COPYRIGHT
4
* found in the root folder of this project or at
5
* http://eng.tada.se/osprojects/COPYRIGHT.html
7
* @author Thomas Hallgren
11
#include <utils/typcache.h>
13
#include "pljava/backports.h"
14
#include "pljava/MemoryContext.h"
15
#include "pljava/type/Type_priv.h"
16
#include "pljava/type/ComplexType.h"
17
#include "pljava/type/TupleDesc.h"
18
#include "pljava/type/SingleRowWriter.h"
21
* void primitive type.
23
static jclass s_SingleRowWriter_class;
24
static jmethodID s_SingleRowWriter_init;
25
static jmethodID s_SingleRowWriter_getTupleAndClear;
26
static TypeClass s_SingleRowWriterClass;
27
static HashMap s_idCache;
28
#if (PGSQL_MAJOR_VER >= 8)
29
static HashMap s_modCache;
33
* This function is a bit special in that it adds an additional parameter
34
* to the parameter list (a java.sql.ResultSet implemented as a
35
* SingleRowWriter) and calls a boolean method. It's assumed that the
36
* SingleRowWriter has been initialized with values if the method returns
37
* true. If so, the values are obtained in the form of a HeapTuple which in
38
* turn is returned (as a Datum) from this method.
40
* NOTE! It's an absolute prerequisite that the args argument has room for
41
* one extra parameter.
43
static Datum _SingleRowWriter_invoke(Type self, JNIEnv* env, jclass cls, jmethodID method, jvalue* args, PG_FUNCTION_ARGS)
45
bool saveIcj = isCallingJava;
48
TupleDesc tupleDesc = Type_getTupleDesc(self, fcinfo);
49
jobject jtd = TupleDesc_create(env, tupleDesc);
50
jobject singleRowWriter = SingleRowWriter_create(env, jtd);
51
int numArgs = fcinfo->nargs;
52
(*env)->DeleteLocalRef(env, jtd);
54
/* It's guaranteed that the args array has room for one more
57
args[numArgs].l = singleRowWriter;
60
hasRow = ((*env)->CallStaticBooleanMethodA(env, cls, method, args) == JNI_TRUE);
61
isCallingJava = saveIcj;
65
/* Obtain tuple and return it as a Datum. Must be done using a more
68
MemoryContext currCtx = MemoryContext_switchToUpperContext();
69
HeapTuple tuple = SingleRowWriter_getTupleAndClear(env, singleRowWriter);
70
#if (PGSQL_MAJOR_VER == 7 && PGSQL_MINOR_VER < 5)
71
result = TupleGetDatum(TupleDescGetSlot(tupleDesc), tuple);
73
result = HeapTupleGetDatum(tuple);
75
MemoryContextSwitchTo(currCtx);
78
fcinfo->isnull = true;
80
(*env)->DeleteLocalRef(env, singleRowWriter);
84
jobject SingleRowWriter_create(JNIEnv* env, jobject tupleDesc)
90
result = PgObject_newJavaObject(env, s_SingleRowWriter_class, s_SingleRowWriter_init, tupleDesc);
94
HeapTuple SingleRowWriter_getTupleAndClear(JNIEnv* env, jobject jrps)
98
bool saveIcj = isCallingJava;
103
isCallingJava = true;
104
tuple = (*env)->CallObjectMethod(env, jrps, s_SingleRowWriter_getTupleAndClear);
105
isCallingJava = saveIcj;
109
result = (HeapTuple)NativeStruct_getStruct(env, tuple);
110
(*env)->DeleteLocalRef(env, tuple);
114
static jvalue _SingleRowWriter_coerceDatum(Type self, JNIEnv* env, Datum nothing)
121
static Datum _SingleRowWriter_coerceObject(Type self, JNIEnv* env, jobject nothing)
126
static Type SingleRowWriter_obtain(Oid typeId)
128
#if (PGSQL_MAJOR_VER < 8)
129
return (Type)ComplexType_createType(
130
s_SingleRowWriterClass, s_idCache, typeId, lookup_rowtype_tupdesc(typeId, -1));
132
return (Type)ComplexType_createType(
133
s_SingleRowWriterClass, s_idCache, s_modCache, lookup_rowtype_tupdesc(typeId, -1));
137
Type SingleRowWriter_createType(Oid typid, TupleDesc tupleDesc)
139
#if (PGSQL_MAJOR_VER < 8)
140
return (Type)ComplexType_createType(
141
s_SingleRowWriterClass, s_idCache, typid, tupleDesc);
143
return (Type)ComplexType_createType(
144
s_SingleRowWriterClass, s_idCache, s_modCache, tupleDesc);
148
/* Make this datatype available to the postgres system.
150
extern Datum SingleRowWriter_initialize(PG_FUNCTION_ARGS);
151
PG_FUNCTION_INFO_V1(SingleRowWriter_initialize);
152
Datum SingleRowWriter_initialize(PG_FUNCTION_ARGS)
154
JNIEnv* env = (JNIEnv*)PG_GETARG_POINTER(0);
156
s_SingleRowWriter_class = (*env)->NewGlobalRef(
157
env, PgObject_getJavaClass(env, "org/postgresql/pljava/jdbc/SingleRowWriter"));
159
s_SingleRowWriter_init = PgObject_getJavaMethod(
160
env, s_SingleRowWriter_class, "<init>", "(Lorg/postgresql/pljava/internal/TupleDesc;)V");
162
s_SingleRowWriter_getTupleAndClear = PgObject_getJavaMethod(
163
env, s_SingleRowWriter_class, "getTupleAndClear", "()Lorg/postgresql/pljava/internal/Tuple;");
165
s_idCache = HashMap_create(13, TopMemoryContext);
166
#if (PGSQL_MAJOR_VER >= 8)
167
s_modCache = HashMap_create(13, TopMemoryContext);
170
s_SingleRowWriterClass = ComplexTypeClass_alloc("type.SingleRowWriter");
171
s_SingleRowWriterClass->JNISignature = "Ljava/sql/ResultSet;";
172
s_SingleRowWriterClass->javaTypeName = "java.lang.ResultSet";
173
s_SingleRowWriterClass->coerceDatum = _SingleRowWriter_coerceDatum;
174
s_SingleRowWriterClass->coerceObject = _SingleRowWriter_coerceObject;
175
s_SingleRowWriterClass->invoke = _SingleRowWriter_invoke;
177
Type_registerJavaType("org.postgresql.pljava.jdbc.SingleRowWriter", SingleRowWriter_obtain);