Handle<Value> newIndexBound(const Arguments &args) { HandleScope scope; const Local<Object> spec = args[0]->ToObject(); Local<Value> v; Local<Object> o; NdbIndexScanOperation::IndexBound * bound = new NdbIndexScanOperation::IndexBound; Local<Object> jsBound = IndexBoundEnvelope.newWrapper(); wrapPointerInObject(bound, IndexBoundEnvelope, jsBound); bound->low_key = 0; v = spec->Get(BOUND_LOW_KEY); if(v->IsNull()) { bound->low_key = 0; } else { o = v->ToObject(); bound->low_key = node::Buffer::Data(o); } bound->low_key_count = 0; v = spec->Get(BOUND_LOW_KEY_COUNT); if(! v->IsNull()) { bound->low_key_count = v->Uint32Value(); } bound->low_inclusive = false; v = spec->Get(BOUND_LOW_INCLUSIVE); if(! v->IsNull()) { bound->low_inclusive = v->BooleanValue(); } bound->high_key = 0; v = spec->Get(BOUND_HIGH_KEY); if(v->IsNull()) { bound->high_key = 0; } else { o = v->ToObject(); bound->high_key = node::Buffer::Data(o); } bound->high_key_count = 0; v = spec->Get(BOUND_HIGH_KEY_COUNT); if(! v->IsNull()) { bound->high_key_count = v->Uint32Value(); } bound->high_inclusive = false; v = spec->Get(BOUND_HIGH_INCLUSIVE); if(! v->IsNull()) { bound->high_inclusive = v->BooleanValue(); } bound->range_no = 0; v = spec->Get(BOUND_RANGE_NO); if(! v->IsNull()) { bound->range_no = v->Uint32Value(); } debug_print_bound(bound); return scope.Close(jsBound); }
DBScanHelper::DBScanHelper(const Arguments &args) : nbounds(0), isIndexScan(false) { DEBUG_MARKER(UDEB_DEBUG); Local<Value> v; const Local<Object> spec = args[0]->ToObject(); int opcode = args[1]->Int32Value(); tx = unwrapPointer<NdbTransaction *>(args[2]->ToObject()); lmode = NdbOperation::LM_CommittedRead; scan_options = & options; options.optionsPresent = 0ULL; v = spec->Get(SCAN_TABLE_RECORD); if(! v->IsNull()) { Local<Object> o = v->ToObject(); row_record = unwrapPointer<const Record *>(o); } v = spec->Get(SCAN_INDEX_RECORD); if(! v->IsNull()) { Local<Object> o = v->ToObject(); isIndexScan = true; key_record = unwrapPointer<const Record *>(o); } v = spec->Get(SCAN_LOCK_MODE); if(! v->IsNull()) { int intLockMode = v->Int32Value(); lmode = static_cast<NdbOperation::LockMode>(intLockMode); } // SCAN_BOUNDS is an array of BoundHelpers v = spec->Get(SCAN_BOUNDS); if(v->IsArray()) { Local<Object> o = v->ToObject(); while(o->Has(nbounds)) { nbounds++; } bounds = new NdbIndexScanOperation::IndexBound *[nbounds]; for(int i = 0 ; i < nbounds ; i++) { Local<Object> b = o->Get(i)->ToObject(); bounds[i] = unwrapPointer<NdbIndexScanOperation::IndexBound *>(b); } } v = spec->Get(SCAN_OPTION_FLAGS); if(! v->IsNull()) { options.scan_flags = v->Uint32Value(); options.optionsPresent |= NdbScanOperation::ScanOptions::SO_SCANFLAGS; } v = spec->Get(SCAN_OPTION_BATCH_SIZE); if(! v->IsNull()) { options.batch = v->Uint32Value(); options.optionsPresent |= NdbScanOperation::ScanOptions::SO_BATCH; } v = spec->Get(SCAN_OPTION_PARALLELISM); if(! v->IsNull()) { options.parallel = v->Uint32Value(); options.optionsPresent |= NdbScanOperation::ScanOptions::SO_PARALLEL; } v = spec->Get(SCAN_FILTER_CODE); if(! v->IsNull()) { Local<Object> o = v->ToObject(); options.interpretedCode = unwrapPointer<NdbInterpretedCode *>(o); options.optionsPresent |= NdbScanOperation::ScanOptions::SO_INTERPRETED; } /* Scanning delete requires key info */ if(opcode == OP_SCAN_DELETE) { options.scan_flags |= NdbScanOperation::SF_KeyInfo; options.optionsPresent |= NdbScanOperation::ScanOptions::SO_SCANFLAGS; } /* Done defining the object */ }
bool CQueryParameter::TransformParameter( Isolate* isolate, Local< Value > value, sBindParameter** pOutParam ) { HandleScope scope( isolate ); Local< Context > context = isolate->GetCurrentContext( ); sBindParameter* pParameter = *pOutParam; if( value->IsNull( ) ) { pParameter->SetNull( ); } else if( value->IsString( ) ) { pParameter->SetString( value.As<String>( ) ); } else if( value->IsBoolean( ) ) { pParameter->SetBool( value->BooleanValue( context ).FromJust( ) ); } else if( value->IsInt32( ) ) { pParameter->SetInt( value->Int32Value( context ).FromJust( ) ); } else if( value->IsUint32( ) ) { pParameter->SetUInt( value->Uint32Value( context ).FromJust( ) ); } else if( value->IsNumber( ) ) { double d = value->NumberValue( context ).FromJust( ); if( _isnan( d ) || !_finite( d ) ) { return false; } else if( d == floor( d ) && d >= std::numeric_limits<int64_t>::min( ) && d <= std::numeric_limits<int64_t>::max( ) ) { pParameter->SetInt64( value->IntegerValue( context ).FromJust( ) ); } else { pParameter->SetDouble( value->NumberValue( context ).FromJust( ) ); } } else if( value->IsDate( ) ) { Local<Date> dateObject = value.As<Date>( ); pParameter->SetDate( dateObject->NumberValue( context ).FromJust( ) ); } else if( value->IsObject( ) ) { Local<Object> objValue = value.As<Object>( ); if( node::Buffer::HasInstance( value ) ) { pParameter->SetBuffer( isolate, objValue ); } else { Local< String > strId = String::NewFromUtf8( isolate, "_objId", NewStringType::kNormal ).ToLocalChecked( ); if( objValue->HasRealNamedProperty( context, strId ).FromJust( ) ) { Local< Uint32 > numTypeId = objValue->Get( context, strId ).ToLocalChecked( ).As< Uint32 >( ); uint32_t nType = numTypeId->Int32Value( context ).FromJust( ); switch( nType ) { case ID_INPUT_STREAM: { Local<Value> type = objValue->Get( context, String::NewFromUtf8( isolate, "type", NewStringType::kNormal ).ToLocalChecked( ) ).ToLocalChecked( ); Local<Value> stream = objValue->Get( context, String::NewFromUtf8( isolate, "stream", NewStringType::kNormal ).ToLocalChecked( ) ).ToLocalChecked( ); Local<Value> length = objValue->Get( context, String::NewFromUtf8( isolate, "length", NewStringType::kNormal ).ToLocalChecked( ) ).ToLocalChecked( ); pParameter->SetStream( isolate, type->Uint32Value( context ).FromJust( ), stream, static_cast< SQLUINTEGER >( length->IntegerValue( context ).FromJust( ) ) ); break; } case ID_NUMERIC_VALUE: { Local< Value > precision = objValue->Get( context, String::NewFromUtf8( isolate, "precision", NewStringType::kNormal ).ToLocalChecked( ) ).ToLocalChecked( ); Local<Value> scale = objValue->Get( context, String::NewFromUtf8( isolate, "scale", NewStringType::kNormal ).ToLocalChecked( ) ).ToLocalChecked( ); Local<Value> sign = objValue->Get( context, String::NewFromUtf8( isolate, "sign", NewStringType::kNormal ).ToLocalChecked( ) ).ToLocalChecked( ); Local<Value> value = objValue->Get( context, String::NewFromUtf8( isolate, "value", NewStringType::kNormal ).ToLocalChecked( ) ).ToLocalChecked( ); Local< Uint32 > numPrecision = precision.As<Uint32>( ); Local< Uint32 > numScale = scale.As<Uint32>( ); Local< Boolean > boolSign = sign.As<Boolean>( ); Local< ArrayBuffer > arrBuffer = ( value.As<Uint8Array>( ) )->Buffer( ); ArrayBuffer::Contents contents = arrBuffer->GetContents( ); if( contents.ByteLength( ) > SQL_MAX_NUMERIC_LEN ) { return false; } pParameter->SetNumeric( numPrecision->Uint32Value( context ).FromJust( ), numScale->Uint32Value( context ).FromJust( ), boolSign->BooleanValue( context ).FromJust( ), contents.Data( ), contents.ByteLength( ) ); break; } default: { return false; } } } else { return false; } } } else { return false; } return true; }
bool QueryOperation::BindParameters( Handle<Array> node_params ) { uint32_t count = node_params->Length(); if( count > 0 ) { for( uint32_t i = 0; i < count; ++i ) { Local<Value> p = node_params->Get( i ); ParamBinding binding; if( p->IsNull() ) { binding.js_type = ParamBinding::JS_NULL; binding.c_type = SQL_C_CHAR; binding.sql_type = SQL_CHAR; binding.param_size = 1; binding.digits = 0; binding.buffer = NULL; binding.buffer_len = 0; binding.indptr = SQL_NULL_DATA; } else if( p->IsString() ) { binding.js_type = ParamBinding::JS_STRING; binding.c_type = SQL_C_WCHAR; binding.sql_type = SQL_WVARCHAR; Local<String> str_param = p->ToString(); int str_len = str_param->Length(); binding.buffer = new uint16_t[ str_len + 1 ]; // null terminator str_param->Write( static_cast<uint16_t*>( binding.buffer )); if( str_len > 4000 ) { binding.param_size = 0; // max types require 0 precision } else { binding.param_size = str_len; } binding.buffer_len = str_len * sizeof( uint16_t ); binding.digits = 0; binding.indptr = binding.buffer_len; } else if( p->IsBoolean() ) { binding.js_type = ParamBinding::JS_BOOLEAN; binding.c_type = SQL_C_BIT; binding.sql_type = SQL_BIT; binding.buffer = new uint16_t; binding.buffer_len = sizeof( uint16_t ); *static_cast<uint16_t*>( binding.buffer ) = p->BooleanValue(); binding.param_size = 1; binding.digits = 0; binding.indptr = binding.buffer_len; } else if( p->IsInt32()) { binding.js_type = ParamBinding::JS_INT; binding.c_type = SQL_C_SLONG; binding.sql_type = SQL_INTEGER; binding.buffer = new int32_t; binding.buffer_len = sizeof( int32_t ); *static_cast<int32_t*>( binding.buffer ) = p->Int32Value(); binding.param_size = sizeof( int32_t ); binding.digits = 0; binding.indptr = binding.buffer_len; } else if( p->IsUint32()) { binding.js_type = ParamBinding::JS_UINT; binding.c_type = SQL_C_ULONG; binding.sql_type = SQL_BIGINT; binding.buffer = new uint32_t; binding.buffer_len = sizeof( uint32_t ); *static_cast<int32_t*>( binding.buffer ) = p->Uint32Value(); binding.param_size = sizeof( uint32_t ); binding.digits = 0; binding.indptr = binding.buffer_len; } else if( p->IsNumber()) { // numbers can be either integers or doubles. We attempt to determine which it is through a simple // cast and equality check double d = p->NumberValue(); if( _isnan( d ) || !_finite( d ) ) { return ParameterErrorToUserCallback( i, "Invalid number parameter" ); } else if( d == floor( d ) && d >= std::numeric_limits<int64_t>::min() && d <= std::numeric_limits<int64_t>::max() ) { binding.js_type = ParamBinding::JS_NUMBER; binding.c_type = SQL_C_SBIGINT; binding.sql_type = SQL_BIGINT; binding.buffer = new int64_t; binding.buffer_len = sizeof( int64_t ); *static_cast<int64_t*>( binding.buffer ) = p->IntegerValue(); binding.param_size = sizeof( int64_t ); binding.digits = 0; binding.indptr = binding.buffer_len; } else { binding.js_type = ParamBinding::JS_NUMBER; binding.c_type = SQL_C_DOUBLE; binding.sql_type = SQL_DOUBLE; binding.buffer = new double; binding.buffer_len = sizeof( double ); *static_cast<double*>( binding.buffer ) = p->NumberValue(); binding.param_size = sizeof( double ); binding.digits = 0; binding.indptr = binding.buffer_len; } } else if( p->IsDate() ) { // Since JS dates have no timezone context, all dates are assumed to be UTC Handle<Date> dateObject = Handle<Date>::Cast<Value>( p ); assert( !dateObject.IsEmpty() ); // dates in JS are stored internally as ms count from Jan 1, 1970 double d = dateObject->NumberValue(); SQL_SS_TIMESTAMPOFFSET_STRUCT* sql_tm = new SQL_SS_TIMESTAMPOFFSET_STRUCT; TimestampColumn sql_date( d ); sql_date.ToTimestampOffset( *sql_tm ); binding.js_type = ParamBinding::JS_DATE; binding.c_type = SQL_C_BINARY; // TODO: Determine proper SQL type based on version of server we're talking to binding.sql_type = SQL_SS_TIMESTAMPOFFSET; binding.buffer = sql_tm; binding.buffer_len = sizeof( SQL_SS_TIMESTAMPOFFSET_STRUCT ); // TODO: Determine proper precision and size based on version of server we're talking to binding.param_size = SQL_SERVER_2008_DEFAULT_DATETIME_PRECISION; binding.digits = SQL_SERVER_2008_DEFAULT_DATETIME_SCALE; binding.indptr = binding.buffer_len; } else if( p->IsObject() && node::Buffer::HasInstance( p )) { // TODO: Determine if we need something to keep the Buffer object from going // away while we use it we could just copy the data, but with buffers being // potentially very large, that could be problematic Local<Object> o = p.As<Object>(); binding.js_type = ParamBinding::JS_BUFFER; binding.c_type = SQL_C_BINARY; binding.sql_type = SQL_VARBINARY; binding.buffer = node::Buffer::Data( o ); binding.buffer_len = node::Buffer::Length( o ); binding.param_size = binding.buffer_len; binding.digits = 0; binding.indptr = binding.buffer_len; } else { return ParameterErrorToUserCallback( i, "Invalid parameter type" ); } params.push_back( move( binding )); } } return true; }
ScanOperation::ScanOperation(const Arguments &args) : KeyOperation(), scan_op(0), index_scan_op(0), nbounds(0), isIndexScan(false) { DEBUG_MARKER(UDEB_DEBUG); Local<Value> v; const Local<Object> spec = args[0]->ToObject(); opcode = args[1]->Int32Value(); ctx = unwrapPointer<TransactionImpl *>(args[2]->ToObject()); lmode = NdbOperation::LM_CommittedRead; scan_options.scan_flags = 0; scan_options.optionsPresent = 0ULL; v = spec->Get(SCAN_TABLE_RECORD); if(! v->IsNull()) { Local<Object> o = v->ToObject(); row_record = unwrapPointer<const Record *>(o); createBlobReadHandles(row_record); } v = spec->Get(SCAN_INDEX_RECORD); if(! v->IsNull()) { Local<Object> o = v->ToObject(); isIndexScan = true; key_record = unwrapPointer<const Record *>(o); } v = spec->Get(SCAN_LOCK_MODE); if(! v->IsNull()) { int intLockMode = v->Int32Value(); DEBUG_PRINT("Scan lock mode %d", intLockMode); lmode = static_cast<NdbOperation::LockMode>(intLockMode); } // SCAN_BOUNDS is an array of BoundHelpers v = spec->Get(SCAN_BOUNDS); if(v->IsArray()) { Local<Object> o = v->ToObject(); while(o->Has(nbounds)) { nbounds++; } DEBUG_PRINT("Index Scan with %d IndexBounds", nbounds); bounds = new NdbIndexScanOperation::IndexBound *[nbounds]; for(int i = 0 ; i < nbounds ; i++) { Local<Object> b = o->Get(i)->ToObject(); bounds[i] = unwrapPointer<NdbIndexScanOperation::IndexBound *>(b); } } v = spec->Get(SCAN_OPTION_FLAGS); if(! v->IsNull()) { scan_options.scan_flags = v->Uint32Value(); } v = spec->Get(SCAN_OPTION_BATCH_SIZE); if(! v->IsNull()) { scan_options.batch = v->Uint32Value(); scan_options.optionsPresent |= NdbScanOperation::ScanOptions::SO_BATCH; } v = spec->Get(SCAN_OPTION_PARALLELISM); if(! v->IsNull()) { scan_options.parallel = v->Uint32Value(); scan_options.optionsPresent |= NdbScanOperation::ScanOptions::SO_PARALLEL; } v = spec->Get(SCAN_FILTER_CODE); if(! v->IsNull()) { Local<Object> o = v->ToObject(); scan_options.interpretedCode = unwrapPointer<NdbInterpretedCode *>(o); scan_options.optionsPresent |= NdbScanOperation::ScanOptions::SO_INTERPRETED; } /* Scanning delete requires key info */ if(opcode == OP_SCAN_DELETE) { scan_options.scan_flags |= NdbScanOperation::SF_KeyInfo; } /* If any flags were set, also set SO_SCANFLAGS options */ if(scan_options.scan_flags != 0) { scan_options.optionsPresent |= NdbScanOperation::ScanOptions::SO_SCANFLAGS; } /* Done defining the object */ debug_print_flags_and_options(scan_options); }