mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	Issue #23758: Improve num_params docs of create_{function,aggregate} functions
If you pass -1, the callable can take any number of arguments. Added tests to verify the behavior. Initial patch by Cédric Krier.
This commit is contained in:
		
							parent
							
								
									f70fe6f6cf
								
							
						
					
					
						commit
						fa0f62d6ab
					
				
					 2 changed files with 36 additions and 3 deletions
				
			
		|  | @ -324,8 +324,9 @@ Connection Objects | ||||||
| 
 | 
 | ||||||
|       Creates a user-defined function that you can later use from within SQL |       Creates a user-defined function that you can later use from within SQL | ||||||
|       statements under the function name *name*. *num_params* is the number of |       statements under the function name *name*. *num_params* is the number of | ||||||
|       parameters the function accepts, and *func* is a Python callable that is called |       parameters the function accepts (if *num_params* is -1, the function may | ||||||
|       as the SQL function. |       take any number of arguments), and *func* is a Python callable that is | ||||||
|  |       called as the SQL function. | ||||||
| 
 | 
 | ||||||
|       The function can return any of the types supported by SQLite: bytes, str, int, |       The function can return any of the types supported by SQLite: bytes, str, int, | ||||||
|       float and None. |       float and None. | ||||||
|  | @ -340,7 +341,8 @@ Connection Objects | ||||||
|       Creates a user-defined aggregate function. |       Creates a user-defined aggregate function. | ||||||
| 
 | 
 | ||||||
|       The aggregate class must implement a ``step`` method, which accepts the number |       The aggregate class must implement a ``step`` method, which accepts the number | ||||||
|       of parameters *num_params*, and a ``finalize`` method which will return the |       of parameters *num_params* (if *num_params* is -1, the function may take | ||||||
|  |       any number of arguments), and a ``finalize`` method which will return the | ||||||
|       final result of the aggregate. |       final result of the aggregate. | ||||||
| 
 | 
 | ||||||
|       The ``finalize`` method can return any of the types supported by SQLite: |       The ``finalize`` method can return any of the types supported by SQLite: | ||||||
|  |  | ||||||
|  | @ -55,6 +55,9 @@ def func_isblob(v): | ||||||
| def func_islonglong(v): | def func_islonglong(v): | ||||||
|     return isinstance(v, int) and v >= 1<<31 |     return isinstance(v, int) and v >= 1<<31 | ||||||
| 
 | 
 | ||||||
|  | def func(*args): | ||||||
|  |     return len(args) | ||||||
|  | 
 | ||||||
| class AggrNoStep: | class AggrNoStep: | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         pass |         pass | ||||||
|  | @ -111,6 +114,19 @@ def step(self, whichType, val): | ||||||
|     def finalize(self): |     def finalize(self): | ||||||
|         return self.val |         return self.val | ||||||
| 
 | 
 | ||||||
|  | class AggrCheckTypes: | ||||||
|  |     def __init__(self): | ||||||
|  |         self.val = 0 | ||||||
|  | 
 | ||||||
|  |     def step(self, whichType, *vals): | ||||||
|  |         theType = {"str": str, "int": int, "float": float, "None": type(None), | ||||||
|  |                    "blob": bytes} | ||||||
|  |         for val in vals: | ||||||
|  |             self.val += int(theType[whichType] is type(val)) | ||||||
|  | 
 | ||||||
|  |     def finalize(self): | ||||||
|  |         return self.val | ||||||
|  | 
 | ||||||
| class AggrSum: | class AggrSum: | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         self.val = 0.0 |         self.val = 0.0 | ||||||
|  | @ -140,6 +156,7 @@ def setUp(self): | ||||||
|         self.con.create_function("isnone", 1, func_isnone) |         self.con.create_function("isnone", 1, func_isnone) | ||||||
|         self.con.create_function("isblob", 1, func_isblob) |         self.con.create_function("isblob", 1, func_isblob) | ||||||
|         self.con.create_function("islonglong", 1, func_islonglong) |         self.con.create_function("islonglong", 1, func_islonglong) | ||||||
|  |         self.con.create_function("spam", -1, func) | ||||||
| 
 | 
 | ||||||
|     def tearDown(self): |     def tearDown(self): | ||||||
|         self.con.close() |         self.con.close() | ||||||
|  | @ -257,6 +274,13 @@ def CheckParamLongLong(self): | ||||||
|         val = cur.fetchone()[0] |         val = cur.fetchone()[0] | ||||||
|         self.assertEqual(val, 1) |         self.assertEqual(val, 1) | ||||||
| 
 | 
 | ||||||
|  |     def CheckAnyArguments(self): | ||||||
|  |         cur = self.con.cursor() | ||||||
|  |         cur.execute("select spam(?, ?)", (1, 2)) | ||||||
|  |         val = cur.fetchone()[0] | ||||||
|  |         self.assertEqual(val, 2) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class AggregateTests(unittest.TestCase): | class AggregateTests(unittest.TestCase): | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|         self.con = sqlite.connect(":memory:") |         self.con = sqlite.connect(":memory:") | ||||||
|  | @ -279,6 +303,7 @@ def setUp(self): | ||||||
|         self.con.create_aggregate("excStep", 1, AggrExceptionInStep) |         self.con.create_aggregate("excStep", 1, AggrExceptionInStep) | ||||||
|         self.con.create_aggregate("excFinalize", 1, AggrExceptionInFinalize) |         self.con.create_aggregate("excFinalize", 1, AggrExceptionInFinalize) | ||||||
|         self.con.create_aggregate("checkType", 2, AggrCheckType) |         self.con.create_aggregate("checkType", 2, AggrCheckType) | ||||||
|  |         self.con.create_aggregate("checkTypes", -1, AggrCheckTypes) | ||||||
|         self.con.create_aggregate("mysum", 1, AggrSum) |         self.con.create_aggregate("mysum", 1, AggrSum) | ||||||
| 
 | 
 | ||||||
|     def tearDown(self): |     def tearDown(self): | ||||||
|  | @ -349,6 +374,12 @@ def CheckAggrCheckParamInt(self): | ||||||
|         val = cur.fetchone()[0] |         val = cur.fetchone()[0] | ||||||
|         self.assertEqual(val, 1) |         self.assertEqual(val, 1) | ||||||
| 
 | 
 | ||||||
|  |     def CheckAggrCheckParamsInt(self): | ||||||
|  |         cur = self.con.cursor() | ||||||
|  |         cur.execute("select checkTypes('int', ?, ?)", (42, 24)) | ||||||
|  |         val = cur.fetchone()[0] | ||||||
|  |         self.assertEqual(val, 2) | ||||||
|  | 
 | ||||||
|     def CheckAggrCheckParamFloat(self): |     def CheckAggrCheckParamFloat(self): | ||||||
|         cur = self.con.cursor() |         cur = self.con.cursor() | ||||||
|         cur.execute("select checkType('float', ?)", (3.14,)) |         cur.execute("select checkType('float', ?)", (3.14,)) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Berker Peksag
						Berker Peksag