Skip to content

Commit 04a1d5b

Browse files
committed
Add tests and fix initialization for fetching CLOBs as Strings
1 parent 466b21e commit 04a1d5b

File tree

5 files changed

+944
-289
lines changed

5 files changed

+944
-289
lines changed

src/njs/src/njsConnection.cpp

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include "njsIntLob.h"
5555
#include <stdlib.h>
5656
#include <limits>
57+
5758
using namespace std;
5859

5960
// persistent Connection class handle
@@ -68,7 +69,11 @@ Nan::Persistent<FunctionTemplate> Connection::connectionTemplate_s;
6869

6970
// Size of block allocated each time when callback is called for
7071
// for fetch-CLOB-as-STRING. This constant is used only CLOB-as-STRING case
71-
#define NJS_ITER_SIZE 1048576
72+
#if OCI_MAJOR_VERSION >= 12
73+
#define NJS_ITER_SIZE 524287 /* Use (512KB - 1) with 12c Clients */
74+
#else
75+
#define NJS_ITER_SIZE 65535 /* Use (64KB - 1) with 11g Clients */
76+
#endif
7277

7378
// Max number of bytes allowed for PLSQL STRING/BUFFER arguments
7479
#define NJS_THRESHOLD_SIZE_PLSQL_STRING_ARG 32767
@@ -2560,6 +2565,13 @@ void Connection::PrepareAndBind (eBaton* executeBaton)
25602565

25612566
DpiBindCallbackCtx *ctx = extBind->fields.extDMLReturnCbCtx.ctx =
25622567
(DpiBindCallbackCtx *) malloc ( sizeof ( DpiBindCallbackCtx ) );
2568+
if ( !ctx )
2569+
{
2570+
executeBaton->error = NJSMessages::getErrorMsg (
2571+
errInsufficientMemory );
2572+
goto exitPrepareAndBind;
2573+
}
2574+
25632575
ctx->callbackfn = Connection::cbDynBufferGet;
25642576
/* App specific callback */
25652577
ctx->data = (void *)executeBaton;
@@ -2653,6 +2665,12 @@ void Connection::PrepareAndBind (eBaton* executeBaton)
26532665
DpiBindCallbackCtx *ctx = extBind->fields.extDMLReturnCbCtx.ctx =
26542666
(DpiBindCallbackCtx *) malloc ( sizeof ( DpiBindCallbackCtx ) );
26552667

