oracledb 2.2.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.
@@ -92,6 +92,9 @@ extern unsigned long dpiDebugLevel;
92
92
  // define maximum buffer size permitted in variables
93
93
  #define DPI_MAX_VAR_BUFFER_SIZE (1024 * 1024 * 1024 - 2)
94
94
 
95
+ // define subscription grouping repeat count
96
+ #define DPI_SUBSCR_GROUPING_FOREVER -1
97
+
95
98
  // define number of rows to prefetch
96
99
  #define DPI_PREFETCH_ROWS_DEFAULT 2
97
100
 
@@ -129,6 +132,7 @@ extern unsigned long dpiDebugLevel;
129
132
  #define DPI_OCI_DTYPE_AQMSG_PROPERTIES 59
130
133
  #define DPI_OCI_DTYPE_INTERVAL_YM 62
131
134
  #define DPI_OCI_DTYPE_INTERVAL_DS 63
135
+ #define DPI_OCI_DTYPE_AQNFY_DESCRIPTOR 64
132
136
  #define DPI_OCI_DTYPE_TIMESTAMP 68
133
137
  #define DPI_OCI_DTYPE_TIMESTAMP_TZ 69
134
138
  #define DPI_OCI_DTYPE_TIMESTAMP_LTZ 70
@@ -178,6 +182,7 @@ extern unsigned long dpiDebugLevel;
178
182
  #define DPI_OCI_ATTR_ENQ_TIME 62
179
183
  #define DPI_OCI_ATTR_MSG_STATE 63
180
184
  #define DPI_OCI_ATTR_ORIGINAL_MSGID 69
185
+ #define DPI_OCI_ATTR_QUEUE_NAME 70
181
186
  #define DPI_OCI_ATTR_NUM_DML_ERRORS 73
182
187
  #define DPI_OCI_ATTR_DML_ROW_OFFSET 74
183
188
  #define DPI_OCI_ATTR_SUBSCR_NAME 94
@@ -207,6 +212,10 @@ extern unsigned long dpiDebugLevel;
207
212
  #define DPI_OCI_ATTR_SUBSCR_CQ_QOSFLAGS 229
208
213
  #define DPI_OCI_ATTR_LIST_TYPE_ATTRS 229
209
214
  #define DPI_OCI_ATTR_SUBSCR_CQ_REGID 230
215
+ #define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_CLASS 231
216
+ #define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_VALUE 232
217
+ #define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_TYPE 233
218
+ #define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_REPEAT_COUNT 235
210
219
  #define DPI_OCI_ATTR_NCHARSET_ID 262
211
220
  #define DPI_OCI_ATTR_APPCTX_SIZE 273
212
221
  #define DPI_OCI_ATTR_APPCTX_LIST 274
@@ -229,6 +238,7 @@ extern unsigned long dpiDebugLevel;
229
238
  #define DPI_OCI_ATTR_CHNF_OPERATIONS 403
230
239
  #define DPI_OCI_ATTR_CHDES_DBNAME 405
231
240
  #define DPI_OCI_ATTR_CHDES_NFYTYPE 406
241
+ #define DPI_OCI_ATTR_NFY_FLAGS 406
232
242
  #define DPI_OCI_ATTR_CHDES_XID 407
233
243
  #define DPI_OCI_ATTR_MSG_DELIVERY_MODE 407
234
244
  #define DPI_OCI_ATTR_CHDES_TABLE_CHANGES 408
@@ -246,6 +256,7 @@ extern unsigned long dpiDebugLevel;
246
256
  #define DPI_OCI_ATTR_CONNECTION_CLASS 425
247
257
  #define DPI_OCI_ATTR_PURITY 426
248
258
  #define DPI_OCI_ATTR_RECEIVE_TIMEOUT 436
259
+ #define DPI_OCI_ATTR_SUBSCR_IPADDR 452
249
260
  #define DPI_OCI_ATTR_UB8_ROW_COUNT 457
250
261
  #define DPI_OCI_ATTR_SPOOL_AUTH 460
251
262
  #define DPI_OCI_ATTR_LTXID 462
@@ -257,6 +268,7 @@ extern unsigned long dpiDebugLevel;
257
268
  #define DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT 495
258
269
  #define DPI_OCI_ATTR_SHARDING_KEY 496
259
270
  #define DPI_OCI_ATTR_SUPER_SHARDING_KEY 497
271
+ #define DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT 506
260
272
 
261
273
  // define OCI object type constants
262
274
  #define DPI_OCI_OTYPE_NAME 1
