Skip to content

Commit 998b25e

Browse files
Saumya Garggargsaumya
authored andcommitted
initial edit
1 parent fc5903a commit 998b25e

3 files changed

Lines changed: 61 additions & 183 deletions

File tree

mssql_python/pybind/connection/connection.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
#include "connection.h"
88
#include <iostream>
9+
#include <vector>
10+
11+
#include <pybind11/pybind11.h>
12+
913

1014
//-------------------------------------------------------------------------------------------------
1115
// Implements the Connection class declared in connection.h.
@@ -114,11 +118,55 @@ bool Connection::getAutocommit() const {
114118
return value == SQL_AUTOCOMMIT_ON;
115119
}
116120

121+
<<<<<<< HEAD
117122
SqlHandlePtr Connection::allocStatementHandle() {
118123
if (!_dbc_handle) {
119124
throw std::runtime_error("Connection handle not allocated");
120125
}
121126
LOG("Allocating statement handle");
127+
=======
128+
SQLRETURN set_attribute(SQLINTEGER Attribute, py::object ValuePtr) {
129+
LOG("Set SQL Connection Attribute");
130+
if (!SQLSetConnectAttr_ptr) {
131+
LOG("Function pointer not initialized. Loading the driver.");
132+
DriverLoader::getInstance().loadDriver(); // Load the driver
133+
}
134+
135+
// Print the type of ValuePtr and attribute value - helpful for debugging
136+
LOG("Type of ValuePtr: {}, Attribute: {}", py::type::of(ValuePtr).attr("__name__").cast<std::string>(), Attribute);
137+
138+
SQLPOINTER value = 0;
139+
SQLINTEGER length = 0;
140+
141+
if (py::isinstance<py::int_>(ValuePtr)) {
142+
// Handle integer values
143+
int intValue = ValuePtr.cast<int>();
144+
value = reinterpret_cast<SQLPOINTER>(intValue);
145+
length = SQL_IS_INTEGER; // Integer values don't require a length
146+
} else if (py::isinstance<py::bytes>(ValuePtr) || py::isinstance<py::bytearray>(ValuePtr)) {
147+
// Handle byte or bytearray values (like access tokens)
148+
// Store in static buffer to ensure memory remains valid during connection
149+
static std::vector<std::string> bytesBuffers;
150+
bytesBuffers.push_back(ValuePtr.cast<std::string>());
151+
value = const_cast<char*>(bytesBuffers.back().c_str());
152+
length = SQL_IS_POINTER; // Indicates we're passing a pointer (required for token)
153+
} else {
154+
LOG("Unsupported ValuePtr type");
155+
return SQL_ERROR;
156+
}
157+
158+
SQLRETURN ret = SQLSetConnectAttr_ptr(_dbc_handle->get(), Attribute, value, length);
159+
if (!SQL_SUCCEEDED(ret)) {
160+
LOG("Failed to set Connection attribute");
161+
}
162+
else {
163+
LOG("Set Connection attribute successfully");
164+
}
165+
return ret;
166+
}
167+
168+
SqlHandlePtr Connection::alloc_statement_handle() {
169+
>>>>>>> 52a2dba (initial edit)
122170
SQLHANDLE stmt = nullptr;
123171
SQLRETURN ret = SQLAllocHandle_ptr(SQL_HANDLE_STMT, _dbc_handle->get(), &stmt);
124172
if (!SQL_SUCCEEDED(ret)) {

mssql_python/pybind/ddbc_bindings.cpp

Lines changed: 13 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -671,134 +671,6 @@ void SqlHandle::free() {
671671
}
672672
}
673673

674-
// Wrap SQLAllocHandle
675-
SQLRETURN SQLAllocHandle_wrap(SQLSMALLINT HandleType, SqlHandlePtr InputHandle, SqlHandlePtr& OutputHandle) {
676-
LOG("Allocate SQL Handle");
677-
if (!SQLAllocHandle_ptr) {
678-
LOG("Function pointer not initialized. Loading the driver.");
679-
DriverLoader::getInstance().loadDriver(); // Load the driver
680-
}
681-
682-
SQLHANDLE rawOutputHandle = nullptr;
683-
SQLRETURN ret = SQLAllocHandle_ptr(HandleType, InputHandle ? InputHandle->get() : nullptr, &rawOutputHandle);
684-
if (!SQL_SUCCEEDED(ret)) {
685-
LOG("Failed to allocate handle");
686-
return ret;
687-
}
688-
OutputHandle = std::make_shared<SqlHandle>(HandleType, rawOutputHandle);
689-
return ret;
690-
}
691-
692-
// Wrap SQLSetEnvAttr
693-
SQLRETURN SQLSetEnvAttr_wrap(SqlHandlePtr EnvHandle, SQLINTEGER Attribute, intptr_t ValuePtr,
694-
SQLINTEGER StringLength) {
695-
LOG("Set SQL environment Attribute");
696-
if (!SQLSetEnvAttr_ptr) {
697-
LOG("Function pointer not initialized. Loading the driver.");
698-
DriverLoader::getInstance().loadDriver(); // Load the driver
699-
}
700-
701-
// TODO: Does ValuePtr need to be converted from Python to C++ object?
702-
SQLRETURN ret = SQLSetEnvAttr_ptr(EnvHandle->get(), Attribute, reinterpret_cast<SQLPOINTER>(ValuePtr), StringLength);
703-
if (!SQL_SUCCEEDED(ret)) {
704-
LOG("Failed to set environment attribute");
705-
}
706-
return ret;
707-
}
708-
709-
// Wrap SQLSetConnectAttr
710-
SQLRETURN SQLSetConnectAttr_wrap(SqlHandlePtr ConnectionHandle, SQLINTEGER Attribute,
711-
py::object ValuePtr) {
712-
LOG("Set SQL Connection Attribute");
713-
if (!SQLSetConnectAttr_ptr) {
714-
LOG("Function pointer not initialized. Loading the driver.");
715-
DriverLoader::getInstance().loadDriver(); // Load the driver
716-
}
717-
718-
// Print the type of ValuePtr and attribute value - helpful for debugging
719-
LOG("Type of ValuePtr: {}, Attribute: {}", py::type::of(ValuePtr).attr("__name__").cast<std::string>(), Attribute);
720-
721-
SQLPOINTER value = 0;
722-
SQLINTEGER length = 0;
723-
724-
if (py::isinstance<py::int_>(ValuePtr)) {
725-
// Handle integer values
726-
int intValue = ValuePtr.cast<int>();
727-
value = reinterpret_cast<SQLPOINTER>(intValue);
728-
length = SQL_IS_INTEGER; // Integer values don't require a length
729-
// } else if (py::isinstance<py::str>(ValuePtr)) {
730-
// // Handle Unicode string values
731-
// static std::wstring unicodeValueBuffer;
732-
// unicodeValueBuffer = ValuePtr.cast<std::wstring>();
733-
// value = const_cast<SQLWCHAR*>(unicodeValueBuffer.c_str());
734-
// length = SQL_NTS; // Indicates null-terminated string
735-
} else if (py::isinstance<py::bytes>(ValuePtr) || py::isinstance<py::bytearray>(ValuePtr)) {
736-
// Handle byte or bytearray values (like access tokens)
737-
// Store in static buffer to ensure memory remains valid during connection
738-
static std::vector<std::string> bytesBuffers;
739-
bytesBuffers.push_back(ValuePtr.cast<std::string>());
740-
value = const_cast<char*>(bytesBuffers.back().c_str());
741-
length = SQL_IS_POINTER; // Indicates we're passing a pointer (required for token)
742-
// } else if (py::isinstance<py::list>(ValuePtr) || py::isinstance<py::tuple>(ValuePtr)) {
743-
// // Handle list or tuple values
744-
// LOG("ValuePtr is a sequence (list or tuple)");
745-
// for (py::handle item : ValuePtr) {
746-
// LOG("Processing item in sequence");
747-
// SQLRETURN ret = SQLSetConnectAttr_wrap(ConnectionHandle, Attribute, py::reinterpret_borrow<py::object>(item));
748-
// if (!SQL_SUCCEEDED(ret)) {
749-
// LOG("Failed to set attribute for item in sequence");
750-
// return ret;
751-
// }
752-
// }
753-
} else {
754-
LOG("Unsupported ValuePtr type");
755-
return SQL_ERROR;
756-
}
757-
758-
SQLRETURN ret = SQLSetConnectAttr_ptr(ConnectionHandle->get(), Attribute, value, length);
759-
if (!SQL_SUCCEEDED(ret)) {
760-
LOG("Failed to set Connection attribute");
761-
}
762-
LOG("Set Connection attribute successfully");
763-
return ret;
764-
}
765-
766-
// Wrap SQLSetStmtAttr
767-
SQLRETURN SQLSetStmtAttr_wrap(SqlHandlePtr StatementHandle, SQLINTEGER Attribute, intptr_t ValuePtr,
768-
SQLINTEGER StringLength) {
769-
LOG("Set SQL Statement Attribute");
770-
if (!SQLSetConnectAttr_ptr) {
771-
LOG("Function pointer not initialized. Loading the driver.");
772-
DriverLoader::getInstance().loadDriver(); // Load the driver
773-
}
774-
775-
// TODO: Does ValuePtr need to be converted from Python to C++ object?
776-
SQLRETURN ret = SQLSetStmtAttr_ptr(StatementHandle->get(), Attribute, reinterpret_cast<SQLPOINTER>(ValuePtr), StringLength);
777-
if (!SQL_SUCCEEDED(ret)) {
778-
LOG("Failed to set Statement attribute");
779-
}
780-
return ret;
781-
}
782-
783-
// Wrap SQLGetConnectionAttrA
784-
// Currently only supports retrieval of int-valued attributes
785-
// TODO: add support to retrieve all types of attributes
786-
SQLINTEGER SQLGetConnectionAttr_wrap(SqlHandlePtr ConnectionHandle, SQLINTEGER attribute) {
787-
LOG("Get SQL COnnection Attribute");
788-
if (!SQLGetConnectAttr_ptr) {
789-
LOG("Function pointer not initialized. Loading the driver.");
790-
DriverLoader::getInstance().loadDriver(); // Load the driver
791-
}
792-
793-
SQLINTEGER stringLength;
794-
SQLINTEGER intValue;
795-
796-
// Try to get the attribute as an integer
797-
SQLGetConnectAttr_ptr(ConnectionHandle->get(), attribute, &intValue,
798-
sizeof(SQLINTEGER), &stringLength);
799-
return intValue;
800-
}
801-
802674
// Helper function to check for driver errors
803675
ErrorInfo SQLCheckError_Wrap(SQLSMALLINT handleType, SqlHandlePtr handle, SQLRETURN retcode) {
804676
LOG("Checking errors for retcode - {}" , retcode);
@@ -832,23 +704,6 @@ ErrorInfo SQLCheckError_Wrap(SQLSMALLINT handleType, SqlHandlePtr handle, SQLRET
832704
return errorInfo;
833705
}
834706

835-
// Wrap SQLDriverConnect
836-
SQLRETURN SQLDriverConnect_wrap(SqlHandlePtr ConnectionHandle, intptr_t WindowHandle, const std::wstring& ConnectionString) {
837-
LOG("Driver Connect to MSSQL");
838-
if (!SQLDriverConnect_ptr) {
839-
LOG("Function pointer not initialized. Loading the driver.");
840-
DriverLoader::getInstance().loadDriver(); // Load the driver
841-
}
842-
SQLRETURN ret = SQLDriverConnect_ptr(ConnectionHandle->get(),
843-
reinterpret_cast<SQLHWND>(WindowHandle),
844-
const_cast<SQLWCHAR*>(ConnectionString.c_str()), SQL_NTS, nullptr,
845-
0, nullptr, SQL_DRIVER_NOPROMPT);
846-
if (!SQL_SUCCEEDED(ret)) {
847-
LOG("Failed to connect to DB");
848-
}
849-
return ret;
850-
}
851-
852707
// Wrap SQLExecDirect
853708
SQLRETURN SQLExecDirect_wrap(SqlHandlePtr StatementHandle, const std::wstring& Query) {
854709
LOG("Execute SQL query directly - {}", Query.c_str());
@@ -2004,17 +1859,6 @@ SQLRETURN SQLMoreResults_wrap(SqlHandlePtr StatementHandle) {
20041859
return SQLMoreResults_ptr(StatementHandle->get());
20051860
}
20061861

2007-
// Wrap SQLEndTran
2008-
SQLRETURN SQLEndTran_wrap(SQLSMALLINT HandleType, SqlHandlePtr Handle, SQLSMALLINT CompletionType) {
2009-
LOG("End SQL Transaction");
2010-
if (!SQLEndTran_ptr) {
2011-
LOG("Function pointer not initialized. Loading the driver.");
2012-
DriverLoader::getInstance().loadDriver(); // Load the driver
2013-
}
2014-
2015-
return SQLEndTran_ptr(HandleType, Handle->get(), CompletionType);
2016-
}
2017-
20181862
// Wrap SQLFreeHandle
20191863
SQLRETURN SQLFreeHandle_wrap(SQLSMALLINT HandleType, SqlHandlePtr Handle) {
20201864
LOG("Free SQL handle");
@@ -2030,17 +1874,6 @@ SQLRETURN SQLFreeHandle_wrap(SQLSMALLINT HandleType, SqlHandlePtr Handle) {
20301874
return ret;
20311875
}
20321876

2033-
// Wrap SQLDisconnect
2034-
SQLRETURN SQLDisconnect_wrap(SqlHandlePtr ConnectionHandle) {
2035-
LOG("Disconnect from MSSQL");
2036-
if (!SQLDisconnect_ptr) {
2037-
LOG("Function pointer not initialized. Loading the driver.");
2038-
DriverLoader::getInstance().loadDriver(); // Load the driver
2039-
}
2040-
2041-
return SQLDisconnect_ptr(ConnectionHandle->get());
2042-
}
2043-
20441877
// Wrap SQLRowCount
20451878
SQLLEN SQLRowCount_wrap(SqlHandlePtr StatementHandle) {
20461879
LOG("Get number of row affected by last execute");
@@ -2102,22 +1935,21 @@ PYBIND11_MODULE(ddbc_bindings, m) {
21021935

21031936
py::class_<SqlHandle, SqlHandlePtr>(m, "SqlHandle")
21041937
.def("free", &SqlHandle::free);
2105-
2106-
m.def("DDBCSQLAllocHandle", [](SQLSMALLINT HandleType, SqlHandlePtr InputHandle = nullptr) {
2107-
SqlHandlePtr OutputHandle;
2108-
SQLRETURN rc = SQLAllocHandle_wrap(HandleType, InputHandle, OutputHandle);
2109-
return py::make_tuple(rc, OutputHandle);
2110-
}, "Allocate an environment, connection, statement, or descriptor handle");
2111-
m.def("DDBCSQLSetEnvAttr", &SQLSetEnvAttr_wrap,
2112-
"Set an attribute that governs aspects of environments");
1938+
py::class_<Connection>(m, "Connection")
1939+
.def(py::init<const std::wstring&, bool>(), py::arg("conn_str"))
1940+
.def("connect", &Connection::connect, "Establish a connection to the database")
1941+
.def("close", &Connection::close, "Close the connection")
1942+
.def("commit", [](Connection& self) {
1943+
self.end_transaction(SQL_COMMIT);
1944+
})
1945+
.def("rollback", [](Connection& self) {
1946+
self.end_transaction(SQL_ROLLBACK)})
1947+
.def("set_autocommit", &Connection::set_autocommit)
1948+
.def("get_autocommit", &Connection::get_autocommit)
1949+
.def("set_attribute", &Connection::set_attribute);
1950+
.def("alloc_statement_handle", &Connection::alloc_statement_handle);
21131951
m.def("DDBCSQLSetConnectAttr", &SQLSetConnectAttr_wrap,
21141952
"Set an attribute that governs aspects of connections");
2115-
m.def("DDBCSQLSetStmtAttr", &SQLSetStmtAttr_wrap,
2116-
"Set an attribute that governs aspects of statements");
2117-
m.def("DDBCSQLGetConnectionAttr", &SQLGetConnectionAttr_wrap,
2118-
"Get an attribute that governs aspects of connections");
2119-
m.def("DDBCSQLDriverConnect", &SQLDriverConnect_wrap,
2120-
"Connect to a data source with a connection string");
21211953
m.def("DDBCSQLExecDirect", &SQLExecDirect_wrap, "Execute a SQL query directly");
21221954
m.def("DDBCSQLExecute", &SQLExecute_wrap, "Prepare and execute T-SQL statements");
21231955
m.def("DDBCSQLRowCount", &SQLRowCount_wrap,
@@ -2135,7 +1967,6 @@ PYBIND11_MODULE(ddbc_bindings, m) {
21351967
m.def("DDBCSQLFetchAll", &FetchAll_wrap, "Fetch all rows from the result set");
21361968
m.def("DDBCSQLEndTran", &SQLEndTran_wrap, "End a transaction");
21371969
m.def("DDBCSQLFreeHandle", &SQLFreeHandle_wrap, "Free a handle");
2138-
m.def("DDBCSQLDisconnect", &SQLDisconnect_wrap, "Disconnect from a data source");
21391970
m.def("DDBCSQLCheckError", &SQLCheckError_Wrap, "Check for driver errors");
21401971

21411972
// Add a version attribute

mssql_python/pybind/ddbc_bindings.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
// INFO|TODO - Note that is file is Windows specific right now. Making it arch agnostic will be
55
// taken up in future.
66

7-
>>>>>>> 1182190 (resolve review comments)
87
#pragma once
98

109
#include <Windows.h>

0 commit comments

Comments
 (0)