Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
does not change the default provider or ship any Rust driver binaries.

### Changed
- Fetches reuse owned native metadata for stable columns within a result set;
`fetchmany()` avoids the Python metadata-dictionary roundtrip. Re-execution,
result transitions and statement/connection cleanup invalidate this metadata.
Public descriptions stay fresh, name-validation timing is preserved, and
`sql_variant` columns retain per-row descriptions and per-value probes.
Fetch buffers, decoding settings and converted values are not cached.
- DATE, TIME, and TIMESTAMP fetch conversion uses checked CPython constructors
for the standard datetime types, while preserving cached substitute constructors,
their positional arguments and exceptions, and fractional-second truncation.
Expand Down
24 changes: 24 additions & 0 deletions mssql_python/pybind/connection/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ void Connection::connect(const py::dict& attrs_before) {

void Connection::disconnect(bool rollbackBeforeDisconnect) {
PERF_TIMER("Connection::disconnect");
clearResultMetadata();
// Determine GIL state once, up front. disconnect() runs both from
// pybind11-bound methods (GIL held) and from GIL-less destructor / shutdown
// paths: Connection::~Connection() dropping the last shared_ptr, or teardown
Expand Down Expand Up @@ -265,13 +266,32 @@ void Connection::checkError(SQLRETURN ret) const {
}
}

void Connection::clearResultMetadata() {
std::vector<SqlHandlePtr> handles;
{
std::lock_guard<std::mutex> lock(_childHandlesMutex);
handles.reserve(_childStatementHandles.size());
for (const auto& weakHandle : _childStatementHandles) {
if (auto handle = weakHandle.lock()) {
handles.push_back(std::move(handle));
}
}
}
// Releasing the last handle can acquire the connection cleanup gate.
// Keep that destruction outside the child-list lock.
for (const auto& handle : handles) {
handle->resultMetadata.clear();
}
}

void Connection::commit() {
PERF_TIMER("Connection::commit");
if (!_dbcHandle) {
ThrowStdException("Connection handle not allocated");
}
updateLastUsed();
LOG("Committing transaction");
clearResultMetadata();
SQLRETURN ret;
{
// Release the GIL during the blocking SQLEndTran network round-trip.
Expand All @@ -288,6 +308,7 @@ void Connection::rollback() {
}
updateLastUsed();
LOG("Rolling back transaction");
clearResultMetadata();
SQLRETURN ret;
{
// Release the GIL during the blocking SQLEndTran network round-trip.
Expand All @@ -302,6 +323,7 @@ void Connection::setAutocommit(bool enable) {
if (!_dbcHandle) {
ThrowStdException("Connection handle not allocated");
}
clearResultMetadata();
SQLINTEGER value = enable ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
LOG("Setting autocommit=%d", enable);
SQLRETURN ret;
Expand Down Expand Up @@ -395,6 +417,7 @@ SqlHandlePtr Connection::allocStatementHandle() {
}

SQLRETURN Connection::setAttribute(SQLINTEGER attribute, py::object value) {
clearResultMetadata();
LOG("Setting SQL attribute=%d", attribute);
// SQLPOINTER ptr = nullptr;
// SQLINTEGER length = 0;
Expand Down Expand Up @@ -581,6 +604,7 @@ bool Connection::reset() {
if (!_dbcHandle) {
ThrowStdException("Connection handle not allocated");
}
clearResultMetadata();
LOG("Resetting connection via SQL_ATTR_RESET_CONNECTION");
// NOTE: SQL_ATTR_RESET_CONNECTION is a pool-checkin reset: it asks the
// driver to wipe per-session state (temp tables, open cursors, SET
Expand Down
1 change: 1 addition & 0 deletions mssql_python/pybind/connection/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class Connection {
void allocateDbcHandle();
void checkError(SQLRETURN ret) const;
void applyAttrsBefore(const py::dict& attrs_before);
void clearResultMetadata();

std::u16string _connStr;
bool _fromPool = false;
Expand Down
Loading
Loading