@@ -465,6 +477,9 @@ typedef enum {
465
477
  DPI_ERR_SUBSCR_CLOSED,
466
478
  DPI_ERR_NO_EDITION_WITH_NEW_PASSWORD,
467
479
  DPI_ERR_UNEXPECTED_OCI_RETURN_VALUE,
480
+ DPI_ERR_EXEC_MODE_ONLY_FOR_DML,
481
+ DPI_ERR_ARRAY_VAR_NOT_SUPPORTED,
482
+ DPI_ERR_EVENTS_MODE_REQUIRED,
468
483
  DPI_ERR_MAX
469
484
  } dpiErrorNum;
470
485
 
@@ -511,7 +526,6 @@ typedef enum {
511
526
  // old type definitions (to be dropped)
512
527
  //-----------------------------------------------------------------------------
513
528
 
514
- // structure used for creating connections (2.0)
515
529
  typedef struct {
516
530
  dpiAuthMode authMode;
517
531
  const char *connectionClass;
@@ -532,6 +546,34 @@ typedef struct {
532
546
  int outTagFound;
533
547
  } dpiConnCreateParams__v20;
534
548
 
549
+ typedef struct {
550
+ dpiSubscrNamespace subscrNamespace;
551
+ dpiSubscrProtocol protocol;
552
+ dpiSubscrQOS qos;
553
+ dpiOpCode operations;
554
+ uint32_t portNumber;
555
+ uint32_t timeout;
556
+ const char *name;
557
+ uint32_t nameLength;
558
+ dpiSubscrCallback callback;
559
+ void *callbackContext;
560
+ const char *recipientName;
561
+ uint32_t recipientNameLength;
562
+ } dpiSubscrCreateParams__v23;
563
+
564
+ typedef struct {
565
+ uint32_t minSessions;
566
+ uint32_t maxSessions;
567
+ uint32_t sessionIncrement;
568
+ int pingInterval;
569
+ int pingTimeout;
570
+ int homogeneous;
571
+ int externalAuth;
572
+ dpiPoolGetMode getMode;
573
+ const char *outPoolName;
574
+ uint32_t outPoolNameLength;
575
+ } dpiPoolCreateParams__v23;
576
+
535
577
 
536
578
  //-----------------------------------------------------------------------------
537
579
  // OCI type definitions
@@ -603,6 +645,7 @@ typedef struct {
603
645
  dpiVersionInfo *versionInfo;
604
646
  void *baseDate;
605
647
  int threaded;
648
+ int events;
606
649
  } dpiEnv;
607
650
 
608
651
  typedef struct {
@@ -851,9 +894,11 @@ struct dpiSubscr {
851
894
  dpiType_HEAD
852
895
  dpiConn *conn;
853
896
  void *handle;
897
+ dpiSubscrNamespace subscrNamespace;
854
898
  dpiSubscrQOS qos;
855
899
  dpiSubscrCallback callback;
856
900
  void *callbackContext;
901
+ int registered;
857
902
  };
858
903
 
859
904
  struct dpiDeqOptions {
@@ -881,8 +926,7 @@ struct dpiMsgProps {
881
926
  // definition of internal dpiContext methods
882
927
  //-----------------------------------------------------------------------------
883
928
  void dpiContext__initCommonCreateParams(dpiCommonCreateParams *params);
884
- void dpiContext__initConnCreateParams(const dpiContext *context,
885
- dpiConnCreateParams *params, size_t *structSize);
929
+ void dpiContext__initConnCreateParams(dpiConnCreateParams *params);
886
930
  void dpiContext__initPoolCreateParams(dpiPoolCreateParams *params);
887
931
  void dpiContext__initSubscrCreateParams(dpiSubscrCreateParams *params);
888
932
 
@@ -1320,7 +1364,8 @@ int dpiOci__stringResize(void *envHandle, void **handle, uint32_t newSize,
1320
1364
  int dpiOci__stringSize(void *envHandle, void *handle, uint32_t *size);
1321
1365
  int dpiOci__subscriptionRegister(dpiConn *conn, void **handle,
1322
1366
  dpiError *error);
1323
- int dpiOci__subscriptionUnRegister(dpiSubscr *subscr, dpiError *error);
1367
+ int dpiOci__subscriptionUnRegister(dpiConn *conn, dpiSubscr *subscr,
1368
+ dpiError *error);
1324
1369
  int dpiOci__tableDelete(dpiObject *obj, int32_t index, dpiError *error);
1325
1370
  int dpiOci__tableExists(dpiObject *obj, int32_t index, int *exists,
1326
1371
  dpiError *error);
package/odpi/src/dpiOci.c CHANGED
@@ -2792,15 +2792,16 @@ int dpiOci__subscriptionRegister(dpiConn *conn, void **handle, dpiError *error)
2792
2792
  // dpiOci__subscriptionUnRegister() [INTERNAL]
2793
2793
  // Wrapper for OCISubscriptionUnRegister().
2794
2794
  //-----------------------------------------------------------------------------
2795
- int dpiOci__subscriptionUnRegister(dpiSubscr *subscr, dpiError *error)
2795
+ int dpiOci__subscriptionUnRegister(dpiConn *conn, dpiSubscr *subscr,
2796
+ dpiError *error)
2796
2797
  {
2797
2798
  int status;
2798
2799
 
2799
2800
  DPI_OCI_LOAD_SYMBOL("OCISubscriptionUnRegister",
2800
2801
  dpiOciSymbols.fnSubscriptionUnRegister)
2801
- status = (*dpiOciSymbols.fnSubscriptionUnRegister)(subscr->conn->handle,
2802
+ status = (*dpiOciSymbols.fnSubscriptionUnRegister)(conn->handle,
2802
2803
  subscr->handle, error->handle, DPI_OCI_DEFAULT);
2803
- return dpiError__check(error, status, subscr->conn, "unregister");
2804
+ return dpiError__check(error, status, conn, "unregister");
2804
2805
  }
2805
2806
 
2806
2807
 
@@ -119,6 +119,31 @@ static int dpiPool__create(dpiPool *pool, const char *userName,
119
119
  DPI_OCI_ATTR_SPOOL_GETMODE, "set get mode", error) < 0)
120
120
  return DPI_FAILURE;
121
121
 
122
+ // set the session timeout on the pool
123
+ if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*)
124
+ &createParams->timeout, 0, DPI_OCI_ATTR_SPOOL_TIMEOUT,
125
+ "set timeout", error) < 0)
126
+ return DPI_FAILURE;
127
+
128
+ // set the wait timeout on the pool (valid in 12.2 and higher)
129
+ if (pool->env->versionInfo->versionNum > 12 ||
130
+ (pool->env->versionInfo->versionNum == 12 &&
131
+ pool->env->versionInfo->releaseNum >= 2)) {
132
+ if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*)
133
+ &createParams->waitTimeout, 0, DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT,
134
+ "set wait timeout", error) < 0)
135
+ return DPI_FAILURE;
136
+ }
137
+
138
+ // set the maximum lifetime session on the pool (valid in 12.1 and higher)
139
+ if (pool->env->versionInfo->versionNum >= 12) {
140
+ if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*)
141
+ &createParams->maxLifetimeSession, 0,
142
+ DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION,
143
+ "set max lifetime session", error) < 0)
144
+ return DPI_FAILURE;
145
+ }
146
+
122
147
  // set reamining attributes directly
