iris-pex-embedded-python 3.4.1b1__py3-none-any.whl → 3.4.1b2__py3-none-any.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 iris-pex-embedded-python might be problematic. Click here for more details.

Files changed (74) hide show
  1. iop/_director.py +23 -23
  2. {iris_pex_embedded_python-3.4.1b1.dist-info → iris_pex_embedded_python-3.4.1b2.dist-info}/METADATA +1 -1
  3. iris_pex_embedded_python-3.4.1b2.dist-info/RECORD +79 -0
  4. iris_pex_embedded_python-3.4.1b2.dist-info/top_level.txt +2 -0
  5. intersystems_iris/_BufferReader.py +0 -10
  6. intersystems_iris/_BufferWriter.py +0 -32
  7. intersystems_iris/_ConnectionInformation.py +0 -56
  8. intersystems_iris/_ConnectionParameters.py +0 -18
  9. intersystems_iris/_Constant.py +0 -38
  10. intersystems_iris/_DBList.py +0 -506
  11. intersystems_iris/_Device.py +0 -69
  12. intersystems_iris/_GatewayContext.py +0 -25
  13. intersystems_iris/_GatewayException.py +0 -4
  14. intersystems_iris/_GatewayUtility.py +0 -74
  15. intersystems_iris/_IRIS.py +0 -1294
  16. intersystems_iris/_IRISConnection.py +0 -516
  17. intersystems_iris/_IRISEmbedded.py +0 -85
  18. intersystems_iris/_IRISGlobalNode.py +0 -273
  19. intersystems_iris/_IRISGlobalNodeView.py +0 -25
  20. intersystems_iris/_IRISIterator.py +0 -143
  21. intersystems_iris/_IRISList.py +0 -360
  22. intersystems_iris/_IRISNative.py +0 -208
  23. intersystems_iris/_IRISOREF.py +0 -9
  24. intersystems_iris/_IRISObject.py +0 -424
  25. intersystems_iris/_IRISReference.py +0 -133
  26. intersystems_iris/_InStream.py +0 -149
  27. intersystems_iris/_LegacyIterator.py +0 -135
  28. intersystems_iris/_ListItem.py +0 -15
  29. intersystems_iris/_ListReader.py +0 -84
  30. intersystems_iris/_ListWriter.py +0 -161
  31. intersystems_iris/_LogFileStream.py +0 -115
  32. intersystems_iris/_MessageHeader.py +0 -51
  33. intersystems_iris/_OutStream.py +0 -25
  34. intersystems_iris/_PrintStream.py +0 -65
  35. intersystems_iris/_PythonGateway.py +0 -850
  36. intersystems_iris/_SharedMemorySocket.py +0 -87
  37. intersystems_iris/__init__.py +0 -79
  38. intersystems_iris/__main__.py +0 -7
  39. intersystems_iris/dbapi/_Column.py +0 -56
  40. intersystems_iris/dbapi/_DBAPI.py +0 -2631
  41. intersystems_iris/dbapi/_Descriptor.py +0 -46
  42. intersystems_iris/dbapi/_IRISStream.py +0 -65
  43. intersystems_iris/dbapi/_Message.py +0 -158
  44. intersystems_iris/dbapi/_Parameter.py +0 -171
  45. intersystems_iris/dbapi/_ParameterCollection.py +0 -141
  46. intersystems_iris/dbapi/_ResultSetRow.py +0 -361
  47. intersystems_iris/dbapi/_SQLType.py +0 -32
  48. intersystems_iris/dbapi/__init__.py +0 -0
  49. intersystems_iris/dbapi/preparser/_PreParser.py +0 -1674
  50. intersystems_iris/dbapi/preparser/_Scanner.py +0 -391
  51. intersystems_iris/dbapi/preparser/_Token.py +0 -81
  52. intersystems_iris/dbapi/preparser/_TokenList.py +0 -251
  53. intersystems_iris/dbapi/preparser/__init__.py +0 -0
  54. intersystems_iris/pex/_BusinessHost.py +0 -101
  55. intersystems_iris/pex/_BusinessOperation.py +0 -105
  56. intersystems_iris/pex/_BusinessProcess.py +0 -214
  57. intersystems_iris/pex/_BusinessService.py +0 -95
  58. intersystems_iris/pex/_Common.py +0 -228
  59. intersystems_iris/pex/_Director.py +0 -24
  60. intersystems_iris/pex/_IRISBusinessOperation.py +0 -5
  61. intersystems_iris/pex/_IRISBusinessService.py +0 -18
  62. intersystems_iris/pex/_IRISInboundAdapter.py +0 -5
  63. intersystems_iris/pex/_IRISOutboundAdapter.py +0 -17
  64. intersystems_iris/pex/_InboundAdapter.py +0 -57
  65. intersystems_iris/pex/_Message.py +0 -6
  66. intersystems_iris/pex/_OutboundAdapter.py +0 -46
  67. intersystems_iris/pex/__init__.py +0 -25
  68. iris_pex_embedded_python-3.4.1b1.dist-info/RECORD +0 -144
  69. iris_pex_embedded_python-3.4.1b1.dist-info/top_level.txt +0 -4
  70. irisnative/_IRISNative.py +0 -9
  71. irisnative/__init__.py +0 -10
  72. {iris_pex_embedded_python-3.4.1b1.dist-info → iris_pex_embedded_python-3.4.1b2.dist-info}/WHEEL +0 -0
  73. {iris_pex_embedded_python-3.4.1b1.dist-info → iris_pex_embedded_python-3.4.1b2.dist-info}/entry_points.txt +0 -0
  74. {iris_pex_embedded_python-3.4.1b1.dist-info → iris_pex_embedded_python-3.4.1b2.dist-info}/licenses/LICENSE +0 -0
