Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 13 additions & 0 deletions docs/reference/adapters/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ exports a typed config class and a driver implementation.

Sync + Async SQL Server via Microsoft's official mssql-python driver.

.. grid-item-card:: pymssql
:link: pymssql
:link-type: doc

Sync SQL Server via pymssql / FreeTDS.

Feature Comparison
==================

Expand Down Expand Up @@ -235,6 +241,12 @@ Feature Comparison
- Yes
-
-
* - pymssql
- Yes
-
- Yes
-
-

.. toctree::
:hidden:
Expand All @@ -257,3 +269,4 @@ Feature Comparison
adbc
arrow_odbc
mssql_python
pymssql
57 changes: 57 additions & 0 deletions docs/reference/adapters/pymssql.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
========
pymssql
========

Sync SQL Server adapter using `pymssql <https://pypi.org/project/pymssql/>`_
and FreeTDS. It uses pyformat parameters (``%s`` and ``%(name)s``) and exposes
sync SQLSpec config, driver, pooling, data dictionary, migration, and extension
store integrations.

Configuration
=============

.. autoclass:: sqlspec.adapters.pymssql.PymssqlConfig
:members:
:show-inheritance:

Connection Parameters
=====================

.. autoclass:: sqlspec.adapters.pymssql.config.PymssqlConnectionParams
:members:
:show-inheritance:

Driver Features
===============

.. autoclass:: sqlspec.adapters.pymssql.config.PymssqlDriverFeatures
:members:
:show-inheritance:

Driver
======

.. autoclass:: sqlspec.adapters.pymssql.PymssqlDriver
:members:
:show-inheritance:

Connection Pool
===============

.. autoclass:: sqlspec.adapters.pymssql.PymssqlConnectionPool
:members:
:show-inheritance:

Data Dictionary
===============

.. autoclass:: sqlspec.adapters.pymssql.data_dictionary.PymssqlSyncDataDictionary
:members:
:show-inheritance:

Migrations
==========

.. autoclass:: sqlspec.adapters.pymssql.migrations.PymssqlSyncMigrationTracker
:members:
:show-inheritance:
1 change: 1 addition & 0 deletions docs/usage/drivers_and_querying.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Supported Drivers (High Level)
- **PostgreSQL**: asyncpg, psycopg (sync/async), psqlpy, ADBC
- **SQLite**: sqlite3, aiosqlite, ADBC
- **MySQL**: asyncmy, mysql-connector, pymysql
- **SQL Server**: mssql-python, pymssql, arrow-odbc
- **Analytics / Cloud**: DuckDB, BigQuery, Spanner, Oracle, ADBC

Core Execution Pattern
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,8 @@ module = [
"asyncmy.*",
"mssql_python",
"mssql_python.*",
"pymssql",
"pymssql.*",
"pyarrow",
"pyarrow.*",
"opentelemetry.*",
Expand Down
26 changes: 26 additions & 0 deletions sqlspec/adapters/pymssql/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""pymssql adapter for SQLSpec."""

from sqlspec.adapters.pymssql._typing import PymssqlConnection, PymssqlCursor
from sqlspec.adapters.pymssql.config import (
PymssqlConfig,
PymssqlConnectionParams,
PymssqlDriverFeatures,
PymssqlPoolParams,
)
from sqlspec.adapters.pymssql.core import default_statement_config, driver_profile
from sqlspec.adapters.pymssql.driver import PymssqlDriver, PymssqlExceptionHandler
from sqlspec.adapters.pymssql.pool import PymssqlConnectionPool

__all__ = (
"PymssqlConfig",
"PymssqlConnection",
"PymssqlConnectionParams",
"PymssqlConnectionPool",
"PymssqlCursor",
"PymssqlDriver",
"PymssqlDriverFeatures",
"PymssqlExceptionHandler",
"PymssqlPoolParams",
"default_statement_config",
"driver_profile",
)
95 changes: 95 additions & 0 deletions sqlspec/adapters/pymssql/_typing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
"""pymssql adapter type definitions.

This module contains type aliases and classes that are excluded from mypyc
compilation to avoid ABI boundary issues.
"""

import contextlib
from typing import TYPE_CHECKING, Any

from sqlspec.typing import import_optional, import_optional_attr

PYMSSQL_MODULE: Any = import_optional("pymssql")

if TYPE_CHECKING:
from collections.abc import Callable
from types import TracebackType
from typing import TypeAlias

from sqlspec.adapters.pymssql.driver import PymssqlDriver
from sqlspec.core import StatementConfig

PymssqlConnection: TypeAlias = Any
PymssqlRawCursor: TypeAlias = Any

if not TYPE_CHECKING:
PymssqlConnection = import_optional_attr("pymssql", "Connection") or Any
PymssqlRawCursor = import_optional_attr("pymssql", "Cursor") or Any

__all__ = ("PYMSSQL_MODULE", "PymssqlConnection", "PymssqlCursor", "PymssqlRawCursor", "PymssqlSessionContext")


class PymssqlCursor:
"""Context manager for pymssql cursor operations."""

__slots__ = ("connection", "cursor")

def __init__(self, connection: "PymssqlConnection") -> None:
self.connection = connection
self.cursor: PymssqlRawCursor | None = None

def __enter__(self) -> "PymssqlRawCursor":
self.cursor = self.connection.cursor()
return self.cursor

def __exit__(self, *_: Any) -> None:
if self.cursor is not None:
with contextlib.suppress(Exception):
self.cursor.close()


class PymssqlSessionContext:
"""Sync context manager for pymssql sessions."""

__slots__ = (
"_acquire_connection",
"_connection",
"_driver",
"_driver_features",
"_prepare_driver",
"_release_connection",
"_statement_config",
)

def __init__(
self,
acquire_connection: "Callable[[], Any]",
release_connection: "Callable[[Any], Any]",
statement_config: "StatementConfig",
driver_features: "dict[str, Any]",
prepare_driver: "Callable[[PymssqlDriver], PymssqlDriver]",
) -> None:
self._acquire_connection = acquire_connection
self._release_connection = release_connection
self._statement_config = statement_config
self._driver_features = driver_features
self._prepare_driver = prepare_driver
self._connection: Any = None
self._driver: PymssqlDriver | None = None

def __enter__(self) -> "PymssqlDriver":
from sqlspec.adapters.pymssql.driver import PymssqlDriver

self._connection = self._acquire_connection()
self._driver = PymssqlDriver(
connection=self._connection, statement_config=self._statement_config, driver_features=self._driver_features
)
return self._prepare_driver(self._driver)

def __exit__(
self, exc_type: "type[BaseException] | None", exc_val: "BaseException | None", exc_tb: "TracebackType | None"
) -> "bool | None":
if self._connection is not None:
self._release_connection(self._connection)
self._connection = None
return None
10 changes: 10 additions & 0 deletions sqlspec/adapters/pymssql/adk/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""pymssql ADK extension."""

from sqlspec.adapters.pymssql.adk.store import (
PymssqlADKConfig,
PymssqlADKMemoryStore,
PymssqlADKStore,
PymssqlSyncADKStore,
)

__all__ = ("PymssqlADKConfig", "PymssqlADKMemoryStore", "PymssqlADKStore", "PymssqlSyncADKStore")
Loading
Loading