123
148
  pool->homogeneous = createParams->homogeneous;
124
149
  pool->externalAuth = createParams->externalAuth;
@@ -154,26 +179,37 @@ void dpiPool__free(dpiPool *pool, dpiError *error)
154
179
  static int dpiPool__getAttributeUint(dpiPool *pool, uint32_t attribute,
155
180
  uint32_t *value, const char *fnName)
156
181
  {
182
+ int status, supported = 1;
157
183
  dpiError error;
158
- int status;
159
184
 
160
185
  if (dpiPool__checkConnected(pool, fnName, &error) < 0)
161
186
  return dpiGen__endPublicFn(pool, DPI_FAILURE, &error);
162
187
  DPI_CHECK_PTR_NOT_NULL(pool, value)
163
188
  switch (attribute) {
164
- case DPI_OCI_ATTR_SPOOL_BUSY_COUNT:
165
189
  case DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION:
190
+ if (pool->env->versionInfo->versionNum < 12)
191
+ supported = 0;
192
+ break;
193
+ case DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT:
194
+ if (pool->env->versionInfo->versionNum < 12 ||
195
+ (pool->env->versionInfo->versionNum == 12 &&
196
+ pool->env->versionInfo->releaseNum < 2))
197
+ supported = 0;
198
+ break;
199
+ case DPI_OCI_ATTR_SPOOL_BUSY_COUNT:
166
200
  case DPI_OCI_ATTR_SPOOL_OPEN_COUNT:
167
201
  case DPI_OCI_ATTR_SPOOL_STMTCACHESIZE:
168
202
  case DPI_OCI_ATTR_SPOOL_TIMEOUT:
169
- status = dpiOci__attrGet(pool->handle, DPI_OCI_HTYPE_SPOOL, value,
170
- NULL, attribute, "get attribute value", &error);
171
203
  break;
172
204
  default:
173
- status = dpiError__set(&error, "get attribute",
174
- DPI_ERR_NOT_SUPPORTED);
205
+ supported = 0;
175
206
  break;
176
207
  }
208
+ if (supported)
209
+ status = dpiOci__attrGet(pool->handle, DPI_OCI_HTYPE_SPOOL, value,
210
+ NULL, attribute, "get attribute value", &error);
211
+ else status = dpiError__set(&error, "get attribute value",
212
+ DPI_ERR_NOT_SUPPORTED);
177
213
  return dpiGen__endPublicFn(pool, status, &error);
178
214
  }
