5454#include " njsIntLob.h"
5555#include < stdlib.h>
5656#include < limits>
57+
5758using 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 }
0 commit comments