@@ -500,13 +500,6 @@ void Connection::GetBindUnit (Handle<Value> val, Bind* bind,
500500 goto exitGetBindUnit;
501501 }
502502
503- // For in binds allocate buffer for bind values (scalar).
504- if ( dir != BIND_OUT )
505- {
506- Connection::cbDynBufferAllocate ( bind, 1 ) ;
507- }
508-
509-
510503 Local<Value> element = bind_unit->Get (String::New (" val" ));
511504 switch (dir)
512505 {
@@ -535,8 +528,6 @@ void Connection::GetBindUnit (Handle<Value> val, Bind* bind,
535528 else
536529 {
537530 bind->isOut = false ;
538- // This is IN Bind, allocate.
539- Connection::cbDynBufferAllocate ( bind, 1 ) ;
540531 Connection::GetInBindParams (val, bind, executeBaton, BIND_IN);
541532 if (!executeBaton->error .empty ()) goto exitGetBindUnit;
542533 }
@@ -585,11 +576,20 @@ void Connection::GetOutBindParams (unsigned short dataType, Bind* bind,
585576
586577 PARAMETERS:
587578 Handle value, bind struct, eBaton struct
579+
580+ NOTE:
581+ For IN Bind only len field field is used, and for only a scalar value now,
582+ allocate for one unit.
588583*/
589584void Connection::GetInBindParams (Handle<Value> v8val, Bind* bind,
590585 eBaton* executeBaton, BindType type)
591586{
587+ /* Allocate for scalar indicator & length */
588+ bind->ind = (short *)malloc ( sizeof ( short ) );
589+ bind->len = (DPI_BUFLEN_TYPE *)malloc ( sizeof ( DPI_BUFLEN_TYPE ) );
590+
592591 *(bind->ind ) = 0 ;
592+
593593 if (v8val->IsUndefined () || v8val->IsNull ())
594594 {
595595 bind->value = NULL ;
@@ -739,7 +739,7 @@ void Connection::Async_Execute (uv_work_t *req)
739739 row ++ )
740740 {
741741 if (executeBaton->binds [b]->maxSize <
742- executeBaton->binds [b]->len [row])
742+ (DPI_SZ_TYPE) executeBaton->binds [b]->len2 [row])
743743 {
744744 /* Report insufficient buffer for OUT binds */
745745 executeBaton->error =
@@ -778,7 +778,19 @@ void Connection::Async_Execute (uv_work_t *req)
778778 }
779779 catch (dpi::Exception& e)
780780 {
781- executeBaton->error = std::string (e.what ());
781+ // In Case of DML Returning, if the buffer is small, and if the callback
782+ // is called multiple times, an ORA error 24343 was reported. Converting
783+ // that error to errInsufficientBufferForBinds.
784+ if ( !executeBaton->stmtIsReturning &&
785+ (e.errnum () != 24343 ) )
786+ {
787+ executeBaton->error = std::string (e.what ());
788+ }
789+ else
790+ {
791+ executeBaton->error = NJSMessages::getErrorMsg (
792+ errInsufficientBufferForBinds ) ;
793+ }
782794 }
783795 exitAsyncExecute:
784796 ;
@@ -815,23 +827,24 @@ void Connection::PrepareAndBind (eBaton* executeBaton)
815827 errInvalidBindDataType, 2 );
816828 return ;
817829 }
830+
831+ // Allocate for OUT Binds
832+ // For DML Returning, allocation happens through callback.
833+ if ( executeBaton->binds [index]->isOut &&
834+ !executeBaton->stmtIsReturning &&
835+ !executeBaton->binds [index]->value )
836+ {
837+ Connection::cbDynBufferAllocate ( executeBaton->binds [index],
838+ false , 1 );
839+ }
840+
818841
819842 // Convert v8::Date to Oracle DB Type
820843 if ( executeBaton->binds [index]->type == DpiTimestampLTZ )
821844 {
822845 Connection::UpdateDateValue ( executeBaton ) ;
823846 }
824847
825- // For OUT binds (with NO RETURNING INTO clause allocate for
826- // scalar value. For RETURNING INTO clause, callback will allocate
827- // NOTE: For IN Binds, the allocation & initialization happens
828- // in GetBindUnit itself.
829- if ( !executeBaton->stmtIsReturning &&
830- executeBaton->binds [index]->isOut )
831- {
832- Connection::cbDynBufferAllocate ( executeBaton->binds [index], 1 );
833- }
834-
835848 // Bind by name
836849 executeBaton->dpistmt ->bind (
837850 (const unsigned char *)executeBaton->binds [index]->key .c_str (),
@@ -867,6 +880,16 @@ void Connection::PrepareAndBind (eBaton* executeBaton)
867880 return ;
868881 }
869882
883+ // Allocate for OUT Binds
884+ // For DML Returning, allocation happens through callback
885+ if ( executeBaton->binds [index]->isOut &&
886+ !executeBaton->stmtIsReturning &&
887+ !executeBaton->binds [index]->value )
888+ {
889+ Connection::cbDynBufferAllocate ( executeBaton->binds [index],
890+ false , 1 );
891+ }
892+
870893 if ( executeBaton->binds [index]->type == DpiTimestampLTZ )
871894 {
872895 Connection::UpdateDateValue ( executeBaton ) ;
@@ -1243,7 +1266,7 @@ Handle<Value> Connection::GetArrayValue ( Bind *binds, unsigned long count )
12431266 ( binds->ind [index] == -1 ) ? Null () :
12441267 String::New ((char *)binds->value +
12451268 (index * binds->maxSize ),
1246- binds->len [index]));
1269+ binds->len2 [index]));
12471270 break ;
12481271 case dpi::DpiInteger:
12491272 arrVal->Set ( index,
@@ -1296,15 +1319,10 @@ Handle<Value> Connection::GetOutBinds (eBaton* executeBaton)
12961319 if ( executeBaton->binds [0 ]->key .empty () )
12971320 {
12981321 // Binds as JS array
1299- unsigned int outCount = 0 ;
1300- for (unsigned int index = 0 ; index < executeBaton->binds .size (); index++)
1301- {
1302- if (executeBaton->binds [index]->isOut )
1303- outCount++;
1304- }
13051322 return scope.Close ( GetOutBindArray ( executeBaton->binds ,
1323+ executeBaton->numOutBinds ,
13061324 executeBaton->stmtIsReturning ,
1307- outCount ));
1325+ executeBaton-> rowsAffected ));
13081326 }
13091327 else
13101328 {
@@ -1358,8 +1376,8 @@ Handle<Value> Connection::GetOutBindArray ( std::vector<Bind*> &binds,
13581376 val = Connection::GetArrayValue ( binds[index], rowcount );
13591377 }
13601378 arrayBinds->Set ( it, val );
1379+ it ++;
13611380 }
1362- it++;
13631381 }
13641382 return scope.Close (arrayBinds);
13651383}
@@ -1856,7 +1874,8 @@ void Connection::UpdateDateValue ( eBaton * ebaton )
18561874 callback/Utility function to allocate for BIND values (IN & OUT).
18571875 This has been consolidated to a callback/utility funciton so that
18581876 allocation happens only once.
1859- For IN binds, the allocation and initialization happens in GetBindUnit ()
1877+ For IN binds, the allocation and initialization happens in
1878+ GetInBindParams()
18601879 For OUT binds the allocation happens in PrepareAndBind ().
18611880 For OUT binds using RETURNING INTO clause, this function is used as
18621881 callback.
@@ -1868,30 +1887,59 @@ void Connection::UpdateDateValue ( eBaton * ebaton )
18681887 RETURNS
18691888 -None-
18701889*/
1871- void Connection::cbDynBufferAllocate ( void *ctx, DPI_SZ_TYPE nRows )
1890+ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
1891+ unsigned int nRows )
18721892{
18731893 Bind *bind = (Bind *)ctx;
18741894
18751895 bind->ind = (short *)malloc ( nRows * sizeof ( short ) ) ;
1876- bind->len = (DPI_BUFLEN_TYPE *)malloc ( nRows * sizeof ( DPI_BUFLEN_TYPE ) );
1896+ if ( dmlReturning )
1897+ {
1898+ bind->len2 = ( unsigned int *)malloc ( nRows * sizeof ( unsigned int ) );
1899+ }
1900+ else
1901+ {
1902+ bind->len = (DPI_BUFLEN_TYPE *)malloc ( nRows *
1903+ sizeof ( DPI_BUFLEN_TYPE ) );
1904+ }
18771905
18781906 switch ( bind->type )
18791907 {
18801908 case dpi::DpiVarChar:
1881- /* one extra char for EOS; 1 more to determine insufficient buffer later */
1882- bind->value = (char *)malloc ( ( bind->maxSize + 2 ) * nRows ) ;
1909+ /* one extra char for EOS */
1910+ bind->value = (char *)malloc ( ( bind->maxSize + 1 ) * nRows ) ;
1911+ if ( dmlReturning )
1912+ {
1913+ *(bind->len2 ) = bind->maxSize ;
1914+ }
1915+ else
1916+ {
1917+ *(bind->len ) = bind->maxSize ;
1918+ }
18831919 break ;
18841920
18851921 case dpi::DpiInteger:
18861922 bind->value = ( int *) malloc ( sizeof (int ) * nRows ) ;
1923+ if ( !dmlReturning )
1924+ {
1925+ *(bind->len ) = sizeof ( int ) ;
1926+ }
18871927 break ;
18881928
18891929 case dpi::DpiUnsignedInteger:
18901930 bind->value = ( unsigned int *)malloc ( sizeof ( unsigned int ) * nRows );
1931+ if ( !dmlReturning )
1932+ {
1933+ *(bind->len ) = sizeof ( unsigned int ) ;
1934+ }
18911935 break ;
18921936
18931937 case dpi::DpiDouble:
18941938 bind->value = ( double *)malloc ( sizeof ( double ) * nRows );
1939+ if ( !dmlReturning )
1940+ {
1941+ *(bind->len ) = sizeof ( double ) ;
1942+ }
18951943 break ;
18961944
18971945 case dpi::DpiTimestampLTZ:
@@ -1916,21 +1964,22 @@ void Connection::cbDynBufferAllocate ( void *ctx, DPI_SZ_TYPE nRows )
19161964 nRows (IN) # of rows (after execution, so knows rows-affected)
19171965 index (IN) row index
19181966 bufpp (INOUT) buffer for the cell
1919- alenp (INOUT) buffer for actual length
1920- indp (INOUT) buffer for the indicator
1967+ alenpp (INOUT) buffer for actual length
1968+ indpp (INOUT) buffer for the indicator
19211969 rcode (INOUT) return code - not used
19221970 piecep (INOUT) for piece wise operations.
19231971
19241972 RETURN
19251973 0. (Any non zero value to indicate errors).
19261974
19271975 NOTE:
1928- OCI does not support DATE/TIMESTAMP for dynamic Binding.
1976+ 1. DATE/TIMESTAMP not supported
1977+ 2. using bind->len2 for DML returning (not bind->len)
19291978*/
19301979
19311980int Connection::cbDynBufferGet ( void *ctx, DPI_SZ_TYPE nRows,
19321981 unsigned long iter, unsigned long index,
1933- dvoid **bufpp, void **alenp , void **indp ,
1982+ dvoid **bufpp, void **alenpp , void **indpp ,
19341983 unsigned short **rcode, unsigned char *piecep)
19351984{
19361985 Bind *bind = (Bind *)ctx;
@@ -1948,15 +1997,16 @@ int Connection::cbDynBufferGet ( void *ctx, DPI_SZ_TYPE nRows,
19481997 // First time callback, allocate the buffer(s).
19491998 if ( index == 0 )
19501999 {
1951- Connection::cbDynBufferAllocate (ctx, nRows );
2000+ Connection::cbDynBufferAllocate (ctx, true , nRows );
19522001 }
19532002
2003+ bind->ind [index] = -1 ;
19542004
19552005 // Find block of memory for this index
19562006 switch ( bind->type )
19572007 {
19582008 case dpi::DpiVarChar:
1959- bind->len [index] = ( bind->maxSize + 1 ) ;
2009+ bind->len2 [index] = bind->maxSize ;
19602010 /* 1 extra char for EOS, 1 extra to determine insufficient buf later */
19612011 *bufpp = (void *)&(((char *)bind->value )[ (bind->maxSize ) * index]);
19622012 /* Buffer provided by the application could be small, in this case to
@@ -1966,16 +2016,16 @@ int Connection::cbDynBufferGet ( void *ctx, DPI_SZ_TYPE nRows,
19662016 *piecep = OCI_FIRST_PIECE;
19672017 break ;
19682018 case dpi::DpiInteger:
1969- bind->len [index] = sizeof ( int ) ;
2019+ bind->len2 [index] = sizeof ( int ) ;
19702020 *bufpp = ( void *)&(((int *)bind->value )[index]);
19712021 break ;
19722022 case dpi::DpiUnsignedInteger:
1973- bind->len [index] = sizeof ( unsigned int ) ;
2023+ bind->len2 [index] = sizeof ( unsigned int ) ;
19742024 *bufpp = ( void *)&(((unsigned int *)bind->value )[index]);
19752025 break ;
19762026
19772027 case dpi::DpiDouble:
1978- bind->len [index] = sizeof ( double ) ;
2028+ bind->len2 [index] = sizeof ( double ) ;
19792029 *bufpp = (void *)&(((double *)bind->value )[index]);
19802030 break ;
19812031
@@ -1984,8 +2034,8 @@ int Connection::cbDynBufferGet ( void *ctx, DPI_SZ_TYPE nRows,
19842034 break ;
19852035 }
19862036
1987- *alenp = &(bind->len [index]);
1988- *indp = &(bind->ind [index]);
2037+ *alenpp = &(bind->len2 [index]);
2038+ *indpp = &(bind->ind [index]);
19892039 }
19902040 else
19912041 {
0 commit comments