23
23
24
24
import unittest
25
25
import unittest .mock
26
- import gc
27
26
import sqlite3 as sqlite
28
27
28
+ from test .support import gc_collect
29
+
30
+
29
31
def func_returntext ():
30
32
return "foo"
31
33
def func_returntextwithnull ():
@@ -45,22 +47,6 @@ def func_returnlonglong():
45
47
def func_raiseexception ():
46
48
5 / 0
47
49
48
- def func_isstring (v ):
49
- return type (v ) is str
50
- def func_isint (v ):
51
- return type (v ) is int
52
- def func_isfloat (v ):
53
- return type (v ) is float
54
- def func_isnone (v ):
55
- return type (v ) is type (None )
56
- def func_isblob (v ):
57
- return isinstance (v , (bytes , memoryview ))
58
- def func_islonglong (v ):
59
- return isinstance (v , int ) and v >= 1 << 31
60
-
61
- def func (* args ):
62
- return len (args )
63
-
64
50
class AggrNoStep :
65
51
def __init__ (self ):
66
52
pass
@@ -161,15 +147,13 @@ def setUp(self):
161
147
self .con .create_function ("returnnull" , 0 , func_returnnull )
162
148
self .con .create_function ("returnblob" , 0 , func_returnblob )
163
149
self .con .create_function ("returnlonglong" , 0 , func_returnlonglong )
150
+ self .con .create_function ("returnnan" , 0 , lambda : float ("nan" ))
151
+ self .con .create_function ("returntoolargeint" , 0 , lambda : 1 << 65 )
164
152
self .con .create_function ("raiseexception" , 0 , func_raiseexception )
165
153
166
- self .con .create_function ("isstring" , 1 , func_isstring )
167
- self .con .create_function ("isint" , 1 , func_isint )
168
- self .con .create_function ("isfloat" , 1 , func_isfloat )
169
- self .con .create_function ("isnone" , 1 , func_isnone )
170
- self .con .create_function ("isblob" , 1 , func_isblob )
171
- self .con .create_function ("islonglong" , 1 , func_islonglong )
172
- self .con .create_function ("spam" , - 1 , func )
154
+ self .con .create_function ("isblob" , 1 , lambda x : isinstance (x , bytes ))
155
+ self .con .create_function ("isnone" , 1 , lambda x : x is None )
156
+ self .con .create_function ("spam" , - 1 , lambda * x : len (x ))
173
157
self .con .execute ("create table test(t text)" )
174
158
175
159
def tearDown (self ):
@@ -246,51 +230,23 @@ def test_func_return_long_long(self):
246
230
val = cur .fetchone ()[0 ]
247
231
self .assertEqual (val , 1 << 31 )
248
232
233
+ def test_func_return_nan (self ):
234
+ cur = self .con .cursor ()
235
+ cur .execute ("select returnnan()" )
236
+ self .assertIsNone (cur .fetchone ()[0 ])
237
+
238
+ def test_func_return_too_large_int (self ):
239
+ cur = self .con .cursor ()
240
+ with self .assertRaises (sqlite .OperationalError ):
241
+ self .con .execute ("select returntoolargeint()" )
242
+
249
243
def test_func_exception (self ):
250
244
cur = self .con .cursor ()
251
245
with self .assertRaises (sqlite .OperationalError ) as cm :
252
246
cur .execute ("select raiseexception()" )
253
247
cur .fetchone ()
254
248
self .assertEqual (str (cm .exception ), 'user-defined function raised exception' )
255
249
256
- def test_param_string (self ):
257
- cur = self .con .cursor ()
258
- for text in ["foo" , str ()]:
259
- with self .subTest (text = text ):
260
- cur .execute ("select isstring(?)" , (text ,))
261
- val = cur .fetchone ()[0 ]
262
- self .assertEqual (val , 1 )
263
-
264
- def test_param_int (self ):
265
- cur = self .con .cursor ()
266
- cur .execute ("select isint(?)" , (42 ,))
267
- val = cur .fetchone ()[0 ]
268
- self .assertEqual (val , 1 )
269
-
270
- def test_param_float (self ):
271
- cur = self .con .cursor ()
272
- cur .execute ("select isfloat(?)" , (3.14 ,))
273
- val = cur .fetchone ()[0 ]
274
- self .assertEqual (val , 1 )
275
-
276
- def test_param_none (self ):
277
- cur = self .con .cursor ()
278
- cur .execute ("select isnone(?)" , (None ,))
279
- val = cur .fetchone ()[0 ]
280
- self .assertEqual (val , 1 )
281
-
282
- def test_param_blob (self ):
283
- cur = self .con .cursor ()
284
- cur .execute ("select isblob(?)" , (memoryview (b"blob" ),))
285
- val = cur .fetchone ()[0 ]
286
- self .assertEqual (val , 1 )
287
-
288
- def test_param_long_long (self ):
289
- cur = self .con .cursor ()
290
- cur .execute ("select islonglong(?)" , (1 << 42 ,))
291
- val = cur .fetchone ()[0 ]
292
- self .assertEqual (val , 1 )
293
-
294
250
def test_any_arguments (self ):
295
251
cur = self .con .cursor ()
296
252
cur .execute ("select spam(?, ?)" , (1 , 2 ))
@@ -301,6 +257,52 @@ def test_empty_blob(self):
301
257
cur = self .con .execute ("select isblob(x'')" )
302
258
self .assertTrue (cur .fetchone ()[0 ])
303
259
260
+ def test_nan_float (self ):
261
+ cur = self .con .execute ("select isnone(?)" , (float ("nan" ),))
262
+ # SQLite has no concept of nan; it is converted to NULL
263
+ self .assertTrue (cur .fetchone ()[0 ])
264
+
265
+ def test_too_large_int (self ):
266
+ err = "Python int too large to convert to SQLite INTEGER"
267
+ self .assertRaisesRegex (OverflowError , err , self .con .execute ,
268
+ "select spam(?)" , (1 << 65 ,))
269
+
270
+ def test_non_contiguous_blob (self ):
271
+ self .assertRaisesRegex (ValueError , "could not convert BLOB to buffer" ,
272
+ self .con .execute , "select spam(?)" ,
273
+ (memoryview (b"blob" )[::2 ],))
274
+
275
+ def test_param_surrogates (self ):
276
+ self .assertRaisesRegex (UnicodeEncodeError , "surrogates not allowed" ,
277
+ self .con .execute , "select spam(?)" ,
278
+ ("\ud803 \ude6d " ,))
279
+
280
+ def test_func_params (self ):
281
+ results = []
282
+ def append_result (arg ):
283
+ results .append ((arg , type (arg )))
284
+ self .con .create_function ("test_params" , 1 , append_result )
285
+
286
+ dataset = [
287
+ (42 , int ),
288
+ (- 1 , int ),
289
+ (1234567890123456789 , int ),
290
+ (4611686018427387905 , int ), # 63-bit int with non-zero low bits
291
+ (3.14 , float ),
292
+ (float ('inf' ), float ),
293
+ ("text" , str ),
294
+ ("1\x00 2" , str ),
295
+ ("\u02e2 q\u02e1 \u2071 \u1d57 \u1d49 " , str ),
296
+ (b"blob" , bytes ),
297
+ (bytearray (range (2 )), bytes ),
298
+ (memoryview (b"blob" ), bytes ),
299
+ (None , type (None )),
300
+ ]
301
+ for val , _ in dataset :
302
+ cur = self .con .execute ("select test_params(?)" , (val ,))
303
+ cur .fetchone ()
304
+ self .assertEqual (dataset , results )
305
+
304
306
# Regarding deterministic functions:
305
307
#
306
308
# Between 3.8.3 and 3.15.0, deterministic functions were only used to
@@ -356,7 +358,7 @@ def md5sum(t):
356
358
y .append (y )
357
359
358
360
del x ,y
359
- gc . collect ()
361
+ gc_collect ()
360
362
361
363
class AggregateTests (unittest .TestCase ):
362
364
def setUp (self ):
0 commit comments