6
6
from tarantool .error import InterfaceError
7
7
from .connection import Connection as BaseConnection
8
8
9
- update_insert_pattern = re .compile (r'^UPDATE|INSERT' )
9
+ update_insert_pattern = re .compile (r'^UPDATE|^ INSERT' , re . IGNORECASE )
10
10
11
11
12
12
class Cursor :
13
13
_lastrowid = 0
14
14
_rowcount = 0
15
15
description = None
16
16
position = 0
17
- arraysize = 200
17
+ arraysize = 1
18
18
autocommit = True
19
+ closed = False
19
20
20
21
def __init__ (self , connection ):
21
22
self ._c = connection
22
- self .rows = []
23
+ self .rows = None
23
24
24
25
def callproc (self , procname , * params ): # TODO
25
26
"""
@@ -48,6 +49,8 @@ def _convert_param(p):
48
49
return "NULL"
49
50
if isinstance (p , bool ):
50
51
return str (p )
52
+ if isinstance (p , str ):
53
+ return "'%s'" % p .replace ("'" , "''" )
51
54
return "'%s'" % p
52
55
53
56
@staticmethod
@@ -85,29 +88,37 @@ def execute(self, query, params=None):
85
88
86
89
Return values are not defined.
87
90
"""
91
+ if self .closed :
92
+ raise self ._c .ProgrammingError
88
93
if params :
89
94
query = query % tuple (
90
95
self ._convert_param (param ) for param in params )
91
96
92
97
response = self ._c .execute (query )
93
98
94
99
self .rows = tuple (response .body .values ())[1 ] if len (
95
- response .body ) > 1 else []
100
+ response .body ) > 1 else None
96
101
97
- if update_insert_pattern .match (query . upper () ):
102
+ if update_insert_pattern .match (query ):
98
103
try :
99
104
self ._rowcount = response .rowcount
100
105
except InterfaceError :
101
- self ._rowcount = 1
106
+ self ._rowcount = - 1
102
107
else :
103
- self ._rowcount = 1
108
+ self ._rowcount = - 1
104
109
105
110
if query .upper ().startswith ('INSERT' ):
106
111
self ._lastrowid = self ._extract_last_row_id (response .body )
107
112
return response
108
113
109
- def executemany (self , query , params ):
110
- return self .execute (query , params )
114
+ def executemany (self , query , param_sets ):
115
+ rowcounts = []
116
+ for params in param_sets :
117
+ self .execute (query , params )
118
+ rowcounts .append (self .rowcount )
119
+
120
+ self ._rowcount = - 1 if - 1 in rowcounts else sum (rowcounts )
121
+ return self
111
122
112
123
@property
113
124
def lastrowid (self ):
@@ -150,10 +161,11 @@ def fetchone(self):
150
161
An Error (or subclass) exception is raised if the previous call to
151
162
.execute*() did not produce any result set or no call was issued yet.
152
163
"""
153
-
164
+ if self .rows is None :
165
+ raise self ._c .Error
154
166
return self .fetchmany (1 )[0 ] if len (self .rows ) else None
155
167
156
- def fetchmany (self , size ):
168
+ def fetchmany (self , size = None ):
157
169
"""
158
170
Fetch the next set of rows of a query result, returning a sequence of
159
171
sequences (e.g. a list of tuples). An empty sequence is returned when
@@ -174,6 +186,11 @@ def fetchmany(self, size):
174
186
.arraysize attribute. If the size parameter is used, then it is best
175
187
for it to retain the same value from one .fetchmany() call to the next.
176
188
"""
189
+ size = size or self .arraysize
190
+
191
+ if self .rows is None :
192
+ raise self ._c .ProgrammingError
193
+
177
194
if len (self .rows ) < size :
178
195
items = self .rows
179
196
self .rows = []
@@ -190,6 +207,9 @@ def fetchall(self):
190
207
An Error (or subclass) exception is raised if the previous call to
191
208
.execute*() did not produce any result set or no call was issued yet.
192
209
"""
210
+ if self .rows is None :
211
+ raise self ._c .ProgrammingError
212
+
193
213
items = self .rows [:]
194
214
self .rows = []
195
215
return items
@@ -216,10 +236,17 @@ def setoutputsize(self, size, column=None):
216
236
217
237
class Connection (BaseConnection ):
218
238
_cursor = None
239
+ paramstyle = 'format'
240
+ apilevel = "2.0"
241
+ threadsafety = 0
219
242
220
243
server_version = 2
221
244
222
- def commit (self ): # TODO
245
+ def connect (self ):
246
+ super ().connect ()
247
+ return self
248
+
249
+ def commit (self ):
223
250
"""
224
251
Commit any pending transaction to the database.
225
252
@@ -230,6 +257,8 @@ def commit(self): # TODO
230
257
Database modules that do not support transactions should implement
231
258
this method with void functionality.
232
259
"""
260
+ if self ._socket is None :
261
+ raise self .ProgrammingError
233
262
234
263
def rollback (self ):
235
264
"""
@@ -238,6 +267,13 @@ def rollback(self):
238
267
Closing a connection without committing the changes first will cause
239
268
an implicit rollback to be performed.
240
269
"""
270
+ if self ._socket is None :
271
+ raise self .ProgrammingError
272
+
273
+ def execute (self , query , params = None ):
274
+ if self ._socket is None :
275
+ raise self .ProgrammingError
276
+ return super ().execute (query , params )
241
277
242
278
def close (self ):
243
279
"""
@@ -252,6 +288,8 @@ def close(self):
252
288
if self ._socket :
253
289
self ._socket .close ()
254
290
self ._socket = None
291
+ else :
292
+ raise self .ProgrammingError
255
293
256
294
def _set_cursor (self ):
257
295
self ._cursor = Cursor (self )
0 commit comments