Skip to content

Commit 053f88c

Browse files
committed
Fix binding NULL to PL/SQL parameters
1 parent 7c1a54e commit 053f88c

19 files changed

+8328
-228
lines changed

src/njs/src/njsConnection.cpp

+85-176
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,6 @@ Nan::Persistent<FunctionTemplate> Connection::connectionTemplate_s;
7575
#define NJS_ITER_SIZE 65535 /* Use (64KB - 1) with 11g Clients */
7676
#endif
7777

78-
// Max number of bytes allowed for PLSQL STRING/BUFFER arguments
79-
#define NJS_THRESHOLD_SIZE_PLSQL_STRING_ARG 32767
80-
8178
// number of rows prefetched by non-ResultSet queries
8279
#define NJS_PREFETCH_NON_RESULTSET 2
8380

@@ -1088,6 +1085,7 @@ void Connection::GetInBindParamsScalar(Local<Value> v8val, Bind* bind,
10881085
{
10891086
case NJS_VALUETYPE_NULL:
10901087
bind->value = NULL;
1088+
*(bind->len) = 0; /* NULL value provided, no buffer used */
10911089
bind->type = dpi::DpiVarChar;
10921090
break;
10931091

@@ -2403,41 +2401,17 @@ void Connection::Descr2StringOrBuffer ( eBaton* executeBaton )
24032401
* index - Index of the Bind vector
24042402
*
24052403
* NOTE:
2406-
* Bind enhancements for CLOB/BLOB As String/Buffer not supported for INOUT
2407-
* arguments
2404+
* Bind type is expected only STRING and RAW
24082405
*
24092406
*/
24102407
void Connection::ConvertStringOrBuffer2LOB ( eBaton* executeBaton,
24112408
unsigned int index )
24122409
{
24132410
Bind *bind = executeBaton->binds[index];
2414-
DPI_SZ_TYPE size = 0;
24152411

2416-
if ( !bind->isOut && !bind->isInOut )
2412+
ExtBind* extBind = new ExtBind ( NJS_EXTBIND_LOB );
2413+
if ( extBind )
24172414
{
2418-
// Case for BIND_IN
2419-
size = *bind->len;
2420-
}
2421-
else if ( bind->isInOut )
2422-
{
2423-
// Case for BIND_INOUT
2424-
size = ( bind->maxSize >= *( bind->len ) ) ? bind->maxSize : *( bind->len );
2425-
}
2426-
else if ( bind->isOut && !bind->isInOut )
2427-
{
2428-
// Case for BIND_OUT
2429-
size = bind->maxSize;
2430-
}
2431-
2432-
if ( size > NJS_THRESHOLD_SIZE_PLSQL_STRING_ARG )
2433-
{
2434-
ExtBind* extBind = new ExtBind ( NJS_EXTBIND_LOB );
2435-
if ( !extBind )
2436-
{
2437-
executeBaton->error = NJSMessages::getErrorMsg
2438-
( errInsufficientMemory );
2439-
goto exitConvertStringOrBuffer2LOB;
2440-
}
24412415
extBind->fields.extLob.maxSize = bind->maxSize;
24422416

24432417
// Convert the input data into Temp LOB for IN and INOUT binds
@@ -2462,9 +2436,13 @@ void Connection::ConvertStringOrBuffer2LOB ( eBaton* executeBaton,
24622436

24632437
// Change the bind->type to LOB to handle more than 32k data
24642438
bind->type = ( bind->type == DpiVarChar ) ? DpiClob : DpiBlob;
2439+
2440+
}
2441+
else
2442+
{
2443+
executeBaton->error = NJSMessages::getErrorMsg
2444+
( errInsufficientMemory );
24652445
}
2466-
exitConvertStringOrBuffer2LOB:
2467-
;
24682446
}
24692447

24702448

@@ -2517,98 +2495,104 @@ void Connection::PrepareLOBsForBind ( eBaton* executeBaton, unsigned int index )
25172495
*/
25182496
void Connection::PrepareAndBind (eBaton* executeBaton)
25192497
{
2520-
executeBaton->dpistmt = executeBaton->dpiconn->getStmt(executeBaton->sql);
2521-
executeBaton->st = executeBaton->dpistmt->stmtType ();
2498+
executeBaton->dpistmt = executeBaton->dpiconn->
2499+
getStmt(executeBaton->sql);
2500+
executeBaton->st = executeBaton->dpistmt->stmtType ();
25222501
executeBaton->stmtIsReturning = executeBaton->dpistmt->isReturning ();
2523-
ExtBind *extBind = NULL ;
2502+
ExtBind *extBind = NULL ;
25242503

25252504
if(!executeBaton->binds.empty())
25262505
{
2527-
if(!executeBaton->binds[0]->key.empty())
2506+
for(unsigned int index = 0 ;index < executeBaton->binds.size();
2507+
index++)
25282508
{
2529-
for(unsigned int index = 0 ;index < executeBaton->binds.size();
2530-
index++)
2509+
if ( executeBaton->binds[index]->isOut &&
2510+
executeBaton->stmtIsReturning &&
2511+
executeBaton->binds[index]->type == dpi::DpiRSet )
25312512
{
2532-
if ( executeBaton->binds[index]->isOut &&
2533-
executeBaton->stmtIsReturning &&
2534-
executeBaton->binds[index]->type == dpi::DpiRSet )
2535-
{
2536-
executeBaton->error = NJSMessages::getErrorMsg (
2537-
errInvalidResultSet ) ;
2538-
goto exitPrepareAndBind;
2539-
}
2513+
executeBaton->error = NJSMessages::getErrorMsg (
2514+
errInvalidResultSet ) ;
2515+
goto exitPrepareAndBind;
2516+
}
25402517

2541-
// Process bind enhancements CLOB/BLOB As String/Buffer for PL/SQL
2542-
if ( ( executeBaton->st == DpiStmtBegin ||
2543-
executeBaton->st == DpiStmtDeclare ||
2544-
executeBaton->st == DpiStmtCall ) &&
2545-
( executeBaton->binds[index]->type == DpiVarChar ||
2546-
executeBaton->binds[index]->type == DpiRaw ) )
2518+
// Process bind enhancements CLOB/BLOB As String/Buffer for PL/SQL
2519+
/* Interested only in PL/SQL procedure calls */
2520+
if ( ( executeBaton->st == DpiStmtBegin ||
2521+
executeBaton->st == DpiStmtDeclare ||
2522+
executeBaton->st == DpiStmtCall ))
2523+
{
2524+
/* Interested only in STRING or RAW data type */
2525+
if ( executeBaton->binds[index]->type == DpiVarChar ||
2526+
executeBaton->binds[index]->type == DpiRaw )
25472527
{
2548-
ConvertStringOrBuffer2LOB ( executeBaton, index );
2528+
if ( IsValue2TempLob ( executeBaton, index ) )
2529+
{
2530+
ConvertStringOrBuffer2LOB ( executeBaton, index ) ;
2531+
}
25492532
}
2533+
}
2534+
2535+
// process LOB object for IN and INOUT bind
2536+
if ( ( executeBaton->binds[index]->isInOut ||
2537+
!executeBaton->binds[index]->isOut ) &&
2538+
( *(executeBaton->binds[index]->ind) != -1 ) &&
2539+
( executeBaton->binds[index]->type == DpiClob ||
2540+
executeBaton->binds[index]->type == DpiBlob ) )
2541+
{
2542+
PrepareLOBsForBind ( executeBaton, index );
2543+
}
2544+
2545+
// Allocate for OUT Binds
2546+
// For DML Returning, allocation happens through callback.
2547+
// binds->value is a pointer to a pointer in case of LOBs
2548+
if ( executeBaton->binds[index]->isOut &&
2549+
!executeBaton->stmtIsReturning &&
2550+
!executeBaton->binds[index]->value )
2551+
{
2552+
Connection::cbDynBufferAllocate ( executeBaton, false, 1, index );
25502553

25512554
if ( !executeBaton->error.empty() )
25522555
{
25532556
goto exitPrepareAndBind;
25542557
}
2558+
}
25552559

2556-
// process LOB object for IN and INOUT bind
2557-
if ( ( executeBaton->binds[index]->isInOut ||
2558-
!executeBaton->binds[index]->isOut ) &&
2559-
( *(executeBaton->binds[index]->ind) != -1 ) &&
2560-
( executeBaton->binds[index]->type == DpiClob ||
2561-
executeBaton->binds[index]->type == DpiBlob ) )
2562-
{
2563-
PrepareLOBsForBind ( executeBaton, index );
2564-
}
2565-
2566-
// Allocate for OUT Binds
2567-
// For DML Returning, allocation happens through callback.
2568-
// binds->value is a pointer to a pointer in case of LOBs
2569-
if ( executeBaton->binds[index]->isOut &&
2570-
!executeBaton->stmtIsReturning &&
2571-
!executeBaton->binds[index]->value )
2572-
{
2573-
Connection::cbDynBufferAllocate ( executeBaton,
2574-
false, 1, index );
2575-
}
2560+
// Convert v8::Date to Oracle DB Type for IN and IN/OUT binds
2561+
if ( executeBaton->binds[index]->type == DpiTimestampLTZ &&
2562+
( executeBaton->binds[index]->isInOut || // INOUT binds
2563+
!executeBaton->binds[index]->isOut ) ) // NOT OUT && NOT INOUT
2564+
{
2565+
Connection::UpdateDateValue ( executeBaton,
2566+
executeBaton->binds[index], 1 ) ;
2567+
}
25762568

2577-
// Convert v8::Date to Oracle DB Type for IN and IN/OUT binds
2578-
if ( executeBaton->binds[index]->type == DpiTimestampLTZ &&
2579-
( executeBaton->binds[index]->isInOut || // INOUT binds
2580-
!executeBaton->binds[index]->isOut ) ) // NOT OUT && NOT INOUT
2581-
{
2582-
Connection::UpdateDateValue ( executeBaton,
2583-
executeBaton->binds[index], 1 ) ;
2584-
}
2569+
if ( executeBaton->stmtIsReturning && executeBaton->binds[index]->isOut )
2570+
{
2571+
extBind = new ExtBind ( NJS_EXTBIND_DMLRETCB ) ;
25852572

2586-
if ( executeBaton->stmtIsReturning &&
2587-
executeBaton->binds[index]->isOut )
2573+
DpiBindCallbackCtx *ctx = extBind->fields.extDMLReturnCbCtx.ctx =
2574+
(DpiBindCallbackCtx *) malloc ( sizeof ( DpiBindCallbackCtx ) );
2575+
if ( !ctx )
25882576
{
2589-
extBind = new ExtBind ( NJS_EXTBIND_DMLRETCB ) ;
2590-
2591-
DpiBindCallbackCtx *ctx = extBind->fields.extDMLReturnCbCtx.ctx =
2592-
(DpiBindCallbackCtx *) malloc ( sizeof ( DpiBindCallbackCtx ) );
2593-
if ( !ctx )
2594-
{
2595-
executeBaton->error = NJSMessages::getErrorMsg (
2577+
executeBaton->error = NJSMessages::getErrorMsg (
25962578
errInsufficientMemory );
2597-
goto exitPrepareAndBind;
2598-
}
2579+
goto exitPrepareAndBind;
2580+
}
25992581

2600-
ctx->callbackfn = Connection::cbDynBufferGet;
2582+
ctx->callbackfn = Connection::cbDynBufferGet;
26012583
/* App specific callback */
2602-
ctx->data = (void *)executeBaton;
2584+
ctx->data = (void *)executeBaton;
26032585
/* Data for App specific callback */
2604-
ctx->bndpos = index; /* for callback, bind position zero based */
2605-
ctx->nrows = 0; /* # of rows - will be filled in later */
2606-
ctx->iter = 0; /* # iteration - will be filled in later */
2607-
ctx->dpistmt = executeBaton->dpistmt; /* DPI Statement object */
2586+
ctx->bndpos = index; /* for callback, bind position zero based */
2587+
ctx->nrows = 0; /* # of rows - will be filled in later */
2588+
ctx->iter = 0; /* # iteration - will be filled in later */
2589+
ctx->dpistmt = executeBaton->dpistmt; /* DPI Statement object */
26082590

2609-
executeBaton->extBinds[index] = extBind;
2610-
}
2591+
executeBaton->extBinds[index] = extBind;
2592+
}
26112593

2594+
if ( !executeBaton->binds[index]->key.empty () )
2595+
{
26122596
// Bind by name
26132597
executeBaton->dpistmt->bind(
26142598
(const unsigned char*)executeBaton->binds[index]->key.c_str(),
@@ -2630,83 +2614,8 @@ void Connection::PrepareAndBind (eBaton* executeBaton)
26302614
executeBaton->binds[index]->isOut) ?
26312615
extBind->fields.extDMLReturnCbCtx.ctx : NULL);
26322616
}
2633-
}
2634-
else
2635-
{
2636-
for(unsigned int index = 0 ;index < executeBaton->binds.size();
2637-
index++)
2617+
else
26382618
{
2639-
// Process bind enhancements CLOB/BLOB As String/Buffer for PL/SQL
2640-
if ( ( executeBaton->st == DpiStmtBegin ||
2641-
executeBaton->st == DpiStmtDeclare ||
2642-
executeBaton->st == DpiStmtCall ) &&
2643-
( executeBaton->binds[index]->type == DpiVarChar ||
2644-
executeBaton->binds[index]->type == DpiRaw ) )
2645-
{
2646-
ConvertStringOrBuffer2LOB ( executeBaton, index );
2647-
}
2648-
2649-
if ( !executeBaton->error.empty() )
2650-
{
2651-
goto exitPrepareAndBind;
2652-
}
2653-
2654-
// process LOB object for IN and INOUT bind
2655-
if ( ( executeBaton->binds[index]->isInOut ||
2656-
!executeBaton->binds[index]->isOut ) &&
2657-
( *(executeBaton->binds[index]->ind) != -1 ) &&
2658-
( executeBaton->binds[index]->type == DpiClob ||
2659-
executeBaton->binds[index]->type == DpiBlob ) )
2660-
{
2661-
PrepareLOBsForBind ( executeBaton, index );
2662-
}
2663-
2664-
// Allocate for OUT Binds
2665-
// For DML Returning, allocation happens through callback
2666-
if ( executeBaton->binds[index]->isOut &&
2667-
!executeBaton->stmtIsReturning &&
2668-
!executeBaton->binds[index]->value )
2669-
{
2670-
Connection::cbDynBufferAllocate ( executeBaton,
2671-
false, 1, index );
2672-
}
2673-
2674-
// Convert v8::Date to Oracle DB Type for IN and IN/OUT binds
2675-
if ( executeBaton->binds[index]->type == DpiTimestampLTZ &&
2676-
// InOut bind
2677-
(executeBaton->binds[index]->isInOut ||
2678-
// In bind
2679-
(!executeBaton->binds[index]->isOut &&
2680-
!executeBaton->binds[index]->isInOut)))
2681-
{
2682-
Connection::UpdateDateValue ( executeBaton,
2683-
executeBaton->binds[index], 1 ) ;
2684-
}
2685-
2686-
if ( executeBaton->stmtIsReturning &&
2687-
executeBaton->binds[index]->isOut )
2688-
{
2689-
extBind = new ExtBind ( NJS_EXTBIND_DMLRETCB );
2690-
DpiBindCallbackCtx *ctx = extBind->fields.extDMLReturnCbCtx.ctx =
2691-
(DpiBindCallbackCtx *) malloc ( sizeof ( DpiBindCallbackCtx ) );
2692-
2693-
if ( !ctx )
2694-
{
2695-
executeBaton->error = NJSMessages::getErrorMsg (
2696-
errInsufficientMemory );
2697-
goto exitPrepareAndBind;
2698-
}
2699-
ctx->callbackfn = Connection::cbDynBufferGet;
2700-
/* App specific callback */
2701-
ctx->data = (void *)executeBaton;
2702-
/* Data for App specific callback */
2703-
ctx->bndpos = index; /* for callback, bind position zero based */
2704-
ctx->nrows = 0; /* # of rows - will be filled in later */
2705-
ctx->iter = 0; /* # iteration - will be filled in later */
2706-
ctx->dpistmt = executeBaton->dpistmt; /* DPI Statement object */
2707-
executeBaton->extBinds[index] = extBind;
2708-
}
2709-
27102619
// Bind by position
27112620
executeBaton->dpistmt->bind(
27122621
index+1,executeBaton->binds[index]->type,

0 commit comments

Comments
 (0)