@@ -1,2631 +0,0 @@
1
- from typing import Union
2
- import struct
3
- import copy
4
- import enum
5
- import copy
6
- import uuid
7
- import decimal
8
- import intersystems_iris
9
- from collections import namedtuple
10
- from . import _Message
11
- import intersystems_iris.dbapi._Parameter
12
- import intersystems_iris.dbapi._Column
13
- from ._ResultSetRow import _ResultSetRow
14
- import intersystems_iris.dbapi._ParameterCollection
15
- import intersystems_iris.dbapi.preparser._PreParser
16
- from intersystems_iris.dbapi._Parameter import ParameterMode
17
- from intersystems_iris.dbapi.preparser._PreParser import StatementType, MultiValuesInsert
18
- from intersystems_iris._IRISConnection import Feature
19
- from intersystems_iris._InStream import _InStream
20
- from intersystems_iris.dbapi._IRISStream import (
21
- IRISStream,
22
- IRISBinaryStream,
23
- )
24
- from intersystems_iris._IRISOREF import _IRISOREF
25
- from ._SQLType import SQLType
26
-
27
- from .._IRISNative import connect as native_connect
28
- from .._IRISEmbedded import _IRISEmbedded
29
- from intersystems_iris._IRISConnection import _IRISConnection
30
-
31
-
32
- def NotImplementedErrorDBAPI(msg=None):
33
- import traceback
34
-
35
- if msg is None:
36
- traceback.print_stack()
37
- msg = "Coming soon to an IRIS DB API near you!"
38
- return NotImplementedError(msg)
39
-
40
-
41
- def embedded_connect(*args, hostname=None, port=None, namespace=None, username=None, password=None, **kw):
42
- connection = _IRISEmbedded()
43
- connection.connect(hostname, port, namespace, username, password, **kw)
44
- return connection
45
-
46
-
47
- def connect(*args, embedded=False, hostname=None, port=None, namespace=None, username=None, password=None, **kw) -> Union[_IRISConnection, _IRISEmbedded]:
48
- try:
49
- if not embedded:
50
- return native_connect(
51
- *args, hostname=hostname, port=port, namespace=namespace, username=username, password=password, **kw
52
- )
53
- else:
54
- return embedded_connect(
55
- *args, hostname=hostname, port=port, namespace=namespace, username=username, password=password, **kw
56
- )
57
- except Exception as e:
58
- raise OperationalError(e)
59
-
60
-
61
- class ServerReturnType(enum.IntEnum):
62
- NO_RETURN_VALUE = 0
63
- IGNORE_RETURN_VALUE = 1
64
- HAS_RETURN_VALUE = 2
65
- NULL_RETURN_VALUE = 3
66
-
67
-
68
- class CursorType(enum.IntEnum):
69
- DEFAULT = 0
70
- PREPARED = 1
71
- CALLABLE = 2
72
-
73
-
74
- # api globals, methods, classes, etc.
75
- # globals
76
- apilevel = "2.0"
77
- threadsafety = 0
78
- paramstyle = "qmark"
79
-
80
-
81
- class _BaseCursor:
82
- embedded = False
83
-
84
- def __init__(self, connection):
85
- self._connection = connection
86
-
87
- self.statement = None
88
- self._parsed_statement = None
89
-
90
- self._columns = None
91
- self._rowcount = -1
92
- self.arraysize = 1
93
-
94
- self._result_set = None
95
-
96
- self._rsrow = None
97
- self._rownumber = 0
98
- self._cursor_ptr = 0
99
- self._scroll_flag = False
100
-
101
- self.maxRowItemCount = 0
102
-
103
- self._is_batch_update = False
104
-
105
- self._exec_params = None
106
- self._params = intersystems_iris.dbapi._ParameterCollection._ParameterCollection()
107
- self._multiple_result_sets = False
108
- self._mrs_done = False
109
- self._has_return_value = 0
110
- self._cursor_type = 0
111
- self._parameter_list_mismatch_exception = False
112
- self._fetch_done = False
113
- self._output_parameter_list = None
114
-
115
- self._sqlcode = None
116
- self._lastrowid = None
117
-
118
- self._closed = False
119
-
120
- def __enter__(self):
121
- return self
122
-
123
- def __exit__(self, type, value, traceback):
124
- self._connection.rollback()
125
- self.close()
126
-
127
- def __iter__(self):
128
- if self._result_set == None:
129
- raise InterfaceError(
130
- "Either execute has not yet been called, or the previous call of execute did not return a result set"
131
- )
132
- return self
133
-
134
- def __next__(self):
135
- row = self.fetchone()
136
- if row:
137
- return row
138
- raise StopIteration
139
-
140
- # non-api methods and classes
141
- def isClosed(self):
142
- return self._closed
143
-
144
- def setinputsizes(self, sizes):
145
- raise NotImplementedErrorDBAPI()
146
-
147
- def setoutputsize(size, column=None):
148
- raise NotImplementedErrorDBAPI()
149
-
150
- @property
151
- def sqlcode(self):
152
- if self._closed:
153
- raise InterfaceError("Cursor is closed")
154
- return 0 if self._sqlcode is None else self._sqlcode
155
-
156
- def close(self):
157
- if self._closed:
158
- return
159
- self._columns = None
160
- self._rowcount = -1
161
- self.arraysize = 0
162
-
163
- self._connection = None
164
- self._in_message = None
165
- self._out_message = None
166
-
167
- self._result_set = None
168
-
169
- if self._rsrow != None:
170
- self._rsrow = None
171
- self._cursor_ptr = 0
172
- self._scroll_flag = False
173
- self._warehouse = []
174
- self._warehouse_dict = {}
175
- self._last_row_in_warehouse_dict = -1
176
- self._warehouse_dict_keys = []
177
-
178
- self._params = None
179
- self._parsed_statement = None
180
- self._cursor_type = CursorType.DEFAULT
181
- self._statementType = StatementType.UPDATE # default
182
- self._paramInfo = None
183
- self.statement = None
184
- self.statementFeatureOption = Feature.optionNone
185
- self._statement_id = None
186
- self._sqlcode = None
187
- self._current_wire = None
188
- self._result_set = []
189
- self._rs_index = -1
190
-
191
- self._parameter_sets = 0
192
- self._exec_params = None
193
- self._is_batch_update = False
194
- self._multiple_result_sets = False
195
- self._mrs_done = False
196
- self._fetch_done = False
197
- self._parameter_list_mismatch_exception = False
198
- if self._output_parameter_list != None:
199
- self._output_parameter_list._clear_list()
200
-
201
- self._closed = True
202
-
203
- def _cleanup(self):
204
- if self._rsrow != None:
205
- self._rsrow = None
206
- if self._params != None:
207
- self._params._clear()
208
- self._multiple_result_sets = False
209
- self._mrs_done = False
210
- self._fetch_done = False
211
- self._parameter_list_mismatch_exception = False
212
- self._parameter_sets = 0
213
- self._rowcount = -1
214
- self._exec_params = None
215
- self._statementType = StatementType.UPDATE
216
- self.statementFeatureOption = 0
217
- self.maxRowItemCount = 0
218
- self._is_batch_update = False
219
-
220
- def _is_alive(self):
221
- if self._closed:
222
- raise InterfaceError("Cursor is closed")
223
- if self._connection == None or self._connection.isClosed():
224
- raise InterfaceError("Connection not open")
225
-
226
- def direct_execute(self, operation, *params):
227
- self._is_alive()
228
-
229
- self.statement = operation
230
- if len(params) == 1 and (isinstance(params[0], tuple) or isinstance(params[0], list)):
231
- self.params = params[0]
232
- else:
233
- self.params = params
234
- self._params.set_input_params(self.params)
235
-
236
- self._cursor_type = CursorType.DEFAULT
237
- self._cleanup()
238
- self._preparse()
239
-
240
- self._execute()
241
- return self._rowcount
242
-
243
- def execute(self, operation, params=()):
244
- self._is_alive()
245
-
246
- self.statement = operation
247
- if params and not isinstance(params, list) and not isinstance(params, tuple):
248
- params = (params,)
249
- self.params = params if params is not None else ()
250
- self._params.set_input_params(self.params)
251
-
252
- self._cleanup()
253
- try:
254
- self._preparse()
255
- except MultiValuesInsert as ex:
256
- # convert to executemany
257
- params = params or ex.params
258
- params_count = int(len(params) / ex.rows)
259
- new_params = [params[i : i + params_count] for i in range(0, len(params), params_count)]
260
- return self.executemany(ex.query, new_params)
261
- except Exception:
262
- raise
263
-
264
- if self._statementType == StatementType.UPDATE:
265
- self._cursor_type = CursorType.PREPARED
266
- self._prepare()
267
- else:
268
- self._cursor_type = CursorType.DEFAULT
269
-
270
- self._execute()
271
- return self._rowcount
272
-
273
- def add_batch(self):
274
- self._is_alive()
275
-
276
- if self._params._array_bound:
277
- if len(self._params._params_list) > 0:
278
- cnt = 0
279
- first = True
280
- for i in range(self._params._user_parameters_size):
281
- i = i + 1
282
- cnt = len(self._params._get_user_param(i)._values)
283
- if cnt > 1:
284
- if first:
285
- self._parameter_sets = cnt
286
- first = False
287
- elif self._parameter_sets != cnt:
288
- raise Exception(
289
- "Unmatched columnwise parameter values: "
290
- + str(self._parameter_sets)
291
- + " rows expected, but found only "
292
- + str(cnt)
293
- + " in "
294
- + str(i)
295
- + " parameter!"
296
- )
297
- if self._parameter_sets > 1:
298
- return
299
- self._parameter_sets = self._parameter_sets + 1
300
-
301
- for param in self._params._params_list:
302
- if param.mode != ParameterMode.REPLACED_LITERAL:
303
- if len(param._values) != self._parameter_sets:
304
- if self._parameter_sets != 1:
305
- if len(param._values) + 1 == self._parameter_sets:
306
- param._values.append(param._values[len(param._values) - 1])
307
- continue
308
-
309
- def executemany(self, operation, seq_of_params):
310
- self._is_alive()
311
- self._rowcount = 0
312
-
313
- if not isinstance(seq_of_params, tuple) and not isinstance(seq_of_params, list):
314
- seq_of_params = tuple(seq_of_params)
315
-
316
- self.statement = operation
317
- self.params = copy.deepcopy(seq_of_params)
318
- self._params.set_input_params(self.params)
319
-
320
- self._cursor_type = CursorType.PREPARED
321
- self._cleanup()
322
- self._is_batch_update = True
323
-
324
- self._preparse()
325
- self._prepare()
326
-
327
- for row_num, param_row in enumerate(seq_of_params):
328
- self.add_batch()
329
-
330
- if self._parameter_sets == 0:
331
- for param in self._params._params_list:
332
- if param.value == "?":
333
- raise ValueError("Missing value")
334
- self._prepared_update_execute() # similar to executing a statement w/ literals
335
- return
336
-
337
- for param in self._params._params_list:
338
- mode = param.mode
339
- if mode == ParameterMode.INPUT_OUTPUT or mode == ParameterMode.OUTPUT:
340
- raise ValueError("INOUT/OUT parameters not permitted")
341
-
342
- self._prepared_update_execute()
343
-
344
- return self._rowcount
345
-
346
- def _process_sqlcode(self, sqlcode, message=None):
347
- self._sqlcode = sqlcode
348
- if sqlcode in [0, 100]:
349
- return
350
- if abs(sqlcode) in [108, 119, 121, 122]:
351
- raise IntegrityError(message)
352
- if abs(sqlcode) in [1, 12]:
353
- raise OperationalError(message)
354
- raise DatabaseError(message)
355
-
356
- def _preparse(self):
357
- csql = self._connection._pre_preparse_cache.get(self.statement)
358
- if csql is not None:
359
- self._has_return_value = csql._has_return_value
360
- self._params = copy.deepcopy(csql._params)
361
- self._params.set_input_params(self.params)
362
- self._parsed_statement = csql._parsed_statement
363
- self._statementType = csql._statementType
364
- self._paramInfo = csql._paramInfo
365
- return
366
-
367
- count = 0
368
- for i, item in enumerate(self.params):
369
- if isinstance(item, list) or isinstance(item, tuple):
370
- if not self._is_batch_update:
371
- raise TypeError("Unsupported argument type: " + str(type(item)))
372
- for ele in item:
373
- if not intersystems_iris._DBList._DBList._set_switcher.get(type(ele), None) and not issubclass(
374
- type(ele), enum.Enum
375
- ):
376
- raise TypeError("Unsupported argument type: " + str(type(ele)))
377
- elif intersystems_iris._DBList._DBList._set_switcher.get(type(item), None) is None:
378
- item = str(item)
379
- # raise TypeError("Unsupported argument type: " + str(type(item)))
380
- if i == 0:
381
- count = len(item) if isinstance(item, list) or isinstance(item, tuple) else 1
382
- else:
383
- curr_count = len(item) if isinstance(item, list) or isinstance(item, tuple) else 1
384
- if count != curr_count:
385
- raise Exception("Parameter count does not match")
386
-
387
- parser = intersystems_iris.dbapi.preparser._PreParser._PreParser(
388
- self._connection._connection_info._delimited_ids, embedded=self.embedded
389
- )
390
- try:
391
- pOut = parser.PreParse(self.statement, self._params)
392
- except MultiValuesInsert:
393
- raise
394
- except Exception as e:
395
- raise InterfaceError("Error parsing statement '" + self.statement + "':\n" + str(e))
396
-
397
- if len(self.params) > 0:
398
- item = self.params[0]
399
- if (isinstance(item, list) or isinstance(item, tuple)) and not self._is_batch_update:
400
- raise TypeError("Unsupported argument type: " + str(type(item)))
401
-
402
- self._parsed_statement = pOut.sResult
403
- self._statementType = pOut.p_eStmtType
404
- self._paramInfo = parser.m_ParamInfo
405
-
406
- if self._statementType == StatementType.CALL:
407
- self._has_return_value = ServerReturnType.NO_RETURN_VALUE
408
- elif self._statementType == StatementType.CALLWITHRESULT:
409
- self._has_return_value = ServerReturnType.HAS_RETURN_VALUE
410
-
411
- self._update_parameters()
412
- self._connection._add_pre_preparse_cache(self.statement, self)
413
-
414
- def _prepare(self):
415
- notDDL = bool(
416
- self._statementType != StatementType.DDL_ALTER_DROP and self._statementType != StatementType.DDL_OTHER
417
- )
418
-
419
- if notDDL and self._get_cached_info():
420
- return
421
- else:
422
- self._prepare_new()
423
-
424
- def _update_parameters(self):
425
- count = self._paramInfo._list_data[0] # self._paramInfo.count()
426
- if count == 0:
427
- return
428
-
429
- temp_list_data = self._paramInfo._list_data[1:]
430
- param_info_count = int(len(temp_list_data) / 2)
431
- if self._is_batch_update:
432
- unknown_count = replaced_count = 0
433
- for item in temp_list_data:
434
- if item == "c":
435
- replaced_count = replaced_count + 1
436
- elif item == "?":
437
- unknown_count = unknown_count + 1
438
-
439
- if len(self.params) > 0:
440
- item = self.params[0]
441
- param_count = len(item) if isinstance(item, list) or isinstance(item, tuple) else len(self.params)
442
- if param_count != unknown_count:
443
- raise Exception(f"Parameter mismatch: {param_count}/{unknown_count}")
444
- else:
445
- if self._cursor_type == CursorType.CALLABLE:
446
- i = 0
447
- for param in self._params._params_list:
448
- if param.mode == ParameterMode.RETURN_VALUE:
449
- continue
450
- else:
451
- if len(self._params._params_list) == len(self.params) and self.params[i] == None:
452
- param.mode = ParameterMode.OUTPUT
453
- if len(self._params._params_list) > len(self.params):
454
- if i >= len(self.params):
455
- param.mode = ParameterMode.OUTPUT
456
- else:
457
- if self.params[i] == None:
458
- param.mode = ParameterMode.OUTPUT
459
- i += 1
460
- return
461
-
462
- if len(temp_list_data) > 0:
463
- if count != param_info_count:
464
- raise Exception("Parameter mismatch")
465
-
466
- unknown_count = replaced_count = 0
467
- for item in temp_list_data:
468
- if item == "c":
469
- replaced_count = replaced_count + 1
470
- elif item == "?":
471
- unknown_count = unknown_count + 1
472
-
473
- if unknown_count != len(self.params):
474
- raise Exception(
475
- f"Incorrect number of parameters: {unknown_count}/{replaced_count}/{len(self.params)}"
476
- )
477
-
478
- def _is_not_default_or_replaced(self, param):
479
- mode = param.mode
480
- if (
481
- mode != ParameterMode.REPLACED_LITERAL
482
- and mode != ParameterMode.DEFAULT_PARAMETER
483
- and mode != ParameterMode.INPUT
484
- ):
485
- raise Exception("Parameters not allowed in Cursor class")
486
-
487
- def _validate_parameters(self):
488
- if self._parameter_list_mismatch_exception and not self._params._has_bound_by_param_name:
489
- raise Exception("Parameter list mismatch")
490
- for param in self._params._params_list:
491
- self._is_not_default_or_replaced(param)
492
-
493
- def _validate_prepared_parameters(self):
494
- if self._parameter_list_mismatch_exception and not self._params._has_bound_by_param_name:
495
- raise Exception("Parameter list mismatch")
496
- i = 0
497
- if (
498
- self._has_return_value == ServerReturnType.IGNORE_RETURN_VALUE
499
- or self._has_return_value == ServerReturnType.NULL_RETURN_VALUE
500
- ):
501
- i = 1
502
- for param in self._params._params_list:
503
- if i == 1:
504
- i = 0
505
- continue
506
- if param.mode == ParameterMode.UNKNOWN:
507
- if self._params._has_named_parameters():
508
- param.mode = ParameterMode.DEFAULT_PARAMETER
509
- else:
510
- raise Exception("Not all parameters bound/registered")
511
-
512
- def _execute(self):
513
- if self._closed:
514
- raise InterfaceError("Cursor is closed")
515
- if self._connection == None or self._connection.isClosed():
516
- raise InterfaceError("Connection not open")
517
-
518
- exec_switcher = {
519
- StatementType.QUERY: self._execute_query,
520
- StatementType.CALL: self._execute_update,
521
- StatementType.STMT_USE: self._execute_update,
522
- StatementType.UPDATE: self._execute_update,
523
- StatementType.DDL_OTHER: self._execute_update,
524
- StatementType.DDL_ALTER_DROP: self._execute_update,
525
- }
526
- exec_func = exec_switcher.get(self._statementType, None)
527
- if exec_func is None:
528
- raise NotImplementedErrorDBAPI(f"StatementType {self._statementType.name} not implemented")
529
- else:
530
- return exec_func()
531
-
532
- def _prepare_stored_procedure(self):
533
- if self._get_cached_info():
534
- self._prepared_stored_procedure_execute()
535
- pass
536
-
537
- def _execute_stored_procedure(self):
538
- if self._cursor_type == CursorType.DEFAULT:
539
- if self._get_cached_info():
540
- # found in client side cache - send SQ message
541
- self._stored_procedure_update()
542
- else:
543
- # not found in client side cache - send DS message
544
- self._send_direct_stored_procedure_request()
545
- else:
546
- self._stored_procedure_update()
547
-
548
- def _execute_query(self):
549
- self._fetch_done = False
550
- if self._cursor_type == CursorType.DEFAULT:
551
- if self._statementType not in [StatementType.QUERY, StatementType.CALL, StatementType.CALLWITHRESULT]:
552
- raise Exception("Not a query")
553
-
554
- if self._exec_params != None:
555
- self._prepare_stored_procedure()
556
- self._bind_exec_params()
557
- if self._statementType in [StatementType.DIRECT_CALL_UPDATE, StatementType.PREPARED_CALL_UPDATE]:
558
- raise Exception("Not a query")
559
- elif self._statementType in [StatementType.DIRECT_CALL_QUERY, StatementType.PREPARED_CALL_QUERY]:
560
- self._stored_procedure_query()
561
- return
562
-
563
- self._validate_parameters()
564
-
565
- if self._statementType in [StatementType.CALL, StatementType.CALLWITHRESULT]:
566
- self._execute_stored_procedure()
567
- if not (self._statementType in [StatementType.DIRECT_CALL_QUERY, StatementType.PREPARED_CALL_QUERY]):
568
- raise Exception("Not a query")
569
- return
570
-
571
- if self._get_cached_info():
572
- # found in client side cache - send PQ message
573
- self._prepared_query_execute()
574
- else:
575
- # not found in client side cache - send DQ message
576
- self._send_direct_query_request()
577
- else:
578
- if (
579
- self._statementType != StatementType.QUERY
580
- and self._statementType != StatementType.PREPARED_CALL_QUERY
581
- and self._statementType != StatementType.DIRECT_CALL_QUERY
582
- ):
583
- raise Exception("Not a query")
584
-
585
- if self._exec_params != None:
586
- self._bind_exec_params()
587
- self._validate_prepared_parameters()
588
-
589
- if self.statementFeatureOption & Feature.optionFastSelect == Feature.optionFastSelect:
590
- self._rsrow = _ResultSetRow(self._connection, self._columns, self.maxRowItemCount)
591
- else:
592
- self._rsrow = _ResultSetRow(self._connection, self._columns, 0)
593
-
594
- if self._cursor_type == CursorType.CALLABLE or self._statementType == StatementType.PREPARED_CALL_QUERY:
595
- self._stored_procedure_query()
596
- return
597
- self._prepared_query_execute()
598
-
599
- def _execute_update(self):
600
- if self._cursor_type == CursorType.DEFAULT:
601
- if self._statementType == StatementType.QUERY:
602
- raise Exception("Not an update")
603
-
604
- if self._exec_params != None:
605
- self._prepare_stored_procedure()
606
- self._bind_exec_params()
607
- if self._statementType in [StatementType.DIRECT_CALL_UPDATE, StatementType.PREPARED_CALL_UPDATE]:
608
- self._stored_procedure_query()
609
- elif self._statementType in [StatementType.DIRECT_CALL_QUERY, StatementType.PREPARED_CALL_QUERY]:
610
- raise Exception("Not an update")
611
- return
612
-
613
- self._validate_parameters()
614
-
615
- if self._statementType == StatementType.CALL:
616
- self._execute_stored_procedure()
617
- if self._statementType == StatementType.DIRECT_CALL_QUERY:
618
- raise Exception("Not an update")
619
- return
620
-
621
- notDDL = bool(
622
- self._statementType != StatementType.DDL_ALTER_DROP and self._statementType != StatementType.DDL_OTHER
623
- )
624
-
625
- if notDDL and self._get_cached_info():
626
- # found in client side cache - send PU message
627
- self._prepared_update_execute()
628
- else:
629
- # not found in client side cache - send DU message
630
- self._send_direct_update_request()
631
- else:
632
- if self._statementType == StatementType.QUERY or self._statementType == StatementType.PREPARED_CALL_QUERY:
633
- raise Exception("Not an update")
634
-
635
- if self._exec_params != None:
636
- self._bind_exec_params()
637
- self._validate_prepared_parameters()
638
-
639
- if (
640
- self._cursor_type == CursorType.CALLABLE
641
- or self._statementType == StatementType.PREPARED_CALL_UPDATE
642
- or self._statementType == StatementType.DIRECT_CALL_UPDATE
643
- ):
644
- self._stored_procedure_update()
645
- return
646
-
647
- self._prepared_update_execute()
648
-
649
- def _query404(self):
650
- with self._connection._lock:
651
- self._validate_parameters()
652
- self._send_direct_query_request()
653
-
654
- def _update404(self):
655
- with self._connection._lock:
656
- # self._reset_cached_info()
657
- self._validate_parameters()
658
- # self._prepare()
659
- # self._validate_prepared_parameters()
660
- # self._prepared_update_execute()
661
- self._send_direct_update_request()
662
-
663
- # api properties and methods
664
- @property
665
- def description(self):
666
- if self._statementType is StatementType.UPDATE:
667
- return None
668
-
669
- if self._columns is None:
670
- return None
671
-
672
- Column = namedtuple(
673
- "Column",
674
- [
675
- "name",
676
- "type_code",
677
- "display_size",
678
- "internal_size",
679
- "precision",
680
- "scale",
681
- "null_ok",
682
- ],
683
- )
684
-
685
- sequence = []
686
- for column in self._columns:
687
- sequence.append(
688
- Column(
689
- column.name,
690
- column.type,
691
- None,
692
- None,
693
- column.precision,
694
- column.scale,
695
- column.nullable,
696
- )
697
- )
698
- return tuple(sequence)
699
-
700
- # currently doesn't work for queries
701
- @property
702
- def rowcount(self):
703
- return self._rowcount
704
-
705
-
706
- # Cursor class
707
- class Cursor(_BaseCursor):
708
- def __init__(self, connection):
709
- super().__init__(connection)
710
-
711
- self._columns = None
712
- self._rowcount = -1
713
- self.arraysize = 1
714
-
715
- self._in_message = intersystems_iris._InStream._InStream(connection)
716
- self._out_message = intersystems_iris._OutStream._OutStream(connection)
717
- self.statementFeatureOption = 0
718
-
719
- self._result_set = None
720
-
721
- self._rsrow = None
722
- self._rownumber = 0
723
- self._cursor_ptr = 0
724
- self._scroll_flag = False
725
- self._warehouse = list()
726
-
727
- self._warehouse_dict = dict()
728
- self._last_row_in_warehouse_dict = -1
729
- self._warehouse_dict_keys = list()
730
-
731
- self.maxRowItemCount = 0
732
-
733
- self._parameter_sets = 0
734
- self._exec_params = None
735
- self._params = intersystems_iris.dbapi._ParameterCollection._ParameterCollection()
736
- self._is_batch_update = False
737
-
738
- self._exec_params = None
739
- self._multiple_result_sets = False
740
- self._mrs_done = False
741
- self._has_return_value = 0
742
- self._cursor_type = 0
743
- self._parameter_list_mismatch_exception = False
744
- self._fetch_done = False
745
- self._output_parameter_list = None
746
-
747
- self._lastrowid = None
748
-
749
- self._closed = False
750
-
751
- def _process_sqlcode(self, sqlcode, message=None):
752
- if sqlcode in [0, 100]:
753
- return
754
- super()._process_sqlcode(sqlcode, self._get_error_info(sqlcode))
755
-
756
- def _get_cached_info(self):
757
- if not self._connection._preparedCache or not hasattr(self._connection._preparedCache, "__iter__"):
758
- return False
759
- if self._parsed_statement in self._connection._preparedCache:
760
- self._prepare_cached(self._connection._preparedCache[self._parsed_statement])
761
- return True
762
- else:
763
- return False
764
-
765
- def _reset_cached_info(self):
766
- if not self._connection._preparedCache or not hasattr(self._connection._preparedCache, "__iter__"):
767
- return
768
- if self._parsed_statement in self._connection._preparedCache:
769
- del self._connection._preparedCache[self._parsed_statement]
770
-
771
- def _prepare_cached(self, cached_statement):
772
- self._statement_id = cached_statement.statement_id
773
-
774
- if self._statementType == StatementType.CALL or self._statementType == StatementType.CALLWITHRESULT:
775
- if len(self._params._params_list) != len(cached_statement._params._params_list):
776
- if (
777
- self._statementType == StatementType.CALL
778
- and self._has_return_value == 0
779
- and cached_statement._has_return_value == 1
780
- and len(self._params._params_list) + 1 == len(cached_statement._params._params_list)
781
- ):
782
- self._params._params_list.insert(
783
- 0, intersystems_iris.dbapi._Parameter._Parameter(None, ParameterMode.OUTPUT, "c")
784
- )
785
- else:
786
- if len(self._params._params_list) == 0 or len(self._params._params_list) == 1:
787
- self._params._clear()
788
- else:
789
- return False
790
-
791
- if cached_statement._statementType == StatementType.QUERY:
792
- self._statementType = StatementType.PREPARED_CALL_QUERY
793
- else:
794
- if cached_statement._statementType == StatementType.UPDATE:
795
- self._statementType = StatementType.PREPARED_CALL_UPDATE
796
- else:
797
- self._statementType = cached_statement._statementType
798
-
799
- self._has_return_value = cached_statement._has_return_value
800
- self._multiple_result_sets = cached_statement.multiple_result_sets
801
- self._mrs_done = False
802
-
803
- if not self._multiple_result_sets and (
804
- self._statementType
805
- in [StatementType.QUERY, StatementType.PREPARED_CALL_QUERY, StatementType.DIRECT_CALL_QUERY]
806
- ):
807
- self._columns = []
808
- for column in cached_statement.columns:
809
- self._columns.append(column.Clone())
810
-
811
- if self.statementFeatureOption & Feature.optionFastSelect == Feature.optionFastSelect:
812
- self._rsrow = _ResultSetRow(self._connection, self._columns, cached_statement.maxRowItemCount)
813
- else:
814
- self._rsrow = _ResultSetRow(self._connection, self._columns, 0)
815
-
816
- else:
817
- if self._statementType == StatementType.QUERY:
818
- self._columns = []
819
- for column in cached_statement.columns:
820
- self._columns.append(column.Clone())
821
-
822
- if self.statementFeatureOption & Feature.optionFastSelect == Feature.optionFastSelect:
823
- self._rsrow = _ResultSetRow(self._connection, self._columns, cached_statement.maxRowItemCount)
824
- else:
825
- self._rsrow = _ResultSetRow(self._connection, self._columns, 0)
826
-
827
- if hasattr(cached_statement, "statementFeatureOption"):
828
- self.statementFeatureOption = cached_statement.statementFeatureOption
829
- if hasattr(cached_statement, "maxRowItemCount"):
830
- self.maxRowItemCount = cached_statement.maxRowItemCount
831
- if hasattr(cached_statement, "_params"):
832
- self._params._update_param_info(cached_statement._params)
833
-
834
- def _prepare_new(self):
835
- # send PP message
836
- with self._connection._lock:
837
- # message header
838
- self._statement_id = self._connection._get_new_statement_id()
839
- self._out_message.wire._write_header(_Message.PREPARE)
840
- intersystems_iris._MessageHeader._MessageHeader._set_statement_id(
841
- self._out_message.wire.buffer, self._statement_id
842
- )
843
-
844
- # message body
845
- self._out_message.wire._set(1) # number of statement chunks
846
- self._out_message.wire._set(self._parsed_statement) # statement itself
847
- self._out_message.wire._set_raw_bytes(self._paramInfo.getBuffer()) # paramInfo (from _PreParser)
848
-
849
- # send message
850
- sequence_number = self._connection._get_new_sequence_number()
851
- self._out_message._send(sequence_number)
852
-
853
- # retrieve response
854
- self._in_message._read_message_sql(sequence_number, self._statement_id, 0, [0])
855
- sqlcode = self._in_message.wire.header._get_function_code()
856
- if sqlcode not in [0, 100]:
857
- raise DatabaseError(self._get_error_info(sqlcode))
858
-
859
- # process metadata
860
- try:
861
- if self._connection._isFastOption():
862
- self._check_statement_feature(self._in_message.wire)
863
- else:
864
- self.statementFeatureOption = Feature.optionNone
865
-
866
- if self._statementType == StatementType.QUERY:
867
- self._get_column_info(self._in_message.wire)
868
- else:
869
- self._columns = None
870
-
871
- addToCache = self._get_parameter_info(self._in_message.wire)
872
- if addToCache:
873
- self._cache_prepared_statement()
874
- except IndexError:
875
- raise DatabaseError("Server response message terminated prematurely")
876
- except TypeError:
877
- raise DatabaseError("Unexpected server response message format")
878
-
879
- def _get_error_info(self, sqlcode):
880
- with self._connection._lock:
881
- self._out_message.wire._write_header(_Message.GET_SERVER_ERROR)
882
- self._out_message.wire._set(sqlcode)
883
-
884
- sequence_number = self._connection._get_new_sequence_number()
885
- self._out_message._send(sequence_number)
886
-
887
- self._in_message._read_message_sql(sequence_number)
888
- return self._in_message.wire._get()
889
-
890
- def _check_statement_feature(self, wire):
891
- self.statementFeatureOption = wire._get()
892
- if (
893
- self.statementFeatureOption == Feature.optionFastSelect
894
- or self.statementFeatureOption == Feature.optionFastInsert
895
- ):
896
- self.maxRowItemCount = wire._get()
897
- else:
898
- self.maxRowItemCount = 0
899
-
900
- def _get_column_info(self, wire):
901
- self._columns = []
902
- count = wire._get()
903
- for i in range(count):
904
- name = wire._get()
905
- type = wire._get()
906
- precision = wire._get()
907
- scale = wire._get()
908
- nullable = wire._get()
909
- label = wire._get()
910
- tableName = wire._get()
911
- schema = wire._get()
912
- catalog = wire._get()
913
- if catalog == 0:
914
- catalog = None
915
- additionalData = wire._get().encode()
916
- slotPosition = (
917
- wire._get()
918
- if self.statementFeatureOption & Feature.optionFastSelect == Feature.optionFastSelect
919
- else i + 1
920
- )
921
- self._columns.append(
922
- intersystems_iris.dbapi._Column._Column(
923
- name,
924
- type,
925
- precision,
926
- scale,
927
- nullable,
928
- label,
929
- tableName,
930
- schema,
931
- catalog,
932
- additionalData,
933
- slotPosition,
934
- )
935
- )
936
-
937
- def _get_parameter_info(self, wire):
938
- count = wire._get()
939
- if count != len(self._params._params_list):
940
- raise Exception("Invalid number of parameters")
941
- self._read_parameter_data(wire, count, False)
942
-
943
- addToCache = bool(wire._get())
944
- return addToCache
945
-
946
- def _read_parameter_data(self, wire, count, is_stored_procedure):
947
- if count != len(self._params._params_list):
948
- raise Exception("Invalid number of parameters")
949
- with self._connection._lock:
950
- r = 0
951
- user_param_count = 0
952
- if self._has_return_value == ServerReturnType.NULL_RETURN_VALUE:
953
- r += 1
954
- if self._has_return_value == ServerReturnType.IGNORE_RETURN_VALUE:
955
- user_param_count -= 1
956
-
957
- for i in range(count):
958
- param = self._params._params_list[i + r]
959
- param.type = wire._get()
960
- param.precision = wire._get()
961
- param.scale = wire._get()
962
- param.nullable = wire._get()
963
-
964
- if self.statementFeatureOption & Feature.optionFastInsert == Feature.optionFastInsert:
965
- param.slotPosition = wire._get()
966
- self.rowOfDefaultValues = wire._get() # needs to be processed
967
- else:
968
- param.slotPosition = i + r
969
-
970
- if is_stored_procedure:
971
- param.name = wire._get()
972
- wire._get()
973
-
974
- if is_stored_procedure:
975
- self._params._update_names()
976
-
977
- def _execute_update(self):
978
- super()._execute_update()
979
-
980
- if self._parameter_sets == 0 and not self._multiple_result_sets:
981
- self._rowcount = self._in_message.wire._get()
982
-
983
- class prepared_statement(intersystems_iris._IRISConnection.CachedSQL):
984
- def __init__(self, cursor):
985
- if not isinstance(cursor, Cursor):
986
- raise TypeError("cursor must be a Cursor")
987
-
988
- super().__init__(cursor)
989
- self.statement = cursor._parsed_statement
990
- self.statement_id = cursor._statement_id
991
-
992
- if cursor._columns != None:
993
- self.columns = []
994
- for column in cursor._columns:
995
- self.columns.append(column.Clone())
996
-
997
- if hasattr(cursor, "statementFeatureOption"):
998
- self.statementFeatureOption = cursor.statementFeatureOption
999
- if hasattr(cursor, "maxRowItemCount"):
1000
- self.maxRowItemCount = cursor.maxRowItemCount
1001
-
1002
- self.multiple_result_sets = cursor._multiple_result_sets
1003
-
1004
- def _cache_prepared_statement(self):
1005
- self._connection._cache_prepared_statement(self.prepared_statement(self))
1006
-
1007
- def _write_parameters(self):
1008
- sets = self._parameter_sets or 1
1009
-
1010
- self._out_message.wire._set(sets) # nParamSets
1011
- self._out_message.wire._set(len(self._params._params_list)) # nParams
1012
- for i in range(sets):
1013
- param_index = 0
1014
- param_counter = i
1015
- for param in self._params._params_list:
1016
- mode = param.mode
1017
- if mode == ParameterMode.REPLACED_LITERAL:
1018
- self._out_message.wire._set_parameter(param)
1019
- elif not mode == ParameterMode.INPUT:
1020
- temp_param = intersystems_iris.dbapi._Parameter._Parameter(param._values[i])
1021
- self._out_message.wire._set_parameter(temp_param)
1022
- elif len(self.params) > 0:
1023
- item = self.params[param_counter]
1024
- if isinstance(item, list) or isinstance(item, tuple):
1025
- value = item[param_index]
1026
- param_index = param_index + 1
1027
- else:
1028
- value = item
1029
- param_counter = param_counter + 1
1030
- temp_param = intersystems_iris.dbapi._Parameter._Parameter(value)
1031
- self._out_message.wire._set_parameter(temp_param)
1032
- else:
1033
- raise Exception("Missing value")
1034
-
1035
- def _prepared_query_execute(self):
1036
- # send PQ message
1037
- with self._connection._lock:
1038
- # message header
1039
- self._out_message.wire._write_header(_Message.PREPARED_QUERY_EXECUTE)
1040
- intersystems_iris._MessageHeader._MessageHeader._set_statement_id(
1041
- self._out_message.wire.buffer, self._statement_id
1042
- )
1043
-
1044
- # message body
1045
- self._write_parameters()
1046
- self._out_message.wire._set(0) # query timeout
1047
- self._out_message.wire._set(0) # maxRows (0 = all rows)
1048
-
1049
- # send
1050
- sequence_number = self._connection._get_new_sequence_number()
1051
- self._out_message._send(sequence_number)
1052
-
1053
- # retrieve response
1054
- self._in_message._read_message_sql(sequence_number, self._statement_id, _InStream.FETCH_DATA, [404, 100])
1055
- self._sqlcode = self._in_message.wire.header._get_function_code()
1056
- self._handle_error_504(self._sqlcode)
1057
- if self._sqlcode == 404:
1058
- return
1059
- self._process_sqlcode(self._sqlcode)
1060
-
1061
- self._current_wire = self._in_message.wire
1062
- self._result_set = [self._current_wire]
1063
- self._rs_index = 0
1064
-
1065
- self._rowcount = -1
1066
-
1067
- def _send_direct_stored_procedure_request(self):
1068
- # self._has_return_value = ServerReturnType.NO_RETURN_VALUE
1069
- # send DS message
1070
- with self._connection._lock:
1071
- # message header
1072
- self._statement_id = self._connection._get_new_statement_id()
1073
- self._out_message.wire._write_header(_Message.DIRECT_STORED_PROCEDURE)
1074
- intersystems_iris._MessageHeader._MessageHeader._set_statement_id(
1075
- self._out_message.wire.buffer, self._statement_id
1076
- )
1077
-
1078
- # message body
1079
- self._out_message.wire._set(self._parsed_statement) # statement itself
1080
- self._out_message.wire._set(0) # resultSetType != ResultSet.TYPE_SCROLL_INSENSITIVE
1081
- self._out_message.wire._set(0) # query timeout
1082
- self._out_message.wire._set(0) # maxRows (0 = all rows)
1083
- self._write_stored_procedure_parameters()
1084
-
1085
- # send
1086
- sequence_number = self._connection._get_new_sequence_number()
1087
- self._out_message._send(sequence_number)
1088
-
1089
- try:
1090
- # retrieve metadata
1091
- self._in_message._read_message_sql(sequence_number, self._statement_id, 0, [100])
1092
- sqlcode = self._in_message.wire.header._get_function_code()
1093
- if sqlcode not in [0, 100]:
1094
- raise DatabaseError(self._get_error_info(sqlcode))
1095
-
1096
- self._process_stored_procedure_metadata(self._in_message.wire, True)
1097
- if self._multiple_result_sets:
1098
- # todo
1099
- return
1100
-
1101
- self._cache_prepared_statement()
1102
-
1103
- if self._statementType in [
1104
- StatementType.UPDATE,
1105
- StatementType.DIRECT_CALL_UPDATE,
1106
- StatementType.PREPARED_CALL_UPDATE,
1107
- ]:
1108
- return False
1109
-
1110
- except IndexError:
1111
- raise DatabaseError("Server response message terminated prematurely")
1112
- except TypeError:
1113
- raise DatabaseError("Unexpected server response message format")
1114
-
1115
- def _prepared_stored_procedure_execute(self):
1116
- # send SU message
1117
- with self._connection._lock:
1118
- # message header
1119
- self._out_message.wire._write_header(_Message.PREPARED_UPDATE_EXECUTE)
1120
- intersystems_iris._MessageHeader._MessageHeader._set_statement_id(
1121
- self._out_message.wire.buffer, self._statement_id
1122
- )
1123
-
1124
- def _send_direct_query_request(self):
1125
- # send DQ message
1126
- with self._connection._lock:
1127
- # message header
1128
- self._statement_id = self._connection._get_new_statement_id()
1129
- self._out_message.wire._write_header(_Message.DIRECT_QUERY)
1130
- intersystems_iris._MessageHeader._MessageHeader._set_statement_id(
1131
- self._out_message.wire.buffer, self._statement_id
1132
- )
1133
-
1134
- # message body
1135
- self._out_message.wire._set(1) # number of statement chunks
1136
- self._out_message.wire._set(self._parsed_statement) # statement itself
1137
- self._out_message.wire._set_raw_bytes(self._paramInfo.getBuffer()) # paramInfo (from _PreParser)
1138
- self._write_parameters()
1139
- self._out_message.wire._set(0) # query timeout
1140
- self._out_message.wire._set(0) # maxRows (0 = all rows)
1141
-
1142
- # send
1143
- sequence_number = self._connection._get_new_sequence_number()
1144
- self._out_message._send(sequence_number)
1145
-
1146
- try:
1147
- # retrieve metadata
1148
- self._in_message._read_message_sql(sequence_number, self._statement_id, 0, [100])
1149
- sqlcode = self._in_message.wire.header._get_function_code()
1150
- self._process_sqlcode(sqlcode)
1151
-
1152
- if self._connection._isFastOption():
1153
- self._check_statement_feature(self._in_message.wire)
1154
- else:
1155
- self.statementFeatureOption = Feature.optionNone
1156
- self._get_column_info(self._in_message.wire)
1157
- self._get_parameter_info(self._in_message.wire)
1158
- self._cache_prepared_statement()
1159
-
1160
- # retrieve data
1161
- self._in_message._read_message_sql(sequence_number, self._statement_id, _InStream.FETCH_DATA, [100])
1162
- self._sqlcode = self._in_message.wire.header._get_function_code()
1163
- if self._sqlcode not in [0, 100]:
1164
- raise DatabaseError(self._get_error_info(self._sqlcode))
1165
-
1166
- except IndexError:
1167
- raise DatabaseError("Server response message terminated prematurely")
1168
- except TypeError:
1169
- raise DatabaseError("Unexpected server response message format")
1170
-
1171
- self._current_wire = self._in_message.wire
1172
- self._result_set = [self._current_wire]
1173
- self._rs_index = 0
1174
-
1175
- self._rowcount = -1
1176
- if self.statementFeatureOption & Feature.optionFastSelect == Feature.optionFastSelect:
1177
- self._rsrow = _ResultSetRow(self._connection, self._columns, self.maxRowItemCount)
1178
- else:
1179
- self._rsrow = _ResultSetRow(self._connection, self._columns, 0)
1180
-
1181
- def _update_streams(self):
1182
- sets = self._parameter_sets or 1
1183
- self.params = list(self.params).copy()
1184
- param_types = [param.type for param in self._params._params_list]
1185
- if not self.params:
1186
- return
1187
-
1188
- for i in range(sets):
1189
- params = self._params.collect(i)
1190
- for pi, param in enumerate(params):
1191
- if param_types[pi] in (SQLType.LONGVARBINARY, SQLType.LONGVARCHAR) and param is not None:
1192
- stream_oref = self._send_stream(param_types[pi], param)
1193
- if isinstance(self.params[i], tuple):
1194
- self.params[i] = list(self.params[i])
1195
- if isinstance(self.params[i], list):
1196
- self.params[i][pi] = stream_oref
1197
- else:
1198
- self.params[pi] = stream_oref
1199
-
1200
- def _send_stream(self, param_type, value):
1201
- if isinstance(value, _IRISOREF):
1202
- return value
1203
- if not isinstance(value, str) and not isinstance(value, bytes):
1204
- raise Exception(f"Invalid value type for stream, got {type(value).__name__}, expected str or bytes")
1205
- stream_oref = None
1206
- offset = 0
1207
- full_size = len(value)
1208
- if full_size < 3 * 1024 * 1024:
1209
- return value
1210
- with self._connection._lock:
1211
- while True:
1212
- size = full_size
1213
- if size == 0:
1214
- break
1215
- size = 4096 if size > 4096 else size
1216
- chunk = value[offset : offset + size]
1217
- if not isinstance(chunk, bytes):
1218
- chunk = bytes(chunk, "utf-8")
1219
- offset += size
1220
- full_size -= size
1221
-
1222
- # message header
1223
- code = (
1224
- _Message.STORE_BINARY_STREAM
1225
- if param_type == SQLType.LONGVARBINARY
1226
- else _Message.STORE_CHARACTER_STREAM
1227
- )
1228
- self._out_message.wire._write_header(code)
1229
- intersystems_iris._MessageHeader._MessageHeader._set_statement_id(
1230
- self._out_message.wire.buffer, self._statement_id
1231
- )
1232
- # message body
1233
- self._out_message.wire._set(stream_oref or "0")
1234
- self._out_message.wire._set_raw_bytes(struct.pack("<i", size))
1235
- self._out_message.wire._set_raw_bytes(chunk)
1236
-
1237
- # send
1238
- sequence_number = self._connection._get_new_sequence_number()
1239
- self._out_message._send(sequence_number)
1240
-
1241
- self._in_message._read_message_sql(sequence_number, self._statement_id, 0)
1242
- stream_oref = self._sqlcode = self._in_message.wire._get()
1243
-
1244
- return _IRISOREF(stream_oref)
1245
-
1246
- def _prepared_update_execute(self):
1247
- self._update_streams()
1248
-
1249
- # send PU message
1250
- with self._connection._lock:
1251
- # message header
1252
- self._out_message.wire._write_header(_Message.PREPARED_UPDATE_EXECUTE)
1253
- intersystems_iris._MessageHeader._MessageHeader._set_statement_id(
1254
- self._out_message.wire.buffer, self._statement_id
1255
- )
1256
-
1257
- # message body
1258
- self._lastrowid = None
1259
- self._out_message.wire._set(-1) # autoGeneratedKeyColumn
1260
- self._out_message.wire._set(0) # statement timeout always 0 for non-queries
1261
- self._write_parameters()
1262
-
1263
- # send
1264
- sequence_number = self._connection._get_new_sequence_number()
1265
- self._out_message._send(sequence_number)
1266
-
1267
- # retrieve response
1268
- self._in_message._read_message_sql(sequence_number, self._statement_id, 0, [404, 100])
1269
- self._sqlcode = self._in_message.wire.header._get_function_code()
1270
- if self._sqlcode == 404:
1271
- self._update404()
1272
- return
1273
- self._process_sqlcode(self._sqlcode)
1274
-
1275
- def _send_direct_update_request(self):
1276
- # send DU message
1277
- with self._connection._lock:
1278
- self._statement_id = self._connection._get_new_statement_id()
1279
- # message header
1280
- self._out_message.wire._write_header(_Message.DIRECT_UPDATE)
1281
- intersystems_iris._MessageHeader._MessageHeader._set_statement_id(
1282
- self._out_message.wire.buffer, self._statement_id
1283
- )
1284
-
1285
- # message body
1286
- self._lastrowid = None
1287
- self._out_message.wire._set(1) # number of statement chunks
1288
- self._out_message.wire._set(self._parsed_statement) # statement itself
1289
- self._out_message.wire._set_raw_bytes(self._paramInfo.getBuffer()) # paramInfo (from _PreParser)
1290
- self._out_message.wire._set(-1) # autoGeneratedKeyColumn
1291
- self._out_message.wire._set(0) # statement timeout always 0 for non-queries
1292
- self._write_parameters()
1293
-
1294
- # send
1295
- sequence_number = self._connection._get_new_sequence_number()
1296
- self._out_message._send(sequence_number)
1297
-
1298
- try:
1299
- # retrieve response
1300
- self._in_message._read_message_sql(sequence_number, self._statement_id, 0, [100])
1301
- self._sqlcode = self._in_message.wire.header._get_function_code()
1302
- self._process_sqlcode(self._sqlcode)
1303
-
1304
- addToCache = self._get_parameter_info(self._in_message.wire)
1305
-
1306
- notDDL = bool(
1307
- self._statementType != StatementType.DDL_ALTER_DROP
1308
- and self._statementType != StatementType.DDL_OTHER
1309
- )
1310
- if notDDL and addToCache:
1311
- self._cache_prepared_statement()
1312
-
1313
- except IndexError:
1314
- raise DatabaseError("Server response message terminated prematurely")
1315
- except TypeError:
1316
- raise DatabaseError("Unexpected server response message format")
1317
-
1318
- def _prepare_stored_procedure(self):
1319
- with self._connection._lock:
1320
- # message header
1321
- self._statement_id = self._connection._get_new_statement_id()
1322
- self._out_message.wire._write_header(_Message.PREPARE_STORED_PROCEDURE)
1323
- intersystems_iris._MessageHeader._MessageHeader._set_statement_id(
1324
- self._out_message.wire.buffer, self._statement_id
1325
- )
1326
-
1327
- # message body
1328
- # self._out_message.wire._set(1) # number of statement chunks
1329
- self._out_message.wire._set(self._parsed_statement) # statement itself
1330
-
1331
- # send message
1332
- sequence_number = self._connection._get_new_sequence_number()
1333
- self._out_message._send(sequence_number)
1334
-
1335
- # retrieve response
1336
- self._in_message._read_message_sql(sequence_number, self._statement_id, 0, [0])
1337
- sqlcode = self._in_message.wire.header._get_function_code()
1338
- self._process_sqlcode(sqlcode)
1339
-
1340
- self._process_stored_procedure_metadata(self._in_message.wire, False)
1341
- if self._multiple_result_sets:
1342
- return
1343
- self._cache_prepared_statement()
1344
- return
1345
-
1346
- def _process_stored_procedure_metadata(self, wire, direct_execute):
1347
- ret_stmt_type = wire._get()
1348
- if ret_stmt_type < 0:
1349
- if ret_stmt_type == -1:
1350
- self._multiple_result_sets_metadata(wire, False, direct_execute)
1351
- else:
1352
- self._multiple_result_sets_metadata(wire, True, direct_execute)
1353
- return
1354
- if ret_stmt_type % 2 == StatementType.QUERY.value:
1355
- self._get_column_info(wire)
1356
- if not self._stored_procedure_parameter_info(wire, ret_stmt_type > 1, direct_execute):
1357
- if direct_execute and ret_stmt_type % 2 == StatementType.QUERY.value:
1358
- # result set type check
1359
- self._in_message.wire._move_to_end()
1360
- if direct_execute:
1361
- raise Exception("Parameter list mismatch")
1362
- if direct_execute and self._parameter_list_mismatch_exception:
1363
- raise Exception("Parameter list mismatch")
1364
- if self._cursor_type == CursorType.CALLABLE:
1365
- self._statementType = StatementType(ret_stmt_type % 2)
1366
- return
1367
- if self._cursor_type == CursorType.PREPARED:
1368
- if ret_stmt_type % 2 == StatementType.QUERY.value:
1369
- self._statementType = StatementType.PREPARED_CALL_QUERY
1370
- else:
1371
- self._statementType = StatementType.PREPARED_CALL_UPDATE
1372
- return
1373
- if ret_stmt_type % 2 == StatementType.QUERY.value:
1374
- self._statementType = StatementType.DIRECT_CALL_QUERY
1375
- else:
1376
- self._statementType = StatementType.DIRECT_CALL_UPDATE
1377
- return
1378
-
1379
- def _multiple_result_sets_metadata(self, wire, server_has_return, direct_execute):
1380
- self._multiple_result_sets = True
1381
- self._mrs_done = False
1382
- if not self._stored_procedure_parameter_info(wire, server_has_return, direct_execute):
1383
- raise Exception("Parameter list mismatch")
1384
-
1385
- if self._cursor_type == CursorType.CALLABLE:
1386
- self._statementType = StatementType.QUERY
1387
- elif self._cursor_type == CursorType.PREPARED:
1388
- self._statementType = StatementType.PREPARED_CALL_QUERY
1389
- else:
1390
- self._statementType = StatementType.DIRECT_CALL_QUERY
1391
-
1392
- def _stored_procedure_parameter_info(self, wire, server_has_return, direct_execute):
1393
- count = wire._get()
1394
- size = len(self._params._params_list)
1395
- if self._cursor_type != CursorType.CALLABLE and self._has_return_value == 1:
1396
- wire._move_to_end()
1397
- return False
1398
- if self._exec_params != None:
1399
- while size < count:
1400
- self._params._params_list.insert(0, intersystems_iris.dbapi._Parameter._Parameter())
1401
- size = size + 1
1402
- if server_has_return:
1403
- self._has_return_value = ServerReturnType.IGNORE_RETURN_VALUE
1404
- elif size == count:
1405
- if server_has_return and self._has_return_value == ServerReturnType.HAS_RETURN_VALUE:
1406
- self._has_return_value = ServerReturnType.HAS_RETURN_VALUE
1407
- elif not server_has_return and self._has_return_value == ServerReturnType.NO_RETURN_VALUE:
1408
- self._has_return_value = ServerReturnType.NO_RETURN_VALUE
1409
- elif (
1410
- size == 1
1411
- and count == 1
1412
- and (
1413
- self._params._params_list[0].mode == ParameterMode.DEFAULT_PARAMETER
1414
- and self._has_return_value == ServerReturnType.NO_RETURN_VALUE
1415
- and server_has_return
1416
- )
1417
- or (
1418
- self._params._params_list[0].mode == ParameterMode.UNKNOWN
1419
- and self._has_return_value == ServerReturnType.IGNORE_RETURN_VALUE
1420
- and server_has_return
1421
- )
1422
- ):
1423
- self._params._params_list.pop(0)
1424
- self._params._params_list.insert(0, intersystems_iris.dbapi._Parameter._Parameter())
1425
- self._has_return_value = ServerReturnType.IGNORE_RETURN_VALUE
1426
- else:
1427
- wire._move_to_end()
1428
- return False
1429
- elif size == count + 1:
1430
- if not server_has_return and self._has_return_value == ServerReturnType.HAS_RETURN_VALUE:
1431
- self._has_return_value = ServerReturnType.NULL_RETURN_VALUE
1432
- elif (size == 2 and count == 1) or (size == 1 and count == 0):
1433
- if self._params._params_list[-1].mode == ParameterMode.DEFAULT_PARAMETER:
1434
- if server_has_return and self._has_return_value == ServerReturnType.HAS_RETURN_VALUE:
1435
- self._params._params_list.pop(-1)
1436
- self._has_return_value = ServerReturnType.HAS_RETURN_VALUE
1437
- elif not server_has_return and self._has_return_value == ServerReturnType.NO_RETURN_VALUE:
1438
- self._params._params_list.pop(-1)
1439
- self._has_return_value = ServerReturnType.NO_RETURN_VALUE
1440
- else:
1441
- wire._move_to_end()
1442
- return False
1443
- else:
1444
- wire._move_to_end()
1445
- return False
1446
- else:
1447
- wire._move_to_end()
1448
- return False
1449
- elif size == count - 1:
1450
- if server_has_return and self._has_return_value == ServerReturnType.NO_RETURN_VALUE:
1451
- self._params._params_list.insert(0, intersystems_iris.dbapi._Parameter._Parameter())
1452
- self._has_return_value = ServerReturnType.IGNORE_RETURN_VALUE
1453
- else:
1454
- self._params._params_list.append(
1455
- intersystems_iris.dbapi._Parameter._Parameter(ParameterMode.DEFAULT_PARAMETER, "c")
1456
- )
1457
- else:
1458
- self._parameter_list_mismatch_exception = True
1459
- if server_has_return and self._has_return_value == ServerReturnType.NO_RETURN_VALUE:
1460
- self._has_return_value = ServerReturnType.IGNORE_RETURN_VALUE
1461
- param = intersystems_iris.dbapi._Parameter._Parameter()
1462
- param.mode = ParameterMode.OUTPUT
1463
- self._params._params_list.insert(0, param)
1464
- size = size + 1
1465
- while size < count:
1466
- self._params._params_list.append(
1467
- intersystems_iris.dbapi._Parameter._Parameter(ParameterMode.DEFAULT_PARAMETER, "c")
1468
- )
1469
- size = size + 1
1470
- self._read_parameter_data(wire, count, True)
1471
- return True
1472
-
1473
- def _bind_exec_params(self):
1474
- for param in self._params._params_list:
1475
- exec_param = self._get_exec_param_by_name(param.name)
1476
- if exec_param != None:
1477
- if exec_param.mode == ParameterMode.UNKNOWN:
1478
- continue
1479
- param.mode = exec_param.mode
1480
- if exec_param.mode != ParameterMode.OUTPUT:
1481
- if isinstance(exec_param.value, list):
1482
- self._params._array_bound = True
1483
- param._bind(exec_param.value, self._parameter_sets)
1484
- else:
1485
- param.__bound = exec_param.bound
1486
- if exec_param.scale != -1:
1487
- param.scale = exec_param.scale
1488
- else:
1489
- if param.mode == ParameterMode.UNKNOWN:
1490
- param.mode = ParameterMode.DEFAULT_PARAMETER
1491
-
1492
- def _get_exec_param_by_name(self, name):
1493
- self._exec_params._has_bound_by_param_name = True
1494
- return self._exec_params._params_list[self._exec_params._param_names.get(name.upper())]
1495
-
1496
- def _stored_procedure_update(self):
1497
- with self._connection._lock:
1498
- # message header
1499
- self._out_message.wire._write_header(_Message.STORED_PROCEDURE_UPDATE_EXECUTE)
1500
- intersystems_iris._MessageHeader._MessageHeader._set_statement_id(
1501
- self._out_message.wire.buffer, self._statement_id
1502
- )
1503
-
1504
- # message body
1505
- self._out_message.wire._set(0) # isStatic should always be 0 for non-queries
1506
- self._out_message.wire._set(0) # query timeout
1507
- self._out_message.wire._set(0) # maxRows (0 = all rows)
1508
- self._write_stored_procedure_parameters()
1509
-
1510
- # send
1511
- sequence_number = self._connection._get_new_sequence_number()
1512
- self._out_message._send(sequence_number)
1513
-
1514
- # retrieve response
1515
- self._in_message._read_message_sql(sequence_number, self._statement_id, 0, [404, 100])
1516
- self._sqlcode = self._in_message.wire.header._get_function_code()
1517
- self._process_sqlcode(self._sqlcode)
1518
- if self._sqlcode == 404:
1519
- self._update404(404)
1520
- else:
1521
- self._get_output_parameters(self._in_message.wire)
1522
- return
1523
-
1524
- def _stored_procedure_query(self):
1525
- if self._multiple_result_sets:
1526
- self._execute_multiple_result_sets(False)
1527
- return
1528
- with self._connection._lock:
1529
- # message header
1530
- self._out_message.wire._write_header(_Message.STORED_PROCEDURE_QUERY_EXECUTE)
1531
- intersystems_iris._MessageHeader._MessageHeader._set_statement_id(
1532
- self._out_message.wire.buffer, self._statement_id
1533
- )
1534
-
1535
- # message body
1536
- self._out_message.wire._set(0) # ResultSet.TYPE_SCROLL_INSENSITIVE
1537
- self._out_message.wire._set(0) # query timeout
1538
- self._out_message.wire._set(0) # maxRows (0 = all rows)
1539
- self._write_stored_procedure_parameters()
1540
-
1541
- # send
1542
- sequence_number = self._connection._get_new_sequence_number()
1543
- self._out_message._send(sequence_number)
1544
-
1545
- # retrieve response
1546
- self._in_message._read_message_sql(sequence_number, self._statement_id, 0, [404, 100])
1547
- self._sqlcode = self._in_message.wire.header._get_function_code()
1548
- if self._sqlcode == 404:
1549
- self._handle_error_504(404)
1550
- return
1551
- elif self._sqlcode == 100:
1552
- self._handle_error_100(100)
1553
- return
1554
- self._get_output_parameters(self._in_message.wire)
1555
- self._in_message._read_message_sql(sequence_number, self._statement_id, _InStream.FETCH_DATA, [100])
1556
- self._sqlcode = self._in_message.wire.header._get_function_code()
1557
- self._process_sqlcode(self._sqlcode)
1558
- if self._sqlcode == 100:
1559
- self._handle_error_100(100)
1560
-
1561
- self._current_wire = self._in_message.wire
1562
- self._result_set = [self._current_wire]
1563
- self._rs_index = 0
1564
-
1565
- def _execute_multiple_result_sets(self, validate):
1566
- self._fetch_done = False
1567
- if validate:
1568
- self._validate_parameters()
1569
- with self._connection._lock:
1570
- self._out_message.wire._write_header(_Message.EXECUTE_MULTIPLE_RESULT_SETS)
1571
- self._out_message.wire._set(0) # resultSetType != ResultSet.TYPE_SCROLL_INSENSITIVE
1572
- self._out_message.wire._set(0) # query timeout
1573
- self._write_stored_procedure_parameters()
1574
-
1575
- # send
1576
- sequence_number = self._connection._get_new_sequence_number()
1577
- self._out_message._send(sequence_number)
1578
-
1579
- if self.statementFeatureOption & Feature.optionFastSelect == Feature.optionFastSelect:
1580
- self._rsrow = _ResultSetRow(self._connection, self._columns, self.maxRowItemCount)
1581
- else:
1582
- self._rsrow = _ResultSetRow(self._connection, self._columns, 0)
1583
-
1584
- self._in_message._read_message_sql(sequence_number, self._statement_id, _InStream.FETCH_DATA, [100])
1585
- self._sqlcode = self._in_message.wire.header._get_function_code()
1586
- if self._sqlcode == 100:
1587
- self._fetch_done = True
1588
- self._get_output_parameters(self._in_message.wire)
1589
-
1590
- self._current_wire = self._in_message.wire
1591
- self._result_set = [self._current_wire]
1592
- self._rs_index = 0
1593
-
1594
- results = self._in_message.wire._get()
1595
- if results >= 0:
1596
- self._update_cnt = results
1597
- return False
1598
- elif results == -1:
1599
- return True
1600
- elif results == -2:
1601
- self._update_cnt = -1
1602
- self._mrs_done = True
1603
- # self._rsrow._is_after_last = True
1604
- return False
1605
- else:
1606
- raise Exception("Invalid result type value")
1607
-
1608
- def _write_stored_procedure_parameters(self):
1609
- i = 0
1610
- if self._parameter_sets != 0:
1611
- self._out_message.wire._set(self._parameter_sets)
1612
- self._out_message.wire._set(len(self._params._params_list))
1613
- for j in range(self._parameter_sets):
1614
- for i, param in enumerate(self._params._params_list):
1615
- self._out_message.wire._set_parameter(param._values[j])
1616
- return
1617
- self._out_message.wire._set(1)
1618
- if self._has_return_value != ServerReturnType.NO_RETURN_VALUE:
1619
- i = 1
1620
- self._out_message.wire._set(len(self._params._params_list) - i)
1621
- param_index = 0
1622
- param_counter = 0
1623
- for param in self._params._params_list:
1624
- if i == 1:
1625
- i = 0
1626
- continue
1627
- if param.mode == ParameterMode.OUTPUT or param.mode == ParameterMode.DEFAULT_PARAMETER:
1628
- self._out_message.wire._set_undefined()
1629
- elif not (param.mode == ParameterMode.INPUT or param.mode == ParameterMode.INPUT_OUTPUT):
1630
- self._out_message.wire._set_parameter_type(param.type, param.value)
1631
- elif len(self.params) > 0:
1632
- item = self.params[param_counter]
1633
- if isinstance(item, list) or isinstance(item, tuple):
1634
- value = item[param_index]
1635
- param_index = param_index + 1
1636
- else:
1637
- value = item
1638
- param_counter = param_counter + 1
1639
- self._out_message.wire._set_parameter_type(param.type, value)
1640
- else:
1641
- raise Exception("Missing value")
1642
-
1643
- def _get_output_parameters(self, wire):
1644
- beg = wire._get_offset()
1645
- i = 0
1646
- if self._has_return_value == ServerReturnType.NULL_RETURN_VALUE:
1647
- i += 1
1648
- for param in self._params._params_list:
1649
- if i == 1:
1650
- i = 0
1651
- continue
1652
- if (
1653
- param.mode == ParameterMode.INPUT_OUTPUT
1654
- or param.mode == ParameterMode.OUTPUT
1655
- or param.mode == ParameterMode.RETURN_VALUE
1656
- ):
1657
- wire._next_unless_undefined()
1658
- else:
1659
- wire._next()
1660
- if self._has_return_value == ServerReturnType.NULL_RETURN_VALUE:
1661
- self._output_parameter_list = wire._get_output_parameter_list(beg, True)
1662
- self._has_return_value = ServerReturnType.HAS_RETURN_VALUE
1663
- else:
1664
- self._output_parameter_list = wire._get_output_parameter_list(beg, False)
1665
- if self._statementType not in [StatementType.DIRECT_CALL_UPDATE]:
1666
- self._params._prep_list_index(
1667
- False, self._output_parameter_list
1668
- ) # fast select not supported for stored procedures
1669
- return
1670
-
1671
- def _handle_error_504(self, error):
1672
- if error == 404:
1673
- self._query404()
1674
- return
1675
- self._handle_error_100(error)
1676
-
1677
- def _handle_error_100(self, error):
1678
- if error == 100:
1679
- self._fetch_done = True
1680
- pass
1681
- else:
1682
- pass
1683
-
1684
- def stored_results(self):
1685
- if self._closed:
1686
- raise InterfaceError("Cursor is closed")
1687
- if self._statementType not in [
1688
- StatementType.QUERY,
1689
- StatementType.DIRECT_CALL_QUERY,
1690
- StatementType.PREPARED_CALL_QUERY,
1691
- ]:
1692
- return None
1693
- # getResultSet()
1694
- if self._multiple_result_sets:
1695
- if self._rsrow == None and self._rowcount == -1:
1696
- return None
1697
- if self._mrs_done:
1698
- return None
1699
- self._get_column_info(self._in_message.wire)
1700
- self.nextset()
1701
- return iter(self._stored_results)
1702
-
1703
- def nextset(self):
1704
- if len(self._stored_results) == 0:
1705
- # getResultSet()
1706
- if self.statementFeatureOption & Feature.optionFastSelect == Feature.optionFastSelect:
1707
- self._rsrow = _ResultSetRow(self._connection, self._columns, self.maxRowItemCount)
1708
- else:
1709
- self._rsrow = _ResultSetRow(self._connection, self._columns, 0)
1710
- self._rsrow.indexRow(self._in_message.wire.list_item)
1711
- self._stored_results.append(self._rsrow._offsets)
1712
- return True
1713
- else:
1714
- # getMoreResults()
1715
- if self._closed:
1716
- raise InterfaceError("Cursor is closed")
1717
- if self._connection == None or self._connection.isClosed():
1718
- raise InterfaceError("Connection not open")
1719
- if (
1720
- self._mrs_done
1721
- or not self._multiple_result_sets
1722
- or (
1723
- self._statementType != StatementType.PREPARED_CALL_QUERY
1724
- and self._statementType != StatementType.DIRECT_CALL_QUERY
1725
- and self._statementType != StatementType.CALL
1726
- and self._statementType != StatementType.CALLWITHRESULT
1727
- and not (self._statementType == StatementType.QUERY and self._cursor_type == CursorType.CALLABLE)
1728
- )
1729
- ):
1730
- return False
1731
- with self._connection._lock:
1732
- self._out_message.wire._write_header(_Message.GET_MORE_RESULTS)
1733
- self._out_message.wire._set(1) # current = CLOSE_CURRENT_RESULT
1734
-
1735
- # send
1736
- sequence_number = self._connection._get_new_sequence_number()
1737
- self._out_message._send(sequence_number)
1738
-
1739
- self._in_message._read_message_sql(sequence_number, self._statement_id, 0, [100])
1740
- sqlcode = self._in_message.wire.header._get_function_code()
1741
-
1742
- self._current_wire = self._in_message.wire
1743
- self._result_set = [self._current_wire]
1744
- self._rs_index = 0
1745
-
1746
- results = self._in_message.wire._get()
1747
- if results >= 0:
1748
- self._update_cnt = results
1749
- return False
1750
- elif results == -1:
1751
- self._rsrow = None
1752
- self._get_column_info(self._in_message.wire)
1753
- if self.statementFeatureOption & Feature.optionFastSelect == Feature.optionFastSelect:
1754
- self._rsrow = _ResultSetRow(self._connection, self._columns, self.maxRowItemCount)
1755
- else:
1756
- self._rsrow = _ResultSetRow(self._connection, self._columns, 0)
1757
- self._rsrow.indexRow(self._in_message.wire.list_item)
1758
- self._stored_results.append(self._rsrow._offsets)
1759
- if sqlcode == 100:
1760
- self._fetch_done = True
1761
- else:
1762
- self._fetch_done = False
1763
- return True
1764
- elif results == -2:
1765
- self._update_cnt = -1
1766
- self._mrs_done = True
1767
- return False
1768
- else:
1769
- raise Exception("Invalid result type value")
1770
- return
1771
-
1772
- def _get_result_set(self, oref):
1773
- if oref == None:
1774
- return None
1775
-
1776
- with self._connection._lock:
1777
- self._out_message.wire._write_header(_Message.GET_RESULT_SET_OBJECT)
1778
- self._out_message.wire._set(oref)
1779
- self._out_message.wire._set(0) # IRISResultSet.GET_RESULT_SET_OBJECT_INIT
1780
-
1781
- # send
1782
- sequence_number = self._connection._get_new_sequence_number()
1783
- self._out_message._send(sequence_number)
1784
-
1785
- # retrieve response
1786
- error = self._in_message._read_message_sql(sequence_number, self._statement_id, 0, [100])
1787
- if error == 100:
1788
- self._fetch_done = True
1789
- self._get_column_info(self._in_message.wire)
1790
- return
1791
-
1792
- def callproc(self, procname, *params):
1793
- if self._closed:
1794
- raise InterfaceError("Cursor is closed")
1795
- if self._connection == None or self._connection.isClosed():
1796
- raise InterfaceError("Connection not open")
1797
-
1798
- self.statement = procname
1799
- if len(params) == 1 and (isinstance(params[0], tuple) or isinstance(params[0], list)):
1800
- self.params = self.params[0]
1801
- else:
1802
- self.params = params
1803
-
1804
- self._params.set_input_params(self.params)
1805
-
1806
- self._cursor_type = CursorType.CALLABLE
1807
- self._cleanup()
1808
- self._preparse()
1809
- self._stored_results = []
1810
-
1811
- if not self._get_cached_info():
1812
- self._prepare_stored_procedure()
1813
-
1814
- # execute() in IrisPreparedStatement
1815
- if self._multiple_result_sets:
1816
- return self._execute_multiple_result_sets(True)
1817
- if self._statementType == StatementType.QUERY or self._statementType == StatementType.PREPARED_CALL_QUERY:
1818
- self._execute_query()
1819
- self._rowcount = -1
1820
- if self._fetch_done and self._in_message.wire.header._get_message_length() == 0:
1821
- return
1822
- return self._process_return_values()
1823
- self._execute_update()
1824
- if self._parameter_sets == 0 and not self._multiple_result_sets:
1825
- self._rowcount = self._in_message.wire._get()
1826
-
1827
- return self._process_return_values()
1828
-
1829
- def _process_return_values(self):
1830
- return_args = []
1831
- for i, param in enumerate(self._params._params_list):
1832
- if param.mode in [ParameterMode.RETURN_VALUE, ParameterMode.OUTPUT, ParameterMode.INPUT]:
1833
- offset = self._params._get_user_list_offset(i + 1)
1834
- val = self._output_parameter_list._get_at_offset(offset)
1835
- if param.type == -51: # RESULT_SET_TYPE
1836
- self._get_result_set(val)
1837
- self.nextset()
1838
- return_args.append(self._stored_results[0])
1839
- else:
1840
- if val == "\x01": # Either represents the number 1 or a null/None value
1841
- # maybe move this to _grab_ascii_string in DBList?
1842
- off = self._output_parameter_list.list_item.data_offset
1843
- buf = self._output_parameter_list.list_item.buffer
1844
- if buf[off] == 1 and buf[off - 1] == 1 and buf[off - 2] == 3:
1845
- return_args.append(None)
1846
- else:
1847
- return_args.append(val)
1848
- if len(return_args) > 0:
1849
- if any(i != None for i in return_args):
1850
- return return_args
1851
- else:
1852
- return
1853
- else:
1854
- return
1855
-
1856
- @property
1857
- def lastrowid(self):
1858
- if self._lastrowid is not None:
1859
- return self._lastrowid
1860
-
1861
- if self._closed:
1862
- return None
1863
- if self._connection == None or self._connection.isClosed():
1864
- return None
1865
-
1866
- if self._statementType is not StatementType.UPDATE or self._rowcount < 1:
1867
- return None
1868
-
1869
- if self._rowcount > 1:
1870
- with self._connection.cursor() as cursor:
1871
- cursor.execute("SELECT LAST_IDENTITY()")
1872
- self._lastrowid = cursor.fetchone()[0]
1873
- return self._lastrowid
1874
-
1875
- # In multiple rows inserted it returns the first inserted value, not the last one
1876
- with self._connection._lock:
1877
- self._out_message.wire._write_header(_Message.GET_AUTO_GENERATED_KEYS)
1878
- sequence_number = self._connection._get_new_sequence_number()
1879
- self._out_message._send(sequence_number)
1880
- self._in_message._read_message_sql(sequence_number)
1881
- self._sqlcode = self._in_message.wire.header._get_function_code()
1882
- if self._sqlcode != 100:
1883
- raise DatabaseError(self._get_error_info(self._sqlcode))
1884
- self._get_column_info(self._in_message.wire)
1885
- self._lastrowid = self._in_message.wire._get()
1886
- return self._lastrowid
1887
-
1888
- def _cleanup(self):
1889
- super()._cleanup()
1890
- if self._rsrow != None:
1891
- self._rsrow = None
1892
- if self._params != None:
1893
- self._params._clear()
1894
- self._multiple_result_sets = False
1895
- self._mrs_done = False
1896
- self._fetch_done = False
1897
- self._parameter_list_mismatch_exception = False
1898
- self._parameter_sets = 0
1899
- self._rowcount = -1
1900
- self._exec_params = None
1901
- self._statementType = StatementType.UPDATE
1902
- self.statementFeatureOption = 0
1903
- self.maxRowItemCount = 0
1904
- self._is_batch_update = False
1905
-
1906
- def close(self):
1907
- if self._closed:
1908
- return
1909
- self._columns = None
1910
- self._rowcount = -1
1911
- self.arraysize = 0
1912
-
1913
- self._connection = None
1914
- self._in_message = None
1915
- self._out_message = None
1916
-
1917
- self._result_set = None
1918
-
1919
- if self._rsrow != None:
1920
- self._rsrow = None
1921
- self._cursor_ptr = 0
1922
- self._scroll_flag = False
1923
- self._warehouse = []
1924
- self._warehouse_dict = {}
1925
- self._last_row_in_warehouse_dict = -1
1926
- self._warehouse_dict_keys = []
1927
-
1928
- self._params = None
1929
- self._parsed_statement = None
1930
- self._cursor_type = CursorType.DEFAULT
1931
- self._statementType = StatementType.UPDATE # default
1932
- self._paramInfo = None
1933
- self.statement = None
1934
- self.statementFeatureOption = Feature.optionNone
1935
- self._statement_id = None
1936
- self._sqlcode = None
1937
- self._current_wire = None
1938
- self._result_set = []
1939
- self._rs_index = -1
1940
-
1941
- self._parameter_sets = 0
1942
- self._exec_params = None
1943
- self._is_batch_update = False
1944
- self._multiple_result_sets = False
1945
- self._mrs_done = False
1946
- self._fetch_done = False
1947
- self._parameter_list_mismatch_exception = False
1948
- if self._output_parameter_list != None:
1949
- self._output_parameter_list._clear_list()
1950
-
1951
- self._closed = True
1952
-
1953
- def executemany(self, operation, seq_of_params):
1954
- super().executemany(operation, seq_of_params)
1955
- self._rowcount = 0
1956
- for i in range(len(self.params)):
1957
- self._rowcount += self._in_message.wire._get()
1958
- return self._rowcount
1959
-
1960
- def scroll(self, value, mode):
1961
- if mode == None or mode == "":
1962
- mode = "relative"
1963
- mode = mode.lower()
1964
- if mode != "absolute" and mode != "relative":
1965
- raise ValueError("This mode is not supported - use 'relative' or 'absolute'.")
1966
-
1967
- # Backward Scrolling
1968
- if value < 0:
1969
- if mode == "relative":
1970
- self._rownumber = self._cursor_ptr + value - 1
1971
- else:
1972
- raise ValueError("Negative values with absolute scrolling are not allowed.")
1973
- self._cursor_ptr = self._rownumber + 1
1974
- if self._rs_index == 0:
1975
- return self._warehouse[self._rownumber]
1976
- else:
1977
- if self._rownumber <= self._last_row_in_warehouse_dict:
1978
- return self._retrieve_from_warehouse(self._rownumber)
1979
- else:
1980
- if self._current_wire == None:
1981
- rows_available = self._last_row_in_warehouse_dict
1982
- else:
1983
- rows_available = self._last_row_in_warehouse_dict + len(self._warehouse)
1984
- if self._rownumber <= rows_available:
1985
- return self._warehouse[self._rownumber - self._last_row_in_warehouse_dict - 1]
1986
- # Forward Scrolling
1987
- else:
1988
- if mode == "absolute":
1989
- self._cursor_ptr = 0
1990
- self._scroll_flag = True
1991
- self._rownumber = self._cursor_ptr + value - 1
1992
- if self._rs_index == 0:
1993
- if self._rownumber >= len(self._warehouse):
1994
- if mode == "absolute":
1995
- self._cursor_ptr = len(self._warehouse)
1996
- return self.fetchone()
1997
- else:
1998
- self._scroll_flag = False
1999
- self._cursor_ptr = self._rownumber + 1
2000
- return self._warehouse[self._rownumber]
2001
- else:
2002
- if self._rownumber <= self._last_row_in_warehouse_dict:
2003
- self._scroll_flag = False
2004
- self._cursor_ptr = self._rownumber + 1
2005
- return self._retrieve_from_warehouse(self._rownumber)
2006
- else:
2007
- if self._current_wire == None:
2008
- rows_available = self._last_row_in_warehouse_dict
2009
- else:
2010
- rows_available = self._last_row_in_warehouse_dict + len(self._warehouse)
2011
- if self._rownumber <= rows_available:
2012
- self._scroll_flag = False
2013
- self._cursor_ptr = self._rownumber + 1
2014
- return self._warehouse[self._rownumber - self._last_row_in_warehouse_dict - 1]
2015
- else:
2016
- if mode == "absolute":
2017
- self._cursor_ptr = rows_available + 1
2018
- return self.fetchone()
2019
-
2020
- def _retrieve_from_warehouse(self, value):
2021
- for idx, (key, val) in enumerate(self._warehouse_dict.items()):
2022
- if value <= key:
2023
- if idx != 0:
2024
- prev_key = self._warehouse_dict_keys[idx - 1]
2025
- return val[value - prev_key - 1]
2026
- return val[value]
2027
-
2028
- def _switch_buffer(self):
2029
- if self._sqlcode == 0:
2030
- with self._connection._lock:
2031
- self._out_message.wire._write_header(_Message.FETCH_DATA)
2032
- intersystems_iris._MessageHeader._MessageHeader._set_statement_id(
2033
- self._out_message.wire.buffer, self._statement_id
2034
- )
2035
-
2036
- sequence_number = self._connection._get_new_sequence_number()
2037
- self._out_message._send(sequence_number)
2038
-
2039
- self._in_message._read_message_sql(sequence_number, self._statement_id, 0, [100])
2040
- self._sqlcode = self._in_message.wire.header._get_function_code()
2041
- self._process_sqlcode(self._sqlcode)
2042
- self._result_set.append(self._in_message.wire)
2043
-
2044
- if self._sqlcode == 404:
2045
- self._query404()
2046
- return
2047
-
2048
- if self._rs_index + 1 == len(self._result_set):
2049
- self._warehouse_dict[self._cursor_ptr] = self._warehouse
2050
- self._warehouse_dict_keys = sorted(self._warehouse_dict.keys())
2051
- self._last_row_in_warehouse_dict = self._warehouse_dict_keys[-1]
2052
- self._current_wire = None
2053
- else:
2054
- self._warehouse_dict[self._cursor_ptr] = self._warehouse
2055
- self._warehouse_dict_keys = sorted(self._warehouse_dict.keys())
2056
- self._last_row_in_warehouse_dict = self._warehouse_dict_keys[-1]
2057
- self._warehouse = []
2058
- self._rsrow._new_buffer = True
2059
- self._rs_index += 1
2060
- self._current_wire = self._result_set[self._rs_index]
2061
-
2062
- def fetchone_helper(self):
2063
- row_indexing = True
2064
- if self.statementFeatureOption & Feature.optionFastSelect == Feature.optionFastSelect:
2065
- list_item = self._current_wire.list_item
2066
- buffer = list_item.buffer
2067
- length = list_item.list_buffer_end
2068
-
2069
- if self._rsrow._new_buffer:
2070
- prev_offset = list_item.next_offset
2071
- self._rsrow._new_buffer = False
2072
- else:
2073
- prev_offset = self._rsrow._offsets._length
2074
-
2075
- if prev_offset < length:
2076
- if self._rsrow._fast_first_iter:
2077
- self._rsrow._fast_first_iter = False
2078
- else:
2079
- if self._rsrow._new_buffer:
2080
- list_item.buffer = buffer
2081
- list_item.next_offset = prev_offset
2082
- intersystems_iris._DBList._DBList._get_list_element(list_item)
2083
- length = list_item.next_offset
2084
- prev_offset = list_item.data_offset
2085
- if list_item.data_length == 0: #
2086
- for j in range(self._rsrow.colCount):
2087
- rowItems[j] = -1
2088
- self._rsrow._offsets = self._rsrow.update(rowItems) # ???
2089
- return True
2090
- else:
2091
- if self._rsrow.rowItems != None:
2092
- self._rsrow.rowItems[-1] = 0
2093
- return False
2094
-
2095
- self._rsrow._last_list_item = list_item
2096
- self._rsrow._offsets = self._rsrow.DataRowFastSelect(self._rsrow, prev_offset, length, buffer)
2097
- self._warehouse.append(self._rsrow._offsets)
2098
-
2099
- if self._current_wire._is_end():
2100
- self._switch_buffer()
2101
-
2102
- else:
2103
- row_indexing = self._rsrow.indexRow(self._current_wire.list_item)
2104
- if row_indexing:
2105
- self._warehouse.append(self._rsrow._offsets)
2106
-
2107
- if self._rsrow.rowItems == None:
2108
- return
2109
-
2110
- if self._rsrow.rowItems[-1] >= self._current_wire.list_item.list_buffer_end:
2111
- self._switch_buffer()
2112
-
2113
- self._cursor_ptr += 1
2114
- return row_indexing
2115
-
2116
- def fetchone(self):
2117
- if self._result_set == None:
2118
- raise InterfaceError(
2119
- "Either execute has not yet been called, or the previous call of execute did not return a result set"
2120
- )
2121
-
2122
- if self._current_wire == None and self._cursor_ptr > self._last_row_in_warehouse_dict:
2123
- return None
2124
-
2125
- retval = None
2126
- if self._rs_index == 0:
2127
- if self._cursor_ptr < len(self._warehouse):
2128
- self._cursor_ptr += 1
2129
- retval = self._warehouse[self._cursor_ptr - 1]
2130
- else:
2131
- rownumber = self._cursor_ptr
2132
- if rownumber <= self._last_row_in_warehouse_dict:
2133
- self._cursor_ptr += 1
2134
- retval = self._retrieve_from_warehouse(rownumber)
2135
- else:
2136
- if self._current_wire == None:
2137
- rows_available = self._last_row_in_warehouse_dict
2138
- else:
2139
- rows_available = self._last_row_in_warehouse_dict + len(self._warehouse)
2140
- if rownumber <= rows_available:
2141
- self._cursor_ptr += 1
2142
- retval = self._warehouse[rownumber - self._last_row_in_warehouse_dict - 1]
2143
-
2144
- if retval is None:
2145
- if self._scroll_flag:
2146
- while self._cursor_ptr <= self._rownumber:
2147
- if self.fetchone_helper():
2148
- retval = self._rsrow._offsets
2149
- self._scroll_flag = False
2150
- else:
2151
- if self.fetchone_helper():
2152
- retval = self._rsrow._offsets
2153
-
2154
- if retval is None:
2155
- return retval
2156
- # print('retval', retval[:])
2157
- return retval.as_tuple()
2158
- # return tuple(retval[:])
2159
-
2160
- def fetchmany(self, size=None):
2161
- if self._result_set == None:
2162
- raise InterfaceError(
2163
- "Either execute has not yet been called, or the previous call of execute did not return a result set"
2164
- )
2165
-
2166
- if self._current_wire == None:
2167
- if self._cursor_ptr > self._last_row_in_warehouse_dict:
2168
- return []
2169
- if size is None:
2170
- size = self.arraysize
2171
- if self._rs_index == 0:
2172
- if self._cursor_ptr < len(self._warehouse):
2173
- rows = []
2174
- for i in range(size):
2175
- row = self._warehouse[self._cursor_ptr]
2176
- rows.append(row[:])
2177
- if self._cursor_ptr + 1 >= len(self._warehouse):
2178
- self._cursor_ptr += 1
2179
- break
2180
- self._cursor_ptr += 1
2181
- return rows
2182
- else:
2183
- rows = []
2184
- for i in range(size):
2185
- row = self._retrieve_from_warehouse(self._cursor_ptr)
2186
- rows.append(row[:])
2187
- if self._cursor_ptr + 1 > self._last_row_in_warehouse_dict:
2188
- self._cursor_ptr += 1
2189
- break
2190
- self._cursor_ptr += 1
2191
- return rows
2192
-
2193
- if size is None:
2194
- size = self.arraysize
2195
-
2196
- rows = []
2197
- for i in range(size):
2198
- row = self.fetchone()
2199
- if row is None:
2200
- break
2201
- rows.append(row)
2202
- return rows
2203
-
2204
- def fetchall(self):
2205
- if self._result_set == None:
2206
- raise InterfaceError(
2207
- "Either execute has not yet been called, or the previous call of execute did not return a result set"
2208
- )
2209
-
2210
- if self._current_wire == None:
2211
- if self._cursor_ptr > self._last_row_in_warehouse_dict:
2212
- return []
2213
- if self._rs_index == 0:
2214
- if self._cursor_ptr < len(self._warehouse):
2215
- rows = []
2216
- while 1:
2217
- row = self._warehouse[self._cursor_ptr]
2218
- rows.append(row[:])
2219
- if self._cursor_ptr + 1 >= len(self._warehouse):
2220
- self._cursor_ptr += 1
2221
- break
2222
- self._cursor_ptr += 1
2223
- return rows
2224
- else:
2225
- rows = []
2226
- while 1:
2227
- row = self._retrieve_from_warehouse(self._cursor_ptr)
2228
- rows.append(row[:])
2229
- if self._cursor_ptr + 1 > self._last_row_in_warehouse_dict:
2230
- self._cursor_ptr += 1
2231
- break
2232
- self._cursor_ptr += 1
2233
- return rows
2234
-
2235
- rows = []
2236
- while self._current_wire is not None:
2237
- row = self.fetchone()
2238
- if not row:
2239
- break
2240
- rows.append(row)
2241
-
2242
- return rows
2243
-
2244
-
2245
- class EmbdeddedCursor(_BaseCursor):
2246
- embedded = True
2247
- _result_set = None
2248
-
2249
- def __init__(self, connection: _IRISEmbedded) -> None:
2250
- super().__init__(connection)
2251
- self._sql = connection.iris.sql
2252
- self._iris = connection.iris
2253
- self._closed = False
2254
- self._connection = connection
2255
- self.restore_selectmode = self._iris.system.SQL.SetSelectMode(1)
2256
- self.restore_autocommit = self._iris.system.SQL.SetAutoCommit(
2257
- 0 if self._connection.autoCommit is None else 1 if self._connection.autoCommit else 2
2258
- )
2259
-
2260
- def close(self):
2261
- self._iris.system.SQL.SetSelectMode(self.restore_selectmode)
2262
- self._iris.system.SQL.SetAutoCommit(self.restore_autocommit)
2263
- super().close()
2264
-
2265
- def __del__(self):
2266
- try:
2267
- self.close()
2268
- except:
2269
- pass
2270
- return
2271
-
2272
- def _get_cached_info(self):
2273
- return False
2274
-
2275
- def _get_parameters(self, params_set=0):
2276
- params = self._params.collect(params_set)
2277
- # None = '', '' = b'\x00'
2278
- _conv = {
2279
- type(None): lambda v: "",
2280
- str: lambda v: v or b"\x00",
2281
- decimal.Decimal: lambda v: float(v),
2282
- }
2283
- params = [_conv[type(v)](v) if type(v) in _conv else v for v in params]
2284
- return params
2285
-
2286
- def _get_column_info(self):
2287
- self._columns = []
2288
- if self._result_set is None:
2289
- return
2290
-
2291
- metadata = self._result_set.ResultSet._GetMetadata()
2292
- count = metadata.columnCount if metadata != "" and metadata is not None else 0
2293
- for i in range(count):
2294
- slotPosition = i + 1
2295
- _column_info = metadata.columns.GetAt(slotPosition)
2296
- name = _column_info.colName
2297
- odbctype = _column_info.ODBCType
2298
- if _column_info.scale in SQLType.__members__:
2299
- # There is a bug on IRIS side, when it may return incorrectly when it passed that way NUMERIC(?, ?)
2300
- precision = 15
2301
- scale = 15
2302
- else:
2303
- precision = _column_info.precision or None
2304
- scale = _column_info.scale or None
2305
- nullable = _column_info.isNullable
2306
- label = _column_info.label
2307
- tableName = _column_info.tableName
2308
- schema = _column_info.schemaName
2309
- catalog = None
2310
- additionalData = [
2311
- _column_info.isAutoIncrement,
2312
- _column_info.isCaseSensitive,
2313
- _column_info.isCurrency,
2314
- _column_info.isReadOnly,
2315
- _column_info.isRowVersion,
2316
- _column_info.isUnique,
2317
- _column_info.isAliased,
2318
- _column_info.isExpression,
2319
- _column_info.isHidden,
2320
- _column_info.isIdentity,
2321
- _column_info.isKeyColumn,
2322
- _column_info.isRowId,
2323
- ]
2324
- self._columns.append(
2325
- intersystems_iris.dbapi._Column._Column(
2326
- name,
2327
- odbctype,
2328
- precision,
2329
- scale,
2330
- nullable,
2331
- label,
2332
- tableName,
2333
- schema,
2334
- catalog,
2335
- additionalData,
2336
- slotPosition,
2337
- )
2338
- )
2339
-
2340
- @property
2341
- def lastrowid(self):
2342
- return self._lastrowid
2343
-
2344
- def _prepare_new(self):
2345
- statement = self._parsed_statement
2346
- sqlcode = 0
2347
- message = None
2348
- try:
2349
- self._statement = self._sql.prepare(statement)
2350
- except Exception as ex:
2351
- sqlcode = ex.sqlcode
2352
- message = ex.message
2353
- self._process_sqlcode(sqlcode, message)
2354
-
2355
- def _prepared_query_execute(self):
2356
- self._rowcount = 0
2357
- params = self._get_parameters()
2358
- sqlcode = 0
2359
- message = None
2360
- try:
2361
- self._result_set = self._statement.execute(*params)
2362
- self._get_column_info()
2363
- self._rowcount += self._result_set.ResultSet._ROWCOUNT
2364
- except Exception as ex:
2365
- sqlcode = ex.sqlcode
2366
- message = ex.message
2367
-
2368
- self._process_sqlcode(sqlcode, message)
2369
-
2370
- def _send_direct_update_request(self):
2371
- self._rowcount = 0
2372
- self._lastrowid = None
2373
- statement = self._parsed_statement
2374
-
2375
- sets = self._parameter_sets or 1
2376
- for i in range(sets):
2377
- params = self._get_parameters(i)
2378
-
2379
- sqlcode = 0
2380
- message = None
2381
- try:
2382
- _result_set = self._sql.exec(statement, *params)
2383
- self._rowcount += _result_set.ResultSet._ROWCOUNT
2384
- self._lastrowid = _result_set.ResultSet._ROWID
2385
- except Exception as ex:
2386
- sqlcode = ex.sqlcode
2387
- message = ex.message
2388
-
2389
- self._process_sqlcode(sqlcode, message)
2390
-
2391
- def _send_direct_query_request(self):
2392
- self._rowcount = 0
2393
- statement = self._parsed_statement
2394
-
2395
- params = self._get_parameters()
2396
- sqlcode = 0
2397
- message = None
2398
- try:
2399
- self._result_set = self._sql.exec(statement, *params)
2400
- self._rowcount = self._result_set.ResultSet._ROWCOUNT
2401
- self._get_column_info()
2402
- except Exception as ex:
2403
- sqlcode = ex.sqlcode
2404
- message = ex.message
2405
- self._process_sqlcode(sqlcode, message)
2406
-
2407
- def _prepared_update_execute(self):
2408
- self._rowcount = 0
2409
- self._lastrowid = None
2410
- sets = self._parameter_sets or 1
2411
- metadata = self._statement.Statement._Metadata.parameters
2412
- param_types = [metadata.GetAt(i + 1).ODBCType for i in range(metadata.Size)]
2413
-
2414
- stream_chunk_size = 32000
2415
-
2416
- for i in range(sets):
2417
- params = self._get_parameters(i)
2418
- for ip, param in enumerate(params):
2419
- if param_types[ip] in (SQLType.LONGVARBINARY, SQLType.LONGVARCHAR):
2420
- stream_class = (
2421
- "%Stream.GlobalBinary"
2422
- if param_types[ip] == SQLType.LONGVARBINARY
2423
- else "%Stream.GlobalCharacter"
2424
- )
2425
- stream = self._iris.cls(stream_class)._New()
2426
- while param:
2427
- stream.Write(param[:stream_chunk_size])
2428
- param = param[stream_chunk_size:]
2429
- params[ip] = stream
2430
-
2431
- sqlcode = 0
2432
- message = None
2433
- try:
2434
- _result_set = self._statement.execute(*params)
2435
- self._rowcount += _result_set.ResultSet._ROWCOUNT
2436
- self._lastrowid = _result_set.ResultSet._ROWID
2437
- except Exception as ex:
2438
- sqlcode = ex.sqlcode
2439
- message = ex.message
2440
- self._process_sqlcode(sqlcode, message)
2441
-
2442
- def _send_direct_stored_procedure_request(self):
2443
- sqlproc = self._parsed_statement
2444
- self._rowcount = 0
2445
- params = self._get_parameters()
2446
- params_marks = ", ".join(["?"] * len(params))
2447
- statement = f"CALL {sqlproc} ({params_marks})"
2448
-
2449
- sqlcode = 0
2450
- message = None
2451
- try:
2452
- self._result_set = self._sql.exec(statement, *params)
2453
- self._rowcount = self._result_set.ResultSet._ROWCOUNT
2454
- self._get_column_info()
2455
- except Exception as ex:
2456
- sqlcode = ex.sqlcode
2457
- message = ex.message
2458
- self._process_sqlcode(sqlcode, message)
2459
-
2460
- @property
2461
- def rowcount(self):
2462
- return self._rowcount
2463
-
2464
- def fetchone(self):
2465
- if self._result_set == None:
2466
- raise InterfaceError(
2467
- "Either execute has not yet been called, or the previous call of execute did not return a result set"
2468
- )
2469
-
2470
- try:
2471
- values = self._result_set.__next__()
2472
- except:
2473
- return None
2474
-
2475
- values = [None if v == "" else "" if v == "\x00" else v for v in values]
2476
- row = namedtuple("Row", [col.name for col in self._columns], rename=True)
2477
-
2478
- _types = {
2479
- SQLType.GUID: uuid.UUID,
2480
- SQLType.BIGINT: int,
2481
- SQLType.BINARY: bytes,
2482
- SQLType.VARBINARY: bytes,
2483
- SQLType.BIT: bool,
2484
- SQLType.FLOAT: float,
2485
- SQLType.NUMERIC: decimal.Decimal,
2486
- SQLType.INTEGER: int,
2487
- SQLType.VARCHAR: str,
2488
- SQLType.LONGVARBINARY: IRISBinaryStream,
2489
- SQLType.LONGVARCHAR: IRISStream,
2490
- }
2491
-
2492
- if self._columns:
2493
- for _column in self._columns:
2494
- value = values[_column.slotPosition - 1]
2495
-
2496
- ctype = _column.type
2497
- value_type = _types[ctype] if ctype in _types else None
2498
- try:
2499
- if not _column.tableName and not _column.schema:
2500
- if type(value) == float:
2501
- value = decimal.Decimal(str(value))
2502
- elif value is None or value_type is None:
2503
- pass
2504
- elif value_type is bytes:
2505
- value = bytes(map(ord, value))
2506
- elif value_type is decimal.Decimal:
2507
- value = decimal.Decimal(str(value))
2508
- elif issubclass(value_type, IRISStream):
2509
- stream = value_type(self._connection, value, embedded=True)
2510
- value = stream.fetch()
2511
- elif not isinstance(value, value_type):
2512
- value = value_type(value)
2513
- except Exception as ex:
2514
- raise ex
2515
- pass
2516
- values[_column.slotPosition - 1] = value
2517
- return row(*values)
2518
-
2519
- def fetchall(self):
2520
- if self._result_set == None:
2521
- raise InterfaceError(
2522
- "Either execute has not yet been called, or the previous call of execute did not return a result set"
2523
- )
2524
-
2525
- rows = []
2526
- while True:
2527
- row = self.fetchone()
2528
- if not row:
2529
- break
2530
- rows.append(row)
2531
- return rows
2532
-
2533
- def fetchmany(self, size=None):
2534
- if self._result_set == None:
2535
- raise InterfaceError(
2536
- "Either execute has not yet been called, or the previous call of execute did not return a result set"
2537
- )
2538
-
2539
- if size is None:
2540
- size = self.arraysize
2541
-
2542
- rows = []
2543
- for i in range(size):
2544
- row = self.fetchone()
2545
- if row is None:
2546
- break
2547
- rows.append(row)
2548
- return rows
2549
-
2550
- def nextset(self):
2551
- raise NotImplementedErrorDBAPI()
2552
-
2553
-
2554
- # Type Objects
2555
- def Date(year, month, day):
2556
- raise NotImplementedErrorDBAPI()
2557
-
2558
-
2559
- def Time(hour, minutes, second):
2560
- raise NotImplementedErrorDBAPI()
2561
-
2562
-
2563
- def Timestamp(year, month, day, hour, minute, second):
2564
- raise NotImplementedErrorDBAPI()
2565
-
2566
-
2567
- def DateFromTicks(ticks):
2568
- raise NotImplementedErrorDBAPI()
2569
-
2570
-
2571
- def TimeFromTicks(ticks):
2572
- raise NotImplementedErrorDBAPI()
2573
-
2574
-
2575
- def TimestampFromTicks(ticks):
2576
- raise NotImplementedErrorDBAPI()
2577
-
2578
-
2579
- # def Binary(string):
2580
- # return string
2581
-
2582
- # Type definitions.
2583
- Binary = bytes
2584
-
2585
- STRING = str
2586
- BINARY = bytes
2587
- NUMBER = float
2588
- ROWID = str
2589
-
2590
- # still needs type singletons (?)
2591
-
2592
-
2593
- # Exception architecture
2594
- class Error(Exception):
2595
- pass
2596
-
2597
-
2598
- class Warning(Exception):
2599
- pass
2600
-
2601
-
2602
- class InterfaceError(Error):
2603
- pass
2604
-
2605
-
2606
- class DatabaseError(Error):
2607
- pass
2608
-
2609
-
2610
- class InternalError(DatabaseError):
2611
- pass
2612
-
2613
-
2614
- class OperationalError(DatabaseError):
2615
- pass
2616
-
2617
-
2618
- class ProgrammingError(DatabaseError):
2619
- pass
2620
-
2621
-
2622
- class IntegrityError(DatabaseError):
2623
- pass
2624
-
2625
-
2626
- class DataError(DatabaseError):
2627
- pass
2628
-
2629
-
2630
- class NotSupportedError(DatabaseError):
2631
- pass