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,98 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Microsoft Corporation.
|
|
3
|
+
Licensed under the MIT license.
|
|
4
|
+
This module provides a way to create a new connection object to interact with the database.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Dict, Optional, Union
|
|
8
|
+
|
|
9
|
+
from arrowsql.connection import Connection, TokenProvider
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def connect(
|
|
13
|
+
connection_str: str = "",
|
|
14
|
+
autocommit: bool = False,
|
|
15
|
+
attrs_before: Optional[Dict[int, Union[int, str, bytes]]] = None,
|
|
16
|
+
timeout: int = 0,
|
|
17
|
+
native_uuid: Optional[bool] = None,
|
|
18
|
+
token_provider: Optional[TokenProvider] = None,
|
|
19
|
+
**kwargs: Any,
|
|
20
|
+
) -> Connection:
|
|
21
|
+
"""
|
|
22
|
+
Constructor for creating a connection to the database.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
connection_str (str): The connection string to connect to.
|
|
26
|
+
autocommit (bool): If True, causes a commit to be performed after each SQL statement.
|
|
27
|
+
attrs_before (dict, optional): A dictionary of connection attributes to set before
|
|
28
|
+
connecting.
|
|
29
|
+
timeout (int): Login (connection-attempt) timeout in seconds. 0 (default)
|
|
30
|
+
uses the driver default. This bounds the login/network handshake (via
|
|
31
|
+
SQL_ATTR_LOGIN_TIMEOUT), not query execution — it is distinct from the
|
|
32
|
+
``Connection.timeout`` property, which is the per-statement query
|
|
33
|
+
timeout. If both ``timeout`` and ``attrs_before[SQL_ATTR_LOGIN_TIMEOUT]``
|
|
34
|
+
are supplied, the explicit ``attrs_before`` value takes precedence.
|
|
35
|
+
native_uuid (bool, optional): Controls whether UNIQUEIDENTIFIER columns return
|
|
36
|
+
uuid.UUID objects (True) or str (False) for this connection.
|
|
37
|
+
- True: UNIQUEIDENTIFIER columns return uuid.UUID objects.
|
|
38
|
+
- False: UNIQUEIDENTIFIER columns return str (pyodbc-compatible).
|
|
39
|
+
- None (default): Uses the module-level ``mssql_python.native_uuid`` setting (True).
|
|
40
|
+
|
|
41
|
+
This per-connection override is useful for migration from pyodbc:
|
|
42
|
+
connections that need string UUIDs can pass native_uuid=False, while the default (True)
|
|
43
|
+
returns native uuid.UUID objects.
|
|
44
|
+
token_provider (object, optional): A token provider for Microsoft Entra ID
|
|
45
|
+
authentication. This must be any object with a ``.get_token(scope)`` method that
|
|
46
|
+
returns an object with a ``.token`` attribute containing a raw JWT string — for
|
|
47
|
+
example, any ``azure-identity`` credential class such as
|
|
48
|
+
``DefaultAzureCredential``, ``AzureCliCredential``, ``ManagedIdentityCredential``,
|
|
49
|
+
``CertificateCredential``, etc.
|
|
50
|
+
|
|
51
|
+
When provided, the driver calls ``token_provider.get_token()`` to acquire an
|
|
52
|
+
access token for SQL Server, bypassing the built-in credential map.
|
|
53
|
+
Cannot be combined with ``Authentication=`` in the connection string.
|
|
54
|
+
|
|
55
|
+
For environment-portable code, prefer ``Authentication=ActiveDirectoryDefault``
|
|
56
|
+
in the connection string — ``DefaultAzureCredential`` automatically picks the
|
|
57
|
+
right credential per environment (CLI on dev, Managed Identity in prod).
|
|
58
|
+
Use ``token_provider=`` only when you need explicit control over token
|
|
59
|
+
acquisition (e.g., excluding specific providers, using a credential not in
|
|
60
|
+
the built-in map, or passing custom options to the credential constructor).
|
|
61
|
+
|
|
62
|
+
Example::
|
|
63
|
+
|
|
64
|
+
from azure.identity import AzureCliCredential
|
|
65
|
+
conn = mssql_python.connect("Server=s;Database=d",
|
|
66
|
+
token_provider=AzureCliCredential())
|
|
67
|
+
|
|
68
|
+
Note: the token scope is fixed to the Azure **commercial** cloud
|
|
69
|
+
(``https://database.windows.net/.default``). Sovereign clouds (Azure US
|
|
70
|
+
Government, Azure China, Azure Germany) are **out of scope** — acquire the token
|
|
71
|
+
yourself and pass it via ``attrs_before[SQL_COPT_SS_ACCESS_TOKEN]`` instead.
|
|
72
|
+
Keyword Args:
|
|
73
|
+
**kwargs: Additional key/value pairs for the connection string.
|
|
74
|
+
Below attributes are not implemented in the internal driver:
|
|
75
|
+
- encoding (str): The encoding for the connection string.
|
|
76
|
+
- ansi (bool): If True, indicates the driver does not support Unicode.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Connection: A new connection object to interact with the database.
|
|
80
|
+
|
|
81
|
+
Raises:
|
|
82
|
+
DatabaseError: If there is an error while trying to connect to the database.
|
|
83
|
+
InterfaceError: If there is an error related to the database interface.
|
|
84
|
+
|
|
85
|
+
This function provides a way to create a new connection object, which can then
|
|
86
|
+
be used to perform database operations such as executing queries, committing
|
|
87
|
+
transactions, and closing the connection.
|
|
88
|
+
"""
|
|
89
|
+
conn = Connection(
|
|
90
|
+
connection_str,
|
|
91
|
+
autocommit=autocommit,
|
|
92
|
+
attrs_before=attrs_before,
|
|
93
|
+
timeout=timeout,
|
|
94
|
+
native_uuid=native_uuid,
|
|
95
|
+
token_provider=token_provider,
|
|
96
|
+
**kwargs,
|
|
97
|
+
)
|
|
98
|
+
return conn
|
|
Binary file
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"""Type stub for the compiled extension ``mssql_python.ddbc_bindings`` (RUST-PORT).
|
|
2
|
+
|
|
3
|
+
Covers the port-specific surface in full (Arrow, bulk copy, native asyncio) and
|
|
4
|
+
the upstream-compatible entry points the Python layer calls. Statement and
|
|
5
|
+
connection handles are opaque to callers; the Python layer owns them.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple
|
|
9
|
+
|
|
10
|
+
__version__: str
|
|
11
|
+
__architecture__: str
|
|
12
|
+
ARCHITECTURE: str
|
|
13
|
+
__rust_port__: bool
|
|
14
|
+
SQL_NO_TOTAL: int
|
|
15
|
+
|
|
16
|
+
# ---------------------------------------------------------------------------
|
|
17
|
+
# Arrow (Arrow PyCapsule interface; no pyarrow needed)
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
class ArrowTable:
|
|
21
|
+
"""A fully fetched result. Zero-copy for any Arrow consumer."""
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def num_rows(self) -> int: ...
|
|
25
|
+
@property
|
|
26
|
+
def num_columns(self) -> int: ...
|
|
27
|
+
@property
|
|
28
|
+
def num_batches(self) -> int: ...
|
|
29
|
+
@property
|
|
30
|
+
def column_names(self) -> List[str]: ...
|
|
31
|
+
def __len__(self) -> int: ...
|
|
32
|
+
def __arrow_c_schema__(self) -> Any: ...
|
|
33
|
+
def __arrow_c_stream__(self, requested_schema: Optional[Any] = None) -> Any: ...
|
|
34
|
+
@staticmethod
|
|
35
|
+
def concat(tables: Sequence["ArrowTable"]) -> "ArrowTable": ...
|
|
36
|
+
|
|
37
|
+
class ArrowStream:
|
|
38
|
+
"""A result being streamed as Arrow record batches (one-shot)."""
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def num_columns(self) -> int: ...
|
|
42
|
+
@property
|
|
43
|
+
def column_names(self) -> List[str]: ...
|
|
44
|
+
@property
|
|
45
|
+
def closed(self) -> bool: ...
|
|
46
|
+
def __arrow_c_schema__(self) -> Any: ...
|
|
47
|
+
def __arrow_c_stream__(self, requested_schema: Optional[Any] = None) -> Any: ...
|
|
48
|
+
def read_all(self) -> ArrowTable: ...
|
|
49
|
+
def close(self) -> None: ...
|
|
50
|
+
|
|
51
|
+
class ArrowMergeStream:
|
|
52
|
+
"""Batches of several ArrowStreams merged into one unordered, bounded stream."""
|
|
53
|
+
|
|
54
|
+
def __init__(self, schema_from: ArrowStream, workers: int, depth: int = 8) -> None: ...
|
|
55
|
+
def pump(self, stream: ArrowStream) -> None: ...
|
|
56
|
+
def worker_done(self) -> None: ...
|
|
57
|
+
def fail(self, message: str) -> None: ...
|
|
58
|
+
@property
|
|
59
|
+
def stopped(self) -> bool: ...
|
|
60
|
+
@property
|
|
61
|
+
def closed(self) -> bool: ...
|
|
62
|
+
@property
|
|
63
|
+
def in_use(self) -> bool: ...
|
|
64
|
+
@property
|
|
65
|
+
def num_columns(self) -> int: ...
|
|
66
|
+
@property
|
|
67
|
+
def column_names(self) -> List[str]: ...
|
|
68
|
+
def close(self) -> None: ...
|
|
69
|
+
def read_all(self) -> ArrowTable: ...
|
|
70
|
+
def __arrow_c_schema__(self) -> Any: ...
|
|
71
|
+
def __arrow_c_stream__(self, requested_schema: Optional[Any] = None) -> Any: ...
|
|
72
|
+
|
|
73
|
+
class AgentRender:
|
|
74
|
+
"""Collects the bounded text output of one statement (see arrowsql.agent)."""
|
|
75
|
+
|
|
76
|
+
def __init__(
|
|
77
|
+
self,
|
|
78
|
+
format: str = "tsv",
|
|
79
|
+
max_bytes: int = 10000,
|
|
80
|
+
max_rows: int = 1000,
|
|
81
|
+
max_cell_chars: int = 500,
|
|
82
|
+
tail_rows: int = 0,
|
|
83
|
+
timeout_s: Optional[float] = None,
|
|
84
|
+
) -> None: ...
|
|
85
|
+
def has_room(self) -> bool: ...
|
|
86
|
+
def result_set(
|
|
87
|
+
self, statement: Any, messages: Optional[List[Any]] = None
|
|
88
|
+
) -> Tuple[int, bool]: ...
|
|
89
|
+
def rows_affected(self, count: int) -> None: ...
|
|
90
|
+
def message(self, text: str) -> None: ...
|
|
91
|
+
def omit(self, count: int) -> None: ...
|
|
92
|
+
def finish(self) -> str: ...
|
|
93
|
+
|
|
94
|
+
def DDBCArrowFetchTable(
|
|
95
|
+
statement: Any,
|
|
96
|
+
max_rows: int = -1,
|
|
97
|
+
batch_size: int = 65536,
|
|
98
|
+
messages: Optional[List[Any]] = None,
|
|
99
|
+
) -> Tuple[int, ArrowTable]: ...
|
|
100
|
+
def DDBCArrowStream(
|
|
101
|
+
statement: Any,
|
|
102
|
+
batch_size: int = 65536,
|
|
103
|
+
prefetch: int = 2,
|
|
104
|
+
owner: Optional[Any] = None,
|
|
105
|
+
) -> ArrowStream: ...
|
|
106
|
+
def DDBCSQLFetchArrowBatch(
|
|
107
|
+
statement: Any,
|
|
108
|
+
capsules: List[Any],
|
|
109
|
+
arrowBatchSize: int,
|
|
110
|
+
charCtype: int,
|
|
111
|
+
messages: Optional[List[Any]] = None,
|
|
112
|
+
) -> int: ...
|
|
113
|
+
|
|
114
|
+
# ---------------------------------------------------------------------------
|
|
115
|
+
# Native bulk copy
|
|
116
|
+
# ---------------------------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
class BulkUnsupported(Exception):
|
|
119
|
+
"""The native bulk copy cannot load this source into this destination."""
|
|
120
|
+
|
|
121
|
+
def DDBCBulkCopyRows(
|
|
122
|
+
handle: Any,
|
|
123
|
+
table_name: str,
|
|
124
|
+
rows: Iterable[Tuple[Any, ...]],
|
|
125
|
+
batch_size: int = 0,
|
|
126
|
+
timeout: int = 30,
|
|
127
|
+
column_mappings: Optional[Any] = None,
|
|
128
|
+
keep_identity: bool = False,
|
|
129
|
+
check_constraints: bool = False,
|
|
130
|
+
table_lock: bool = False,
|
|
131
|
+
keep_nulls: bool = False,
|
|
132
|
+
fire_triggers: bool = False,
|
|
133
|
+
use_internal_transaction: bool = False,
|
|
134
|
+
) -> Dict[str, Any]: ...
|
|
135
|
+
def DDBCBulkCopyArrow(
|
|
136
|
+
handle: Any,
|
|
137
|
+
table_name: str,
|
|
138
|
+
source: Any,
|
|
139
|
+
batch_size: int = 0,
|
|
140
|
+
timeout: int = 30,
|
|
141
|
+
column_mappings: Optional[Any] = None,
|
|
142
|
+
keep_identity: bool = False,
|
|
143
|
+
check_constraints: bool = False,
|
|
144
|
+
table_lock: bool = False,
|
|
145
|
+
keep_nulls: bool = False,
|
|
146
|
+
fire_triggers: bool = False,
|
|
147
|
+
use_internal_transaction: bool = False,
|
|
148
|
+
) -> Dict[str, Any]: ...
|
|
149
|
+
def SQLExecuteManyRows(statementHandle: Any, query: str, rows: Any) -> Optional[int]: ...
|
|
150
|
+
|
|
151
|
+
# ---------------------------------------------------------------------------
|
|
152
|
+
# Native asyncio (Unix only; absent on Windows). Use mssql_python.aio instead.
|
|
153
|
+
# ---------------------------------------------------------------------------
|
|
154
|
+
|
|
155
|
+
class AioHub:
|
|
156
|
+
def __init__(self, event_loop: Any, shape_factory: Any) -> None: ...
|
|
157
|
+
def fileno(self) -> int: ...
|
|
158
|
+
def drain(self) -> None: ...
|
|
159
|
+
def pending(self) -> int: ...
|
|
160
|
+
|
|
161
|
+
class AioRowBatch:
|
|
162
|
+
def next(self) -> Any: ...
|
|
163
|
+
def take(self, n: int) -> List[Any]: ...
|
|
164
|
+
def remaining(self) -> int: ...
|
|
165
|
+
def shape(self) -> Any: ...
|
|
166
|
+
|
|
167
|
+
class AioConnection:
|
|
168
|
+
autocommit: bool
|
|
169
|
+
timeout: int
|
|
170
|
+
def execute(self, *args: Any) -> Any: ...
|
|
171
|
+
def executemany(self, *args: Any) -> Any: ...
|
|
172
|
+
def fetch(self, *args: Any) -> Any: ...
|
|
173
|
+
def fetch_arrow(self, *args: Any) -> Any: ...
|
|
174
|
+
def nextset(self, *args: Any) -> Any: ...
|
|
175
|
+
def query(self, *args: Any) -> Any: ...
|
|
176
|
+
def cursor(self) -> Any: ...
|
|
177
|
+
def close_cursor(self, *args: Any) -> Any: ...
|
|
178
|
+
def commit(self) -> Any: ...
|
|
179
|
+
def rollback(self) -> Any: ...
|
|
180
|
+
def set_autocommit(self, value: bool) -> Any: ...
|
|
181
|
+
def cancel(self) -> None: ...
|
|
182
|
+
def close(self) -> Any: ...
|
|
183
|
+
def open_cursors(self) -> int: ...
|
|
184
|
+
|
|
185
|
+
class AioPool:
|
|
186
|
+
max_size: int
|
|
187
|
+
timeout: int
|
|
188
|
+
def acquire(self) -> Any: ...
|
|
189
|
+
def query(self, *args: Any) -> Any: ...
|
|
190
|
+
def cancel(self) -> None: ...
|
|
191
|
+
def close(self) -> Any: ...
|
|
192
|
+
def idle(self) -> int: ...
|
|
193
|
+
def in_use(self) -> int: ...
|
|
194
|
+
|
|
195
|
+
def aio_connect(
|
|
196
|
+
hub: AioHub,
|
|
197
|
+
conn_str: str,
|
|
198
|
+
autocommit: bool = False,
|
|
199
|
+
timeout: int = 0,
|
|
200
|
+
tuple_rows: bool = False,
|
|
201
|
+
) -> Any: ...
|
|
202
|
+
def aio_create_pool(
|
|
203
|
+
hub: AioHub,
|
|
204
|
+
conn_str: str,
|
|
205
|
+
min_size: int = 1,
|
|
206
|
+
max_size: int = 10,
|
|
207
|
+
autocommit: bool = True,
|
|
208
|
+
timeout: int = 0,
|
|
209
|
+
tuple_rows: bool = False,
|
|
210
|
+
reset: bool = True,
|
|
211
|
+
) -> Any: ...
|
|
212
|
+
|
|
213
|
+
# ---------------------------------------------------------------------------
|
|
214
|
+
# Upstream-compatible surface (see docs/CONTRACT.md for argument details)
|
|
215
|
+
# ---------------------------------------------------------------------------
|
|
216
|
+
|
|
217
|
+
class ErrorInfo:
|
|
218
|
+
sqlState: str
|
|
219
|
+
ddbcErrorMsg: str
|
|
220
|
+
nativeError: int
|
|
221
|
+
|
|
222
|
+
class SqlHandle:
|
|
223
|
+
def free(self) -> None: ...
|
|
224
|
+
def _close_cursor(self) -> None: ...
|
|
225
|
+
def _cancel(self) -> None: ...
|
|
226
|
+
|
|
227
|
+
class ParamInfo: ...
|
|
228
|
+
class NumericData: ...
|
|
229
|
+
|
|
230
|
+
class Connection:
|
|
231
|
+
def __init__(
|
|
232
|
+
self,
|
|
233
|
+
conn_str: str,
|
|
234
|
+
use_pool: bool,
|
|
235
|
+
attrs_before: Optional[Dict[int, Any]] = None,
|
|
236
|
+
pool_key: str = "",
|
|
237
|
+
token_factory: Optional[Any] = None,
|
|
238
|
+
) -> None: ...
|
|
239
|
+
def close(self, transaction_already_rolled_back: bool = False) -> None: ...
|
|
240
|
+
def commit(self) -> None: ...
|
|
241
|
+
def rollback(self) -> None: ...
|
|
242
|
+
def set_autocommit(self, value: bool) -> None: ...
|
|
243
|
+
def get_autocommit(self) -> bool: ...
|
|
244
|
+
def set_attr(self, attribute: int, value: Any) -> None: ...
|
|
245
|
+
def alloc_statement_handle(self) -> SqlHandle: ...
|
|
246
|
+
def get_info(self, info_type: int) -> Any: ...
|
|
247
|
+
|
|
248
|
+
def DDBCSQLExecDirect(statement: Any, query: str) -> int: ...
|
|
249
|
+
def DDBCSQLExecute(
|
|
250
|
+
statementHandle: Any,
|
|
251
|
+
query: str,
|
|
252
|
+
params: Any,
|
|
253
|
+
inputSizes: Any,
|
|
254
|
+
isStmtPrepared: Any,
|
|
255
|
+
usePrepare: bool,
|
|
256
|
+
encodingSettings: Any,
|
|
257
|
+
) -> int: ...
|
|
258
|
+
def SQLExecuteMany(
|
|
259
|
+
statementHandle: Any,
|
|
260
|
+
query: str,
|
|
261
|
+
columnwise_params: Any,
|
|
262
|
+
paramInfos: Any,
|
|
263
|
+
paramSetSize: int,
|
|
264
|
+
encodingSettings: Any,
|
|
265
|
+
) -> int: ...
|
|
266
|
+
def DDBCSQLRowCount(statement: Any) -> int: ...
|
|
267
|
+
def DDBCSQLNumResultCols(statementHandle: Any, messages: Optional[List[Any]] = None) -> int: ...
|
|
268
|
+
def DDBCSQLMoreResults(statement: Any) -> int: ...
|
|
269
|
+
def DDBCSQLResetStmt(statement: Any) -> int: ...
|
|
270
|
+
def DDBCSQLCheckError(handleType: int, handle: Any, retcode: int) -> ErrorInfo: ...
|
|
271
|
+
def DDBCSQLGetAllDiagRecords(handle: Any) -> List[Tuple[str, str]]: ...
|
|
272
|
+
def enable_pooling(max_size: int = 100, idle_timeout: int = 600) -> None: ...
|
|
273
|
+
def close_pooling() -> None: ...
|
|
274
|
+
def disable_pooling() -> None: ...
|
|
275
|
+
def update_log_level(level: int) -> None: ...
|
|
276
|
+
def __getattr__(name: str) -> Any: ...
|
|
277
|
+
|
|
278
|
+
def utf8_wrap_query(
|
|
279
|
+
query: str, columns: List[Tuple[Optional[str], int, int, Optional[bool]]]
|
|
280
|
+
) -> Optional[Tuple[str, str]]: ...
|
|
281
|
+
def utf8_collations_supported(
|
|
282
|
+
product_major_version: Optional[int], engine_edition: Optional[int]
|
|
283
|
+
) -> bool: ...
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Microsoft Corporation.
|
|
3
|
+
Licensed under the MIT license.
|
|
4
|
+
|
|
5
|
+
This module provides functions for managing decimal separator configuration.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
11
|
+
from arrowsql.helpers import Settings
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _setDecimalSeparator(separator: str, settings: "Settings", set_in_cpp_func=None) -> None:
|
|
15
|
+
"""
|
|
16
|
+
Internal implementation for setting the decimal separator.
|
|
17
|
+
|
|
18
|
+
Not intended for direct external use — the public API is exposed via
|
|
19
|
+
``mssql_python.setDecimalSeparator`` (created by ``create_decimal_separator_functions``).
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
separator (str): The character to use as decimal separator
|
|
23
|
+
settings (Settings): The settings object to update
|
|
24
|
+
set_in_cpp_func: Optional callable to set the separator in C++ bindings
|
|
25
|
+
|
|
26
|
+
Raises:
|
|
27
|
+
ValueError: If the separator is not a single character string
|
|
28
|
+
"""
|
|
29
|
+
# Type validation
|
|
30
|
+
if not isinstance(separator, str):
|
|
31
|
+
raise ValueError("Decimal separator must be a string")
|
|
32
|
+
|
|
33
|
+
# Length validation
|
|
34
|
+
if len(separator) == 0:
|
|
35
|
+
raise ValueError("Decimal separator cannot be empty")
|
|
36
|
+
|
|
37
|
+
if len(separator) > 1:
|
|
38
|
+
raise ValueError("Decimal separator must be a single character")
|
|
39
|
+
|
|
40
|
+
# Character validation (covers \t, \n, \r, \v, \f and all other whitespace)
|
|
41
|
+
if separator.isspace():
|
|
42
|
+
raise ValueError("Whitespace characters are not allowed as decimal separators")
|
|
43
|
+
|
|
44
|
+
# Set in Python side settings
|
|
45
|
+
settings.decimal_separator = separator
|
|
46
|
+
|
|
47
|
+
# Update the C++ side if available
|
|
48
|
+
if set_in_cpp_func is not None:
|
|
49
|
+
set_in_cpp_func(separator)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def create_decimal_separator_functions(settings: "Settings"):
|
|
53
|
+
"""
|
|
54
|
+
Factory function to create decimal separator getter/setter bound to specific settings.
|
|
55
|
+
|
|
56
|
+
This function handles importing the C++ binding and initializing the decimal separator.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
settings: The Settings instance to bind to
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Tuple of (setDecimalSeparator, getDecimalSeparator) functions
|
|
63
|
+
"""
|
|
64
|
+
# Try to import and initialize the C++ binding
|
|
65
|
+
try:
|
|
66
|
+
from arrowsql.ddbc_bindings import DDBCSetDecimalSeparator
|
|
67
|
+
|
|
68
|
+
# Set the initial decimal separator in C++
|
|
69
|
+
DDBCSetDecimalSeparator(settings.decimal_separator)
|
|
70
|
+
cpp_binding = DDBCSetDecimalSeparator
|
|
71
|
+
except ImportError:
|
|
72
|
+
# Handle case where ddbc_bindings is not available
|
|
73
|
+
cpp_binding = None
|
|
74
|
+
|
|
75
|
+
def setter(separator: str) -> None:
|
|
76
|
+
"""
|
|
77
|
+
Sets the decimal separator character used when parsing NUMERIC/DECIMAL values
|
|
78
|
+
from the database, e.g. the "." in "1,234.56".
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
separator (str): The character to use as decimal separator
|
|
82
|
+
|
|
83
|
+
Raises:
|
|
84
|
+
ValueError: If the separator is not a single character string
|
|
85
|
+
"""
|
|
86
|
+
_setDecimalSeparator(separator, settings, cpp_binding)
|
|
87
|
+
|
|
88
|
+
def getter() -> str:
|
|
89
|
+
"""
|
|
90
|
+
Returns the decimal separator character used when parsing NUMERIC/DECIMAL values
|
|
91
|
+
from the database.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
str: The current decimal separator character
|
|
95
|
+
"""
|
|
96
|
+
return settings.decimal_separator
|
|
97
|
+
|
|
98
|
+
return setter, getter
|