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.
- intersystems_iris/_BufferReader.py +10 -0
- intersystems_iris/_BufferWriter.py +32 -0
- intersystems_iris/_ConnectionInformation.py +54 -0
- intersystems_iris/_ConnectionParameters.py +18 -0
- intersystems_iris/_Constant.py +38 -0
- intersystems_iris/_DBList.py +499 -0
- intersystems_iris/_Device.py +69 -0
- intersystems_iris/_GatewayContext.py +25 -0
- intersystems_iris/_GatewayException.py +4 -0
- intersystems_iris/_GatewayUtility.py +74 -0
- intersystems_iris/_IRIS.py +1294 -0
- intersystems_iris/_IRISConnection.py +516 -0
- intersystems_iris/_IRISEmbedded.py +85 -0
- intersystems_iris/_IRISGlobalNode.py +273 -0
- intersystems_iris/_IRISGlobalNodeView.py +25 -0
- intersystems_iris/_IRISIterator.py +143 -0
- intersystems_iris/_IRISList.py +360 -0
- intersystems_iris/_IRISNative.py +208 -0
- intersystems_iris/_IRISOREF.py +4 -0
- intersystems_iris/_IRISObject.py +424 -0
- intersystems_iris/_IRISReference.py +133 -0
- intersystems_iris/_InStream.py +149 -0
- intersystems_iris/_LegacyIterator.py +135 -0
- intersystems_iris/_ListItem.py +15 -0
- intersystems_iris/_ListReader.py +84 -0
- intersystems_iris/_ListWriter.py +157 -0
- intersystems_iris/_LogFileStream.py +115 -0
- intersystems_iris/_MessageHeader.py +51 -0
- intersystems_iris/_OutStream.py +25 -0
- intersystems_iris/_PrintStream.py +65 -0
- intersystems_iris/_PythonGateway.py +850 -0
- intersystems_iris/_SharedMemorySocket.py +87 -0
- intersystems_iris/__init__.py +79 -0
- intersystems_iris/__main__.py +7 -0
- intersystems_iris/dbapi/_Column.py +56 -0
- intersystems_iris/dbapi/_DBAPI.py +2295 -0
- intersystems_iris/dbapi/_Descriptor.py +46 -0
- intersystems_iris/dbapi/_IRISStream.py +63 -0
- intersystems_iris/dbapi/_Message.py +158 -0
- intersystems_iris/dbapi/_Parameter.py +138 -0
- intersystems_iris/dbapi/_ParameterCollection.py +133 -0
- intersystems_iris/dbapi/_ResultSetRow.py +314 -0
- intersystems_iris/dbapi/_SQLType.py +32 -0
- intersystems_iris/dbapi/__init__.py +0 -0
- intersystems_iris/dbapi/preparser/_PreParser.py +1658 -0
- intersystems_iris/dbapi/preparser/_Scanner.py +391 -0
- intersystems_iris/dbapi/preparser/_Token.py +81 -0
- intersystems_iris/dbapi/preparser/_TokenList.py +251 -0
- intersystems_iris/dbapi/preparser/__init__.py +0 -0
- intersystems_iris/pex/_BusinessHost.py +101 -0
- intersystems_iris/pex/_BusinessOperation.py +105 -0
- intersystems_iris/pex/_BusinessProcess.py +214 -0
- intersystems_iris/pex/_BusinessService.py +95 -0
- intersystems_iris/pex/_Common.py +228 -0
- intersystems_iris/pex/_Director.py +24 -0
- intersystems_iris/pex/_IRISBusinessOperation.py +5 -0
- intersystems_iris/pex/_IRISBusinessService.py +18 -0
- intersystems_iris/pex/_IRISInboundAdapter.py +5 -0
- intersystems_iris/pex/_IRISOutboundAdapter.py +17 -0
- intersystems_iris/pex/_InboundAdapter.py +57 -0
- intersystems_iris/pex/_Message.py +6 -0
- intersystems_iris/pex/_OutboundAdapter.py +46 -0
- intersystems_iris/pex/__init__.py +25 -0
- iris/__init__.py +25 -0
- iris/iris_site.py +13 -0
- iris/irisbuiltins.py +97 -0
- iris/irisloader.py +199 -0
- irisnative/_IRISNative.py +9 -0
- irisnative/__init__.py +10 -0
- {sqlalchemy_iris-0.5.0b3.dist-info → sqlalchemy_iris-0.6.0b1.dist-info}/METADATA +1 -1
- sqlalchemy_iris-0.6.0b1.dist-info/RECORD +83 -0
- sqlalchemy_iris-0.6.0b1.dist-info/top_level.txt +4 -0
- sqlalchemy_iris-0.5.0b3.dist-info/RECORD +0 -14
- sqlalchemy_iris-0.5.0b3.dist-info/top_level.txt +0 -1
- {sqlalchemy_iris-0.5.0b3.dist-info → sqlalchemy_iris-0.6.0b1.dist-info}/LICENSE +0 -0
- {sqlalchemy_iris-0.5.0b3.dist-info → sqlalchemy_iris-0.6.0b1.dist-info}/WHEEL +0 -0
- {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')
|