1
- /* Copyright (c) 2015, 2016 , Oracle and/or its affiliates.
1
+ /* Copyright (c) 2015, 2017 , Oracle and/or its affiliates.
2
2
All rights reserved. */
3
3
4
4
/* *****************************************************************************
@@ -68,7 +68,7 @@ Nan::Persistent<FunctionTemplate> Connection::connectionTemplate_s;
68
68
#define NJS_MAX_FETCH_AS_STRING_SIZE 200
69
69
70
70
// Size of block allocated each time when callback is called for
71
- // for fetch-CLOB-as-STRING. This constant is used only CLOB- as-STRING case
71
+ // for fetch-CLOB-as-STRING/fetch-BLOB- as-Buffer.
72
72
#if OCI_MAJOR_VERSION >= 12
73
73
#define NJS_ITER_SIZE 524287 /* Use (512KB - 1) with 12c Clients */
74
74
#else
@@ -490,13 +490,16 @@ NAN_METHOD(Connection::Execute)
490
490
executeBaton->outFormat = connection->oracledb_ ->getOutFormat ();
491
491
executeBaton->autoCommit = connection->oracledb_ ->getAutoCommit ();
492
492
executeBaton->dpienv = connection->oracledb_ ->getDpiEnv ();
493
+ executeBaton->dpiconn = connection->dpiconn_ ;
494
+ executeBaton->njsconn = connection;
493
495
executeBaton->fetchAsStringTypes =
494
496
(DataType*) connection->oracledb_ ->getFetchAsStringTypes ();
495
497
executeBaton->fetchAsStringTypesCount =
496
498
connection->oracledb_ ->getFetchAsStringTypesCount ();
497
-
498
- executeBaton->dpiconn = connection->dpiconn_ ;
499
- executeBaton->njsconn = connection;
499
+ executeBaton->fetchAsBufferTypes =
500
+ (DataType*)connection->oracledb_ ->getFetchAsBufferTypes ();
501
+ executeBaton->fetchAsBufferTypesCount =
502
+ connection->oracledb_ ->getFetchAsBufferTypesCount () ;
500
503
executeBaton->extendedMetaData =
501
504
connection->oracledb_ ->getExtendedMetaData ();
502
505
@@ -637,9 +640,11 @@ void Connection::ProcessOptions (Nan::NAN_METHOD_ARGS_TYPE args, unsigned int in
637
640
638
641
fInfo [index].njsType = (DataType) tmptype;
639
642
640
- // Only Conversion to STRING allowed now. Either STRING or DB type.
643
+ // Only Conversion to STRING/Buffer allowed now.
644
+ // Either STRING/BUFFER or DB type.
641
645
if ( ( fInfo [index].njsType != NJS_DATATYPE_DEFAULT ) &&
642
- ( fInfo [index].njsType != NJS_DATATYPE_STR ) )
646
+ ( fInfo [index].njsType != NJS_DATATYPE_STR ) &&
647
+ ( fInfo [index].njsType != NJS_DATATYPE_BUFFER) )
643
648
{
644
649
executeBaton->error = NJSMessages::getErrorMsg (
645
650
errInvalidTypeForConversion );
@@ -2796,8 +2801,11 @@ void Connection::CopyMetaData ( MetaInfo *mInfo,
2796
2801
break ;
2797
2802
2798
2803
case dpi::DpiBlob:
2799
- mInfo [col].dpiFetchType = mData [col].dbType ;
2800
- mInfo [col].njsFetchType = NJS_DATATYPE_BLOB;
2804
+ mInfo [col].dpiFetchType = Connection::GetTargetType ( executeBaton,
2805
+ mInfo [col].name ,
2806
+ dpi::DpiBlob );
2807
+ mInfo [col].njsFetchType = ( mInfo [col].dpiFetchType == dpi::DpiRaw ) ?
2808
+ NJS_DATATYPE_BUFFER : NJS_DATATYPE_BLOB ;
2801
2809
break ;
2802
2810
2803
2811
case dpi::DpiRowid:
@@ -2907,6 +2915,10 @@ boolean Connection::MapByName ( eBaton *executeBaton, std::string &name,
2907
2915
{
2908
2916
targetType = dpi::DpiVarChar;
2909
2917
}
2918
+ else if ( executeBaton->fetchInfo [f].njsType == NJS_DATATYPE_BUFFER )
2919
+ {
2920
+ targetType = dpi::DpiRaw ;
2921
+ }
2910
2922
else if ( executeBaton->fetchInfo [f].njsType == NJS_DATATYPE_DEFAULT )
2911
2923
{
2912
2924
targetType = Connection::SourceDBType2TargetDBType ( targetType );
@@ -2939,7 +2951,7 @@ boolean Connection::MapByType ( eBaton *executeBaton, unsigned short &dbType )
2939
2951
boolean modified = false ;
2940
2952
unsigned int count = 0 ;
2941
2953
2942
- /* If oracledb property is set map using that */
2954
+ /* Process Fetch-As-string settings from global oracledb property first */
2943
2955
if ( executeBaton->fetchAsStringTypes )
2944
2956
{
2945
2957
count = executeBaton->fetchAsStringTypesCount ;
@@ -3000,6 +3012,26 @@ boolean Connection::MapByType ( eBaton *executeBaton, unsigned short &dbType )
3000
3012
}
3001
3013
}
3002
3014
3015
+ /* Process fetch-blob-as-buffer from global oracledb property */
3016
+ if ( !modified && executeBaton->fetchAsBufferTypes )
3017
+ {
3018
+ count = executeBaton->fetchAsBufferTypesCount ;
3019
+ switch ( dbType )
3020
+ {
3021
+ case dpi::DpiBlob:
3022
+ for ( unsigned int t = 0 ; !modified && ( t < count ) ; t ++ )
3023
+ {
3024
+ if ( executeBaton->fetchAsBufferTypes [t] == NJS_DATATYPE_BLOB )
3025
+ {
3026
+ /* convert all BLOB column values to BUFFER */
3027
+ dbType = dpi::DpiRaw;
3028
+ modified = true ;
3029
+ break ;
3030
+ }
3031
+ }
3032
+ }
3033
+ }
3034
+
3003
3035
return dbType;
3004
3036
}
3005
3037
@@ -3215,9 +3247,17 @@ void Connection::DoDefines ( eBaton* executeBaton )
3215
3247
case dpi::DpiBlob:
3216
3248
case dpi::DpiBfile:
3217
3249
defines[col].fetchType = executeBaton->mInfo [col].dpiFetchType ;
3218
- defines[col].maxSize =
3219
- ( defines[col].fetchType == dpi::DpiVarChar ) ?
3220
- sizeof ( char *) : sizeof ( Descriptor *) ;
3250
+ if ( executeBaton->mInfo [col].dbType == dpi::DpiClob )
3251
+ {
3252
+ defines[col].maxSize =
3253
+ ( defines[col].fetchType == dpi::DpiVarChar ) ?
3254
+ sizeof ( char *) : sizeof ( Descriptor *) ;
3255
+ }
3256
+ else if ( executeBaton->mInfo [col].dbType == dpi::DpiBlob )
3257
+ {
3258
+ defines[col].maxSize = ( defines[col].fetchType == dpi::DpiRaw ) ?
3259
+ sizeof ( void *) : sizeof ( Descriptor * ) ;
3260
+ }
3221
3261
3222
3262
if ( NJS_SIZE_T_OVERFLOW ( defines[col].maxSize ,
3223
3263
executeBaton->maxRows ) )
@@ -3242,13 +3282,17 @@ void Connection::DoDefines ( eBaton* executeBaton )
3242
3282
{
3243
3283
for (unsigned int j = 0 ; j < executeBaton->maxRows ; j++)
3244
3284
{
3245
- if ( defines[col].fetchType == dpi::DpiVarChar )
3285
+ switch ( defines[col].fetchType )
3246
3286
{
3287
+ case dpi::DpiVarChar:
3247
3288
// Clob-Fetch-As-String - allocation happens in callback
3248
3289
((char **)(defines[col].buf ))[j] = NULL ;
3249
- }
3250
- else
3251
- {
3290
+ break ;
3291
+ case dpi::DpiRaw:
3292
+ // Blob-Fetch-As-Buffer - allocation happens in callback
3293
+ ((void **)(defines[col].buf ))[j] = NULL ;
3294
+ break ;
3295
+ default :
3252
3296
((Descriptor **)(defines[col].buf ))[j] =
3253
3297
executeBaton->dpienv ->allocDescriptor (LobDescriptorType);
3254
3298
}
@@ -3309,32 +3353,34 @@ void Connection::DoDefines ( eBaton* executeBaton )
3309
3353
3310
3354
void *buf = NULL ;
3311
3355
DpiDefineCallbackCtx *ctx = NULL ;
3312
- bool clobAsStr = false ;
3356
+ bool lobAs = false ;
3313
3357
3314
- if ( ( defines[col].fetchType == dpi::DpiVarChar ) &&
3315
- ( executeBaton->mInfo [col].dbType == dpi::DpiClob ) )
3358
+ if ( ( ( defines[col].fetchType == dpi::DpiVarChar ) &&
3359
+ ( executeBaton->mInfo [col].dbType == dpi::DpiClob ) ) ||
3360
+ ( ( defines[col].fetchType == dpi::DpiRaw ) &&
3361
+ ( executeBaton->mInfo [col].dbType == dpi::DpiBlob ) ) )
3316
3362
{
3363
+ /* Fetch Clob-As-String or Blob-As-Buffer case */
3317
3364
ctx = ( DpiDefineCallbackCtx * )malloc (
3318
3365
sizeof ( DpiDefineCallbackCtx ) );
3319
3366
ctx->callbackfn = (definecbtype ) Connection::cbDynDefine ;
3320
3367
ctx->data = (void *)executeBaton ;
3321
3368
ctx->definePos = col ;
3322
3369
ctx->prevIter = -1L ; /* no row processed yet */
3323
- clobAsStr = true ;
3370
+ lobAs = true ;
3324
3371
executeBaton->extDefines [col] = new ExtDefine (
3325
- NJS_EXTDEFINE_CLOBASSTR ) ;
3326
- executeBaton->extDefines [col]->fields .extClobAsStr .ctx = (void *) ctx;
3372
+ NJS_EXTDEFINE_CONVERT_LOB ) ;
3373
+ executeBaton->extDefines [col]->fields .extConvertLob .ctx = (void *) ctx;
3327
3374
3328
- executeBaton->extDefines [col]->fields .extClobAsStr .len2 =
3375
+ executeBaton->extDefines [col]->fields .extConvertLob .len2 =
3329
3376
( unsigned int * ) malloc ( sizeof ( unsigned int ) *
3330
3377
executeBaton->maxRows );
3331
- if ( !executeBaton->extDefines [col]->fields .extClobAsStr .len2 )
3378
+ if ( !executeBaton->extDefines [col]->fields .extConvertLob .len2 )
3332
3379
{
3333
3380
executeBaton->error = NJSMessages::getErrorMsg (
3334
3381
errInsufficientMemory );
3335
3382
error = true ;
3336
3383
}
3337
-
3338
3384
}
3339
3385
else
3340
3386
{
@@ -3343,10 +3389,10 @@ void Connection::DoDefines ( eBaton* executeBaton )
3343
3389
3344
3390
executeBaton->dpistmt ->define (col+1 , defines[col].fetchType ,
3345
3391
buf,
3346
- clobAsStr ?
3392
+ lobAs ?
3347
3393
DPI_MAX_BUFLEN :defines[col].maxSize ,
3348
- clobAsStr ? NULL : defines[col].ind ,
3349
- clobAsStr ? NULL : defines[col].len ,
3394
+ lobAs ? NULL : defines[col].ind ,
3395
+ lobAs ? NULL : defines[col].len ,
3350
3396
ctx );
3351
3397
}
3352
3398
}
@@ -3372,17 +3418,17 @@ void Connection::DoFetch (eBaton* executeBaton)
3372
3418
Define *define = &(executeBaton->defines [col] );
3373
3419
ExtDefine *extDefine = executeBaton->extDefines [col];
3374
3420
3375
- if ( extDefine && extDefine -> extDefType == NJS_EXTDEFINE_CLOBASSTR )
3421
+ if ( extDefine && extDefine -> extDefType == NJS_EXTDEFINE_CONVERT_LOB )
3376
3422
{
3377
- /* In case of fetch-clob -as-string, the last read operation has partial
3423
+ /* In case of fetch-lob -as-xxx the last read operation has partial
3378
3424
* size read, and consolidated len is maintained in extDefine, add both
3379
3425
* and set it back to define->len[row] it can be used later
3380
3426
*/
3381
3427
for ( unsigned int row = 0 ; row < executeBaton->rowsFetched ; row ++ )
3382
3428
{
3383
3429
define->len [row] = ( DPI_BUFLEN_TYPE )
3384
- extDefine->fields .extClobAsStr .len2 [row];
3385
- define->len [row] += extDefine->fields .extClobAsStr .cLen ;
3430
+ extDefine->fields .extConvertLob .len2 [row];
3431
+ define->len [row] += extDefine->fields .extConvertLob .cLen ;
3386
3432
}
3387
3433
}
3388
3434
}
@@ -3982,6 +4028,11 @@ Local<Value> Connection::GetValue ( eBaton *executeBaton,
3982
4028
{
3983
4029
buf = ((char **) (define->buf ))[row];
3984
4030
}
4031
+ else if ( ( define->fetchType == dpi::DpiRaw ) &&
4032
+ ( executeBaton->mInfo [col].dbType == dpi::DpiBlob ) )
4033
+ {
4034
+ buf = ((void **) (define->buf ))[row];
4035
+ }
3985
4036
else
3986
4037
{
3987
4038
buf = ((char *)(define->buf ) + ( row * ( define->maxSize ) ) );
@@ -5607,12 +5658,12 @@ int Connection::cbDynDefine ( void *octxp, unsigned long definePos,
5607
5658
if ( *prevIter != iter )
5608
5659
{
5609
5660
*prevIter = iter;
5610
- extDefine->fields .extClobAsStr .cLen = 0 ;
5661
+ extDefine->fields .extConvertLob .cLen = 0 ;
5611
5662
}
5612
5663
else
5613
5664
{
5614
5665
// maintain incremental size of clob
5615
- extDefine->fields .extClobAsStr .cLen += NJS_ITER_SIZE ;
5666
+ extDefine->fields .extConvertLob .cLen += NJS_ITER_SIZE ;
5616
5667
}
5617
5668
5618
5669
tmp = buf[iter]; // preserve the current memory address
@@ -5621,7 +5672,7 @@ int Connection::cbDynDefine ( void *octxp, unsigned long definePos,
5621
5672
buf[iter] = (char *) ( ( !buf[iter] ) ?
5622
5673
malloc ( maxLen ) :
5623
5674
realloc ( buf[iter],
5624
- maxLen + extDefine->fields .extClobAsStr .cLen ) ) ;
5675
+ maxLen + extDefine->fields .extConvertLob .cLen ) ) ;
5625
5676
if ( !buf[iter] )
5626
5677
{
5627
5678
// If realloc fails, the IN parameter requires to be freed and untouched
@@ -5631,13 +5682,13 @@ int Connection::cbDynDefine ( void *octxp, unsigned long definePos,
5631
5682
}
5632
5683
else
5633
5684
{
5634
- extDefine->fields .extClobAsStr .len2 [iter] = maxLen;
5685
+ extDefine->fields .extConvertLob .len2 [iter] = maxLen;
5635
5686
define->ind [iter] = 0 ; // default value for indicator
5636
5687
5637
- *bufpp = (void *) (&buf[iter][extDefine->fields .extClobAsStr .cLen ]);
5688
+ *bufpp = (void *) (&buf[iter][extDefine->fields .extConvertLob .cLen ]);
5638
5689
5639
5690
// size for this iter
5640
- *alenpp = (unsigned int *) &(extDefine->fields .extClobAsStr .len2 [iter]) ;
5691
+ *alenpp = (unsigned int *) &(extDefine->fields .extConvertLob .len2 [iter]) ;
5641
5692
5642
5693
*indpp = (void *) &(define->ind [iter]); // indicator
5643
5694
}
0 commit comments