2323
2424import unittest
2525import unittest .mock
26- import gc
2726import sqlite3 as sqlite
2827
28+ from test .support import gc_collect
29+
30+
2931def func_returntext ():
3032 return "foo"
3133def func_returntextwithnull ():
@@ -45,22 +47,6 @@ def func_returnlonglong():
4547def func_raiseexception ():
4648 5 / 0
4749
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-
6450class AggrNoStep :
6551 def __init__ (self ):
6652 pass
@@ -161,15 +147,13 @@ def setUp(self):
161147 self .con .create_function ("returnnull" , 0 , func_returnnull )
162148 self .con .create_function ("returnblob" , 0 , func_returnblob )
163149 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 )
164152 self .con .create_function ("raiseexception" , 0 , func_raiseexception )
165153
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 ))
173157 self .con .execute ("create table test(t text)" )
174158
175159 def tearDown (self ):
@@ -246,51 +230,23 @@ def test_func_return_long_long(self):
246230 val = cur .fetchone ()[0 ]
247231 self .assertEqual (val , 1 << 31 )
248232
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+
249243 def test_func_exception (self ):
250244 cur = self .con .cursor ()
251245 with self .assertRaises (sqlite .OperationalError ) as cm :
252246 cur .execute ("select raiseexception()" )
253247 cur .fetchone ()
254248 self .assertEqual (str (cm .exception ), 'user-defined function raised exception' )
255249
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-
294250 def test_any_arguments (self ):
295251 cur = self .con .cursor ()
296252 cur .execute ("select spam(?, ?)" , (1 , 2 ))
@@ -301,6 +257,52 @@ def test_empty_blob(self):
301257 cur = self .con .execute ("select isblob(x'')" )
302258 self .assertTrue (cur .fetchone ()[0 ])
303259
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+
304306 # Regarding deterministic functions:
305307 #
306308 # Between 3.8.3 and 3.15.0, deterministic functions were only used to
@@ -356,7 +358,7 @@ def md5sum(t):
356358 y .append (y )
357359
358360 del x ,y
359- gc . collect ()
361+ gc_collect ()
360362
361363class AggregateTests (unittest .TestCase ):
362364 def setUp (self ):
0 commit comments