Skip to content

Commit 69fffb1

Browse files
Added dbapi module with dbapi-appliance unit tests
Co-authored-by: Denis Ignatenko <[email protected]>
1 parent bd37703 commit 69fffb1

13 files changed

+533
-26
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ sophia
1616

1717
# Vim Swap files
1818
*.sw[a-z]
19+
.idea

Diff for: .travis.yml

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ env:
1515
- OS=ubuntu DIST=trusty
1616
- OS=ubuntu DIST=xenial
1717
- OS=ubuntu DIST=bionic
18-
- OS=ubuntu DIST=disco
1918
- OS=debian DIST=jessie
2019
- OS=debian DIST=stretch
2120
- OS=debian DIST=buster

Diff for: appveyor.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ environment:
22
matrix:
33
- PYTHON: "C:\\Python27"
44
- PYTHON: "C:\\Python27-x64"
5-
- PYTHON: "C:\\Python34"
6-
- PYTHON: "C:\\Python34-x64"
75
- PYTHON: "C:\\Python35"
86
- PYTHON: "C:\\Python35-x64"
97
- PYTHON: "C:\\Python36"
108
- PYTHON: "C:\\Python36-x64"
119
- PYTHON: "C:\\Python37"
1210
- PYTHON: "C:\\Python37-x64"
11+
- PYTHON: "C:\\Python38"
12+
- PYTHON: "C:\\Python38-x64"
1313

1414
install:
1515
# install runtime dependencies
1616
- "%PYTHON%\\python.exe -m pip install -r requirements.txt"
1717
# install testing dependencies
18-
- "%PYTHON%\\python.exe -m pip install pyyaml"
18+
- "%PYTHON%\\python.exe -m pip install pyyaml dbapi-compliance==1.15.0"
1919

2020
build: off
2121

Diff for: tarantool/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,4 @@ def connectmesh(addrs=({'host': 'localhost', 'port': 3301},), user=None,
7575

7676
__all__ = ['connect', 'Connection', 'connectmesh', 'MeshConnection', 'Schema',
7777
'Error', 'DatabaseError', 'NetworkError', 'NetworkWarning',
78-
'SchemaError']
78+
'SchemaError', 'dbapi']

Diff for: tarantool/connection.py

