2323
2424import contextlib
2525import functools
26- import gc
2726import io
2827import re
2928import sys
3029import unittest
3130import unittest .mock
3231import sqlite3 as sqlite
3332
34- from test .support import bigmemtest , catch_unraisable_exception
33+ from test .support import bigmemtest , catch_unraisable_exception , gc_collect
34+
3535from test .test_sqlite3 .test_dbapi import cx_limit
3636
3737
@@ -94,22 +94,6 @@ def func_memoryerror():
9494def func_overflowerror ():
9595 raise OverflowError
9696
97- def func_isstring (v ):
98- return type (v ) is str
99- def func_isint (v ):
100- return type (v ) is int
101- def func_isfloat (v ):
102- return type (v ) is float
103- def func_isnone (v ):
104- return type (v ) is type (None )
105- def func_isblob (v ):
106- return isinstance (v , (bytes , memoryview ))
107- def func_islonglong (v ):
108- return isinstance (v , int ) and v >= 1 << 31
109-
110- def func (* args ):
111- return len (args )
112-
11397class AggrNoStep :
11498 def __init__ (self ):
11599 pass
@@ -210,17 +194,15 @@ def setUp(self):
210194 self .con .create_function ("returnnull" , 0 , func_returnnull )
211195 self .con .create_function ("returnblob" , 0 , func_returnblob )
212196 self .con .create_function ("returnlonglong" , 0 , func_returnlonglong )
197+ self .con .create_function ("returnnan" , 0 , lambda : float ("nan" ))
198+ self .con .create_function ("returntoolargeint" , 0 , lambda : 1 << 65 )
213199 self .con .create_function ("raiseexception" , 0 , func_raiseexception )
214200 self .con .create_function ("memoryerror" , 0 , func_memoryerror )
215201 self .con .create_function ("overflowerror" , 0 , func_overflowerror )
216202
217- self .con .create_function ("isstring" , 1 , func_isstring )
218- self .con .create_function ("isint" , 1 , func_isint )
219- self .con .create_function ("isfloat" , 1 , func_isfloat )
220- self .con .create_function ("isnone" , 1 , func_isnone )
221- self .con .create_function ("isblob" , 1 , func_isblob )
222- self .con .create_function ("islonglong" , 1 , func_islonglong )
223- self .con .create_function ("spam" , - 1 , func )
203+ self .con .create_function ("isblob" , 1 , lambda x : isinstance (x , bytes ))
204+ self .con .create_function ("isnone" , 1 , lambda x : x is None )
205+ self .con .create_function ("spam" , - 1 , lambda * x : len (x ))
224206 self .con .execute ("create table test(t text)" )
225207
226208 def tearDown (self ):
@@ -305,6 +287,16 @@ def test_func_return_long_long(self):
305287 val = cur .fetchone ()[0 ]
306288 self .assertEqual (val , 1 << 31 )
307289
290+ def test_func_return_nan (self ):
291+ cur = self .con .cursor ()
292+ cur .execute ("select returnnan()" )
293+ self .assertIsNone (cur .fetchone ()[0 ])
294+
295+ def test_func_return_too_large_int (self ):
296+ cur = self .con .cursor ()
297+ self .assertRaisesRegex (sqlite .DataError , "string or blob too big" ,
298+ self .con .execute , "select returntoolargeint()" )
299+
308300 @with_tracebacks (ZeroDivisionError , name = "func_raiseexception" )
309301 def test_func_exception (self ):
310302 cur = self .con .cursor ()
@@ -327,44 +319,6 @@ def test_func_overflow_error(self):
327319 cur .execute ("select overflowerror()" )
328320 cur .fetchone ()
329321
330- def test_param_string (self ):
331- cur = self .con .cursor ()
332- for text in ["foo" , str ()]:
333- with self .subTest (text = text ):
334- cur .execute ("select isstring(?)" , (text ,))
335- val = cur .fetchone ()[0 ]
336- self .assertEqual (val , 1 )
337-
338- def test_param_int (self ):
339- cur = self .con .cursor ()
340- cur .execute ("select isint(?)" , (42 ,))
341- val = cur .fetchone ()[0 ]
342- self .assertEqual (val , 1 )
343-
344- def test_param_float (self ):
345- cur = self .con .cursor ()
346- cur .execute ("select isfloat(?)" , (3.14 ,))
347- val = cur .fetchone ()[0 ]
348- self .assertEqual (val , 1 )
349-
350- def test_param_none (self ):
351- cur = self .con .cursor ()
352- cur .execute ("select isnone(?)" , (None ,))
353- val = cur .fetchone ()[0 ]
354- self .assertEqual (val , 1 )
355-
356- def test_param_blob (self ):
357- cur = self .con .cursor ()
358- cur .execute ("select isblob(?)" , (memoryview (b"blob" ),))
359- val = cur .fetchone ()[0 ]
360- self .assertEqual (val , 1 )
361-
362- def test_param_long_long (self ):
363- cur = self .con .cursor ()
364- cur .execute ("select islonglong(?)" , (1 << 42 ,))
365- val = cur .fetchone ()[0 ]
366- self .assertEqual (val , 1 )
367-
368322 def test_any_arguments (self ):
369323 cur = self .con .cursor ()
370324 cur .execute ("select spam(?, ?)" , (1 , 2 ))
@@ -375,6 +329,52 @@ def test_empty_blob(self):
375329 cur = self .con .execute ("select isblob(x'')" )
376330 self .assertTrue (cur .fetchone ()[0 ])
377331
332+ def test_nan_float (self ):
333+ cur = self .con .execute ("select isnone(?)" , (float ("nan" ),))
334+ # SQLite has no concept of nan; it is converted to NULL
335+ self .assertTrue (cur .fetchone ()[0 ])
336+
337+ def test_too_large_int (self ):
338+ err = "Python int too large to convert to SQLite INTEGER"
339+ self .assertRaisesRegex (OverflowError , err , self .con .execute ,
340+ "select spam(?)" , (1 << 65 ,))
341+
342+ def test_non_contiguous_blob (self ):
343+ self .assertRaisesRegex (ValueError , "could not convert BLOB to buffer" ,
344+ self .con .execute , "select spam(?)" ,
345+ (memoryview (b"blob" )[::2 ],))
346+
347+ def test_param_surrogates (self ):
348+ self .assertRaisesRegex (UnicodeEncodeError , "surrogates not allowed" ,
349+ self .con .execute , "select spam(?)" ,
350+ ("\ud803 \ude6d " ,))
351+
352+ def test_func_params (self ):
353+ results = []
354+ def append_result (arg ):
355+ results .append ((arg , type (arg )))
356+ self .con .create_function ("test_params" , 1 , append_result )
357+
358+ dataset = [
359+ (42 , int ),
360+ (- 1 , int ),
361+ (1234567890123456789 , int ),
362+ (4611686018427387905 , int ), # 63-bit int with non-zero low bits
363+ (3.14 , float ),
364+ (float ('inf' ), float ),
365+ ("text" , str ),
366+ ("1\x00 2" , str ),
367+ ("\u02e2 q\u02e1 \u2071 \u1d57 \u1d49 " , str ),
368+ (b"blob" , bytes ),
369+ (bytearray (range (2 )), bytes ),
370+ (memoryview (b"blob" ), bytes ),
371+ (None , type (None )),
372+ ]
373+ for val , _ in dataset :
374+ cur = self .con .execute ("select test_params(?)" , (val ,))
375+ cur .fetchone ()
376+ self .assertEqual (dataset , results )
377+
378378 # Regarding deterministic functions:
379379 #
380380 # Between 3.8.3 and 3.15.0, deterministic functions were only used to
@@ -430,7 +430,7 @@ def md5sum(t):
430430 y .append (y )
431431
432432 del x ,y
433- gc . collect ()
433+ gc_collect ()
434434
435435 @with_tracebacks (OverflowError )
436436 def test_func_return_too_large_int (self ):
0 commit comments