//--------------------------------------------------------------------------------------------------------------------------------- // File: Connection.cpp // Contents: C++ interface to Microsoft Driver for Node.js for SQL Server // // Copyright Microsoft Corporation and contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // // You may obtain a copy of the License at: // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //--------------------------------------------------------------------------------------------------------------------------------- #include "stdafx.h" #include #include #include namespace mssql { using namespace v8; Nan::Persistent Connection::constructor; Connection::Connection() : connectionBridge(make_unique()) { } void Connection::api(Local & tpl) { Nan::SetPrototypeMethod(tpl, "close", close); Nan::SetPrototypeMethod(tpl, "open", open); Nan::SetPrototypeMethod(tpl, "query", query); Nan::SetPrototypeMethod(tpl, "bindQuery", bind_query); Nan::SetPrototypeMethod(tpl, "prepare", prepare); Nan::SetPrototypeMethod(tpl, "readColumn", read_column); Nan::SetPrototypeMethod(tpl, "beginTransaction", begin_transaction); Nan::SetPrototypeMethod(tpl, "commit", commit); Nan::SetPrototypeMethod(tpl, "rollback", rollback); Nan::SetPrototypeMethod(tpl, "nextResult", read_next_result); Nan::SetPrototypeMethod(tpl, "callProcedure", call_procedure); Nan::SetPrototypeMethod(tpl, "unbind", unbind); Nan::SetPrototypeMethod(tpl, "freeStatement", free_statement); Nan::SetPrototypeMethod(tpl, "cancelQuery", cancel_statement); Nan::SetPrototypeMethod(tpl, "pollingMode", polling_mode); } void Connection::Init(Local exports) { Nan::HandleScope scope; const auto initialized = OdbcConnection::InitializeEnvironment(); const auto name = Nan::New("Connection").ToLocalChecked(); if (!initialized) { const nodeTypeFactory fact; MutateJS::set_property_value(exports, name, Nan::Null()); fact.throwError("Unable to initialize msnodesql"); return; } // Prepare constructor template auto tpl = Nan::New(New); tpl->SetClassName(name); tpl->InstanceTemplate()->SetInternalFieldCount(1); api(tpl); constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked()); Nan::Set(exports, name, Nan::GetFunction(tpl).ToLocalChecked()); } Connection::~Connection() { // close the connection now since the object is being collected //connectionBridge->Collect(); } void Connection::close(NanCb info) { const auto cb = info[0].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->close(cb); info.GetReturnValue().Set(ret); } void Connection::begin_transaction(NanCb info) { const auto cb = info[0].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->begin_transaction(cb); info.GetReturnValue().Set(ret); } void Connection::commit(NanCb info) { const auto cb = info[0].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->commit(cb); info.GetReturnValue().Set(ret); } void Connection::rollback(NanCb info) { const auto cb = info[0].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->rollback(cb); info.GetReturnValue().Set(ret); } void Connection::New(NanCb info) { const auto context = info.GetIsolate()->GetCurrentContext(); if (info.IsConstructCall()) { // Invoked as constructor: `new MyObject(...)` auto* obj = new Connection(); obj->Wrap(info.This()); info.GetReturnValue().Set(info.This()); } else { // Invoked as plain function `MyObject(...)`, turn into construct call. constexpr auto argc = 1; Local argv[argc] = {info[0]}; const auto cons = Nan::New(constructor); info.GetReturnValue().Set( cons->NewInstance(context, argc, argv).ToLocalChecked()); } } void Connection::query(NanCb info) { const auto query_id = info[0].As(); const auto query_object = info[1].As(); const auto params = info[2].As(); const auto callback = info[3].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->query(query_id, query_object, params, callback); info.GetReturnValue().Set(ret); } void Connection::prepare(NanCb info) { const auto query_id = info[0].As(); const auto query_object = info[1].As(); const auto callback = info[2].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->prepare(query_id, query_object, callback); info.GetReturnValue().Set(ret); } void Connection::bind_query(NanCb info) { const auto query_id = info[0].As(); const auto params = info[1].As(); const auto callback = info[2].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->query_prepared(query_id, params, callback); info.GetReturnValue().Set(ret); } void Connection::call_procedure(NanCb info) { // need to ensure the signature is changed (in js ?) to form (?) = call sproc (?, ? ... ); const auto query_id = info[0].As(); const auto query_object = info[1].As(); const auto params = info[2].As(); const auto callback = info[3].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->call_procedure(query_id, query_object, params, callback); info.GetReturnValue().Set(ret); } void Connection::unbind(NanCb info) { const auto query_id = info[0].As(); const auto callback = info[1].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->unbind_parameters(query_id, callback); info.GetReturnValue().Set(ret); } void Connection::free_statement(NanCb info) { const auto query_id = info[0].As(); const auto callback = info[1].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->free_statement(query_id, callback); info.GetReturnValue().Set(ret); } void Connection::read_column(NanCb info) { const auto query_id = info[0].As(); const auto number_rows = info[1].As(); const auto cb = info[2].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->read_column(query_id, number_rows, cb); info.GetReturnValue().Set(ret); } void Connection::read_next_result(NanCb info) { const auto query_id = info[0].As(); const auto callback = info[1].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->read_next_result(query_id, callback); info.GetReturnValue().Set(ret); } void Connection::open(NanCb info) { const auto connection_object = info[0].As(); const auto callback = info[1].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->open(connection_object, callback, info.This()); info.GetReturnValue().Set(ret); } void Connection::cancel_statement(NanCb info) { const auto query_id = info[0].As(); const auto callback = info[1].As(); const auto* const connection = Unwrap(info.This()); const auto ret = connection->connectionBridge->cancel(query_id, callback); info.GetReturnValue().Set(ret); } void Connection::polling_mode(NanCb info) { const auto query_id = info[0].As(); const auto v1 = info[1].As(); const auto callback = info[2].As(); const auto* const connection = Unwrap(info.This()); const nodeTypeFactory fact; const auto context = fact.isolate->GetCurrentContext(); const auto maybe = v1->Int32Value(context); const auto i32 = maybe.FromMaybe(0); const auto b1 = Nan::New(i32 > 0); const auto ret = connection->connectionBridge->polling_mode(query_id, b1, callback); info.GetReturnValue().Set(ret); } }