~ubuntu-branches/ubuntu/oneiric/postgresql-pljava/oneiric

« back to all changes in this revision

Viewing changes to src/C/pljava/ExecutionPlan.c

  • Committer: Bazaar Package Importer
  • Author(s): Peter Eisentraut
  • Date: 2006-06-26 10:44:55 UTC
  • mfrom: (1.1.1 upstream) (3.1.1 edgy)
  • Revision ID: james.westby@ubuntu.com-20060626104455-135i9wosat2k8vvt
Tags: 1.3.0-1
* New upstream release (closes: #375199)
* Built for postgresql 8.1 (closes: #339641)
* Rebuilt for new libgcj library (closes: #369986)
* Updated copyright file
* Updated standards version
* Made use of cdbs simple patchsys

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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
 
6
 *
 
7
 * @author Thomas Hallgren
 
8
 */
 
9
#include <postgres.h>
 
10
#include <executor/tuptable.h>
 
11
#include <utils/guc.h>
 
12
 
 
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"
 
21
 
 
22
/* Class 07 - Dynamic SQL Error */
 
23
#define ERRCODE_PARAMETER_COUNT_MISMATCH        MAKE_SQLSTATE('0','7', '0','0','1')
 
24
 
 
25
/* Make this datatype available to the postgres system.
 
26
 */
 
27
extern void ExecutionPlan_initialize(void);
 
28
void ExecutionPlan_initialize(void)
 
29
{
 
30
        JNINativeMethod methods[] =
 
31
        {
 
32
                {
 
33
                "_cursorOpen",
 
34
                "(JJLjava/lang/String;[Ljava/lang/Object;)Lorg/postgresql/pljava/internal/Portal;",
 
35
                Java_org_postgresql_pljava_internal_ExecutionPlan__1cursorOpen
 
36
                },
 
37
                {
 
38
                "_isCursorPlan",
 
39
                "(J)Z",
 
40
                Java_org_postgresql_pljava_internal_ExecutionPlan__1isCursorPlan
 
41
                },
 
42
                {
 
43
                "_execute",
 
44
                "(JJ[Ljava/lang/Object;I)I",
 
45
                Java_org_postgresql_pljava_internal_ExecutionPlan__1execute
 
46
                },
 
47
                {
 
48
                "_prepare",
 
49
                "(JLjava/lang/String;[Lorg/postgresql/pljava/internal/Oid;)J",
 
50
                Java_org_postgresql_pljava_internal_ExecutionPlan__1prepare
 
51
                },
 
52
                {
 
53
                "_invalidate",
 
54
                "(J)V",
 
55
                Java_org_postgresql_pljava_internal_ExecutionPlan__1invalidate
 
56
                },
 
57
                { 0, 0, 0 }
 
58
        };
 
59
        PgObject_registerNatives("org/postgresql/pljava/internal/ExecutionPlan", methods);
 
60
}
 
61
 
 
62
static bool coerceObjects(void* ePlan, jobjectArray jvalues, Datum** valuesPtr, char** nullsPtr)
 
63
{
 
64
        char*  nulls = 0;
 
65
        Datum* values = 0;
 
66
 
 
67
        int count = SPI_getargcount(ePlan);
 
68
        if((jvalues == 0 && count != 0)
 
69
        || (jvalues != 0 && count != JNI_getArrayLength(jvalues)))
 
70
        {
 
71
                Exception_throw(ERRCODE_PARAMETER_COUNT_MISMATCH,
 
72
                        "Number of values does not match number of arguments for prepared plan");
 
73
                return false;
 
74
        }
 
75
 
 
76
        if(count > 0)
 
77
        {
 
78
                int idx;
 
79
                jobject typeMap = Invocation_getTypeMap();
 
80
                values = (Datum*)palloc(count * sizeof(Datum));
 
81
                for(idx = 0; idx < count; ++idx)
 
82
                {
 
83
                        Oid typeId = SPI_getargtypeid(ePlan, idx);
 
84
                        Type type = Type_fromOid(typeId, typeMap);
 
85
                        jobject value = JNI_getObjectArrayElement(jvalues, idx);
 
86
                        if(value != 0)
 
87
                        {
 
88
                                values[idx] = Type_coerceObject(type, value);
 
89
                                JNI_deleteLocalRef(value);
 
90
                        }
 
91
                        else
 
92
                        {
 
93
                                values[idx] = 0;
 
94
                                if(nulls == 0)
 
95
                                {
 
96
                                        nulls = (char*)palloc(count+1);
 
97
                                        memset(nulls, ' ', count);      /* all values non-null initially */
 
98
                                        nulls[count] = 0;
 
99
                                        *nullsPtr = nulls;
 
100
                                }
 
101
                                nulls[idx] = 'n';
 
102
                        }
 
103
                }
 
104
        }
 
105
        *valuesPtr = values;
 
106
        *nullsPtr = nulls;
 
107
        return true;
 
108
}
 
109
 
 
110
/****************************************
 
111
 * JNI methods
 
112
 ****************************************/
 
113
/*
 
114
 * Class:     org_postgresql_pljava_internal_ExecutionPlan
 
115
 * Method:    _cursorOpen
 
116
 * Signature: (JJLjava/lang/String;[Ljava/lang/Object;)Lorg/postgresql/pljava/internal/Portal;
 
117
 */
 
118
JNIEXPORT jobject JNICALL
 
119
Java_org_postgresql_pljava_internal_ExecutionPlan__1cursorOpen(JNIEnv* env, jclass clazz, jlong _this, jlong threadId, jstring cursorName, jobjectArray jvalues)
 
120
{
 
121
        jobject jportal = 0;
 
122
        if(_this != 0)
 
123
        {
 
124
                BEGIN_NATIVE
 
125
                STACK_BASE_VARS
 
126
                STACK_BASE_PUSH(threadId)
 
127
                PG_TRY();
 
128
                {
 
129
                        Ptr2Long p2l;
 
130
                        Datum*  values  = 0;
 
131
                        char*   nulls   = 0;
 
132
                        p2l.longVal = _this;
 
133
                        if(coerceObjects(p2l.ptrVal, jvalues, &values, &nulls))
 
134
                        {
 
135
                                Portal portal;
 
136
                                char* name = 0;
 
137
                                if(cursorName != 0)
 
138
                                        name = String_createNTS(cursorName);
 
139
 
 
140
                                Invocation_assertConnect();
 
141
                                portal = SPI_cursor_open(
 
142
                                        name, p2l.ptrVal, values, nulls, Function_isCurrentReadOnly());
 
143
                                if(name != 0)
 
144
                                        pfree(name);
 
145
                                if(values != 0)
 
146
                                        pfree(values);
 
147
                                if(nulls != 0)
 
148
                                        pfree(nulls);
 
149
                        
 
150
                                jportal = Portal_create(portal);
 
151
                        }
 
152
                }
 
153
                PG_CATCH();
 
154
                {
 
155
                        Exception_throw_ERROR("SPI_cursor_open");
 
156
                }
 
157
                PG_END_TRY();
 
158
                STACK_BASE_POP()
 
159
                END_NATIVE
 
160
        }
 
161
        return jportal;
 
162
}
 
163
 
 
164
/*
 
165
 * Class:     org_postgresql_pljava_internal_ExecutionPlan
 
166
 * Method:    _isCursorPlan
 
167
 * Signature: (J)Z
 
168
 */
 
169
JNIEXPORT jboolean JNICALL
 
170
Java_org_postgresql_pljava_internal_ExecutionPlan__1isCursorPlan(JNIEnv* env, jclass clazz, jlong _this)
 
171
{
 
172
        jboolean result = JNI_FALSE;
 
173
 
 
174
        if(_this != 0)
 
175
        {
 
176
                BEGIN_NATIVE
 
177
                PG_TRY();
 
178
                {
 
179
                        Ptr2Long p2l;
 
180
                        p2l.longVal = _this;
 
181
                        Invocation_assertConnect();
 
182
                        result = (jboolean)SPI_is_cursor_plan(p2l.ptrVal);
 
183
                }
 
184
                PG_CATCH();
 
185
                {
 
186
                        Exception_throw_ERROR("SPI_is_cursor_plan");
 
187
                }
 
188
                PG_END_TRY();
 
189
                END_NATIVE
 
190
        }
 
191
        return result;
 
192
}
 
193
 
 
194
/*
 
195
 * Class:     org_postgresql_pljava_internal_ExecutionPlan
 
196
 * Method:    _execute
 
197
 * Signature: (JJ[Ljava/lang/Object;I)V
 
198
 */
 
199
JNIEXPORT jint JNICALL
 
200
Java_org_postgresql_pljava_internal_ExecutionPlan__1execute(JNIEnv* env, jclass clazz, jlong _this, jlong threadId, jobjectArray jvalues, jint count)
 
201
{
 
202
        jint result = 0;
 
203
        if(_this != 0)
 
204
        {
 
205
                BEGIN_NATIVE
 
206
                STACK_BASE_VARS
 
207
                STACK_BASE_PUSH(threadId)
 
208
                PG_TRY();
 
209
                {
 
210
                        Ptr2Long p2l;
 
211
                        Datum* values = 0;
 
212
                        char*  nulls  = 0;
 
213
                        p2l.longVal = _this;
 
214
                        if(coerceObjects(p2l.ptrVal, jvalues, &values, &nulls))
 
215
                        {
 
216
                                Invocation_assertConnect();
 
217
                                result = (jint)SPI_execute_plan(
 
218
                                        p2l.ptrVal, values, nulls, Function_isCurrentReadOnly(), (int)count);
 
219
                                if(result < 0)
 
220
                                        Exception_throwSPI("execute_plan", result);
 
221
 
 
222
                                if(values != 0)
 
223
                                        pfree(values);
 
224
                                if(nulls != 0)
 
225
                                        pfree(nulls);
 
226
                        }
 
227
                }
 
228
                PG_CATCH();
 
229
                {
 
230
                        Exception_throw_ERROR("SPI_execute_plan");
 
231
                }
 
232
                PG_END_TRY();
 
233
                STACK_BASE_POP()
 
234
                END_NATIVE
 
235
        }
 
236
        return result;
 
237
}
 
238
 
 
239
/*
 
240
 * Class:     org_postgresql_pljava_internal_ExecutionPlan
 
241
 * Method:    _prepare
 
242
 * Signature: (JLjava/lang/String;[Lorg/postgresql/pljava/internal/Oid;)J;
 
243
 */
 
244
JNIEXPORT jlong JNICALL
 
245
Java_org_postgresql_pljava_internal_ExecutionPlan__1prepare(JNIEnv* env, jclass clazz, jlong threadId, jstring jcmd, jobjectArray paramTypes)
 
246
{
 
247
        jlong result = 0;
 
248
        BEGIN_NATIVE
 
249
        STACK_BASE_VARS
 
250
        STACK_BASE_PUSH(threadId)
 
251
        PG_TRY();
 
252
        {
 
253
                char* cmd;
 
254
                void* ePlan;
 
255
                int paramCount = 0;
 
256
                Oid* paramOids = 0;
 
257
 
 
258
                if(paramTypes != 0)
 
259
                {
 
260
                        paramCount = JNI_getArrayLength(paramTypes);
 
261
                        if(paramCount > 0)
 
262
                        {
 
263
                                int idx;
 
264
                                paramOids = (Oid*)palloc(paramCount * sizeof(Oid));
 
265
                                for(idx = 0; idx < paramCount; ++idx)
 
266
                                {
 
267
                                        jobject joid = JNI_getObjectArrayElement(paramTypes, idx);
 
268
                                        paramOids[idx] = Oid_getOid(joid);
 
269
                                        JNI_deleteLocalRef(joid);
 
270
                                }
 
271
                        }
 
272
                }
 
273
 
 
274
                cmd   = String_createNTS(jcmd);
 
275
                Invocation_assertConnect();
 
276
                ePlan = SPI_prepare(cmd, paramCount, paramOids);
 
277
                pfree(cmd);
 
278
 
 
279
                if(ePlan == 0)
 
280
                        Exception_throwSPI("prepare", SPI_result);
 
281
                else
 
282
                {
 
283
                        Ptr2Long p2l;
 
284
                        
 
285
                        /* Make the plan durable
 
286
                         */
 
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 */
 
291
                }
 
292
        }
 
293
        PG_CATCH();
 
294
        {
 
295
                Exception_throw_ERROR("SPI_prepare");
 
296
        }
 
297
        PG_END_TRY();
 
298
        STACK_BASE_POP()
 
299
        END_NATIVE
 
300
        return result;
 
301
}
 
302
 
 
303
/*
 
304
 * Class:     org_postgresql_pljava_internal_ExecutionPlan
 
305
 * Method:    _invalidate
 
306
 * Signature: (J)V
 
307
 */
 
308
JNIEXPORT void JNICALL
 
309
Java_org_postgresql_pljava_internal_ExecutionPlan__1invalidate(JNIEnv* env, jclass clazz, jlong _this)
 
310
{
 
311
        /* The plan is not cached as a normal JavaHandle since its made
 
312
         * persistent.
 
313
         */
 
314
        if(_this != 0)
 
315
        {
 
316
                BEGIN_NATIVE_NO_ERRCHECK
 
317
                PG_TRY();
 
318
                {
 
319
                        Ptr2Long p2l;
 
320
                        p2l.longVal = _this;
 
321
                        SPI_freeplan(p2l.ptrVal);
 
322
                }
 
323
                PG_CATCH();
 
324
                {
 
325
                        Exception_throw_ERROR("SPI_freeplan");
 
326
                }
 
327
                PG_END_TRY();
 
328
                END_NATIVE
 
329
        }
 
330
}