mssql-python 0.7.0__cp311-cp311-macosx_15_0_universal2.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.
Potentially problematic release.
This version of mssql-python might be problematic. Click here for more details.
- mssql_python/__init__.py +74 -0
- mssql_python/bcp_options.py +121 -0
- mssql_python/connection.py +270 -0
- mssql_python/constants.py +118 -0
- mssql_python/cursor.py +730 -0
- mssql_python/db_connection.py +37 -0
- mssql_python/ddbc_bindings.cp311-universal2.so +0 -0
- mssql_python/ddbc_bindings.py +104 -0
- mssql_python/exceptions.py +650 -0
- mssql_python/helpers.py +186 -0
- mssql_python/libs/LICENSING +19 -0
- mssql_python/libs/linux/debian_ubuntu/arm64/lib/MICROSOFT_ODBC_DRIVER_FOR_SQL_SERVER_LICENSE.txt +76 -0
- mssql_python/libs/linux/debian_ubuntu/arm64/lib/libmsodbcsql-18.5.so.1.1 +0 -0
- mssql_python/libs/linux/debian_ubuntu/arm64/lib/libodbcinst.so.2 +0 -0
- mssql_python/libs/linux/debian_ubuntu/arm64/share/resources/en_US/msodbcsqlr18.rll +0 -0
- mssql_python/libs/linux/debian_ubuntu/x86_64/lib/MICROSOFT_ODBC_DRIVER_FOR_SQL_SERVER_LICENSE.txt +76 -0
- mssql_python/libs/linux/debian_ubuntu/x86_64/lib/libmsodbcsql-18.5.so.1.1 +0 -0
- mssql_python/libs/linux/debian_ubuntu/x86_64/lib/libodbcinst.so.2 +0 -0
- mssql_python/libs/linux/debian_ubuntu/x86_64/share/resources/en_US/msodbcsqlr18.rll +0 -0
- mssql_python/libs/linux/rhel/arm64/lib/MICROSOFT_ODBC_DRIVER_FOR_SQL_SERVER_LICENSE.txt +76 -0
- mssql_python/libs/linux/rhel/arm64/lib/libmsodbcsql-18.5.so.1.1 +0 -0
- mssql_python/libs/linux/rhel/arm64/lib/libodbcinst.so.2 +0 -0
- mssql_python/libs/linux/rhel/arm64/share/resources/en_US/msodbcsqlr18.rll +0 -0
- mssql_python/libs/linux/rhel/x86_64/lib/MICROSOFT_ODBC_DRIVER_FOR_SQL_SERVER_LICENSE.txt +76 -0
- mssql_python/libs/linux/rhel/x86_64/lib/libmsodbcsql-18.5.so.1.1 +0 -0
- mssql_python/libs/linux/rhel/x86_64/lib/libodbcinst.so.2 +0 -0
- mssql_python/libs/linux/rhel/x86_64/share/resources/en_US/msodbcsqlr18.rll +0 -0
- mssql_python/libs/macos/arm64/lib/MICROSOFT_ODBC_DRIVER_FOR_SQL_SERVER_LICENSE.txt +76 -0
- mssql_python/libs/macos/arm64/lib/libltdl.7.dylib +0 -0
- mssql_python/libs/macos/arm64/lib/libmsodbcsql.18.dylib +0 -0
- mssql_python/libs/macos/arm64/lib/libodbc.2.dylib +0 -0
- mssql_python/libs/macos/arm64/lib/libodbcinst.2.dylib +0 -0
- mssql_python/libs/macos/arm64/share/doc/msodbcsql18/LICENSE.txt +101 -0
- mssql_python/libs/macos/arm64/share/doc/msodbcsql18/RELEASE_NOTES +465 -0
- mssql_python/libs/macos/arm64/share/msodbcsql18/resources/en_US/msodbcsqlr18.rll +0 -0
- mssql_python/libs/macos/x86_64/lib/MICROSOFT_ODBC_DRIVER_FOR_SQL_SERVER_LICENSE.txt +76 -0
- mssql_python/libs/macos/x86_64/lib/libltdl.7.dylib +0 -0
- mssql_python/libs/macos/x86_64/lib/libmsodbcsql.18.dylib +0 -0
- mssql_python/libs/macos/x86_64/lib/libodbc.2.dylib +0 -0
- mssql_python/libs/macos/x86_64/lib/libodbcinst.2.dylib +0 -0
- mssql_python/libs/macos/x86_64/share/doc/msodbcsql18/LICENSE.txt +101 -0
- mssql_python/libs/macos/x86_64/share/doc/msodbcsql18/RELEASE_NOTES +465 -0
- mssql_python/libs/macos/x86_64/share/msodbcsql18/resources/en_US/msodbcsqlr18.rll +0 -0
- mssql_python/libs/windows/arm64/1033/msodbcsqlr18.rll +0 -0
- mssql_python/libs/windows/arm64/MICROSOFT_ODBC_DRIVER_FOR_SQL_SERVER_LICENSE.txt +76 -0
- mssql_python/libs/windows/arm64/msodbcdiag18.dll +0 -0
- mssql_python/libs/windows/arm64/msodbcsql18.dll +0 -0
- mssql_python/libs/windows/arm64/mssql-auth.dll +0 -0
- mssql_python/libs/windows/x64/1033/msodbcsqlr18.rll +0 -0
- mssql_python/libs/windows/x64/MICROSOFT_ODBC_DRIVER_FOR_SQL_SERVER_LICENSE.txt +76 -0
- mssql_python/libs/windows/x64/MICROSOFT_VISUAL_STUDIO_LICENSE.txt +54 -0
- mssql_python/libs/windows/x64/msodbcdiag18.dll +0 -0
- mssql_python/libs/windows/x64/msodbcsql18.dll +0 -0
- mssql_python/libs/windows/x64/mssql-auth.dll +0 -0
- mssql_python/libs/windows/x86/1033/msodbcsqlr18.rll +0 -0
- mssql_python/libs/windows/x86/MICROSOFT_ODBC_DRIVER_FOR_SQL_SERVER_LICENSE.txt +76 -0
- mssql_python/libs/windows/x86/msodbcdiag18.dll +0 -0
- mssql_python/libs/windows/x86/msodbcsql18.dll +0 -0
- mssql_python/libs/windows/x86/mssql-auth.dll +0 -0
- mssql_python/logging_config.py +65 -0
- mssql_python/msvcp140.dll +0 -0
- mssql_python/pooling.py +47 -0
- mssql_python/row.py +65 -0
- mssql_python/testing_ddbc_bindings.py +463 -0
- mssql_python/type.py +107 -0
- mssql_python-0.7.0.dist-info/LICENSE +47 -0
- mssql_python-0.7.0.dist-info/METADATA +39 -0
- mssql_python-0.7.0.dist-info/RECORD +70 -0
- mssql_python-0.7.0.dist-info/WHEEL +5 -0
- mssql_python-0.7.0.dist-info/top_level.txt +1 -0
mssql_python/__init__.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Microsoft Corporation.
|
|
3
|
+
Licensed under the MIT license.
|
|
4
|
+
This module initializes the mssql_python package.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# Exceptions
|
|
8
|
+
# https://www.python.org/dev/peps/pep-0249/#exceptions
|
|
9
|
+
from .exceptions import (
|
|
10
|
+
Warning,
|
|
11
|
+
Error,
|
|
12
|
+
InterfaceError,
|
|
13
|
+
DatabaseError,
|
|
14
|
+
DataError,
|
|
15
|
+
OperationalError,
|
|
16
|
+
IntegrityError,
|
|
17
|
+
InternalError,
|
|
18
|
+
ProgrammingError,
|
|
19
|
+
NotSupportedError,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Type Objects
|
|
23
|
+
from .type import (
|
|
24
|
+
Date,
|
|
25
|
+
Time,
|
|
26
|
+
Timestamp,
|
|
27
|
+
DateFromTicks,
|
|
28
|
+
TimeFromTicks,
|
|
29
|
+
TimestampFromTicks,
|
|
30
|
+
Binary,
|
|
31
|
+
STRING,
|
|
32
|
+
BINARY,
|
|
33
|
+
NUMBER,
|
|
34
|
+
DATETIME,
|
|
35
|
+
ROWID,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Connection Objects
|
|
39
|
+
from .db_connection import connect, Connection
|
|
40
|
+
|
|
41
|
+
# Cursor Objects
|
|
42
|
+
from .cursor import Cursor
|
|
43
|
+
|
|
44
|
+
# Logging Configuration
|
|
45
|
+
from .logging_config import setup_logging, get_logger
|
|
46
|
+
|
|
47
|
+
# Constants
|
|
48
|
+
from .constants import ConstantsDDBC
|
|
49
|
+
|
|
50
|
+
# GLOBALS
|
|
51
|
+
# Read-Only
|
|
52
|
+
apilevel = "2.0"
|
|
53
|
+
paramstyle = "qmark"
|
|
54
|
+
threadsafety = 1
|
|
55
|
+
|
|
56
|
+
from .pooling import PoolingManager
|
|
57
|
+
def pooling(max_size=100, idle_timeout=600, enabled=True):
|
|
58
|
+
# """
|
|
59
|
+
# Enable connection pooling with the specified parameters.
|
|
60
|
+
# By default:
|
|
61
|
+
# - If not explicitly called, pooling will be auto-enabled with default values.
|
|
62
|
+
|
|
63
|
+
# Args:
|
|
64
|
+
# max_size (int): Maximum number of connections in the pool.
|
|
65
|
+
# idle_timeout (int): Time in seconds before idle connections are closed.
|
|
66
|
+
|
|
67
|
+
# Returns:
|
|
68
|
+
# None
|
|
69
|
+
# """
|
|
70
|
+
if not enabled:
|
|
71
|
+
PoolingManager.disable()
|
|
72
|
+
else:
|
|
73
|
+
PoolingManager.enable(max_size, idle_timeout)
|
|
74
|
+
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import List, Optional, Literal
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass
|
|
6
|
+
class ColumnFormat:
|
|
7
|
+
"""
|
|
8
|
+
Represents the format of a column in a bulk copy operation.
|
|
9
|
+
Attributes:
|
|
10
|
+
prefix_len (int): Option: (format_file) or (prefix_len, data_len).
|
|
11
|
+
The length of the prefix for fixed-length data types. Must be non-negative.
|
|
12
|
+
data_len (int): Option: (format_file) or (prefix_len, data_len).
|
|
13
|
+
The length of the data. Must be non-negative.
|
|
14
|
+
field_terminator (Optional[bytes]): Option: (-t). The field terminator string.
|
|
15
|
+
e.g., b',' for comma-separated values.
|
|
16
|
+
row_terminator (Optional[bytes]): Option: (-r). The row terminator string.
|
|
17
|
+
e.g., b'\\n' for newline-terminated rows.
|
|
18
|
+
server_col (int): Option: (format_file) or (server_col). The 1-based column number
|
|
19
|
+
in the SQL Server table. Defaults to 1, representing the first column.
|
|
20
|
+
Must be a positive integer.
|
|
21
|
+
file_col (int): Option: (format_file) or (file_col). The 1-based column number
|
|
22
|
+
in the data file. Defaults to 1, representing the first column.
|
|
23
|
+
Must be a positive integer.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
prefix_len: int
|
|
27
|
+
data_len: int
|
|
28
|
+
field_terminator: Optional[bytes] = None
|
|
29
|
+
row_terminator: Optional[bytes] = None
|
|
30
|
+
server_col: int = 1
|
|
31
|
+
file_col: int = 1
|
|
32
|
+
|
|
33
|
+
def __post_init__(self):
|
|
34
|
+
if self.prefix_len < 0:
|
|
35
|
+
raise ValueError("prefix_len must be a non-negative integer.")
|
|
36
|
+
if self.data_len < 0:
|
|
37
|
+
raise ValueError("data_len must be a non-negative integer.")
|
|
38
|
+
if self.server_col <= 0:
|
|
39
|
+
raise ValueError("server_col must be a positive integer (1-based).")
|
|
40
|
+
if self.file_col <= 0:
|
|
41
|
+
raise ValueError("file_col must be a positive integer (1-based).")
|
|
42
|
+
if self.field_terminator is not None and not isinstance(
|
|
43
|
+
self.field_terminator, bytes
|
|
44
|
+
):
|
|
45
|
+
raise TypeError("field_terminator must be bytes or None.")
|
|
46
|
+
if self.row_terminator is not None and not isinstance(
|
|
47
|
+
self.row_terminator, bytes
|
|
48
|
+
):
|
|
49
|
+
raise TypeError("row_terminator must be bytes or None.")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class BCPOptions:
|
|
54
|
+
"""
|
|
55
|
+
Represents the options for a bulk copy operation.
|
|
56
|
+
Attributes:
|
|
57
|
+
direction (Literal[str]): 'in' or 'out'. Option: (-i or -o).
|
|
58
|
+
data_file (str): The data file. Option: (positional argument).
|
|
59
|
+
error_file (Optional[str]): The error file. Option: (-e).
|
|
60
|
+
format_file (Optional[str]): The format file to use for 'in'/'out'. Option: (-f).
|
|
61
|
+
batch_size (Optional[int]): The batch size. Option: (-b).
|
|
62
|
+
max_errors (Optional[int]): The maximum number of errors allowed. Option: (-m).
|
|
63
|
+
first_row (Optional[int]): The first row to process. Option: (-F).
|
|
64
|
+
last_row (Optional[int]): The last row to process. Option: (-L).
|
|
65
|
+
code_page (Optional[str]): The code page. Option: (-C).
|
|
66
|
+
keep_identity (bool): Keep identity values. Option: (-E).
|
|
67
|
+
keep_nulls (bool): Keep null values. Option: (-k).
|
|
68
|
+
hints (Optional[str]): Additional hints. Option: (-h).
|
|
69
|
+
bulk_mode (str): Bulk mode ('native', 'char', 'unicode'). Option: (-n, -c, -w).
|
|
70
|
+
Defaults to "native".
|
|
71
|
+
columns (List[ColumnFormat]): Column formats.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
direction: Literal["in", "out"]
|
|
75
|
+
data_file: str # data_file is mandatory for 'in' and 'out'
|
|
76
|
+
error_file: Optional[str] = None
|
|
77
|
+
format_file: Optional[str] = None
|
|
78
|
+
# write_format_file is removed as 'format' direction is not actively supported
|
|
79
|
+
batch_size: Optional[int] = None
|
|
80
|
+
max_errors: Optional[int] = None
|
|
81
|
+
first_row: Optional[int] = None
|
|
82
|
+
last_row: Optional[int] = None
|
|
83
|
+
code_page: Optional[str] = None
|
|
84
|
+
keep_identity: bool = False
|
|
85
|
+
keep_nulls: bool = False
|
|
86
|
+
hints: Optional[str] = None
|
|
87
|
+
bulk_mode: Literal["native", "char", "unicode"] = "native"
|
|
88
|
+
columns: List[ColumnFormat] = field(default_factory=list)
|
|
89
|
+
|
|
90
|
+
def __post_init__(self):
|
|
91
|
+
if self.direction not in ["in", "out"]:
|
|
92
|
+
raise ValueError("direction must be 'in' or 'out'.")
|
|
93
|
+
if not self.data_file:
|
|
94
|
+
raise ValueError("data_file must be provided and non-empty for 'in' or 'out' directions.")
|
|
95
|
+
if self.error_file is None or not self.error_file: # Making error_file mandatory for in/out
|
|
96
|
+
raise ValueError("error_file must be provided and non-empty for 'in' or 'out' directions.")
|
|
97
|
+
|
|
98
|
+
if self.format_file is not None and not self.format_file:
|
|
99
|
+
raise ValueError("format_file, if provided, must not be an empty string.")
|
|
100
|
+
if self.batch_size is not None and self.batch_size <= 0:
|
|
101
|
+
raise ValueError("batch_size must be a positive integer.")
|
|
102
|
+
if self.max_errors is not None and self.max_errors < 0:
|
|
103
|
+
raise ValueError("max_errors must be a non-negative integer.")
|
|
104
|
+
if self.first_row is not None and self.first_row <= 0:
|
|
105
|
+
raise ValueError("first_row must be a positive integer.")
|
|
106
|
+
if self.last_row is not None and self.last_row <= 0:
|
|
107
|
+
raise ValueError("last_row must be a positive integer.")
|
|
108
|
+
if self.last_row is not None and self.first_row is None:
|
|
109
|
+
raise ValueError("first_row must be specified if last_row is specified.")
|
|
110
|
+
if (
|
|
111
|
+
self.first_row is not None
|
|
112
|
+
and self.last_row is not None
|
|
113
|
+
and self.last_row < self.first_row
|
|
114
|
+
):
|
|
115
|
+
raise ValueError("last_row must be greater than or equal to first_row.")
|
|
116
|
+
if self.code_page is not None and not self.code_page:
|
|
117
|
+
raise ValueError("code_page, if provided, must not be an empty string.")
|
|
118
|
+
if self.hints is not None and not self.hints:
|
|
119
|
+
raise ValueError("hints, if provided, must not be an empty string.")
|
|
120
|
+
if self.bulk_mode not in ["native", "char", "unicode"]:
|
|
121
|
+
raise ValueError("bulk_mode must be 'native', 'char', or 'unicode'.")
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Microsoft Corporation.
|
|
3
|
+
Licensed under the MIT license.
|
|
4
|
+
This module defines the Connection class, which is used to manage a connection to a database.
|
|
5
|
+
The class provides methods to establish a connection, create cursors, commit transactions,
|
|
6
|
+
roll back transactions, and close the connection.
|
|
7
|
+
Resource Management:
|
|
8
|
+
- All cursors created from this connection are tracked internally.
|
|
9
|
+
- When close() is called on the connection, all open cursors are automatically closed.
|
|
10
|
+
- Do not use any cursor after the connection is closed; doing so will raise an exception.
|
|
11
|
+
- Cursors are also cleaned up automatically when no longer referenced, to prevent memory leaks.
|
|
12
|
+
"""
|
|
13
|
+
import weakref
|
|
14
|
+
from mssql_python.cursor import Cursor
|
|
15
|
+
from mssql_python.logging_config import get_logger, ENABLE_LOGGING
|
|
16
|
+
from mssql_python.constants import ConstantsDDBC as ddbc_sql_const
|
|
17
|
+
from mssql_python.helpers import add_driver_to_connection_str, check_error
|
|
18
|
+
from mssql_python import ddbc_bindings
|
|
19
|
+
from mssql_python.pooling import PoolingManager
|
|
20
|
+
from mssql_python.exceptions import DatabaseError, InterfaceError
|
|
21
|
+
|
|
22
|
+
logger = get_logger()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Connection:
|
|
26
|
+
"""
|
|
27
|
+
A class to manage a connection to a database, compliant with DB-API 2.0 specifications.
|
|
28
|
+
|
|
29
|
+
This class provides methods to establish a connection to a database, create cursors,
|
|
30
|
+
commit transactions, roll back transactions, and close the connection. It is designed
|
|
31
|
+
to be used in a context where database operations are required, such as executing queries
|
|
32
|
+
and fetching results.
|
|
33
|
+
|
|
34
|
+
Methods:
|
|
35
|
+
__init__(database: str) -> None:
|
|
36
|
+
connect_to_db() -> None:
|
|
37
|
+
cursor() -> Cursor:
|
|
38
|
+
commit() -> None:
|
|
39
|
+
rollback() -> None:
|
|
40
|
+
close() -> None:
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self, connection_str: str = "", autocommit: bool = False, attrs_before: dict = None, **kwargs) -> None:
|
|
44
|
+
"""
|
|
45
|
+
Initialize the connection object with the specified connection string and parameters.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
- connection_str (str): The connection string to connect to.
|
|
49
|
+
- autocommit (bool): If True, causes a commit to be performed after each SQL statement.
|
|
50
|
+
**kwargs: Additional key/value pairs for the connection string.
|
|
51
|
+
Not including below properties since we are driver doesn't support this:
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
None
|
|
55
|
+
|
|
56
|
+
Raises:
|
|
57
|
+
ValueError: If the connection string is invalid or connection fails.
|
|
58
|
+
|
|
59
|
+
This method sets up the initial state for the connection object,
|
|
60
|
+
preparing it for further operations such as connecting to the
|
|
61
|
+
database, executing queries, etc.
|
|
62
|
+
"""
|
|
63
|
+
self.connection_str = self._construct_connection_string(
|
|
64
|
+
connection_str, **kwargs
|
|
65
|
+
)
|
|
66
|
+
self._attrs_before = attrs_before or {}
|
|
67
|
+
self._closed = False
|
|
68
|
+
|
|
69
|
+
# Using WeakSet which automatically removes cursors when they are no longer in use
|
|
70
|
+
# It is a set that holds weak references to its elements.
|
|
71
|
+
# When an object is only weakly referenced, it can be garbage collected even if it's still in the set.
|
|
72
|
+
# It prevents memory leaks by ensuring that cursors are cleaned up when no longer in use without requiring explicit deletion.
|
|
73
|
+
# TODO: Think and implement scenarios for multi-threaded access to cursors
|
|
74
|
+
self._cursors = weakref.WeakSet()
|
|
75
|
+
|
|
76
|
+
# Auto-enable pooling if user never called
|
|
77
|
+
if not PoolingManager.is_initialized():
|
|
78
|
+
PoolingManager.enable()
|
|
79
|
+
self._pooling = PoolingManager.is_enabled()
|
|
80
|
+
self._conn = ddbc_bindings.Connection(self.connection_str, self._pooling, self._attrs_before)
|
|
81
|
+
self.setautocommit(autocommit)
|
|
82
|
+
|
|
83
|
+
def _construct_connection_string(self, connection_str: str = "", **kwargs) -> str:
|
|
84
|
+
"""
|
|
85
|
+
Construct the connection string by concatenating the connection string
|
|
86
|
+
with key/value pairs from kwargs.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
connection_str (str): The base connection string.
|
|
90
|
+
**kwargs: Additional key/value pairs for the connection string.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
str: The constructed connection string.
|
|
94
|
+
"""
|
|
95
|
+
# Add the driver attribute to the connection string
|
|
96
|
+
conn_str = add_driver_to_connection_str(connection_str)
|
|
97
|
+
|
|
98
|
+
# Add additional key-value pairs to the connection string
|
|
99
|
+
for key, value in kwargs.items():
|
|
100
|
+
if key.lower() == "host" or key.lower() == "server":
|
|
101
|
+
key = "Server"
|
|
102
|
+
elif key.lower() == "user" or key.lower() == "uid":
|
|
103
|
+
key = "Uid"
|
|
104
|
+
elif key.lower() == "password" or key.lower() == "pwd":
|
|
105
|
+
key = "Pwd"
|
|
106
|
+
elif key.lower() == "database":
|
|
107
|
+
key = "Database"
|
|
108
|
+
elif key.lower() == "encrypt":
|
|
109
|
+
key = "Encrypt"
|
|
110
|
+
elif key.lower() == "trust_server_certificate":
|
|
111
|
+
key = "TrustServerCertificate"
|
|
112
|
+
else:
|
|
113
|
+
continue
|
|
114
|
+
conn_str += f"{key}={value};"
|
|
115
|
+
|
|
116
|
+
if ENABLE_LOGGING:
|
|
117
|
+
logger.info("Final connection string: %s", conn_str)
|
|
118
|
+
|
|
119
|
+
return conn_str
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def autocommit(self) -> bool:
|
|
123
|
+
"""
|
|
124
|
+
Return the current autocommit mode of the connection.
|
|
125
|
+
Returns:
|
|
126
|
+
bool: True if autocommit is enabled, False otherwise.
|
|
127
|
+
"""
|
|
128
|
+
return self._conn.get_autocommit()
|
|
129
|
+
|
|
130
|
+
@autocommit.setter
|
|
131
|
+
def autocommit(self, value: bool) -> None:
|
|
132
|
+
"""
|
|
133
|
+
Set the autocommit mode of the connection.
|
|
134
|
+
Args:
|
|
135
|
+
value (bool): True to enable autocommit, False to disable it.
|
|
136
|
+
Returns:
|
|
137
|
+
None
|
|
138
|
+
"""
|
|
139
|
+
self.setautocommit(value)
|
|
140
|
+
if ENABLE_LOGGING:
|
|
141
|
+
logger.info("Autocommit mode set to %s.", value)
|
|
142
|
+
|
|
143
|
+
def setautocommit(self, value: bool = True) -> None:
|
|
144
|
+
"""
|
|
145
|
+
Set the autocommit mode of the connection.
|
|
146
|
+
Args:
|
|
147
|
+
value (bool): True to enable autocommit, False to disable it.
|
|
148
|
+
Returns:
|
|
149
|
+
None
|
|
150
|
+
Raises:
|
|
151
|
+
DatabaseError: If there is an error while setting the autocommit mode.
|
|
152
|
+
"""
|
|
153
|
+
self._conn.set_autocommit(value)
|
|
154
|
+
|
|
155
|
+
def cursor(self) -> Cursor:
|
|
156
|
+
"""
|
|
157
|
+
Return a new Cursor object using the connection.
|
|
158
|
+
|
|
159
|
+
This method creates and returns a new cursor object that can be used to
|
|
160
|
+
execute SQL queries and fetch results. The cursor is associated with the
|
|
161
|
+
current connection and allows interaction with the database.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
Cursor: A new cursor object for executing SQL queries.
|
|
165
|
+
|
|
166
|
+
Raises:
|
|
167
|
+
DatabaseError: If there is an error while creating the cursor.
|
|
168
|
+
InterfaceError: If there is an error related to the database interface.
|
|
169
|
+
"""
|
|
170
|
+
"""Return a new Cursor object using the connection."""
|
|
171
|
+
if self._closed:
|
|
172
|
+
# raise InterfaceError
|
|
173
|
+
raise InterfaceError(
|
|
174
|
+
driver_error="Cannot create cursor on closed connection",
|
|
175
|
+
ddbc_error="Cannot create cursor on closed connection",
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
cursor = Cursor(self)
|
|
179
|
+
self._cursors.add(cursor) # Track the cursor
|
|
180
|
+
return cursor
|
|
181
|
+
|
|
182
|
+
def commit(self) -> None:
|
|
183
|
+
"""
|
|
184
|
+
Commit the current transaction.
|
|
185
|
+
|
|
186
|
+
This method commits the current transaction to the database, making all
|
|
187
|
+
changes made during the transaction permanent. It should be called after
|
|
188
|
+
executing a series of SQL statements that modify the database to ensure
|
|
189
|
+
that the changes are saved.
|
|
190
|
+
|
|
191
|
+
Raises:
|
|
192
|
+
DatabaseError: If there is an error while committing the transaction.
|
|
193
|
+
"""
|
|
194
|
+
# Commit the current transaction
|
|
195
|
+
self._conn.commit()
|
|
196
|
+
if ENABLE_LOGGING:
|
|
197
|
+
logger.info("Transaction committed successfully.")
|
|
198
|
+
|
|
199
|
+
def rollback(self) -> None:
|
|
200
|
+
"""
|
|
201
|
+
Roll back the current transaction.
|
|
202
|
+
|
|
203
|
+
This method rolls back the current transaction, undoing all changes made
|
|
204
|
+
during the transaction. It should be called if an error occurs during the
|
|
205
|
+
transaction or if the changes should not be saved.
|
|
206
|
+
|
|
207
|
+
Raises:
|
|
208
|
+
DatabaseError: If there is an error while rolling back the transaction.
|
|
209
|
+
"""
|
|
210
|
+
# Roll back the current transaction
|
|
211
|
+
self._conn.rollback()
|
|
212
|
+
if ENABLE_LOGGING:
|
|
213
|
+
logger.info("Transaction rolled back successfully.")
|
|
214
|
+
|
|
215
|
+
def close(self) -> None:
|
|
216
|
+
"""
|
|
217
|
+
Close the connection now (rather than whenever .__del__() is called).
|
|
218
|
+
|
|
219
|
+
This method closes the connection to the database, releasing any resources
|
|
220
|
+
associated with it. After calling this method, the connection object should
|
|
221
|
+
not be used for any further operations. The same applies to all cursor objects
|
|
222
|
+
trying to use the connection. Note that closing a connection without committing
|
|
223
|
+
the changes first will cause an implicit rollback to be performed.
|
|
224
|
+
|
|
225
|
+
Raises:
|
|
226
|
+
DatabaseError: If there is an error while closing the connection.
|
|
227
|
+
"""
|
|
228
|
+
# Close the connection
|
|
229
|
+
if self._closed:
|
|
230
|
+
return
|
|
231
|
+
|
|
232
|
+
# Close all cursors first, but don't let one failure stop the others
|
|
233
|
+
if hasattr(self, '_cursors'):
|
|
234
|
+
# Convert to list to avoid modification during iteration
|
|
235
|
+
cursors_to_close = list(self._cursors)
|
|
236
|
+
close_errors = []
|
|
237
|
+
|
|
238
|
+
for cursor in cursors_to_close:
|
|
239
|
+
try:
|
|
240
|
+
if not cursor.closed:
|
|
241
|
+
cursor.close()
|
|
242
|
+
except Exception as e:
|
|
243
|
+
# Collect errors but continue closing other cursors
|
|
244
|
+
close_errors.append(f"Error closing cursor: {e}")
|
|
245
|
+
if ENABLE_LOGGING:
|
|
246
|
+
logger.warning(f"Error closing cursor: {e}")
|
|
247
|
+
|
|
248
|
+
# If there were errors closing cursors, log them but continue
|
|
249
|
+
if close_errors and ENABLE_LOGGING:
|
|
250
|
+
logger.warning(f"Encountered {len(close_errors)} errors while closing cursors")
|
|
251
|
+
|
|
252
|
+
# Clear the cursor set explicitly to release any internal references
|
|
253
|
+
self._cursors.clear()
|
|
254
|
+
|
|
255
|
+
# Close the connection even if cursor cleanup had issues
|
|
256
|
+
try:
|
|
257
|
+
if self._conn:
|
|
258
|
+
self._conn.close()
|
|
259
|
+
self._conn = None
|
|
260
|
+
except Exception as e:
|
|
261
|
+
if ENABLE_LOGGING:
|
|
262
|
+
logger.error(f"Error closing database connection: {e}")
|
|
263
|
+
# Re-raise the connection close error as it's more critical
|
|
264
|
+
raise
|
|
265
|
+
finally:
|
|
266
|
+
# Always mark as closed, even if there were errors
|
|
267
|
+
self._closed = True
|
|
268
|
+
|
|
269
|
+
if ENABLE_LOGGING:
|
|
270
|
+
logger.info("Connection closed successfully.")
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Microsoft Corporation.
|
|
3
|
+
Licensed under the MIT license.
|
|
4
|
+
This module contains the constants used in the DDBC module.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from enum import Enum
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ConstantsDDBC(Enum):
|
|
11
|
+
"""
|
|
12
|
+
Constants used in the DDBC module.
|
|
13
|
+
"""
|
|
14
|
+
SQL_HANDLE_ENV = 1
|
|
15
|
+
SQL_HANDLE_DBC = 2
|
|
16
|
+
SQL_HANDLE_STMT = 3
|
|
17
|
+
SQL_SUCCESS = 0
|
|
18
|
+
SQL_SUCCESS_WITH_INFO = 1
|
|
19
|
+
SQL_NO_DATA = 100
|
|
20
|
+
SQL_STILL_EXECUTING = 2
|
|
21
|
+
SQL_NTS = -3
|
|
22
|
+
SQL_DRIVER_NOPROMPT = 0
|
|
23
|
+
SQL_ATTR_ASYNC_DBC_EVENT = 119
|
|
24
|
+
SQL_IS_INTEGER = -6
|
|
25
|
+
SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE = 117
|
|
26
|
+
SQL_OV_DDBC3_80 = 380
|
|
27
|
+
SQL_ATTR_DDBC_VERSION = 200
|
|
28
|
+
SQL_ATTR_ASYNC_ENABLE = 4
|
|
29
|
+
SQL_ATTR_ASYNC_STMT_EVENT = 29
|
|
30
|
+
SQL_ERROR = -1
|
|
31
|
+
SQL_INVALID_HANDLE = -2
|
|
32
|
+
SQL_NULL_HANDLE = 0
|
|
33
|
+
SQL_OV_DDBC3 = 3
|
|
34
|
+
SQL_COMMIT = 0
|
|
35
|
+
SQL_ROLLBACK = 1
|
|
36
|
+
SQL_ATTR_AUTOCOMMIT = 102
|
|
37
|
+
SQL_SMALLINT = 5
|
|
38
|
+
SQL_CHAR = 1
|
|
39
|
+
SQL_WCHAR = -8
|
|
40
|
+
SQL_WVARCHAR = -9
|
|
41
|
+
SQL_BIT = -7
|
|
42
|
+
SQL_TINYINT = -6
|
|
43
|
+
SQL_BIGINT = -5
|
|
44
|
+
SQL_BINARY = -2
|
|
45
|
+
SQL_VARBINARY = -3
|
|
46
|
+
SQL_LONGVARBINARY = -4
|
|
47
|
+
SQL_LONGVARCHAR = -1
|
|
48
|
+
SQL_UNKNOWN_TYPE = 0
|
|
49
|
+
SQL_NUMERIC = 2
|
|
50
|
+
SQL_DECIMAL = 3
|
|
51
|
+
SQL_INTEGER = 4
|
|
52
|
+
SQL_FLOAT = 6
|
|
53
|
+
SQL_REAL = 7
|
|
54
|
+
SQL_DOUBLE = 8
|
|
55
|
+
SQL_DATETIME = 9
|
|
56
|
+
SQL_INTERVAL = 10
|
|
57
|
+
SQL_TIMESTAMP = 11
|
|
58
|
+
SQL_DATE = 9
|
|
59
|
+
SQL_TIME = 10
|
|
60
|
+
SQL_VARCHAR = 12
|
|
61
|
+
SQL_TYPE_DATE = 91
|
|
62
|
+
SQL_TYPE_TIME = 92
|
|
63
|
+
SQL_TYPE_TIMESTAMP = 93
|
|
64
|
+
SQL_TYPE_TIMESTAMP_WITH_TIMEZONE = 95
|
|
65
|
+
SQL_GUID = -11
|
|
66
|
+
SQL_XML = 241
|
|
67
|
+
SQL_SMALLDATETIME = 58
|
|
68
|
+
SQL_TIMESTAMPOFFSET = 43
|
|
69
|
+
SQL_DATETIME2 = 42
|
|
70
|
+
SQL_SMALLMONEY = 122
|
|
71
|
+
SQL_MONEY = 60
|
|
72
|
+
SQL_WLONGVARCHAR = -10
|
|
73
|
+
SQL_C_BIT = -7
|
|
74
|
+
SQL_C_TINYINT = -6
|
|
75
|
+
SQL_C_SBIGINT = -25
|
|
76
|
+
SQL_C_BINARY = -2
|
|
77
|
+
SQL_AUTOCOMMIT_ON = 1
|
|
78
|
+
SQL_AUTOCOMMIT_OFF = 0
|
|
79
|
+
SQL_C_VARBINARY = -3
|
|
80
|
+
SQL_C_LONGVARBINARY = -4
|
|
81
|
+
SQL_C_LONGVARCHAR = -1
|
|
82
|
+
SQL_C_CHAR = -8
|
|
83
|
+
SQL_C_NUMERIC = 2
|
|
84
|
+
SQL_C_DECIMAL = 3
|
|
85
|
+
SQL_C_LONG = 4
|
|
86
|
+
SQL_C_SHORT = 5
|
|
87
|
+
SQL_C_FLOAT = 7
|
|
88
|
+
SQL_C_DOUBLE = 8
|
|
89
|
+
SQL_C_TYPE_DATE = 91
|
|
90
|
+
SQL_C_TYPE_TIME = 92
|
|
91
|
+
SQL_C_TYPE_TIMESTAMP = 93
|
|
92
|
+
SQL_C_TYPE_TIMESTAMP_WITH_TIMEZONE = 95
|
|
93
|
+
SQL_C_GUID = -11
|
|
94
|
+
SQL_DESC_TYPE = 2
|
|
95
|
+
SQL_DESC_LENGTH = 3
|
|
96
|
+
SQL_DESC_NAME = 4
|
|
97
|
+
SQL_ATTR_ROW_ARRAY_SIZE = 27
|
|
98
|
+
SQL_ATTR_ROWS_FETCHED_PTR = 26
|
|
99
|
+
SQL_ATTR_ROW_STATUS_PTR = 25
|
|
100
|
+
SQL_FETCH_NEXT = 1
|
|
101
|
+
SQL_ROW_SUCCESS = 0
|
|
102
|
+
SQL_ROW_SUCCESS_WITH_INFO = 1
|
|
103
|
+
SQL_ROW_NOROW = 100
|
|
104
|
+
SQL_ATTR_CURSOR_TYPE = 6
|
|
105
|
+
SQL_CURSOR_FORWARD_ONLY = 0
|
|
106
|
+
SQL_CURSOR_STATIC = 3
|
|
107
|
+
SQL_CURSOR_KEYSET_DRIVEN = 2
|
|
108
|
+
SQL_CURSOR_DYNAMIC = 3
|
|
109
|
+
SQL_NULL_DATA = -1
|
|
110
|
+
SQL_C_DEFAULT = 99
|
|
111
|
+
SQL_ATTR_ROW_BIND_TYPE = 5
|
|
112
|
+
SQL_BIND_BY_COLUMN = 0
|
|
113
|
+
SQL_PARAM_INPUT = 1
|
|
114
|
+
SQL_PARAM_OUTPUT = 2
|
|
115
|
+
SQL_PARAM_INPUT_OUTPUT = 3
|
|
116
|
+
SQL_C_WCHAR = -8
|
|
117
|
+
SQL_NULLABLE = 1
|
|
118
|
+
SQL_MAX_NUMERIC_LEN = 16
|