Skip to content

Commit 896f34d

Browse files
author
Saumya Garg
committed
refining
1 parent 015c430 commit 896f34d

File tree

2 files changed

+101
-49
lines changed

2 files changed

+101
-49
lines changed

mssql_python/pybind/connection/connection.cpp

Lines changed: 84 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,84 +12,100 @@
1212
// This class wraps low-level ODBC operations like connect/disconnect,
1313
// transaction control, and autocommit configuration.
1414
//-------------------------------------------------------------------------------------------------
15-
Connection::Connection(const std::wstring& conn_str, bool autocommit) : _conn_str(conn_str) , _autocommit(autocommit) {}
15+
Connection::Connection(const std::wstring& conn_str, bool autocommit)
16+
: _conn_str(conn_str) , _autocommit(autocommit) {}
1617

1718
Connection::~Connection() {
18-
close(); // Ensure the connection is closed when the object is destroyed.
19+
close(); // Ensure the connection is closed when the object is destroyed.
1920
}
2021

2122
SQLRETURN Connection::connect() {
22-
SQLHANDLE env = nullptr;
23-
SQLHANDLE dbc = nullptr;
24-
25-
LOG("Allocate SQL Handle");
26-
if (!SQLAllocHandle_ptr) {
27-
LOG("Function pointer not initialized. Loading the driver.");
28-
DriverLoader::getInstance().loadDriver();
29-
}
30-
SQLRETURN ret = SQLAllocHandle_ptr(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
31-
if (!SQL_SUCCEEDED(ret)) {
32-
LOG("Failed to allocate environment handle");
33-
throw std::runtime_error("Failed to allocate environment handle");
34-
}
35-
_env_handle = std::make_shared<SqlHandle>(SQL_HANDLE_ENV, env);
36-
37-
ret = SQLSetEnvAttr_ptr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3_80, 0);
38-
if (!SQL_SUCCEEDED(ret)) {
39-
LOG("Failed to set environment attribute");
40-
throw std::runtime_error("Failed to set environment attribute");
41-
}
23+
allocDbcHandle();
24+
return connectToDb();
25+
}
4226

27+
// Allocates DBC handle
28+
void Connection::allocDbcHandle() {
29+
SQLHANDLE dbc = nullptr;
4330
LOG("Allocate SQL Connection Handle");
44-
ret = SQLAllocHandle_ptr(SQL_HANDLE_DBC, env, &dbc);
31+
SQLRETURN ret = SQLAllocHandle_ptr(SQL_HANDLE_DBC, getSharedEnvHandle()->get(), &dbc);
4532
if (!SQL_SUCCEEDED(ret)) {
46-
LOG("Failed to allocate connection handle");
4733
throw std::runtime_error("Failed to allocate connection handle");
4834
}
4935
_dbc_handle = std::make_shared<SqlHandle>(SQL_HANDLE_DBC, dbc);
36+
}
5037

