sqlalchemy-jdbcapi 2.0.0.post2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sqlalchemy_jdbcapi/__init__.py +128 -0
- sqlalchemy_jdbcapi/_version.py +34 -0
- sqlalchemy_jdbcapi/dialects/__init__.py +30 -0
- sqlalchemy_jdbcapi/dialects/base.py +879 -0
- sqlalchemy_jdbcapi/dialects/db2.py +134 -0
- sqlalchemy_jdbcapi/dialects/mssql.py +117 -0
- sqlalchemy_jdbcapi/dialects/mysql.py +152 -0
- sqlalchemy_jdbcapi/dialects/oceanbase.py +218 -0
- sqlalchemy_jdbcapi/dialects/odbc_base.py +389 -0
- sqlalchemy_jdbcapi/dialects/odbc_mssql.py +69 -0
- sqlalchemy_jdbcapi/dialects/odbc_mysql.py +101 -0
- sqlalchemy_jdbcapi/dialects/odbc_oracle.py +80 -0
- sqlalchemy_jdbcapi/dialects/odbc_postgresql.py +63 -0
- sqlalchemy_jdbcapi/dialects/oracle.py +180 -0
- sqlalchemy_jdbcapi/dialects/postgresql.py +110 -0
- sqlalchemy_jdbcapi/dialects/sqlite.py +141 -0
- sqlalchemy_jdbcapi/jdbc/__init__.py +98 -0
- sqlalchemy_jdbcapi/jdbc/connection.py +244 -0
- sqlalchemy_jdbcapi/jdbc/cursor.py +329 -0
- sqlalchemy_jdbcapi/jdbc/dataframe.py +198 -0
- sqlalchemy_jdbcapi/jdbc/driver_manager.py +353 -0
- sqlalchemy_jdbcapi/jdbc/exceptions.py +53 -0
- sqlalchemy_jdbcapi/jdbc/jvm.py +176 -0
- sqlalchemy_jdbcapi/jdbc/type_converter.py +292 -0
- sqlalchemy_jdbcapi/jdbc/types.py +72 -0
- sqlalchemy_jdbcapi/odbc/__init__.py +46 -0
- sqlalchemy_jdbcapi/odbc/connection.py +136 -0
- sqlalchemy_jdbcapi/odbc/exceptions.py +48 -0
- sqlalchemy_jdbcapi/py.typed +2 -0
- sqlalchemy_jdbcapi-2.0.0.post2.dist-info/METADATA +825 -0
- sqlalchemy_jdbcapi-2.0.0.post2.dist-info/RECORD +36 -0
- sqlalchemy_jdbcapi-2.0.0.post2.dist-info/WHEEL +5 -0
- sqlalchemy_jdbcapi-2.0.0.post2.dist-info/entry_points.txt +20 -0
- sqlalchemy_jdbcapi-2.0.0.post2.dist-info/licenses/AUTHORS +7 -0
- sqlalchemy_jdbcapi-2.0.0.post2.dist-info/licenses/LICENSE +13 -0
- sqlalchemy_jdbcapi-2.0.0.post2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ODBC connection wrapper.
|
|
3
|
+
|
|
4
|
+
Provides a thin wrapper around pyodbc connections for consistency with
|
|
5
|
+
the JDBC bridge interface.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from .exceptions import (
|
|
14
|
+
DatabaseError,
|
|
15
|
+
InterfaceError,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Connection:
|
|
22
|
+
"""
|
|
23
|
+
ODBC connection wrapper.
|
|
24
|
+
|
|
25
|
+
Wraps pyodbc.Connection to provide a consistent interface with the JDBC bridge.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, pyodbc_connection: Any) -> None:
|
|
29
|
+
"""
|
|
30
|
+
Initialize ODBC connection wrapper.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
pyodbc_connection: Underlying pyodbc connection object.
|
|
34
|
+
"""
|
|
35
|
+
self._connection = pyodbc_connection
|
|
36
|
+
self._closed = False
|
|
37
|
+
|
|
38
|
+
def cursor(self) -> Any:
|
|
39
|
+
"""
|
|
40
|
+
Create a new cursor.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Cursor object.
|
|
44
|
+
"""
|
|
45
|
+
if self._closed:
|
|
46
|
+
raise InterfaceError("Connection is closed")
|
|
47
|
+
return self._connection.cursor()
|
|
48
|
+
|
|
49
|
+
def commit(self) -> None:
|
|
50
|
+
"""Commit the current transaction."""
|
|
51
|
+
if self._closed:
|
|
52
|
+
raise InterfaceError("Connection is closed")
|
|
53
|
+
try:
|
|
54
|
+
self._connection.commit()
|
|
55
|
+
except Exception as e:
|
|
56
|
+
raise DatabaseError(f"Failed to commit transaction: {e}") from e
|
|
57
|
+
|
|
58
|
+
def rollback(self) -> None:
|
|
59
|
+
"""Roll back the current transaction."""
|
|
60
|
+
if self._closed:
|
|
61
|
+
raise InterfaceError("Connection is closed")
|
|
62
|
+
try:
|
|
63
|
+
self._connection.rollback()
|
|
64
|
+
except Exception as e:
|
|
65
|
+
raise DatabaseError(f"Failed to rollback transaction: {e}") from e
|
|
66
|
+
|
|
67
|
+
def close(self) -> None:
|
|
68
|
+
"""Close the connection."""
|
|
69
|
+
if not self._closed:
|
|
70
|
+
self._connection.close()
|
|
71
|
+
self._closed = True
|
|
72
|
+
|
|
73
|
+
def __enter__(self) -> Connection:
|
|
74
|
+
"""Context manager entry."""
|
|
75
|
+
return self
|
|
76
|
+
|
|
77
|
+
def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
|
78
|
+
"""Context manager exit."""
|
|
79
|
+
if exc_type is not None:
|
|
80
|
+
self.rollback()
|
|
81
|
+
else:
|
|
82
|
+
self.commit()
|
|
83
|
+
self.close()
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def closed(self) -> bool:
|
|
87
|
+
"""Check if connection is closed."""
|
|
88
|
+
return self._closed
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def connect(
|
|
92
|
+
connection_string: str,
|
|
93
|
+
autocommit: bool = False,
|
|
94
|
+
timeout: int | None = None,
|
|
95
|
+
**kwargs: Any,
|
|
96
|
+
) -> Connection:
|
|
97
|
+
"""
|
|
98
|
+
Create an ODBC connection.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
connection_string: ODBC connection string.
|
|
102
|
+
autocommit: Enable autocommit mode.
|
|
103
|
+
timeout: Connection timeout in seconds.
|
|
104
|
+
**kwargs: Additional connection parameters.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
ODBC Connection object.
|
|
108
|
+
|
|
109
|
+
Raises:
|
|
110
|
+
InterfaceError: If pyodbc is not installed.
|
|
111
|
+
DatabaseError: If connection fails.
|
|
112
|
+
"""
|
|
113
|
+
try:
|
|
114
|
+
import pyodbc
|
|
115
|
+
except ImportError as e:
|
|
116
|
+
raise InterfaceError(
|
|
117
|
+
"pyodbc is not installed. Install with: pip install pyodbc"
|
|
118
|
+
) from e
|
|
119
|
+
|
|
120
|
+
try:
|
|
121
|
+
# Build connection string with parameters
|
|
122
|
+
params = dict(kwargs)
|
|
123
|
+
if timeout is not None:
|
|
124
|
+
params["timeout"] = timeout
|
|
125
|
+
if autocommit:
|
|
126
|
+
params["autocommit"] = True
|
|
127
|
+
|
|
128
|
+
# Create connection
|
|
129
|
+
conn = pyodbc.connect(connection_string, **params)
|
|
130
|
+
|
|
131
|
+
logger.info("ODBC connection established")
|
|
132
|
+
return Connection(conn)
|
|
133
|
+
|
|
134
|
+
except pyodbc.Error as e:
|
|
135
|
+
logger.error(f"Failed to connect to database: {e}")
|
|
136
|
+
raise DatabaseError(f"Failed to connect: {e}") from e
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ODBC-specific exceptions.
|
|
3
|
+
|
|
4
|
+
Most exceptions are proxied from pyodbc, but we provide our own hierarchy
|
|
5
|
+
for consistency with DB-API 2.0 specification.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Error(Exception):
|
|
12
|
+
"""Base exception for all ODBC errors."""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Warning(Exception): # noqa: A001
|
|
16
|
+
"""Exception raised for important warnings."""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class InterfaceError(Error):
|
|
20
|
+
"""Exception raised for errors related to the database interface."""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class DatabaseError(Error):
|
|
24
|
+
"""Exception raised for errors related to the database."""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class InternalError(DatabaseError):
|
|
28
|
+
"""Exception raised for internal database errors."""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class OperationalError(DatabaseError):
|
|
32
|
+
"""Exception raised for operational database errors."""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ProgrammingError(DatabaseError):
|
|
36
|
+
"""Exception raised for programming errors."""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class IntegrityError(DatabaseError):
|
|
40
|
+
"""Exception raised for database integrity errors."""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class DataError(DatabaseError):
|
|
44
|
+
"""Exception raised for data processing errors."""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class NotSupportedError(DatabaseError):
|
|
48
|
+
"""Exception raised for unsupported operations."""
|