oracledb 2.1.0 → 2.3.0

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 (52) hide show
  1. package/CHANGELOG.md +174 -54
  2. package/LICENSE.md +52 -18
  3. package/README.md +35 -68
  4. package/binding.gyp +5 -4
  5. package/lib/connection.js +164 -14
  6. package/lib/oracledb.js +160 -11
  7. package/lib/pool.js +33 -22
  8. package/lib/querystream.js +3 -2
  9. package/lib/rel.txt +1 -1
  10. package/odpi/LICENSE.md +1 -1
  11. package/odpi/README.md +25 -84
  12. package/odpi/embed/README.md +1 -1
  13. package/odpi/include/dpi.h +51 -7
  14. package/odpi/src/dpiConn.c +78 -9
  15. package/odpi/src/dpiContext.c +24 -10
  16. package/odpi/src/dpiEnv.c +5 -1
  17. package/odpi/src/dpiError.c +4 -0
  18. package/odpi/src/dpiErrorMessages.h +6 -4
  19. package/odpi/src/dpiImpl.h +125 -68
  20. package/odpi/src/dpiMsgProps.c +33 -0
  21. package/odpi/src/dpiObject.c +17 -10
  22. package/odpi/src/dpiObjectType.c +1 -1
  23. package/odpi/src/dpiOci.c +55 -40
  24. package/odpi/src/dpiOracleType.c +2 -2
  25. package/odpi/src/dpiPool.c +88 -18
  26. package/odpi/src/dpiStmt.c +57 -36
  27. package/odpi/src/dpiSubscr.c +117 -9
  28. package/odpi/src/dpiUtils.c +20 -9
  29. package/odpi/src/dpiVar.c +504 -430
  30. package/package/MAKEPKG.BAT +64 -1
  31. package/package/README.md +9 -5
  32. package/package/createpackage.js +2 -2
  33. package/package/extractpackage.js +2 -1
  34. package/package/oracledbinstall.js +19 -19
  35. package/package/package.json +4 -4
  36. package/package.json +4 -4
  37. package/src/njsCommon.cpp +94 -10
  38. package/src/njsCommon.h +73 -21
  39. package/src/njsConnection.cpp +1425 -458
  40. package/src/njsConnection.h +68 -19
  41. package/src/njsIntLob.cpp +5 -1
  42. package/src/njsIntLob.h +1 -1
  43. package/src/njsMessages.cpp +9 -2
  44. package/src/njsMessages.h +9 -2
  45. package/src/njsOracle.cpp +213 -23
  46. package/src/njsOracle.h +18 -2
  47. package/src/njsPool.cpp +32 -14
  48. package/src/njsPool.h +4 -4
  49. package/src/njsResultSet.cpp +4 -3
  50. package/src/njsResultSet.h +1 -1
  51. package/src/njsSubscription.cpp +388 -0
  52. package/src/njsSubscription.h +111 -0
package/odpi/src/dpiVar.c CHANGED
@@ -17,7 +17,8 @@
17
17
  #include "dpiImpl.h"
18
18
 
19
19
  // forward declarations of internal functions only used in this file
20
- static int dpiVar__initBuffers(dpiVar *var, dpiError *error);
20
+ static int dpiVar__initBuffer(dpiVar *var, dpiVarBuffer *buffer,
21
+ dpiError *error);
21
22
  static int dpiVar__setBytesFromDynamicBytes(dpiBytes *bytes,
22
23
  dpiDynamicBytes *dynBytes, dpiError *error);
23
24
  static int dpiVar__setBytesFromLob(dpiBytes *bytes, dpiDynamicBytes *dynBytes,
@@ -86,9 +87,9 @@ int dpiVar__allocate(dpiConn *conn, dpiOracleTypeNum oracleTypeNum,
86
87
  return DPI_FAILURE;
87
88
 
88
89
  // basic initialization
89
- tempVar->maxArraySize = maxArraySize;
90
+ tempVar->buffer.maxArraySize = maxArraySize;
90
91
  if (!isArray)
91
- tempVar->actualArraySize = maxArraySize;
92
+ tempVar->buffer.actualArraySize = maxArraySize;
92
93
  tempVar->sizeInBytes = sizeInBytes;
93
94
  if (sizeInBytes > DPI_MAX_BASIC_BUFFER_SIZE) {
94
95
  tempVar->sizeInBytes = 0;
@@ -111,123 +112,13 @@ int dpiVar__allocate(dpiConn *conn, dpiOracleTypeNum oracleTypeNum,
111
112
  }
112
113
 
113
114
  // allocate the data for the variable
114
- if (dpiVar__initBuffers(tempVar, error) < 0) {
115
+ if (dpiVar__initBuffer(tempVar, &tempVar->buffer, error) < 0) {
115
116
  dpiVar__free(tempVar, error);
116
117
  return DPI_FAILURE;
117
118
  }
118
119
 
119
120
  *var = tempVar;
120
- *data = tempVar->externalData;
121
- return DPI_SUCCESS;
122
- }
123
-
124
-
125
- //-----------------------------------------------------------------------------
126
- // dpiVar__allocateBuffers() [INTERNAL]
127
- // Allocate buffers used for passing data to/from Oracle.
128
- //-----------------------------------------------------------------------------
129
- static int dpiVar__allocateBuffers(dpiVar *var, dpiError *error)
130
- {
131
- uint32_t i, tempBufferSize = 0;
132
- unsigned long long dataLength;
133
- dpiBytes *bytes;
134
-
135
- // initialize dynamic buffers for dynamic variables
136
- if (var->isDynamic) {
137
- if (dpiUtils__allocateMemory(var->maxArraySize,
138
- sizeof(dpiDynamicBytes), 1, "allocate dynamic bytes",
139
- (void**) &var->dynamicBytes, error) < 0)
140
- return DPI_FAILURE;
141
-
142
- // for all other variables, validate length and allocate buffers
143
- } else {
144
- dataLength = (unsigned long long) var->maxArraySize *
145
- (unsigned long long) var->sizeInBytes;
146
- if (dataLength > INT_MAX)
147
- return dpiError__set(error, "check max array size",
148
- DPI_ERR_ARRAY_SIZE_TOO_BIG, var->maxArraySize);
149
- if (dpiUtils__allocateMemory(1, (size_t) dataLength, 0,
150
- "allocate buffer", (void**) &var->data.asRaw, error) < 0)
151
- return DPI_FAILURE;
152
- }
153
-
154
- // allocate the indicator for the variable
155
- // ensure all values start out as null
156
- if (!var->indicator) {
157
- if (dpiUtils__allocateMemory(var->maxArraySize, sizeof(int16_t), 0,
158
- "allocate indicator", (void**) &var->indicator, error) < 0)
159
- return DPI_FAILURE;
160
- for (i = 0; i < var->maxArraySize; i++)
161
- var->indicator[i] = DPI_OCI_IND_NULL;
162
- }
163
-
164
- // allocate the actual length buffers for all but dynamic bytes which are
165
- // handled differently; ensure actual length starts out as maximum value
166
- if (!var->isDynamic && !var->actualLength16 && !var->actualLength32) {
167
- if (var->env->versionInfo->versionNum < 12) {
168
- if (dpiUtils__allocateMemory(var->maxArraySize, sizeof(uint16_t),
169
- 0, "allocate actual length", (void**) &var->actualLength16,
170
- error) < 0)
171
- return DPI_FAILURE;
172
- for (i = 0; i < var->maxArraySize; i++)
173
- var->actualLength16[i] = (uint16_t) var->sizeInBytes;
174
- } else {
175
- if (dpiUtils__allocateMemory(var->maxArraySize, sizeof(uint32_t),
176
- 0, "allocate actual length", (void**) &var->actualLength32,
177
- error) < 0)
178
- return DPI_FAILURE;
179
- for (i = 0; i < var->maxArraySize; i++)
180
- var->actualLength32[i] = var->sizeInBytes;
181
- }
182
- }
183
-
184
- // for variable length data, also allocate the return code array
185
- if (var->type->defaultNativeTypeNum == DPI_NATIVE_TYPE_BYTES &&
186
- !var->isDynamic && !var->returnCode) {
187
- if (dpiUtils__allocateMemory(var->maxArraySize, sizeof(uint16_t), 0,
188
- "allocate return code", (void**) &var->returnCode, error) < 0)
189
- return DPI_FAILURE;
190
- }
191
-
192
- // for numbers transferred to/from Oracle as bytes, allocate an additional
193
- // set of buffers
194
- if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_NUMBER &&
195
- var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) {
196
- tempBufferSize = DPI_NUMBER_AS_TEXT_CHARS;
197
- if (var->env->charsetId == DPI_CHARSET_ID_UTF16)
198
- tempBufferSize *= 2;
199
- if (!var->tempBuffer) {
200
- if (dpiUtils__allocateMemory(var->maxArraySize, tempBufferSize, 0,
201
- "allocate temp buffer", (void**) &var->tempBuffer,
202
- error) < 0)
203
- return DPI_FAILURE;
204
- }
205
- }
206
-
207
- // allocate the external data array, if needed
208
- if (!var->externalData) {
209
- if (dpiUtils__allocateMemory(var->maxArraySize, sizeof(dpiData), 1,
210
- "allocate external data", (void**) &var->externalData,
211
- error) < 0)
212
- return DPI_FAILURE;
213
- for (i = 0; i < var->maxArraySize; i++)
214
- var->externalData[i].isNull = 1;
215
- }
216
-
217
- // for bytes transfers, set encoding and pointers for small strings
218
- if (var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) {
219
- for (i = 0; i < var->maxArraySize; i++) {
220
- bytes = &var->externalData[i].value.asBytes;
221
- if (var->type->charsetForm == DPI_SQLCS_IMPLICIT)
222
- bytes->encoding = var->env->encoding;
223
- else bytes->encoding = var->env->nencoding;
224
- if (var->tempBuffer)
225
- bytes->ptr = var->tempBuffer + i * tempBufferSize;
226
- else if (!var->isDynamic && !var->dynamicBytes)
227
- bytes->ptr = var->data.asBytes + i * var->sizeInBytes;
228
- }
229
- }
230
-
121
+ *data = tempVar->buffer.externalData;
231
122
  return DPI_SUCCESS;
232
123
  }
233
124
 
@@ -297,27 +188,33 @@ static int dpiVar__allocateDynamicBytes(dpiDynamicBytes *dynBytes,
297
188
  // the callack functions used for dynamic binding during DML returning
298
189
  // statement execution.
299
190
  //-----------------------------------------------------------------------------
300
- static void dpiVar__assignCallbackBuffer(dpiVar *var, uint32_t index,
301
- void **bufpp)
191
+ static void dpiVar__assignCallbackBuffer(dpiVar *var, dpiVarBuffer *buffer,
192
+ uint32_t index, void **bufpp)
302
193
  {
303
194
  switch (var->type->oracleTypeNum) {
304
195
  case DPI_ORACLE_TYPE_TIMESTAMP:
305
196
  case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
306
197
  case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
307
- *bufpp = var->data.asTimestamp[index];
198
+ *bufpp = buffer->data.asTimestamp[index];
308
199
  break;
309
200
  case DPI_ORACLE_TYPE_INTERVAL_DS:
310
201
  case DPI_ORACLE_TYPE_INTERVAL_YM:
311
- *bufpp = var->data.asInterval[index];
202
+ *bufpp = buffer->data.asInterval[index];
312
203
  break;
313
204
  case DPI_ORACLE_TYPE_CLOB:
314
205
  case DPI_ORACLE_TYPE_BLOB:
315
206
  case DPI_ORACLE_TYPE_NCLOB:
316
207
  case DPI_ORACLE_TYPE_BFILE:
317
- *bufpp = var->data.asLobLocator[index];
208
+ *bufpp = buffer->data.asLobLocator[index];
209
+ break;
210
+ case DPI_ORACLE_TYPE_ROWID:
211
+ *bufpp = buffer->data.asRowid[index];
212
+ break;
213
+ case DPI_ORACLE_TYPE_STMT:
214
+ *bufpp = buffer->data.asStmt[index];
318
215
  break;
319
216
  default:
320
- *bufpp = var->data.asBytes + index * var->sizeInBytes;
217
+ *bufpp = buffer->data.asBytes + index * var->sizeInBytes;
321
218
  break;
322
219
  }
323
220
  }
@@ -333,9 +230,10 @@ static int dpiVar__checkArraySize(dpiVar *var, uint32_t pos,
333
230
  if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, fnName, needErrorHandle,
334
231
  error) < 0)
335
232
  return DPI_FAILURE;
336
- if (pos >= var->maxArraySize)
233
+ if (pos >= var->buffer.maxArraySize)
337
234
  return dpiError__set(error, "check array size",
338
- DPI_ERR_INVALID_ARRAY_POSITION, pos, var->maxArraySize);
235
+ DPI_ERR_INVALID_ARRAY_POSITION, pos,
236
+ var->buffer.maxArraySize);
339
237
  return DPI_SUCCESS;
340
238
  }
