@@ -44,22 +44,6 @@ def func_returnlonglong():
4444def func_raiseexception ():
4545 5 / 0
4646
47- def func_isstring (v ):
48- return type (v ) is str
49- def func_isint (v ):
50- return type (v ) is int
51- def func_isfloat (v ):
52- return type (v ) is float
53- def func_isnone (v ):
54- return type (v ) is type (None )
55- def func_isblob (v ):
56- return isinstance (v , (bytes , memoryview ))
57- def func_islonglong (v ):
58- return isinstance (v , int ) and v >= 1 << 31
59-
60- def func (* args ):
61- return len (args )
62-
6347class AggrNoStep :
6448 def __init__ (self ):
6549 pass
@@ -160,15 +144,13 @@ def setUp(self):
160144 self .con .create_function ("returnnull" , 0 , func_returnnull )
161145 self .con .create_function ("returnblob" , 0 , func_returnblob )
162146 self .con .create_function ("returnlonglong" , 0 , func_returnlonglong )
147+ self .con .create_function ("returnnan" , 0 , lambda : float ("nan" ))
148+ self .con .create_function ("returntoolargeint" , 0 , lambda : 1 << 65 )
163149 self .con .create_function ("raiseexception" , 0 , func_raiseexception )
164150
165- self .con .create_function ("isstring" , 1 , func_isstring )
166- self .con .create_function ("isint" , 1 , func_isint )
167- self .con .create_function ("isfloat" , 1 , func_isfloat )
168- self .con .create_function ("isnone" , 1 , func_isnone )
169- self .con .create_function ("isblob" , 1 , func_isblob )
170- self .con .create_function ("islonglong" , 1 , func_islonglong )
171- self .con .create_function ("spam" , - 1 , func )
151+ self .con .create_function ("isblob" , 1 , lambda x : isinstance (x , bytes ))
152+ self .con .create_function ("isnone" , 1 , lambda x : x is None )
153+ self .con .create_function ("spam" , - 1 , lambda * x : len (x ))
172154 self .con .execute ("create table test(t text)" )
173155
174156 def tearDown (self ):
@@ -245,57 +227,79 @@ def CheckFuncReturnLongLong(self):
245227 val = cur .fetchone ()[0 ]
246228 self .assertEqual (val , 1 << 31 )
247229
230+ def CheckFuncReturnNaN (self ):
231+ cur = self .con .cursor ()
232+ cur .execute ("select returnnan()" )
233+ self .assertIsNone (cur .fetchone ()[0 ])
234+
235+ def CheckFuncReturnTooLargeInt (self ):
236+ cur = self .con .cursor ()
237+ with self .assertRaises (sqlite .OperationalError ):
238+ self .con .execute ("select returntoolargeint()" )
239+
248240 def CheckFuncException (self ):
249241 cur = self .con .cursor ()
250242 with self .assertRaises (sqlite .OperationalError ) as cm :
251243 cur .execute ("select raiseexception()" )
252244 cur .fetchone ()
253245 self .assertEqual (str (cm .exception ), 'user-defined function raised exception' )
254246
255- def CheckParamString (self ):
256- cur = self .con .cursor ()
257- for text in ["foo" , str ()]:
258- with self .subTest (text = text ):
259- cur .execute ("select isstring(?)" , (text ,))
260- val = cur .fetchone ()[0 ]
261- self .assertEqual (val , 1 )
262-
263- def CheckParamInt (self ):
264- cur = self .con .cursor ()
265- cur .execute ("select isint(?)" , (42 ,))
266- val = cur .fetchone ()[0 ]
267- self .assertEqual (val , 1 )
268-
269- def CheckParamFloat (self ):
270- cur = self .con .cursor ()
271- cur .execute ("select isfloat(?)" , (3.14 ,))
272- val = cur .fetchone ()[0 ]
273- self .assertEqual (val , 1 )
274-
275- def CheckParamNone (self ):
276- cur = self .con .cursor ()
277- cur .execute ("select isnone(?)" , (None ,))
278- val = cur .fetchone ()[0 ]
279- self .assertEqual (val , 1 )
280-
281- def CheckParamBlob (self ):
282- cur = self .con .cursor ()
283- cur .execute ("select isblob(?)" , (memoryview (b"blob" ),))
284- val = cur .fetchone ()[0 ]
285- self .assertEqual (val , 1 )
286-
287- def CheckParamLongLong (self ):
288- cur = self .con .cursor ()
289- cur .execute ("select islonglong(?)" , (1 << 42 ,))
290- val = cur .fetchone ()[0 ]
291- self .assertEqual (val , 1 )
292-
293247 def CheckAnyArguments (self ):
294248 cur = self .con .cursor ()
295249 cur .execute ("select spam(?, ?)" , (1 , 2 ))
296250 val = cur .fetchone ()[0 ]
297251 self .assertEqual (val , 2 )
298252
253+ def CheckEmptyBlob (self ):
254+ cur = self .con .execute ("select isblob(x'')" )
255+ self .assertTrue (cur .fetchone ()[0 ])
256+
257+ def CheckNaNFloat (self ):
258+ cur = self .con .execute ("select isnone(?)" , (float ("nan" ),))
259+ # SQLite has no concept of nan; it is converted to NULL
260+ self .assertTrue (cur .fetchone ()[0 ])
261+
262+ def CheckTooLargeInt (self ):
263+ err = "Python int too large to convert to SQLite INTEGER"
264+ self .assertRaisesRegex (OverflowError , err , self .con .execute ,
265+ "select spam(?)" , (1 << 65 ,))
266+
267+ def CheckNonContiguousBlob (self ):
268+ self .assertRaisesRegex (ValueError , "could not convert BLOB to buffer" ,
269+ self .con .execute , "select spam(?)" ,
270+ (memoryview (b"blob" )[::2 ],))
271+
272+ def CheckParamSurrogates (self ):
273+ self .assertRaisesRegex (UnicodeEncodeError , "surrogates not allowed" ,
274+ self .con .execute , "select spam(?)" ,
275+ ("\ud803 \ude6d " ,))
276+
277+ def CheckFuncParams (self ):
278+ results = []
279+ def append_result (arg ):
280+ results .append ((arg , type (arg )))
281+ self .con .create_function ("test_params" , 1 , append_result )
282+
283+ dataset = [
284+ (42 , int ),
285+ (- 1 , int ),
286+ (1234567890123456789 , int ),
287+ (4611686018427387905 , int ), # 63-bit int with non-zero low bits
288+ (3.14 , float ),
289+ (float ('inf' ), float ),
290+ ("text" , str ),
291+ ("1\x00 2" , str ),
292+ ("\u02e2 q\u02e1 \u2071 \u1d57 \u1d49 " , str ),
293+ (b"blob" , bytes ),
294+ (bytearray (range (2 )), bytes ),
295+ (memoryview (b"blob" ), bytes ),
296+ (None , type (None )),
297+ ]
298+ for val , _ in dataset :
299+ cur = self .con .execute ("select test_params(?)" , (val ,))
300+ cur .fetchone ()
301+ self .assertEqual (dataset , results )
302+
299303 # Regarding deterministic functions:
300304 #
301305 # Between 3.8.3 and 3.15.0, deterministic functions were only used to
0 commit comments