179
215
 
@@ -185,10 +221,10 @@ static int dpiPool__getAttributeUint(dpiPool *pool, uint32_t attribute,
185
221
  static int dpiPool__setAttributeUint(dpiPool *pool, uint32_t attribute,
186
222
  uint32_t value, const char *fnName)
187
223
  {
224
+ int status, supported = 1;
225
+ void *ociValue = &value;
188
226
  uint8_t shortValue;
189
- void *ociValue;
190
227
  dpiError error;
191
- int status;
192
228
 
193
229
  // make sure session pool is connected
194
230
  if (dpiPool__checkConnected(pool, fnName, &error) < 0)
@@ -201,18 +237,29 @@ static int dpiPool__setAttributeUint(dpiPool *pool, uint32_t attribute,
201
237
  ociValue = &shortValue;
202
238
  break;
203
239
  case DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION:
240
+ if (pool->env->versionInfo->versionNum < 12)
241
+ supported = 0;
242
+ break;
243
+ case DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT:
244
+ if (pool->env->versionInfo->versionNum < 12 ||
245
+ (pool->env->versionInfo->versionNum == 12 &&
246
+ pool->env->versionInfo->releaseNum < 2))
247
+ supported = 0;
248
+ break;
204
249
  case DPI_OCI_ATTR_SPOOL_STMTCACHESIZE:
205
250
  case DPI_OCI_ATTR_SPOOL_TIMEOUT:
206
- ociValue = &value;
207
251
  break;
208
252
  default:
209
- dpiError__set(&error, "set attribute", DPI_ERR_NOT_SUPPORTED);
210
- return dpiGen__endPublicFn(pool, DPI_FAILURE, &error);
253
+ supported = 0;
254
+ break;
211
255
  }
212
256
 
213
257
  // set value in the OCI
214
- status = dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, ociValue, 0,
215
- attribute, "set attribute value", &error);
258
+ if (supported)
259
+ status = dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, ociValue,
260
+ 0, attribute, "set attribute value", &error);
261
+ else status = dpiError__set(&error, "set attribute value",
262
+ DPI_ERR_NOT_SUPPORTED);
216
263
  return dpiGen__endPublicFn(pool, status, &error);
217
264
  }
218
265
 
@@ -226,7 +273,6 @@ int dpiPool_acquireConnection(dpiPool *pool, const char *userName,
226
273
  dpiConnCreateParams *params, dpiConn **conn)
227
274
  {
228
275
  dpiConnCreateParams localParams;
229
- size_t structSize;
230
276
  dpiError error;
231
277
  int status;
232
278
 
@@ -239,10 +285,9 @@ int dpiPool_acquireConnection(dpiPool *pool, const char *userName,
239
285
 
240
286
  // use default parameters if none provided
241
287
  if (!params || pool->env->context->dpiMinorVersion == 0) {
242
- dpiContext__initConnCreateParams(pool->env->context, &localParams,
243
- &structSize);
288
+ dpiContext__initConnCreateParams(&localParams);
244
289
  if (params)
245
- memcpy(&localParams, params, structSize);
290
+ memcpy(&localParams, params, sizeof(dpiConnCreateParams__v20));
246
291
  params = &localParams;
247
292
  }
248
293
 
@@ -309,8 +354,11 @@ int dpiPool_create(const dpiContext *context, const char *userName,
309
354
  dpiContext__initCommonCreateParams(&localCommonParams);
310
355
  commonParams = &localCommonParams;
311
356
  }
312
- if (!createParams) {
357
+ if (!createParams || context->dpiMinorVersion < 4) {
313
358
  dpiContext__initPoolCreateParams(&localCreateParams);
359
+ if (createParams)
360
+ memcpy(&localCreateParams, createParams,
361
+ sizeof(dpiPoolCreateParams__v23));
314
362
  createParams = &localCreateParams;
315
363
  }
316
364
 
@@ -433,6 +481,17 @@ int dpiPool_getTimeout(dpiPool *pool, uint32_t *value)
433
481
  }
434
482
 
435
483
 
484
+ //-----------------------------------------------------------------------------
485
+ // dpiPool_getWaitTimeout() [PUBLIC]
486
+ // Return the pool's wait timeout value.
487
+ //-----------------------------------------------------------------------------
488
+ int dpiPool_getWaitTimeout(dpiPool *pool, uint32_t *value)
489
+ {
490
+ return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT,
491
+ value, __func__);
492
+ }
493
+
494
+
436
495
  //-----------------------------------------------------------------------------
437
496
  // dpiPool_release() [PUBLIC]
438
497
  // Release a reference to the pool.
@@ -486,3 +545,14 @@ int dpiPool_setTimeout(dpiPool *pool, uint32_t value)
486
545
  __func__);
