@@ -500,13 +500,6 @@ void Connection::GetBindUnit (Handle<Value> val, Bind* bind,
500
500
goto exitGetBindUnit;
501
501
}
502
502
503
- // For in binds allocate buffer for bind values (scalar).
504
- if ( dir != BIND_OUT )
505
- {
506
- Connection::cbDynBufferAllocate ( bind, 1 ) ;
507
- }
508
-
509
-
510
503
Local<Value> element = bind_unit->Get (String::New (" val" ));
511
504
switch (dir)
512
505
{
@@ -535,8 +528,6 @@ void Connection::GetBindUnit (Handle<Value> val, Bind* bind,
535
528
else
536
529
{
537
530
bind->isOut = false ;
538
- // This is IN Bind, allocate.
539
- Connection::cbDynBufferAllocate ( bind, 1 ) ;
540
531
Connection::GetInBindParams (val, bind, executeBaton, BIND_IN);
541
532
if (!executeBaton->error .empty ()) goto exitGetBindUnit;
542
533
}
@@ -585,11 +576,20 @@ void Connection::GetOutBindParams (unsigned short dataType, Bind* bind,
585
576
586
577
PARAMETERS:
587
578
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.
588
583
*/
589
584
void Connection::GetInBindParams (Handle<Value> v8val, Bind* bind,
590
585
eBaton* executeBaton, BindType type)
591
586
{
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
+
592
591
*(bind->ind ) = 0 ;
592
+
593
593
if (v8val->IsUndefined () || v8val->IsNull ())
594
594
{
595
595
bind->value = NULL ;
@@ -739,7 +739,7 @@ void Connection::Async_Execute (uv_work_t *req)
739
739
row ++ )
740
740
{
741
741
if (executeBaton->binds [b]->maxSize <
742
- executeBaton->binds [b]->len [row])
742
+ (DPI_SZ_TYPE) executeBaton->binds [b]->len2 [row])
743
743
{
744
744
/* Report insufficient buffer for OUT binds */
745
745
executeBaton->error =
@@ -778,7 +778,19 @@ void Connection::Async_Execute (uv_work_t *req)
778
778
}
779
779
catch (dpi::Exception& e)
780
780
{
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
+ }
782
794
}
783
795
exitAsyncExecute:
784
796
;
@@ -815,23 +827,24 @@ void Connection::PrepareAndBind (eBaton* executeBaton)
815
827
errInvalidBindDataType, 2 );
816
828
return ;
817
829
}
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
+
818
841
819
842
// Convert v8::Date to Oracle DB Type
820
843
if ( executeBaton->binds [index]->type == DpiTimestampLTZ )
821
844
{
822
845
Connection::UpdateDateValue ( executeBaton ) ;
823
846
}
824
847
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
-
835
848
// Bind by name
836
849
executeBaton->dpistmt ->bind (
837
850
(const unsigned char *)executeBaton->binds [index]->key .c_str (),
@@ -867,6 +880,16 @@ void Connection::PrepareAndBind (eBaton* executeBaton)
867
880
return ;
868
881
}
869
882
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
+
870
893
if ( executeBaton->binds [index]->type == DpiTimestampLTZ )
871
894
{
872
895
Connection::UpdateDateValue ( executeBaton ) ;
@@ -1243,7 +1266,7 @@ Handle<Value> Connection::GetArrayValue ( Bind *binds, unsigned long count )
1243
1266
( binds->ind [index] == -1 ) ? Null () :
1244
1267
String::New ((char *)binds->value +
1245
1268
(index * binds->maxSize ),
1246
- binds->len [index]));
1269
+ binds->len2 [index]));
1247
1270
break ;
1248
1271
case dpi::DpiInteger:
1249
1272
arrVal->Set ( index,
@@ -1296,15 +1319,10 @@ Handle<Value> Connection::GetOutBinds (eBaton* executeBaton)
1296
1319
if ( executeBaton->binds [0 ]->key .empty () )
1297
1320
{
1298
1321
// 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
- }
1305
1322
return scope.Close ( GetOutBindArray ( executeBaton->binds ,
1323
+ executeBaton->numOutBinds ,
1306
1324
executeBaton->stmtIsReturning ,
1307
- outCount ));
1325
+ executeBaton-> rowsAffected ));
1308
1326
}
1309
1327
else
1310
1328
{
@@ -1358,8 +1376,8 @@ Handle<Value> Connection::GetOutBindArray ( std::vector<Bind*> &binds,
1358
1376
val = Connection::GetArrayValue ( binds[index], rowcount );
1359
1377
}
1360
1378
arrayBinds->Set ( it, val );
1379
+ it ++;
1361
1380
}
1362
- it++;
1363
1381
}
1364
1382
return scope.Close (arrayBinds);
1365
1383
}
@@ -1856,7 +1874,8 @@ void Connection::UpdateDateValue ( eBaton * ebaton )
1856
1874
callback/Utility function to allocate for BIND values (IN & OUT).
1857
1875
This has been consolidated to a callback/utility funciton so that
1858
1876
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()
1860
1879
For OUT binds the allocation happens in PrepareAndBind ().
1861
1880
For OUT binds using RETURNING INTO clause, this function is used as
1862
1881
callback.
@@ -1868,30 +1887,59 @@ void Connection::UpdateDateValue ( eBaton * ebaton )
1868
1887
RETURNS
1869
1888
-None-
1870
1889
*/
1871
- void Connection::cbDynBufferAllocate ( void *ctx, DPI_SZ_TYPE nRows )
1890
+ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
1891
+ unsigned int nRows )
1872
1892
{
1873
1893
Bind *bind = (Bind *)ctx;
1874
1894
1875
1895
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
+ }
1877
1905
1878
1906
switch ( bind->type )
1879
1907
{
1880
1908
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
+ }
1883
1919
break ;
1884
1920
1885
1921
case dpi::DpiInteger:
1886
1922
bind->value = ( int *) malloc ( sizeof (int ) * nRows ) ;
1923
+ if ( !dmlReturning )
1924
+ {
1925
+ *(bind->len ) = sizeof ( int ) ;
1926
+ }
1887
1927
break ;
1888
1928
1889
1929
case dpi::DpiUnsignedInteger:
1890
1930
bind->value = ( unsigned int *)malloc ( sizeof ( unsigned int ) * nRows );
1931
+ if ( !dmlReturning )
1932
+ {
1933
+ *(bind->len ) = sizeof ( unsigned int ) ;
1934
+ }
1891
1935
break ;
1892
1936
1893
1937
case dpi::DpiDouble:
1894
1938
bind->value = ( double *)malloc ( sizeof ( double ) * nRows );
1939
+ if ( !dmlReturning )
1940
+ {
1941
+ *(bind->len ) = sizeof ( double ) ;
1942
+ }
1895
1943
break ;
1896
1944
1897
1945
case dpi::DpiTimestampLTZ:
@@ -1916,21 +1964,22 @@ void Connection::cbDynBufferAllocate ( void *ctx, DPI_SZ_TYPE nRows )
1916
1964
nRows (IN) # of rows (after execution, so knows rows-affected)
1917
1965
index (IN) row index
1918
1966
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
1921
1969
rcode (INOUT) return code - not used
1922
1970
piecep (INOUT) for piece wise operations.
1923
1971
1924
1972
RETURN
1925
1973
0. (Any non zero value to indicate errors).
1926
1974
1927
1975
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)
1929
1978
*/
1930
1979
1931
1980
int Connection::cbDynBufferGet ( void *ctx, DPI_SZ_TYPE nRows,
1932
1981
unsigned long iter, unsigned long index,
1933
- dvoid **bufpp, void **alenp , void **indp ,
1982
+ dvoid **bufpp, void **alenpp , void **indpp ,
1934
1983
unsigned short **rcode, unsigned char *piecep)
1935
1984
{
1936
1985
Bind *bind = (Bind *)ctx;
@@ -1948,15 +1997,16 @@ int Connection::cbDynBufferGet ( void *ctx, DPI_SZ_TYPE nRows,
1948
1997
// First time callback, allocate the buffer(s).
1949
1998
if ( index == 0 )
1950
1999
{
1951
- Connection::cbDynBufferAllocate (ctx, nRows );
2000
+ Connection::cbDynBufferAllocate (ctx, true , nRows );
1952
2001
}
1953
2002
2003
+ bind->ind [index] = -1 ;
1954
2004
1955
2005
// Find block of memory for this index
1956
2006
switch ( bind->type )
1957
2007
{
1958
2008
case dpi::DpiVarChar:
1959
- bind->len [index] = ( bind->maxSize + 1 ) ;
2009
+ bind->len2 [index] = bind->maxSize ;
1960
2010
/* 1 extra char for EOS, 1 extra to determine insufficient buf later */
1961
2011
*bufpp = (void *)&(((char *)bind->value )[ (bind->maxSize ) * index]);
1962
2012
/* 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,
1966
2016
*piecep = OCI_FIRST_PIECE;
1967
2017
break ;
1968
2018
case dpi::DpiInteger:
1969
- bind->len [index] = sizeof ( int ) ;
2019
+ bind->len2 [index] = sizeof ( int ) ;
1970
2020
*bufpp = ( void *)&(((int *)bind->value )[index]);
1971
2021
break ;
1972
2022
case dpi::DpiUnsignedInteger:
1973
- bind->len [index] = sizeof ( unsigned int ) ;
2023
+ bind->len2 [index] = sizeof ( unsigned int ) ;
1974
2024
*bufpp = ( void *)&(((unsigned int *)bind->value )[index]);
1975
2025
break ;
1976
2026
1977
2027
case dpi::DpiDouble:
1978
- bind->len [index] = sizeof ( double ) ;
2028
+ bind->len2 [index] = sizeof ( double ) ;
1979
2029
*bufpp = (void *)&(((double *)bind->value )[index]);
1980
2030
break ;
1981
2031
@@ -1984,8 +2034,8 @@ int Connection::cbDynBufferGet ( void *ctx, DPI_SZ_TYPE nRows,
1984
2034
break ;
1985
2035
}
1986
2036
1987
- *alenp = &(bind->len [index]);
1988
- *indp = &(bind->ind [index]);
2037
+ *alenpp = &(bind->len2 [index]);
2038
+ *indpp = &(bind->ind [index]);
1989
2039
}
1990
2040
else
1991
2041
{
0 commit comments