sqlalchemy-iris 0.5.0b3__py3-none-any.whl → 0.6.0b1__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.
Files changed (77) hide show
  1. intersystems_iris/_BufferReader.py +10 -0
  2. intersystems_iris/_BufferWriter.py +32 -0
  3. intersystems_iris/_ConnectionInformation.py +54 -0
  4. intersystems_iris/_ConnectionParameters.py +18 -0
  5. intersystems_iris/_Constant.py +38 -0
  6. intersystems_iris/_DBList.py +499 -0
  7. intersystems_iris/_Device.py +69 -0
  8. intersystems_iris/_GatewayContext.py +25 -0
  9. intersystems_iris/_GatewayException.py +4 -0
  10. intersystems_iris/_GatewayUtility.py +74 -0
  11. intersystems_iris/_IRIS.py +1294 -0
  12. intersystems_iris/_IRISConnection.py +516 -0
  13. intersystems_iris/_IRISEmbedded.py +85 -0
  14. intersystems_iris/_IRISGlobalNode.py +273 -0
  15. intersystems_iris/_IRISGlobalNodeView.py +25 -0
  16. intersystems_iris/_IRISIterator.py +143 -0
  17. intersystems_iris/_IRISList.py +360 -0
  18. intersystems_iris/_IRISNative.py +208 -0
  19. intersystems_iris/_IRISOREF.py +4 -0
  20. intersystems_iris/_IRISObject.py +424 -0
  21. intersystems_iris/_IRISReference.py +133 -0
  22. intersystems_iris/_InStream.py +149 -0
  23. intersystems_iris/_LegacyIterator.py +135 -0
  24. intersystems_iris/_ListItem.py +15 -0
  25. intersystems_iris/_ListReader.py +84 -0
  26. intersystems_iris/_ListWriter.py +157 -0
  27. intersystems_iris/_LogFileStream.py +115 -0
  28. intersystems_iris/_MessageHeader.py +51 -0
  29. intersystems_iris/_OutStream.py +25 -0
  30. intersystems_iris/_PrintStream.py +65 -0
  31. intersystems_iris/_PythonGateway.py +850 -0
  32. intersystems_iris/_SharedMemorySocket.py +87 -0
  33. intersystems_iris/__init__.py +79 -0
  34. intersystems_iris/__main__.py +7 -0
  35. intersystems_iris/dbapi/_Column.py +56 -0
  36. intersystems_iris/dbapi/_DBAPI.py +2295 -0
  37. intersystems_iris/dbapi/_Descriptor.py +46 -0
  38. intersystems_iris/dbapi/_IRISStream.py +63 -0
  39. intersystems_iris/dbapi/_Message.py +158 -0
  40. intersystems_iris/dbapi/_Parameter.py +138 -0
  41. intersystems_iris/dbapi/_ParameterCollection.py +133 -0
  42. intersystems_iris/dbapi/_ResultSetRow.py +314 -0
  43. intersystems_iris/dbapi/_SQLType.py +32 -0
  44. intersystems_iris/dbapi/__init__.py +0 -0
  45. intersystems_iris/dbapi/preparser/_PreParser.py +1658 -0
  46. intersystems_iris/dbapi/preparser/_Scanner.py +391 -0
  47. intersystems_iris/dbapi/preparser/_Token.py +81 -0
  48. intersystems_iris/dbapi/preparser/_TokenList.py +251 -0
  49. intersystems_iris/dbapi/preparser/__init__.py +0 -0
  50. intersystems_iris/pex/_BusinessHost.py +101 -0
  51. intersystems_iris/pex/_BusinessOperation.py +105 -0
  52. intersystems_iris/pex/_BusinessProcess.py +214 -0
  53. intersystems_iris/pex/_BusinessService.py +95 -0
  54. intersystems_iris/pex/_Common.py +228 -0
  55. intersystems_iris/pex/_Director.py +24 -0
  56. intersystems_iris/pex/_IRISBusinessOperation.py +5 -0
  57. intersystems_iris/pex/_IRISBusinessService.py +18 -0
  58. intersystems_iris/pex/_IRISInboundAdapter.py +5 -0
  59. intersystems_iris/pex/_IRISOutboundAdapter.py +17 -0
  60. intersystems_iris/pex/_InboundAdapter.py +57 -0
  61. intersystems_iris/pex/_Message.py +6 -0
  62. intersystems_iris/pex/_OutboundAdapter.py +46 -0
  63. intersystems_iris/pex/__init__.py +25 -0
  64. iris/__init__.py +25 -0
  65. iris/iris_site.py +13 -0
  66. iris/irisbuiltins.py +97 -0
  67. iris/irisloader.py +199 -0
  68. irisnative/_IRISNative.py +9 -0
  69. irisnative/__init__.py +10 -0
  70. {sqlalchemy_iris-0.5.0b3.dist-info → sqlalchemy_iris-0.6.0b1.dist-info}/METADATA +1 -1
  71. sqlalchemy_iris-0.6.0b1.dist-info/RECORD +83 -0
  72. sqlalchemy_iris-0.6.0b1.dist-info/top_level.txt +4 -0
  73. sqlalchemy_iris-0.5.0b3.dist-info/RECORD +0 -14
  74. sqlalchemy_iris-0.5.0b3.dist-info/top_level.txt +0 -1
  75. {sqlalchemy_iris-0.5.0b3.dist-info → sqlalchemy_iris-0.6.0b1.dist-info}/LICENSE +0 -0
  76. {sqlalchemy_iris-0.5.0b3.dist-info → sqlalchemy_iris-0.6.0b1.dist-info}/WHEEL +0 -0
  77. {sqlalchemy_iris-0.5.0b3.dist-info → sqlalchemy_iris-0.6.0b1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,516 @@
1
+ import base64
2
+ import enum
3
+ import getpass
4
+ import os
5
+ import platform
6
+ import socket
7
+ import struct
8
+ import sys
9
+ import threading
10
+ import ssl
11
+ import intersystems_iris._ConnectionInformation
12
+ import intersystems_iris._ConnectionParameters
13
+ import intersystems_iris._Constant
14
+ import intersystems_iris._Device
15
+ import intersystems_iris._GatewayException
16
+ import intersystems_iris._IRISOREF
17
+ import intersystems_iris._InStream
18
+ import intersystems_iris._LogFileStream
19
+ import intersystems_iris._OutStream
20
+ import intersystems_iris._PythonGateway
21
+ import intersystems_iris._IRIS
22
+ import intersystems_iris._IRISObject
23
+ import intersystems_iris.dbapi
24
+
25
+ class Feature():
26
+ optionNone = 0
27
+ optionFastSelect = 1
28
+ optionFastInsert = 2
29
+ optionRedirectOutput = 32
30
+ optionAllowedOptions = optionRedirectOutput
31
+ optionDefaultOptions = optionRedirectOutput
32
+
33
+ class _IRISConnection():
34
+ '''
35
+ A connection to an IRIS instance.
36
+
37
+ Create one by calling the iris.createConnection method. The hostname, port, namespace, timeout, and logfile from the last successful connection attempt are saved as properties of the connection object.
38
+ '''
39
+
40
+ CLOSED_PROXY_UPDATE_THRESHOLD = 100
41
+ MESSAGE_HANDSHAKE = b'HS'
42
+ MESSAGE_CONNECT = b'CN'
43
+ MESSAGE_DISCONNECT = b'DC'
44
+
45
+ def __init__(self):
46
+ self._connection_info = intersystems_iris._ConnectionInformation._ConnectionInformation()
47
+ self._connection_params = intersystems_iris._ConnectionParameters._ConnectionParameters()
48
+ self._sequence_number = -1
49
+ self._statement_id = 0
50
+ self._lock = threading.RLock()
51
+ self._lock_closed_oref = threading.RLock()
52
+ self._disable_output_redirect = False
53
+ self._oref_registry = {}
54
+ self._oref_to_class_map = {}
55
+ self._iris_object_proxy_map = {}
56
+ self._iris_object_proxy_closed = []
57
+ self._pre_preparse_cache = {}
58
+ self._preparedCache = {}
59
+ self._autoCommit = True
60
+ self._device = None
61
+ self._gateways = {}
62
+ self._log_stream = None
63
+ self._output_redirect_handler = None
64
+
65
+
66
+ def __enter__(self):
67
+ return self
68
+
69
+ def __exit__(self, type, value, traceback):
70
+ self.close()
71
+
72
+ def __del__(self):
73
+ try:
74
+ self.close()
75
+ except:
76
+ pass
77
+ return
78
+
79
+ @property
80
+ def hostname(self):
81
+ return self._connection_params.hostname
82
+
83
+ @property
84
+ def port(self):
85
+ return self._connection_params.port
86
+
87
+ @property
88
+ def namespace(self):
89
+ return self._connection_params.namespace
90
+
91
+ @property
92
+ def timeout(self):
93
+ return self._connection_params.timeout
94
+
95
+ @property
96
+ def sharedmemory(self):
97
+ return self._connection_params.sharedmemory
98
+
99
+ @property
100
+ def logfile(self):
101
+ return self._connection_params.logfile
102
+
103
+ @property
104
+ def compact_double(self):
105
+ return self._connection_info._compact_double
106
+
107
+ def _is_using_sharedmemory(self):
108
+ return self._device.is_sharedmemory()
109
+
110
+ def close(self):
111
+ '''
112
+ Close the connection to the IRIS instance if it is open.
113
+
114
+ close()
115
+
116
+ Do nothing if the connection is already closed.
117
+
118
+ Return Value
119
+ ------------
120
+ None.
121
+ '''
122
+ if self._device != None:
123
+ with self._lock:
124
+ try:
125
+ self._out_message.wire._write_header(intersystems_iris.IRISConnection.MESSAGE_DISCONNECT)
126
+ self._out_message._send(0)
127
+ except Exception as e:
128
+ pass
129
+ self._preparedCache = {}
130
+ self._device.close()
131
+ self._device = None
132
+ return
133
+
134
+ def isClosed(self):
135
+ '''
136
+ Return True if the connection is closed.
137
+
138
+ isClosed()
139
+
140
+ Returns
141
+ -------
142
+ bool
143
+ True if the connection is closed,
144
+ False if it is open.
145
+ '''
146
+ return self._device == None
147
+
148
+ def isUsingSharedMemory(self):
149
+ '''
150
+ Return True if the connection is open and using shared memory.
151
+
152
+ isUsingSharedMemory()
153
+
154
+ Returns
155
+ -------
156
+ bool
157
+ True if the connection has an open shared memory connection,
158
+ False otherwise.
159
+ '''
160
+ return self._device.is_sharedmemory()
161
+
162
+ def _set_gateway(self, gateway):
163
+ thread_id = threading.get_ident()
164
+ self._gateways[thread_id] = gateway
165
+ return
166
+
167
+ def _get_gateway(self):
168
+ thread_id = threading.get_ident()
169
+ if thread_id not in self._gateways.keys():
170
+ self._gateways[thread_id] = intersystems_iris._PythonGateway._PythonGateway(self, None, None, None)
171
+ return self._gateways[thread_id]
172
+
173
+ def _connect(
174
+ self,
175
+ hostname,
176
+ port,
177
+ namespace,
178
+ username,
179
+ password,
180
+ timeout,
181
+ sharedmemory,
182
+ logfile,
183
+ sslcontext,
184
+ autoCommit,
185
+ isolationLevel,
186
+ featureOptions,
187
+ application_name=None,
188
+ ):
189
+ if type(hostname) != str or len(hostname) == 0:
190
+ raise ValueError("invalid hostname: non-empty string required")
191
+ if type(port) != int or port == 0:
192
+ raise ValueError("invalid port: non-zero integer required")
193
+ if type(namespace) != str or len(namespace) == 0:
194
+ raise ValueError("invalid namespace: non-empty string required")
195
+ if ((featureOptions & ~intersystems_iris._IRISConnection.Feature.optionAllowedOptions) != 0):
196
+ raise ValueError("invalid featureOptions value specified: " + str(featureOptions))
197
+ try:
198
+ self._log_stream = intersystems_iris._LogFileStream._LogFileStream(logfile) if len(logfile)>0 else None
199
+ with self._lock:
200
+ server_address = (hostname, port)
201
+ self._device = intersystems_iris._Device._Device(self, None, sslcontext)
202
+ self._device.settimeout(timeout)
203
+ self._device.connect(server_address)
204
+ self._in_message = intersystems_iris._InStream._InStream(self)
205
+ self._out_message = intersystems_iris._OutStream._OutStream(self)
206
+ # send MESSAGE_HANDSHAKE message
207
+ self._out_message.wire._write_header(intersystems_iris.IRISConnection.MESSAGE_HANDSHAKE)
208
+ protocol_bytes = struct.pack("<H",intersystems_iris._Constant._Constant.PROTOCOL_VERSION)
209
+ self._out_message.wire._set_raw_bytes(protocol_bytes)
210
+ sequence_number = self._get_new_sequence_number()
211
+ self._out_message._send(sequence_number)
212
+ self._in_message._read_message_sql(sequence_number)
213
+ protocol_bytes = self._in_message.wire._get_raw_bytes(2)
214
+ protocol = struct.unpack("<H", protocol_bytes)[0]
215
+ if protocol<61:
216
+ raise Exception("connection failed: IRIS xDBC protocol is not compatible")
217
+ self._connection_info.protocol_version = protocol
218
+ featureBits = struct.unpack("<H", self._in_message.wire._get_raw_bytes(2))[0]
219
+ self._connection_info._is_unicode = (featureBits & 1) > 0
220
+ self._connection_info._compact_double = (protocol >= 65) and (featureBits & 2) > 0
221
+ self._connection_info._set_server_locale(self._in_message.wire._get())
222
+ self._out_message.wire._set_connection_info(self._connection_info)
223
+ # send MESSAGE_CONNECT message
224
+ self._out_message.wire._write_header(intersystems_iris.IRISConnection.MESSAGE_CONNECT)
225
+ # namespace
226
+ self._out_message.wire._set(namespace)
227
+ # encoded username
228
+ if self._connection_info._is_unicode:
229
+ username_encoded = self.__encodew(username)
230
+ else:
231
+ username_encoded = self.__encode(username)
232
+ self._out_message.wire._set(username_encoded)
233
+ # encoded password
234
+ if self._connection_info._is_unicode:
235
+ password_encoded = self.__encodew(password)
236
+ else:
237
+ password_encoded = self.__encode(password)
238
+ self._out_message.wire._set(password_encoded)
239
+ # OS username
240
+ osuser = getpass.getuser()
241
+ self._out_message.wire._set(osuser)
242
+ # machine hostname
243
+ thishostname = self._device.gethostname()
244
+ self._out_message.wire._set(thishostname)
245
+ # application name
246
+ appname = application_name or os.path.basename(__file__)
247
+ self._out_message.wire._set(appname)
248
+ # machine OS Info, not used anymore
249
+ osinfo = bytearray(12)
250
+ self._out_message.wire._set(osinfo)
251
+ # temporarily disable shared-memory
252
+ sharedmemory = False
253
+ # HostName or IP for licensing
254
+ if (sharedmemory):
255
+ self._out_message.wire._set("SHM|||||")
256
+ else:
257
+ thishostIP = self._device.gethostbyname(hostname)
258
+ self._out_message.wire._set(thishostIP)
259
+ # EventClass -> null for now
260
+ self._out_message.wire._set("")
261
+ # Autocommit
262
+ if autoCommit:
263
+ self._out_message.wire._set(1)
264
+ else:
265
+ self._out_message.wire._set(2)
266
+ # Isolation Level
267
+ self._out_message.wire._set(isolationLevel)
268
+ # Feature Option
269
+ self._out_message.wire._set(featureOptions)
270
+ sequence_number = self._get_new_sequence_number()
271
+ self._out_message._send(sequence_number)
272
+ code = self._in_message._read_message_sql(sequence_number)
273
+ if code != 0:
274
+ raise Exception(self._in_message.wire._get())
275
+ self._connection_info._parse_server_version(self._in_message.wire._get())
276
+ self._connection_info._delimited_ids = self._in_message.wire._get()
277
+ self._in_message.wire._get() # ignore
278
+ isolationLevel = self._in_message.wire._get()
279
+ self._connection_info._server_job_number = self._in_message.wire._get()
280
+ sqlEmptyString = self._in_message.wire._get()
281
+ featureOptions = self._in_message.wire._get()
282
+ self._device.settimeout(None)
283
+ if(sharedmemory):
284
+ self._device.establishSHMSocket()
285
+ self._connection_params.hostname = hostname
286
+ self._connection_params.port = port
287
+ self._connection_params.namespace = namespace
288
+ self._connection_params.timeout = timeout
289
+ self._connection_params.sharedmemory = sharedmemory
290
+ self._connection_params.logfile = logfile
291
+ self._connection_params.sslcontext = sslcontext
292
+ self._autoCommit = autoCommit
293
+ self._connection_params.isolationLevel = isolationLevel
294
+ self._connection_params.featureOptions = featureOptions
295
+ except ssl.SSLError:
296
+ # To ensure security, replace any ssl error messages with a generic error
297
+ self._device.close()
298
+ self._device = None
299
+ raise ssl.SSLError(1, "Error establishing SSL connection")
300
+ except Exception as e:
301
+ if self._device != None:
302
+ self._device.close()
303
+ self._device = None
304
+ raise e
305
+ return
306
+
307
+ # Encodes the given Unicode string
308
+ def __encodew(self, input_data):
309
+ length = len(input_data)
310
+ out_char = [None] * length
311
+ i = 0
312
+ while length > 0:
313
+ length -= 1
314
+ tint2 = ord(input_data[i])
315
+ tint = (((ord(input_data[i]) ^ 0xA7) & 255) + length) & 255
316
+ out_char[length] = chr((tint2 & (255<<8)) | (((tint << 5) | (tint >> 3)) & 255))
317
+ i += 1
318
+ if i == 0:
319
+ return None
320
+ return ''.join(out_char)
321
+
322
+ # Encodes the given Multi Byte string
323
+ def __encode(self, input_data):
324
+ length = len(input_data)
325
+ out = [None] * length
326
+ i = 0
327
+ while length > 0:
328
+ length -= 1
329
+ tint = (((ord(input_data[i]) ^ 0xA7) & 255) + length) & 255
330
+ tmp = (tint << 5) | (tint >> 3)
331
+ tmp = tmp.to_bytes((tmp.bit_length() + 7) // 8, byteorder='little', signed=True)[0]
332
+ out[length] = tmp
333
+ i += 1
334
+ return bytes(out)
335
+
336
+ # this method should only be called when the connection is locked
337
+ def _get_new_sequence_number(self):
338
+ self._sequence_number += 2
339
+ return self._sequence_number
340
+
341
+ # this method should only be called when the connection is locked
342
+ def _get_new_statement_id(self):
343
+ self._statement_id += 1
344
+ return self._statement_id
345
+
346
+ def _oref_registry_lookup(self, object):
347
+ for key in self._oref_registry:
348
+ if self._oref_registry[key] == object:
349
+ return key
350
+ for key in self._iris_object_proxy_map:
351
+ if self._iris_object_proxy_map[key]() == object:
352
+ return key
353
+ return None
354
+
355
+ def _map_local_object_to_oref(self, caller_in_message, caller_out_message, object):
356
+ class_name = "%Net.Remote.Object"
357
+ with self._lock:
358
+ sequence_number = self._get_new_sequence_number()
359
+ caller_out_message.wire._write_header(intersystems_iris._Constant._Constant.MESSAGE_CREATE_OBJECT)
360
+ caller_out_message.wire._set(1)
361
+ caller_out_message.wire._set(class_name)
362
+ caller_out_message._send(sequence_number)
363
+ caller_in_message._read_message_gateway(sequence_number)
364
+ oref = caller_in_message.wire._get()._oref
365
+ if oref == "error":
366
+ raise Exception(caller_in_message.wire._get())
367
+ self._oref_registry[oref] = object
368
+ self._oref_to_class_map[oref] = type(object).__name__
369
+ with self._lock_closed_oref:
370
+ self._iris_object_proxy_closed.append(oref)
371
+ return oref
372
+
373
+ def _map_local_object_from_oref(self, oref):
374
+ created_proxy = False
375
+ obj = self._oref_registry.get(oref)
376
+ if obj == None:
377
+ weak = self._iris_object_proxy_map.get(oref)
378
+ if weak != None:
379
+ obj = weak()
380
+ if obj == None:
381
+ obj = intersystems_iris.IRISObject(self, oref)
382
+ created_proxy = True
383
+ if not created_proxy:
384
+ with self._lock_closed_oref:
385
+ self._iris_object_proxy_closed.append(oref)
386
+ return obj
387
+
388
+ def _close_unused_oref(self, oref):
389
+ with self._lock_closed_oref:
390
+ self._iris_object_proxy_closed.append(oref)
391
+
392
+ def _get_closed_iris_objects(self):
393
+ with self._lock_closed_oref:
394
+ closed_iris_objects = self._iris_object_proxy_closed
395
+ self._iris_object_proxy_closed = []
396
+ return ",".join(closed_iris_objects)
397
+
398
+ def releaseIRISObjects(self):
399
+ '''
400
+ Immediately release proxy references on IRISObject proxy objects that have been closed.
401
+
402
+ Proxy references are references on OREFs taken out on behave of IRISObject objects. Once an IRISObject is closed, the proxy reference will be released, but that process usually doesn't happen immediately.
403
+
404
+ Calling releaseIRISObjects will cause all the proxy references of already-closed proxy objects to be release, which can lead to closing of OREFs if no other references exist in the IRIS process.
405
+ '''
406
+ native = intersystems_iris.IRIS(self)
407
+ native._release_closed_iris_object(True)
408
+ return
409
+
410
+ def _get_parameter_listream(self, caller_in_message, caller_out_message, oref, instance):
411
+ if oref.endswith("@%Library.ListOfDataTypes") or oref.endswith("@%Library.ListOfObjects"):
412
+ if type(instance) != list:
413
+ raise intersystems_iris._GatewayException._GatewayException("Object is not a list")
414
+ with self._lock:
415
+ caller_out_message.wire._write_header(intersystems_iris._Constant._Constant.MESSAGE_GET_LIST)
416
+ caller_out_message.wire._set(oref)
417
+ sequence_number = self._get_new_sequence_number()
418
+ caller_out_message._send(sequence_number)
419
+ code = caller_in_message._read_message_gateway(sequence_number)
420
+ response = caller_in_message.wire._get()
421
+ if response == "error":
422
+ raise intersystems_iris._GatewayException._GatewayException(caller_in_message.wire._get())
423
+ size = caller_in_message.wire._get()
424
+ for i in range(size):
425
+ if i>= len(instance):
426
+ break
427
+ value = caller_in_message.wire._get()
428
+ if isinstance(value, intersystems_iris._IRISOREF._IRISOREF):
429
+ value = self._map_local_object_from_oref(value._oref)
430
+ instance[i] = value
431
+ return
432
+ if oref.endswith("@%Library.GlobalBinaryStream"):
433
+ if type(instance) != bytearray:
434
+ raise intersystems_iris._GatewayException._GatewayException("Object is not a bytearray")
435
+ with self._lock:
436
+ caller_out_message.wire._write_header(intersystems_iris._Constant._Constant.MESSAGE_GET_STREAM)
437
+ caller_out_message.wire._set(oref)
438
+ sequence_number = self._get_new_sequence_number()
439
+ caller_out_message._send(sequence_number)
440
+ code = caller_in_message._read_message_gateway(sequence_number)
441
+ response = caller_in_message.wire._get()
442
+ if response == "error":
443
+ raise intersystems_iris._GatewayException._GatewayException(caller_in_message.wire._get())
444
+ size = caller_in_message.wire._get()
445
+ pointer = 0
446
+ buffer_size = len(instance)
447
+ while (size>0):
448
+ chunk_string = caller_in_message.wire._get()
449
+ chunk_bytes = bytes(chunk_string, self._connection_info._locale)
450
+ chunk_size = len(chunk_bytes)
451
+ if pointer+chunk_size>buffer_size:
452
+ chunk_size = buffer_size-pointer
453
+ instance[pointer:pointer+chunk_size] = chunk_bytes[0:chunk_size]
454
+ pointer += chunk_size
455
+ size -= chunk_size
456
+ if pointer >= buffer_size:
457
+ break
458
+ return
459
+ raise intersystems_iris._GatewayException._GatewayException("Invalid argument for %setall(1): " + str(oref))
460
+
461
+ def setOutputRedirectHandler(self, class_name, method_name):
462
+ class_object = self._get_gateway()._load_class(class_name)
463
+ self._output_redirect_handler = getattr(class_object, method_name)
464
+
465
+ def _cache_prepared_statement(self, prepared_statement):
466
+ self._preparedCache[prepared_statement.statement] = prepared_statement
467
+
468
+ def _isFastSelectOption(self):
469
+ return bool(self._connection_params.featureOptions & intersystems_iris._IRISConnection.Feature.optionFastSelect)
470
+
471
+ def _isFastInsertOption(self):
472
+ return bool(self._connection_params.featureOptions & intersystems_iris._IRISConnection.Feature.optionFastInsert)
473
+
474
+ def _isFastOption(self):
475
+ return self._isFastSelectOption() or self._isFastInsertOption()
476
+
477
+ def cursor(self):
478
+ if self.isClosed():
479
+ raise intersystems_iris.dbapi._DBAPI.InterfaceError("Connection is closed")
480
+ return intersystems_iris.dbapi._DBAPI.Cursor(self)
481
+
482
+ def commit(self):
483
+ with self._lock:
484
+ self._out_message.wire._write_header(intersystems_iris.dbapi._Message.COMMIT)
485
+ sequence_number = self._get_new_sequence_number()
486
+ self._out_message._send(sequence_number)
487
+ self._in_message._read_message_sql(sequence_number, -1, 0, [0])
488
+
489
+ def rollback(self):
490
+ with self._lock:
491
+ self._out_message.wire._write_header(intersystems_iris.dbapi._Message.ROLLBACK)
492
+ sequence_number = self._get_new_sequence_number()
493
+ self._out_message._send(sequence_number)
494
+ self._in_message._read_message_sql(sequence_number, -1, 0, [0])
495
+
496
+ def setAutoCommit(self, enableAutoCommit):
497
+ self._autoCommit = enableAutoCommit
498
+ code = intersystems_iris.dbapi._Message.AUTOCOMMIT_ON if enableAutoCommit else intersystems_iris.dbapi._Message.AUTOCOMMIT_OFF
499
+ with self._lock:
500
+ self._out_message.wire._write_header(code)
501
+ sequence_number = self._get_new_sequence_number()
502
+ self._out_message._send(sequence_number)
503
+
504
+ def _add_pre_preparse_cache(self, sql, cursor):
505
+ preparse_cache_size = 50 # this variable is in ConnectionParameters class of Java and is hardcoded to this value
506
+ if len(self._pre_preparse_cache) < preparse_cache_size:
507
+ if cursor._exec_params == None:
508
+ self._pre_preparse_cache[sql] = CachedSQL(cursor)
509
+
510
+ class CachedSQL:
511
+ def __init__(self, cursor):
512
+ self._has_return_value = cursor._has_return_value
513
+ self._statementType = cursor._statementType
514
+ self._parsed_statement = cursor._parsed_statement
515
+ self._params = intersystems_iris.dbapi._ParameterCollection._ParameterCollection(cursor._params, False)
516
+ self._paramInfo = cursor._paramInfo
@@ -0,0 +1,85 @@
1
+ import os
2
+ import intersystems_iris.dbapi._DBAPI as dbapi
3
+ from intersystems_iris._IRISConnection import CachedSQL
4
+ from intersystems_iris._ConnectionInformation import _ConnectionInformation
5
+
6
+ def set_var(var, value):
7
+ old = os.environ[var] if var in os.environ else None
8
+ os.environ[var] = value
9
+ return old
10
+
11
+ def setup_vars(username, password, namespace):
12
+ vars = {}
13
+ if username:
14
+ vars['IRISUSERNAME'] = set_var('IRISUSERNAME', username)
15
+ if password:
16
+ vars['IRISPASSWORD'] = set_var('IRISPASSWORD', password)
17
+ if namespace:
18
+ vars['IRISNAMESPACE'] = set_var('IRISNAMESPACE', namespace)
19
+ return vars
20
+
21
+ def reset_vars(vars):
22
+ for var in vars:
23
+ if vars[var] is None:
24
+ del os.environ[var]
25
+ else:
26
+ os.environ[var] = vars[var]
27
+
28
+ class _IRISEmbedded:
29
+ def __init__(self) -> None:
30
+ self._connection_info = _ConnectionInformation()
31
+ self._pre_preparse_cache = {}
32
+ self._preparedCache = {}
33
+
34
+ def connect(
35
+ self,
36
+ hostname=None,
37
+ port=None,
38
+ namespace=None,
39
+ username=None,
40
+ password=None,
41
+ autoCommit=None,
42
+ isolationLevel=None,
43
+ **kw
44
+ ):
45
+ current_vars = setup_vars(username, password, namespace)
46
+ try:
47
+ import iris
48
+ except:
49
+ raise dbapi.OperationalError('Not able to connect to IRIS')
50
+ finally:
51
+ reset_vars(current_vars)
52
+ self.iris = iris
53
+ self._connection_info._delimited_ids = 1
54
+ self.restore_autocommit = iris.system.SQL.SetAutoCommit(0 if autoCommit is None else 1 if autoCommit else 2)
55
+
56
+ def __enter__(self):
57
+ return self
58
+
59
+ def __exit__(self, type, value, traceback):
60
+ self.close()
61
+
62
+ def close(self):
63
+ self.iris.system.SQL.SetAutoCommit(self.restore_autocommit)
64
+ self.iris = None
65
+
66
+ def isClosed(self):
67
+ return self.iris is None
68
+
69
+ def cursor(self):
70
+ return dbapi.EmbdeddedCursor(self)
71
+
72
+ def _add_pre_preparse_cache(self, sql, cursor):
73
+ preparse_cache_size = 50 # this variable is in ConnectionParameters class of Java and is hardcoded to this value
74
+ if len(self._pre_preparse_cache) < preparse_cache_size:
75
+ if cursor._exec_params == None:
76
+ self._pre_preparse_cache[sql] = CachedSQL(cursor)
77
+
78
+ def setAutoCommit(self, autoCommit):
79
+ return self.iris.system.SQL.SetAutoCommit(0 if autoCommit is None else 1 if autoCommit else 2)
80
+
81
+ def commit(self):
82
+ self.iris.sql.exec('commit')
83
+
84
+ def rollback(self):
85
+ self.iris.sql.exec('rollback')