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,180 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Oracle JDBC dialect for SQLAlchemy.
|
|
3
|
+
|
|
4
|
+
Provides full Oracle Database support through JDBC, compatible with SQLAlchemy 2.0+.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
import re
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from sqlalchemy import exc, sql, util
|
|
14
|
+
from sqlalchemy.dialects.oracle.base import OracleDialect
|
|
15
|
+
from sqlalchemy.engine import Connection
|
|
16
|
+
|
|
17
|
+
from .base import BaseJDBCDialect, JDBCDriverConfig
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class OracleDialect(BaseJDBCDialect, OracleDialect): # type: ignore
|
|
23
|
+
"""
|
|
24
|
+
Oracle Database dialect using JDBC driver.
|
|
25
|
+
|
|
26
|
+
Supports Oracle-specific features including:
|
|
27
|
+
- Sequences
|
|
28
|
+
- Synonyms
|
|
29
|
+
- Database links
|
|
30
|
+
- Packages
|
|
31
|
+
- Custom types
|
|
32
|
+
|
|
33
|
+
Connection URL formats:
|
|
34
|
+
jdbcapi+oracle://user:password@host:1521/database
|
|
35
|
+
jdbcapi+oracle://user:password@host:1521/SID
|
|
36
|
+
jdbcapi+oraclejdbc://user:password@host:1521/service_name # Alias
|
|
37
|
+
|
|
38
|
+
For TNS connections:
|
|
39
|
+
jdbcapi+oracle://user:password@tnsname
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
name = "oracle"
|
|
43
|
+
driver = "jdbcapi"
|
|
44
|
+
|
|
45
|
+
# Oracle-specific capabilities
|
|
46
|
+
supports_sequences = True
|
|
47
|
+
supports_native_boolean = False # Oracle < 23c doesn't have native boolean
|
|
48
|
+
supports_identity_columns = True # Oracle 12c+
|
|
49
|
+
|
|
50
|
+
# Override column specifications for JDBC type handling
|
|
51
|
+
colspecs = util.update_copy(
|
|
52
|
+
OracleDialect.colspecs, # type: ignore
|
|
53
|
+
{
|
|
54
|
+
# Add JDBC-specific type mappings here if needed
|
|
55
|
+
},
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
@classmethod
|
|
59
|
+
def get_driver_config(cls) -> JDBCDriverConfig:
|
|
60
|
+
"""Get Oracle JDBC driver configuration."""
|
|
61
|
+
return JDBCDriverConfig(
|
|
62
|
+
driver_class="oracle.jdbc.OracleDriver",
|
|
63
|
+
jdbc_url_template="jdbc:oracle:thin:@{host}:{port}/{database}",
|
|
64
|
+
default_port=1521,
|
|
65
|
+
supports_transactions=True,
|
|
66
|
+
supports_schemas=True,
|
|
67
|
+
supports_sequences=True,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
def create_connect_args(self, url: Any) -> tuple[list[Any], dict[str, Any]]:
|
|
71
|
+
"""
|
|
72
|
+
Create connection arguments from SQLAlchemy URL.
|
|
73
|
+
|
|
74
|
+
Handles various Oracle connection formats including TNS names.
|
|
75
|
+
"""
|
|
76
|
+
config = self.get_driver_config()
|
|
77
|
+
|
|
78
|
+
# Check if this is a TNS name (no port specified)
|
|
79
|
+
if url.port is None and url.host and "/" not in url.host:
|
|
80
|
+
# TNS name format
|
|
81
|
+
jdbc_url = f"jdbc:oracle:thin:@{url.host}"
|
|
82
|
+
if url.database:
|
|
83
|
+
jdbc_url = f"{jdbc_url}/{url.database}"
|
|
84
|
+
else:
|
|
85
|
+
# Standard format
|
|
86
|
+
jdbc_url = config.format_jdbc_url(
|
|
87
|
+
host=url.host or "localhost",
|
|
88
|
+
port=url.port,
|
|
89
|
+
database=url.database,
|
|
90
|
+
query_params=dict(url.query) if url.query else None,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
logger.debug(f"Creating Oracle connection to: {jdbc_url}")
|
|
94
|
+
|
|
95
|
+
# Build driver arguments
|
|
96
|
+
driver_args: dict[str, Any] = {}
|
|
97
|
+
|
|
98
|
+
if url.username:
|
|
99
|
+
driver_args["user"] = url.username
|
|
100
|
+
if url.password:
|
|
101
|
+
driver_args["password"] = url.password
|
|
102
|
+
|
|
103
|
+
# Add query parameters as connection properties
|
|
104
|
+
if url.query:
|
|
105
|
+
driver_args.update(url.query)
|
|
106
|
+
|
|
107
|
+
kwargs = {
|
|
108
|
+
"jclassname": config.driver_class,
|
|
109
|
+
"url": jdbc_url,
|
|
110
|
+
"driver_args": driver_args if driver_args else None,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return ([], kwargs)
|
|
114
|
+
|
|
115
|
+
def initialize(self, connection: Connection) -> None:
|
|
116
|
+
"""Initialize Oracle connection."""
|
|
117
|
+
super().initialize(connection)
|
|
118
|
+
logger.debug("Initialized Oracle JDBC dialect")
|
|
119
|
+
|
|
120
|
+
def _get_server_version_info(self, connection: Connection) -> tuple[int, ...]:
|
|
121
|
+
"""
|
|
122
|
+
Get Oracle server version.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Tuple of version numbers (e.g., (19, 3, 0))
|
|
126
|
+
"""
|
|
127
|
+
try:
|
|
128
|
+
banner = connection.execute(
|
|
129
|
+
sql.text("SELECT BANNER FROM v$version")
|
|
130
|
+
).scalar()
|
|
131
|
+
|
|
132
|
+
if banner:
|
|
133
|
+
# Parse version from string like:
|
|
134
|
+
# "Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production"
|
|
135
|
+
match = re.search(r"Release ([\d\.]+)", banner)
|
|
136
|
+
if match:
|
|
137
|
+
version_str = match.group(1)
|
|
138
|
+
parts = version_str.split(".")
|
|
139
|
+
return tuple(int(p) for p in parts[:3])
|
|
140
|
+
|
|
141
|
+
except exc.DBAPIError as e:
|
|
142
|
+
logger.warning(f"Failed to get Oracle server version: {e}")
|
|
143
|
+
|
|
144
|
+
# Default fallback
|
|
145
|
+
return (11, 0, 0)
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def _is_oracle_8(self) -> bool:
|
|
149
|
+
"""Check if connected to Oracle 8 (legacy support)."""
|
|
150
|
+
return getattr(self, "_server_version_info", (11, 0, 0))[0] < 9
|
|
151
|
+
|
|
152
|
+
def _check_max_identifier_length(self, connection: Connection) -> int | None:
|
|
153
|
+
"""
|
|
154
|
+
Get maximum identifier length for this Oracle version.
|
|
155
|
+
|
|
156
|
+
Oracle 12.2+ supports 128 characters, earlier versions support 30.
|
|
157
|
+
"""
|
|
158
|
+
version = getattr(self, "_server_version_info", (11, 0, 0))
|
|
159
|
+
if version >= (12, 2):
|
|
160
|
+
return 128
|
|
161
|
+
return 30
|
|
162
|
+
|
|
163
|
+
def do_ping(self, dbapi_connection: Any) -> bool:
|
|
164
|
+
"""
|
|
165
|
+
Check if Oracle connection is alive.
|
|
166
|
+
|
|
167
|
+
Uses Oracle's dual table for efficiency.
|
|
168
|
+
"""
|
|
169
|
+
try:
|
|
170
|
+
cursor = dbapi_connection.cursor()
|
|
171
|
+
cursor.execute("SELECT 1 FROM DUAL")
|
|
172
|
+
cursor.close()
|
|
173
|
+
return True
|
|
174
|
+
except Exception as e:
|
|
175
|
+
logger.debug(f"Oracle ping failed: {e}")
|
|
176
|
+
return False
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
# Export the dialect
|
|
180
|
+
dialect = OracleDialect
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""
|
|
2
|
+
PostgreSQL JDBC dialect for SQLAlchemy.
|
|
3
|
+
|
|
4
|
+
Provides full PostgreSQL support through JDBC, compatible with SQLAlchemy 2.0+.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
import re
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from sqlalchemy import sql
|
|
14
|
+
from sqlalchemy.dialects.postgresql.base import PGDialect
|
|
15
|
+
from sqlalchemy.engine import Connection
|
|
16
|
+
|
|
17
|
+
from .base import BaseJDBCDialect, JDBCDriverConfig
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class PostgreSQLDialect(BaseJDBCDialect, PGDialect):
|
|
23
|
+
"""
|
|
24
|
+
PostgreSQL dialect using JDBC driver.
|
|
25
|
+
|
|
26
|
+
Supports all PostgreSQL-specific features including:
|
|
27
|
+
- Arrays
|
|
28
|
+
- JSONB
|
|
29
|
+
- UUID
|
|
30
|
+
- Full-text search
|
|
31
|
+
- Custom types
|
|
32
|
+
|
|
33
|
+
Connection URL format:
|
|
34
|
+
jdbcapi+postgresql://user:password@host:5432/database
|
|
35
|
+
jdbcapi+pgjdbc://user:password@host:5432/database # Alias
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
name = "postgresql"
|
|
39
|
+
driver = "jdbcapi"
|
|
40
|
+
|
|
41
|
+
# PostgreSQL-specific capabilities
|
|
42
|
+
supports_native_enum = True
|
|
43
|
+
supports_sequences = True
|
|
44
|
+
supports_native_boolean = True
|
|
45
|
+
supports_smallserial = True
|
|
46
|
+
|
|
47
|
+
# Column specifications inherited from PGDialect
|
|
48
|
+
# Can be extended in the future for JDBC-specific type mappings if needed
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def get_driver_config(cls) -> JDBCDriverConfig:
|
|
52
|
+
"""Get PostgreSQL JDBC driver configuration."""
|
|
53
|
+
return JDBCDriverConfig(
|
|
54
|
+
driver_class="org.postgresql.Driver",
|
|
55
|
+
jdbc_url_template="jdbc:postgresql://{host}:{port}/{database}",
|
|
56
|
+
default_port=5432,
|
|
57
|
+
supports_transactions=True,
|
|
58
|
+
supports_schemas=True,
|
|
59
|
+
supports_sequences=True,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
def initialize(self, connection: Connection) -> None:
|
|
63
|
+
"""Initialize PostgreSQL connection."""
|
|
64
|
+
super().initialize(connection)
|
|
65
|
+
|
|
66
|
+
# Set up PostgreSQL-specific settings
|
|
67
|
+
logger.debug("Initialized PostgreSQL JDBC dialect")
|
|
68
|
+
|
|
69
|
+
def _get_server_version_info(self, connection: Connection) -> tuple[int, ...]:
|
|
70
|
+
"""
|
|
71
|
+
Get PostgreSQL server version.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Tuple of version numbers (e.g., (14, 5, 0))
|
|
75
|
+
"""
|
|
76
|
+
try:
|
|
77
|
+
result = connection.execute(sql.text("SELECT version()")).scalar()
|
|
78
|
+
if result:
|
|
79
|
+
# Parse version from string like:
|
|
80
|
+
# "PostgreSQL 14.5 on x86_64-pc-linux-gnu..."
|
|
81
|
+
match = re.search(r"PostgreSQL (\d+)\.(\d+)(?:\.(\d+))?", result)
|
|
82
|
+
if match:
|
|
83
|
+
major = int(match.group(1))
|
|
84
|
+
minor = int(match.group(2))
|
|
85
|
+
patch = int(match.group(3)) if match.group(3) else 0
|
|
86
|
+
return (major, minor, patch)
|
|
87
|
+
except Exception as e:
|
|
88
|
+
logger.warning(f"Failed to get server version: {e}")
|
|
89
|
+
|
|
90
|
+
# Default fallback
|
|
91
|
+
return (9, 0, 0)
|
|
92
|
+
|
|
93
|
+
def do_ping(self, dbapi_connection: Any) -> bool:
|
|
94
|
+
"""
|
|
95
|
+
Check if PostgreSQL connection is alive.
|
|
96
|
+
|
|
97
|
+
Uses a simple SELECT query for efficiency.
|
|
98
|
+
"""
|
|
99
|
+
try:
|
|
100
|
+
cursor = dbapi_connection.cursor()
|
|
101
|
+
cursor.execute("SELECT 1")
|
|
102
|
+
cursor.close()
|
|
103
|
+
return True
|
|
104
|
+
except Exception as e:
|
|
105
|
+
logger.debug(f"PostgreSQL ping failed: {e}")
|
|
106
|
+
return False
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# Export the dialect
|
|
110
|
+
dialect = PostgreSQLDialect
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SQLite JDBC dialect for SQLAlchemy.
|
|
3
|
+
|
|
4
|
+
Provides SQLite support through JDBC (mainly for testing or Java interop).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from sqlalchemy import exc, sql
|
|
13
|
+
from sqlalchemy.dialects.sqlite.base import SQLiteDialect as BaseSQLiteDialect
|
|
14
|
+
from sqlalchemy.engine import Connection
|
|
15
|
+
|
|
16
|
+
from .base import BaseJDBCDialect, JDBCDriverConfig
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class SQLiteDialect(BaseJDBCDialect, BaseSQLiteDialect):
|
|
22
|
+
"""
|
|
23
|
+
SQLite dialect using JDBC driver.
|
|
24
|
+
|
|
25
|
+
Note: For production use, the native sqlite3 dialect is recommended.
|
|
26
|
+
This JDBC dialect is primarily useful for:
|
|
27
|
+
- Testing JDBC infrastructure
|
|
28
|
+
- Java application integration
|
|
29
|
+
- Environments where native sqlite3 is not available
|
|
30
|
+
|
|
31
|
+
Connection URL format:
|
|
32
|
+
jdbcapi+sqlite:///path/to/database.db
|
|
33
|
+
jdbcapi+sqlite:///:memory: # In-memory database
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
name = "sqlite"
|
|
37
|
+
driver = "jdbcapi"
|
|
38
|
+
|
|
39
|
+
# SQLite capabilities
|
|
40
|
+
supports_native_boolean = False
|
|
41
|
+
supports_sequences = False
|
|
42
|
+
supports_native_enum = False
|
|
43
|
+
supports_native_decimal = False
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def import_dbapi(cls) -> Any:
|
|
47
|
+
"""
|
|
48
|
+
Import JDBC module.
|
|
49
|
+
|
|
50
|
+
SQLAlchemy's SQLite dialect expects sqlite_version_info attribute,
|
|
51
|
+
so we add it as a wrapper.
|
|
52
|
+
"""
|
|
53
|
+
from sqlalchemy_jdbcapi import jdbc
|
|
54
|
+
|
|
55
|
+
# Add sqlite_version_info if not present (required by SQLAlchemy's SQLite dialect)
|
|
56
|
+
if not hasattr(jdbc, "sqlite_version_info"):
|
|
57
|
+
# Use a reasonable default version
|
|
58
|
+
jdbc.sqlite_version_info = (3, 40, 0)
|
|
59
|
+
|
|
60
|
+
return jdbc
|
|
61
|
+
|
|
62
|
+
@classmethod
|
|
63
|
+
def get_driver_config(cls) -> JDBCDriverConfig:
|
|
64
|
+
"""Get SQLite JDBC driver configuration."""
|
|
65
|
+
return JDBCDriverConfig(
|
|
66
|
+
driver_class="org.sqlite.JDBC",
|
|
67
|
+
jdbc_url_template="jdbc:sqlite:{database}",
|
|
68
|
+
default_port=0, # Not applicable for SQLite
|
|
69
|
+
supports_transactions=True,
|
|
70
|
+
supports_schemas=False, # SQLite has limited schema support
|
|
71
|
+
supports_sequences=False,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def create_connect_args(self, url: Any) -> tuple[list[Any], dict[str, Any]]:
|
|
75
|
+
"""
|
|
76
|
+
Create connection arguments for SQLite.
|
|
77
|
+
|
|
78
|
+
Handles file paths and in-memory databases.
|
|
79
|
+
"""
|
|
80
|
+
config = self.get_driver_config()
|
|
81
|
+
|
|
82
|
+
# Build JDBC URL
|
|
83
|
+
if url.database:
|
|
84
|
+
if url.database == ":memory:":
|
|
85
|
+
jdbc_url = "jdbc:sqlite::memory:"
|
|
86
|
+
else:
|
|
87
|
+
jdbc_url = f"jdbc:sqlite:{url.database}"
|
|
88
|
+
else:
|
|
89
|
+
# Default to in-memory
|
|
90
|
+
jdbc_url = "jdbc:sqlite::memory:"
|
|
91
|
+
|
|
92
|
+
logger.debug(f"Creating SQLite connection to: {jdbc_url}")
|
|
93
|
+
|
|
94
|
+
kwargs = {
|
|
95
|
+
"jclassname": config.driver_class,
|
|
96
|
+
"url": jdbc_url,
|
|
97
|
+
"driver_args": None,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return ([], kwargs)
|
|
101
|
+
|
|
102
|
+
def initialize(self, connection: Connection) -> None:
|
|
103
|
+
"""Initialize SQLite connection."""
|
|
104
|
+
super().initialize(connection)
|
|
105
|
+
logger.debug("Initialized SQLite JDBC dialect")
|
|
106
|
+
|
|
107
|
+
def _get_server_version_info(self, connection: Connection) -> tuple[int, ...]:
|
|
108
|
+
"""
|
|
109
|
+
Get SQLite version.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
Tuple of version numbers (e.g., (3, 40, 1))
|
|
113
|
+
"""
|
|
114
|
+
try:
|
|
115
|
+
result = connection.execute(sql.text("SELECT sqlite_version()")).scalar()
|
|
116
|
+
|
|
117
|
+
if result:
|
|
118
|
+
# Parse version from string like: "3.40.1"
|
|
119
|
+
parts = result.split(".")
|
|
120
|
+
return tuple(int(p) for p in parts[:3])
|
|
121
|
+
|
|
122
|
+
except exc.DBAPIError as e:
|
|
123
|
+
logger.warning(f"Failed to get SQLite version: {e}")
|
|
124
|
+
|
|
125
|
+
# Default fallback
|
|
126
|
+
return (3, 30, 0)
|
|
127
|
+
|
|
128
|
+
def do_ping(self, dbapi_connection: Any) -> bool:
|
|
129
|
+
"""Check if SQLite connection is alive."""
|
|
130
|
+
try:
|
|
131
|
+
cursor = dbapi_connection.cursor()
|
|
132
|
+
cursor.execute("SELECT 1")
|
|
133
|
+
cursor.close()
|
|
134
|
+
return True
|
|
135
|
+
except Exception as e:
|
|
136
|
+
logger.debug(f"SQLite ping failed: {e}")
|
|
137
|
+
return False
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
# Export the dialect
|
|
141
|
+
dialect = SQLiteDialect
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JDBC Bridge Layer for SQLAlchemy.
|
|
3
|
+
|
|
4
|
+
This module provides a Python DB-API 2.0 compliant interface to JDBC drivers
|
|
5
|
+
using JPype for JVM interaction. This replaces the unmaintained JayDeBeApi library
|
|
6
|
+
with a modern, type-safe, and feature-rich implementation.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from .connection import Connection, connect
|
|
12
|
+
from .cursor import Cursor
|
|
13
|
+
from .driver_manager import (
|
|
14
|
+
RECOMMENDED_JDBC_DRIVERS,
|
|
15
|
+
JDBCDriver,
|
|
16
|
+
clear_driver_cache,
|
|
17
|
+
download_driver,
|
|
18
|
+
get_driver_cache_dir,
|
|
19
|
+
get_driver_path,
|
|
20
|
+
list_cached_drivers,
|
|
21
|
+
)
|
|
22
|
+
from .exceptions import (
|
|
23
|
+
DatabaseError,
|
|
24
|
+
DataError,
|
|
25
|
+
Error,
|
|
26
|
+
IntegrityError,
|
|
27
|
+
InterfaceError,
|
|
28
|
+
InternalError,
|
|
29
|
+
NotSupportedError,
|
|
30
|
+
OperationalError,
|
|
31
|
+
ProgrammingError,
|
|
32
|
+
Warning,
|
|
33
|
+
)
|
|
34
|
+
from .jvm import get_classpath, is_jvm_started, shutdown_jvm, start_jvm
|
|
35
|
+
from .types import (
|
|
36
|
+
BINARY,
|
|
37
|
+
DATETIME,
|
|
38
|
+
NUMBER,
|
|
39
|
+
ROWID,
|
|
40
|
+
STRING,
|
|
41
|
+
Binary,
|
|
42
|
+
Date,
|
|
43
|
+
DateFromTicks,
|
|
44
|
+
Time,
|
|
45
|
+
TimeFromTicks,
|
|
46
|
+
Timestamp,
|
|
47
|
+
TimestampFromTicks,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
__all__ = [
|
|
51
|
+
# Core functions
|
|
52
|
+
"connect",
|
|
53
|
+
# JVM management
|
|
54
|
+
"start_jvm",
|
|
55
|
+
"is_jvm_started",
|
|
56
|
+
"shutdown_jvm",
|
|
57
|
+
"get_classpath",
|
|
58
|
+
# Driver management
|
|
59
|
+
"JDBCDriver",
|
|
60
|
+
"RECOMMENDED_JDBC_DRIVERS",
|
|
61
|
+
"download_driver",
|
|
62
|
+
"get_driver_path",
|
|
63
|
+
"get_driver_cache_dir",
|
|
64
|
+
"list_cached_drivers",
|
|
65
|
+
"clear_driver_cache",
|
|
66
|
+
# Classes
|
|
67
|
+
"Connection",
|
|
68
|
+
"Cursor",
|
|
69
|
+
# Exceptions
|
|
70
|
+
"Error",
|
|
71
|
+
"Warning",
|
|
72
|
+
"InterfaceError",
|
|
73
|
+
"DatabaseError",
|
|
74
|
+
"InternalError",
|
|
75
|
+
"OperationalError",
|
|
76
|
+
"ProgrammingError",
|
|
77
|
+
"IntegrityError",
|
|
78
|
+
"DataError",
|
|
79
|
+
"NotSupportedError",
|
|
80
|
+
# Types
|
|
81
|
+
"Date",
|
|
82
|
+
"Time",
|
|
83
|
+
"Timestamp",
|
|
84
|
+
"DateFromTicks",
|
|
85
|
+
"TimeFromTicks",
|
|
86
|
+
"TimestampFromTicks",
|
|
87
|
+
"Binary",
|
|
88
|
+
"STRING",
|
|
89
|
+
"BINARY",
|
|
90
|
+
"NUMBER",
|
|
91
|
+
"DATETIME",
|
|
92
|
+
"ROWID",
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
# DB-API 2.0 module attributes
|
|
96
|
+
apilevel = "2.0"
|
|
97
|
+
threadsafety = 1 # Threads may share the module, but not connections
|
|
98
|
+
paramstyle = "qmark" # Question mark style, e.g. ...WHERE name=?
|