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.
Files changed (45) hide show
  1. arrowsql/__init__.py +653 -0
  2. arrowsql/_rust_auth.py +170 -0
  3. arrowsql/_server_sqlstate.py +11 -0
  4. arrowsql/_utf8_strings.py +78 -0
  5. arrowsql/agent.py +620 -0
  6. arrowsql/aio.py +533 -0
  7. arrowsql/arrow_parallel.py +464 -0
  8. arrowsql/async_query/__init__.py +40 -0
  9. arrowsql/async_query/_connection_context.py +39 -0
  10. arrowsql/async_query/_native.py +24 -0
  11. arrowsql/async_query/async_connection.py +160 -0
  12. arrowsql/async_query/async_cursor.py +225 -0
  13. arrowsql/async_query/async_execute.py +113 -0
  14. arrowsql/async_query/async_fetch.py +153 -0
  15. arrowsql/async_query/exception_translator.py +132 -0
  16. arrowsql/auth.py +913 -0
  17. arrowsql/bulk_parallel.py +385 -0
  18. arrowsql/connection.py +2377 -0
  19. arrowsql/connection_string_builder.py +114 -0
  20. arrowsql/connection_string_parser.py +417 -0
  21. arrowsql/constants.py +701 -0
  22. arrowsql/cursor.py +4516 -0
  23. arrowsql/db_connection.py +98 -0
  24. arrowsql/ddbc_bindings.cp313-win_amd64.pyd +0 -0
  25. arrowsql/ddbc_bindings.pyi +283 -0
  26. arrowsql/decimal_config.py +98 -0
  27. arrowsql/exceptions.py +378 -0
  28. arrowsql/helpers.py +436 -0
  29. arrowsql/logging.py +700 -0
  30. arrowsql/mssql_python.pyi +579 -0
  31. arrowsql/odbc_provider.py +269 -0
  32. arrowsql/parameter_helper.py +442 -0
  33. arrowsql/perf_timer.py +286 -0
  34. arrowsql/pooling.py +147 -0
  35. arrowsql/py.typed +1 -0
  36. arrowsql/row.py +462 -0
  37. arrowsql/type.py +160 -0
  38. arrowsql-0.1.0.dist-info/METADATA +146 -0
  39. arrowsql-0.1.0.dist-info/RECORD +45 -0
  40. arrowsql-0.1.0.dist-info/WHEEL +4 -0
  41. arrowsql-0.1.0.dist-info/entry_points.txt +2 -0
  42. arrowsql-0.1.0.dist-info/licenses/LICENSE +21 -0
  43. arrowsql-0.1.0.dist-info/licenses/LICENSE.upstream-mssql-python +47 -0
  44. arrowsql-0.1.0.dist-info/sboms/ddbc_bindings.cyclonedx.json +5195 -0
  45. 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
@@ -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