From 5e0bafdee272b5e1a60d0d69278d045e9dbf804e Mon Sep 17 00:00:00 2001 From: Peter Keuter Date: Thu, 31 Oct 2019 13:30:59 +0100 Subject: [PATCH 1/3] Add node v12 compatibility --- package-lock.json | 18 +++ package.json | 4 +- src/h/sqlany_utils.h | 2 +- src/sqlanywhere.cpp | 16 +-- src/utils.cpp | 256 ++++++++++++++++++++++--------------------- 5 files changed, 163 insertions(+), 133 deletions(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..7b6a8e3 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,18 @@ +{ + "name": "sqlanywhere", + "version": "1.0.24", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "help": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/help/-/help-3.0.2.tgz", + "integrity": "sha1-luGQ1KCkU7icLLSwWrOOOo+f2t0=" + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" + } + } +} diff --git a/package.json b/package.json index 088d5d2..faf4836 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "SQL ANYWHERE", "name": "sqlanywhere", "description": "SQL Anywhere JavaScript Driver.", - "version": "1.0.24", + "version": "2.0.0", "repository": { "url": "https://github.com/sqlanywhere/node-sqlanywhere" }, @@ -15,6 +15,6 @@ }, "dependencies": { "help": "^3.0.2", - "nan": "2.11.1" + "nan": "^2.14.0" } } diff --git a/src/h/sqlany_utils.h b/src/h/sqlany_utils.h index 928b1cc..908b5d2 100644 --- a/src/h/sqlany_utils.h +++ b/src/h/sqlany_utils.h @@ -157,7 +157,7 @@ void callBack( std::string * str, #endif bool getBindParameters( std::vector &execData - , Handle arg + , Local arg , std::vector ¶ms , unsigned &num_rows ); diff --git a/src/sqlanywhere.cpp b/src/sqlanywhere.cpp index df1018a..10416e7 100644 --- a/src/sqlanywhere.cpp +++ b/src/sqlanywhere.cpp @@ -3,6 +3,7 @@ // *************************************************************************** #include "nodever_cover.h" #include "sqlany_utils.h" +#include "nan.h" #if !v010 @@ -454,7 +455,7 @@ NODE_API_FUNC( Connection::exec ) return; } - String::Utf8Value param0( args[0]->ToString() ); + Nan::Utf8String param0( args[0]->ToString(isolate) ); executeBaton *baton = new executeBaton(); baton->obj = obj; @@ -641,7 +642,7 @@ NODE_API_FUNC( Connection::prepare ) return; } - String::Utf8Value param0( args[0]->ToString() ); + Nan::Utf8String param0( args[0]->ToString(isolate) ); prepareBaton *baton = new prepareBaton(); baton->obj = obj; @@ -797,6 +798,7 @@ NODE_API_FUNC( Connection::connect ) /**********************************/ { Isolate *isolate = args.GetIsolate(); + Local context = isolate->GetCurrentContext(); HandleScope scope( isolate ); int num_args = args.Length(); Connection *obj; @@ -856,26 +858,26 @@ NODE_API_FUNC( Connection::connect ) baton->sqlca_connection = sqlca_connection; if( sqlca_connection ) { - baton->sqlca = (void *)(long)args[0]->NumberValue(); + baton->sqlca = (void *)(long)args[0]->NumberValue(context).ToChecked(); } else { Local localArg = Local::New( isolate, obj->_arg ); if( localArg->Length() > 0 ) { - String::Utf8Value param0( localArg ); + Nan::Utf8String param0( localArg ); baton->conn_string = std::string(*param0); } else { baton->conn_string = std::string(); } if( arg_is_string ) { - String::Utf8Value param0( args[0]->ToString() ); + Nan::Utf8String param0( args[0]->ToString(isolate) ); baton->conn_string.append( ";" ); baton->conn_string.append(*param0); } else if( arg_is_object ) { Persistent arg_string; - HashToString( args[0]->ToObject(), arg_string ); + HashToString( args[0]->ToObject(context).ToLocalChecked(), arg_string ); Local local_arg_string = Local::New( isolate, arg_string ); - String::Utf8Value param0( local_arg_string ); + Nan::Utf8String param0( local_arg_string ); baton->conn_string.append( ";" ); baton->conn_string.append(*param0); arg_string.Reset(); diff --git a/src/utils.cpp b/src/utils.cpp index 319ddd6..616a012 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -82,6 +82,7 @@ void throwError( int code ) { Isolate *isolate = Isolate::GetCurrent(); std::string message; + getErrorMsg( code, message ); isolate->ThrowException( Exception::Error( String::NewFromUtf8( isolate, message.c_str() ) ) ); @@ -194,126 +195,131 @@ void callBack( std::string * str, } static bool getWideBindParameters( std::vector &execData, - Handle arg, + Local arg, std::vector & params, unsigned &num_rows ) /*********************************************************************************/ { - Handle rows = Handle::Cast( arg ); - num_rows = rows->Length(); - - Handle row0 = Handle::Cast( rows->Get(0) ); - unsigned num_cols = row0->Length(); - unsigned c; - - if( num_cols == 0 ) { - // if an empty array was passed in, we still need ExecuteData - ExecuteData *ex = new ExecuteData; - execData.push_back( ex ); - return true; - } - - // Make sure that each array in the list has the same number and types - // of values - for( unsigned int r = 1; r < num_rows; r++ ) { - Handle row = Handle::Cast( rows->Get(r) ); - for( c = 0; c < num_cols; c++ ) { - Handle val0 = row0->Get(c); - Handle val = row->Get(c); - - if( ( val0->IsInt32() || val0->IsNumber() ) && - ( !val->IsInt32() && !val->IsNumber() && !val->IsNull() ) ) { - return false; - } - if( val0->IsString() && - !val->IsString() && !val->IsNull() ) { - return false; - } - if( Buffer::HasInstance( val0 ) && - !Buffer::HasInstance( val ) && !val->IsNull() ) { - return false; - } - } - } - - for( c = 0; c < num_cols; c++ ) { - a_sqlany_bind_param param; - memset( ¶m, 0, sizeof( param ) ); - - ExecuteData *ex = new ExecuteData; - execData.push_back( ex ); - - double * param_double = new double[num_rows]; - ex->addNum( param_double ); - char ** char_arr = new char *[num_rows]; - size_t * len = new size_t[num_rows]; - ex->addStrings( char_arr, len ); - sacapi_bool * is_null = new sacapi_bool[num_rows]; - ex->addNull( is_null ); - param.value.is_null = is_null; - param.value.is_address = false; - - if( row0->Get(c)->IsInt32() || row0->Get(c)->IsNumber() ) { - param.value.type = A_DOUBLE; - param.value.buffer = (char *)( param_double ); - - } else if( row0->Get(c)->IsString() ) { - param.value.type = A_STRING; - param.value.buffer = (char *)char_arr; - param.value.length = len; - param.value.is_address = true; - - } else if( Buffer::HasInstance( row0->Get(c) ) ) { - param.value.type = A_BINARY; - param.value.buffer = (char *)char_arr; - param.value.length = len; - param.value.is_address = true; - - } else if( row0->Get(c)->IsNull() ) { - - } else{ - return false; - } - - for( unsigned int r = 0; r < num_rows; r++ ) { - Handle bind_params = Handle::Cast( rows->Get(r) ); - - is_null[r] = false; - if( bind_params->Get(c)->IsInt32() || bind_params->Get(c)->IsNumber() ) { - param_double[r] = bind_params->Get(c)->NumberValue(); - - } else if( bind_params->Get(c)->IsString() ) { - String::Utf8Value paramValue( bind_params->Get(c)->ToString() ); - const char* param_string = (*paramValue); - len[r] = (size_t)paramValue.length(); - char *param_char = new char[len[r] + 1]; - char_arr[r] = param_char; - memcpy( param_char, param_string, len[r] + 1 ); - - } else if( Buffer::HasInstance( bind_params->Get(c) ) ) { - len[r] = Buffer::Length( bind_params->Get(c) ); - char *param_char = new char[len[r]]; - char_arr[r] = param_char; - memcpy( param_char, Buffer::Data( bind_params->Get(c) ), len[r] ); - - } else if( bind_params->Get(c)->IsNull() ) { - is_null[r] = true; - } - } - - params.push_back( param ); - } + //Isolate* isolate = Isolate::GetCurrent(); + //Local context = isolate->GetCurrentContext(); + //Local rows = Local::Cast( arg ); + // num_rows = rows->Length(); + + //Local row0 = Local::Cast( rows->Get(0) ); + // unsigned num_cols = row0->Length(); + // unsigned c; + + // if( num_cols == 0 ) { + //// if an empty array was passed in, we still need ExecuteData + //ExecuteData *ex = new ExecuteData; + //execData.push_back( ex ); + //return true; + // } + + // // Make sure that each array in the list has the same number and types + // // of values + // for( unsigned int r = 1; r < num_rows; r++ ) { + //Local row = Local::Cast( rows->Get(r) ); + //for( c = 0; c < num_cols; c++ ) { + // Local val0 = row0->Get(c); + // Local val = row->Get(c); + + // if( ( val0->IsInt32() || val0->IsNumber() ) && + // ( !val->IsInt32() && !val->IsNumber() && !val->IsNull() ) ) { + // return false; + // } + // if( val0->IsString() && + // !val->IsString() && !val->IsNull() ) { + // return false; + // } + // if( Buffer::HasInstance( val0 ) && + // !Buffer::HasInstance( val ) && !val->IsNull() ) { + // return false; + // } + //} + // } + + // for( c = 0; c < num_cols; c++ ) { + //a_sqlany_bind_param param; + //memset( ¶m, 0, sizeof( param ) ); + + //ExecuteData *ex = new ExecuteData; + //execData.push_back( ex ); + + //double * param_double = new double[num_rows]; + //ex->addNum( param_double ); + //char ** char_arr = new char *[num_rows]; + //size_t * len = new size_t[num_rows]; + //ex->addStrings( char_arr, len ); + //sacapi_bool * is_null = new sacapi_bool[num_rows]; + //ex->addNull( is_null ); + //param.value.is_null = is_null; + //param.value.is_address = false; + + //if( row0->Get(c)->IsInt32() || row0->Get(c)->IsNumber() ) { + // param.value.type = A_DOUBLE; + // param.value.buffer = (char *)( param_double ); + + //} else if( row0->Get(c)->IsString() ) { + // param.value.type = A_STRING; + // param.value.buffer = (char *)char_arr; + // param.value.length = len; + // param.value.is_address = true; + + //} else if( Buffer::HasInstance( row0->Get(c) ) ) { + // param.value.type = A_BINARY; + // param.value.buffer = (char *)char_arr; + // param.value.length = len; + // param.value.is_address = true; + // + //} else if( row0->Get(c)->IsNull() ) { + + //} else{ + // return false; + //} + + //for( unsigned int r = 0; r < num_rows; r++ ) { + // Local bind_params = Local::Cast( rows->Get(r) ); + // + // is_null[r] = false; + // if( bind_params->Get(c)->IsInt32() || bind_params->Get(c)->IsNumber() ) { + // param_double[r] = bind_params->Get(c)->NumberValue(context).ToChecked(); + // + // } else if( bind_params->Get(c)->IsString() ) { + // Nan::Utf8String paramValue( bind_params->Get(c)->ToString(isolate) ); + // const char* param_string = (*paramValue); + // len[r] = (size_t)paramValue.length(); + // char *param_char = new char[len[r] + 1]; + // char_arr[r] = param_char; + // memcpy( param_char, param_string, len[r] + 1 ); + // + // } else if( Buffer::HasInstance( bind_params->Get(c) ) ) { + // len[r] = Buffer::Length( bind_params->Get(c) ); + // char *param_char = new char[len[r]]; + // char_arr[r] = param_char; + // memcpy( param_char, Buffer::Data( bind_params->Get(c) ), len[r] ); + + // } else if( bind_params->Get(c)->IsNull() ) { + // is_null[r] = true; + // } + //} + // + //params.push_back( param ); + // } return true; } bool getBindParameters( std::vector &execData, - Handle arg, + Local arg, std::vector & params, unsigned &num_rows ) /*************************************************************************/ { - Handle bind_params = Handle::Cast( arg ); + + Isolate* isolate = Isolate::GetCurrent(); + Local context = isolate->GetCurrentContext(); + Local bind_params = Local::Cast( arg ); if( bind_params->Length() == 0 ) { // if an empty array was passed in, we still need ExecuteData @@ -336,20 +342,20 @@ bool getBindParameters( std::vector &execData, if( bind_params->Get(i)->IsInt32() ) { int *param_int = new int; - *param_int = bind_params->Get(i)->Int32Value(); + *param_int = bind_params->Get(i)->Int32Value(context).ToChecked(); ex->addInt( param_int ); param.value.buffer = (char *)( param_int ); param.value.type = A_VAL32; } else if( bind_params->Get(i)->IsNumber() ) { double *param_double = new double; - *param_double = bind_params->Get(i)->NumberValue(); // Remove Round off Error + *param_double = bind_params->Get(i)->NumberValue(context).ToChecked(); // Remove Round off Error ex->addNum( param_double ); param.value.buffer = (char *)( param_double ); param.value.type = A_DOUBLE; } else if( bind_params->Get(i)->IsString() ) { - String::Utf8Value paramValue( bind_params->Get(i)->ToString() ); + Nan::Utf8String paramValue( bind_params->Get(i)->ToString(context).ToLocalChecked() ); const char* param_string = (*paramValue); size_t *len = new size_t; *len = (size_t)paramValue.length(); @@ -755,6 +761,7 @@ void StmtObject::Init( Isolate *isolate ) /***************************************/ { HandleScope scope(isolate); + Local context = isolate->GetCurrentContext(); // Prepare constructor template Local tpl = FunctionTemplate::New( isolate, New ); tpl->SetClassName( String::NewFromUtf8( isolate, "StmtObject" ) ); @@ -764,7 +771,7 @@ void StmtObject::Init( Isolate *isolate ) NODE_SET_PROTOTYPE_METHOD( tpl, "exec", exec ); NODE_SET_PROTOTYPE_METHOD( tpl, "drop", drop ); NODE_SET_PROTOTYPE_METHOD( tpl, "getMoreResults", getMoreResults ); - constructor.Reset( isolate, tpl->GetFunction() ); + constructor.Reset( isolate, tpl->GetFunction(context).ToLocalChecked() ); } void StmtObject::New( const FunctionCallbackInfo &args ) @@ -791,7 +798,7 @@ void StmtObject::CreateNewInstance( const FunctionCallbackInfo & args, Isolate *isolate = args.GetIsolate(); HandleScope scope(isolate); const unsigned argc = 1; - Handle argv[argc] = { args[0] }; + Local argv[argc] = { args[0] }; Localcons = Local::New( isolate, constructor ); #if NODE_MAJOR_VERSION >= 10 Local env = isolate->GetCurrentContext(); @@ -829,15 +836,16 @@ void HashToString( Local obj, Persistent &ret ) { Isolate *isolate = Isolate::GetCurrent(); HandleScope scope(isolate); - Local props = obj->GetOwnPropertyNames(); - int length = props->Length(); + Local context = isolate->GetCurrentContext(); + MaybeLocal props = obj->GetOwnPropertyNames(context); + int length = props.ToLocalChecked()->Length(); std::string params = ""; bool first = true; for( int i = 0; i < length; i++ ) { - Local key = props->Get(i).As(); + Local key = props.ToLocalChecked()->Get(i).As(); Local val = obj->Get(key).As(); - String::Utf8Value key_utf8( key ); - String::Utf8Value val_utf8( val ); + String::Utf8Value key_utf8( isolate, key ); + String::Utf8Value val_utf8( isolate, val ); if( !first ) { params += ";"; } @@ -899,6 +907,7 @@ Connection::Connection( const FunctionCallbackInfo &args ) /***************************************************************/ { Isolate *isolate = args.GetIsolate(); + Local context = isolate->GetCurrentContext(); HandleScope scope( isolate ); uv_mutex_init(&conn_mutex); conn = NULL; @@ -911,14 +920,14 @@ Connection::Connection( const FunctionCallbackInfo &args ) if( args.Length() == 1 ) { //CheckArgType( args[0] ); if( args[0]->IsString() ) { - Local str = args[0]->ToString(); - int string_len = str->Utf8Length(); + MaybeLocal str = args[0]->ToString(context); + int string_len = str.ToLocalChecked()->Utf8Length(isolate); char *buf = new char[string_len+1]; - str->WriteUtf8( buf ); + str.ToLocalChecked()->WriteUtf8(isolate, buf ); _arg.Reset( isolate, String::NewFromUtf8( isolate, buf ) ); delete [] buf; } else if( args[0]->IsObject() ) { - HashToString( args[0]->ToObject(), _arg ); + HashToString(args[0]->ToObject(context).ToLocalChecked(), _arg); } else if( !args[0]->IsUndefined() && !args[0]->IsNull() ) { throwError( JS_ERR_INVALID_ARGUMENTS ); } else { @@ -977,6 +986,7 @@ void Connection::Init( Isolate *isolate ) /***************************************/ { HandleScope scope( isolate ); + Local context = isolate->GetCurrentContext(); // Prepare constructor template Local tpl = FunctionTemplate::New( isolate, New ); tpl->SetClassName( String::NewFromUtf8( isolate, "Connection" ) ); @@ -992,7 +1002,7 @@ void Connection::Init( Isolate *isolate ) NODE_SET_PROTOTYPE_METHOD( tpl, "rollback", rollback ); NODE_SET_PROTOTYPE_METHOD( tpl, "connected", connected ); - constructor.Reset( isolate, tpl->GetFunction() ); + constructor.Reset( isolate, tpl->GetFunction(context).ToLocalChecked() ); } void Connection::New( const FunctionCallbackInfo &args ) @@ -1026,7 +1036,7 @@ void Connection::NewInstance( const FunctionCallbackInfo &args ) Isolate *isolate = args.GetIsolate(); HandleScope scope( isolate ); const unsigned argc = 1; - Handle argv[argc] = { args[0] }; + Local argv[argc] = { args[0] }; Local cons = Local::New( isolate, constructor ); #if NODE_MAJOR_VERSION >= 10 Local env = isolate->GetCurrentContext(); From 3b4e0d18a336d17166782ba6f3c9a53a1dea21ad Mon Sep 17 00:00:00 2001 From: Peter Keuter Date: Thu, 31 Oct 2019 13:31:33 +0100 Subject: [PATCH 2/3] Add gitignore file --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b7dab5e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +build \ No newline at end of file From a2089b6ca246e46361214f302f15c737065b83db Mon Sep 17 00:00:00 2001 From: Peter Keuter Date: Thu, 31 Oct 2019 13:47:58 +0100 Subject: [PATCH 3/3] Uncomment wrongly commented code --- src/utils.cpp | 212 +++++++++++++++++++++++++------------------------- 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/src/utils.cpp b/src/utils.cpp index 616a012..b378f56 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -200,112 +200,112 @@ static bool getWideBindParameters( std::vector &execData, unsigned &num_rows ) /*********************************************************************************/ { - //Isolate* isolate = Isolate::GetCurrent(); - //Local context = isolate->GetCurrentContext(); - //Local rows = Local::Cast( arg ); - // num_rows = rows->Length(); - - //Local row0 = Local::Cast( rows->Get(0) ); - // unsigned num_cols = row0->Length(); - // unsigned c; - - // if( num_cols == 0 ) { - //// if an empty array was passed in, we still need ExecuteData - //ExecuteData *ex = new ExecuteData; - //execData.push_back( ex ); - //return true; - // } - - // // Make sure that each array in the list has the same number and types - // // of values - // for( unsigned int r = 1; r < num_rows; r++ ) { - //Local row = Local::Cast( rows->Get(r) ); - //for( c = 0; c < num_cols; c++ ) { - // Local val0 = row0->Get(c); - // Local val = row->Get(c); - - // if( ( val0->IsInt32() || val0->IsNumber() ) && - // ( !val->IsInt32() && !val->IsNumber() && !val->IsNull() ) ) { - // return false; - // } - // if( val0->IsString() && - // !val->IsString() && !val->IsNull() ) { - // return false; - // } - // if( Buffer::HasInstance( val0 ) && - // !Buffer::HasInstance( val ) && !val->IsNull() ) { - // return false; - // } - //} - // } - - // for( c = 0; c < num_cols; c++ ) { - //a_sqlany_bind_param param; - //memset( ¶m, 0, sizeof( param ) ); - - //ExecuteData *ex = new ExecuteData; - //execData.push_back( ex ); - - //double * param_double = new double[num_rows]; - //ex->addNum( param_double ); - //char ** char_arr = new char *[num_rows]; - //size_t * len = new size_t[num_rows]; - //ex->addStrings( char_arr, len ); - //sacapi_bool * is_null = new sacapi_bool[num_rows]; - //ex->addNull( is_null ); - //param.value.is_null = is_null; - //param.value.is_address = false; - - //if( row0->Get(c)->IsInt32() || row0->Get(c)->IsNumber() ) { - // param.value.type = A_DOUBLE; - // param.value.buffer = (char *)( param_double ); - - //} else if( row0->Get(c)->IsString() ) { - // param.value.type = A_STRING; - // param.value.buffer = (char *)char_arr; - // param.value.length = len; - // param.value.is_address = true; - - //} else if( Buffer::HasInstance( row0->Get(c) ) ) { - // param.value.type = A_BINARY; - // param.value.buffer = (char *)char_arr; - // param.value.length = len; - // param.value.is_address = true; - // - //} else if( row0->Get(c)->IsNull() ) { - - //} else{ - // return false; - //} - - //for( unsigned int r = 0; r < num_rows; r++ ) { - // Local bind_params = Local::Cast( rows->Get(r) ); - // - // is_null[r] = false; - // if( bind_params->Get(c)->IsInt32() || bind_params->Get(c)->IsNumber() ) { - // param_double[r] = bind_params->Get(c)->NumberValue(context).ToChecked(); - // - // } else if( bind_params->Get(c)->IsString() ) { - // Nan::Utf8String paramValue( bind_params->Get(c)->ToString(isolate) ); - // const char* param_string = (*paramValue); - // len[r] = (size_t)paramValue.length(); - // char *param_char = new char[len[r] + 1]; - // char_arr[r] = param_char; - // memcpy( param_char, param_string, len[r] + 1 ); - // - // } else if( Buffer::HasInstance( bind_params->Get(c) ) ) { - // len[r] = Buffer::Length( bind_params->Get(c) ); - // char *param_char = new char[len[r]]; - // char_arr[r] = param_char; - // memcpy( param_char, Buffer::Data( bind_params->Get(c) ), len[r] ); - - // } else if( bind_params->Get(c)->IsNull() ) { - // is_null[r] = true; - // } - //} - // - //params.push_back( param ); - // } + Isolate* isolate = Isolate::GetCurrent(); + Local context = isolate->GetCurrentContext(); + Local rows = Local::Cast( arg ); + num_rows = rows->Length(); + + Local row0 = Local::Cast( rows->Get(0) ); + unsigned num_cols = row0->Length(); + unsigned c; + + if( num_cols == 0 ) { + // if an empty array was passed in, we still need ExecuteData + ExecuteData *ex = new ExecuteData; + execData.push_back( ex ); + return true; + } + + // Make sure that each array in the list has the same number and types + // of values + for( unsigned int r = 1; r < num_rows; r++ ) { + Local row = Local::Cast( rows->Get(r) ); + for( c = 0; c < num_cols; c++ ) { + Local val0 = row0->Get(c); + Local val = row->Get(c); + + if( ( val0->IsInt32() || val0->IsNumber() ) && + ( !val->IsInt32() && !val->IsNumber() && !val->IsNull() ) ) { + return false; + } + if( val0->IsString() && + !val->IsString() && !val->IsNull() ) { + return false; + } + if( Buffer::HasInstance( val0 ) && + !Buffer::HasInstance( val ) && !val->IsNull() ) { + return false; + } + } + } + + for( c = 0; c < num_cols; c++ ) { + a_sqlany_bind_param param; + memset( ¶m, 0, sizeof( param ) ); + + ExecuteData *ex = new ExecuteData; + execData.push_back( ex ); + + double * param_double = new double[num_rows]; + ex->addNum( param_double ); + char ** char_arr = new char *[num_rows]; + size_t * len = new size_t[num_rows]; + ex->addStrings( char_arr, len ); + sacapi_bool * is_null = new sacapi_bool[num_rows]; + ex->addNull( is_null ); + param.value.is_null = is_null; + param.value.is_address = false; + + if( row0->Get(c)->IsInt32() || row0->Get(c)->IsNumber() ) { + param.value.type = A_DOUBLE; + param.value.buffer = (char *)( param_double ); + + } else if( row0->Get(c)->IsString() ) { + param.value.type = A_STRING; + param.value.buffer = (char *)char_arr; + param.value.length = len; + param.value.is_address = true; + + } else if( Buffer::HasInstance( row0->Get(c) ) ) { + param.value.type = A_BINARY; + param.value.buffer = (char *)char_arr; + param.value.length = len; + param.value.is_address = true; + + } else if( row0->Get(c)->IsNull() ) { + + } else{ + return false; + } + + for( unsigned int r = 0; r < num_rows; r++ ) { + Local bind_params = Local::Cast( rows->Get(r) ); + + is_null[r] = false; + if( bind_params->Get(c)->IsInt32() || bind_params->Get(c)->IsNumber() ) { + param_double[r] = bind_params->Get(c)->NumberValue(context).ToChecked(); + + } else if( bind_params->Get(c)->IsString() ) { + Nan::Utf8String paramValue( bind_params->Get(c)->ToString(isolate) ); + const char* param_string = (*paramValue); + len[r] = (size_t)paramValue.length(); + char *param_char = new char[len[r] + 1]; + char_arr[r] = param_char; + memcpy( param_char, param_string, len[r] + 1 ); + + } else if( Buffer::HasInstance( bind_params->Get(c) ) ) { + len[r] = Buffer::Length( bind_params->Get(c) ); + char *param_char = new char[len[r]]; + char_arr[r] = param_char; + memcpy( param_char, Buffer::Data( bind_params->Get(c) ), len[r] ); + + } else if( bind_params->Get(c)->IsNull() ) { + is_null[r] = true; + } + } + + params.push_back( param ); + } return true; }