blob: 6f57d1911b24d8cceeefe7d77b3f754f857bc0b8 [file] [log] [blame]
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001# pysqlite2/test/userfunctions.py: tests for user-defined functions and
2# aggregates.
3#
Erlend Egeberg Aaslandc610d972020-05-29 01:27:31 +02004# Copyright (C) 2005-2007 Gerhard Häring <gh@ghaering.de>
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005#
6# This file is part of pysqlite.
7#
8# This software is provided 'as-is', without any express or implied
9# warranty. In no event will the authors be held liable for any damages
10# arising from the use of this software.
11#
12# Permission is granted to anyone to use this software for any purpose,
13# including commercial applications, and to alter it and redistribute it
14# freely, subject to the following restrictions:
15#
16# 1. The origin of this software must not be misrepresented; you must not
17# claim that you wrote the original software. If you use this software
18# in a product, an acknowledgment in the product documentation would be
19# appreciated but is not required.
20# 2. Altered source versions must be plainly marked as such, and must not be
21# misrepresented as being the original software.
22# 3. This notice may not be removed or altered from any source distribution.
23
24import unittest
Sergey Fedoseev08308582018-07-08 12:09:20 +050025import unittest.mock
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000026import sqlite3 as sqlite
27
28def func_returntext():
29 return "foo"
30def func_returnunicode():
Guido van Rossumef87d6e2007-05-02 19:09:54 +000031 return "bar"
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000032def func_returnint():
33 return 42
34def func_returnfloat():
35 return 3.14
36def func_returnnull():
37 return None
38def func_returnblob():
Guido van Rossumbae07c92007-10-08 02:46:15 +000039 return b"blob"
Petri Lehtinen4fe85ab2012-02-19 21:38:00 +020040def func_returnlonglong():
41 return 1<<31
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000042def func_raiseexception():
43 5/0
44
45def func_isstring(v):
Guido van Rossumef87d6e2007-05-02 19:09:54 +000046 return type(v) is str
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000047def func_isint(v):
48 return type(v) is int
49def func_isfloat(v):
50 return type(v) is float
51def func_isnone(v):
52 return type(v) is type(None)
53def func_isblob(v):
Guido van Rossumbae07c92007-10-08 02:46:15 +000054 return isinstance(v, (bytes, memoryview))
Petri Lehtinen4fe85ab2012-02-19 21:38:00 +020055def func_islonglong(v):
56 return isinstance(v, int) and v >= 1<<31
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000057
Berker Peksagfa0f62d2016-03-27 22:39:14 +030058def func(*args):
59 return len(args)
60
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000061class AggrNoStep:
62 def __init__(self):
63 pass
64
Thomas Wouters0e3f5912006-08-11 14:57:12 +000065 def finalize(self):
66 return 1
67
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000068class AggrNoFinalize:
69 def __init__(self):
70 pass
71
72 def step(self, x):
73 pass
74
75class AggrExceptionInInit:
76 def __init__(self):
77 5/0
78
79 def step(self, x):
80 pass
81
82 def finalize(self):
83 pass
84
85class AggrExceptionInStep:
86 def __init__(self):
87 pass
88
89 def step(self, x):
90 5/0
91
92 def finalize(self):
93 return 42
94
95class AggrExceptionInFinalize:
96 def __init__(self):
97 pass
98
99 def step(self, x):
100 pass
101
102 def finalize(self):
103 5/0
104
105class AggrCheckType:
106 def __init__(self):
107 self.val = None
108
109 def step(self, whichType, val):
Guido van Rossumbae07c92007-10-08 02:46:15 +0000110 theType = {"str": str, "int": int, "float": float, "None": type(None),
111 "blob": bytes}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000112 self.val = int(theType[whichType] is type(val))
113
114 def finalize(self):
115 return self.val
116
Berker Peksagfa0f62d2016-03-27 22:39:14 +0300117class AggrCheckTypes:
118 def __init__(self):
119 self.val = 0
120
121 def step(self, whichType, *vals):
122 theType = {"str": str, "int": int, "float": float, "None": type(None),
123 "blob": bytes}
124 for val in vals:
125 self.val += int(theType[whichType] is type(val))
126
127 def finalize(self):
128 return self.val
129
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000130class AggrSum:
131 def __init__(self):
132 self.val = 0.0
133
134 def step(self, val):
135 self.val += val
136
137 def finalize(self):
138 return self.val
139
140class FunctionTests(unittest.TestCase):
141 def setUp(self):
142 self.con = sqlite.connect(":memory:")
143
144 self.con.create_function("returntext", 0, func_returntext)
145 self.con.create_function("returnunicode", 0, func_returnunicode)
146 self.con.create_function("returnint", 0, func_returnint)
147 self.con.create_function("returnfloat", 0, func_returnfloat)
148 self.con.create_function("returnnull", 0, func_returnnull)
149 self.con.create_function("returnblob", 0, func_returnblob)
Petri Lehtinen4fe85ab2012-02-19 21:38:00 +0200150 self.con.create_function("returnlonglong", 0, func_returnlonglong)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000151 self.con.create_function("raiseexception", 0, func_raiseexception)
152
153 self.con.create_function("isstring", 1, func_isstring)
154 self.con.create_function("isint", 1, func_isint)
155 self.con.create_function("isfloat", 1, func_isfloat)
156 self.con.create_function("isnone", 1, func_isnone)
157 self.con.create_function("isblob", 1, func_isblob)
Petri Lehtinen4fe85ab2012-02-19 21:38:00 +0200158 self.con.create_function("islonglong", 1, func_islonglong)
Berker Peksagfa0f62d2016-03-27 22:39:14 +0300159 self.con.create_function("spam", -1, func)
Erlend Egeberg Aaslandc610d972020-05-29 01:27:31 +0200160 self.con.execute("create table test(t text)")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000161
162 def tearDown(self):
163 self.con.close()
164
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100165 def test_func_error_on_create(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300166 with self.assertRaises(sqlite.OperationalError):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000167 self.con.create_function("bla", -100, lambda x: 2*x)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000168
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100169 def test_func_ref_count(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000170 def getfunc():
171 def f():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000172 return 1
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000173 return f
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000174 f = getfunc()
175 globals()["foo"] = f
176 # self.con.create_function("reftest", 0, getfunc())
177 self.con.create_function("reftest", 0, f)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000178 cur = self.con.cursor()
179 cur.execute("select reftest()")
180
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100181 def test_func_return_text(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000182 cur = self.con.cursor()
183 cur.execute("select returntext()")
184 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000185 self.assertEqual(type(val), str)
186 self.assertEqual(val, "foo")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000187
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100188 def test_func_return_unicode(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000189 cur = self.con.cursor()
190 cur.execute("select returnunicode()")
191 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000192 self.assertEqual(type(val), str)
193 self.assertEqual(val, "bar")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000194
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100195 def test_func_return_int(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000196 cur = self.con.cursor()
197 cur.execute("select returnint()")
198 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000199 self.assertEqual(type(val), int)
200 self.assertEqual(val, 42)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000201
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100202 def test_func_return_float(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000203 cur = self.con.cursor()
204 cur.execute("select returnfloat()")
205 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000206 self.assertEqual(type(val), float)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000207 if val < 3.139 or val > 3.141:
208 self.fail("wrong value")
209
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100210 def test_func_return_null(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000211 cur = self.con.cursor()
212 cur.execute("select returnnull()")
213 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000214 self.assertEqual(type(val), type(None))
215 self.assertEqual(val, None)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000216
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100217 def test_func_return_blob(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000218 cur = self.con.cursor()
219 cur.execute("select returnblob()")
220 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000221 self.assertEqual(type(val), bytes)
222 self.assertEqual(val, b"blob")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000223
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100224 def test_func_return_long_long(self):
Petri Lehtinen4fe85ab2012-02-19 21:38:00 +0200225 cur = self.con.cursor()
226 cur.execute("select returnlonglong()")
227 val = cur.fetchone()[0]
228 self.assertEqual(val, 1<<31)
229
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100230 def test_func_exception(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000231 cur = self.con.cursor()
Berker Peksag1003b342016-06-12 22:34:49 +0300232 with self.assertRaises(sqlite.OperationalError) as cm:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000233 cur.execute("select raiseexception()")
234 cur.fetchone()
Berker Peksag1003b342016-06-12 22:34:49 +0300235 self.assertEqual(str(cm.exception), 'user-defined function raised exception')
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000236
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100237 def test_param_string(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000238 cur = self.con.cursor()
Miss Islington (bot)067d6d42021-06-04 11:54:39 -0700239 for text in ["foo", str()]:
240 with self.subTest(text=text):
241 cur.execute("select isstring(?)", (text,))
242 val = cur.fetchone()[0]
243 self.assertEqual(val, 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000244
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100245 def test_param_int(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000246 cur = self.con.cursor()
247 cur.execute("select isint(?)", (42,))
248 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000249 self.assertEqual(val, 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000250
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100251 def test_param_float(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000252 cur = self.con.cursor()
253 cur.execute("select isfloat(?)", (3.14,))
254 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000255 self.assertEqual(val, 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000256
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100257 def test_param_none(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000258 cur = self.con.cursor()
259 cur.execute("select isnone(?)", (None,))
260 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000261 self.assertEqual(val, 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000262
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100263 def test_param_blob(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000264 cur = self.con.cursor()
Guido van Rossumbae07c92007-10-08 02:46:15 +0000265 cur.execute("select isblob(?)", (memoryview(b"blob"),))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000266 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000267 self.assertEqual(val, 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000268
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100269 def test_param_long_long(self):
Petri Lehtinen4fe85ab2012-02-19 21:38:00 +0200270 cur = self.con.cursor()
271 cur.execute("select islonglong(?)", (1<<42,))
272 val = cur.fetchone()[0]
273 self.assertEqual(val, 1)
274
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100275 def test_any_arguments(self):
Berker Peksagfa0f62d2016-03-27 22:39:14 +0300276 cur = self.con.cursor()
277 cur.execute("select spam(?, ?)", (1, 2))
278 val = cur.fetchone()[0]
279 self.assertEqual(val, 2)
280
Erlend Egeberg Aasland5cb601f2021-04-14 23:09:11 +0200281 def test_empty_blob(self):
282 cur = self.con.execute("select isblob(x'')")
283 self.assertTrue(cur.fetchone()[0])
284
Erlend Egeberg Aaslandc610d972020-05-29 01:27:31 +0200285 # Regarding deterministic functions:
286 #
287 # Between 3.8.3 and 3.15.0, deterministic functions were only used to
288 # optimize inner loops, so for those versions we can only test if the
289 # sqlite machinery has factored out a call or not. From 3.15.0 and onward,
290 # deterministic functions were permitted in WHERE clauses of partial
291 # indices, which allows testing based on syntax, iso. the query optimizer.
292 @unittest.skipIf(sqlite.sqlite_version_info < (3, 8, 3), "Requires SQLite 3.8.3 or higher")
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100293 def test_func_non_deterministic(self):
Sergey Fedoseev08308582018-07-08 12:09:20 +0500294 mock = unittest.mock.Mock(return_value=None)
Erlend Egeberg Aaslandc610d972020-05-29 01:27:31 +0200295 self.con.create_function("nondeterministic", 0, mock, deterministic=False)
296 if sqlite.sqlite_version_info < (3, 15, 0):
297 self.con.execute("select nondeterministic() = nondeterministic()")
298 self.assertEqual(mock.call_count, 2)
299 else:
300 with self.assertRaises(sqlite.OperationalError):
301 self.con.execute("create index t on test(t) where nondeterministic() is not null")
Sergey Fedoseev08308582018-07-08 12:09:20 +0500302
Erlend Egeberg Aaslandc610d972020-05-29 01:27:31 +0200303 @unittest.skipIf(sqlite.sqlite_version_info < (3, 8, 3), "Requires SQLite 3.8.3 or higher")
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100304 def test_func_deterministic(self):
Sergey Fedoseev08308582018-07-08 12:09:20 +0500305 mock = unittest.mock.Mock(return_value=None)
306 self.con.create_function("deterministic", 0, mock, deterministic=True)
Erlend Egeberg Aaslandc610d972020-05-29 01:27:31 +0200307 if sqlite.sqlite_version_info < (3, 15, 0):
308 self.con.execute("select deterministic() = deterministic()")
309 self.assertEqual(mock.call_count, 1)
310 else:
311 try:
312 self.con.execute("create index t on test(t) where deterministic() is not null")
313 except sqlite.OperationalError:
314 self.fail("Unexpected failure while creating partial index")
Sergey Fedoseev08308582018-07-08 12:09:20 +0500315
316 @unittest.skipIf(sqlite.sqlite_version_info >= (3, 8, 3), "SQLite < 3.8.3 needed")
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100317 def test_func_deterministic_not_supported(self):
Sergey Fedoseev08308582018-07-08 12:09:20 +0500318 with self.assertRaises(sqlite.NotSupportedError):
319 self.con.create_function("deterministic", 0, int, deterministic=True)
320
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100321 def test_func_deterministic_keyword_only(self):
Sergey Fedoseev08308582018-07-08 12:09:20 +0500322 with self.assertRaises(TypeError):
323 self.con.create_function("deterministic", 0, int, True)
324
Berker Peksagfa0f62d2016-03-27 22:39:14 +0300325
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000326class AggregateTests(unittest.TestCase):
327 def setUp(self):
328 self.con = sqlite.connect(":memory:")
329 cur = self.con.cursor()
330 cur.execute("""
331 create table test(
332 t text,
333 i integer,
334 f float,
335 n,
336 b blob
337 )
338 """)
339 cur.execute("insert into test(t, i, f, n, b) values (?, ?, ?, ?, ?)",
Guido van Rossumbae07c92007-10-08 02:46:15 +0000340 ("foo", 5, 3.14, None, memoryview(b"blob"),))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000341
342 self.con.create_aggregate("nostep", 1, AggrNoStep)
343 self.con.create_aggregate("nofinalize", 1, AggrNoFinalize)
344 self.con.create_aggregate("excInit", 1, AggrExceptionInInit)
345 self.con.create_aggregate("excStep", 1, AggrExceptionInStep)
346 self.con.create_aggregate("excFinalize", 1, AggrExceptionInFinalize)
347 self.con.create_aggregate("checkType", 2, AggrCheckType)
Berker Peksagfa0f62d2016-03-27 22:39:14 +0300348 self.con.create_aggregate("checkTypes", -1, AggrCheckTypes)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000349 self.con.create_aggregate("mysum", 1, AggrSum)
350
351 def tearDown(self):
352 #self.cur.close()
353 #self.con.close()
354 pass
355
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100356 def test_aggr_error_on_create(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300357 with self.assertRaises(sqlite.OperationalError):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000358 self.con.create_function("bla", -100, AggrSum)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000359
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100360 def test_aggr_no_step(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000361 cur = self.con.cursor()
Berker Peksag1003b342016-06-12 22:34:49 +0300362 with self.assertRaises(AttributeError) as cm:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000363 cur.execute("select nostep(t) from test")
Berker Peksag1003b342016-06-12 22:34:49 +0300364 self.assertEqual(str(cm.exception), "'AggrNoStep' object has no attribute 'step'")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000365
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100366 def test_aggr_no_finalize(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000367 cur = self.con.cursor()
Berker Peksag1003b342016-06-12 22:34:49 +0300368 with self.assertRaises(sqlite.OperationalError) as cm:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000369 cur.execute("select nofinalize(t) from test")
370 val = cur.fetchone()[0]
Berker Peksag1003b342016-06-12 22:34:49 +0300371 self.assertEqual(str(cm.exception), "user-defined aggregate's 'finalize' method raised error")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000372
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100373 def test_aggr_exception_in_init(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000374 cur = self.con.cursor()
Berker Peksag1003b342016-06-12 22:34:49 +0300375 with self.assertRaises(sqlite.OperationalError) as cm:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000376 cur.execute("select excInit(t) from test")
377 val = cur.fetchone()[0]
Berker Peksag1003b342016-06-12 22:34:49 +0300378 self.assertEqual(str(cm.exception), "user-defined aggregate's '__init__' method raised error")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000379
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100380 def test_aggr_exception_in_step(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000381 cur = self.con.cursor()
Berker Peksag1003b342016-06-12 22:34:49 +0300382 with self.assertRaises(sqlite.OperationalError) as cm:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000383 cur.execute("select excStep(t) from test")
384 val = cur.fetchone()[0]
Berker Peksag1003b342016-06-12 22:34:49 +0300385 self.assertEqual(str(cm.exception), "user-defined aggregate's 'step' method raised error")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000386
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100387 def test_aggr_exception_in_finalize(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000388 cur = self.con.cursor()
Berker Peksag1003b342016-06-12 22:34:49 +0300389 with self.assertRaises(sqlite.OperationalError) as cm:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000390 cur.execute("select excFinalize(t) from test")
391 val = cur.fetchone()[0]
Berker Peksag1003b342016-06-12 22:34:49 +0300392 self.assertEqual(str(cm.exception), "user-defined aggregate's 'finalize' method raised error")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000393
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100394 def test_aggr_check_param_str(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000395 cur = self.con.cursor()
Miss Islington (bot)067d6d42021-06-04 11:54:39 -0700396 cur.execute("select checkTypes('str', ?, ?)", ("foo", str()))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000397 val = cur.fetchone()[0]
Miss Islington (bot)067d6d42021-06-04 11:54:39 -0700398 self.assertEqual(val, 2)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000399
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100400 def test_aggr_check_param_int(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000401 cur = self.con.cursor()
402 cur.execute("select checkType('int', ?)", (42,))
403 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000404 self.assertEqual(val, 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000405
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100406 def test_aggr_check_params_int(self):
Berker Peksagfa0f62d2016-03-27 22:39:14 +0300407 cur = self.con.cursor()
408 cur.execute("select checkTypes('int', ?, ?)", (42, 24))
409 val = cur.fetchone()[0]
410 self.assertEqual(val, 2)
411
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100412 def test_aggr_check_param_float(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000413 cur = self.con.cursor()
414 cur.execute("select checkType('float', ?)", (3.14,))
415 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000416 self.assertEqual(val, 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000417
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100418 def test_aggr_check_param_none(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000419 cur = self.con.cursor()
420 cur.execute("select checkType('None', ?)", (None,))
421 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000422 self.assertEqual(val, 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000423
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100424 def test_aggr_check_param_blob(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000425 cur = self.con.cursor()
Guido van Rossumbae07c92007-10-08 02:46:15 +0000426 cur.execute("select checkType('blob', ?)", (memoryview(b"blob"),))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000427 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000428 self.assertEqual(val, 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000429
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100430 def test_aggr_check_aggr_sum(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000431 cur = self.con.cursor()
432 cur.execute("delete from test")
433 cur.executemany("insert into test(i) values (?)", [(10,), (20,), (30,)])
434 cur.execute("select mysum(i) from test")
435 val = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000436 self.assertEqual(val, 60)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000437
Erlend Egeberg Aasland979b23c2021-02-19 12:20:32 +0100438 def test_aggr_no_match(self):
439 cur = self.con.execute("select mysum(i) from (select 1 as i) where i == 0")
440 val = cur.fetchone()[0]
441 self.assertIsNone(val)
442
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000443class AuthorizerTests(unittest.TestCase):
Serhiy Storchaka3cf96ac2013-02-07 17:01:47 +0200444 @staticmethod
445 def authorizer_cb(action, arg1, arg2, dbname, source):
446 if action != sqlite.SQLITE_SELECT:
447 return sqlite.SQLITE_DENY
448 if arg2 == 'c2' or arg1 == 't2':
449 return sqlite.SQLITE_DENY
450 return sqlite.SQLITE_OK
451
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000452 def setUp(self):
453 self.con = sqlite.connect(":memory:")
454 self.con.executescript("""
455 create table t1 (c1, c2);
456 create table t2 (c1, c2);
457 insert into t1 (c1, c2) values (1, 2);
458 insert into t2 (c1, c2) values (4, 5);
459 """)
460
461 # For our security test:
462 self.con.execute("select c2 from t2")
463
Serhiy Storchaka3cf96ac2013-02-07 17:01:47 +0200464 self.con.set_authorizer(self.authorizer_cb)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000465
466 def tearDown(self):
467 pass
468
Serhiy Storchaka3cf96ac2013-02-07 17:01:47 +0200469 def test_table_access(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300470 with self.assertRaises(sqlite.DatabaseError) as cm:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000471 self.con.execute("select * from t2")
Berker Peksag1003b342016-06-12 22:34:49 +0300472 self.assertIn('prohibited', str(cm.exception))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000473
Serhiy Storchaka3cf96ac2013-02-07 17:01:47 +0200474 def test_column_access(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300475 with self.assertRaises(sqlite.DatabaseError) as cm:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000476 self.con.execute("select c2 from t1")
Berker Peksag1003b342016-06-12 22:34:49 +0300477 self.assertIn('prohibited', str(cm.exception))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000478
Serhiy Storchaka3cf96ac2013-02-07 17:01:47 +0200479class AuthorizerRaiseExceptionTests(AuthorizerTests):
480 @staticmethod
481 def authorizer_cb(action, arg1, arg2, dbname, source):
482 if action != sqlite.SQLITE_SELECT:
483 raise ValueError
484 if arg2 == 'c2' or arg1 == 't2':
485 raise ValueError
486 return sqlite.SQLITE_OK
487
488class AuthorizerIllegalTypeTests(AuthorizerTests):
489 @staticmethod
490 def authorizer_cb(action, arg1, arg2, dbname, source):
491 if action != sqlite.SQLITE_SELECT:
492 return 0.0
493 if arg2 == 'c2' or arg1 == 't2':
494 return 0.0
495 return sqlite.SQLITE_OK
496
497class AuthorizerLargeIntegerTests(AuthorizerTests):
498 @staticmethod
499 def authorizer_cb(action, arg1, arg2, dbname, source):
500 if action != sqlite.SQLITE_SELECT:
501 return 2**32
502 if arg2 == 'c2' or arg1 == 't2':
503 return 2**32
504 return sqlite.SQLITE_OK
505
506
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000507def suite():
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100508 tests = [
509 AggregateTests,
510 AuthorizerIllegalTypeTests,
511 AuthorizerLargeIntegerTests,
512 AuthorizerRaiseExceptionTests,
513 AuthorizerTests,
514 FunctionTests,
515 ]
516 return unittest.TestSuite(
517 [unittest.TestLoader().loadTestsFromTestCase(t) for t in tests]
518 )
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000519
520def test():
521 runner = unittest.TextTestRunner()
522 runner.run(suite())
523
524if __name__ == "__main__":
525 test()