2
* Copyright (c) 2004, 2005, 2006 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
10
#include <executor/tuptable.h>
11
#include <utils/guc.h>
13
#include "org_postgresql_pljava_internal_ExecutionPlan.h"
14
#include "pljava/Invocation.h"
15
#include "pljava/Exception.h"
16
#include "pljava/Function.h"
17
#include "pljava/SPI.h"
18
#include "pljava/type/Oid.h"
19
#include "pljava/type/Portal.h"
20
#include "pljava/type/String.h"
22
/* Class 07 - Dynamic SQL Error */
23
#define ERRCODE_PARAMETER_COUNT_MISMATCH MAKE_SQLSTATE('0','7', '0','0','1')
25
/* Make this datatype available to the postgres system.
27
extern void ExecutionPlan_initialize(void);
28
void ExecutionPlan_initialize(void)
30
JNINativeMethod methods[] =
34
"(JJLjava/lang/String;[Ljava/lang/Object;)Lorg/postgresql/pljava/internal/Portal;",
35
Java_org_postgresql_pljava_internal_ExecutionPlan__1cursorOpen
40
Java_org_postgresql_pljava_internal_ExecutionPlan__1isCursorPlan
44
"(JJ[Ljava/lang/Object;I)I",
45
Java_org_postgresql_pljava_internal_ExecutionPlan__1execute
49
"(JLjava/lang/String;[Lorg/postgresql/pljava/internal/Oid;)J",
50
Java_org_postgresql_pljava_internal_ExecutionPlan__1prepare
55
Java_org_postgresql_pljava_internal_ExecutionPlan__1invalidate
59
PgObject_registerNatives("org/postgresql/pljava/internal/ExecutionPlan", methods);
62
static bool coerceObjects(void* ePlan, jobjectArray jvalues, Datum** valuesPtr, char** nullsPtr)
67
int count = SPI_getargcount(ePlan);
68
if((jvalues == 0 && count != 0)
69
|| (jvalues != 0 && count != JNI_getArrayLength(jvalues)))
71
Exception_throw(ERRCODE_PARAMETER_COUNT_MISMATCH,
72
"Number of values does not match number of arguments for prepared plan");
79
jobject typeMap = Invocation_getTypeMap();
80
values = (Datum*)palloc(count * sizeof(Datum));
81
for(idx = 0; idx < count; ++idx)
83
Oid typeId = SPI_getargtypeid(ePlan, idx);
84
Type type = Type_fromOid(typeId, typeMap);
85
jobject value = JNI_getObjectArrayElement(jvalues, idx);
88
values[idx] = Type_coerceObject(type, value);
89
JNI_deleteLocalRef(value);
96
nulls = (char*)palloc(count+1);
97
memset(nulls, ' ', count); /* all values non-null initially */
110
/****************************************
112
****************************************/
114
* Class: org_postgresql_pljava_internal_ExecutionPlan
115
* Method: _cursorOpen
116
* Signature: (JJLjava/lang/String;[Ljava/lang/Object;)Lorg/postgresql/pljava/internal/Portal;
118
JNIEXPORT jobject JNICALL
119
Java_org_postgresql_pljava_internal_ExecutionPlan__1cursorOpen(JNIEnv* env, jclass clazz, jlong _this, jlong threadId, jstring cursorName, jobjectArray jvalues)
126
STACK_BASE_PUSH(threadId)
133
if(coerceObjects(p2l.ptrVal, jvalues, &values, &nulls))
138
name = String_createNTS(cursorName);
140
Invocation_assertConnect();
141
portal = SPI_cursor_open(
142
name, p2l.ptrVal, values, nulls, Function_isCurrentReadOnly());
150
jportal = Portal_create(portal);
155
Exception_throw_ERROR("SPI_cursor_open");
165
* Class: org_postgresql_pljava_internal_ExecutionPlan
166
* Method: _isCursorPlan
169
JNIEXPORT jboolean JNICALL
170
Java_org_postgresql_pljava_internal_ExecutionPlan__1isCursorPlan(JNIEnv* env, jclass clazz, jlong _this)
172
jboolean result = JNI_FALSE;
181
Invocation_assertConnect();
182
result = (jboolean)SPI_is_cursor_plan(p2l.ptrVal);
186
Exception_throw_ERROR("SPI_is_cursor_plan");
195
* Class: org_postgresql_pljava_internal_ExecutionPlan
197
* Signature: (JJ[Ljava/lang/Object;I)V
199
JNIEXPORT jint JNICALL
200
Java_org_postgresql_pljava_internal_ExecutionPlan__1execute(JNIEnv* env, jclass clazz, jlong _this, jlong threadId, jobjectArray jvalues, jint count)
207
STACK_BASE_PUSH(threadId)
214
if(coerceObjects(p2l.ptrVal, jvalues, &values, &nulls))
216
Invocation_assertConnect();
217
result = (jint)SPI_execute_plan(
218
p2l.ptrVal, values, nulls, Function_isCurrentReadOnly(), (int)count);
220
Exception_throwSPI("execute_plan", result);
230
Exception_throw_ERROR("SPI_execute_plan");
240
* Class: org_postgresql_pljava_internal_ExecutionPlan
242
* Signature: (JLjava/lang/String;[Lorg/postgresql/pljava/internal/Oid;)J;
244
JNIEXPORT jlong JNICALL
245
Java_org_postgresql_pljava_internal_ExecutionPlan__1prepare(JNIEnv* env, jclass clazz, jlong threadId, jstring jcmd, jobjectArray paramTypes)
250
STACK_BASE_PUSH(threadId)
260
paramCount = JNI_getArrayLength(paramTypes);
264
paramOids = (Oid*)palloc(paramCount * sizeof(Oid));
265
for(idx = 0; idx < paramCount; ++idx)
267
jobject joid = JNI_getObjectArrayElement(paramTypes, idx);
268
paramOids[idx] = Oid_getOid(joid);
269
JNI_deleteLocalRef(joid);
274
cmd = String_createNTS(jcmd);
275
Invocation_assertConnect();
276
ePlan = SPI_prepare(cmd, paramCount, paramOids);
280
Exception_throwSPI("prepare", SPI_result);
285
/* Make the plan durable
287
p2l.longVal = 0L; /* ensure that the rest is zeroed out */
288
p2l.ptrVal = SPI_saveplan(ePlan);
289
result = p2l.longVal;
290
SPI_freeplan(ePlan); /* Get rid of the original, nobody can see it anymore */
295
Exception_throw_ERROR("SPI_prepare");
304
* Class: org_postgresql_pljava_internal_ExecutionPlan
305
* Method: _invalidate
308
JNIEXPORT void JNICALL
309
Java_org_postgresql_pljava_internal_ExecutionPlan__1invalidate(JNIEnv* env, jclass clazz, jlong _this)
311
/* The plan is not cached as a normal JavaHandle since its made
316
BEGIN_NATIVE_NO_ERRCHECK
321
SPI_freeplan(p2l.ptrVal);
325
Exception_throw_ERROR("SPI_freeplan");