51-
ret = SQLDriverConnect_ptr(dbc, nullptr,
38+
// Connects to the database
39+
SQLRETURN Connection::connectToDb() {
40+
LOG("Connecting to database");
41+
SQLRETURN ret = SQLDriverConnect_ptr(_dbc_handle->get(), nullptr,
5242
(SQLWCHAR*)_conn_str.c_str(), SQL_NTS,
5343
nullptr, 0, nullptr, SQL_DRIVER_NOPROMPT);
5444
if (!SQL_SUCCEEDED(ret)) {
55-
LOG("Failed to connect to database");
56-
}
57-
else {
58-
LOG("Connected to database successfully");
45+
throw std::runtime_error("Failed to connect to database");
5946
}
47+
LOG("Connected to database successfully");
6048
return ret;
6149
}
6250

6351
SQLRETURN Connection::close() {
52+
if (!_dbc_handle) {
53+
LOG("No connection handle to close");
54+
return SQL_SUCCESS;
55+
}
6456
LOG("Disconnect from MSSQL");
6557
if (!SQLDisconnect_ptr) {
6658
LOG("Function pointer not initialized. Loading the driver.");
6759
DriverLoader::getInstance().loadDriver();
6860
}
6961

70-
return SQLDisconnect_ptr(_dbc_handle->get());
62+
SQLRETURN ret = SQLDisconnect_ptr(_dbc_handle->get());
63+
_dbc_handle.reset();
64+
return ret;
7165
}
7266

73-
SQLRETURN Connection::end_transaction(SQLSMALLINT completion_type) {
74-
LOG(completion_type == SQL_COMMIT ? "End SQL Transaction (Commit)" : "End SQL Transaction (Rollback)");
75-
if (!SQLEndTran_ptr) {
76-
LOG("Function pointer not initialized. Loading the driver.");
77-
DriverLoader::getInstance().loadDriver();
67+
SQLRETURN Connection::commit() {
68+
if (!_dbc_handle) {
69+
throw std::runtime_error("Connection handle not allocated");
70+
}
71+
LOG("Committing transaction");
72+
SQLRETURN ret = SQLEndTran_ptr(SQL_HANDLE_DBC, _dbc_handle->get(), SQL_COMMIT);
73+
if (!SQL_SUCCEEDED(ret)) {
74+
throw std::runtime_error("Failed to commit transaction");
7875
}
79-
return SQLEndTran_ptr(_dbc_handle->type(), _dbc_handle->get(), completion_type);
76+
return ret;
8077
}
8178

82-
SQLRETURN Connection::set_autocommit(bool enable) {
79+
SQLRETURN Connection::rollback() {
80+
if (!_dbc_handle) {
81+
throw std::runtime_error("Connection handle not allocated");
82+
}
83+
LOG("Rolling back transaction");
84+
SQLRETURN ret = SQLEndTran_ptr(SQL_HANDLE_DBC, _dbc_handle->get(), SQL_ROLLBACK);
85+
if (!SQL_SUCCEEDED(ret)) {
86+
throw std::runtime_error("Failed to rollback transaction");
87+
}
88+
return ret;
89+
}
90+
91+
SQLRETURN Connection::setAutocommit(bool enable) {
92+
if (!_dbc_handle) {
93+
throw std::runtime_error("Connection handle not allocated");
94+
}
8395
SQLINTEGER value = enable ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
8496
LOG("Set SQL Connection Attribute");
8597
SQLRETURN ret = SQLSetConnectAttr_ptr(_dbc_handle->get(), SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)value, 0);
8698
if (!SQL_SUCCEEDED(ret)) {
8799
throw std::runtime_error("Failed to set autocommit mode.");
88100
}
101+
_autocommit = enable;
89102
return ret;
90103
}
91104

92-
bool Connection::get_autocommit() const {
105+
bool Connection::getAutocommit() const {
106+
if (!_dbc_handle) {
107+
throw std::runtime_error("Connection handle not allocated");
108+
}
93109
LOG("Get SQL Connection Attribute");
94110
SQLINTEGER value;
95111
SQLINTEGER string_length;
@@ -98,12 +114,41 @@ bool Connection::get_autocommit() const {
98114
return value == SQL_AUTOCOMMIT_ON;
99115
}
100116

101-
SqlHandlePtr Connection::alloc_statement_handle() {
117+
SqlHandlePtr Connection::allocStatementHandle() {
118+
if (!_dbc_handle) {
119+
throw std::runtime_error("Connection handle not allocated");
120+
}
102121
LOG("Allocating statement handle");
103122
SQLHANDLE stmt = nullptr;
104123
SQLRETURN ret = SQLAllocHandle_ptr(SQL_HANDLE_STMT, _dbc_handle->get(), &stmt);
105124
if (!SQL_SUCCEEDED(ret)) {
106125
throw std::runtime_error("Failed to allocate statement handle");
107126
}
108127
return std::make_shared<SqlHandle>(SQL_HANDLE_STMT, stmt);
128+
}
129+
130+
SqlHandlePtr Connection::getSharedEnvHandle() {
131+
static std::once_flag flag;
132+
static SqlHandlePtr env_handle;
133+
134+
std::call_once(flag, []() {
135+
LOG("Allocating environment handle");
136+
SQLHANDLE env = nullptr;
137+
if (!SQLAllocHandle_ptr) {
138+
LOG("Function pointers not initialized, loading driver");
139+
DriverLoader::getInstance().loadDriver();
140+
}
141+
SQLRETURN ret = SQLAllocHandle_ptr(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
142+
if (!SQL_SUCCEEDED(ret)) {
143+
throw std::runtime_error("Failed to allocate environment handle");
144+
}
145+
env_handle = std::make_shared<SqlHandle>(SQL_HANDLE_ENV, env);
146+
147+
LOG("Setting environment attributes");
148+
ret = SQLSetEnvAttr_ptr(env_handle->get(), SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3_80, 0);
149+
if (!SQL_SUCCEEDED(ret)) {
150+
throw std::runtime_error("Failed to set environment attribute");
151+
}
152+
});
153+
return env_handle;
109154
}

mssql_python/pybind/connection/connection.h

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include "ddbc_bindings.h"
1111

1212
// Represents a single ODBC database connection.
13-
// Manages its own environment and connection handles.
13+
// Manages connection handles.
1414
// Note: This class does NOT implement pooling logic directly.
1515

1616
class Connection {
@@ -24,23 +24,30 @@ class Connection {
2424
// Close the connection and free resources.
2525
SQLRETURN close();
2626

27-
// End the transaction with the specified completion type.
28-
SQLRETURN end_transaction(SQLSMALLINT completion_type);
27+
// Commit the current transaction.
28+
SQLRETURN commit();
29+
30+
// Rollback the current transaction.
31+
SQLRETURN rollback();
2932

3033
// Enable or disable autocommit mode.
31-
SQLRETURN set_autocommit(bool value);
34+
SQLRETURN setAutocommit(bool value);
3235

3336
// Check whether autocommit is enabled.
34-
bool get_autocommit() const;
37+
bool getAutocommit() const;
3538

36-
SqlHandlePtr alloc_statement_handle(); // Will later be moved to cursor c++ class
39+
// Allocate a new statement handle on this connection.
40+
SqlHandlePtr allocStatementHandle();
3741

3842
private:
43+
void allocDbcHandle();
44+
SQLRETURN connectToDb();
3945

40-
std::wstring _conn_str; // Connection string
41-
SqlHandlePtr _env_handle; // Environment handle
42-
SqlHandlePtr _dbc_handle; // Connection handle
43-
46+
std::wstring _conn_str;
47+
SqlHandlePtr _dbc_handle;
4448
bool _autocommit = false;
49+
50+
static SqlHandlePtr getSharedEnvHandle();
4551
};
52+
4653
#endif // CONNECTION_H

0 commit comments

Comments
 (0)