2668+
if ( !ctx )
2669+
{
2670+
executeBaton->error = NJSMessages::getErrorMsg (
2671+
errInsufficientMemory );
2672+
goto exitPrepareAndBind;
2673+
}
26562674
ctx->callbackfn = Connection::cbDynBufferGet;
26572675
/* App specific callback */
26582676
ctx->data = (void *)executeBaton;
@@ -3337,6 +3355,25 @@ void Connection::DoFetch (eBaton* executeBaton)
33373355
NJSErrorType errNum = errSuccess;
33383356
executeBaton->dpistmt->fetch ( executeBaton->maxRows );
33393357
executeBaton->rowsFetched = executeBaton->dpistmt->rowsFetched();
3358+
3359+
for ( unsigned int col = 0; col < executeBaton->numCols; col ++ )
3360+
{
3361+
Define *define = &(executeBaton->defines[col] );
3362+
ExtDefine *extDefine = executeBaton->extDefines[col];
3363+
3364+
if ( extDefine && extDefine -> extDefType == NJS_EXTDEFINE_CLOBASSTR )
3365+
{
3366+
/* In case of fetch-clob-as-string, the last read operation has partial
3367+
* size read, and consolidated len is maintained in extDefine, add both
3368+
* and set it back to define->len[row] it can be used later
3369+
*/
3370+
for ( unsigned int row = 0; row < executeBaton->rowsFetched ; row ++ )
3371+
{
3372+
define->len[row] += extDefine->fields.extClobAsStr.cLen ;
3373+
}
3374+
}
3375+
}
3376+
33403377
errNum = Connection::Descr2Double ( executeBaton->defines,
33413378
executeBaton->numCols,
33423379
executeBaton->rowsFetched,
@@ -4116,7 +4153,7 @@ Local<Value> Connection::GetValueCommon ( eBaton *executeBaton,
41164153
switch(type)
41174154
{
41184155
case (dpi::DpiVarChar) :
4119-
value = Nan::New<v8::String>((char*)val, len).ToLocalChecked();
4156+
value = Nan::New<v8::String>((char*)val, len).ToLocalChecked();
41204157
break;
41214158
case (dpi::DpiInteger) :
41224159
value = Nan::New<v8::Integer>(*(int*)val);
@@ -5548,28 +5585,30 @@ int Connection::cbDynDefine ( void *octxp, unsigned long definePos,
55485585
{
55495586
eBaton *executeBaton = (eBaton *) octxp ;
55505587
Define *define = &(executeBaton->defines[definePos]);
5551-
unsigned long maxLen = 0;
5588+
ExtDefine *extDefine = executeBaton->extDefines[definePos];
5589+
unsigned long maxLen = NJS_ITER_SIZE ;
55525590
char **buf = (char **)define->buf ;
55535591
char *tmp = NULL ; // to presever ptr for realloc
55545592
int ret = 0;
55555593

55565594
if ( *prevIter != iter )
55575595
{
5558-
// For next row, start from minimum buffer
5559-
maxLen = NJS_ITER_SIZE ;
55605596
*prevIter = iter;
5597+
extDefine->fields.extClobAsStr.cLen = 0;
55615598
}
55625599
else
55635600
{
5564-
// More data for same row, try with next incremental size
5565-
maxLen = ( ( ( unsigned long ) (**alenpp ) ) + NJS_ITER_SIZE );
5601+
// maintain incremental size of clob
5602+
extDefine->fields.extClobAsStr.cLen += NJS_ITER_SIZE ;
55665603
}
55675604

55685605
tmp = buf[iter]; // preserve the current memory address
55695606

55705607
// allocate or reallocate buffer
55715608
buf[iter] = (char *) ( ( !buf[iter] ) ?
5572-
malloc ( maxLen ) : realloc ( buf[iter], maxLen ) ) ;
5609+
malloc ( maxLen ) :
5610+
realloc ( buf[iter],
5611+
maxLen + extDefine->fields.extClobAsStr.cLen ) ) ;
55735612
if ( !buf[iter] )
55745613
{
55755614
// If realloc fails, the IN parameter requires to be freed and untouched
@@ -5582,7 +5621,7 @@ int Connection::cbDynDefine ( void *octxp, unsigned long definePos,
55825621
define->len[iter] = maxLen;
55835622
define->ind[iter] = 0; // default value for indicator
55845623

5585-
*bufpp = (void *) buf[iter]; // memory for this iter
5624+
*bufpp = (void *) (&buf[iter][extDefine->fields.extClobAsStr.cLen]);
55865625
*alenpp = (unsigned long *) &(define->len[iter]) ; // size for this iter
55875626
*indpp = (void *) &(define->ind[iter]); // indicator
55885627
}

src/njs/src/njsConnection.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ typedef struct ExtDefine
239239
struct
240240
{
241241
void *ctx; /* Context pointer used by the call back */
242+
DPI_BUFLEN_TYPE cLen;
242243
} extClobAsStr ;
243244
} fields;
244245

@@ -248,6 +249,7 @@ typedef struct ExtDefine
248249
if ( type == NJS_EXTDEFINE_CLOBASSTR )
249250
{
250251
fields.extClobAsStr.ctx = NULL ;
252+
fields.extClobAsStr.cLen = 0;
251253
}
252254
}
253255
} ExtDefine;
@@ -396,7 +398,7 @@ typedef struct eBaton
396398
case NJS_EXTBIND_DMLRETCB:
397399
if ( extBinds[index]->fields.extDMLReturnCbCtx.ctx )
398400
{
399-
delete extBinds[index];
401+
free ( extBinds[index]->fields.extDMLReturnCbCtx.ctx ) ;
400402
}
401403
break;
402404

@@ -405,6 +407,7 @@ typedef struct eBaton
405407
break;
406408
}
407409
}
410+
delete extBinds[index];
408411
}
409412
extBinds.clear ();
410413
}

0 commit comments

Comments
 (0)