@@ -834,14 +834,13 @@ void Connection::GetBindUnit (Local<Value> val, Bind* bind, bool array,
834834 case NJS_BIND_IN :
835835 bind->isOut = false ;
836836 bind->isInOut = false ;
837- Connection::GetInBindParams (element, bind, executeBaton, NJS_BIND_IN );
837+ Connection::GetInBindParams (element, bind, executeBaton );
838838 if (!executeBaton->error .empty ()) goto exitGetBindUnit;
839839 break ;
840840 case NJS_BIND_INOUT :
841841 bind->isOut = true ;
842842 bind->isInOut = true ;
843- Connection::GetInBindParams (element, bind, executeBaton,
844- NJS_BIND_INOUT);
843+ Connection::GetInBindParams (element, bind, executeBaton );
845844 if (!executeBaton->error .empty ()) goto exitGetBindUnit;
846845 break ;
847846 case NJS_BIND_OUT :
@@ -866,7 +865,7 @@ void Connection::GetBindUnit (Local<Value> val, Bind* bind, bool array,
866865 else
867866 {
868867 bind->isOut = false ;
869- Connection::GetInBindParams (val, bind, executeBaton, NJS_BIND_IN );
868+ Connection::GetInBindParams (val, bind, executeBaton );
870869 if (!executeBaton->error .empty ()) goto exitGetBindUnit;
871870 }
872871 exitGetBindUnit:
@@ -957,17 +956,17 @@ void Connection::GetOutBindParams (unsigned short dataType, Bind* bind,
957956 allocate for one unit.
958957*/
959958void Connection::GetInBindParams (Local<Value> v8val, Bind* bind,
960- eBaton* executeBaton, BindType type )
959+ eBaton* executeBaton )
961960{
962961 Nan::HandleScope scope;
963962
964963 if (v8val->IsArray () )
965964 {
966- GetInBindParamsArray (Local<Array>::Cast (v8val), bind, executeBaton, type );
965+ GetInBindParamsArray (Local<Array>::Cast (v8val), bind, executeBaton );
967966 }
968967 else
969968 {
970- GetInBindParamsScalar (v8val, bind, executeBaton, type );
969+ GetInBindParamsScalar (v8val, bind, executeBaton );
971970 }
972971}
973972
@@ -984,20 +983,54 @@ void Connection::GetInBindParams(Local<Value> v8val, Bind* bind,
984983 allocate for one unit.
985984*/
986985void Connection::GetInBindParamsScalar (Local<Value> v8val, Bind* bind,
987- eBaton* executeBaton, BindType type )
986+ eBaton* executeBaton)
988987{
989988 Nan::HandleScope scope;
990- ValueType dataType = NJS_VALUETYPE_INVALID;
989+ ValueType valType = NJS_VALUETYPE_INVALID;
990+ boolean v8valNULL ; /* whether given v8 value is NULL/Undefined */
991991
992992 /* Allocate for scalar indicator & length */
993993 bind->ind = (short *)malloc ( sizeof ( short ) );
994994 bind->len = (DPI_BUFLEN_TYPE *)malloc ( sizeof ( DPI_BUFLEN_TYPE ) );
995995
996996 *(bind->ind ) = 0 ;
997997
998- dataType = Connection::GetValueType ( v8val );
998+ valType = Connection::GetValueType ( v8val );
999+ v8valNULL = ( valType == NJS_VALUETYPE_NULL ) ? true : false ;
9991000
1000- switch ( dataType )
1001+ /*
1002+ * In case of INOUT Bind, if given value is NULL
1003+ * make use of specified OUT bind type
1004+ */
1005+ if ( v8valNULL && bind->isInOut )
1006+ {
1007+ switch ( bind->type )
1008+ {
1009+ case NJS_DATATYPE_STR:
1010+ valType = NJS_VALUETYPE_STRING;
1011+ break ;
1012+
1013+ case NJS_DATATYPE_NUM:
1014+ valType = NJS_VALUETYPE_NUMBER;
1015+ break ;
1016+
1017+ case NJS_DATATYPE_DATE:
1018+ valType = NJS_VALUETYPE_DATE;
1019+ break ;
1020+
1021+ case NJS_DATATYPE_BUFFER:
1022+ valType = NJS_VALUETYPE_OBJECT; /* DB RAW Type, v8 Buffer */
1023+ break ;
1024+
1025+ // The following types are NOT supported as IN BIND (for INOUT) ignore
1026+ case NJS_DATATYPE_CURSOR:
1027+ case NJS_DATATYPE_CLOB:
1028+ case NJS_DATATYPE_BLOB:
1029+ break ;
1030+ }
1031+ }
1032+
1033+ switch ( valType )
10011034 {
10021035 case NJS_VALUETYPE_NULL:
10031036 bind->value = NULL ;
@@ -1014,10 +1047,16 @@ void Connection::GetInBindParamsScalar(Local<Value> v8val, Bind* bind,
10141047 goto exitGetInBindParamsScalar;
10151048 }
10161049
1017- v8::String::Utf8Value str (v8val->ToString ());
1050+ /*
1051+ * Use empty string in case of IN value is NULL, but overriden for
1052+ * INOUT binds
1053+ */
1054+ v8::String::Utf8Value str ( v8valNULL ?
1055+ Nan::New<v8::String> ( " " , 0 ).ToLocalChecked () :
1056+ v8val->ToString ());
10181057
10191058 bind->type = dpi::DpiVarChar;
1020- if (type == NJS_BIND_INOUT )
1059+ if ( bind-> isInOut )
10211060 {
10221061 *(bind->len ) = str.length ();
10231062 }
@@ -1053,7 +1092,7 @@ void Connection::GetInBindParamsScalar(Local<Value> v8val, Bind* bind,
10531092 bind->type = dpi::DpiInteger;
10541093 bind->maxSize = *(bind->len ) = sizeof (int );
10551094 bind->value = (int *)malloc (*(bind->len ));
1056- *(int *)(bind->value ) = v8val->ToInt32 ()->Value ();
1095+ *(int *)(bind->value ) = v8valNULL ? 0 : v8val->ToInt32 ()->Value ();
10571096 break ;
10581097
10591098 case NJS_VALUETYPE_UINTEGER:
@@ -1066,7 +1105,8 @@ void Connection::GetInBindParamsScalar(Local<Value> v8val, Bind* bind,
10661105 bind->type = dpi::DpiUnsignedInteger;
10671106 bind->maxSize = *(bind->len ) = sizeof (unsigned int );
10681107 bind->value = (unsigned int *)malloc (*(bind->len ));
1069- *(unsigned int *)(bind->value ) = v8val->ToUint32 ()->Value ();
1108+ *(unsigned int *)(bind->value ) = v8valNULL ? 0 :
1109+ v8val->ToUint32 ()->Value ();
10701110 break ;
10711111
10721112 case NJS_VALUETYPE_NUMBER:
@@ -1079,7 +1119,7 @@ void Connection::GetInBindParamsScalar(Local<Value> v8val, Bind* bind,
10791119 bind->type = dpi::DpiDouble;
10801120 bind->maxSize = *(bind->len ) = sizeof (double );
10811121 bind->value = (double *)malloc (*(bind->len ));
1082- *(double *)(bind->value ) = v8val->NumberValue ();
1122+ *(double *)(bind->value ) = v8valNULL ? 0 : v8val->NumberValue ();
10831123 break ;
10841124
10851125 case NJS_VALUETYPE_DATE:
@@ -1104,11 +1144,23 @@ void Connection::GetInBindParamsScalar(Local<Value> v8val, Bind* bind,
11041144 case NJS_VALUETYPE_OBJECT:
11051145 {
11061146 Local<Object> obj = v8val->ToObject ();
1107- if (Buffer::HasInstance (obj))
1147+
1148+ if ( v8valNULL && bind->isInOut )
1149+ {
1150+ /*
1151+ * In case of RAW/Buffer type and INOUT Bind, if IN value is NULL,
1152+ * allocate based on OUT type, maxSize
1153+ */
1154+ bind->type = dpi::DpiRaw;
1155+ *( bind->len ) = ( DPI_BUFLEN_TYPE ) (( bind->isInOut ) ?
1156+ bind->maxSize : 0 );
1157+ bind->value = ( char *) malloc ( *(bind -> len ) );
1158+ }
1159+ else if (Buffer::HasInstance (obj))
11081160 {
11091161 size_t bufLen = Buffer::Length (obj);
11101162 bind->type = dpi::DpiRaw;
1111- if (type == NJS_BIND_INOUT )
1163+ if ( bind-> isInOut )
11121164 {
11131165 *(bind->len ) = (DPI_BUFLEN_TYPE) bufLen;
11141166 }
@@ -1160,7 +1212,7 @@ void Connection::GetInBindParamsScalar(Local<Value> v8val, Bind* bind,
11601212 allocate for one unit.
11611213*/
11621214void Connection::GetInBindParamsArray (Local<Array> va8vals, Bind *bind,
1163- eBaton *executeBaton, BindType type )
1215+ eBaton *executeBaton )
11641216{
11651217 Nan::HandleScope scope;
11661218 size_t arrayElementSize = 0 ; // actual array element size
@@ -3906,8 +3958,9 @@ void Connection::v8Date2OraDate(v8::Local<v8::Value> val, Bind *bind)
39063958 Local<Date> date = val.As <Date>(); // Expects to be of v8::Date type
39073959
39083960 // Get the number of seconds from 1970-1-1 0:0:0
3909- *(long double *)(bind->extvalue ) = date->NumberValue ();
3910-
3961+ // In case given value is NULL/Undefined, set it to 0
3962+ *(long double *)(bind->extvalue ) = (val->IsNull () || val->IsUndefined ()) ?
3963+ 0 : date->NumberValue ();
39113964}
39123965
39133966/* **************************************************************************/
@@ -3979,45 +4032,59 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
39794032
39804033 Connection::AllocateBindArray ( bind->type , bind, executeBaton,
39814034 &arrayElementSize );
3982- return ;
4035+ goto exitcbDynBufferAllocate ;
39834036 }
39844037
39854038
39864039 if ( NJS_SIZE_T_OVERFLOW ( sizeof ( short ), nRows ) )
39874040 {
39884041 executeBaton->error = NJSMessages::getErrorMsg ( errResultsTooLarge );
3989- return ;
4042+ goto exitcbDynBufferAllocate ;
39904043 }
39914044 else
39924045 {
3993- bind->ind = (short *)malloc ( (size_t )nRows * sizeof ( short ) ) ;
3994- if ( !bind->ind )
4046+ if ( !bind->ind )
39954047 {
3996- executeBaton->error = NJSMessages::getErrorMsg ( errInsufficientMemory );
3997- return ;
4048+ bind->ind = (short *)malloc ( (size_t )nRows * sizeof ( short ) ) ;
4049+ if ( !bind->ind )
4050+ {
4051+ executeBaton->error = NJSMessages::getErrorMsg (
4052+ errInsufficientMemory );
4053+ goto exitcbDynBufferAllocate;
4054+ }
39984055 }
39994056 }
40004057 if ( dmlReturning )
40014058 {
40024059 if ( NJS_SIZE_T_OVERFLOW ( sizeof ( unsigned int ), nRows ) )
40034060 {
40044061 executeBaton->error = NJSMessages::getErrorMsg ( errResultsTooLarge );
4005- return ;
4062+ goto exitcbDynBufferAllocate ;
40064063 }
40074064 else
40084065 {
40094066 bind->len2 = ( unsigned int *)malloc ( nRows * sizeof ( unsigned int ) );
40104067 if ( !bind->len2 )
40114068 {
4012- executeBaton->error = NJSMessages::getErrorMsg ( errInsufficientMemory );
4013- return ;
4069+ executeBaton->error = NJSMessages::getErrorMsg (
4070+ errInsufficientMemory );
4071+ goto exitcbDynBufferAllocate;
40144072 }
40154073 }
40164074 }
40174075 else
40184076 {
4019- bind->len = (DPI_BUFLEN_TYPE *)malloc ( nRows *
4020- sizeof ( DPI_BUFLEN_TYPE ) );
4077+ if ( !bind->len )
4078+ {
4079+ bind->len = (DPI_BUFLEN_TYPE *)malloc ( nRows *
4080+ sizeof ( DPI_BUFLEN_TYPE ) );
4081+ if ( !bind->len )
4082+ {
4083+ executeBaton->error = NJSMessages::getErrorMsg (
4084+ errInsufficientMemory ) ;
4085+ goto exitcbDynBufferAllocate;
4086+ }
4087+ }
40214088 }
40224089
40234090 switch ( bind->type )
@@ -4028,7 +4095,7 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
40284095 if ( NJS_SIZE_T_OVERFLOW ( (bind->maxSize + 1 ), nRows) )
40294096 {
40304097 executeBaton->error = NJSMessages::getErrorMsg ( errResultsTooLarge );
4031- return ;
4098+ goto exitcbDynBufferAllocate ;
40324099 }
40334100 else
40344101 {
@@ -4037,7 +4104,7 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
40374104 {
40384105 executeBaton->error = NJSMessages::getErrorMsg (
40394106 errInsufficientMemory);
4040- return ;
4107+ goto exitcbDynBufferAllocate ;
40414108 }
40424109 }
40434110
@@ -4055,7 +4122,7 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
40554122 if ( NJS_SIZE_T_OVERFLOW ( sizeof (int ), nRows) )
40564123 {
40574124 executeBaton->error = NJSMessages::getErrorMsg ( errResultsTooLarge );
4058- return ;
4125+ goto exitcbDynBufferAllocate ;
40594126 }
40604127 else
40614128 {
@@ -4064,7 +4131,7 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
40644131 {
40654132 executeBaton->error = NJSMessages::getErrorMsg (
40664133 errInsufficientMemory);
4067- return ;
4134+ goto exitcbDynBufferAllocate ;
40684135 }
40694136 }
40704137 if ( !dmlReturning )
@@ -4077,7 +4144,7 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
40774144 if ( NJS_SIZE_T_OVERFLOW ( sizeof ( unsigned int ), nRows) )
40784145 {
40794146 executeBaton->error = NJSMessages::getErrorMsg ( errResultsTooLarge );
4080- return ;
4147+ goto exitcbDynBufferAllocate ;
40814148 }
40824149 else
40834150 {
@@ -4086,7 +4153,7 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
40864153 {
40874154 executeBaton->error = NJSMessages::getErrorMsg (
40884155 errInsufficientMemory);
4089- return ;
4156+ goto exitcbDynBufferAllocate ;
40904157 }
40914158 }
40924159 if ( !dmlReturning )
@@ -4099,7 +4166,7 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
40994166 if ( NJS_SIZE_T_OVERFLOW ( sizeof ( double ), nRows) )
41004167 {
41014168 executeBaton->error = NJSMessages::getErrorMsg ( errResultsTooLarge );
4102- return ;
4169+ goto exitcbDynBufferAllocate ;
41034170 }
41044171 else
41054172 {
@@ -4108,7 +4175,7 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
41084175 {
41094176 executeBaton->error = NJSMessages::getErrorMsg (
41104177 errInsufficientMemory);
4111- return ;
4178+ goto exitcbDynBufferAllocate ;
41124179 }
41134180 }
41144181 if ( !dmlReturning )
@@ -4131,7 +4198,7 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
41314198 if ( NJS_SIZE_T_OVERFLOW ( sizeof ( Descriptor * ), nRows) )
41324199 {
41334200 executeBaton->error = NJSMessages::getErrorMsg ( errResultsTooLarge );
4134- return ;
4201+ goto exitcbDynBufferAllocate ;
41354202 }
41364203 else
41374204 {
@@ -4140,7 +4207,7 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
41404207 {
41414208 executeBaton->error = NJSMessages::getErrorMsg (
41424209 errInsufficientMemory);
4143- return ;
4210+ goto exitcbDynBufferAllocate ;
41444211 }
41454212 }
41464213 // and allocate the underlying descriptor(s)
@@ -4161,7 +4228,7 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
41614228 if ( NJS_SIZE_T_OVERFLOW ( sizeof ( long double ), nRows) )
41624229 {
41634230 executeBaton->error = NJSMessages::getErrorMsg ( errResultsTooLarge );
4164- return ;
4231+ goto exitcbDynBufferAllocate ;
41654232 }
41664233 else
41674234 {
@@ -4171,7 +4238,7 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
41714238 {
41724239 executeBaton->error = NJSMessages::getErrorMsg (
41734240 errInsufficientMemory);
4174- return ;
4241+ goto exitcbDynBufferAllocate ;
41754242 }
41764243 }
41774244 // needed to post-process DML RETURNING of TimestampLTZ
@@ -4194,7 +4261,7 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
41944261 if ( NJS_SIZE_T_OVERFLOW ( bind->maxSize , nRows ) )
41954262 {
41964263 executeBaton->error = NJSMessages::getErrorMsg ( errResultsTooLarge );
4197- return ;
4264+ goto exitcbDynBufferAllocate ;
41984265 }
41994266 else
42004267 {
@@ -4203,6 +4270,9 @@ void Connection::cbDynBufferAllocate ( void *ctx, bool dmlReturning,
42034270 }
42044271 break ;
42054272 }
4273+
4274+ exitcbDynBufferAllocate:
4275+ ;
42064276}
42074277
42084278/* ***************************************************************************/
0 commit comments