oracledb 3.0.0 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/CHANGELOG.md +135 -8
  2. package/README.md +6 -4
  3. package/build/Release/oracledb-abi48-darwin-x64.node +0 -0
  4. package/build/Release/oracledb-abi48-darwin-x64.node-buildinfo.txt +1 -0
  5. package/build/Release/oracledb-abi48-linux-x64.node +0 -0
  6. package/build/Release/oracledb-abi48-linux-x64.node-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-abi48-win32-x64.node +0 -0
  8. package/build/Release/oracledb-abi48-win32-x64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-abi57-darwin-x64.node +0 -0
  10. package/build/Release/oracledb-abi57-darwin-x64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-abi57-linux-x64.node +0 -0
  12. package/build/Release/oracledb-abi57-linux-x64.node-buildinfo.txt +1 -0
  13. package/build/Release/oracledb-abi57-win32-x64.node +0 -0
  14. package/build/Release/oracledb-abi57-win32-x64.node-buildinfo.txt +1 -0
  15. package/build/Release/oracledb-abi64-darwin-x64.node +0 -0
  16. package/build/Release/oracledb-abi64-darwin-x64.node-buildinfo.txt +1 -0
  17. package/build/Release/oracledb-abi64-linux-x64.node +0 -0
  18. package/build/Release/oracledb-abi64-linux-x64.node-buildinfo.txt +1 -0
  19. package/build/Release/oracledb-abi64-win32-x64.node +0 -0
  20. package/build/Release/oracledb-abi64-win32-x64.node-buildinfo.txt +1 -0
  21. package/build/Release/oracledb-abi67-darwin-x64.node +0 -0
  22. package/build/Release/oracledb-abi67-darwin-x64.node-buildinfo.txt +1 -0
  23. package/build/Release/oracledb-abi67-linux-x64.node +0 -0
  24. package/build/Release/oracledb-abi67-linux-x64.node-buildinfo.txt +1 -0
  25. package/build/Release/oracledb-abi67-win32-x64.node +0 -0
  26. package/build/Release/oracledb-abi67-win32-x64.node-buildinfo.txt +1 -0
  27. package/lib/connection.js +18 -4
  28. package/lib/oracledb.js +44 -92
  29. package/lib/pool.js +36 -2
  30. package/lib/sodaCollection.js +1 -1
  31. package/lib/sodaDatabase.js +1 -1
  32. package/lib/util.js +82 -5
  33. package/package/README.md +32 -101
  34. package/package/install.js +139 -0
  35. package/package/prunebinaries.js +51 -0
  36. package/package.json +4 -11
  37. package/binding.gyp +0 -162
  38. package/lib/rel.txt +0 -1
  39. package/odpi/.npmignore +0 -4
  40. package/odpi/LICENSE.md +0 -218
  41. package/odpi/README.md +0 -61
  42. package/odpi/embed/README.md +0 -4
  43. package/odpi/embed/dpi.c +0 -50
  44. package/odpi/include/dpi.h +0 -1748
  45. package/odpi/src/dpiConn.c +0 -2089
  46. package/odpi/src/dpiContext.c +0 -296
  47. package/odpi/src/dpiData.c +0 -797
  48. package/odpi/src/dpiDebug.c +0 -184
  49. package/odpi/src/dpiDeqOptions.c +0 -370
  50. package/odpi/src/dpiEnqOptions.c +0 -174
  51. package/odpi/src/dpiEnv.c +0 -189
  52. package/odpi/src/dpiError.c +0 -204
  53. package/odpi/src/dpiErrorMessages.h +0 -86
  54. package/odpi/src/dpiGen.c +0 -303
  55. package/odpi/src/dpiGlobal.c +0 -292
  56. package/odpi/src/dpiHandleList.c +0 -117
  57. package/odpi/src/dpiHandlePool.c +0 -118
  58. package/odpi/src/dpiImpl.h +0 -1707
  59. package/odpi/src/dpiLob.c +0 -506
  60. package/odpi/src/dpiMsgProps.c +0 -386
  61. package/odpi/src/dpiObject.c +0 -897
  62. package/odpi/src/dpiObjectAttr.c +0 -115
  63. package/odpi/src/dpiObjectType.c +0 -326
  64. package/odpi/src/dpiOci.c +0 -3527
  65. package/odpi/src/dpiOracleType.c +0 -492
  66. package/odpi/src/dpiPool.c +0 -549
  67. package/odpi/src/dpiRowid.c +0 -136
  68. package/odpi/src/dpiSodaColl.c +0 -685
  69. package/odpi/src/dpiSodaCollCursor.c +0 -143
  70. package/odpi/src/dpiSodaDb.c +0 -432
  71. package/odpi/src/dpiSodaDoc.c +0 -230
  72. package/odpi/src/dpiSodaDocCursor.c +0 -143
  73. package/odpi/src/dpiStmt.c +0 -1797
  74. package/odpi/src/dpiSubscr.c +0 -674
  75. package/odpi/src/dpiUtils.c +0 -410
  76. package/odpi/src/dpiVar.c +0 -1794
  77. package/package/MAKEPKG.BAT +0 -156
  78. package/package/Makefile +0 -85
  79. package/package/createpackage.js +0 -186
  80. package/package/extractpackage.js +0 -76
  81. package/package/getversion.js +0 -37
  82. package/package/oracledbinstall.js +0 -497
  83. package/package/package.json +0 -54
  84. package/package/util.js +0 -286
  85. package/src/njsCommon.cpp +0 -1055
  86. package/src/njsCommon.h +0 -484
  87. package/src/njsConnection.cpp +0 -2926
  88. package/src/njsConnection.h +0 -227
  89. package/src/njsIntLob.cpp +0 -618
  90. package/src/njsIntLob.h +0 -179
  91. package/src/njsMessages.cpp +0 -122
  92. package/src/njsMessages.h +0 -118
  93. package/src/njsOracle.cpp +0 -1274
  94. package/src/njsOracle.h +0 -237
  95. package/src/njsPool.cpp +0 -482
  96. package/src/njsPool.h +0 -132
  97. package/src/njsResultSet.cpp +0 -478
  98. package/src/njsResultSet.h +0 -120
  99. package/src/njsSodaCollection.cpp +0 -507
  100. package/src/njsSodaCollection.h +0 -128
  101. package/src/njsSodaDatabase.cpp +0 -335
  102. package/src/njsSodaDatabase.h +0 -108
  103. package/src/njsSodaDocCursor.cpp +0 -203
  104. package/src/njsSodaDocCursor.h +0 -94
  105. package/src/njsSodaDocument.cpp +0 -412
  106. package/src/njsSodaDocument.h +0 -105
  107. package/src/njsSodaOperation.cpp +0 -557
  108. package/src/njsSodaOperation.h +0 -123
  109. package/src/njsSubscription.cpp +0 -388
  110. package/src/njsSubscription.h +0 -111
  111. package/src/njsUtils.cpp +0 -158
  112. package/src/njsUtils.h +0 -68
