mssql-python 0.1.6__cp313-cp313-win_arm64.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 +55 -0
- mssql_python/connection.py +424 -0
- mssql_python/constants.py +120 -0
- mssql_python/cursor.py +736 -0
- mssql_python/db_connection.py +38 -0
- mssql_python/ddbc_bindings.cp313-arm64.pyd +0 -0
- mssql_python/ddbc_bindings.py +38 -0
- mssql_python/exceptions.py +650 -0
- mssql_python/helpers.py +111 -0
- mssql_python/libs/LICENSING +19 -0
- mssql_python/libs/arm64/1033/msodbcsqlr18.rll +0 -0
- mssql_python/libs/arm64/msodbcdiag18.dll +0 -0
- mssql_python/libs/arm64/msodbcsql18.dll +0 -0
- mssql_python/libs/arm64/mssql-auth.dll +0 -0
- mssql_python/logging_config.py +65 -0
- mssql_python/mssql_python.pyi +192 -0
- mssql_python/msvcp140.dll +0 -0
- mssql_python/testing_ddbc_bindings.py +463 -0
- mssql_python/type.py +107 -0
- mssql_python-0.1.6.dist-info/METADATA +45 -0
- mssql_python-0.1.6.dist-info/RECORD +24 -0
- mssql_python-0.1.6.dist-info/WHEEL +5 -0
- mssql_python-0.1.6.dist-info/licenses/LICENSE +47 -0
- mssql_python-0.1.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Microsoft Corporation.
|
|
3
|
+
Licensed under the MIT license.
|
|
4
|
+
This module provides functions to test DDBC bindings.
|
|
5
|
+
"""
|
|
6
|
+
import ctypes
|
|
7
|
+
import datetime
|
|
8
|
+
import os
|
|
9
|
+
from mssql_python import ddbc_bindings
|
|
10
|
+
from mssql_python.logging_config import setup_logging
|
|
11
|
+
|
|
12
|
+
setup_logging()
|
|
13
|
+
|
|
14
|
+
# Constants
|
|
15
|
+
SQL_HANDLE_ENV = 1
|
|
16
|
+
SQL_HANDLE_DBC = 2
|
|
17
|
+
SQL_HANDLE_STMT = 3
|
|
18
|
+
SQL_ATTR_DDBC_VERSION = 200
|
|
19
|
+
SQL_OV_DDBC3_80 = 380
|
|
20
|
+
SQL_DRIVER_NOPROMPT = 0
|
|
21
|
+
SQL_NTS = -3 # SQL_NULL_TERMINATED for indicating string length in SQLDriverConnect
|
|
22
|
+
SQL_NO_DATA = 100 # This is the value to indicate that there is no more data
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def alloc_handle(handle_type, input_handle):
|
|
26
|
+
"""
|
|
27
|
+
Allocate a handle for the given handle type and input handle.
|
|
28
|
+
"""
|
|
29
|
+
result_alloc, handle = ddbc_bindings.DDBCSQLAllocHandle(
|
|
30
|
+
handle_type,
|
|
31
|
+
input_handle
|
|
32
|
+
)
|
|
33
|
+
if result_alloc < 0:
|
|
34
|
+
print(
|
|
35
|
+
"Error:", ddbc_bindings.DDBCSQLCheckError(handle_type, handle, result_alloc)
|
|
36
|
+
)
|
|
37
|
+
raise RuntimeError(f"Failed to allocate handle. Error code: {result_alloc}")
|
|
38
|
+
return handle
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def free_handle(handle_type, handle):
|
|
42
|
+
"""
|
|
43
|
+
Free the handle for the given handle type and handle.
|
|
44
|
+
"""
|
|
45
|
+
result_free = ddbc_bindings.DDBCSQLFreeHandle(handle_type, handle)
|
|
46
|
+
if result_free < 0:
|
|
47
|
+
print(
|
|
48
|
+
"Error:", ddbc_bindings.DDBCSQLCheckError(handle_type, handle, result_free)
|
|
49
|
+
)
|
|
50
|
+
raise RuntimeError(f"Failed to free handle. Error code: {result_free}")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def ddbc_sql_execute(
|
|
54
|
+
stmt_handle, query, params, param_info_list, is_stmt_prepared, use_prepare=True
|
|
55
|
+
):
|
|
56
|
+
"""
|
|
57
|
+
Execute an SQL statement using DDBC bindings.
|
|
58
|
+
"""
|
|
59
|
+
result_execute = ddbc_bindings.DDBCSQLExecute(
|
|
60
|
+
stmt_handle, query, params, param_info_list, is_stmt_prepared, use_prepare
|
|
61
|
+
)
|
|
62
|
+
if result_execute < 0:
|
|
63
|
+
print(
|
|
64
|
+
"Error: ",
|
|
65
|
+
ddbc_bindings.DDBCSQLCheckError(SQL_HANDLE_STMT, stmt_handle, result_execute),
|
|
66
|
+
)
|
|
67
|
+
raise RuntimeError(f"Failed to execute query. Error code: {result_execute}")
|
|
68
|
+
return result_execute
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def fetch_data_onebyone(stmt_handle):
|
|
72
|
+
"""
|
|
73
|
+
Fetch data one by one using DDBC bindings.
|
|
74
|
+
"""
|
|
75
|
+
rows = []
|
|
76
|
+
ret_fetch = 1
|
|
77
|
+
while ret_fetch != SQL_NO_DATA:
|
|
78
|
+
row = []
|
|
79
|
+
ret_fetch = ddbc_bindings.DDBCSQLFetchOne(stmt_handle, row)
|
|
80
|
+
if ret_fetch < 0:
|
|
81
|
+
print(
|
|
82
|
+
"Error: ",
|
|
83
|
+
ddbc_bindings.DDBCSQLCheckError(
|
|
84
|
+
SQL_HANDLE_STMT, stmt_handle, ret_fetch
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
raise RuntimeError(f"Failed to fetch data. Error code: {ret_fetch}")
|
|
88
|
+
print(row)
|
|
89
|
+
rows.append(row)
|
|
90
|
+
return rows
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def fetch_data_many(stmt_handle):
|
|
94
|
+
"""
|
|
95
|
+
Fetch data in batches using DDBC bindings.
|
|
96
|
+
"""
|
|
97
|
+
rows = []
|
|
98
|
+
ret_fetch = 1
|
|
99
|
+
while ret_fetch != SQL_NO_DATA:
|
|
100
|
+
ret_fetch = ddbc_bindings.DDBCSQLFetchMany(stmt_handle, rows, 10)
|
|
101
|
+
if ret_fetch < 0:
|
|
102
|
+
print(
|
|
103
|
+
"Error: ",
|
|
104
|
+
ddbc_bindings.DDBCSQLCheckError(
|
|
105
|
+
SQL_HANDLE_STMT, stmt_handle, ret_fetch
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
raise RuntimeError(f"Failed to fetch data. Error code: {ret_fetch}")
|
|
109
|
+
return rows
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def fetch_data_all(stmt_handle):
|
|
113
|
+
"""
|
|
114
|
+
Fetch all data using DDBC bindings.
|
|
115
|
+
"""
|
|
116
|
+
rows = []
|
|
117
|
+
ret_fetch = ddbc_bindings.DDBCSQLFetchAll(stmt_handle, rows)
|
|
118
|
+
if ret_fetch != SQL_NO_DATA:
|
|
119
|
+
print(
|
|
120
|
+
"Error: ",
|
|
121
|
+
ddbc_bindings.DDBCSQLCheckError(SQL_HANDLE_STMT, stmt_handle, ret_fetch),
|
|
122
|
+
)
|
|
123
|
+
raise RuntimeError(f"Failed to fetch data. Error code: {ret_fetch}")
|
|
124
|
+
return rows
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def fetch_data(stmt_handle):
|
|
128
|
+
"""
|
|
129
|
+
Fetch data using DDBC bindings.
|
|
130
|
+
"""
|
|
131
|
+
rows = []
|
|
132
|
+
column_count = ddbc_bindings.DDBCSQLNumResultCols(stmt_handle)
|
|
133
|
+
print("Number of columns = " + str(column_count))
|
|
134
|
+
while True:
|
|
135
|
+
result_fetch = ddbc_bindings.DDBCSQLFetch(stmt_handle)
|
|
136
|
+
if result_fetch == SQL_NO_DATA:
|
|
137
|
+
break
|
|
138
|
+
if result_fetch < 0:
|
|
139
|
+
print(
|
|
140
|
+
"Error: ",
|
|
141
|
+
ddbc_bindings.DDBCSQLCheckError(
|
|
142
|
+
SQL_HANDLE_STMT, stmt_handle, result_fetch
|
|
143
|
+
),
|
|
144
|
+
)
|
|
145
|
+
raise RuntimeError(f"Failed to fetch data. Error code: {result_fetch}")
|
|
146
|
+
if column_count > 0:
|
|
147
|
+
row = []
|
|
148
|
+
result_get_data = ddbc_bindings.DDBCSQLGetData(stmt_handle, column_count, row)
|
|
149
|
+
if result_get_data < 0:
|
|
150
|
+
print(
|
|
151
|
+
"Error: ",
|
|
152
|
+
ddbc_bindings.DDBCSQLCheckError(
|
|
153
|
+
SQL_HANDLE_STMT, stmt_handle, result_get_data
|
|
154
|
+
),
|
|
155
|
+
)
|
|
156
|
+
raise RuntimeError(f"Failed to get data. Error code: {result_get_data}")
|
|
157
|
+
rows.append(row)
|
|
158
|
+
return rows
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def describe_columns(stmt_handle):
|
|
162
|
+
"""
|
|
163
|
+
Describe columns using DDBC bindings.
|
|
164
|
+
"""
|
|
165
|
+
column_names = []
|
|
166
|
+
result_describe = ddbc_bindings.DDBCSQLDescribeCol(stmt_handle, column_names)
|
|
167
|
+
if result_describe < 0:
|
|
168
|
+
print(
|
|
169
|
+
"Error: ",
|
|
170
|
+
ddbc_bindings.DDBCSQLCheckError(SQL_HANDLE_STMT, stmt_handle, result_describe),
|
|
171
|
+
)
|
|
172
|
+
raise RuntimeError(f"Failed to describe columns. Error code: {result_describe}")
|
|
173
|
+
return column_names
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def connect_to_db(dbc_handle, connection_string):
|
|
177
|
+
"""
|
|
178
|
+
Connect to the database using DDBC bindings.
|
|
179
|
+
"""
|
|
180
|
+
result_connect = ddbc_bindings.DDBCSQLDriverConnect(dbc_handle, 0, connection_string)
|
|
181
|
+
if result_connect < 0:
|
|
182
|
+
print(
|
|
183
|
+
"Error: ",
|
|
184
|
+
ddbc_bindings.DDBCSQLCheckError(SQL_HANDLE_DBC, dbc_handle, result_connect),
|
|
185
|
+
)
|
|
186
|
+
raise RuntimeError(f"SQLDriverConnect failed. Error code: {result_connect}")
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def add_string_param(params, param_infos, data_string):
|
|
190
|
+
"""
|
|
191
|
+
Add a string parameter to the parameter list.
|
|
192
|
+
"""
|
|
193
|
+
params.append(data_string)
|
|
194
|
+
param_info = ddbc_bindings.ParamInfo()
|
|
195
|
+
param_info.paramCType = 1 # SQL_C_CHAR
|
|
196
|
+
param_info.paramSQLType = 12 # SQL_VARCHAR
|
|
197
|
+
param_info.columnSize = len(data_string)
|
|
198
|
+
param_info.inputOutputType = 1 # SQL_PARAM_INPUT
|
|
199
|
+
param_infos.append(param_info)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def add_wstring_param(params, param_infos, wide_string):
|
|
203
|
+
"""
|
|
204
|
+
Add a wide string parameter to the parameter list.
|
|
205
|
+
"""
|
|
206
|
+
params.append(wide_string)
|
|
207
|
+
param_info = ddbc_bindings.ParamInfo()
|
|
208
|
+
param_info.paramCType = -8 # SQL_C_WCHAR
|
|
209
|
+
param_info.paramSQLType = -9 # SQL_WVARCHAR
|
|
210
|
+
param_info.columnSize = len(wide_string)
|
|
211
|
+
param_info.inputOutputType = 1 # SQL_PARAM_INPUT
|
|
212
|
+
param_infos.append(param_info)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def add_date_param(params, param_infos):
|
|
216
|
+
"""
|
|
217
|
+
Add a date parameter to the parameter list.
|
|
218
|
+
"""
|
|
219
|
+
date_obj = datetime.date(2025, 1, 28) # 28th Jan 2025
|
|
220
|
+
params.append(date_obj)
|
|
221
|
+
param_info = ddbc_bindings.ParamInfo()
|
|
222
|
+
param_info.paramCType = 91 # SQL_C_TYPE_DATE
|
|
223
|
+
param_info.paramSQLType = 91 # SQL_TYPE_DATE
|
|
224
|
+
param_info.inputOutputType = 1 # SQL_PARAM_INPUT
|
|
225
|
+
param_infos.append(param_info)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def add_time_param(params, param_infos):
|
|
229
|
+
"""
|
|
230
|
+
Add a time parameter to the parameter list.
|
|
231
|
+
"""
|
|
232
|
+
time_obj = datetime.time(5, 15, 30) # 5:15 AM + 30 secs
|
|
233
|
+
params.append(time_obj)
|
|
234
|
+
param_info = ddbc_bindings.ParamInfo()
|
|
235
|
+
param_info.paramCType = 92 # SQL_C_TYPE_TIME
|
|
236
|
+
param_info.paramSQLType = 92 # SQL_TYPE_TIME
|
|
237
|
+
param_info.inputOutputType = 1 # SQL_PARAM_INPUT
|
|
238
|
+
param_infos.append(param_info)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def add_datetime_param(params, param_infos, add_none):
|
|
242
|
+
"""
|
|
243
|
+
Add a datetime parameter to the parameter list.
|
|
244
|
+
"""
|
|
245
|
+
param_info = ddbc_bindings.ParamInfo()
|
|
246
|
+
if add_none:
|
|
247
|
+
params.append(None)
|
|
248
|
+
param_info.paramCType = 99 # SQL_C_DEFAULT
|
|
249
|
+
else:
|
|
250
|
+
datetime_obj = datetime.datetime(2025, 1, 28, 5, 15, 30)
|
|
251
|
+
params.append(datetime_obj)
|
|
252
|
+
param_info.paramCType = 93 # SQL_C_TYPE_TIMESTAMP
|
|
253
|
+
param_info.paramSQLType = 93 # SQL_TYPE_TIMESTAMP
|
|
254
|
+
param_info.inputOutputType = 1 # SQL_PARAM_INPUT
|
|
255
|
+
param_infos.append(param_info)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def add_bool_param(params, param_infos, bool_val):
|
|
259
|
+
"""
|
|
260
|
+
Add a boolean parameter to the parameter list.
|
|
261
|
+
"""
|
|
262
|
+
params.append(bool_val)
|
|
263
|
+
param_info = ddbc_bindings.ParamInfo()
|
|
264
|
+
param_info.paramCType = -7 # SQL_C_BIT
|
|
265
|
+
param_info.paramSQLType = -7 # SQL_BIT
|
|
266
|
+
param_info.inputOutputType = 1 # SQL_PARAM_INPUT
|
|
267
|
+
param_infos.append(param_info)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def add_tinyint_param(params, param_infos, val):
|
|
271
|
+
"""
|
|
272
|
+
Add a tinyint parameter to the parameter list.
|
|
273
|
+
"""
|
|
274
|
+
params.append(val)
|
|
275
|
+
param_info = ddbc_bindings.ParamInfo()
|
|
276
|
+
param_info.paramCType = -6 # SQL_C_TINYINT
|
|
277
|
+
param_info.paramSQLType = -6 # SQL_TINYINT
|
|
278
|
+
param_info.inputOutputType = 1 # SQL_PARAM_INPUT
|
|
279
|
+
param_infos.append(param_info)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def add_bigint_param(params, param_infos, val):
|
|
283
|
+
"""
|
|
284
|
+
Add a bigint parameter to the parameter list.
|
|
285
|
+
"""
|
|
286
|
+
params.append(val)
|
|
287
|
+
param_info = ddbc_bindings.ParamInfo()
|
|
288
|
+
param_info.paramCType = -25 # SQL_C_SBIGINT
|
|
289
|
+
param_info.paramSQLType = -5 # SQL_BIGINT
|
|
290
|
+
param_info.inputOutputType = 1 # SQL_PARAM_INPUT
|
|
291
|
+
param_infos.append(param_info)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def add_float_param(params, param_infos, val):
|
|
295
|
+
"""
|
|
296
|
+
Add a float parameter to the parameter list.
|
|
297
|
+
"""
|
|
298
|
+
params.append(val)
|
|
299
|
+
param_info = ddbc_bindings.ParamInfo()
|
|
300
|
+
param_info.paramCType = 7 # SQL_C_FLOAT
|
|
301
|
+
param_info.paramSQLType = 7 # SQL_REAL
|
|
302
|
+
param_info.inputOutputType = 1 # SQL_PARAM_INPUT
|
|
303
|
+
param_info.columnSize = 15 # Precision
|
|
304
|
+
param_infos.append(param_info)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def add_double_param(params, param_infos, val):
|
|
308
|
+
"""
|
|
309
|
+
Add a double parameter to the parameter list.
|
|
310
|
+
"""
|
|
311
|
+
params.append(val)
|
|
312
|
+
param_info = ddbc_bindings.ParamInfo()
|
|
313
|
+
param_info.paramCType = 8 # SQL_C_DOUBLE
|
|
314
|
+
param_info.paramSQLType = 8 # SQL_DOUBLE
|
|
315
|
+
param_info.inputOutputType = 1 # SQL_PARAM_INPUT
|
|
316
|
+
param_info.columnSize = 15 # Precision
|
|
317
|
+
param_infos.append(param_info)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def add_numeric_param(params, param_infos, param):
|
|
321
|
+
"""
|
|
322
|
+
Add a numeric parameter to the parameter list.
|
|
323
|
+
"""
|
|
324
|
+
numeric_data = ddbc_bindings.NumericData()
|
|
325
|
+
numeric_data.precision = len(param.as_tuple().digits)
|
|
326
|
+
numeric_data.scale = param.as_tuple().exponent * -1
|
|
327
|
+
numeric_data.sign = param.as_tuple().sign
|
|
328
|
+
numeric_data.val = str(param)
|
|
329
|
+
print(
|
|
330
|
+
type(numeric_data.precision),
|
|
331
|
+
type(numeric_data.scale),
|
|
332
|
+
type(numeric_data.sign),
|
|
333
|
+
type(numeric_data.val),
|
|
334
|
+
type(numeric_data),
|
|
335
|
+
)
|
|
336
|
+
params.append(numeric_data)
|
|
337
|
+
|
|
338
|
+
param_info = ddbc_bindings.ParamInfo()
|
|
339
|
+
param_info.paramCType = 2 # SQL_C_NUMERIC
|
|
340
|
+
param_info.paramSQLType = 2 # SQL_NUMERIC
|
|
341
|
+
param_info.inputOutputType = 1 # SQL_PARAM_INPUT
|
|
342
|
+
param_info.columnSize = 10 # Precision
|
|
343
|
+
param_infos.append(param_info)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
if __name__ == "__main__":
|
|
347
|
+
# Allocate environment handle
|
|
348
|
+
env_handle = alloc_handle(SQL_HANDLE_ENV, None)
|
|
349
|
+
|
|
350
|
+
# Set the DDBC version environment attribute
|
|
351
|
+
result_set_env = ddbc_bindings.DDBCSQLSetEnvAttr(
|
|
352
|
+
env_handle, SQL_ATTR_DDBC_VERSION, SQL_OV_DDBC3_80, 0
|
|
353
|
+
)
|
|
354
|
+
if result_set_env < 0:
|
|
355
|
+
print(
|
|
356
|
+
"Error: ",
|
|
357
|
+
ddbc_bindings.DDBCSQLCheckError(SQL_HANDLE_ENV, env_handle, result_set_env),
|
|
358
|
+
)
|
|
359
|
+
raise RuntimeError(
|
|
360
|
+
f"Failed to set DDBC version attribute. Error code: {result_set_env}"
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
# Allocate connection handle
|
|
364
|
+
dbc_handle = alloc_handle(SQL_HANDLE_DBC, env_handle)
|
|
365
|
+
|
|
366
|
+
# Fetch the connection string from environment variables
|
|
367
|
+
connection_string = os.getenv("DB_CONNECTION_STRING")
|
|
368
|
+
|
|
369
|
+
if not connection_string:
|
|
370
|
+
raise EnvironmentError(
|
|
371
|
+
"Environment variable 'DB_CONNECTION_STRING' is not set or is empty."
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
print("Connecting!")
|
|
375
|
+
connect_to_db(dbc_handle, connection_string)
|
|
376
|
+
print("Connection successful!")
|
|
377
|
+
|
|
378
|
+
# Allocate connection statement handle
|
|
379
|
+
stmt_handle = alloc_handle(SQL_HANDLE_STMT, dbc_handle)
|
|
380
|
+
|
|
381
|
+
ParamInfo = ddbc_bindings.ParamInfo
|
|
382
|
+
"""
|
|
383
|
+
Table schema:
|
|
384
|
+
CREATE TABLE customers (
|
|
385
|
+
id INT IDENTITY(1,1) PRIMARY KEY,
|
|
386
|
+
name NVARCHAR(100),
|
|
387
|
+
email NVARCHAR(100)
|
|
388
|
+
);
|
|
389
|
+
"""
|
|
390
|
+
# Test DDBCSQLExecute for INSERT query
|
|
391
|
+
print("Test DDBCSQLExecute insert")
|
|
392
|
+
insert_sql_query = (
|
|
393
|
+
"INSERT INTO [Employees].[dbo].[EmployeeFullNames] "
|
|
394
|
+
"(FirstName, LastName, date_, time_, wchar_, bool_, tinyint_, bigint_, float_, double_) "
|
|
395
|
+
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"
|
|
396
|
+
)
|
|
397
|
+
params_insert = []
|
|
398
|
+
param_info_list_insert = []
|
|
399
|
+
add_string_param(params_insert, param_info_list_insert, "test")
|
|
400
|
+
add_string_param(params_insert, param_info_list_insert, "inner file")
|
|
401
|
+
add_date_param(params_insert, param_info_list_insert)
|
|
402
|
+
add_time_param(params_insert, param_info_list_insert)
|
|
403
|
+
# add_datetime_param(params_insert, param_info_list_insert, addNone=True) - Cannot insert an explicit value into a timestamp column. Use INSERT with a column list to exclude the timestamp column, or insert a DEFAULT into the timestamp column. Traceback (most recent call last):
|
|
404
|
+
add_wstring_param(params_insert, param_info_list_insert, "Wide str3")
|
|
405
|
+
add_bool_param(params_insert, param_info_list_insert, True)
|
|
406
|
+
add_tinyint_param(params_insert, param_info_list_insert, 127)
|
|
407
|
+
add_bigint_param(params_insert, param_info_list_insert, 123456789)
|
|
408
|
+
add_float_param(params_insert, param_info_list_insert, 12.34)
|
|
409
|
+
add_double_param(params_insert, param_info_list_insert, 12.34)
|
|
410
|
+
# add_numeric_param(params_insert, param_info_list_insert, decimal.Decimal('12'))
|
|
411
|
+
is_stmt_prepared_insert = [False]
|
|
412
|
+
result_insert = ddbc_sql_execute(
|
|
413
|
+
stmt_handle, insert_sql_query, params_insert, param_info_list_insert, is_stmt_prepared_insert, True
|
|
414
|
+
)
|
|
415
|
+
print("DDBCSQLExecute result:", result_insert)
|
|
416
|
+
|
|
417
|
+
# Test DDBCSQLExecute for SELECT query
|
|
418
|
+
print("Test DDBCSQLExecute select")
|
|
419
|
+
is_stmt_prepared_select = [False]
|
|
420
|
+
select_sql_query = (
|
|
421
|
+
"SELECT bool_, float_, wchar_, date_, time_, datetime_, wchar_, FirstName, LastName "
|
|
422
|
+
"FROM [Employees].[dbo].[EmployeeFullNames];"
|
|
423
|
+
)
|
|
424
|
+
params_select = []
|
|
425
|
+
param_info_list_select = []
|
|
426
|
+
result_select = ddbc_sql_execute(
|
|
427
|
+
stmt_handle, select_sql_query, params_select, param_info_list_select, is_stmt_prepared_select, False
|
|
428
|
+
)
|
|
429
|
+
print("DDBCSQLExecute result:", result_select)
|
|
430
|
+
|
|
431
|
+
print("Fetching Data for DDBCSQLExecute!")
|
|
432
|
+
column_names = describe_columns(stmt_handle)
|
|
433
|
+
print(column_names)
|
|
434
|
+
ret_fetch = 1
|
|
435
|
+
while ret_fetch != SQL_NO_DATA:
|
|
436
|
+
if column_names:
|
|
437
|
+
rows = fetch_data_all(stmt_handle)
|
|
438
|
+
for row in rows:
|
|
439
|
+
print(row)
|
|
440
|
+
else:
|
|
441
|
+
print("No columns to fetch data from.")
|
|
442
|
+
ret_fetch = ddbc_bindings.DDBCSQLMoreResults(stmt_handle)
|
|
443
|
+
|
|
444
|
+
# Free the statement handle
|
|
445
|
+
free_handle(SQL_HANDLE_STMT, stmt_handle)
|
|
446
|
+
# Disconnect from the data source
|
|
447
|
+
result_disconnect = ddbc_bindings.DDBCSQLDisconnect(dbc_handle)
|
|
448
|
+
if result_disconnect < 0:
|
|
449
|
+
print(
|
|
450
|
+
"Error: ",
|
|
451
|
+
ddbc_bindings.DDBCSQLCheckError(SQL_HANDLE_DBC, dbc_handle, result_disconnect),
|
|
452
|
+
)
|
|
453
|
+
raise RuntimeError(
|
|
454
|
+
f"Failed to disconnect from the data source. Error code: {result_disconnect}"
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
# Free the connection handle
|
|
458
|
+
free_handle(SQL_HANDLE_DBC, dbc_handle)
|
|
459
|
+
|
|
460
|
+
# Free the environment handle
|
|
461
|
+
free_handle(SQL_HANDLE_ENV, env_handle)
|
|
462
|
+
|
|
463
|
+
print("Done!")
|
mssql_python/type.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Microsoft Corporation.
|
|
3
|
+
Licensed under the MIT license.
|
|
4
|
+
This module contains type objects and constructors for the mssql_python package.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import datetime
|
|
8
|
+
import time
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# Type Objects
|
|
12
|
+
class STRING:
|
|
13
|
+
"""
|
|
14
|
+
This type object is used to describe columns in a database that are string-based (e.g. CHAR).
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self) -> None:
|
|
18
|
+
self.type = "STRING"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class BINARY:
|
|
22
|
+
"""
|
|
23
|
+
This type object is used to describe (long)
|
|
24
|
+
binary columns in a database (e.g. LONG, RAW, BLOBs).
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self) -> None:
|
|
28
|
+
self.type = "BINARY"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class NUMBER:
|
|
32
|
+
"""
|
|
33
|
+
This type object is used to describe numeric columns in a database.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self) -> None:
|
|
37
|
+
self.type = "NUMBER"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class DATETIME:
|
|
41
|
+
"""
|
|
42
|
+
This type object is used to describe date/time columns in a database.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self) -> None:
|
|
46
|
+
self.type = "DATETIME"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class ROWID:
|
|
50
|
+
"""
|
|
51
|
+
This type object is used to describe the “Row ID” column in a database.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(self) -> None:
|
|
55
|
+
self.type = "ROWID"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# Type Constructors
|
|
59
|
+
def Date(year: int, month: int, day: int) -> datetime.date:
|
|
60
|
+
"""
|
|
61
|
+
Generates a date object.
|
|
62
|
+
"""
|
|
63
|
+
return datetime.date(year, month, day)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def Time(hour: int, minute: int, second: int) -> datetime.time:
|
|
67
|
+
"""
|
|
68
|
+
Generates a time object.
|
|
69
|
+
"""
|
|
70
|
+
return datetime.time(hour, minute, second)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def Timestamp(
|
|
74
|
+
year: int, month: int, day: int, hour: int, minute: int, second: int, microsecond: int
|
|
75
|
+
) -> datetime.datetime:
|
|
76
|
+
"""
|
|
77
|
+
Generates a timestamp object.
|
|
78
|
+
"""
|
|
79
|
+
return datetime.datetime(year, month, day, hour, minute, second, microsecond)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def DateFromTicks(ticks: int) -> datetime.date:
|
|
83
|
+
"""
|
|
84
|
+
Generates a date object from ticks.
|
|
85
|
+
"""
|
|
86
|
+
return datetime.date.fromtimestamp(ticks)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def TimeFromTicks(ticks: int) -> datetime.time:
|
|
90
|
+
"""
|
|
91
|
+
Generates a time object from ticks.
|
|
92
|
+
"""
|
|
93
|
+
return datetime.time(*time.gmtime(ticks)[3:6])
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def TimestampFromTicks(ticks: int) -> datetime.datetime:
|
|
97
|
+
"""
|
|
98
|
+
Generates a timestamp object from ticks.
|
|
99
|
+
"""
|
|
100
|
+
return datetime.datetime.fromtimestamp(ticks, datetime.timezone.utc)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def Binary(string: str) -> bytes:
|
|
104
|
+
"""
|
|
105
|
+
Converts a string to bytes using UTF-8 encoding.
|
|
106
|
+
"""
|
|
107
|
+
return bytes(string, "utf-8")
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mssql-python
|
|
3
|
+
Version: 0.1.6
|
|
4
|
+
Summary: A Python library for interacting with Microsoft SQL Server
|
|
5
|
+
Home-page: https://github.com/microsoft/mssql-python
|
|
6
|
+
Author: Microsoft Corporation
|
|
7
|
+
Author-email: pysqldriver@microsoft.com
|
|
8
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Dynamic: author
|
|
13
|
+
Dynamic: author-email
|
|
14
|
+
Dynamic: classifier
|
|
15
|
+
Dynamic: description
|
|
16
|
+
Dynamic: description-content-type
|
|
17
|
+
Dynamic: home-page
|
|
18
|
+
Dynamic: license-file
|
|
19
|
+
Dynamic: requires-python
|
|
20
|
+
Dynamic: summary
|
|
21
|
+
|
|
22
|
+
# mssql-python
|
|
23
|
+
|
|
24
|
+
This is a new Python driver for Microsoft SQL Server currently in Alpha phase.
|
|
25
|
+
|
|
26
|
+
## Alpha Version Release
|
|
27
|
+
|
|
28
|
+
We are excited to announce the release of the alpha version of our driver. This marks a significant milestone in our development journey. While this version is still in the early stages, it includes the foundational code and initial logic that will drive future enhancements.
|
|
29
|
+
|
|
30
|
+
### What's Included:
|
|
31
|
+
|
|
32
|
+
- Basic functionality to get you started.
|
|
33
|
+
- Initial implementation of core features.
|
|
34
|
+
- Placeholder for future improvements and updates.
|
|
35
|
+
|
|
36
|
+
For more information, please visit the project link on Github: https://github.com/microsoft/mssql-python
|
|
37
|
+
|
|
38
|
+
### What's Next:
|
|
39
|
+
|
|
40
|
+
As we continue to develop and refine the driver, you can expect regular updates that will introduce new features, optimizations, and bug fixes. We encourage you to provide feedback and report any issues you encounter, as this will help us improve the driver for the final release.
|
|
41
|
+
|
|
42
|
+
### Stay Tuned:
|
|
43
|
+
|
|
44
|
+
We appreciate your interest and support in this project. Stay tuned for more updates and enhancements as we work towards delivering a robust and fully-featured driver in coming months.
|
|
45
|
+
Thank you for being a part of our journey!
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
mssql_python/__init__.py,sha256=jM9MZ7_cyxbakvERtnUEtxXpuFS0Gfl7f87ebEPFl4M,1015
|
|
2
|
+
mssql_python/connection.py,sha256=nAbk2SbwJV-fZrQOLdr0CkGnq3LHcXH7DioyVle604I,17409
|
|
3
|
+
mssql_python/constants.py,sha256=0whntqgBnrpijXyG5ugyuMfqOZ6SemGFlny-hS4czOE,3010
|
|
4
|
+
mssql_python/cursor.py,sha256=kpoEq25_OznkwotBey5lsPYg8DMsQAqqItxm4GXOZ9E,26162
|
|
5
|
+
mssql_python/db_connection.py,sha256=bVzIMSOirQFhRP0DwcQtIoXNpzRmabzeq155RsZ7HzQ,1806
|
|
6
|
+
mssql_python/ddbc_bindings.cp313-arm64.pyd,sha256=fzOhi1FbujIYtT7qAVgaX_zBzYVBIl6WD8gCmjf6drM,358912
|
|
7
|
+
mssql_python/ddbc_bindings.py,sha256=EKuIMFeR-fTxFLcrtAlsD1cy7KUs_aOIzoVppRtDCqA,1571
|
|
8
|
+
mssql_python/exceptions.py,sha256=QXtyaIflyCCeXT8l1ZlEMahRqN5RtMsJGZGfQ5bU4dc,26288
|
|
9
|
+
mssql_python/helpers.py,sha256=3U_OO4_Gug3xeuv9wOFQDJfXBe4Nnk9Lw0aZykfgBsk,3821
|
|
10
|
+
mssql_python/logging_config.py,sha256=d8HwLUlbMqHud568OS9d2ktqUNA54g-BZBD_A-mn40A,2186
|
|
11
|
+
mssql_python/mssql_python.pyi,sha256=v_62ciVgf4UMAgbd4xCmQzy2WPjomshscY76x3zIndg,4979
|
|
12
|
+
mssql_python/msvcp140.dll,sha256=Xxxd0xkWmQ2UGB4HvDr7Mr49tY8EO5-NZJ4kFYYvZr8,1387552
|
|
13
|
+
mssql_python/testing_ddbc_bindings.py,sha256=q45U9kAZVGnCRXZSR8z533eKV1YF1cc8BfLUGbhiZO4,15967
|
|
14
|
+
mssql_python/type.py,sha256=o2YKr71kM6TrwAaFVuW-TIWthsX29chb5Q7VYlLE6Ts,2444
|
|
15
|
+
mssql_python/libs/LICENSING,sha256=tKc4unjxUNI_4GLJFk3f4uhtqxSQKWfDllM4M3Xj2VI,1287
|
|
16
|
+
mssql_python/libs/arm64/msodbcdiag18.dll,sha256=f50K93e9YISsZCeQdejmRn9EPAW4XcFAFur3rGfsH3E,112168
|
|
17
|
+
mssql_python/libs/arm64/msodbcsql18.dll,sha256=o_fpN9ty56Zxzg3P26G4hfalF5UZSPUyxnPUMRgLCXY,3889208
|
|
18
|
+
mssql_python/libs/arm64/mssql-auth.dll,sha256=EfKOOxI_GU2qazXBhLzVmzOuXqNfyGdVyFzPO7ivxxI,12996128
|
|
19
|
+
mssql_python/libs/arm64/1033/msodbcsqlr18.rll,sha256=LSp2aRjl5RD_yHRUkQR0k1XWXSNGmn7tmvFD7axddxU,200240
|
|
20
|
+
mssql_python-0.1.6.dist-info/licenses/LICENSE,sha256=tMWsxLSz13xS8IQOwtLLNnrtInvjvKds2j5xmJAVsZA,2694
|
|
21
|
+
mssql_python-0.1.6.dist-info/METADATA,sha256=9H6fMZipAv7SPrqPrEyq2qSu8HznHKKRKtFuX3_pq-U,1837
|
|
22
|
+
mssql_python-0.1.6.dist-info/WHEEL,sha256=NSi-TvKb_JiwBrIuOvKq2JP6ukyjAAsPVdQr8ADvoR8,101
|
|
23
|
+
mssql_python-0.1.6.dist-info/top_level.txt,sha256=6fwQBaoJlf_jkq0h4o3PZnvrg4LqyryK7_d6hLHYtaE,13
|
|
24
|
+
mssql_python-0.1.6.dist-info/RECORD,,
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
All files licensed under the MIT license except the dynamic-link libraries (DLLs) in the mssql_python\libs\win folder,
|
|
3
|
+
which are subject to different licensing terms. Please review the licensing details for each component below.
|
|
4
|
+
|
|
5
|
+
A. MIT License
|
|
6
|
+
==================================================================
|
|
7
|
+
Copyright (c) Microsoft Corporation.
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
B. MICROSOFT LICENSES
|
|
29
|
+
==================================================================
|
|
30
|
+
The following dynamic-link libraries (DLLs) in the mssql_python\libs\win folder fall under different Microsoft licenses.
|
|
31
|
+
Below is a breakdown of these components by their respective licenses.
|
|
32
|
+
|
|
33
|
+
1. Microsoft ODBC Driver 18 End User License Agreement (EULA)
|
|
34
|
+
These components are part of the Microsoft ODBC Driver 18 for SQL Server and are governed by the Microsoft ODBC Driver 18 EULA.
|
|
35
|
+
|
|
36
|
+
- msodbcsqlr18.rll: Resource library containing localized error messages for the ODBC driver.
|
|
37
|
+
- msodbcdiag18.dll: Diagnostic library for handling error reporting and troubleshooting.
|
|
38
|
+
- msodbcsql18.dll: Core ODBC driver enabling connectivity between SQL Server and applications.
|
|
39
|
+
|
|
40
|
+
For official licensing terms, refer to: mssql_python\libs\win\MICROSOFT_ODBC_DRIVER_FOR_SQL_SERVER_LICENSE.txt
|
|
41
|
+
|
|
42
|
+
2. Microsoft Visual C++ Redistributable EULA
|
|
43
|
+
These components are part of the Microsoft Visual C++ Redistributable and are governed by the Microsoft Visual C++ Redistributable EULA.
|
|
44
|
+
|
|
45
|
+
- msvcp140.dll: Microsoft C++ Standard Library runtime, required for running C++ applications.
|
|
46
|
+
|
|
47
|
+
For redistribution and usage terms, refer to: mssql_python\libs\win\libs\win\MICROSOFT_VISUAL_STUDIO_LICENSE.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
mssql_python
|