341
239
 
@@ -366,13 +264,13 @@ int dpiVar__convertToLob(dpiVar *var, dpiError *error)
366
264
  // the dynamic bytes structures will not be removed
367
265
  var->sizeInBytes = var->type->sizeInBytes;
368
266
  var->isDynamic = 0;
369
- if (dpiVar__initBuffers(var, error) < 0)
267
+ if (dpiVar__initBuffer(var, &var->buffer, error) < 0)
370
268
  return DPI_FAILURE;
371
269
 
372
270
  // copy any values already set
373
- for (i = 0; i < var->maxArraySize; i++) {
374
- dynBytes = &var->dynamicBytes[i];
375
- lob = var->references[i].asLOB;
271
+ for (i = 0; i < var->buffer.maxArraySize; i++) {
272
+ dynBytes = &var->buffer.dynamicBytes[i];
273
+ lob = var->buffer.references[i].asLOB;
376
274
  if (dynBytes->numChunks == 0)
377
275
  continue;
378
276
  if (dpiLob__setFromBytes(lob, dynBytes->chunks->ptr,
@@ -392,7 +290,7 @@ int dpiVar__convertToLob(dpiVar *var, dpiError *error)
392
290
  int dpiVar__copyData(dpiVar *var, uint32_t pos, dpiData *sourceData,
393
291
  dpiError *error)
394
292
  {
395
- dpiData *targetData = &var->externalData[pos];
293
+ dpiData *targetData = &var->buffer.externalData[pos];
396
294
 
397
295
  // handle null case
398
296
  targetData->isNull = sourceData->isNull;
@@ -441,7 +339,7 @@ int32_t dpiVar__defineCallback(dpiVar *var, UNUSED void *defnp, uint32_t iter,
441
339
  dpiDynamicBytes *bytes;
442
340
 
443
341
  // allocate more chunks, if necessary
444
- bytes = &var->dynamicBytes[iter];
342
+ bytes = &var->buffer.dynamicBytes[iter];
445
343
  if (bytes->numChunks == bytes->allocatedChunks &&
446
344
  dpiVar__allocateChunks(bytes, var->error) < 0)
447
345
  return DPI_OCI_ERROR;
@@ -460,77 +358,18 @@ int32_t dpiVar__defineCallback(dpiVar *var, UNUSED void *defnp, uint32_t iter,
460
358
  chunk->length = chunk->allocatedLength;
461
359
  *bufpp = chunk->ptr;
462
360
  *alenpp = &chunk->length;
463
- *indpp = &(var->indicator[iter]);
361
+ *indpp = &(var->buffer.indicator[iter]);
464
362
  *rcodepp = NULL;
465
363
  return DPI_OCI_CONTINUE;
466
364
  }
467
365
 
468
366
 
469
- //-----------------------------------------------------------------------------
470
- // dpiVar__extendedInitialize() [INTERNAL]
471
- // Performs extended initialization specific to each variable type.
472
- //-----------------------------------------------------------------------------
473
- static int dpiVar__extendedInitialize(dpiVar *var, dpiError *error)
474
- {
475
- // create array of references, if applicable
476
- if (var->type->requiresPreFetch && !var->isDynamic) {
477
- if (dpiUtils__allocateMemory(var->maxArraySize,
478
- sizeof(dpiReferenceBuffer), 1, "allocate references",
479
- (void**) &var->references, error) < 0)
480
- return DPI_FAILURE;
481
- }
482
-
483
- // perform variable specific initialization
484
- switch (var->type->oracleTypeNum) {
485
- case DPI_ORACLE_TYPE_TIMESTAMP:
486
- return dpiOci__arrayDescriptorAlloc(var->env->handle,
487
- &var->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP,
488
- var->maxArraySize, error);
489
- case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
490
- return dpiOci__arrayDescriptorAlloc(var->env->handle,
491
- &var->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP_TZ,
492
- var->maxArraySize, error);
493
- case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
494
- return dpiOci__arrayDescriptorAlloc(var->env->handle,
495
- &var->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP_LTZ,
496
- var->maxArraySize, error);
497
- case DPI_ORACLE_TYPE_INTERVAL_DS:
498
- return dpiOci__arrayDescriptorAlloc(var->env->handle,
499
- &var->data.asInterval[0], DPI_OCI_DTYPE_INTERVAL_DS,
500
- var->maxArraySize, error);
501
- case DPI_ORACLE_TYPE_INTERVAL_YM:
502
- return dpiOci__arrayDescriptorAlloc(var->env->handle,
503
- &var->data.asInterval[0], DPI_OCI_DTYPE_INTERVAL_YM,
504
- var->maxArraySize, error);
505
- break;
506
- case DPI_ORACLE_TYPE_CLOB:
507
- case DPI_ORACLE_TYPE_BLOB:
508
- case DPI_ORACLE_TYPE_NCLOB:
509
- case DPI_ORACLE_TYPE_BFILE:
510
- case DPI_ORACLE_TYPE_STMT:
511
- case DPI_ORACLE_TYPE_ROWID:
512
- return dpiVar__extendedPreFetch(var, error);
513
- case DPI_ORACLE_TYPE_OBJECT:
514
- if (!var->objectType)
515
- return dpiError__set(error, "check object type",
516
- DPI_ERR_NO_OBJECT_TYPE);
517
- if (dpiUtils__allocateMemory(var->maxArraySize, sizeof(void*), 0,
518
- "allocate object indicator",
519
- (void**) &var->objectIndicator, error) < 0)
520
- return DPI_FAILURE;
521
- return dpiVar__extendedPreFetch(var, error);
522
- default:
523
- break;
524
- }
525
- return DPI_SUCCESS;
526
- }
527
-
528
-
529
367
  //-----------------------------------------------------------------------------
530
368
  // dpiVar__extendedPreFetch() [INTERNAL]
531
369
  // Perform any necessary actions prior to fetching data.
532
370
  //-----------------------------------------------------------------------------
533
- int dpiVar__extendedPreFetch(dpiVar *var, dpiError *error)
371
+ int dpiVar__extendedPreFetch(dpiVar *var, dpiVarBuffer *buffer,
372
+ dpiError *error)
534
373
  {
535
374
  dpiRowid *rowid;
536
375
  dpiData *data;
@@ -539,20 +378,21 @@ int dpiVar__extendedPreFetch(dpiVar *var, dpiError *error)
539
378
  uint32_t i;
540
379
 
541
380
  if (var->isDynamic) {
542
- for (i = 0; i < var->maxArraySize; i++)
543
- var->dynamicBytes[i].numChunks = 0;
381
+ for (i = 0; i < buffer->maxArraySize; i++)
382
+ buffer->dynamicBytes[i].numChunks = 0;
544
383
  return DPI_SUCCESS;
545
384
  }
546
385
 
547
386
  switch (var->type->oracleTypeNum) {
548
387
  case DPI_ORACLE_TYPE_STMT:
549
- for (i = 0; i < var->maxArraySize; i++) {
550
- data = &var->externalData[i];
551
- if (var->references[i].asStmt) {
552
- dpiGen__setRefCount(var->references[i].asStmt, error, -1);
553
- var->references[i].asStmt = NULL;
388
+ for (i = 0; i < buffer->maxArraySize; i++) {
389
+ data = &buffer->externalData[i];
390
+ if (buffer->references[i].asStmt) {
391
+ dpiGen__setRefCount(buffer->references[i].asStmt,
392
+ error, -1);
393
+ buffer->references[i].asStmt = NULL;
554
394
  }
555
- var->data.asStmt[i] = NULL;
395
+ buffer->data.asStmt[i] = NULL;
556
396
  data->value.asStmt = NULL;
557
397
  if (dpiStmt__allocate(var->conn, 0, &stmt, error) < 0)
558
398
  return DPI_FAILURE;
@@ -568,9 +408,9 @@ int dpiVar__extendedPreFetch(dpiVar *var, dpiError *error)
568
408
  dpiStmt__free(stmt, error);
569
409
  return DPI_FAILURE;
570
410
  }
571
- var->references[i].asStmt = stmt;
411
+ buffer->references[i].asStmt = stmt;
572
412
  stmt->isOwned = 1;
573
- var->data.asStmt[i] = stmt->handle;
413
+ buffer->data.asStmt[i] = stmt->handle;
574
414
  data->value.asStmt = stmt;
575
415
  }
576
416
  break;
@@ -578,50 +418,52 @@ int dpiVar__extendedPreFetch(dpiVar *var, dpiError *error)
578
418
  case DPI_ORACLE_TYPE_BLOB:
579
419
  case DPI_ORACLE_TYPE_NCLOB:
580
420
  case DPI_ORACLE_TYPE_BFILE:
581
- for (i = 0; i < var->maxArraySize; i++) {
582
- data = &var->externalData[i];
583
- if (var->references[i].asLOB) {
584
- dpiGen__setRefCount(var->references[i].asLOB, error, -1);
585
- var->references[i].asLOB = NULL;
421
+ for (i = 0; i < buffer->maxArraySize; i++) {
422
+ data = &buffer->externalData[i];
423
+ if (buffer->references[i].asLOB) {
424
+ dpiGen__setRefCount(buffer->references[i].asLOB,
425
+ error, -1);
426
+ buffer->references[i].asLOB = NULL;
586
427
  }
587
- var->data.asLobLocator[i] = NULL;
428
+ buffer->data.asLobLocator[i] = NULL;
588
429
  data->value.asLOB = NULL;
589
430
  if (dpiLob__allocate(var->conn, var->type, &lob, error) < 0)
590
431
  return DPI_FAILURE;
591
- var->references[i].asLOB = lob;
592
- var->data.asLobLocator[i] = lob->locator;
432
+ buffer->references[i].asLOB = lob;
433
+ buffer->data.asLobLocator[i] = lob->locator;
593
434
  data->value.asLOB = lob;
594
- if (var->dynamicBytes &&
435
+ if (buffer->dynamicBytes &&
595
436
  dpiOci__lobCreateTemporary(lob, error) < 0)
596
437
  return DPI_FAILURE;
597
438
  }
598
439
  break;
599
440
  case DPI_ORACLE_TYPE_ROWID:
600
- for (i = 0; i < var->maxArraySize; i++) {
601
- data = &var->externalData[i];
602
- if (var->references[i].asRowid) {
603
- dpiGen__setRefCount(var->references[i].asRowid, error, -1);
604
- var->references[i].asRowid = NULL;
441
+ for (i = 0; i < buffer->maxArraySize; i++) {
442
+ data = &buffer->externalData[i];
443
+ if (buffer->references[i].asRowid) {
444
+ dpiGen__setRefCount(buffer->references[i].asRowid,
445
+ error, -1);
446
+ buffer->references[i].asRowid = NULL;
605
447
  }
606
- var->data.asRowid[i] = NULL;
448
+ buffer->data.asRowid[i] = NULL;
607
449
  data->value.asRowid = NULL;
608
450
  if (dpiRowid__allocate(var->conn, &rowid, error) < 0)
609
451
  return DPI_FAILURE;
610
- var->references[i].asRowid = rowid;
611
- var->data.asRowid[i] = rowid->handle;
452
+ buffer->references[i].asRowid = rowid;
453
+ buffer->data.asRowid[i] = rowid->handle;
612
454
  data->value.asRowid = rowid;
613
455
  }
614
456
  break;
615
457
  case DPI_ORACLE_TYPE_OBJECT:
616
- for (i = 0; i < var->maxArraySize; i++) {
617
- data = &var->externalData[i];
618
- if (var->references[i].asObject) {
619
- dpiGen__setRefCount(var->references[i].asObject, error,
620
- -1);
621
- var->references[i].asObject = NULL;
458
+ for (i = 0; i < buffer->maxArraySize; i++) {
459
+ data = &buffer->externalData[i];
460
+ if (buffer->references[i].asObject) {
461
+ dpiGen__setRefCount(buffer->references[i].asObject,
462
+ error, -1);
463
+ buffer->references[i].asObject = NULL;
622
464
  }
623
- var->data.asObject[i] = NULL;
624
- var->objectIndicator[i] = NULL;
465
+ buffer->data.asObject[i] = NULL;
466
+ buffer->objectIndicator[i] = NULL;
625
467
  data->value.asObject = NULL;
626
468
  }
627
469
  break;
@@ -634,10 +476,11 @@ int dpiVar__extendedPreFetch(dpiVar *var, dpiError *error)
634
476
 
635
477
 
636
478
  //-----------------------------------------------------------------------------
637
- // dpiVar__finalizeBuffers() [INTERNAL]
638
- // Finalize buffers used for passing data to/from Oracle.
479
+ // dpiVar__finalizeBuffer() [INTERNAL]
480
+ // Finalize buffer used for passing data to/from Oracle.
639
481
  //-----------------------------------------------------------------------------
640
- static void dpiVar__finalizeBuffers(dpiVar *var, dpiError *error)
482
+ static void dpiVar__finalizeBuffer(dpiVar *var, dpiVarBuffer *buffer,
483
+ dpiError *error)
641
484
  {
642
485
  dpiDynamicBytes *dynBytes;
643
486
  uint32_t i, j;
@@ -645,23 +488,23 @@ static void dpiVar__finalizeBuffers(dpiVar *var, dpiError *error)
645
488
  // free any descriptors that were created
646
489
  switch (var->type->oracleTypeNum) {
647
490
  case DPI_ORACLE_TYPE_TIMESTAMP:
648
- dpiOci__arrayDescriptorFree(&var->data.asTimestamp[0],
491
+ dpiOci__arrayDescriptorFree(&buffer->data.asTimestamp[0],
649
492
  DPI_OCI_DTYPE_TIMESTAMP);
650
493
  break;
651
494
  case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
652
- dpiOci__arrayDescriptorFree(&var->data.asTimestamp[0],
495
+ dpiOci__arrayDescriptorFree(&buffer->data.asTimestamp[0],
653
496
  DPI_OCI_DTYPE_TIMESTAMP_TZ);
654
497
  break;
655
498
  case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
656
- dpiOci__arrayDescriptorFree(&var->data.asTimestamp[0],
499
+ dpiOci__arrayDescriptorFree(&buffer->data.asTimestamp[0],
657
500
  DPI_OCI_DTYPE_TIMESTAMP_LTZ);
658
501
  break;
659
502
  case DPI_ORACLE_TYPE_INTERVAL_DS:
660
- dpiOci__arrayDescriptorFree(&var->data.asInterval[0],
503
+ dpiOci__arrayDescriptorFree(&buffer->data.asInterval[0],
661
504
  DPI_OCI_DTYPE_INTERVAL_DS);
662
505
  break;
663
506
  case DPI_ORACLE_TYPE_INTERVAL_YM:
664
- dpiOci__arrayDescriptorFree(&var->data.asInterval[0],
507
+ dpiOci__arrayDescriptorFree(&buffer->data.asInterval[0],
665
508
  DPI_OCI_DTYPE_INTERVAL_YM);
666
509
  break;
667
510
  default:
@@ -669,21 +512,21 @@ static void dpiVar__finalizeBuffers(dpiVar *var, dpiError *error)
669
512
  }
670
513
 
671
514
  // release any references that were created
672
- if (var->references) {
673
- for (i = 0; i < var->maxArraySize; i++) {
674
- if (var->references[i].asHandle) {
675
- dpiGen__setRefCount(var->references[i].asHandle, error, -1);
676
- var->references[i].asHandle = NULL;
515
+ if (buffer->references) {
516
+ for (i = 0; i < buffer->maxArraySize; i++) {
517
+ if (buffer->references[i].asHandle) {
518
+ dpiGen__setRefCount(buffer->references[i].asHandle, error, -1);
519
+ buffer->references[i].asHandle = NULL;
677
520
  }
678
521
  }
679
- dpiUtils__freeMemory(var->references);
680
- var->references = NULL;
522
+ dpiUtils__freeMemory(buffer->references);
523
+ buffer->references = NULL;
681
524
  }
682
525
 
683
526
  // free any dynamic buffers
684
- if (var->dynamicBytes) {
685
- for (i = 0; i < var->maxArraySize; i++) {
686
- dynBytes = &var->dynamicBytes[i];
527
+ if (buffer->dynamicBytes) {
528
+ for (i = 0; i < buffer->maxArraySize; i++) {
529
+ dynBytes = &buffer->dynamicBytes[i];
687
530
  if (dynBytes->allocatedChunks > 0) {
688
531
  for (j = 0; j < dynBytes->allocatedChunks; j++) {
689
532
  if (dynBytes->chunks[j].ptr) {
@@ -696,42 +539,42 @@ static void dpiVar__finalizeBuffers(dpiVar *var, dpiError *error)
696
539
  dynBytes->chunks = NULL;
697
540
  }
698
541
  }
699
- dpiUtils__freeMemory(var->dynamicBytes);
700
- var->dynamicBytes = NULL;
542
+ dpiUtils__freeMemory(buffer->dynamicBytes);
543
+ buffer->dynamicBytes = NULL;
701
544
  }
702
545
 
703
546
  // free other memory allocated
704
- if (var->indicator) {
705
- dpiUtils__freeMemory(var->indicator);
706
- var->indicator = NULL;
547
+ if (buffer->indicator) {
548
+ dpiUtils__freeMemory(buffer->indicator);
549
+ buffer->indicator = NULL;
707
550
  }
708
- if (var->returnCode) {
709
- dpiUtils__freeMemory(var->returnCode);
710
- var->returnCode = NULL;
551
+ if (buffer->returnCode) {
552
+ dpiUtils__freeMemory(buffer->returnCode);
553
+ buffer->returnCode = NULL;
711
554
  }
712
- if (var->actualLength16) {
713
- dpiUtils__freeMemory(var->actualLength16);
714
- var->actualLength16 = NULL;
555
+ if (buffer->actualLength16) {
556
+ dpiUtils__freeMemory(buffer->actualLength16);
557
+ buffer->actualLength16 = NULL;
715
558
  }
716
- if (var->actualLength32) {
717
- dpiUtils__freeMemory(var->actualLength32);
718
- var->actualLength32 = NULL;
559
+ if (buffer->actualLength32) {
560
+ dpiUtils__freeMemory(buffer->actualLength32);
561
+ buffer->actualLength32 = NULL;
719
562
  }
720
- if (var->externalData) {
721
- dpiUtils__freeMemory(var->externalData);
722
- var->externalData = NULL;
563
+ if (buffer->externalData) {
564
+ dpiUtils__freeMemory(buffer->externalData);
565
+ buffer->externalData = NULL;
723
566
  }
724
- if (var->data.asRaw) {
725
- dpiUtils__freeMemory(var->data.asRaw);
726
- var->data.asRaw = NULL;
567
+ if (buffer->data.asRaw) {
568
+ dpiUtils__freeMemory(buffer->data.asRaw);
569
+ buffer->data.asRaw = NULL;
727
570
  }
728
- if (var->objectIndicator) {
729
- dpiUtils__freeMemory(var->objectIndicator);
730
- var->objectIndicator = NULL;
571
+ if (buffer->objectIndicator) {
572
+ dpiUtils__freeMemory(buffer->objectIndicator);
573
+ buffer->objectIndicator = NULL;
731
574
  }
732
- if (var->tempBuffer) {
733
- dpiUtils__freeMemory(var->tempBuffer);
734
- var->tempBuffer = NULL;
575
+ if (buffer->tempBuffer) {
576
+ dpiUtils__freeMemory(buffer->tempBuffer);
577
+ buffer->tempBuffer = NULL;
735
578
  }
736
579
  }
737
580
 
@@ -742,7 +585,15 @@ static void dpiVar__finalizeBuffers(dpiVar *var, dpiError *error)
742
585
  //-----------------------------------------------------------------------------
743
586
  void dpiVar__free(dpiVar *var, dpiError *error)
744
587
  {
745
- dpiVar__finalizeBuffers(var, error);
588
+ uint32_t i;
589
+
590
+ dpiVar__finalizeBuffer(var, &var->buffer, error);
591
+ if (var->dynBindBuffers) {
592
+ for (i = 0; i < var->buffer.maxArraySize; i++)
593
+ dpiVar__finalizeBuffer(var, &var->dynBindBuffers[i], error);
594
+ dpiUtils__freeMemory(var->dynBindBuffers);
595
+ var->dynBindBuffers = NULL;
596
+ }
746
597
  if (var->objectType) {
747
598
  dpiGen__setRefCount(var->objectType, error, -1);
748
599
  var->objectType = NULL;
@@ -759,35 +610,49 @@ void dpiVar__free(dpiVar *var, dpiError *error)
759
610
  // dpiVar__getValue() [PRIVATE]
760
611
  // Returns the contents of the variable in the type specified, if possible.
761
612
  //-----------------------------------------------------------------------------
762
- int dpiVar__getValue(dpiVar *var, uint32_t pos, dpiData *data,
763
- dpiError *error)
613
+ int dpiVar__getValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos,
614
+ int inFetch, dpiError *error)
764
615
  {
765
616
  dpiOracleTypeNum oracleTypeNum;
766
617
  dpiBytes *bytes;
618
+ dpiData *data;
619
+ uint32_t i;
620
+
621
+ // check for dynamic binds first; if they exist, process them instead
622
+ if (var->dynBindBuffers && buffer == &var->buffer) {
623
+ buffer = &var->dynBindBuffers[pos];
624
+ for (i = 0; i < buffer->maxArraySize; i++) {
625
+ if (dpiVar__getValue(var, buffer, i, inFetch, error) < 0)
626
+ return DPI_FAILURE;
627
+ }
628
+ return DPI_SUCCESS;
629
+ }
630
+
767
631
 
768
632
  // check for a NULL value; for objects the indicator is elsewhere
769
- if (!var->objectIndicator)
770
- data->isNull = (var->indicator[pos] == DPI_OCI_IND_NULL);
771
- else if (var->objectIndicator[pos])
772
- data->isNull =
773
- (*((int16_t*) var->objectIndicator[pos]) == DPI_OCI_IND_NULL);
633
+ data = &buffer->externalData[pos];
634
+ if (!buffer->objectIndicator)
635
+ data->isNull = (buffer->indicator[pos] == DPI_OCI_IND_NULL);
636
+ else if (buffer->objectIndicator[pos])
637
+ data->isNull = (*((int16_t*) buffer->objectIndicator[pos]) ==
638
+ DPI_OCI_IND_NULL);
774
639
  else data->isNull = 1;
775
640
  if (data->isNull)
776
641
  return DPI_SUCCESS;
777
642
 
778
643
  // check return code for variable length data
779
- if (var->returnCode) {
780
- if (var->returnCode[pos] != 0) {
644
+ if (buffer->returnCode) {
645
+ if (buffer->returnCode[pos] != 0) {
781
646
  dpiError__set(error, "check return code", DPI_ERR_COLUMN_FETCH,
782
- pos, var->returnCode[pos]);
783
- error->buffer->code = var->returnCode[pos];
647
+ pos, buffer->returnCode[pos]);
648
+ error->buffer->code = buffer->returnCode[pos];
784
649
  return DPI_FAILURE;
785
650
  }
786
651
  }
787
652
 
788
653
  // for 11g, dynamic lengths are 32-bit whereas static lengths are 16-bit
789
- if (var->actualLength16 && var->actualLength32)
790
- var->actualLength16[pos] = (uint16_t) var->actualLength32[pos];
654
+ if (buffer->actualLength16 && buffer->actualLength32)
655
+ buffer->actualLength16[pos] = (uint16_t) buffer->actualLength32[pos];
791
656
 
792
657
  // transform the various types
793
658
  oracleTypeNum = var->type->oracleTypeNum;
@@ -796,17 +661,18 @@ int dpiVar__getValue(dpiVar *var, uint32_t pos, dpiData *data,
796
661
  case DPI_NATIVE_TYPE_UINT64:
797
662
  switch (oracleTypeNum) {
798
663
  case DPI_ORACLE_TYPE_NATIVE_INT:
799
- data->value.asInt64 = var->data.asInt64[pos];
664
+ data->value.asInt64 = buffer->data.asInt64[pos];
800
665
  return DPI_SUCCESS;
801
666
  case DPI_ORACLE_TYPE_NATIVE_UINT:
802
- data->value.asUint64 = var->data.asUint64[pos];
667
+ data->value.asUint64 = buffer->data.asUint64[pos];
803
668
  return DPI_SUCCESS;
804
669
  case DPI_ORACLE_TYPE_NUMBER:
805
670
  if (var->nativeTypeNum == DPI_NATIVE_TYPE_INT64)
806
671
  return dpiDataBuffer__fromOracleNumberAsInteger(
807
- &data->value, error, &var->data.asNumber[pos]);
672
+ &data->value, error,
673
+ &buffer->data.asNumber[pos]);
808
674
  return dpiDataBuffer__fromOracleNumberAsUnsignedInteger(
809
- &data->value, error, &var->data.asNumber[pos]);
675
+ &data->value, error, &buffer->data.asNumber[pos]);
810
676
  default:
811
677
  break;
812
678
  }
@@ -815,16 +681,16 @@ int dpiVar__getValue(dpiVar *var, uint32_t pos, dpiData *data,
815
681
  switch (oracleTypeNum) {
816
682
  case DPI_ORACLE_TYPE_NUMBER:
817
683
  return dpiDataBuffer__fromOracleNumberAsDouble(
818
- &data->value, error, &var->data.asNumber[pos]);
684
+ &data->value, error, &buffer->data.asNumber[pos]);
819
685
  case DPI_ORACLE_TYPE_NATIVE_DOUBLE:
820
- data->value.asDouble = var->data.asDouble[pos];
686
+ data->value.asDouble = buffer->data.asDouble[pos];
821
687
  return DPI_SUCCESS;
822
688
  case DPI_ORACLE_TYPE_TIMESTAMP:
823
689
  case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
824
690
  case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
825
691
  return dpiDataBuffer__fromOracleTimestampAsDouble(
826
692
  &data->value, var->env, error,
827
- var->data.asTimestamp[pos]);
693
+ buffer->data.asTimestamp[pos]);
828
694
  default:
829
695
  break;
830
696
  }
@@ -840,62 +706,65 @@ int dpiVar__getValue(dpiVar *var, uint32_t pos, dpiData *data,
840
706
  case DPI_ORACLE_TYPE_RAW:
841
707
  case DPI_ORACLE_TYPE_LONG_VARCHAR:
842
708
  case DPI_ORACLE_TYPE_LONG_RAW:
843
- if (var->dynamicBytes)
709
+ if (buffer->dynamicBytes)
844
710
  return dpiVar__setBytesFromDynamicBytes(bytes,
845
- &var->dynamicBytes[pos], error);
846
- if (var->actualLength16)
847
- bytes->length = var->actualLength16[pos];
848
- else bytes->length = var->actualLength32[pos];
711
+ &buffer->dynamicBytes[pos], error);
712
+ if (buffer->actualLength16)
713
+ bytes->length = buffer->actualLength16[pos];
714
+ else bytes->length = buffer->actualLength32[pos];
849
715
  return DPI_SUCCESS;
850
716
  case DPI_ORACLE_TYPE_CLOB:
851
717
  case DPI_ORACLE_TYPE_NCLOB:
852
718
  case DPI_ORACLE_TYPE_BLOB:
853
719
  case DPI_ORACLE_TYPE_BFILE:
854
720
  return dpiVar__setBytesFromLob(bytes,
855
- &var->dynamicBytes[pos],
856
- var->references[pos].asLOB, error);
721
+ &buffer->dynamicBytes[pos],
722
+ buffer->references[pos].asLOB, error);
857
723
  case DPI_ORACLE_TYPE_NUMBER:
858
724
  bytes->length = DPI_NUMBER_AS_TEXT_CHARS;
859
725
  if (var->env->charsetId == DPI_CHARSET_ID_UTF16)
860
726
  bytes->length *= 2;
861
727
  return dpiDataBuffer__fromOracleNumberAsText(&data->value,
862
- var->env, error, &var->data.asNumber[pos]);
728
+ var->env, error, &buffer->data.asNumber[pos]);
863
729
  default:
864
730
  break;
865
731
  }
866
732
  break;
867
733
  case DPI_NATIVE_TYPE_FLOAT:
868
- data->value.asFloat = var->data.asFloat[pos];
734
+ data->value.asFloat = buffer->data.asFloat[pos];
869
735
  break;
870
736
  case DPI_NATIVE_TYPE_TIMESTAMP:
871
737
  if (oracleTypeNum == DPI_ORACLE_TYPE_DATE)
872
738
  return dpiDataBuffer__fromOracleDate(&data->value,
873
- &var->data.asDate[pos]);
739
+ &buffer->data.asDate[pos]);
874
740
  return dpiDataBuffer__fromOracleTimestamp(&data->value, var->env,
875
- error, var->data.asTimestamp[pos],
741
+ error, buffer->data.asTimestamp[pos],
876
742
  oracleTypeNum != DPI_ORACLE_TYPE_TIMESTAMP);
877
743
  break;
878
744
  case DPI_NATIVE_TYPE_INTERVAL_DS:
879
745
  return dpiDataBuffer__fromOracleIntervalDS(&data->value, var->env,
880
- error, var->data.asInterval[pos]);
746
+ error, buffer->data.asInterval[pos]);
881
747
  case DPI_NATIVE_TYPE_INTERVAL_YM:
882
748
  return dpiDataBuffer__fromOracleIntervalYM(&data->value, var->env,
883
- error, var->data.asInterval[pos]);
749
+ error, buffer->data.asInterval[pos]);
884
750
  case DPI_NATIVE_TYPE_OBJECT:
885
751
  data->value.asObject = NULL;
886
- if (!var->references[pos].asObject) {
752
+ if (!buffer->references[pos].asObject) {
887
753
  if (dpiObject__allocate(var->objectType,
888
- var->data.asObject[pos], var->objectIndicator[pos],
889
- &var->references[pos].asObject, error) < 0)
754
+ buffer->data.asObject[pos],
755
+ buffer->objectIndicator[pos], NULL,
756
+ &buffer->references[pos].asObject, error) < 0)
890
757
  return DPI_FAILURE;
758
+ if (inFetch && var->objectType->isCollection)
759
+ buffer->references[pos].asObject->freeIndicator = 1;
891
760
  }
892
- data->value.asObject = var->references[pos].asObject;
761
+ data->value.asObject = buffer->references[pos].asObject;
893
762
  break;
894
763
  case DPI_NATIVE_TYPE_STMT:
895
- data->value.asStmt = var->references[pos].asStmt;
764
+ data->value.asStmt = buffer->references[pos].asStmt;
896
765
  break;
897
766
  case DPI_NATIVE_TYPE_BOOLEAN:
898
- data->value.asBoolean = var->data.asBoolean[pos];
767
+ data->value.asBoolean = buffer->data.asBoolean[pos];
899
768
  break;
900
769
  default:
901
770
  break;
@@ -917,7 +786,7 @@ int32_t dpiVar__inBindCallback(dpiVar *var, UNUSED void *bindp,
917
786
  dpiDynamicBytes *dynBytes;
918
787
 
919
788
  if (var->isDynamic) {
920
- dynBytes = &var->dynamicBytes[index];
789
+ dynBytes = &var->buffer.dynamicBytes[iter];
921
790
  if (dynBytes->allocatedChunks == 0) {
922
791
  *bufpp = NULL;
923
792
  *alenp = 0;
@@ -926,30 +795,182 @@ int32_t dpiVar__inBindCallback(dpiVar *var, UNUSED void *bindp,
926
795
  *alenp = dynBytes->chunks->length;
927
796
  }
928
797
  } else {
929
- dpiVar__assignCallbackBuffer(var, index, bufpp);
930
- if (var->actualLength16)
931
- *alenp = var->actualLength16[index];
932
- else if (var->actualLength32)
933
- *alenp = var->actualLength32[index];
798
+ dpiVar__assignCallbackBuffer(var, &var->buffer, iter, bufpp);
799
+ if (var->buffer.actualLength16)
800
+ *alenp = var->buffer.actualLength16[iter];
801
+ else if (var->buffer.actualLength32)
802
+ *alenp = var->buffer.actualLength32[iter];
934
803
  else *alenp = var->type->sizeInBytes;
935
804
  }
936
805
  *piecep = DPI_OCI_ONE_PIECE;
937
- if (var->objectIndicator)
938
- *indpp = var->objectIndicator[index];
939
- else *indpp = &var->indicator[index];
806
+ if (var->buffer.objectIndicator)
807
+ *indpp = var->buffer.objectIndicator[iter];
808
+ else *indpp = &var->buffer.indicator[iter];
940
809
  return DPI_OCI_CONTINUE;
941
810
  }
942
811
 
943
812
 
944
813
  //-----------------------------------------------------------------------------
945
- // dpiVar__initBuffers() [INTERNAL]
814
+ // dpiVar__initBuffer() [INTERNAL]
946
815
  // Initialize buffers necessary for passing data to/from Oracle.
947
816
  //-----------------------------------------------------------------------------
948
- static int dpiVar__initBuffers(dpiVar *var, dpiError *error)
817
+ static int dpiVar__initBuffer(dpiVar *var, dpiVarBuffer *buffer,
818
+ dpiError *error)
949
819
  {
950
- if (dpiVar__allocateBuffers(var, error) < 0)
951
- return DPI_FAILURE;
952
- return dpiVar__extendedInitialize(var, error);
820
+ uint32_t i, tempBufferSize = 0;
821
+ unsigned long long dataLength;
822
+ dpiBytes *bytes;
823
+
824
+ // initialize dynamic buffers for dynamic variables
825
+ if (var->isDynamic) {
826
+ if (dpiUtils__allocateMemory(buffer->maxArraySize,
827
+ sizeof(dpiDynamicBytes), 1, "allocate dynamic bytes",
828
+ (void**) &buffer->dynamicBytes, error) < 0)
829
+ return DPI_FAILURE;
830
+
831
+ // for all other variables, validate length and allocate buffers
832
+ } else {
833
+ dataLength = (unsigned long long) buffer->maxArraySize *
834
+ (unsigned long long) var->sizeInBytes;
835
+ if (dataLength > INT_MAX)
836
+ return dpiError__set(error, "check max array size",
837
+ DPI_ERR_ARRAY_SIZE_TOO_BIG, buffer->maxArraySize);
838
+ if (dpiUtils__allocateMemory(1, (size_t) dataLength, 0,
839
+ "allocate buffer", (void**) &buffer->data.asRaw, error) < 0)
840
+ return DPI_FAILURE;
841
+ }
842
+
843
+ // allocate the indicator for the variable
844
+ // ensure all values start out as null
845
+ if (!buffer->indicator) {
846
+ if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(int16_t), 0,
847
+ "allocate indicator", (void**) &buffer->indicator, error) < 0)
848
+ return DPI_FAILURE;
849
+ for (i = 0; i < buffer->maxArraySize; i++)
850
+ buffer->indicator[i] = DPI_OCI_IND_NULL;
851
+ }
852
+
853
+ // allocate the actual length buffers for all but dynamic bytes which are
854
+ // handled differently; ensure actual length starts out as maximum value
855
+ if (!var->isDynamic && !buffer->actualLength16 &&
856
+ !buffer->actualLength32) {
857
+ if (var->env->versionInfo->versionNum < 12 && buffer == &var->buffer) {
858
+ if (dpiUtils__allocateMemory(buffer->maxArraySize,
859
+ sizeof(uint16_t), 0, "allocate actual length",
860
+ (void**) &buffer->actualLength16, error) < 0)
861
+ return DPI_FAILURE;
862
+ for (i = 0; i < buffer->maxArraySize; i++)
863
+ buffer->actualLength16[i] = (uint16_t) var->sizeInBytes;
864
+ } else {
865
+ if (dpiUtils__allocateMemory(buffer->maxArraySize,
866
+ sizeof(uint32_t), 0, "allocate actual length",
867
+ (void**) &buffer->actualLength32, error) < 0)
868
+ return DPI_FAILURE;
869
+ for (i = 0; i < buffer->maxArraySize; i++)
870
+ buffer->actualLength32[i] = var->sizeInBytes;
871
+ }
872
+ }
873
+
874
+ // for variable length data, also allocate the return code array
875
+ if (var->type->defaultNativeTypeNum == DPI_NATIVE_TYPE_BYTES &&
876
+ !var->isDynamic && !buffer->returnCode) {
877
+ if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(uint16_t), 0,
878
+ "allocate return code", (void**) &buffer->returnCode,
879
+ error) < 0)
880
+ return DPI_FAILURE;
881
+ }
882
+
883
+ // for numbers transferred to/from Oracle as bytes, allocate an additional
884
+ // set of buffers
885
+ if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_NUMBER &&
886
+ var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) {
887
+ tempBufferSize = DPI_NUMBER_AS_TEXT_CHARS;
888
+ if (var->env->charsetId == DPI_CHARSET_ID_UTF16)
889
+ tempBufferSize *= 2;
890
+ if (!buffer->tempBuffer) {
891
+ if (dpiUtils__allocateMemory(buffer->maxArraySize, tempBufferSize,
892
+ 0, "allocate temp buffer", (void**) &buffer->tempBuffer,
893
+ error) < 0)
894
+ return DPI_FAILURE;
895
+ }
896
+ }
897
+
898
+ // allocate the external data array, if needed
899
+ if (!buffer->externalData) {
900
+ if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(dpiData), 1,
901
+ "allocate external data", (void**) &buffer->externalData,
902
+ error) < 0)
903
+ return DPI_FAILURE;
904
+ for (i = 0; i < buffer->maxArraySize; i++)
905
+ buffer->externalData[i].isNull = 1;
906
+ }
907
+
908
+ // for bytes transfers, set encoding and pointers for small strings
909
+ if (var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) {
910
+ for (i = 0; i < buffer->maxArraySize; i++) {
911
+ bytes = &buffer->externalData[i].value.asBytes;
912
+ if (var->type->charsetForm == DPI_SQLCS_IMPLICIT)
913
+ bytes->encoding = var->env->encoding;
914
+ else bytes->encoding = var->env->nencoding;
915
+ if (buffer->tempBuffer)
916
+ bytes->ptr = buffer->tempBuffer + i * tempBufferSize;
917
+ else if (!var->isDynamic && !buffer->dynamicBytes)
918
+ bytes->ptr = buffer->data.asBytes + i * var->sizeInBytes;
919
+ }
920
+ }
921
+
922
+ // create array of references, if applicable
923
+ if (var->type->requiresPreFetch && !var->isDynamic) {
924
+ if (dpiUtils__allocateMemory(buffer->maxArraySize,
925
+ sizeof(dpiReferenceBuffer), 1, "allocate references",
926
+ (void**) &buffer->references, error) < 0)
927
+ return DPI_FAILURE;
928
+ }
929
+
930
+ // perform variable specific initialization
931
+ switch (var->type->oracleTypeNum) {
932
+ case DPI_ORACLE_TYPE_TIMESTAMP:
933
+ return dpiOci__arrayDescriptorAlloc(var->env->handle,
934
+ &buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP,
935
+ buffer->maxArraySize, error);
936
+ case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
937
+ return dpiOci__arrayDescriptorAlloc(var->env->handle,
938
+ &buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP_TZ,
939
+ buffer->maxArraySize, error);
940
+ case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
941
+ return dpiOci__arrayDescriptorAlloc(var->env->handle,
942
+ &buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP_LTZ,
943
+ buffer->maxArraySize, error);
944
+ case DPI_ORACLE_TYPE_INTERVAL_DS:
945
+ return dpiOci__arrayDescriptorAlloc(var->env->handle,
946
+ &buffer->data.asInterval[0], DPI_OCI_DTYPE_INTERVAL_DS,
947
+ buffer->maxArraySize, error);
948
+ case DPI_ORACLE_TYPE_INTERVAL_YM:
949
+ return dpiOci__arrayDescriptorAlloc(var->env->handle,
950
+ &buffer->data.asInterval[0], DPI_OCI_DTYPE_INTERVAL_YM,
951
+ buffer->maxArraySize, error);
952
+ break;
953
+ case DPI_ORACLE_TYPE_CLOB:
954
+ case DPI_ORACLE_TYPE_BLOB:
955
+ case DPI_ORACLE_TYPE_NCLOB:
956
+ case DPI_ORACLE_TYPE_BFILE:
957
+ case DPI_ORACLE_TYPE_STMT:
958
+ case DPI_ORACLE_TYPE_ROWID:
959
+ return dpiVar__extendedPreFetch(var, buffer, error);
960
+ case DPI_ORACLE_TYPE_OBJECT:
961
+ if (!var->objectType)
962
+ return dpiError__set(error, "check object type",
963
+ DPI_ERR_NO_OBJECT_TYPE);
964
+ if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(void*),
965
+ 0, "allocate object indicator",
966
+ (void**) &buffer->objectIndicator, error) < 0)
967
+ return DPI_FAILURE;
968
+ return dpiVar__extendedPreFetch(var, buffer, error);
969
+ default:
970
+ break;
971
+ }
972
+
973
+ return DPI_SUCCESS;
953
974
  }
954
975
 
955
976
 
@@ -966,8 +987,18 @@ int32_t dpiVar__outBindCallback(dpiVar *var, void *bindp, UNUSED uint32_t iter,
966
987
  dpiDynamicBytesChunk *chunk;
967
988
  uint32_t numRowsReturned;
968
989
  dpiDynamicBytes *bytes;
990
+ dpiVarBuffer *buffer;
969
991
 
970
- // special processing during first iteration
992
+ // determine which variable buffer to use
993
+ if (!var->dynBindBuffers) {
994
+ if (dpiUtils__allocateMemory(var->buffer.maxArraySize,
995
+ sizeof(dpiVarBuffer), 1, "allocate DML returning buffers",
996
+ (void**) &var->dynBindBuffers, var->error) < 0)
997
+ return DPI_FAILURE;
998
+ }
999
+ buffer = &var->dynBindBuffers[iter];
1000
+
1001
+ // special processing during first value returned for each iteration
971
1002
  if (index == 0) {
972
1003
 
973
1004
  // determine number of rows returned
@@ -977,15 +1008,15 @@ int32_t dpiVar__outBindCallback(dpiVar *var, void *bindp, UNUSED uint32_t iter,
977
1008
  return DPI_OCI_ERROR;
978
1009
 
979
1010
  // reallocate buffers, if needed
980
- if (numRowsReturned > var->maxArraySize) {
981
- dpiVar__finalizeBuffers(var, var->error);
982
- var->maxArraySize = numRowsReturned;
983
- if (dpiVar__initBuffers(var, var->error) < 0)
1011
+ if (numRowsReturned > buffer->maxArraySize) {
1012
+ dpiVar__finalizeBuffer(var, buffer, var->error);
1013
+ buffer->maxArraySize = numRowsReturned;
1014
+ if (dpiVar__initBuffer(var, buffer, var->error) < 0)
984
1015
  return DPI_OCI_ERROR;
985
1016
  }
986
1017
 
987
1018
  // set actual array size to number of rows returned
988
- var->actualArraySize = numRowsReturned;
1019
+ buffer->actualArraySize = numRowsReturned;
989
1020
 
990
1021
  }
991
1022
 
@@ -994,7 +1025,7 @@ int32_t dpiVar__outBindCallback(dpiVar *var, void *bindp, UNUSED uint32_t iter,
994
1025
  if (var->isDynamic) {
995
1026
 
996
1027
  // allocate more chunks, if necessary
997
- bytes = &var->dynamicBytes[index];
1028
+ bytes = &buffer->dynamicBytes[index];
998
1029
  if (*piecep == DPI_OCI_ONE_PIECE)
999
1030
  bytes->numChunks = 0;
1000
1031
  if (bytes->numChunks == bytes->allocatedChunks &&
@@ -1015,30 +1046,33 @@ int32_t dpiVar__outBindCallback(dpiVar *var, void *bindp, UNUSED uint32_t iter,
1015
1046
  chunk->length = chunk->allocatedLength;
1016
1047
  *bufpp = chunk->ptr;
1017
1048
  *alenpp = &chunk->length;
1018
- *indpp = &(var->indicator[index]);
1049
+ *indpp = &(buffer->indicator[index]);
1019
1050
  *rcodepp = NULL;
1020
1051
 
1021
1052
  // handle normally allocated variables (one piece)
1022
1053
  } else {
1023
1054
 
1024
1055
  *piecep = DPI_OCI_ONE_PIECE;
1025
- dpiVar__assignCallbackBuffer(var, index, bufpp);
1026
- if (var->actualLength32 || var->actualLength16) {
1027
- if (!var->actualLength32) {
1028
- if (dpiUtils__allocateMemory(var->maxArraySize,
1056
+ if (dpiVar__setValue(var, buffer, index, &buffer->externalData[index],
1057
+ var->error) < 0)
1058
+ return DPI_OCI_ERROR;
1059
+ dpiVar__assignCallbackBuffer(var, buffer, index, bufpp);
1060
+ if (buffer->actualLength32 || buffer->actualLength16) {
1061
+ if (!buffer->actualLength32) {
1062
+ if (dpiUtils__allocateMemory(buffer->maxArraySize,
1029
1063
  sizeof(uint32_t), 1, "allocate 11g lengths",
1030
- (void**) &var->actualLength32, var->error) < 0)
1064
+ (void**) &buffer->actualLength32, var->error) < 0)
1031
1065
  return DPI_OCI_ERROR;
1032
1066
  }
1033
- var->actualLength32[index] = var->sizeInBytes;
1034
- *alenpp = &(var->actualLength32[index]);
1067
+ buffer->actualLength32[index] = var->sizeInBytes;
1068
+ *alenpp = &(buffer->actualLength32[index]);
1035
1069
  } else if (*alenpp && var->type->sizeInBytes)
1036
1070
  **alenpp = var->type->sizeInBytes;
1037
- if (var->objectIndicator)
1038
- *indpp = var->objectIndicator[index];
1039
- else *indpp = &(var->indicator[index]);
1040
- if (var->returnCode)
1041
- *rcodepp = &var->returnCode[index];
1071
+ if (buffer->objectIndicator)
1072
+ *indpp = buffer->objectIndicator[index];
1073
+ else *indpp = &(buffer->indicator[index]);
1074
+ if (buffer->returnCode)
1075
+ *rcodepp = &buffer->returnCode[index];
1042
1076
 
1043
1077
  }
1044
1078
 
@@ -1144,31 +1178,33 @@ static int dpiVar__setBytesFromLob(dpiBytes *bytes, dpiDynamicBytes *dynBytes,
1144
1178
  static int dpiVar__setFromBytes(dpiVar *var, uint32_t pos, const char *value,
1145
1179
  uint32_t valueLength, dpiError *error)
1146
1180
  {
1147
- dpiData *data = &var->externalData[pos];
1181
+ dpiData *data = &var->buffer.externalData[pos];
1148
1182
  dpiDynamicBytes *dynBytes;
1149
1183
  dpiBytes *bytes;
1150
1184
 
1151
1185
  // for internally used LOBs, write the data directly
1152
- if (var->references) {
1186
+ if (var->buffer.references) {
1153
1187
  data->isNull = 0;
1154
- return dpiLob__setFromBytes(var->references[pos].asLOB, value,
1188
+ return dpiLob__setFromBytes(var->buffer.references[pos].asLOB, value,
1155
1189
  valueLength, error);
1156
1190
  }
1157
1191
 
1158
1192
  // validate the target can accept the input
1159
- if ((var->tempBuffer && var->env->charsetId == DPI_CHARSET_ID_UTF16 &&
1193
+ if ((var->buffer.tempBuffer &&
1194
+ var->env->charsetId == DPI_CHARSET_ID_UTF16 &&
1160
1195
  valueLength > DPI_NUMBER_AS_TEXT_CHARS * 2) ||
1161
- (var->tempBuffer && var->env->charsetId != DPI_CHARSET_ID_UTF16 &&
1196
+ (var->buffer.tempBuffer &&
1197
+ var->env->charsetId != DPI_CHARSET_ID_UTF16 &&
1162
1198
  valueLength > DPI_NUMBER_AS_TEXT_CHARS) ||
1163
- (!var->dynamicBytes && !var->tempBuffer &&
1199
+ (!var->buffer.dynamicBytes && !var->buffer.tempBuffer &&
1164
1200
  valueLength > var->sizeInBytes))
1165
1201
  return dpiError__set(error, "check source length",
1166
1202
  DPI_ERR_BUFFER_SIZE_TOO_SMALL, var->sizeInBytes);
1167
1203
 
1168
1204
  // for dynamic bytes, allocate space as needed
1169
1205
  bytes = &data->value.asBytes;
1170
- if (var->dynamicBytes) {
1171
- dynBytes = &var->dynamicBytes[pos];
1206
+ if (var->buffer.dynamicBytes) {
1207
+ dynBytes = &var->buffer.dynamicBytes[pos];
1172
1208
  if (dpiVar__allocateDynamicBytes(dynBytes, valueLength, error) < 0)
1173
1209
  return DPI_FAILURE;
1174
1210
  memcpy(dynBytes->chunks->ptr, value, valueLength);
@@ -1183,13 +1219,13 @@ static int dpiVar__setFromBytes(dpiVar *var, uint32_t pos, const char *value,
1183
1219
  if (valueLength > 0)
1184
1220
  memcpy(bytes->ptr, value, valueLength);
1185
1221
  if (var->type->sizeInBytes == 0) {
1186
- if (var->actualLength32)
1187
- var->actualLength32[pos] = valueLength;
1188
- else if (var->actualLength16)
1189
- var->actualLength16[pos] = (uint16_t) valueLength;
1222
+ if (var->buffer.actualLength32)
1223
+ var->buffer.actualLength32[pos] = valueLength;
1224
+ else if (var->buffer.actualLength16)
1225
+ var->buffer.actualLength16[pos] = (uint16_t) valueLength;
1190
1226
  }
1191
- if (var->returnCode)
1192
- var->returnCode[pos] = 0;
1227
+ if (var->buffer.returnCode)
1228
+ var->buffer.returnCode[pos] = 0;
1193
1229
  }
1194
1230
  data->isNull = 0;
1195
1231
 
@@ -1212,23 +1248,23 @@ static int dpiVar__setFromLob(dpiVar *var, uint32_t pos, dpiLob *lob,
1212
1248
  return DPI_FAILURE;
1213
1249
 
1214
1250
  // mark the value as not null
1215
- data = &var->externalData[pos];
1251
+ data = &var->buffer.externalData[pos];
1216
1252
  data->isNull = 0;
1217
1253
 
1218
1254
  // if values are the same, nothing to do
1219
- if (var->references[pos].asLOB == lob)
1255
+ if (var->buffer.references[pos].asLOB == lob)
1220
1256
  return DPI_SUCCESS;
1221
1257
 
1222
1258
  // clear original value, if needed
1223
- if (var->references[pos].asLOB) {
1224
- dpiGen__setRefCount(var->references[pos].asLOB, error, -1);
1225
- var->references[pos].asLOB = NULL;
1259
+ if (var->buffer.references[pos].asLOB) {
1260
+ dpiGen__setRefCount(var->buffer.references[pos].asLOB, error, -1);
1261
+ var->buffer.references[pos].asLOB = NULL;
1226
1262
  }
1227
1263
 
1228
1264
  // add reference to passed object
1229
1265
  dpiGen__setRefCount(lob, error, 1);
1230
- var->references[pos].asLOB = lob;
1231
- var->data.asLobLocator[pos] = lob->locator;
1266
+ var->buffer.references[pos].asLOB = lob;
1267
+ var->buffer.data.asLobLocator[pos] = lob->locator;
1232
1268
  data->value.asLOB = lob;
1233
1269
  return DPI_SUCCESS;
1234
1270
  }
@@ -1256,24 +1292,24 @@ static int dpiVar__setFromObject(dpiVar *var, uint32_t pos, dpiObject *obj,
1256
1292
  var->objectType->nameLength, var->objectType->name);
1257
1293
 
1258
1294
  // mark the value as not null
1259
- data = &var->externalData[pos];
1295
+ data = &var->buffer.externalData[pos];
1260
1296
  data->isNull = 0;
1261
1297
 
1262
1298
  // if values are the same, nothing to do
1263
- if (var->references[pos].asObject == obj)
1299
+ if (var->buffer.references[pos].asObject == obj)
1264
1300
  return DPI_SUCCESS;
1265
1301
 
1266
1302
  // clear original value, if needed
1267
- if (var->references[pos].asObject) {
1268
- dpiGen__setRefCount(var->references[pos].asObject, error, -1);
1269
- var->references[pos].asObject = NULL;
1303
+ if (var->buffer.references[pos].asObject) {
1304
+ dpiGen__setRefCount(var->buffer.references[pos].asObject, error, -1);
1305
+ var->buffer.references[pos].asObject = NULL;
1270
1306
  }
1271
1307
 
1272
1308
  // add reference to passed object
1273
1309
  dpiGen__setRefCount(obj, error, 1);
1274
- var->references[pos].asObject = obj;
1275
- var->data.asObject[pos] = obj->instance;
1276
- var->objectIndicator[pos] = obj->indicator;
1310
+ var->buffer.references[pos].asObject = obj;
1311
+ var->buffer.data.asObject[pos] = obj->instance;
1312
+ var->buffer.objectIndicator[pos] = obj->indicator;
1277
1313
  data->value.asObject = obj;
1278
1314
  return DPI_SUCCESS;
1279
1315
  }
@@ -1294,23 +1330,23 @@ static int dpiVar__setFromRowid(dpiVar *var, uint32_t pos, dpiRowid *rowid,
1294
1330
  return DPI_FAILURE;
1295
1331
 
1296
1332
  // mark the value as not null
1297
- data = &var->externalData[pos];
1333
+ data = &var->buffer.externalData[pos];
1298
1334
  data->isNull = 0;
1299
1335
 
1300
1336
  // if values are the same, nothing to do
1301
- if (var->references[pos].asRowid == rowid)
1337
+ if (var->buffer.references[pos].asRowid == rowid)
1302
1338
  return DPI_SUCCESS;
1303
1339
 
1304
1340
  // clear original value, if needed
1305
- if (var->references[pos].asRowid) {
1306
- dpiGen__setRefCount(var->references[pos].asRowid, error, -1);
1307
- var->references[pos].asRowid = NULL;
1341
+ if (var->buffer.references[pos].asRowid) {
1342
+ dpiGen__setRefCount(var->buffer.references[pos].asRowid, error, -1);
1343
+ var->buffer.references[pos].asRowid = NULL;
1308
1344
  }
1309
1345
 
1310
1346
  // add reference to passed object
1311
1347
  dpiGen__setRefCount(rowid, error, 1);
1312
- var->references[pos].asRowid = rowid;
1313
- var->data.asRowid[pos] = rowid->handle;
1348
+ var->buffer.references[pos].asRowid = rowid;
1349
+ var->buffer.data.asRowid[pos] = rowid->handle;
1314
1350
  data->value.asRowid = rowid;
1315
1351
  return DPI_SUCCESS;
1316
1352
  }
@@ -1331,23 +1367,23 @@ static int dpiVar__setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt,
1331
1367
  return DPI_FAILURE;
1332
1368
 
1333
1369
  // mark the value as not null
1334
- data = &var->externalData[pos];
1370
+ data = &var->buffer.externalData[pos];
1335
1371
  data->isNull = 0;
1336
1372
 
1337
1373
  // if values are the same, nothing to do
1338
- if (var->references[pos].asStmt == stmt)
1374
+ if (var->buffer.references[pos].asStmt == stmt)
1339
1375
  return DPI_SUCCESS;
1340
1376
 
1341
1377
  // clear original value, if needed
1342
- if (var->references[pos].asStmt) {
1343
- dpiGen__setRefCount(var->references[pos].asStmt, error, -1);
1344
- var->references[pos].asStmt = NULL;
1378
+ if (var->buffer.references[pos].asStmt) {
1379
+ dpiGen__setRefCount(var->buffer.references[pos].asStmt, error, -1);
1380
+ var->buffer.references[pos].asStmt = NULL;
1345
1381
  }
1346
1382
 
1347
1383
  // add reference to passed object
1348
1384
  dpiGen__setRefCount(stmt, error, 1);
1349
- var->references[pos].asStmt = stmt;
1350
- var->data.asStmt[pos] = stmt->handle;
1385
+ var->buffer.references[pos].asStmt = stmt;
1386
+ var->buffer.data.asStmt[pos] = stmt->handle;
1351
1387
  data->value.asStmt = stmt;
1352
1388
  return DPI_SUCCESS;
1353
1389
  }
@@ -1357,8 +1393,8 @@ static int dpiVar__setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt,
1357
1393
  // dpiVar__setValue() [PRIVATE]
1358
1394
  // Sets the contents of the variable using the type specified, if possible.
1359
1395
  //-----------------------------------------------------------------------------
1360
- int dpiVar__setValue(dpiVar *var, uint32_t pos, dpiData *data,
1361
- dpiError *error)
1396
+ int dpiVar__setValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos,
1397
+ dpiData *data, dpiError *error)
1362
1398
  {
1363
1399
  dpiOracleTypeNum oracleTypeNum;
1364
1400
  dpiObject *obj;
@@ -1367,61 +1403,62 @@ int dpiVar__setValue(dpiVar *var, uint32_t pos, dpiData *data,
1367
1403
  // however, when binding objects a value MUST be present or OCI will
1368
1404
  // segfault!
1369
1405
  if (data->isNull) {
1370
- var->indicator[pos] = DPI_OCI_IND_NULL;
1371
- if (var->objectIndicator && !var->data.asObject[pos]) {
1372
- if (dpiObject__allocate(var->objectType, NULL, NULL, &obj,
1406
+ buffer->indicator[pos] = DPI_OCI_IND_NULL;
1407
+ if (buffer->objectIndicator && !buffer->data.asObject[pos]) {
1408
+ if (dpiObject__allocate(var->objectType, NULL, NULL, NULL, &obj,
1373
1409
  error) < 0)
1374
1410
  return DPI_FAILURE;
1375
- var->references[pos].asObject = obj;
1411
+ buffer->references[pos].asObject = obj;
1376
1412
  data->value.asObject = obj;
1377
- var->data.asObject[pos] = obj->instance;
1378
- var->objectIndicator[pos] = obj->indicator;
1379
- if (var->objectIndicator[pos])
1380
- *((int16_t*) var->objectIndicator[pos]) = DPI_OCI_IND_NULL;
1413
+ buffer->data.asObject[pos] = obj->instance;
1414
+ buffer->objectIndicator[pos] = obj->indicator;
1415
+ if (buffer->objectIndicator[pos])
1416
+ *((int16_t*) buffer->objectIndicator[pos]) = DPI_OCI_IND_NULL;
1381
1417
  }
1382
1418
  return DPI_SUCCESS;
1383
1419
  }
1384
1420
 
1385
1421
  // transform the various types
1386
- var->indicator[pos] = DPI_OCI_IND_NOTNULL;
1422
+ buffer->indicator[pos] = DPI_OCI_IND_NOTNULL;
1387
1423
  oracleTypeNum = var->type->oracleTypeNum;
1388
1424
  switch (var->nativeTypeNum) {
1389
1425
  case DPI_NATIVE_TYPE_INT64:
1390
1426
  case DPI_NATIVE_TYPE_UINT64:
1391
1427
  switch (oracleTypeNum) {
1392
1428
  case DPI_ORACLE_TYPE_NATIVE_INT:
1393
- var->data.asInt64[pos] = data->value.asInt64;
1429
+ buffer->data.asInt64[pos] = data->value.asInt64;
1394
1430
  return DPI_SUCCESS;
1395
1431
  case DPI_ORACLE_TYPE_NATIVE_UINT:
1396
- var->data.asUint64[pos] = data->value.asUint64;
1432
+ buffer->data.asUint64[pos] = data->value.asUint64;
1397
1433
  return DPI_SUCCESS;
1398
1434
  case DPI_ORACLE_TYPE_NUMBER:
1399
1435
  if (var->nativeTypeNum == DPI_NATIVE_TYPE_INT64)
1400
1436
  return dpiDataBuffer__toOracleNumberFromInteger(
1401
- &data->value, error, &var->data.asNumber[pos]);
1437
+ &data->value, error,
1438
+ &buffer->data.asNumber[pos]);
1402
1439
  return dpiDataBuffer__toOracleNumberFromUnsignedInteger(
1403
- &data->value, error, &var->data.asNumber[pos]);
1440
+ &data->value, error, &buffer->data.asNumber[pos]);
1404
1441
  default:
1405
1442
  break;
1406
1443
  }
1407
1444
  break;
1408
1445
  case DPI_NATIVE_TYPE_FLOAT:
1409
- var->data.asFloat[pos] = data->value.asFloat;
1446
+ buffer->data.asFloat[pos] = data->value.asFloat;
1410
1447
  return DPI_SUCCESS;
1411
1448
  case DPI_NATIVE_TYPE_DOUBLE:
1412
1449
  switch (oracleTypeNum) {
1413
1450
  case DPI_ORACLE_TYPE_NATIVE_DOUBLE:
1414
- var->data.asDouble[pos] = data->value.asDouble;
1451
+ buffer->data.asDouble[pos] = data->value.asDouble;
1415
1452
  return DPI_SUCCESS;
1416
1453
  case DPI_ORACLE_TYPE_NUMBER:
1417
1454
  return dpiDataBuffer__toOracleNumberFromDouble(
1418
- &data->value, error, &var->data.asNumber[pos]);
1455
+ &data->value, error, &buffer->data.asNumber[pos]);
1419
1456
  case DPI_ORACLE_TYPE_TIMESTAMP:
1420
1457
  case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
1421
1458
  case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
1422
1459
  return dpiDataBuffer__toOracleTimestampFromDouble(
1423
1460
  &data->value, var->env, error,
1424
- var->data.asTimestamp[pos]);
1461
+ buffer->data.asTimestamp[pos]);
1425
1462
  default:
1426
1463
  break;
1427
1464
  }
@@ -1429,35 +1466,35 @@ int dpiVar__setValue(dpiVar *var, uint32_t pos, dpiData *data,
1429
1466
  case DPI_NATIVE_TYPE_BYTES:
1430
1467
  if (oracleTypeNum == DPI_ORACLE_TYPE_NUMBER)
1431
1468
  return dpiDataBuffer__toOracleNumberFromText(&data->value,
1432
- var->env, error, &var->data.asNumber[pos]);
1433
- if (var->actualLength32)
1434
- var->actualLength32[pos] = data->value.asBytes.length;
1435
- else if (var->actualLength16)
1436
- var->actualLength16[pos] =
1469
+ var->env, error, &buffer->data.asNumber[pos]);
1470
+ if (buffer->actualLength32)
1471
+ buffer->actualLength32[pos] = data->value.asBytes.length;
1472
+ else if (buffer->actualLength16)
1473
+ buffer->actualLength16[pos] =
1437
1474
  (uint16_t) data->value.asBytes.length;
1438
- if (var->returnCode)
1439
- var->returnCode[pos] = 0;
1475
+ if (buffer->returnCode)
1476
+ buffer->returnCode[pos] = 0;
1440
1477
  break;
1441
1478
  case DPI_NATIVE_TYPE_TIMESTAMP:
1442
1479
  if (oracleTypeNum == DPI_ORACLE_TYPE_DATE)
1443
1480
  return dpiDataBuffer__toOracleDate(&data->value,
1444
- &var->data.asDate[pos]);
1481
+ &buffer->data.asDate[pos]);
1445
1482
  else if (oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP)
1446
- return dpiDataBuffer__toOracleTimestamp(&data->value, var->env,
1447
- error, var->data.asTimestamp[pos], 0);
1483
+ return dpiDataBuffer__toOracleTimestamp(&data->value,
1484
+ var->env, error, buffer->data.asTimestamp[pos], 0);
1448
1485
  else if (oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_TZ ||
1449
1486
  oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_LTZ)
1450
- return dpiDataBuffer__toOracleTimestamp(&data->value, var->env,
1451
- error, var->data.asTimestamp[pos], 1);
1487
+ return dpiDataBuffer__toOracleTimestamp(&data->value,
1488
+ var->env, error, buffer->data.asTimestamp[pos], 1);
1452
1489
  break;
1453
1490
  case DPI_NATIVE_TYPE_INTERVAL_DS:
1454
1491
  return dpiDataBuffer__toOracleIntervalDS(&data->value, var->env,
1455
- error, var->data.asInterval[pos]);
1492
+ error, buffer->data.asInterval[pos]);
1456
1493
  case DPI_NATIVE_TYPE_INTERVAL_YM:
1457
1494
  return dpiDataBuffer__toOracleIntervalYM(&data->value, var->env,
1458
- error, var->data.asInterval[pos]);
1495
+ error, buffer->data.asInterval[pos]);
1459
1496
  case DPI_NATIVE_TYPE_BOOLEAN:
1460
- var->data.asBoolean[pos] = data->value.asBoolean;
1497
+ buffer->data.asBoolean[pos] = data->value.asBoolean;
1461
1498
  return DPI_SUCCESS;
1462
1499
  default:
1463
1500
  break;
@@ -1524,17 +1561,17 @@ int dpiVar_copyData(dpiVar *var, uint32_t pos, dpiVar *sourceVar,
1524
1561
  if (dpiGen__checkHandle(sourceVar, DPI_HTYPE_VAR, "check source var",
1525
1562
  &error) < 0)
1526
1563
  return dpiGen__endPublicFn(var, DPI_FAILURE, &error);
1527
- if (sourcePos >= sourceVar->maxArraySize) {
1564
+ if (sourcePos >= sourceVar->buffer.maxArraySize) {
1528
1565
  dpiError__set(&error, "check source size",
1529
1566
  DPI_ERR_INVALID_ARRAY_POSITION, sourcePos,
1530
- sourceVar->maxArraySize);
1567
+ sourceVar->buffer.maxArraySize);
1531
1568
  return dpiGen__endPublicFn(var, DPI_FAILURE, &error);
1532
1569
  }
1533
1570
  if (var->nativeTypeNum != sourceVar->nativeTypeNum) {
1534
1571
  dpiError__set(&error, "check types match", DPI_ERR_NOT_SUPPORTED);
1535
1572
  return dpiGen__endPublicFn(var, DPI_FAILURE, &error);
1536
1573
  }
1537
- sourceData = &sourceVar->externalData[sourcePos];
1574
+ sourceData = &sourceVar->buffer.externalData[sourcePos];
1538
1575
  status = dpiVar__copyData(var, pos, sourceData, &error);
1539
1576
  return dpiGen__endPublicFn(var, status, &error);
1540
1577
  }
@@ -1559,8 +1596,13 @@ int dpiVar_getData(dpiVar *var, uint32_t *numElements, dpiData **data)
1559
1596
  return dpiGen__endPublicFn(var, DPI_FAILURE, &error);
1560
1597
  DPI_CHECK_PTR_NOT_NULL(var, numElements)
1561
1598
  DPI_CHECK_PTR_NOT_NULL(var, data)
1562
- *numElements = var->maxArraySize;
1563
- *data = var->externalData;
1599
+ if (var->dynBindBuffers) {
1600
+ *numElements = var->dynBindBuffers->maxArraySize;
1601
+ *data = var->dynBindBuffers->externalData;
1602
+ } else {
1603
+ *numElements = var->buffer.maxArraySize;
1604
+ *data = var->buffer.externalData;
1605
+ }
1564
1606
  return dpiGen__endPublicFn(var, DPI_SUCCESS, &error);
1565
1607
  }
1566
1608
 
@@ -1577,10 +1619,42 @@ int dpiVar_getNumElementsInArray(dpiVar *var, uint32_t *numElements)
1577
1619
  if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, __func__, 0, &error) < 0)
1578
1620
  return dpiGen__endPublicFn(var, DPI_FAILURE, &error);
1579
1621
  DPI_CHECK_PTR_NOT_NULL(var, numElements)
1580
- *numElements = var->actualArraySize;
1622
+ if (var->dynBindBuffers)
1623
+ *numElements = var->dynBindBuffers->actualArraySize;
1624
+ else *numElements = var->buffer.actualArraySize;
1581
1625
  return dpiGen__endPublicFn(var, DPI_SUCCESS, &error);
1582
1626
  }
1583
1627
 
1628
+ //-----------------------------------------------------------------------------
1629
+ // dpiVar_getReturnedData() [PUBLIC]
1630
+ // Return a pointer to the array of dpiData structures allocated for the
1631
+ // given row that have been returned by a DML returning statement. The number
1632
+ // of returned rows is also provided. If the bind variable had no data
1633
+ // returned, the number of rows returned will be 0 and the pointer to the array
1634
+ // of dpiData structures will be NULL. This will also be the case if the
1635
+ // variable was only bound IN or was not bound to a DML returning statement.
1636
+ // There is no way to differentiate between the two.
1637
+ //-----------------------------------------------------------------------------
1638
+ int dpiVar_getReturnedData(dpiVar *var, uint32_t pos, uint32_t *numElements,
1639
+ dpiData **data)
1640
+ {
1641
+ dpiError error;
1642
+
1643
+ if (dpiVar__checkArraySize(var, pos, __func__, 1, &error) < 0)
1644
+ return dpiGen__endPublicFn(var, DPI_FAILURE, &error);
1645
+ DPI_CHECK_PTR_NOT_NULL(var, numElements)
1646
+ DPI_CHECK_PTR_NOT_NULL(var, data)
1647
+ if (var->dynBindBuffers) {
1648
+ *numElements = var->dynBindBuffers[pos].actualArraySize;
1649
+ *data = var->dynBindBuffers[pos].externalData;
1650
+ } else {
1651
+ *numElements = 0;
1652
+ *data = NULL;
1653
+ }
1654
+ return dpiGen__endPublicFn(var, DPI_SUCCESS, &error);
1655
+ }
1656
+
1657
+
1584
1658
 
1585
1659
  //-----------------------------------------------------------------------------
1586
1660
  // dpiVar_getSizeInBytes() [PUBLIC]
@@ -1738,12 +1812,12 @@ int dpiVar_setNumElementsInArray(dpiVar *var, uint32_t numElements)
1738
1812
 
1739
1813
  if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, __func__, 0, &error) < 0)
1740
1814
  return dpiGen__endPublicFn(var, DPI_FAILURE, &error);
1741
- if (numElements > var->maxArraySize) {
1815
+ if (numElements > var->buffer.maxArraySize) {
1742
1816
  dpiError__set(&error, "check num elements",
1743
- DPI_ERR_ARRAY_SIZE_TOO_SMALL, var->maxArraySize);
1817
+ DPI_ERR_ARRAY_SIZE_TOO_SMALL, var->buffer.maxArraySize);
1744
1818
  return dpiGen__endPublicFn(var, DPI_FAILURE, &error);
1745
1819
  }
1746
- var->actualArraySize = numElements;
1820
+ var->buffer.actualArraySize = numElements;
1747
1821
  return dpiGen__endPublicFn(var, DPI_SUCCESS, &error);
1748
1822
  }
1749
1823