487
546
  }
488
547
 
548
+
549
+ //-----------------------------------------------------------------------------
550
+ // dpiPool_setWaitTimeout() [PUBLIC]
551
+ // Set the pool's wait timeout value.
552
+ //-----------------------------------------------------------------------------
553
+ int dpiPool_setWaitTimeout(dpiPool *pool, uint32_t value)
554
+ {
555
+ return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT,
556
+ value, __func__);
557
+ }
558
+
@@ -22,7 +22,7 @@ static int dpiStmt__getQueryInfo(dpiStmt *stmt, uint32_t pos,
22
22
  static int dpiStmt__getQueryInfoFromParam(dpiStmt *stmt, void *param,
23
23
  dpiQueryInfo *info, dpiError *error);
24
24
  static int dpiStmt__postFetch(dpiStmt *stmt, dpiError *error);
25
- static int dpiStmt__preFetch(dpiStmt *stmt, dpiError *error);
25
+ static int dpiStmt__beforeFetch(dpiStmt *stmt, dpiError *error);
26
26
  static int dpiStmt__reExecute(dpiStmt *stmt, uint32_t numIters,
27
27
  uint32_t mode, dpiError *error);
28
28
 
@@ -538,6 +538,9 @@ static int dpiStmt__execute(dpiStmt *stmt, uint32_t numIters,
538
538
  // buffer structures
539
539
  for (i = 0; i < stmt->numBindVars; i++) {
540
540
  var = stmt->bindVars[i].var;
541
+ if (var->isArray && numIters > 1)
542
+ return dpiError__set(error, "bind array var",
543
+ DPI_ERR_ARRAY_VAR_NOT_SUPPORTED);
541
544
  for (j = 0; j < var->buffer.maxArraySize; j++) {
542
545
  data = &var->buffer.externalData[j];
543
546
  if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_STMT &&
@@ -546,13 +549,17 @@ static int dpiStmt__execute(dpiStmt *stmt, uint32_t numIters,
546
549
  DPI_ERR_NOT_SUPPORTED);
547
550
  if (dpiVar__setValue(var, &var->buffer, j, data, error) < 0)
548
551
  return DPI_FAILURE;
552
+ if (var->dynBindBuffers)
553
+ var->dynBindBuffers[j].actualArraySize = 0;
549
554
  }
550
555
  if (stmt->isReturning || var->isDynamic)
551
556
  var->error = error;
552
557
  }
553
558
 
554
- // for queries, set the prefetch rows to the fetch array size in order to
555
- // avoid the network round trip for the first fetch
559
+ // for queries, set the OCI prefetch to a fixed value; this prevents an
560
+ // additional round trip for single row fetches while avoiding the overhead
561
+ // of copying from the OCI prefetch buffer to our own buffers for larger
562
+ // fetches
556
563
  if (stmt->statementType == DPI_STMT_TYPE_SELECT) {
557
564
  prefetchSize = DPI_PREFETCH_ROWS_DEFAULT;
558
565
  if (dpiOci__attrSet(stmt->handle, DPI_OCI_HTYPE_STMT, &prefetchSize,
@@ -615,7 +622,7 @@ static int dpiStmt__execute(dpiStmt *stmt, uint32_t numIters,
615
622
  static int dpiStmt__fetch(dpiStmt *stmt, dpiError *error)
616
623
  {
617
624
  // perform any pre-fetch activities required
618
- if (dpiStmt__preFetch(stmt, error) < 0)
625
+ if (dpiStmt__beforeFetch(stmt, error) < 0)
619
626
  return DPI_FAILURE;
620
627
 
621
628
  // perform fetch
@@ -848,13 +855,13 @@ static int dpiStmt__postFetch(dpiStmt *stmt, dpiError *error)
848
855
 
849
856
 
850
857
  //-----------------------------------------------------------------------------
851
- // dpiStmt__preFetch() [INTERNAL]
858
+ // dpiStmt__beforeFetch() [INTERNAL]
852
859
  // Performs work that needs to be done prior to fetch for each variable. In
853
860
  // addition, variables are created if they do not already exist. A check is
854
861
  // also made to ensure that the variable has enough space to support a fetch
855
862
  // of the requested size.
856
863
  //-----------------------------------------------------------------------------
857
- static int dpiStmt__preFetch(dpiStmt *stmt, dpiError *error)
864
+ static int dpiStmt__beforeFetch(dpiStmt *stmt, dpiError *error)
858
865
  {
859
866
  dpiQueryInfo *queryInfo;
860
867
  dpiData *data;
@@ -1193,6 +1200,18 @@ int dpiStmt_executeMany(dpiStmt *stmt, dpiExecMode mode, uint32_t numIters)
1193
1200
  return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1194
1201
  }
1195
1202
 
1203
+ // batch errors and array DML row counts are only supported with DML
1204
+ // statements (insert, update, delete and merge)
1205
+ if ((mode & DPI_MODE_EXEC_BATCH_ERRORS ||
1206
+ mode & DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS) &&
1207
+ stmt->statementType != DPI_STMT_TYPE_INSERT &&
1208
+ stmt->statementType != DPI_STMT_TYPE_UPDATE &&
1209
+ stmt->statementType != DPI_STMT_TYPE_DELETE &&
1210
+ stmt->statementType != DPI_STMT_TYPE_MERGE) {
1211
+ dpiError__set(&error, "check mode", DPI_ERR_EXEC_MODE_ONLY_FOR_DML);
1212
+ return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1213
+ }
1214
+
1196
1215
  // ensure that all bind variables have a big enough maxArraySize to
1197
1216
  // support this operation
1198
1217
  for (i = 0; i < stmt->numBindVars; i++) {
@@ -1567,8 +1586,9 @@ int dpiStmt_getQueryValue(dpiStmt *stmt, uint32_t pos,
1567
1586
 
1568
1587
  //-----------------------------------------------------------------------------
1569
1588
  // dpiStmt_getRowCount() [PUBLIC]
1570
- // Return the number of rows affected by the last SQL executed (for insert,
1571
- // update or delete) or the number of rows fetched (for queries).
1589
+ // Return the number of rows affected by the last DML executed (for insert,
1590
+ // update, delete and merge) or the number of rows fetched (for queries). In
1591
+ // all other cases, 0 is returned.
1572
1592
  //-----------------------------------------------------------------------------
1573
1593
  int dpiStmt_getRowCount(dpiStmt *stmt, uint64_t *count)
1574
1594
  {
@@ -1580,7 +1600,12 @@ int dpiStmt_getRowCount(dpiStmt *stmt, uint64_t *count)
1580
1600
  DPI_CHECK_PTR_NOT_NULL(stmt, count)
1581
1601
  if (stmt->statementType == DPI_STMT_TYPE_SELECT)
1582
1602
  *count = stmt->rowCount;
1583
- else if (stmt->env->versionInfo->versionNum < 12) {
1603
+ else if (stmt->statementType != DPI_STMT_TYPE_INSERT &&
1604
+ stmt->statementType != DPI_STMT_TYPE_UPDATE &&
1605
+ stmt->statementType != DPI_STMT_TYPE_DELETE &&
1606
+ stmt->statementType != DPI_STMT_TYPE_MERGE) {
1607
+ *count = 0;
1608
+ } else if (stmt->env->versionInfo->versionNum < 12) {
1584
1609
  if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, &rowCount32, 0,
1585
1610
  DPI_OCI_ATTR_ROW_COUNT, "get row count", &error) < 0)
1586
1611
  return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
@@ -1699,7 +1724,7 @@ int dpiStmt_scroll(dpiStmt *stmt, dpiFetchMode mode, int32_t offset,
1699
1724
  }
1700
1725
 
1701
1726
  // perform any pre-fetch activities required
1702
- if (dpiStmt__preFetch(stmt, &error) < 0)
1727
+ if (dpiStmt__beforeFetch(stmt, &error) < 0)
1703
1728
  return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error);
1704
1729
 
1705
1730
  // perform fetch; when fetching the last row, only fetch a single row
@@ -50,6 +50,7 @@ static void dpiSubscr__callback(dpiSubscr *subscr, UNUSED void *handle,
50
50
  dpiError__getInfo(&error, &errorInfo);
51
51
  message.errorInfo = &errorInfo;
52
52
  }
53
+ message.registered = subscr->registered;
53
54
 
54
55
  // invoke user callback
55
56
  (*subscr->callback)(subscr->callbackContext, &message);
@@ -86,6 +87,7 @@ int dpiSubscr__create(dpiSubscr *subscr, dpiConn *conn,
86
87
  dpiSubscrCreateParams *params, uint64_t *subscrId, dpiError *error)
87
88
  {
88
89
  uint32_t qosFlags;
90
+ int32_t int32Val;
89
91
  int rowids;
90
92
 
91
93
  // retain a reference to the connection
@@ -93,6 +95,7 @@ int dpiSubscr__create(dpiSubscr *subscr, dpiConn *conn,
93
95
  subscr->conn = conn;
94
96
  subscr->callback = params->callback;
95
97
  subscr->callbackContext = params->callbackContext;
98
+ subscr->subscrNamespace = params->subscrNamespace;
96
99
  subscr->qos = params->qos;
97
100
 
98
101
  // create the subscription handle
@@ -118,6 +121,13 @@ int dpiSubscr__create(dpiSubscr *subscr, dpiConn *conn,
118
121
  DPI_OCI_ATTR_SUBSCR_TIMEOUT, "set timeout", error) < 0)
119
122
  return DPI_FAILURE;
120
123
 
124
+ // set the IP address used on the client to listen for events
125
+ if (params->ipAddress && params->ipAddressLength > 0 &&
126
+ dpiOci__attrSet(subscr->env->handle, DPI_OCI_HTYPE_ENV,
127
+ (void*) params->ipAddress, params->ipAddressLength,
128
+ DPI_OCI_ATTR_SUBSCR_IPADDR, "set IP address", error) < 0)
129
+ return DPI_FAILURE;
130
+
121
131
  // set the port number used on the client to listen for events
122
132
  if (params->portNumber > 0 && dpiOci__attrSet(subscr->env->handle,
123
133
  DPI_OCI_HTYPE_ENV, (void*) &params->portNumber, 0,
@@ -180,9 +190,44 @@ int dpiSubscr__create(dpiSubscr *subscr, dpiConn *conn,
180
190
  DPI_OCI_ATTR_CHNF_OPERATIONS, "set operations", error) < 0)
181
191
  return DPI_FAILURE;
182
192
 
193
+ // set grouping information, if applicable
194
+ if (params->groupingClass) {
195
+
196
+ // set grouping class
197
+ if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION,
198
+ (void*) &params->groupingClass, 0,
199
+ DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_CLASS, "set grouping class",
200
+ error) < 0)
201
+ return DPI_FAILURE;
202
+
203
+ // set grouping value
204
+ if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION,
205
+ (void*) &params->groupingValue, 0,
206
+ DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_VALUE, "set grouping value",
207
+ error) < 0)
208
+ return DPI_FAILURE;
209
+
210
+ // set grouping type
211
+ if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION,
212
+ (void*) &params->groupingType, 0,
213
+ DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_TYPE, "set grouping type",
214
+ error) < 0)
215
+ return DPI_FAILURE;
216
+
217
+ // set grouping repeat count
218
+ int32Val = DPI_SUBSCR_GROUPING_FOREVER;
219
+ if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION,
220
+ (void*) &int32Val, 0,
221
+ DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_REPEAT_COUNT,
222
+ "set grouping repeat count", error) < 0)
223
+ return DPI_FAILURE;
224
+
225
+ }
226
+
183
227
  // register the subscription
184
228
  if (dpiOci__subscriptionRegister(conn, &subscr->handle, error) < 0)
185
229
  return DPI_FAILURE;
230
+ subscr->registered = 1;
186
231
 
187
232
  // get the registration id, if applicable
188
233
  if (subscrId && dpiOci__attrGet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION,
@@ -201,7 +246,9 @@ int dpiSubscr__create(dpiSubscr *subscr, dpiConn *conn,
201
246
  void dpiSubscr__free(dpiSubscr *subscr, dpiError *error)
202
247
  {
203
248
  if (subscr->handle) {
204
- dpiOci__subscriptionUnRegister(subscr, error);
249
+ if (subscr->registered)
250
+ dpiOci__subscriptionUnRegister(subscr->conn, subscr, error);
251
+ dpiOci__handleFree(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION);
205
252
  subscr->handle = NULL;
206
253
  }
207
254
  if (subscr->conn) {
@@ -247,6 +294,41 @@ static void dpiSubscr__freeMessage(dpiSubscrMessage *message)
247
294
  }
248
295
 
249
296
 
297
+ //-----------------------------------------------------------------------------
298
+ // dpiSubscr__populateAQMessage() [INTERNAL]
299
+ // Populate message with details.
300
+ //-----------------------------------------------------------------------------
301
+ static int dpiSubscr__populateAQMessage(dpiSubscr *subscr,
302
+ dpiSubscrMessage *message, void *descriptor, dpiError *error)
303
+ {
304
+ uint32_t flags = 0;
305
+
306
+ // determine if message is a deregistration message
307
+ if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_AQNFY_DESCRIPTOR, &flags,
308
+ NULL, DPI_OCI_ATTR_NFY_FLAGS, "get flags", error) < 0)
309
+ return DPI_FAILURE;
310
+ message->eventType = (flags == 1) ? DPI_EVENT_DEREG : DPI_EVENT_AQ;
311
+ if (message->eventType == DPI_EVENT_DEREG) {
312
+ subscr->registered = 0;
313
+ return DPI_SUCCESS;
314
+ }
315
+
316
+ // determine the name of the queue which spawned the event
317
+ if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_AQNFY_DESCRIPTOR,
318
+ (void*) &message->queueName, &message->queueNameLength,
319
+ DPI_OCI_ATTR_QUEUE_NAME, "get queue name", error) < 0)
320
+ return DPI_FAILURE;
321
+
322
+ // determine the consumer name for the queue that spawned the event
323
+ if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_AQNFY_DESCRIPTOR,
324
+ (void*) &message->consumerName, &message->consumerNameLength,
325
+ DPI_OCI_ATTR_CONSUMER_NAME, "get consumer name", error) < 0)
326
+ return DPI_FAILURE;
327
+
328
+ return DPI_SUCCESS;
329
+ }
330
+
331
+
250
332
  //-----------------------------------------------------------------------------