+47-8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import ctypes
1313
import ctypes.util
14+
1415
try:
1516
from ctypes import c_ssize_t
1617
except ImportError:
@@ -34,7 +35,8 @@
3435
RequestSubscribe,
3536
RequestUpdate,
3637
RequestUpsert,
37-
RequestAuthenticate
38+
RequestAuthenticate,
39+
RequestExecute
3840
)
3941
from tarantool.space import Space
4042
from tarantool.const import (
@@ -49,11 +51,18 @@
4951
ITERATOR_ALL
5052
)
5153
from tarantool.error import (
54+
Error,
5255
NetworkError,
5356
DatabaseError,
5457
InterfaceError,
5558
SchemaError,
5659
NetworkWarning,
60+
OperationalError,
61+
DataError,
62+
IntegrityError,
63+
InternalError,
64+
ProgrammingError,
65+
NotSupportedError,
5766
SchemaReloadException,
5867
warn
5968
)
@@ -76,11 +85,20 @@ class Connection(object):
7685
Also this class provides low-level interface to data manipulation
7786
(insert/delete/update/select).
7887
'''
79-
Error = tarantool.error
88+
# DBAPI Extension: supply exceptions as attributes on the connection
89+
Error = Error
8090
DatabaseError = DatabaseError
8191
InterfaceError = InterfaceError
8292
SchemaError = SchemaError
8393
NetworkError = NetworkError
94+
Warning = Warning
95+
DataError = DataError
96+
OperationalError = OperationalError
97+
IntegrityError = IntegrityError
98+
InternalError = InternalError
99+
ProgrammingError = ProgrammingError
100+
NotSupportedError = NotSupportedError
101+
ImproperlyConfigured = Exception
84102

85103
def __init__(self, host, port,
86104
user=None,
@@ -91,6 +109,7 @@ def __init__(self, host, port,
91109
connect_now=True,
92110
encoding=ENCODING_DEFAULT,
93111
call_16=False,
112+
use_list=True,
94113
connection_timeout=CONNECTION_TIMEOUT):
95114
'''
96115
Initialize a connection to the server.
@@ -123,6 +142,7 @@ def __init__(self, host, port,
123142
self._socket = None
124143
self.connected = False
125144
self.error = True
145+
self.use_list = use_list
126146
self.encoding = encoding
127147
self.call_16 = call_16
128148
self.connection_timeout = connection_timeout
@@ -260,7 +280,7 @@ def _send_request_wo_reconnect(self, request):
260280
while True:
261281
try:
262282
self._socket.sendall(bytes(request))
263-
response = Response(self, self._read_response())
283+
response = Response(self, self._read_response(), self.use_list)
264284
break
265285
except SchemaReloadException as e:
266286
self.update_schema(e.schema_version)
@@ -292,13 +312,12 @@ def check(): # Check that connection is alive
292312
retbytes = self._sys_recv(sock_fd, buf, 1, flag)
293313

294314
err = 0
295-
if os.name!= 'nt':
315+
if os.name != 'nt':
296316
err = ctypes.get_errno()
297317
else:
298318
err = ctypes.get_last_error()
299319
self._socket.setblocking(True)
300320

301-
302321
WWSAEWOULDBLOCK = 10035
303322
if (retbytes < 0) and (err == errno.EAGAIN or
304323
err == errno.EWOULDBLOCK or
@@ -445,7 +464,7 @@ def _join_v16(self, server_uuid):
445464
self._socket.sendall(bytes(request))
446465

447466
while True:
448-
resp = Response(self, self._read_response())
467+
resp = Response(self, self._read_response(), self.use_list)
449468
yield resp
450469
if resp.code == REQUEST_TYPE_OK or resp.code >= REQUEST_TYPE_ERROR:
451470
return
@@ -459,7 +478,7 @@ class JoinState:
459478
self._socket.sendall(bytes(request))
460479
state = JoinState.Handshake
461480
while True:
462-
resp = Response(self, self._read_response())
481+
resp = Response(self, self._read_response(), self.use_list)
463482
yield resp
464483
if resp.code >= REQUEST_TYPE_ERROR:
465484
return
@@ -488,7 +507,7 @@ def subscribe(self, cluster_uuid, server_uuid, vclock=None):
488507
request = RequestSubscribe(self, cluster_uuid, server_uuid, vclock)
489508
self._socket.sendall(bytes(request))
490509
while True:
491-
resp = Response(self, self._read_response())
510+
resp = Response(self, self._read_response(), self.use_list)
492511
yield resp
493512
if resp.code >= REQUEST_TYPE_ERROR:
494513
return
@@ -785,3 +804,23 @@ def generate_sync(self):
785804
Need override for async io connection
786805
'''
787806
return 0
807+
808+
def execute(self, query, params=None):
809+
'''
810+
Execute SQL request.
811+
Execute SQL query in database.
812+
813+
:param query: SQL syntax query
814+
:type query: str
815+
816+
:param params: Bind values to use in query
817+
:type params: list, dict
818+
819+
:return: query result data
820+
:rtype: list
821+
'''
822+
if not params:
823+
params = []
824+
request = RequestExecute(self, query, params)
825+
response = self._send_request(request)
826+
return response

Diff for: tarantool/const.py

+7
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@
2929
#
3030
IPROTO_DATA = 0x30
3131
IPROTO_ERROR = 0x31
32+
#
33+
IPROTO_METADATA = 0x32
34+
IPROTO_SQL_TEXT = 0x40
35+
IPROTO_SQL_BIND = 0x41
36+
IPROTO_SQL_INFO = 0x42
37+
3238

3339
IPROTO_GREETING_SIZE = 128
3440
IPROTO_BODY_MAX_LEN = 2147483648
@@ -44,6 +50,7 @@
4450
REQUEST_TYPE_EVAL = 8
4551
REQUEST_TYPE_UPSERT = 9
4652
REQUEST_TYPE_CALL = 10
53+
REQUEST_TYPE_EXECUTE = 11
4754
REQUEST_TYPE_PING = 64
4855
REQUEST_TYPE_JOIN = 65
4956
REQUEST_TYPE_SUBSCRIBE = 66

0 commit comments

Comments
 (0)