arrowsql 0.1.0__cp313-cp313-win_amd64.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.
- arrowsql/__init__.py +653 -0
- arrowsql/_rust_auth.py +170 -0
- arrowsql/_server_sqlstate.py +11 -0
- arrowsql/_utf8_strings.py +78 -0
- arrowsql/agent.py +620 -0
- arrowsql/aio.py +533 -0
- arrowsql/arrow_parallel.py +464 -0
- arrowsql/async_query/__init__.py +40 -0
- arrowsql/async_query/_connection_context.py +39 -0
- arrowsql/async_query/_native.py +24 -0
- arrowsql/async_query/async_connection.py +160 -0
- arrowsql/async_query/async_cursor.py +225 -0
- arrowsql/async_query/async_execute.py +113 -0
- arrowsql/async_query/async_fetch.py +153 -0
- arrowsql/async_query/exception_translator.py +132 -0
- arrowsql/auth.py +913 -0
- arrowsql/bulk_parallel.py +385 -0
- arrowsql/connection.py +2377 -0
- arrowsql/connection_string_builder.py +114 -0
- arrowsql/connection_string_parser.py +417 -0
- arrowsql/constants.py +701 -0
- arrowsql/cursor.py +4516 -0
- arrowsql/db_connection.py +98 -0
- arrowsql/ddbc_bindings.cp313-win_amd64.pyd +0 -0
- arrowsql/ddbc_bindings.pyi +283 -0
- arrowsql/decimal_config.py +98 -0
- arrowsql/exceptions.py +378 -0
- arrowsql/helpers.py +436 -0
- arrowsql/logging.py +700 -0
- arrowsql/mssql_python.pyi +579 -0
- arrowsql/odbc_provider.py +269 -0
- arrowsql/parameter_helper.py +442 -0
- arrowsql/perf_timer.py +286 -0
- arrowsql/pooling.py +147 -0
- arrowsql/py.typed +1 -0
- arrowsql/row.py +462 -0
- arrowsql/type.py +160 -0
- arrowsql-0.1.0.dist-info/METADATA +146 -0
- arrowsql-0.1.0.dist-info/RECORD +45 -0
- arrowsql-0.1.0.dist-info/WHEEL +4 -0
- arrowsql-0.1.0.dist-info/entry_points.txt +2 -0
- arrowsql-0.1.0.dist-info/licenses/LICENSE +21 -0
- arrowsql-0.1.0.dist-info/licenses/LICENSE.upstream-mssql-python +47 -0
- arrowsql-0.1.0.dist-info/sboms/ddbc_bindings.cyclonedx.json +5195 -0
- mssql_python/__init__.py +39 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"""Translate mssql-py-core failures to the public DB-API exception hierarchy."""
|
|
2
|
+
|
|
3
|
+
from contextlib import contextmanager
|
|
4
|
+
from typing import Iterator
|
|
5
|
+
|
|
6
|
+
from ..exceptions import (
|
|
7
|
+
DataError,
|
|
8
|
+
DatabaseError,
|
|
9
|
+
Error,
|
|
10
|
+
IntegrityError,
|
|
11
|
+
InterfaceError,
|
|
12
|
+
InternalError,
|
|
13
|
+
NotSupportedError,
|
|
14
|
+
OperationalError,
|
|
15
|
+
ProgrammingError,
|
|
16
|
+
Warning,
|
|
17
|
+
)
|
|
18
|
+
from .._server_sqlstate import sqlstate_for_server_error
|
|
19
|
+
from ..logging import logger
|
|
20
|
+
|
|
21
|
+
_EXCEPTION_TYPES = {
|
|
22
|
+
"Warning": Warning,
|
|
23
|
+
"Error": Error,
|
|
24
|
+
"InterfaceError": InterfaceError,
|
|
25
|
+
"DatabaseError": DatabaseError,
|
|
26
|
+
"DataError": DataError,
|
|
27
|
+
"OperationalError": OperationalError,
|
|
28
|
+
"IntegrityError": IntegrityError,
|
|
29
|
+
"InternalError": InternalError,
|
|
30
|
+
"ProgrammingError": ProgrammingError,
|
|
31
|
+
"NotSupportedError": NotSupportedError,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
_ASYNC_DRIVER_ERROR = "Async operation failed"
|
|
35
|
+
|
|
36
|
+
def is_connection_busy(error: BaseException) -> bool:
|
|
37
|
+
"""Whether py-core rejected the call because the connection is busy."""
|
|
38
|
+
return isinstance(error, OperationalError) and str(error.__cause__).startswith(
|
|
39
|
+
"Connection is busy"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
_PROGRAMMING_RUNTIME_ERRORS = ("Cursor is closed",)
|
|
44
|
+
_INTERFACE_RUNTIME_ERRORS = (
|
|
45
|
+
"Connection is closing",
|
|
46
|
+
"Connection is closed",
|
|
47
|
+
)
|
|
48
|
+
_OPERATIONAL_RUNTIME_ERROR_PREFIXES = (
|
|
49
|
+
"Connection is broken",
|
|
50
|
+
"Connection is busy",
|
|
51
|
+
)
|
|
52
|
+
_PROGRAMMING_TYPE_ERROR_PREFIXES = (
|
|
53
|
+
"The SQL contains ",
|
|
54
|
+
"Parameter style mismatch:",
|
|
55
|
+
"Named parameter cannot be empty",
|
|
56
|
+
)
|
|
57
|
+
_DATA_ERROR_NUMBERS = {241, 245, 248, 8114, 8115, 8134, 8152, 2628}
|
|
58
|
+
_INTEGRITY_ERROR_NUMBERS = {515, 547, 2601, 2627}
|
|
59
|
+
_PROGRAMMING_ERROR_NUMBERS = {102, 156, 201, 207, 208, 2714, 2812, 8144}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _translate_known_builtin_error(error: Exception) -> Exception:
|
|
63
|
+
message = str(error)
|
|
64
|
+
if isinstance(error, RuntimeError):
|
|
65
|
+
if message in _PROGRAMMING_RUNTIME_ERRORS:
|
|
66
|
+
return ProgrammingError(_ASYNC_DRIVER_ERROR, message)
|
|
67
|
+
if message in _INTERFACE_RUNTIME_ERRORS:
|
|
68
|
+
return InterfaceError(_ASYNC_DRIVER_ERROR, message)
|
|
69
|
+
if message.startswith(_OPERATIONAL_RUNTIME_ERROR_PREFIXES):
|
|
70
|
+
return OperationalError(_ASYNC_DRIVER_ERROR, message)
|
|
71
|
+
if isinstance(error, TypeError) and message.startswith(_PROGRAMMING_TYPE_ERROR_PREFIXES):
|
|
72
|
+
return ProgrammingError(_ASYNC_DRIVER_ERROR, message)
|
|
73
|
+
return error
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _classify_database_error(error: Exception, default_type: type[DatabaseError]):
|
|
77
|
+
diagnostics = getattr(error, "sql_errors", ())
|
|
78
|
+
numbers = {item.get("number") for item in diagnostics if isinstance(item, dict)}
|
|
79
|
+
if numbers & _DATA_ERROR_NUMBERS:
|
|
80
|
+
return DataError
|
|
81
|
+
if numbers & _INTEGRITY_ERROR_NUMBERS:
|
|
82
|
+
return IntegrityError
|
|
83
|
+
if numbers & _PROGRAMMING_ERROR_NUMBERS:
|
|
84
|
+
return ProgrammingError
|
|
85
|
+
return default_type
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _server_error_identity(error: Exception):
|
|
89
|
+
"""(sqlstate, native_error) of the first server error py-core reported, if any."""
|
|
90
|
+
for item in getattr(error, "sql_errors", ()):
|
|
91
|
+
if isinstance(item, dict) and isinstance(item.get("number"), int):
|
|
92
|
+
number = item["number"]
|
|
93
|
+
return sqlstate_for_server_error(number, item.get("class")), number
|
|
94
|
+
return None, None
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def translate_py_core_exception(error: Exception) -> Exception:
|
|
98
|
+
"""Translate py-core and recognized built-in errors to public exceptions."""
|
|
99
|
+
for error_type in type(error).__mro__:
|
|
100
|
+
if error_type.__module__ != "mssql_py_core":
|
|
101
|
+
continue
|
|
102
|
+
public_type = _EXCEPTION_TYPES.get(error_type.__name__)
|
|
103
|
+
if public_type is None:
|
|
104
|
+
continue
|
|
105
|
+
if public_type is DatabaseError:
|
|
106
|
+
public_type = _classify_database_error(error, public_type)
|
|
107
|
+
|
|
108
|
+
logger.debug(
|
|
109
|
+
"Async exception translation: %s -> %s",
|
|
110
|
+
error_type.__name__,
|
|
111
|
+
public_type.__name__,
|
|
112
|
+
)
|
|
113
|
+
sqlstate, native_error = _server_error_identity(error)
|
|
114
|
+
translated = public_type(_ASYNC_DRIVER_ERROR, str(error), sqlstate, native_error)
|
|
115
|
+
for attribute in ("sql_errors", "info_messages"):
|
|
116
|
+
if hasattr(error, attribute):
|
|
117
|
+
setattr(translated, attribute, getattr(error, attribute))
|
|
118
|
+
return translated
|
|
119
|
+
|
|
120
|
+
return _translate_known_builtin_error(error)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@contextmanager
|
|
124
|
+
def translate_py_core_exceptions() -> Iterator[None]:
|
|
125
|
+
"""Translate py-core and recognized built-in errors raised by the wrapped operation."""
|
|
126
|
+
try:
|
|
127
|
+
yield
|
|
128
|
+
except Exception as error:
|
|
129
|
+
translated = translate_py_core_exception(error)
|
|
130
|
+
if translated is error:
|
|
131
|
+
raise
|
|
132
|
+
raise translated from error
|