251
333
  // dpiSubscr__populateObjectChangeMessage() [INTERNAL]
252
334
  // Populate object change message with details.
@@ -301,6 +383,17 @@ static int dpiSubscr__populateMessage(dpiSubscr *subscr,
301
383
  {
302
384
  void *rawValue;
303
385
 
386
+ // if quality of service flag indicates that deregistration should take
387
+ // place when the first notification is received, mark the subscription
388
+ // as no longer registered
389
+ if (subscr->qos & DPI_SUBSCR_QOS_DEREG_NFY)
390
+ subscr->registered = 0;
391
+
392
+ // handle AQ messages, if applicable
393
+ if (subscr->subscrNamespace == DPI_SUBSCR_NAMESPACE_AQ)
394
+ return dpiSubscr__populateAQMessage(subscr, message, descriptor,
395
+ error);
396
+
304
397
  // determine the type of event that was spawned
305
398
  if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, &message->eventType,
306
399
  NULL, DPI_OCI_ATTR_CHDES_NFYTYPE, "get event type", error) < 0)
@@ -328,7 +421,7 @@ static int dpiSubscr__populateMessage(dpiSubscr *subscr,
328
421
  return dpiSubscr__populateQueryChangeMessage(subscr, message,
329
422
  descriptor, error);
330
423
  case DPI_EVENT_DEREG:
331
- subscr->handle = NULL;
424
+ subscr->registered = 0;
332
425
  break;
333
426
  default:
334
427
  return dpiError__set(error, "event type", DPI_ERR_NOT_SUPPORTED);
@@ -562,10 +655,10 @@ int dpiSubscr_close(dpiSubscr *subscr)
562
655
 
563
656
  if (dpiSubscr__checkOpen(subscr, __func__, &error) < 0)
564
657
  return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error);