@@ -1,1797 +0,0 @@
1
- //-----------------------------------------------------------------------------
2
- // Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
3
- // This program is free software: you can modify it and/or redistribute it
4
- // under the terms of:
5
- //
6
- // (i) the Universal Permissive License v 1.0 or at your option, any
7
- // later version (http://oss.oracle.com/licenses/upl); and/or
8
- //
9
- // (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0)
10
- //-----------------------------------------------------------------------------
11
-
12
- //-----------------------------------------------------------------------------
13
- // dpiStmt.c
14
- // Implementation of statements (cursors).
15
- //-----------------------------------------------------------------------------
16
-
17
- #include "dpiImpl.h"
18
-
19
- // forward declarations of internal functions only used in this file
20
- static int dpiStmt__getQueryInfo(dpiStmt *stmt, uint32_t pos,
21
- dpiQueryInfo *info, dpiError *error);
22
- static int dpiStmt__getQueryInfoFromParam(dpiStmt *stmt, void *param,
23
- dpiQueryInfo *info, dpiError *error);
24
- static int dpiStmt__postFetch(dpiStmt *stmt, dpiError *error);
25
- static int dpiStmt__beforeFetch(dpiStmt *stmt, dpiError *error);
26
- static int dpiStmt__reExecute(dpiStmt *stmt, uint32_t numIters,
27
- uint32_t mode, dpiError *error);
28
-
29
-
30
- //-----------------------------------------------------------------------------
31
- // dpiStmt__allocate() [INTERNAL]
32
- // Create a new statement object and return it. In case of error NULL is
33
- // returned.
34
- //-----------------------------------------------------------------------------
35
- int dpiStmt__allocate(dpiConn *conn, int scrollable, dpiStmt **stmt,
36
- dpiError *error)
37
- {
38
- dpiStmt *tempStmt;
39
-
40
- *stmt = NULL;
41
- if (dpiGen__allocate(DPI_HTYPE_STMT, conn->env, (void**) &tempStmt,
42
- error) < 0)
43
- return DPI_FAILURE;
44
- dpiGen__setRefCount(conn, error, 1);
45
- tempStmt->conn = conn;
46
- tempStmt->fetchArraySize = DPI_DEFAULT_FETCH_ARRAY_SIZE;
47
- tempStmt->scrollable = scrollable;
48
- *stmt = tempStmt;
49
- return DPI_SUCCESS;
50
- }
51
-
52
-
53
- //-----------------------------------------------------------------------------
54
- // dpiStmt__bind() [INTERNAL]
55
- // Bind the variable to the statement using either a position or a name. A
56
- // reference to the variable will be retained.
57
- //-----------------------------------------------------------------------------
58
- static int dpiStmt__bind(dpiStmt *stmt, dpiVar *var, int addReference,
59
- uint32_t pos, const char *name, uint32_t nameLength, dpiError *error)
60
- {
61
- dpiBindVar *bindVars, *entry = NULL;
62
- int found, dynamicBind, status;
63
- void *bindHandle = NULL;
64
- uint32_t i;
65
-
66
- // a zero length name is not supported
67
- if (pos == 0 && nameLength == 0)
68
- return dpiError__set(error, "bind zero length name",
69
- DPI_ERR_NOT_SUPPORTED);
70
-
71
- // check to see if the bind position or name has already been bound
72
- found = 0;
73
- for (i = 0; i < stmt->numBindVars; i++) {
74
- entry = &stmt->bindVars[i];
75
- if (entry->pos == pos && entry->nameLength == nameLength) {
76
- if (nameLength > 0 && strncmp(entry->name, name, nameLength) != 0)
77
- continue;
78
- found = 1;
79
- break;
80
- }
81
- }
82
-
83
- // if already found, use that entry
84
- if (found) {
85
-
86
- // if already bound, no need to bind a second time
87
- if (entry->var == var)
88
- return DPI_SUCCESS;
89
-
90
- // otherwise, release previously bound variable, if applicable
91
- else if (entry->var) {
92
- dpiGen__setRefCount(entry->var, error, -1);
93
- entry->var = NULL;
94
- }
95
-
96
- // if not found, add to the list of bind variables
97
- } else {
98
-
99
- // allocate memory for additional bind variables, if needed
100
- if (stmt->numBindVars == stmt->allocatedBindVars) {
101
- if (dpiUtils__allocateMemory(stmt->allocatedBindVars + 8,
102
- sizeof(dpiBindVar), 1, "allocate bind vars",
103
- (void**) &bindVars, error) < 0)
104
- return DPI_FAILURE;
105
- if (stmt->bindVars) {
106
- for (i = 0; i < stmt->numBindVars; i++)
107
- bindVars[i] = stmt->bindVars[i];
108
- dpiUtils__freeMemory(stmt->bindVars);
109
- }
110
- stmt->bindVars = bindVars;
111
- stmt->allocatedBindVars += 8;
112
- }
113
-
114
- // add to the list of bind variables
115
- entry = &stmt->bindVars[stmt->numBindVars];
116
- entry->var = NULL;
117
- entry->pos = pos;
118
- if (name) {
119
- if (dpiUtils__allocateMemory(1, nameLength, 0,
120
- "allocate memory for name", (void**) &entry->name,
121
- error) < 0)
122
- return DPI_FAILURE;
123
- entry->nameLength = nameLength;
124
- memcpy( (void*) entry->name, name, nameLength);
125
- }
126
- stmt->numBindVars++;
127
-
128
- }
129
-
130
- // for PL/SQL where the maxSize is greater than 32K, adjust the variable
131
- // so that LOBs are used internally
132
- if (var->isDynamic && (stmt->statementType == DPI_STMT_TYPE_BEGIN ||
133
- stmt->statementType == DPI_STMT_TYPE_DECLARE ||
134
- stmt->statementType == DPI_STMT_TYPE_CALL)) {
135
- if (dpiVar__convertToLob(var, error) < 0)
136
- return DPI_FAILURE;
137
- }
138
-
139
- // perform actual bind
140
- if (addReference)
141
- dpiGen__setRefCount(var, error, 1);
142
- entry->var = var;
143
- dynamicBind = stmt->isReturning || var->isDynamic;
144
- if (pos > 0) {
145
- if (stmt->env->versionInfo->versionNum < 12)
146
- status = dpiOci__bindByPos(stmt, &bindHandle, pos, dynamicBind,
147
- var, error);
148
- else status = dpiOci__bindByPos2(stmt, &bindHandle, pos, dynamicBind,
149
- var, error);
150
- } else {
151
- if (stmt->env->versionInfo->versionNum < 12)
152
- status = dpiOci__bindByName(stmt, &bindHandle, name,
153
- (int32_t) nameLength, dynamicBind, var, error);
154
- else status = dpiOci__bindByName2(stmt, &bindHandle, name,
155
- (int32_t) nameLength, dynamicBind, var, error);
156
- }
157
-
158
- // attempt to improve message "ORA-01036: illegal variable name/number"
159
- if (status < 0) {
160
- if (error->buffer->code == 1036) {
161
- if (stmt->statementType == DPI_STMT_TYPE_CREATE ||
162
- stmt->statementType == DPI_STMT_TYPE_DROP ||
163
- stmt->statementType == DPI_STMT_TYPE_ALTER)
164
- dpiError__set(error, error->buffer->action,
165
- DPI_ERR_NO_BIND_VARS_IN_DDL);
166
- }
167
- return DPI_FAILURE;
168
- }
169
-
170
- // set the charset form if applicable
171
- if (var->type->charsetForm != DPI_SQLCS_IMPLICIT) {
172
- if (dpiOci__attrSet(bindHandle, DPI_OCI_HTYPE_BIND,
173
- (void*) &var->type->charsetForm, 0, DPI_OCI_ATTR_CHARSET_FORM,
174
- "set charset form", error) < 0)
175
- return DPI_FAILURE;
176
- }
177
-
178
- // set the max data size, if applicable
179
- if (var->type->sizeInBytes == 0 && !var->isDynamic) {
180
- if (dpiOci__attrSet(bindHandle, DPI_OCI_HTYPE_BIND,
181
- (void*) &var->sizeInBytes, 0, DPI_OCI_ATTR_MAXDATA_SIZE,
182
- "set max data size", error) < 0)
183
- return DPI_FAILURE;
184
- }
185
-
186
- // bind object, if applicable
187
- if (var->buffer.objectIndicator &&
188
- dpiOci__bindObject(var, bindHandle, error) < 0)
189
- return DPI_FAILURE;
190
-
191
- // setup dynamic bind, if applicable
192
- if (dynamicBind && dpiOci__bindDynamic(var, bindHandle, error) < 0)
193
- return DPI_FAILURE;
194
-
195
- return DPI_SUCCESS;
196
- }
197
-
198
-
199
- //-----------------------------------------------------------------------------
200
- // dpiStmt__check() [INTERNAL]
201
- // Determine if the statement is open and available for use.
202
- //-----------------------------------------------------------------------------
203
- static int dpiStmt__check(dpiStmt *stmt, const char *fnName, dpiError *error)
204
- {
205
- if (dpiGen__startPublicFn(stmt, DPI_HTYPE_STMT, fnName, 1, error) < 0)
206
- return DPI_FAILURE;
207
- if (!stmt->handle)
208
- return dpiError__set(error, "check closed", DPI_ERR_STMT_CLOSED);
209
- if (dpiConn__checkConnected(stmt->conn, error) < 0)
210
- return DPI_FAILURE;
211
- if (stmt->statementType == 0 && dpiStmt__init(stmt, error) < 0)
212
- return DPI_FAILURE;
213
- return DPI_SUCCESS;
214
- }
215
-
216
-
217
- //-----------------------------------------------------------------------------
218
- // dpiStmt__clearBatchErrors() [INTERNAL]
219
- // Clear the batch errors associated with the statement.
220
- //-----------------------------------------------------------------------------
221
- static void dpiStmt__clearBatchErrors(dpiStmt *stmt)
222
- {
223
- if (stmt->batchErrors) {
224
- dpiUtils__freeMemory(stmt->batchErrors);
225
- stmt->batchErrors = NULL;
226
- }
227
- stmt->numBatchErrors = 0;
228
- }
229
-
230
-
231
- //-----------------------------------------------------------------------------
232
- // dpiStmt__clearBindVars() [INTERNAL]
233
- // Clear the bind variables associated with the statement.
234
- //-----------------------------------------------------------------------------
235
- static void dpiStmt__clearBindVars(dpiStmt *stmt, dpiError *error)
236
- {
237
- uint32_t i;
238
-
239
- if (stmt->bindVars) {
240
- for (i = 0; i < stmt->numBindVars; i++) {
241
- dpiGen__setRefCount(stmt->bindVars[i].var, error, -1);
242
- if (stmt->bindVars[i].name)
243
- dpiUtils__freeMemory( (void*) stmt->bindVars[i].name);
244
- }
245
- dpiUtils__freeMemory(stmt->bindVars);
246
- stmt->bindVars = NULL;
247
- }
248
- stmt->numBindVars = 0;
249
- stmt->allocatedBindVars = 0;
250
- }
251
-
252
-
253
- //-----------------------------------------------------------------------------
254
- // dpiStmt__clearQueryVars() [INTERNAL]
255
- // Clear the query variables associated with the statement.
256
- //-----------------------------------------------------------------------------
257
- static void dpiStmt__clearQueryVars(dpiStmt *stmt, dpiError *error)
258
- {
259
- uint32_t i;
260
-
261
- if (stmt->queryVars) {
262
- for (i = 0; i < stmt->numQueryVars; i++) {
263
- if (stmt->queryVars[i]) {
264
- dpiGen__setRefCount(stmt->queryVars[i], error, -1);
265
- stmt->queryVars[i] = NULL;
266
- }
267
- if (stmt->queryInfo[i].typeInfo.objectType) {
268
- dpiGen__setRefCount(stmt->queryInfo[i].typeInfo.objectType,
269
- error, -1);
270
- stmt->queryInfo[i].typeInfo.objectType = NULL;
271
- }
272
- }
273
- dpiUtils__freeMemory(stmt->queryVars);
274
- stmt->queryVars = NULL;
275
- }
276
- if (stmt->queryInfo) {
277
- dpiUtils__freeMemory(stmt->queryInfo);
278
- stmt->queryInfo = NULL;
279
- }
280
- stmt->numQueryVars = 0;
281
- }
282
-
283
-
284
- //-----------------------------------------------------------------------------
285
- // dpiStmt__close() [INTERNAL]
286
- // Internal method used for closing the statement. If the statement is marked
287
- // as needing to be dropped from the statement cache that is done as well. This
288
- // is called from dpiStmt_close() where errors are expected to be propagated
289
- // and from dpiStmt__free() where errors are ignored.
290
- //-----------------------------------------------------------------------------
291
- int dpiStmt__close(dpiStmt *stmt, const char *tag, uint32_t tagLength,
292
- int propagateErrors, dpiError *error)
293
- {
294
- int closing, status = DPI_SUCCESS;
295
-
296
- // determine whether statement is already being closed and if not, mark
297
- // statement as being closed; this MUST be done while holding the lock (if
298
- // in threaded mode) to avoid race conditions!
299
- if (stmt->env->threaded)
300
- dpiMutex__acquire(stmt->env->mutex);
301
- closing = stmt->closing;
302
- stmt->closing = 1;
303
- if (stmt->env->threaded)
304
- dpiMutex__release(stmt->env->mutex);
305
-
306
- // if statement is already being closed, nothing needs to be done
307
- if (closing)
308
- return DPI_SUCCESS;
309
-
310
- // perform actual work of closing statement
311
- dpiStmt__clearBatchErrors(stmt);
312
- dpiStmt__clearBindVars(stmt, error);
313
- dpiStmt__clearQueryVars(stmt, error);
314
- if (stmt->handle) {
315
- if (!stmt->conn->deadSession && stmt->conn->handle) {
316
- if (stmt->isOwned)
317
- dpiOci__handleFree(stmt->handle, DPI_OCI_HTYPE_STMT);
318
- else status = dpiOci__stmtRelease(stmt, tag, tagLength,
319
- propagateErrors, error);
320
- }
321
- if (!stmt->conn->closing)
322
- dpiHandleList__removeHandle(stmt->conn->openStmts,
323
- stmt->openSlotNum);
324
- stmt->handle = NULL;
325
- }
326
-
327
- // if actual close fails, reset closing flag; again, this must be done
328
- // while holding the lock (if in threaded mode) in order to avoid race
329
- // conditions!
330
- if (status < 0) {
331
- if (stmt->env->threaded)
332
- dpiMutex__acquire(stmt->env->mutex);
333
- stmt->closing = 0;
334
- if (stmt->env->threaded)
335
- dpiMutex__release(stmt->env->mutex);
336
- }
337
-
338
- return status;
339
- }
340
-
341
-
342
- //-----------------------------------------------------------------------------
343
- // dpiStmt__createBindVar() [INTERNAL]
344
- // Create a bind variable given a value to bind.
345
- //-----------------------------------------------------------------------------
346
- static int dpiStmt__createBindVar(dpiStmt *stmt,
347
- dpiNativeTypeNum nativeTypeNum, dpiData *data, dpiVar **var,
348
- uint32_t pos, const char *name, uint32_t nameLength, dpiError *error)
349
- {
350
- dpiOracleTypeNum oracleTypeNum;
351
- dpiObjectType *objType;
352
- dpiData *varData;
353
- dpiVar *tempVar;
354
- uint32_t size;
355
-
356
- // determine the type (and size) of bind variable to create
357
- size = 0;
358
- objType = NULL;
359
- switch (nativeTypeNum) {
360
- case DPI_NATIVE_TYPE_INT64:
361
- case DPI_NATIVE_TYPE_UINT64:
362
- case DPI_NATIVE_TYPE_FLOAT:
363
- case DPI_NATIVE_TYPE_DOUBLE:
364
- oracleTypeNum = DPI_ORACLE_TYPE_NUMBER;
365
- break;
366
- case DPI_NATIVE_TYPE_BYTES:
367
- oracleTypeNum = DPI_ORACLE_TYPE_VARCHAR;
368
- size = data->value.asBytes.length;
369
- break;
370
- case DPI_NATIVE_TYPE_TIMESTAMP:
371
- oracleTypeNum = DPI_ORACLE_TYPE_TIMESTAMP;
372
- break;
373
- case DPI_NATIVE_TYPE_INTERVAL_DS:
374
- oracleTypeNum = DPI_ORACLE_TYPE_INTERVAL_DS;
375
- break;
376
- case DPI_NATIVE_TYPE_INTERVAL_YM:
377
- oracleTypeNum = DPI_ORACLE_TYPE_INTERVAL_YM;
378
- break;
379
- case DPI_NATIVE_TYPE_OBJECT:
380
- oracleTypeNum = DPI_ORACLE_TYPE_OBJECT;
381
- if (data->value.asObject)
382
- objType = data->value.asObject->type;
383
- break;
384
- case DPI_NATIVE_TYPE_ROWID:
385
- oracleTypeNum = DPI_ORACLE_TYPE_ROWID;
386
- break;
387
- case DPI_NATIVE_TYPE_BOOLEAN:
388
- oracleTypeNum = DPI_ORACLE_TYPE_BOOLEAN;
389
- break;
390
- default:
391
- return dpiError__set(error, "create bind var",
392
- DPI_ERR_UNHANDLED_CONVERSION, 0, nativeTypeNum);
393
- }
394
-
395
- // create the variable and set its value
396
- if (dpiVar__allocate(stmt->conn, oracleTypeNum, nativeTypeNum, 1, size, 1,
397
- 0, objType, &tempVar, &varData, error) < 0)
398
- return DPI_FAILURE;
399
-
400
- // copy value from source to target data
401
- if (dpiVar__copyData(tempVar, 0, data, error) < 0)
402
- return DPI_FAILURE;
403
-
404
- // bind variable to statement
405
- if (dpiStmt__bind(stmt, tempVar, 0, pos, name, nameLength, error) < 0) {
406
- dpiVar__free(tempVar, error);
407
- return DPI_FAILURE;
408
- }
409
-
410
- *var = tempVar;
411
- return DPI_SUCCESS;
412
- }
413
-
414
-
415
- //-----------------------------------------------------------------------------
416
- // dpiStmt__createQueryVars() [INTERNAL]
417
- // Create space for the number of query variables required to support the
418
- // query.
419
- //-----------------------------------------------------------------------------
420
- static int dpiStmt__createQueryVars(dpiStmt *stmt, dpiError *error)
421
- {
422
- uint32_t numQueryVars, i;
423
-
424
- // determine number of query variables
425
- if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT,
426
- (void*) &numQueryVars, 0, DPI_OCI_ATTR_PARAM_COUNT,
427
- "get parameter count", error) < 0)
428
- return DPI_FAILURE;
429
-
430
- // clear the previous query vars if the number has changed
431
- if (stmt->numQueryVars > 0 && stmt->numQueryVars != numQueryVars)
432
- dpiStmt__clearQueryVars(stmt, error);
433
-
434
- // allocate space for the query vars, if needed
435
- if (numQueryVars != stmt->numQueryVars) {
436
- if (dpiUtils__allocateMemory(numQueryVars, sizeof(dpiVar*), 1,
437
- "allocate query vars", (void**) &stmt->queryVars, error) < 0)
438
- return DPI_FAILURE;
439
- if (dpiUtils__allocateMemory(numQueryVars, sizeof(dpiQueryInfo), 1,
440
- "allocate query info", (void**) &stmt->queryInfo, error) < 0) {
441
- dpiStmt__clearQueryVars(stmt, error);
442
- return DPI_FAILURE;
443
- }
444
- stmt->numQueryVars = numQueryVars;
445
- for (i = 0; i < numQueryVars; i++) {
446
- if (dpiStmt__getQueryInfo(stmt, i + 1, &stmt->queryInfo[i],
447
- error) < 0) {
448
- dpiStmt__clearQueryVars(stmt, error);
449
- return DPI_FAILURE;
450
- }
451
- }
452
- }
453
-
454
- // indicate start of fetch
455
- stmt->bufferRowIndex = stmt->fetchArraySize;
456
- stmt->hasRowsToFetch = 1;
457
- return DPI_SUCCESS;
458
- }
459
-
460
-
461
- //-----------------------------------------------------------------------------
462
- // dpiStmt__define() [INTERNAL]
463
- // Define the variable that will accept output from the statement in the
464
- // specified column. At this point the statement, position and variable are all
465
- // assumed to be valid.
466
- //-----------------------------------------------------------------------------
467
- static int dpiStmt__define(dpiStmt *stmt, uint32_t pos, dpiVar *var,
468
- dpiError *error)
469
- {
470
- void *defineHandle = NULL;
471
- dpiQueryInfo *queryInfo;
472
-
473
- // no need to perform define if variable is unchanged
474
- if (stmt->queryVars[pos - 1] == var)
475
- return DPI_SUCCESS;
476
-
477
- // for objects, the type specified must match the type in the database
478
- queryInfo = &stmt->queryInfo[pos - 1];
479
- if (var->objectType && queryInfo->typeInfo.objectType &&
480
- var->objectType->tdo != queryInfo->typeInfo.objectType->tdo)
481
- return dpiError__set(error, "check type", DPI_ERR_WRONG_TYPE,
482
- var->objectType->schemaLength, var->objectType->schema,
483
- var->objectType->nameLength, var->objectType->name,
484
- queryInfo->typeInfo.objectType->schemaLength,
485
- queryInfo->typeInfo.objectType->schema,
486
- queryInfo->typeInfo.objectType->nameLength,
487
- queryInfo->typeInfo.objectType->name);
488
-
489
- // perform the define
490
- if (stmt->env->versionInfo->versionNum < 12) {
491
- if (dpiOci__defineByPos(stmt, &defineHandle, pos, var, error) < 0)
492
- return DPI_FAILURE;
493
- } else {
494
- if (dpiOci__defineByPos2(stmt, &defineHandle, pos, var, error) < 0)
495
- return DPI_FAILURE;
496
- }
497
-
498
- // set the charset form if applicable
499
- if (var->type->charsetForm != DPI_SQLCS_IMPLICIT) {
500
- if (dpiOci__attrSet(defineHandle, DPI_OCI_HTYPE_DEFINE,
501
- (void*) &var->type->charsetForm, 0, DPI_OCI_ATTR_CHARSET_FORM,
502
- "set charset form", error) < 0)
503
- return DPI_FAILURE;
504
- }
505
-
506
- // define objects, if applicable
507
- if (var->buffer.objectIndicator && dpiOci__defineObject(var, defineHandle,
508
- error) < 0)
509
- return DPI_FAILURE;
510
-
511
- // register callback for dynamic defines
512
- if (var->isDynamic && dpiOci__defineDynamic(var, defineHandle, error) < 0)
513
- return DPI_FAILURE;
514
-
515
- // remove previous variable and retain new one
516
- if (stmt->queryVars[pos - 1])
517
- dpiGen__setRefCount(stmt->queryVars[pos - 1], error, -1);
518
- dpiGen__setRefCount(var, error, 1);
519
- stmt->queryVars[pos - 1] = var;
520
-
521
- return DPI_SUCCESS;
522
- }
523
-
524
-
525
- //-----------------------------------------------------------------------------
526
- // dpiStmt__execute() [INTERNAL]
527
- // Internal execution of statement.
528
- //-----------------------------------------------------------------------------
529
- static int dpiStmt__execute(dpiStmt *stmt, uint32_t numIters,
530
- uint32_t mode, int reExecute, dpiError *error)
531
- {
532
- uint32_t prefetchSize, i, j;
533
- dpiData *data;
534
- dpiVar *var;
535
-
536
- // for all bound variables, transfer data from dpiData structure to Oracle
537
- // buffer structures
538
- for (i = 0; i < stmt->numBindVars; i++) {
539
- var = stmt->bindVars[i].var;
540
- if (var->isArray && numIters > 1)
541
- return dpiError__set(error, "bind array var",
542
- DPI_ERR_ARRAY_VAR_NOT_SUPPORTED);
543
- for (j = 0; j < var->buffer.maxArraySize; j++) {
544
- data = &var->buffer.externalData[j];
545
- if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_STMT &&
546
- data->value.asStmt == stmt)
547
- return dpiError__set(error, "bind to self",
548
- DPI_ERR_NOT_SUPPORTED);
549
- if (dpiVar__setValue(var, &var->buffer, j, data, error) < 0)
550
- return DPI_FAILURE;
551
- if (var->dynBindBuffers)
552
- var->dynBindBuffers[j].actualArraySize = 0;
553
- }
554
- if (stmt->isReturning || var->isDynamic)
555
- var->error = error;
556
- }
557
-
558
- // for queries, set the OCI prefetch to a fixed value; this prevents an
559
- // additional round trip for single row fetches while avoiding the overhead
560
- // of copying from the OCI prefetch buffer to our own buffers for larger
561
- // fetches
562
- if (stmt->statementType == DPI_STMT_TYPE_SELECT) {
563
- prefetchSize = DPI_PREFETCH_ROWS_DEFAULT;
564
- if (dpiOci__attrSet(stmt->handle, DPI_OCI_HTYPE_STMT, &prefetchSize,
565
- sizeof(prefetchSize), DPI_OCI_ATTR_PREFETCH_ROWS,
566
- "set prefetch rows", error) < 0)
567
- return DPI_FAILURE;
568
- }
569
-
570
- // clear batch errors from any previous execution
571
- dpiStmt__clearBatchErrors(stmt);
572
-
573
- // adjust mode for scrollable cursors
574
- if (stmt->scrollable)
575
- mode |= DPI_OCI_STMT_SCROLLABLE_READONLY;
576
-
577
- // perform execution
578
- // re-execute statement for ORA-01007: variable not in select list
579
- // drop statement from cache for all but ORA-00001: unique key violated
580
- if (dpiOci__stmtExecute(stmt, numIters, mode, error) < 0) {
581
- dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT,
582
- &error->buffer->offset, 0, DPI_OCI_ATTR_PARSE_ERROR_OFFSET,
583
- "set parse offset", error);
584
- if (reExecute && error->buffer->code == 1007)
585
- return dpiStmt__reExecute(stmt, numIters, mode, error);
586
- else if (error->buffer->code != 1)
587
- stmt->deleteFromCache = 1;
588
- return DPI_FAILURE;
589
- }
590
-
591
- // for all bound variables, transfer data from Oracle buffer structures to
592
- // dpiData structures; OCI doesn't provide a way of knowing if a variable
593
- // is an out variable so do this for all of them when this is a possibility
594
- if (stmt->isReturning || stmt->statementType == DPI_STMT_TYPE_BEGIN ||
595
- stmt->statementType == DPI_STMT_TYPE_DECLARE ||
596
- stmt->statementType == DPI_STMT_TYPE_CALL) {
597
- for (i = 0; i < stmt->numBindVars; i++) {
598
- var = stmt->bindVars[i].var;
599
- for (j = 0; j < var->buffer.maxArraySize; j++) {
600
- if (dpiVar__getValue(var, &var->buffer, j, 0, error) < 0)
601
- return DPI_FAILURE;
602
- }
603
- var->error = NULL;
604
- }
605
- }
606
-
607
- // create query variables (if applicable) and reset row count to zero
608
- if (stmt->statementType == DPI_STMT_TYPE_SELECT) {
609
- stmt->rowCount = 0;
610
- if (!(mode & DPI_MODE_EXEC_PARSE_ONLY) &&
611
- dpiStmt__createQueryVars(stmt, error) < 0)
612
- return DPI_FAILURE;
613
- }
614
-
615
- return DPI_SUCCESS;
616
- }
617
-
618
-
619
- //-----------------------------------------------------------------------------
620
- // dpiStmt__fetch() [INTERNAL]
621
- // Performs the actual fetch from Oracle.
622
- //-----------------------------------------------------------------------------
623
- static int dpiStmt__fetch(dpiStmt *stmt, dpiError *error)
624
- {
625
- // perform any pre-fetch activities required
626
- if (dpiStmt__beforeFetch(stmt, error) < 0)
627
- return DPI_FAILURE;
628
-
629
- // perform fetch
630
- if (dpiOci__stmtFetch2(stmt, stmt->fetchArraySize, DPI_MODE_FETCH_NEXT, 0,
631
- error) < 0)
632
- return DPI_FAILURE;
633
-
634
- // determine the number of rows fetched into buffers
635
- if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT,
636
- &stmt->bufferRowCount, 0, DPI_OCI_ATTR_ROWS_FETCHED,
637
- "get rows fetched", error) < 0)
638
- return DPI_FAILURE;
639
-
640
- // set buffer row info
641
- stmt->bufferMinRow = stmt->rowCount + 1;
642
- stmt->bufferRowIndex = 0;
643
-
644
- // perform post-fetch activities required
645
- if (dpiStmt__postFetch(stmt, error) < 0)
646
- return DPI_FAILURE;
647
-
648
- return DPI_SUCCESS;
649
- }
650
-
651
-
652
- //-----------------------------------------------------------------------------
653
- // dpiStmt__free() [INTERNAL]
654
- // Free the memory associated with the statement.
655
- //-----------------------------------------------------------------------------
656
- void dpiStmt__free(dpiStmt *stmt, dpiError *error)
657
- {
658
- dpiStmt__close(stmt, NULL, 0, 0, error);
659
- if (stmt->conn) {
660
- dpiGen__setRefCount(stmt->conn, error, -1);
661
- stmt->conn = NULL;
662
- }
663
- dpiUtils__freeMemory(stmt);
664
- }
665
-
666
-
667
- //-----------------------------------------------------------------------------
668
- // dpiStmt__getBatchErrors() [INTERNAL]
669
- // Get batch errors after statement executed with batch errors enabled.
670
- //-----------------------------------------------------------------------------
671
- static int dpiStmt__getBatchErrors(dpiStmt *stmt, dpiError *error)
672
- {
673
- void *batchErrorHandle, *localErrorHandle;
674
- dpiError localError;
675
- int overallStatus;
676
- int32_t rowOffset;
677
- uint32_t i;
678
-
679
- // determine the number of batch errors that were found
680
- if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT,
681
- &stmt->numBatchErrors, 0, DPI_OCI_ATTR_NUM_DML_ERRORS,
682
- "get batch error count", error) < 0)
683
- return DPI_FAILURE;
684
-
685
- // allocate memory for the batch errors
686
- if (dpiUtils__allocateMemory(stmt->numBatchErrors, sizeof(dpiErrorBuffer),
687
- 1, "allocate errors", (void**) &stmt->batchErrors, error) < 0) {
688
- stmt->numBatchErrors = 0;
689
- return DPI_FAILURE;
690
- }
691
-
692
- // allocate error handle used for OCIParamGet()
693
- if (dpiOci__handleAlloc(stmt->env->handle, &localErrorHandle,
694
- DPI_OCI_HTYPE_ERROR, "allocate parameter error handle",
695
- error) < 0) {
696
- dpiStmt__clearBatchErrors(stmt);
697
- return DPI_FAILURE;
698
- }
699
-
700
- // allocate error handle used for batch errors
701
- if (dpiOci__handleAlloc(stmt->env->handle, &batchErrorHandle,
702
- DPI_OCI_HTYPE_ERROR, "allocate batch error handle", error) < 0) {
703
- dpiStmt__clearBatchErrors(stmt);
704
- dpiOci__handleFree(localErrorHandle, DPI_OCI_HTYPE_ERROR);
705
- return DPI_FAILURE;
706
- }
707
-
708
- // process each error
709
- overallStatus = DPI_SUCCESS;
710
- localError.buffer = error->buffer;
711
- localError.env = error->env;
712
- for (i = 0; i < stmt->numBatchErrors; i++) {
713
-
714
- // get error handle for iteration
715
- if (dpiOci__paramGet(error->handle, DPI_OCI_HTYPE_ERROR,
716
- &batchErrorHandle, i, "get batch error", error) < 0) {
717
- overallStatus = dpiError__set(error, "get batch error",
718
- DPI_ERR_INVALID_INDEX, i);
719
- break;
720
- }
721
-
722
- // determine row offset
723
- localError.handle = localErrorHandle;
724
- if (dpiOci__attrGet(batchErrorHandle, DPI_OCI_HTYPE_ERROR, &rowOffset,
725
- 0, DPI_OCI_ATTR_DML_ROW_OFFSET, "get row offset",
726
- &localError) < 0) {
727
- overallStatus = dpiError__set(error, "get row offset",
728
- DPI_ERR_CANNOT_GET_ROW_OFFSET);
729
- break;
730
- }
731
-
732
- // get error message
733
- localError.buffer = &stmt->batchErrors[i];
734
- localError.handle = batchErrorHandle;
735
- dpiError__check(&localError, DPI_OCI_ERROR, stmt->conn,
736
- "get batch error");
737
- if (error->buffer->errorNum) {
738
- overallStatus = DPI_FAILURE;
739
- break;
740
- }
741
- localError.buffer->fnName = error->buffer->fnName;
742
- localError.buffer->offset = (uint16_t) rowOffset;
743
-
744
- }
745
-
746
- // cleanup
747
- dpiOci__handleFree(localErrorHandle, DPI_OCI_HTYPE_ERROR);
748
- dpiOci__handleFree(batchErrorHandle, DPI_OCI_HTYPE_ERROR);
749
- if (overallStatus < 0)
750
- dpiStmt__clearBatchErrors(stmt);
751
- return overallStatus;
752
- }
753
-
754
-
755
- //-----------------------------------------------------------------------------
756
- // dpiStmt__getQueryInfo() [INTERNAL]
757
- // Get query information for the position in question.
758
- //-----------------------------------------------------------------------------
759
- static int dpiStmt__getQueryInfo(dpiStmt *stmt, uint32_t pos,
760
- dpiQueryInfo *info, dpiError *error)
761
- {
762
- void *param;
763
- int status;
764
-
765
- // acquire parameter descriptor
766
- if (dpiOci__paramGet(stmt->handle, DPI_OCI_HTYPE_STMT, &param, pos,
767
- "get parameter", error) < 0)
768
- return DPI_FAILURE;
769
-
770
- // acquire information from the parameter descriptor
771
- status = dpiStmt__getQueryInfoFromParam(stmt, param, info, error);
772
- dpiOci__descriptorFree(param, DPI_OCI_DTYPE_PARAM);
773
- return status;
774
- }
775
-
776
-
777
- //-----------------------------------------------------------------------------
778
- // dpiStmt__getQueryInfoFromParam() [INTERNAL]
779
- // Get query information from the parameter.
780
- //-----------------------------------------------------------------------------
781
- static int dpiStmt__getQueryInfoFromParam(dpiStmt *stmt, void *param,
782
- dpiQueryInfo *info, dpiError *error)
783
- {
784
- uint8_t ociNullOk;
785
-
786
- // aquire name of item
787
- if (dpiOci__attrGet(param, DPI_OCI_HTYPE_DESCRIBE, (void*) &info->name,
788
- &info->nameLength, DPI_OCI_ATTR_NAME, "get name", error) < 0)
789
- return DPI_FAILURE;
790
-
791
- // acquire type information
792
- if (dpiOracleType__populateTypeInfo(stmt->conn, param,
793
- DPI_OCI_HTYPE_DESCRIBE, &info->typeInfo, error) < 0)
794
- return DPI_FAILURE;
795
-
796
- // acquire if column is permitted to be null
797
- if (dpiOci__attrGet(param, DPI_OCI_HTYPE_DESCRIBE, (void*) &ociNullOk, 0,
798
- DPI_OCI_ATTR_IS_NULL, "get null ok", error) < 0)
799
- return DPI_FAILURE;
800
- info->nullOk = ociNullOk;
801
-
802
- return DPI_SUCCESS;
803
- }
804
-
805
-
806
- //-----------------------------------------------------------------------------
807
- // dpiStmt__init() [INTERNAL]
808
- // Initialize the statement for use. This is needed when preparing a
809
- // statement for use and when returning a REF cursor.
810
- //-----------------------------------------------------------------------------
811
- int dpiStmt__init(dpiStmt *stmt, dpiError *error)
812
- {
813
- // get statement type
814
- if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT,
815
- (void*) &stmt->statementType, 0, DPI_OCI_ATTR_STMT_TYPE,
816
- "get statement type", error) < 0)
817
- return DPI_FAILURE;
818
-
819
- // for queries, mark statement as having rows to fetch
820
- if (stmt->statementType == DPI_STMT_TYPE_SELECT)
821
- stmt->hasRowsToFetch = 1;
822
-
823
- // otherwise, check if this is a RETURNING statement
824
- else if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT,
825
- (void*) &stmt->isReturning, 0, DPI_OCI_ATTR_STMT_IS_RETURNING,
826
- "get is returning", error) < 0)
827
- return DPI_FAILURE;
828
-
829
- return DPI_SUCCESS;
830
- }
831
-
832
-
833
- //-----------------------------------------------------------------------------
834
- // dpiStmt__postFetch() [INTERNAL]
835
- // Performs the transformations required to convert Oracle data values into
836
- // C data values.
837
- //-----------------------------------------------------------------------------
838
- static int dpiStmt__postFetch(dpiStmt *stmt, dpiError *error)
839
- {
840
- uint32_t i, j;
841
- dpiVar *var;
842
-
843
- for (i = 0; i < stmt->numQueryVars; i++) {
844
- var = stmt->queryVars[i];
845
- for (j = 0; j < stmt->bufferRowCount; j++) {
846
- if (dpiVar__getValue(var, &var->buffer, j, 1, error) < 0)
847
- return DPI_FAILURE;
848
- if (var->type->requiresPreFetch)
849
- var->requiresPreFetch = 1;
850
- }
851
- var->error = NULL;
852
- }
853
-
854
- return DPI_SUCCESS;
855
- }
856
-
857
-
858
- //-----------------------------------------------------------------------------
859
- // dpiStmt__beforeFetch() [INTERNAL]
860
- // Performs work that needs to be done prior to fetch for each variable. In
861
- // addition, variables are created if they do not already exist. A check is
862
- // also made to ensure that the variable has enough space to support a fetch
863
- // of the requested size.
864
- //-----------------------------------------------------------------------------
865
- static int dpiStmt__beforeFetch(dpiStmt *stmt, dpiError *error)
866
- {
867
- dpiQueryInfo *queryInfo;
868
- dpiData *data;
869
- dpiVar *var;
870
- uint32_t i;
871
-
872
- if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, error) < 0)
873
- return DPI_FAILURE;
874
- for (i = 0; i < stmt->numQueryVars; i++) {
875
- var = stmt->queryVars[i];
876
- if (!var) {
877
- queryInfo = &stmt->queryInfo[i];
878
- if (dpiVar__allocate(stmt->conn, queryInfo->typeInfo.oracleTypeNum,
879
- queryInfo->typeInfo.defaultNativeTypeNum,
880
- stmt->fetchArraySize,
881
- queryInfo->typeInfo.clientSizeInBytes, 1, 0,
882
- queryInfo->typeInfo.objectType, &var, &data, error) < 0)
883
- return DPI_FAILURE;
884
- if (dpiStmt__define(stmt, i + 1, var, error) < 0)
885
- return DPI_FAILURE;
886
- dpiGen__setRefCount(var, error, -1);
887
- }
888
- var->error = error;
889
- if (stmt->fetchArraySize > var->buffer.maxArraySize)
890
- return dpiError__set(error, "check array size",
891
- DPI_ERR_ARRAY_SIZE_TOO_SMALL, var->buffer.maxArraySize);
892
- if (var->requiresPreFetch && dpiVar__extendedPreFetch(var,
893
- &var->buffer, error) < 0)
894
- return DPI_FAILURE;
895
- }
896
-
897
- return DPI_SUCCESS;
898
- }
899
-
900
-
901
- //-----------------------------------------------------------------------------
902
- // dpiStmt__prepare() [INTERNAL]
903
- // Prepare a statement for execution.
904
- //-----------------------------------------------------------------------------
905
- int dpiStmt__prepare(dpiStmt *stmt, const char *sql, uint32_t sqlLength,
906
- const char *tag, uint32_t tagLength, dpiError *error)
907
- {
908
- if (sql && dpiDebugLevel & DPI_DEBUG_LEVEL_SQL)
909
- dpiDebug__print("SQL %.*s\n", sqlLength, sql);
910
- if (dpiOci__stmtPrepare2(stmt, sql, sqlLength, tag, tagLength, error) < 0)
911
- return DPI_FAILURE;
912
- if (dpiHandleList__addHandle(stmt->conn->openStmts, stmt,
913
- &stmt->openSlotNum, error) < 0) {
914
- dpiOci__stmtRelease(stmt, NULL, 0, 0, error);
915
- stmt->handle = NULL;
916
- return DPI_FAILURE;
917
- }
918
-
919
- return dpiStmt__init(stmt, error);
920
- }
921
-
922
-
923
- //-----------------------------------------------------------------------------
924
- // dpiStmt__reExecute() [INTERNAL]
925
- // Re-execute the statement after receiving the error ORA-01007: variable not
926
- // in select list. This takes place when one of the columns in a query is
927
- // dropped, but the original metadata is still being used because the query
928
- // statement was found in the statement cache.
929
- //-----------------------------------------------------------------------------
930
- static int dpiStmt__reExecute(dpiStmt *stmt, uint32_t numIters,
931
- uint32_t mode, dpiError *error)
932
- {
933
- void *origHandle, *newHandle;
934
- uint32_t sqlLength, i;
935
- dpiError localError;
936
- dpiBindVar *bindVar;
937
- dpiVar *var;
938
- int status;
939
- char *sql;
940
-
941
- // acquire the statement that was previously prepared; if this cannot be
942
- // determined, let the original error propagate
943
- localError.buffer = error->buffer;
944
- localError.env = error->env;
945
- localError.handle = error->handle;
946
- if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, (void*) &sql,
947
- &sqlLength, DPI_OCI_ATTR_STATEMENT, "get statement",
948
- &localError) < 0)
949
- return DPI_FAILURE;
950
-
951
- // prepare statement a second time before releasing the original statement;
952
- // release the original statement and delete it from the statement cache
953
- // so that it does not return with the invalid metadata; again, if this
954
- // cannot be done, let the original error propagate
955
- origHandle = stmt->handle;
956
- status = dpiOci__stmtPrepare2(stmt, sql, sqlLength, NULL, 0, &localError);
957
- newHandle = stmt->handle;
958
- stmt->handle = origHandle;
959
- stmt->deleteFromCache = 1;
960
- if (dpiOci__stmtRelease(stmt, NULL, 0, 1, &localError) < 0 || status < 0)
961
- return DPI_FAILURE;
962
- stmt->handle = newHandle;
963
- dpiStmt__clearBatchErrors(stmt);
964
- dpiStmt__clearQueryVars(stmt, error);
965
-
966
- // perform binds
967
- for (i = 0; i < stmt->numBindVars; i++) {
968
- bindVar = &stmt->bindVars[i];
969
- if (!bindVar->var)
970
- continue;
971
- var = bindVar->var;
972
- bindVar->var = NULL;
973
- if (dpiStmt__bind(stmt, var, 0, bindVar->pos, bindVar->name,
974
- bindVar->nameLength, error) < 0) {
975
- dpiGen__setRefCount(var, error, -1);
976
- return DPI_FAILURE;
977
- }
978
- }
979
-
980
- // now re-execute the statement
981
- return dpiStmt__execute(stmt, numIters, mode, 0, error);
982
- }
983
-
984
-
985
- //-----------------------------------------------------------------------------
986
- // dpiStmt_addRef() [PUBLIC]
987
- // Add a reference to the statement.
988
- //-----------------------------------------------------------------------------
989
- int dpiStmt_addRef(dpiStmt *stmt)
990
- {
991
- return dpiGen__addRef(stmt, DPI_HTYPE_STMT, __func__);
992
- }
993
-
994
-
995
- //-----------------------------------------------------------------------------
996
- // dpiStmt_bindByName() [PUBLIC]
997
- // Bind the variable by name.
998
- //-----------------------------------------------------------------------------
999
- int dpiStmt_bindByName(dpiStmt *stmt, const char *name, uint32_t nameLength,
1000
- dpiVar *var)
1001
- {
1002
- dpiError error;
1003
- int status;
1004
-
1005
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1006
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1007
- DPI_CHECK_PTR_NOT_NULL(stmt, name)
1008
- if (dpiGen__checkHandle(var, DPI_HTYPE_VAR, "bind by name", &error) < 0)
1009
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1010
- status = dpiStmt__bind(stmt, var, 1, 0, name, nameLength, &error);
1011
- return dpiGen__endPublicFn(stmt, status, &error);
1012
- }
1013
-
1014
-
1015
- //-----------------------------------------------------------------------------
1016
- // dpiStmt_bindByPos() [PUBLIC]
1017
- // Bind the variable by position.
1018
- //-----------------------------------------------------------------------------
1019
- int dpiStmt_bindByPos(dpiStmt *stmt, uint32_t pos, dpiVar *var)
1020
- {
1021
- dpiError error;
1022
- int status;
1023
-
1024
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1025
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1026
- if (dpiGen__checkHandle(var, DPI_HTYPE_VAR, "bind by pos", &error) < 0)
1027
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1028
- status = dpiStmt__bind(stmt, var, 1, pos, NULL, 0, &error);
1029
- return dpiGen__endPublicFn(stmt, status, &error);
1030
- }
1031
-
1032
-
1033
- //-----------------------------------------------------------------------------
1034
- // dpiStmt_bindValueByName() [PUBLIC]
1035
- // Create a variable and bind it by name.
1036
- //-----------------------------------------------------------------------------
1037
- int dpiStmt_bindValueByName(dpiStmt *stmt, const char *name,
1038
- uint32_t nameLength, dpiNativeTypeNum nativeTypeNum, dpiData *data)
1039
- {
1040
- dpiVar *var = NULL;
1041
- dpiError error;
1042
- int status;
1043
-
1044
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1045
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1046
- DPI_CHECK_PTR_NOT_NULL(stmt, name)
1047
- DPI_CHECK_PTR_NOT_NULL(stmt, data)
1048
- if (dpiStmt__createBindVar(stmt, nativeTypeNum, data, &var, 0, name,
1049
- nameLength, &error) < 0)
1050
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1051
- status = dpiStmt__bind(stmt, var, 1, 0, name, nameLength, &error);
1052
- return dpiGen__endPublicFn(stmt, status, &error);
1053
- }
1054
-
1055
-
1056
- //-----------------------------------------------------------------------------
1057
- // dpiStmt_bindValueByPos() [PUBLIC]
1058
- // Create a variable and bind it by position.
1059
- //-----------------------------------------------------------------------------
1060
- int dpiStmt_bindValueByPos(dpiStmt *stmt, uint32_t pos,
1061
- dpiNativeTypeNum nativeTypeNum, dpiData *data)
1062
- {
1063
- dpiVar *var = NULL;
1064
- dpiError error;
1065
- int status;
1066
-
1067
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1068
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1069
- DPI_CHECK_PTR_NOT_NULL(stmt, data)
1070
- if (dpiStmt__createBindVar(stmt, nativeTypeNum, data, &var, pos, NULL, 0,
1071
- &error) < 0)
1072
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1073
- status = dpiStmt__bind(stmt, var, 1, pos, NULL, 0, &error);
1074
- return dpiGen__endPublicFn(stmt, status, &error);
1075
- }
1076
-
1077
-
1078
- //-----------------------------------------------------------------------------
1079
- // dpiStmt_close() [PUBLIC]
1080
- // Close the statement so that it is no longer usable and all resources have
1081
- // been released.
1082
- //-----------------------------------------------------------------------------
1083
- int dpiStmt_close(dpiStmt *stmt, const char *tag, uint32_t tagLength)
1084
- {
1085
- dpiError error;
1086
- int status;
1087
-
1088
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1089
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1090
- DPI_CHECK_PTR_AND_LENGTH(stmt, tag)
1091
- status = dpiStmt__close(stmt, tag, tagLength, 1, &error);
1092
- return dpiGen__endPublicFn(stmt, status, &error);
1093
- }
1094
-
1095
-
1096
- //-----------------------------------------------------------------------------
1097
- // dpiStmt_define() [PUBLIC]
1098
- // Define the variable that will accept output from the cursor in the
1099
- // specified column.
1100
- //-----------------------------------------------------------------------------
1101
- int dpiStmt_define(dpiStmt *stmt, uint32_t pos, dpiVar *var)
1102
- {
1103
- dpiError error;
1104
- int status;
1105
-
1106
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1107
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1108
- if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, &error) < 0)
1109
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1110
- if (pos == 0 || pos > stmt->numQueryVars) {
1111
- dpiError__set(&error, "check query position",
1112
- DPI_ERR_QUERY_POSITION_INVALID, pos);
1113
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1114
- }
1115
- if (dpiGen__checkHandle(var, DPI_HTYPE_VAR, "check variable", &error) < 0)
1116
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1117
-
1118
- status = dpiStmt__define(stmt, pos, var, &error);
1119
- return dpiGen__endPublicFn(stmt, status, &error);
1120
- }
1121
-
1122
-
1123
- //-----------------------------------------------------------------------------
1124
- // dpiStmt_defineValue() [PUBLIC]
1125
- // Define the type of data to use for output from the cursor in the specified
1126
- // column. This implicitly creates a variable of the specified type and is
1127
- // intended for subsequent use by dpiStmt_getQueryValue(), which makes use of
1128
- // implicitly created variables.
1129
- //-----------------------------------------------------------------------------
1130
- int dpiStmt_defineValue(dpiStmt *stmt, uint32_t pos,
1131
- dpiOracleTypeNum oracleTypeNum, dpiNativeTypeNum nativeTypeNum,
1132
- uint32_t size, int sizeIsBytes, dpiObjectType *objType)
1133
- {
1134
- dpiError error;
1135
- dpiData *data;
1136
- dpiVar *var;
1137
-
1138
- // verify parameters
1139
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1140
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1141
- if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, &error) < 0)
1142
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1143
- if (pos == 0 || pos > stmt->numQueryVars) {
1144
- dpiError__set(&error, "check query position",
1145
- DPI_ERR_QUERY_POSITION_INVALID, pos);
1146
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1147
- }
1148
-
1149
- // create a new variable of the specified type
1150
- if (dpiVar__allocate(stmt->conn, oracleTypeNum, nativeTypeNum,
1151
- stmt->fetchArraySize, size, sizeIsBytes, 0, objType, &var, &data,
1152
- &error) < 0)
1153
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1154
- if (dpiStmt__define(stmt, pos, var, &error) < 0)
1155
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1156
- dpiGen__setRefCount(var, &error, -1);
1157
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1158
- }
1159
-
1160
-
1161
- //-----------------------------------------------------------------------------
1162
- // dpiStmt_execute() [PUBLIC]
1163
- // Execute a statement. If the statement has been executed before, however,
1164
- // and this is a query, the describe information is already available so defer
1165
- // execution until the first fetch.
1166
- //-----------------------------------------------------------------------------
1167
- int dpiStmt_execute(dpiStmt *stmt, dpiExecMode mode, uint32_t *numQueryColumns)
1168
- {
1169
- uint32_t numIters;
1170
- dpiError error;
1171
-
1172
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1173
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1174
- numIters = (stmt->statementType == DPI_STMT_TYPE_SELECT) ? 0 : 1;
1175
- if (dpiStmt__execute(stmt, numIters, mode, 1, &error) < 0)
1176
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1177
- if (numQueryColumns)
1178
- *numQueryColumns = stmt->numQueryVars;
1179
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1180
- }
1181
-
1182
-
1183
- //-----------------------------------------------------------------------------
1184
- // dpiStmt_executeMany() [PUBLIC]
1185
- // Execute a statement multiple times. Queries are not supported. The bind
1186
- // variables are checked to ensure that their maxArraySize is sufficient to
1187
- // support this.
1188
- //-----------------------------------------------------------------------------
1189
- int dpiStmt_executeMany(dpiStmt *stmt, dpiExecMode mode, uint32_t numIters)
1190
- {
1191
- dpiError error;
1192
- uint32_t i;
1193
-
1194
- // verify statement is open
1195
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1196
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1197
-
1198
- // queries are not supported
1199
- if (stmt->statementType == DPI_STMT_TYPE_SELECT) {
1200
- dpiError__set(&error, "check statement type", DPI_ERR_NOT_SUPPORTED);
1201
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1202
- }
1203
-
1204
- // batch errors and array DML row counts are only supported with DML
1205
- // statements (insert, update, delete and merge)
1206
- if ((mode & DPI_MODE_EXEC_BATCH_ERRORS ||
1207
- mode & DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS) &&
1208
- stmt->statementType != DPI_STMT_TYPE_INSERT &&
1209
- stmt->statementType != DPI_STMT_TYPE_UPDATE &&
1210
- stmt->statementType != DPI_STMT_TYPE_DELETE &&
1211
- stmt->statementType != DPI_STMT_TYPE_MERGE) {
1212
- dpiError__set(&error, "check mode", DPI_ERR_EXEC_MODE_ONLY_FOR_DML);
1213
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1214
- }
1215
-
1216
- // ensure that all bind variables have a big enough maxArraySize to
1217
- // support this operation
1218
- for (i = 0; i < stmt->numBindVars; i++) {
1219
- if (stmt->bindVars[i].var->buffer.maxArraySize < numIters) {
1220
- dpiError__set(&error, "check array size",
1221
- DPI_ERR_ARRAY_SIZE_TOO_SMALL,
1222
- stmt->bindVars[i].var->buffer.maxArraySize);
1223
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1224
- }
1225
- }
1226
-
1227
- // perform execution
1228
- dpiStmt__clearBatchErrors(stmt);
1229
- if (dpiStmt__execute(stmt, numIters, mode, 0, &error) < 0)
1230
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1231
-
1232
- // handle batch errors if mode was specified
1233
- if (mode & DPI_MODE_EXEC_BATCH_ERRORS) {
1234
- if (dpiStmt__getBatchErrors(stmt, &error) < 0)
1235
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1236
- }
1237
-
1238
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1239
- }
1240
-
1241
-
1242
- //-----------------------------------------------------------------------------
1243
- // dpiStmt_fetch() [PUBLIC]
1244
- // Fetch a row from the database.
1245
- //-----------------------------------------------------------------------------
1246
- int dpiStmt_fetch(dpiStmt *stmt, int *found, uint32_t *bufferRowIndex)
1247
- {
1248
- dpiError error;
1249
-
1250
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1251
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1252
- DPI_CHECK_PTR_NOT_NULL(stmt, found)
1253
- DPI_CHECK_PTR_NOT_NULL(stmt, bufferRowIndex)
1254
- if (stmt->bufferRowIndex >= stmt->bufferRowCount) {
1255
- if (stmt->hasRowsToFetch && dpiStmt__fetch(stmt, &error) < 0)
1256
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1257
- if (stmt->bufferRowIndex >= stmt->bufferRowCount) {
1258
- *found = 0;
1259
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1260
- }
1261
- }
1262
- *found = 1;
1263
- *bufferRowIndex = stmt->bufferRowIndex;
1264
- stmt->bufferRowIndex++;
1265
- stmt->rowCount++;
1266
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1267
- }
1268
-
1269
-
1270
- //-----------------------------------------------------------------------------
1271
- // dpiStmt_fetchRows() [PUBLIC]
1272
- // Fetch rows into buffers and return the number of rows that were so
1273
- // fetched. If there are still rows available in the buffer, no additional
1274
- // fetch will take place.
1275
- //-----------------------------------------------------------------------------
1276
- int dpiStmt_fetchRows(dpiStmt *stmt, uint32_t maxRows,
1277
- uint32_t *bufferRowIndex, uint32_t *numRowsFetched, int *moreRows)
1278
- {
1279
- dpiError error;
1280
-
1281
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1282
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1283
- DPI_CHECK_PTR_NOT_NULL(stmt, bufferRowIndex)
1284
- DPI_CHECK_PTR_NOT_NULL(stmt, numRowsFetched)
1285
- DPI_CHECK_PTR_NOT_NULL(stmt, moreRows)
1286
- if (stmt->bufferRowIndex >= stmt->bufferRowCount) {
1287
- if (stmt->hasRowsToFetch && dpiStmt__fetch(stmt, &error) < 0)
1288
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1289
- if (stmt->bufferRowIndex >= stmt->bufferRowCount) {
1290
- *moreRows = 0;
1291
- *bufferRowIndex = 0;
1292
- *numRowsFetched = 0;
1293
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1294
- }
1295
- }
1296
- *bufferRowIndex = stmt->bufferRowIndex;
1297
- *numRowsFetched = stmt->bufferRowCount - stmt->bufferRowIndex;
1298
- *moreRows = stmt->hasRowsToFetch;
1299
- if (*numRowsFetched > maxRows) {
1300
- *numRowsFetched = maxRows;
1301
- *moreRows = 1;
1302
- }
1303
- stmt->bufferRowIndex += *numRowsFetched;
1304
- stmt->rowCount += *numRowsFetched;
1305
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1306
- }
1307
-
1308
-
1309
- //-----------------------------------------------------------------------------
1310
- // dpiStmt_getBatchErrorCount() [PUBLIC]
1311
- // Return the number of batch errors that took place during the last
1312
- // execution of the statement.
1313
- //-----------------------------------------------------------------------------
1314
- int dpiStmt_getBatchErrorCount(dpiStmt *stmt, uint32_t *count)
1315
- {
1316
- dpiError error;
1317
-
1318
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1319
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1320
- DPI_CHECK_PTR_NOT_NULL(stmt, count)
1321
- *count = stmt->numBatchErrors;
1322
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1323
- }
1324
-
1325
-
1326
- //-----------------------------------------------------------------------------
1327
- // dpiStmt_getBatchErrors() [PUBLIC]
1328
- // Return the batch errors that took place during the last execution of the
1329
- // statement.
1330
- //-----------------------------------------------------------------------------
1331
- int dpiStmt_getBatchErrors(dpiStmt *stmt, uint32_t numErrors,
1332
- dpiErrorInfo *errors)
1333
- {
1334
- dpiError error, tempError;
1335
- uint32_t i;
1336
-
1337
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1338
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1339
- DPI_CHECK_PTR_NOT_NULL(stmt, errors)
1340
- if (numErrors < stmt->numBatchErrors) {
1341
- dpiError__set(&error, "check num errors", DPI_ERR_ARRAY_SIZE_TOO_SMALL,
1342
- numErrors);
1343
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1344
- }
1345
- for (i = 0; i < stmt->numBatchErrors; i++) {
1346
- tempError.buffer = &stmt->batchErrors[i];
1347
- dpiError__getInfo(&tempError, &errors[i]);
1348
- }
1349
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1350
- }
1351
-
1352
-
1353
- //-----------------------------------------------------------------------------
1354
- // dpiStmt_getBindCount() [PUBLIC]
1355
- // Return the number of bind variables referenced in the prepared SQL. In
1356
- // SQL statements this counts all bind variables but in PL/SQL statements
1357
- // this counts only uniquely named bind variables.
1358
- //-----------------------------------------------------------------------------
1359
- int dpiStmt_getBindCount(dpiStmt *stmt, uint32_t *count)
1360
- {
1361
- dpiError error;
1362
- int status;
1363
-
1364
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1365
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1366
- DPI_CHECK_PTR_NOT_NULL(stmt, count)
1367
- status = dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, (void*) count,
1368
- 0, DPI_OCI_ATTR_BIND_COUNT, "get bind count", &error);
1369
- return dpiGen__endPublicFn(stmt, status, &error);
1370
- }
1371
-
1372
-
1373
- //-----------------------------------------------------------------------------
1374
- // dpiStmt_getBindNames() [PUBLIC]
1375
- // Return the unique names of the bind variables referenced in the prepared
1376
- // SQL.
1377
- //-----------------------------------------------------------------------------
1378
- int dpiStmt_getBindNames(dpiStmt *stmt, uint32_t *numBindNames,
1379
- const char **bindNames, uint32_t *bindNameLengths)
1380
- {
1381
- uint8_t bindNameLengthsBuffer[8], indNameLengthsBuffer[8], isDuplicate[8];
1382
- uint32_t startLoc, i, numThisPass, numActualBindNames;
1383
- char *bindNamesBuffer[8], *indNamesBuffer[8];
1384
- void *bindHandles[8];
1385
- int32_t numFound;
1386
- dpiError error;
1387
-
1388
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1389
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1390
- DPI_CHECK_PTR_NOT_NULL(stmt, numBindNames)
1391
- DPI_CHECK_PTR_NOT_NULL(stmt, bindNames)
1392
- DPI_CHECK_PTR_NOT_NULL(stmt, bindNameLengths)
1393
- startLoc = 1;
1394
- numActualBindNames = 0;
1395
- while (1) {
1396
- if (dpiOci__stmtGetBindInfo(stmt, 8, startLoc, &numFound,
1397
- bindNamesBuffer, bindNameLengthsBuffer, indNamesBuffer,
1398
- indNameLengthsBuffer, isDuplicate, bindHandles, &error) < 0)
1399
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1400
- if (numFound == 0)
1401
- break;
1402
- numThisPass = abs(numFound) - startLoc + 1;
1403
- if (numThisPass > 8)
1404
- numThisPass = 8;
1405
- for (i = 0; i < numThisPass; i++) {
1406
- startLoc++;
1407
- if (isDuplicate[i])
1408
- continue;
1409
- if (numActualBindNames == *numBindNames) {
1410
- dpiError__set(&error, "check num bind names",
1411
- DPI_ERR_ARRAY_SIZE_TOO_SMALL, *numBindNames);
1412
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1413
- }
1414
- bindNames[numActualBindNames] = bindNamesBuffer[i];
1415
- bindNameLengths[numActualBindNames] = bindNameLengthsBuffer[i];
1416
- numActualBindNames++;
1417
- }
1418
- if (numFound > 0)
1419
- break;
1420
- }
1421
- *numBindNames = numActualBindNames;
1422
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1423
- }
1424
-
1425
-
1426
- //-----------------------------------------------------------------------------
1427
- // dpiStmt_getFetchArraySize() [PUBLIC]
1428
- // Get the array size used for fetches.
1429
- //-----------------------------------------------------------------------------
1430
- int dpiStmt_getFetchArraySize(dpiStmt *stmt, uint32_t *arraySize)
1431
- {
1432
- dpiError error;
1433
-
1434
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1435
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1436
- DPI_CHECK_PTR_NOT_NULL(stmt, arraySize)
1437
- *arraySize = stmt->fetchArraySize;
1438
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1439
- }
1440
-
1441
-
1442
- //-----------------------------------------------------------------------------
1443
- // dpiStmt_getImplicitResult() [PUBLIC]
1444
- // Return the next implicit result from the previously executed statement. If
1445
- // no more implicit results exist, NULL is returned.
1446
- //-----------------------------------------------------------------------------
1447
- int dpiStmt_getImplicitResult(dpiStmt *stmt, dpiStmt **implicitResult)
1448
- {
1449
- dpiStmt *tempStmt;
1450
- dpiError error;
1451
- void *handle;
1452
-
1453
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1454
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1455
- DPI_CHECK_PTR_NOT_NULL(stmt, implicitResult)
1456
- if (dpiUtils__checkClientVersion(stmt->env->versionInfo, 12, 1,
1457
- &error) < 0)
1458
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1459
- if (dpiOci__stmtGetNextResult(stmt, &handle, &error) < 0)
1460
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1461
- *implicitResult = NULL;
1462
- if (handle) {
1463
- if (dpiStmt__allocate(stmt->conn, 0, &tempStmt, &error) < 0)
1464
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1465
- tempStmt->handle = handle;
1466
- if (dpiStmt__createQueryVars(tempStmt, &error) < 0) {
1467
- dpiStmt__free(tempStmt, &error);
1468
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1469
- }
1470
- *implicitResult = tempStmt;
1471
- }
1472
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1473
- }
1474
-
1475
-
1476
- //-----------------------------------------------------------------------------
1477
- // dpiStmt_getInfo() [PUBLIC]
1478
- // Return information about the statement in the provided structure.
1479
- //-----------------------------------------------------------------------------
1480
- int dpiStmt_getInfo(dpiStmt *stmt, dpiStmtInfo *info)
1481
- {
1482
- dpiError error;
1483
-
1484
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1485
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1486
- DPI_CHECK_PTR_NOT_NULL(stmt, info)
1487
- info->isQuery = (stmt->statementType == DPI_STMT_TYPE_SELECT);
1488
- info->isPLSQL = (stmt->statementType == DPI_STMT_TYPE_BEGIN ||
1489
- stmt->statementType == DPI_STMT_TYPE_DECLARE ||
1490
- stmt->statementType == DPI_STMT_TYPE_CALL);
1491
- info->isDDL = (stmt->statementType == DPI_STMT_TYPE_CREATE ||
1492
- stmt->statementType == DPI_STMT_TYPE_DROP ||
1493
- stmt->statementType == DPI_STMT_TYPE_ALTER);
1494
- info->isDML = (stmt->statementType == DPI_STMT_TYPE_INSERT ||
1495
- stmt->statementType == DPI_STMT_TYPE_UPDATE ||
1496
- stmt->statementType == DPI_STMT_TYPE_DELETE ||
1497
- stmt->statementType == DPI_STMT_TYPE_MERGE);
1498
- info->statementType = stmt->statementType;
1499
- info->isReturning = stmt->isReturning;
1500
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1501
- }
1502
-
1503
-
1504
- //-----------------------------------------------------------------------------
1505
- // dpiStmt_getNumQueryColumns() [PUBLIC]
1506
- // Returns the number of query columns associated with a statement. If the
1507
- // statement does not refer to a query, 0 is returned.
1508
- //-----------------------------------------------------------------------------
1509
- int dpiStmt_getNumQueryColumns(dpiStmt *stmt, uint32_t *numQueryColumns)
1510
- {
1511
- dpiError error;
1512
-
1513
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1514
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1515
- DPI_CHECK_PTR_NOT_NULL(stmt, numQueryColumns)
1516
- if (stmt->statementType == DPI_STMT_TYPE_SELECT &&
1517
- stmt->numQueryVars == 0 &&
1518
- dpiStmt__createQueryVars(stmt, &error) < 0)
1519
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1520
- *numQueryColumns = stmt->numQueryVars;
1521
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1522
- }
1523
-
1524
-
1525
- //-----------------------------------------------------------------------------
1526
- // dpiStmt_getQueryInfo() [PUBLIC]
1527
- // Get query information for the position in question.
1528
- //-----------------------------------------------------------------------------
1529
- int dpiStmt_getQueryInfo(dpiStmt *stmt, uint32_t pos, dpiQueryInfo *info)
1530
- {
1531
- dpiError error;
1532
-
1533
- // validate parameters
1534
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1535
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1536
- DPI_CHECK_PTR_NOT_NULL(stmt, info)
1537
- if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, &error) < 0)
1538
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1539
- if (pos == 0 || pos > stmt->numQueryVars) {
1540
- dpiError__set(&error, "check query position",
1541
- DPI_ERR_QUERY_POSITION_INVALID, pos);
1542
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1543
- }
1544
-
1545
- // copy query information from internal cache
1546
- memcpy(info, &stmt->queryInfo[pos - 1], sizeof(dpiQueryInfo));
1547
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1548
- }
1549
-
1550
-
1551
- //-----------------------------------------------------------------------------
1552
- // dpiStmt_getQueryValue() [PUBLIC]
1553
- // Get value from query at specified position.
1554
- //-----------------------------------------------------------------------------
1555
- int dpiStmt_getQueryValue(dpiStmt *stmt, uint32_t pos,
1556
- dpiNativeTypeNum *nativeTypeNum, dpiData **data)
1557
- {
1558
- dpiError error;
1559
- dpiVar *var;
1560
-
1561
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1562
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1563
- DPI_CHECK_PTR_NOT_NULL(stmt, nativeTypeNum)
1564
- DPI_CHECK_PTR_NOT_NULL(stmt, data)
1565
- if (!stmt->queryVars) {
1566
- dpiError__set(&error, "check query vars", DPI_ERR_QUERY_NOT_EXECUTED);
1567
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1568
- }
1569
- if (pos == 0 || pos > stmt->numQueryVars) {
1570
- dpiError__set(&error, "check query position",
1571
- DPI_ERR_QUERY_POSITION_INVALID, pos);
1572
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1573
- }
1574
- var = stmt->queryVars[pos - 1];
1575
- if (!var || stmt->bufferRowIndex == 0 ||
1576
- stmt->bufferRowIndex > stmt->bufferRowCount) {
1577
- dpiError__set(&error, "check fetched row", DPI_ERR_NO_ROW_FETCHED);
1578
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1579
- }
1580
- *nativeTypeNum = var->nativeTypeNum;
1581
- *data = &var->buffer.externalData[stmt->bufferRowIndex - 1];
1582
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1583
- }
1584
-
1585
-
1586
- //-----------------------------------------------------------------------------
1587
- // dpiStmt_getRowCount() [PUBLIC]
1588
- // Return the number of rows affected by the last DML executed (for insert,
1589
- // update, delete and merge) or the number of rows fetched (for queries). In
1590
- // all other cases, 0 is returned.
1591
- //-----------------------------------------------------------------------------
1592
- int dpiStmt_getRowCount(dpiStmt *stmt, uint64_t *count)
1593
- {
1594
- uint32_t rowCount32;
1595
- dpiError error;
1596
-
1597
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1598
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1599
- DPI_CHECK_PTR_NOT_NULL(stmt, count)
1600
- if (stmt->statementType == DPI_STMT_TYPE_SELECT)
1601
- *count = stmt->rowCount;
1602
- else if (stmt->statementType != DPI_STMT_TYPE_INSERT &&
1603
- stmt->statementType != DPI_STMT_TYPE_UPDATE &&
1604
- stmt->statementType != DPI_STMT_TYPE_DELETE &&
1605
- stmt->statementType != DPI_STMT_TYPE_MERGE) {
1606
- *count = 0;
1607
- } else if (stmt->env->versionInfo->versionNum < 12) {
1608
- if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, &rowCount32, 0,
1609
- DPI_OCI_ATTR_ROW_COUNT, "get row count", &error) < 0)
1610
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1611
- *count = rowCount32;
1612
- } else {
1613
- if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, count, 0,
1614
- DPI_OCI_ATTR_UB8_ROW_COUNT, "get row count", &error) < 0)
1615
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1616
- }
1617
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1618
- }
1619
-
1620
-
1621
- //-----------------------------------------------------------------------------
1622
- // dpiStmt_getRowCounts() [PUBLIC]
1623
- // Return the number of rows affected by each of the iterations executed
1624
- // using dpiStmt_executeMany().
1625
- //-----------------------------------------------------------------------------
1626
- int dpiStmt_getRowCounts(dpiStmt *stmt, uint32_t *numRowCounts,
1627
- uint64_t **rowCounts)
1628
- {
1629
- dpiError error;
1630
- int status;
1631
-
1632
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1633
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1634
- DPI_CHECK_PTR_NOT_NULL(stmt, numRowCounts)
1635
- DPI_CHECK_PTR_NOT_NULL(stmt, rowCounts)
1636
- if (dpiUtils__checkClientVersion(stmt->env->versionInfo, 12, 1,
1637
- &error) < 0)
1638
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1639
- status = dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, rowCounts,
1640
- numRowCounts, DPI_OCI_ATTR_DML_ROW_COUNT_ARRAY, "get row counts",
1641
- &error);
1642
- return dpiGen__endPublicFn(stmt, status, &error);
1643
- }
1644
-
1645
-
1646
- //-----------------------------------------------------------------------------
1647
- // dpiStmt_getSubscrQueryId() [PUBLIC]
1648
- // Return the query id for a query registered using this statement.
1649
- //-----------------------------------------------------------------------------
1650
- int dpiStmt_getSubscrQueryId(dpiStmt *stmt, uint64_t *queryId)
1651
- {
1652
- dpiError error;
1653
- int status;
1654
-
1655
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1656
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1657
- DPI_CHECK_PTR_NOT_NULL(stmt, queryId)
1658
- status = dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, queryId, 0,
1659
- DPI_OCI_ATTR_CQ_QUERYID, "get query id", &error);
1660
- return dpiGen__endPublicFn(stmt, status, &error);
1661
- }
1662
-
1663
-
1664
- //-----------------------------------------------------------------------------
1665
- // dpiStmt_release() [PUBLIC]
1666
- // Release a reference to the statement.
1667
- //-----------------------------------------------------------------------------
1668
- int dpiStmt_release(dpiStmt *stmt)
1669
- {
1670
- return dpiGen__release(stmt, DPI_HTYPE_STMT, __func__);
1671
- }
1672
-
1673
-
1674
- //-----------------------------------------------------------------------------
1675
- // dpiStmt_scroll() [PUBLIC]
1676
- // Scroll to the specified location in the cursor.
1677
- //-----------------------------------------------------------------------------
1678
- int dpiStmt_scroll(dpiStmt *stmt, dpiFetchMode mode, int32_t offset,
1679
- int32_t rowCountOffset)
1680
- {
1681
- uint32_t numRows, currentPosition;
1682
- uint64_t desiredRow = 0;
1683
- dpiError error;
1684
-
1685
- // make sure the cursor is open
1686
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1687
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1688
-
1689
- // validate mode; determine desired row to fetch
1690
- switch (mode) {
1691
- case DPI_MODE_FETCH_NEXT:
1692
- desiredRow = stmt->rowCount + rowCountOffset + 1;
1693
- break;
1694
- case DPI_MODE_FETCH_PRIOR:
1695
- desiredRow = stmt->rowCount + rowCountOffset - 1;
1696
- break;
1697
- case DPI_MODE_FETCH_FIRST:
1698
- desiredRow = 1;
1699
- break;
1700
- case DPI_MODE_FETCH_LAST:
1701
- break;
1702
- case DPI_MODE_FETCH_ABSOLUTE:
1703
- desiredRow = (uint64_t) offset;
1704
- break;
1705
- case DPI_MODE_FETCH_RELATIVE:
1706
- desiredRow = stmt->rowCount + rowCountOffset + offset;
1707
- offset = (int32_t) (desiredRow -
1708
- (stmt->bufferMinRow + stmt->bufferRowCount - 1));
1709
- break;
1710
- default:
1711
- dpiError__set(&error, "scroll mode", DPI_ERR_NOT_SUPPORTED);
1712
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1713
- }
1714
-
1715
- // determine if a fetch is actually required; "last" is always fetched
1716
- if (mode != DPI_MODE_FETCH_LAST && desiredRow >= stmt->bufferMinRow &&
1717
- desiredRow < stmt->bufferMinRow + stmt->bufferRowCount) {
1718
- stmt->bufferRowIndex = (uint32_t) (desiredRow - stmt->bufferMinRow);
1719
- stmt->rowCount = desiredRow - 1;
1720
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1721
- }
1722
-
1723
- // perform any pre-fetch activities required
1724
- if (dpiStmt__beforeFetch(stmt, &error) < 0)
1725
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1726
-
1727
- // perform fetch; when fetching the last row, only fetch a single row
1728
- numRows = (mode == DPI_MODE_FETCH_LAST) ? 1 : stmt->fetchArraySize;
1729
- if (dpiOci__stmtFetch2(stmt, numRows, mode, offset, &error) < 0)
1730
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1731
-
1732
- // determine the number of rows actually fetched
1733
- if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT,
1734
- &stmt->bufferRowCount, 0, DPI_OCI_ATTR_ROWS_FETCHED,
1735
- "get rows fetched", &error) < 0)
1736
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1737
-
1738
- // check that we haven't gone outside of the result set
1739
- if (stmt->bufferRowCount == 0) {
1740
- if (mode != DPI_MODE_FETCH_FIRST && mode != DPI_MODE_FETCH_LAST) {
1741
- dpiError__set(&error, "check result set bounds",
1742
- DPI_ERR_SCROLL_OUT_OF_RS);
1743
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1744
- }
1745
- stmt->hasRowsToFetch = 0;
1746
- stmt->rowCount = 0;
1747
- stmt->bufferRowIndex = 0;
1748
- stmt->bufferMinRow = 0;
1749
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1750
- }
1751
-
1752
- // determine the current position of the cursor
1753
- if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, &currentPosition, 0,
1754
- DPI_OCI_ATTR_CURRENT_POSITION, "get current pos", &error) < 0)
1755
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1756
-
1757
- // reset buffer row index and row count
1758
- stmt->rowCount = currentPosition - stmt->bufferRowCount;
1759
- stmt->bufferMinRow = stmt->rowCount + 1;
1760
- stmt->bufferRowIndex = 0;
1761
-
1762
- // perform post-fetch activities required
1763
- if (dpiStmt__postFetch(stmt, &error) < 0)
1764
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1765
-
1766
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1767
- }
1768
-
1769
-
1770
- //-----------------------------------------------------------------------------
1771
- // dpiStmt_setFetchArraySize() [PUBLIC]
1772
- // Set the array size used for fetches. Using a value of zero will select the
1773
- // default value. A check is made to ensure that all defined variables have
1774
- // sufficient space to support the array size.
1775
- //-----------------------------------------------------------------------------
1776
- int dpiStmt_setFetchArraySize(dpiStmt *stmt, uint32_t arraySize)
1777
- {
1778
- dpiError error;
1779
- dpiVar *var;
1780
- uint32_t i;
1781
-
1782
- if (dpiStmt__check(stmt, __func__, &error) < 0)
1783
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1784
- if (arraySize == 0)
1785
- arraySize = DPI_DEFAULT_FETCH_ARRAY_SIZE;
1786
- for (i = 0; i < stmt->numQueryVars; i++) {
1787
- var = stmt->queryVars[i];
1788
- if (var && var->buffer.maxArraySize < arraySize) {
1789
- dpiError__set(&error, "check array size",
1790
- DPI_ERR_ARRAY_SIZE_TOO_BIG, arraySize);
1791
- return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1792
- }
1793
- }
1794
- stmt->fetchArraySize = arraySize;
1795
- return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error);
1796
- }
1797
-