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.
- package/CHANGELOG.md +135 -8
- package/README.md +6 -4
- package/build/Release/oracledb-abi48-darwin-x64.node +0 -0
- package/build/Release/oracledb-abi48-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi48-linux-x64.node +0 -0
- package/build/Release/oracledb-abi48-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi48-win32-x64.node +0 -0
- package/build/Release/oracledb-abi48-win32-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi57-darwin-x64.node +0 -0
- package/build/Release/oracledb-abi57-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi57-linux-x64.node +0 -0
- package/build/Release/oracledb-abi57-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi57-win32-x64.node +0 -0
- package/build/Release/oracledb-abi57-win32-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi64-darwin-x64.node +0 -0
- package/build/Release/oracledb-abi64-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi64-linux-x64.node +0 -0
- package/build/Release/oracledb-abi64-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi64-win32-x64.node +0 -0
- package/build/Release/oracledb-abi64-win32-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi67-darwin-x64.node +0 -0
- package/build/Release/oracledb-abi67-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi67-linux-x64.node +0 -0
- package/build/Release/oracledb-abi67-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-abi67-win32-x64.node +0 -0
- package/build/Release/oracledb-abi67-win32-x64.node-buildinfo.txt +1 -0
- package/lib/connection.js +18 -4
- package/lib/oracledb.js +44 -92
- package/lib/pool.js +36 -2
- package/lib/sodaCollection.js +1 -1
- package/lib/sodaDatabase.js +1 -1
- package/lib/util.js +82 -5
- package/package/README.md +32 -101
- package/package/install.js +139 -0
- package/package/prunebinaries.js +51 -0
- package/package.json +4 -11
- package/binding.gyp +0 -162
- package/lib/rel.txt +0 -1
- package/odpi/.npmignore +0 -4
- package/odpi/LICENSE.md +0 -218
- package/odpi/README.md +0 -61
- package/odpi/embed/README.md +0 -4
- package/odpi/embed/dpi.c +0 -50
- package/odpi/include/dpi.h +0 -1748
- package/odpi/src/dpiConn.c +0 -2089
- package/odpi/src/dpiContext.c +0 -296
- package/odpi/src/dpiData.c +0 -797
- package/odpi/src/dpiDebug.c +0 -184
- package/odpi/src/dpiDeqOptions.c +0 -370
- package/odpi/src/dpiEnqOptions.c +0 -174
- package/odpi/src/dpiEnv.c +0 -189
- package/odpi/src/dpiError.c +0 -204
- package/odpi/src/dpiErrorMessages.h +0 -86
- package/odpi/src/dpiGen.c +0 -303
- package/odpi/src/dpiGlobal.c +0 -292
- package/odpi/src/dpiHandleList.c +0 -117
- package/odpi/src/dpiHandlePool.c +0 -118
- package/odpi/src/dpiImpl.h +0 -1707
- package/odpi/src/dpiLob.c +0 -506
- package/odpi/src/dpiMsgProps.c +0 -386
- package/odpi/src/dpiObject.c +0 -897
- package/odpi/src/dpiObjectAttr.c +0 -115
- package/odpi/src/dpiObjectType.c +0 -326
- package/odpi/src/dpiOci.c +0 -3527
- package/odpi/src/dpiOracleType.c +0 -492
- package/odpi/src/dpiPool.c +0 -549
- package/odpi/src/dpiRowid.c +0 -136
- package/odpi/src/dpiSodaColl.c +0 -685
- package/odpi/src/dpiSodaCollCursor.c +0 -143
- package/odpi/src/dpiSodaDb.c +0 -432
- package/odpi/src/dpiSodaDoc.c +0 -230
- package/odpi/src/dpiSodaDocCursor.c +0 -143
- package/odpi/src/dpiStmt.c +0 -1797
- package/odpi/src/dpiSubscr.c +0 -674
- package/odpi/src/dpiUtils.c +0 -410
- package/odpi/src/dpiVar.c +0 -1794
- package/package/MAKEPKG.BAT +0 -156
- package/package/Makefile +0 -85
- package/package/createpackage.js +0 -186
- package/package/extractpackage.js +0 -76
- package/package/getversion.js +0 -37
- package/package/oracledbinstall.js +0 -497
- package/package/package.json +0 -54
- package/package/util.js +0 -286
- package/src/njsCommon.cpp +0 -1055
- package/src/njsCommon.h +0 -484
- package/src/njsConnection.cpp +0 -2926
- package/src/njsConnection.h +0 -227
- package/src/njsIntLob.cpp +0 -618
- package/src/njsIntLob.h +0 -179
- package/src/njsMessages.cpp +0 -122
- package/src/njsMessages.h +0 -118
- package/src/njsOracle.cpp +0 -1274
- package/src/njsOracle.h +0 -237
- package/src/njsPool.cpp +0 -482
- package/src/njsPool.h +0 -132
- package/src/njsResultSet.cpp +0 -478
- package/src/njsResultSet.h +0 -120
- package/src/njsSodaCollection.cpp +0 -507
- package/src/njsSodaCollection.h +0 -128
- package/src/njsSodaDatabase.cpp +0 -335
- package/src/njsSodaDatabase.h +0 -108
- package/src/njsSodaDocCursor.cpp +0 -203
- package/src/njsSodaDocCursor.h +0 -94
- package/src/njsSodaDocument.cpp +0 -412
- package/src/njsSodaDocument.h +0 -105
- package/src/njsSodaOperation.cpp +0 -557
- package/src/njsSodaOperation.h +0 -123
- package/src/njsSubscription.cpp +0 -388
- package/src/njsSubscription.h +0 -111
- package/src/njsUtils.cpp +0 -158
- package/src/njsUtils.h +0 -68
package/odpi/src/dpiStmt.c
DELETED
|
@@ -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, ¶m, 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, ¤tPosition, 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
|
-
|