565
- if (subscr->handle) {
566
- if (dpiOci__subscriptionUnRegister(subscr, &error) < 0)
658
+ if (subscr->registered) {
659
+ if (dpiOci__subscriptionUnRegister(subscr->conn, subscr, &error) < 0)
567
660
  return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error);
568
- subscr->handle = NULL;
661
+ subscr->registered = 0;
569
662
  }
570
663
 
571
664
  return dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error);
package/odpi/src/dpiVar.c CHANGED
@@ -207,6 +207,12 @@ static void dpiVar__assignCallbackBuffer(dpiVar *var, dpiVarBuffer *buffer,
207
207
  case DPI_ORACLE_TYPE_BFILE:
208
208
  *bufpp = buffer->data.asLobLocator[index];
209
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];
215
+ break;
210
216
  default:
211
217
  *bufpp = buffer->data.asBytes + index * var->sizeInBytes;
212
218
  break;
@@ -1639,7 +1645,7 @@ int dpiVar_getReturnedData(dpiVar *var, uint32_t pos, uint32_t *numElements,
1639
1645
  DPI_CHECK_PTR_NOT_NULL(var, numElements)
1640
1646
  DPI_CHECK_PTR_NOT_NULL(var, data)
1641
1647
  if (var->dynBindBuffers) {
1642
- *numElements = var->dynBindBuffers[pos].maxArraySize;
1648
+ *numElements = var->dynBindBuffers[pos].actualArraySize;
1643
1649
  *data = var->dynBindBuffers[pos].externalData;
1644
1650
  } else {
1645
1651
  *numElements = 0;