singlestoredb 1.16.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. singlestoredb/__init__.py +75 -0
  2. singlestoredb/ai/__init__.py +2 -0
  3. singlestoredb/ai/chat.py +139 -0
  4. singlestoredb/ai/embeddings.py +128 -0
  5. singlestoredb/alchemy/__init__.py +90 -0
  6. singlestoredb/apps/__init__.py +3 -0
  7. singlestoredb/apps/_cloud_functions.py +90 -0
  8. singlestoredb/apps/_config.py +72 -0
  9. singlestoredb/apps/_connection_info.py +18 -0
  10. singlestoredb/apps/_dashboards.py +47 -0
  11. singlestoredb/apps/_process.py +32 -0
  12. singlestoredb/apps/_python_udfs.py +100 -0
  13. singlestoredb/apps/_stdout_supress.py +30 -0
  14. singlestoredb/apps/_uvicorn_util.py +36 -0
  15. singlestoredb/auth.py +245 -0
  16. singlestoredb/config.py +484 -0
  17. singlestoredb/connection.py +1487 -0
  18. singlestoredb/converters.py +950 -0
  19. singlestoredb/docstring/__init__.py +33 -0
  20. singlestoredb/docstring/attrdoc.py +126 -0
  21. singlestoredb/docstring/common.py +230 -0
  22. singlestoredb/docstring/epydoc.py +267 -0
  23. singlestoredb/docstring/google.py +412 -0
  24. singlestoredb/docstring/numpydoc.py +562 -0
  25. singlestoredb/docstring/parser.py +100 -0
  26. singlestoredb/docstring/py.typed +1 -0
  27. singlestoredb/docstring/rest.py +256 -0
  28. singlestoredb/docstring/tests/__init__.py +1 -0
  29. singlestoredb/docstring/tests/_pydoctor.py +21 -0
  30. singlestoredb/docstring/tests/test_epydoc.py +729 -0
  31. singlestoredb/docstring/tests/test_google.py +1007 -0
  32. singlestoredb/docstring/tests/test_numpydoc.py +1100 -0
  33. singlestoredb/docstring/tests/test_parse_from_object.py +109 -0
  34. singlestoredb/docstring/tests/test_parser.py +248 -0
  35. singlestoredb/docstring/tests/test_rest.py +547 -0
  36. singlestoredb/docstring/tests/test_util.py +70 -0
  37. singlestoredb/docstring/util.py +141 -0
  38. singlestoredb/exceptions.py +120 -0
  39. singlestoredb/functions/__init__.py +16 -0
  40. singlestoredb/functions/decorator.py +201 -0
  41. singlestoredb/functions/dtypes.py +1793 -0
  42. singlestoredb/functions/ext/__init__.py +1 -0
  43. singlestoredb/functions/ext/arrow.py +375 -0
  44. singlestoredb/functions/ext/asgi.py +2133 -0
  45. singlestoredb/functions/ext/json.py +420 -0
  46. singlestoredb/functions/ext/mmap.py +413 -0
  47. singlestoredb/functions/ext/rowdat_1.py +724 -0
  48. singlestoredb/functions/ext/timer.py +89 -0
  49. singlestoredb/functions/ext/utils.py +218 -0
  50. singlestoredb/functions/signature.py +1578 -0
  51. singlestoredb/functions/typing/__init__.py +41 -0
  52. singlestoredb/functions/typing/numpy.py +20 -0
  53. singlestoredb/functions/typing/pandas.py +2 -0
  54. singlestoredb/functions/typing/polars.py +2 -0
  55. singlestoredb/functions/typing/pyarrow.py +2 -0
  56. singlestoredb/functions/utils.py +421 -0
  57. singlestoredb/fusion/__init__.py +11 -0
  58. singlestoredb/fusion/graphql.py +213 -0
  59. singlestoredb/fusion/handler.py +916 -0
  60. singlestoredb/fusion/handlers/__init__.py +0 -0
  61. singlestoredb/fusion/handlers/export.py +525 -0
  62. singlestoredb/fusion/handlers/files.py +690 -0
  63. singlestoredb/fusion/handlers/job.py +660 -0
  64. singlestoredb/fusion/handlers/models.py +250 -0
  65. singlestoredb/fusion/handlers/stage.py +502 -0
  66. singlestoredb/fusion/handlers/utils.py +324 -0
  67. singlestoredb/fusion/handlers/workspace.py +956 -0
  68. singlestoredb/fusion/registry.py +249 -0
  69. singlestoredb/fusion/result.py +399 -0
  70. singlestoredb/http/__init__.py +27 -0
  71. singlestoredb/http/connection.py +1267 -0
  72. singlestoredb/magics/__init__.py +34 -0
  73. singlestoredb/magics/run_personal.py +137 -0
  74. singlestoredb/magics/run_shared.py +134 -0
  75. singlestoredb/management/__init__.py +9 -0
  76. singlestoredb/management/billing_usage.py +148 -0
  77. singlestoredb/management/cluster.py +462 -0
  78. singlestoredb/management/export.py +295 -0
  79. singlestoredb/management/files.py +1102 -0
  80. singlestoredb/management/inference_api.py +105 -0
  81. singlestoredb/management/job.py +887 -0
  82. singlestoredb/management/manager.py +373 -0
  83. singlestoredb/management/organization.py +226 -0
  84. singlestoredb/management/region.py +169 -0
  85. singlestoredb/management/utils.py +423 -0
  86. singlestoredb/management/workspace.py +1927 -0
  87. singlestoredb/mysql/__init__.py +177 -0
  88. singlestoredb/mysql/_auth.py +298 -0
  89. singlestoredb/mysql/charset.py +214 -0
  90. singlestoredb/mysql/connection.py +2032 -0
  91. singlestoredb/mysql/constants/CLIENT.py +38 -0
  92. singlestoredb/mysql/constants/COMMAND.py +32 -0
  93. singlestoredb/mysql/constants/CR.py +78 -0
  94. singlestoredb/mysql/constants/ER.py +474 -0
  95. singlestoredb/mysql/constants/EXTENDED_TYPE.py +3 -0
  96. singlestoredb/mysql/constants/FIELD_TYPE.py +48 -0
  97. singlestoredb/mysql/constants/FLAG.py +15 -0
  98. singlestoredb/mysql/constants/SERVER_STATUS.py +10 -0
  99. singlestoredb/mysql/constants/VECTOR_TYPE.py +6 -0
  100. singlestoredb/mysql/constants/__init__.py +0 -0
  101. singlestoredb/mysql/converters.py +271 -0
  102. singlestoredb/mysql/cursors.py +896 -0
  103. singlestoredb/mysql/err.py +92 -0
  104. singlestoredb/mysql/optionfile.py +20 -0
  105. singlestoredb/mysql/protocol.py +450 -0
  106. singlestoredb/mysql/tests/__init__.py +19 -0
  107. singlestoredb/mysql/tests/base.py +126 -0
  108. singlestoredb/mysql/tests/conftest.py +37 -0
  109. singlestoredb/mysql/tests/test_DictCursor.py +132 -0
  110. singlestoredb/mysql/tests/test_SSCursor.py +141 -0
  111. singlestoredb/mysql/tests/test_basic.py +452 -0
  112. singlestoredb/mysql/tests/test_connection.py +851 -0
  113. singlestoredb/mysql/tests/test_converters.py +58 -0
  114. singlestoredb/mysql/tests/test_cursor.py +141 -0
  115. singlestoredb/mysql/tests/test_err.py +16 -0
  116. singlestoredb/mysql/tests/test_issues.py +514 -0
  117. singlestoredb/mysql/tests/test_load_local.py +75 -0
  118. singlestoredb/mysql/tests/test_nextset.py +88 -0
  119. singlestoredb/mysql/tests/test_optionfile.py +27 -0
  120. singlestoredb/mysql/tests/thirdparty/__init__.py +6 -0
  121. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +9 -0
  122. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/capabilities.py +323 -0
  123. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/dbapi20.py +865 -0
  124. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +110 -0
  125. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +224 -0
  126. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +101 -0
  127. singlestoredb/mysql/times.py +23 -0
  128. singlestoredb/notebook/__init__.py +16 -0
  129. singlestoredb/notebook/_objects.py +213 -0
  130. singlestoredb/notebook/_portal.py +352 -0
  131. singlestoredb/py.typed +0 -0
  132. singlestoredb/pytest.py +352 -0
  133. singlestoredb/server/__init__.py +0 -0
  134. singlestoredb/server/docker.py +452 -0
  135. singlestoredb/server/free_tier.py +267 -0
  136. singlestoredb/tests/__init__.py +0 -0
  137. singlestoredb/tests/alltypes.sql +307 -0
  138. singlestoredb/tests/alltypes_no_nulls.sql +208 -0
  139. singlestoredb/tests/empty.sql +0 -0
  140. singlestoredb/tests/ext_funcs/__init__.py +702 -0
  141. singlestoredb/tests/local_infile.csv +3 -0
  142. singlestoredb/tests/test.ipynb +18 -0
  143. singlestoredb/tests/test.sql +680 -0
  144. singlestoredb/tests/test2.ipynb +18 -0
  145. singlestoredb/tests/test2.sql +1 -0
  146. singlestoredb/tests/test_basics.py +1332 -0
  147. singlestoredb/tests/test_config.py +318 -0
  148. singlestoredb/tests/test_connection.py +3103 -0
  149. singlestoredb/tests/test_dbapi.py +27 -0
  150. singlestoredb/tests/test_exceptions.py +45 -0
  151. singlestoredb/tests/test_ext_func.py +1472 -0
  152. singlestoredb/tests/test_ext_func_data.py +1101 -0
  153. singlestoredb/tests/test_fusion.py +1527 -0
  154. singlestoredb/tests/test_http.py +288 -0
  155. singlestoredb/tests/test_management.py +1599 -0
  156. singlestoredb/tests/test_plugin.py +33 -0
  157. singlestoredb/tests/test_results.py +171 -0
  158. singlestoredb/tests/test_types.py +132 -0
  159. singlestoredb/tests/test_udf.py +737 -0
  160. singlestoredb/tests/test_udf_returns.py +459 -0
  161. singlestoredb/tests/test_vectorstore.py +51 -0
  162. singlestoredb/tests/test_xdict.py +333 -0
  163. singlestoredb/tests/utils.py +141 -0
  164. singlestoredb/types.py +373 -0
  165. singlestoredb/utils/__init__.py +0 -0
  166. singlestoredb/utils/config.py +950 -0
  167. singlestoredb/utils/convert_rows.py +69 -0
  168. singlestoredb/utils/debug.py +13 -0
  169. singlestoredb/utils/dtypes.py +205 -0
  170. singlestoredb/utils/events.py +65 -0
  171. singlestoredb/utils/mogrify.py +151 -0
  172. singlestoredb/utils/results.py +585 -0
  173. singlestoredb/utils/xdict.py +425 -0
  174. singlestoredb/vectorstore.py +192 -0
  175. singlestoredb/warnings.py +5 -0
  176. singlestoredb-1.16.1.dist-info/METADATA +165 -0
  177. singlestoredb-1.16.1.dist-info/RECORD +183 -0
  178. singlestoredb-1.16.1.dist-info/WHEEL +5 -0
  179. singlestoredb-1.16.1.dist-info/entry_points.txt +2 -0
  180. singlestoredb-1.16.1.dist-info/licenses/LICENSE +201 -0
  181. singlestoredb-1.16.1.dist-info/top_level.txt +3 -0
  182. sqlx/__init__.py +4 -0
  183. sqlx/magic.py +113 -0
@@ -0,0 +1,1472 @@
1
+ #!/usr/bin/env python
2
+ # type: ignore
3
+ """Test SingleStoreDB external functions."""
4
+ import os
5
+ import socket
6
+ import subprocess
7
+ import time
8
+ import unittest
9
+
10
+ import requests
11
+
12
+ import singlestoredb as s2
13
+ import singlestoredb.mysql.constants.FIELD_TYPE as ft
14
+ from . import ext_funcs
15
+ from . import utils
16
+ from singlestoredb.functions.ext.asgi import create_app
17
+
18
+
19
+ try:
20
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
21
+ s.connect(('8.8.8.8', 80))
22
+ HTTP_HOST = s.getsockname()[0]
23
+ except Exception:
24
+ HTTP_HOST = '127.0.0.1'
25
+ finally:
26
+ s.close()
27
+
28
+
29
+ def get_open_port() -> int:
30
+ """Find an open port number."""
31
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
32
+ s.bind(('', 0))
33
+ s.listen(1)
34
+ port = s.getsockname()[1]
35
+ s.close()
36
+ return port
37
+
38
+
39
+ def start_http_server(database, data_format='rowdat_1'):
40
+ """Start an external function server."""
41
+ port = get_open_port()
42
+ print(f'Start UDF HTTP server on http://{HTTP_HOST}:{port}')
43
+ proc = subprocess.Popen(
44
+ ['uvicorn', 'singlestoredb.functions.ext.asgi:create_app'],
45
+ env=dict(
46
+ PATH=os.environ['PATH'],
47
+ PYTHONPATH=os.environ.get('PYTHONPATH', ''),
48
+ UVICORN_HOST=str(HTTP_HOST),
49
+ UVICORN_PORT=str(port),
50
+ UVICORN_FACTORY='1',
51
+ SINGLESTOREDB_EXT_FUNCTIONS='singlestoredb.tests.ext_funcs',
52
+ SINGLESTOREDB_PURE_PYTHON=os.environ.get('SINGLESTOREDB_PURE_PYTHON', '0'),
53
+ ),
54
+ )
55
+
56
+ # Wait for server to be available
57
+ retries = 10
58
+ while retries > 0:
59
+ try:
60
+ out = requests.get(f'http://{HTTP_HOST}:{port}/show/create_function')
61
+ if out.status_code == 200:
62
+ break
63
+ except Exception:
64
+ pass
65
+ time.sleep(3)
66
+ retries -= 1
67
+
68
+ app = create_app(
69
+ ext_funcs,
70
+ url=f'http://{HTTP_HOST}:{port}/invoke',
71
+ data_format=data_format,
72
+ )
73
+ app.register_functions(
74
+ database=database,
75
+ )
76
+
77
+ with s2.connect(database=database) as conn:
78
+ with conn.cursor() as cur:
79
+ cur.execute('set global enable_external_functions=on')
80
+ cur.execute('show functions')
81
+ for item in list(cur):
82
+ cur.execute(f'show create function `{item[0]}`')
83
+ for func in list(cur):
84
+ print(*func)
85
+
86
+ return proc, HTTP_HOST, port
87
+
88
+
89
+ def stop_http_server(proc, database):
90
+ """Stop the external function server."""
91
+ proc.terminate()
92
+ app = create_app(ext_funcs)
93
+ app.drop_functions(database=database)
94
+
95
+
96
+ class TestExtFunc(unittest.TestCase):
97
+
98
+ dbname: str = ''
99
+ dbexisted: bool = False
100
+ http_server = None
101
+ http_host = '127.0.0.1'
102
+ http_port = 0
103
+
104
+ @classmethod
105
+ def setUpClass(cls):
106
+ sql_file = os.path.join(os.path.dirname(__file__), 'test.sql')
107
+ cls.dbname, cls.dbexisted = utils.load_sql(sql_file)
108
+ cls.http_server, cls.http_host, cls.http_port = \
109
+ start_http_server(cls.dbname, 'rowdat_1')
110
+
111
+ @classmethod
112
+ def tearDownClass(cls):
113
+ stop_http_server(cls.http_server, cls.dbname)
114
+ cls.http_server = None
115
+ cls.http_host = '127.0.0.1'
116
+ cls.http_port = 0
117
+ if not cls.dbexisted:
118
+ utils.drop_database(cls.dbname)
119
+
120
+ def setUp(self):
121
+ self.conn = s2.connect(database=type(self).dbname)
122
+ self.cur = self.conn.cursor()
123
+
124
+ def tearDown(self):
125
+ try:
126
+ if self.cur is not None:
127
+ self.cur.close()
128
+ except Exception:
129
+ # traceback.print_exc()
130
+ pass
131
+
132
+ try:
133
+ if self.conn is not None:
134
+ self.conn.close()
135
+ except Exception:
136
+ # traceback.print_exc()
137
+ pass
138
+
139
+ def test_show_create_function(self):
140
+ out = requests.get(
141
+ f'http://{type(self).http_host}:{type(self).http_port}'
142
+ '/show/create_function',
143
+ )
144
+ print(out.text)
145
+
146
+ def test_double_mult(self):
147
+ self.cur.execute('select double_mult(value, 100) as res from data order by id')
148
+
149
+ assert [tuple(x) for x in self.cur] == \
150
+ [(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]
151
+
152
+ desc = self.cur.description
153
+ assert len(desc) == 1
154
+ assert desc[0].name == 'res'
155
+ assert desc[0].type_code == ft.DOUBLE
156
+ assert desc[0].null_ok is False
157
+
158
+ # NULL is not valid
159
+ with self.assertRaises(self.conn.OperationalError):
160
+ self.cur.execute(
161
+ 'select double_mult(value, NULL) as res '
162
+ 'from data order by id',
163
+ )
164
+
165
+ def test_timeout_double_mult(self):
166
+ with self.assertRaises(self.conn.OperationalError) as exc:
167
+ self.cur.execute(
168
+ 'select timeout_double_mult(value, 100) as res '
169
+ 'from longer_data order by id',
170
+ )
171
+ assert 'timeout' in str(exc.exception).lower()
172
+
173
+ def test_async_double_mult(self):
174
+ self.cur.execute(
175
+ 'select async_double_mult(value, 100) as res from data order by id',
176
+ )
177
+
178
+ assert [tuple(x) for x in self.cur] == \
179
+ [(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]
180
+
181
+ desc = self.cur.description
182
+ assert len(desc) == 1
183
+ assert desc[0].name == 'res'
184
+ assert desc[0].type_code == ft.DOUBLE
185
+ assert desc[0].null_ok is False
186
+
187
+ # NULL is not valid
188
+ with self.assertRaises(self.conn.OperationalError):
189
+ self.cur.execute(
190
+ 'select async_double_mult(value, NULL) as res '
191
+ 'from data order by id',
192
+ )
193
+
194
+ def test_async_timeout_double_mult(self):
195
+ with self.assertRaises(self.conn.OperationalError) as exc:
196
+ self.cur.execute(
197
+ 'select async_timeout_double_mult(value, 100) as res '
198
+ 'from longer_data order by id',
199
+ )
200
+ assert 'timeout' in str(exc.exception).lower()
201
+
202
+ def test_pandas_double_mult(self):
203
+ self.cur.execute(
204
+ 'select pandas_double_mult(value, 100) as res '
205
+ 'from data order by id',
206
+ )
207
+
208
+ assert [tuple(x) for x in self.cur] == \
209
+ [(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]
210
+
211
+ desc = self.cur.description
212
+ assert len(desc) == 1
213
+ assert desc[0].name == 'res'
214
+ assert desc[0].type_code == ft.DOUBLE
215
+ assert desc[0].null_ok is False
216
+
217
+ # NULL is not valid
218
+ with self.assertRaises(self.conn.OperationalError):
219
+ self.cur.execute(
220
+ 'select pandas_double_mult(value, NULL) as res '
221
+ 'from data order by id',
222
+ )
223
+
224
+ def test_numpy_double_mult(self):
225
+ self.cur.execute(
226
+ 'select numpy_double_mult(value, 100) as res '
227
+ 'from data order by id',
228
+ )
229
+
230
+ assert [tuple(x) for x in self.cur] == \
231
+ [(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]
232
+
233
+ desc = self.cur.description
234
+ assert len(desc) == 1
235
+ assert desc[0].name == 'res'
236
+ assert desc[0].type_code == ft.DOUBLE
237
+ assert desc[0].null_ok is False
238
+
239
+ # NULL is not valid
240
+ with self.assertRaises(self.conn.OperationalError):
241
+ self.cur.execute(
242
+ 'select numpy_double_mult(value, NULL) as res '
243
+ 'from data order by id',
244
+ )
245
+
246
+ def test_async_numpy_double_mult(self):
247
+ self.cur.execute(
248
+ 'select async_numpy_double_mult(value, 100) as res '
249
+ 'from data order by id',
250
+ )
251
+
252
+ assert [tuple(x) for x in self.cur] == \
253
+ [(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]
254
+
255
+ desc = self.cur.description
256
+ assert len(desc) == 1
257
+ assert desc[0].name == 'res'
258
+ assert desc[0].type_code == ft.DOUBLE
259
+ assert desc[0].null_ok is False
260
+
261
+ # NULL is not valid
262
+ with self.assertRaises(self.conn.OperationalError):
263
+ self.cur.execute(
264
+ 'select async_numpy_double_mult(value, NULL) as res '
265
+ 'from data order by id',
266
+ )
267
+
268
+ def test_arrow_double_mult(self):
269
+ self.cur.execute(
270
+ 'select arrow_double_mult(value, 100) as res '
271
+ 'from data order by id',
272
+ )
273
+
274
+ assert [tuple(x) for x in self.cur] == \
275
+ [(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]
276
+
277
+ desc = self.cur.description
278
+ assert len(desc) == 1
279
+ assert desc[0].name == 'res'
280
+ assert desc[0].type_code == ft.DOUBLE
281
+ assert desc[0].null_ok is False
282
+
283
+ # NULL is not valid
284
+ with self.assertRaises(self.conn.OperationalError):
285
+ self.cur.execute(
286
+ 'select arrow_double_mult(value, NULL) as res '
287
+ 'from data order by id',
288
+ )
289
+
290
+ def test_polars_double_mult(self):
291
+ self.cur.execute(
292
+ 'select polars_double_mult(value, 100) as res '
293
+ 'from data order by id',
294
+ )
295
+
296
+ assert [tuple(x) for x in self.cur] == \
297
+ [(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]
298
+
299
+ desc = self.cur.description
300
+ assert len(desc) == 1
301
+ assert desc[0].name == 'res'
302
+ assert desc[0].type_code == ft.DOUBLE
303
+ assert desc[0].null_ok is False
304
+
305
+ # NULL is not valid
306
+ with self.assertRaises(self.conn.OperationalError):
307
+ self.cur.execute(
308
+ 'select polars_double_mult(value, NULL) as res '
309
+ 'from data order by id',
310
+ )
311
+
312
+ def test_nullable_double_mult(self):
313
+ self.cur.execute(
314
+ 'select nullable_double_mult(value, 100) as res from '
315
+ 'data_with_nulls order by id',
316
+ )
317
+
318
+ assert [tuple(x) for x in self.cur] == \
319
+ [(200.0,), (200.0,), (500.0,), (None,), (0.0,)]
320
+
321
+ desc = self.cur.description
322
+ assert len(desc) == 1
323
+ assert desc[0].name == 'res'
324
+ assert desc[0].type_code == ft.DOUBLE
325
+ assert desc[0].null_ok is True
326
+
327
+ self.cur.execute(
328
+ 'select nullable_double_mult(value, NULL) as res '
329
+ 'from data_with_nulls order by id',
330
+ )
331
+
332
+ assert [tuple(x) for x in self.cur] == \
333
+ [(None,), (None,), (None,), (None,), (None,)]
334
+
335
+ def test_float_mult(self):
336
+ self.cur.execute(
337
+ 'select float_mult(value, 100) as res '
338
+ 'from data order by id',
339
+ )
340
+
341
+ assert [tuple(x) for x in self.cur] == \
342
+ [(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]
343
+
344
+ desc = self.cur.description
345
+ assert len(desc) == 1
346
+ assert desc[0].name == 'res'
347
+ assert desc[0].type_code == ft.FLOAT
348
+ assert desc[0].null_ok is False
349
+
350
+ # NULL is not valid
351
+ with self.assertRaises(self.conn.OperationalError):
352
+ self.cur.execute(
353
+ 'select float_mult(value, NULL) as res '
354
+ 'from data order by id',
355
+ )
356
+
357
+ def test_nullable_float_mult(self):
358
+ self.cur.execute(
359
+ 'select nullable_float_mult(value, 100) as res '
360
+ 'from data_with_nulls order by id',
361
+ )
362
+
363
+ assert [tuple(x) for x in self.cur] == \
364
+ [(200.0,), (200.0,), (500.0,), (None,), (0.0,)]
365
+
366
+ desc = self.cur.description
367
+ assert len(desc) == 1
368
+ assert desc[0].name == 'res'
369
+ assert desc[0].type_code == ft.FLOAT
370
+ assert desc[0].null_ok is True
371
+
372
+ self.cur.execute(
373
+ 'select nullable_float_mult(value, NULL) as res '
374
+ 'from data_with_nulls order by id',
375
+ )
376
+
377
+ assert [tuple(x) for x in self.cur] == \
378
+ [(None,), (None,), (None,), (None,), (None,)]
379
+
380
+ def test_int_mult(self):
381
+ self.cur.execute(
382
+ 'select int_mult(value, 100) as res '
383
+ 'from data order by id',
384
+ )
385
+
386
+ assert [tuple(x) for x in self.cur] == \
387
+ [(200,), (200,), (500,), (400,), (0,)]
388
+
389
+ desc = self.cur.description
390
+ assert len(desc) == 1
391
+ assert desc[0].name == 'res'
392
+ assert desc[0].type_code == ft.LONGLONG
393
+ assert desc[0].null_ok is False
394
+
395
+ # NULL is not valid
396
+ with self.assertRaises(self.conn.OperationalError):
397
+ self.cur.execute(
398
+ 'select int_mult(value, NULL) as res '
399
+ 'from data order by id',
400
+ )
401
+
402
+ def test_tinyint_mult(self):
403
+ self.cur.execute(
404
+ 'select tinyint_mult(value, 100) as res '
405
+ 'from data order by id',
406
+ )
407
+
408
+ assert [tuple(x) for x in self.cur] == \
409
+ [(127,), (127,), (127,), (127,), (0,)]
410
+
411
+ desc = self.cur.description
412
+ assert len(desc) == 1
413
+ assert desc[0].name == 'res'
414
+ assert desc[0].type_code == ft.TINY
415
+ assert desc[0].null_ok is False
416
+
417
+ # NULL is not valid
418
+ with self.assertRaises(self.conn.OperationalError):
419
+ self.cur.execute(
420
+ 'select tinyint_mult(value, NULL) as res '
421
+ 'from data order by id',
422
+ )
423
+
424
+ def test_pandas_tinyint_mult(self):
425
+ self.cur.execute(
426
+ 'select pandas_tinyint_mult(value, 100) as res '
427
+ 'from data order by id',
428
+ )
429
+
430
+ assert [tuple(x) for x in self.cur] == \
431
+ [(127,), (127,), (127,), (127,), (0,)]
432
+
433
+ desc = self.cur.description
434
+ assert len(desc) == 1
435
+ assert desc[0].name == 'res'
436
+ assert desc[0].type_code == ft.TINY
437
+ assert desc[0].null_ok is False
438
+
439
+ # NULL is not valid
440
+ with self.assertRaises(self.conn.OperationalError):
441
+ self.cur.execute(
442
+ 'select pandas_tinyint_mult(value, NULL) as res '
443
+ 'from data order by id',
444
+ )
445
+
446
+ def test_polars_tinyint_mult(self):
447
+ self.cur.execute(
448
+ 'select polars_tinyint_mult(value, 100) as res '
449
+ 'from data order by id',
450
+ )
451
+
452
+ assert [tuple(x) for x in self.cur] == \
453
+ [(127,), (127,), (127,), (127,), (0,)]
454
+
455
+ desc = self.cur.description
456
+ assert len(desc) == 1
457
+ assert desc[0].name == 'res'
458
+ assert desc[0].type_code == ft.TINY
459
+ assert desc[0].null_ok is False
460
+
461
+ # NULL is not valid
462
+ with self.assertRaises(self.conn.OperationalError):
463
+ self.cur.execute(
464
+ 'select polars_tinyint_mult(value, NULL) as res '
465
+ 'from data order by id',
466
+ )
467
+
468
+ def test_numpy_tinyint_mult(self):
469
+ self.cur.execute(
470
+ 'select numpy_tinyint_mult(value, 100) as res '
471
+ 'from data order by id',
472
+ )
473
+
474
+ assert [tuple(x) for x in self.cur] == \
475
+ [(127,), (127,), (127,), (127,), (0,)]
476
+
477
+ desc = self.cur.description
478
+ assert len(desc) == 1
479
+ assert desc[0].name == 'res'
480
+ assert desc[0].type_code == ft.TINY
481
+ assert desc[0].null_ok is False
482
+
483
+ # NULL is not valid
484
+ with self.assertRaises(self.conn.OperationalError):
485
+ self.cur.execute(
486
+ 'select numpy_tinyint_mult(value, NULL) as res '
487
+ 'from data order by id',
488
+ )
489
+
490
+ def test_arrow_tinyint_mult(self):
491
+ self.cur.execute(
492
+ 'select arrow_tinyint_mult(value, 100) as res from '
493
+ 'data order by id',
494
+ )
495
+
496
+ assert [tuple(x) for x in self.cur] == \
497
+ [(127,), (127,), (127,), (127,), (0,)]
498
+
499
+ desc = self.cur.description
500
+ assert len(desc) == 1
501
+ assert desc[0].name == 'res'
502
+ assert desc[0].type_code == ft.TINY
503
+ assert desc[0].null_ok is False
504
+
505
+ # NULL is not valid
506
+ with self.assertRaises(self.conn.OperationalError):
507
+ self.cur.execute(
508
+ 'select arrow_tinyint_mult(value, NULL) as res '
509
+ 'from data order by id',
510
+ )
511
+
512
+ def test_nullable_tinyint_mult(self):
513
+ self.cur.execute(
514
+ 'select nullable_tinyint_mult(value, 100) as res from '
515
+ 'data_with_nulls order by id',
516
+ )
517
+
518
+ assert [tuple(x) for x in self.cur] == \
519
+ [(127,), (127,), (127,), (None,), (0,)]
520
+
521
+ desc = self.cur.description
522
+ assert len(desc) == 1
523
+ assert desc[0].name == 'res'
524
+ assert desc[0].type_code == ft.TINY
525
+ assert desc[0].null_ok is True
526
+
527
+ def test_pandas_nullable_tinyint_mult(self):
528
+ self.cur.execute(
529
+ 'select pandas_nullable_tinyint_mult(value, 100) as res '
530
+ 'from data_with_nulls order by id',
531
+ )
532
+
533
+ assert [tuple(x) for x in self.cur] == \
534
+ [(127,), (127,), (127,), (0,), (0,)]
535
+
536
+ desc = self.cur.description
537
+ assert len(desc) == 1
538
+ assert desc[0].name == 'res'
539
+ assert desc[0].type_code == ft.TINY
540
+ assert desc[0].null_ok is True
541
+
542
+ def test_pandas_nullable_tinyint_mult_with_masks(self):
543
+ self.cur.execute(
544
+ 'select pandas_nullable_tinyint_mult_with_masks(value, 100) '
545
+ 'as res from data_with_nulls order by id',
546
+ )
547
+
548
+ assert [tuple(x) for x in self.cur] == \
549
+ [(127,), (127,), (127,), (None,), (0,)]
550
+
551
+ desc = self.cur.description
552
+ assert len(desc) == 1
553
+ assert desc[0].name == 'res'
554
+ assert desc[0].type_code == ft.TINY
555
+ assert desc[0].null_ok is True
556
+
557
+ def test_polars_nullable_tinyint_mult(self):
558
+ self.cur.execute(
559
+ 'select polars_nullable_tinyint_mult(value, 100) as res '
560
+ 'from data_with_nulls order by id',
561
+ )
562
+
563
+ assert [tuple(x) for x in self.cur] == \
564
+ [(127,), (127,), (127,), (0,), (0,)]
565
+
566
+ desc = self.cur.description
567
+ assert len(desc) == 1
568
+ assert desc[0].name == 'res'
569
+ assert desc[0].type_code == ft.TINY
570
+ assert desc[0].null_ok is True
571
+
572
+ def test_polars_nullable_tinyint_mult_with_masks(self):
573
+ self.cur.execute(
574
+ 'select polars_nullable_tinyint_mult_with_masks(value, 100) '
575
+ 'as res from data_with_nulls order by id',
576
+ )
577
+
578
+ assert [tuple(x) for x in self.cur] == \
579
+ [(127,), (127,), (127,), (None,), (0,)]
580
+
581
+ desc = self.cur.description
582
+ assert len(desc) == 1
583
+ assert desc[0].name == 'res'
584
+ assert desc[0].type_code == ft.TINY
585
+ assert desc[0].null_ok is True
586
+
587
+ def test_numpy_nullable_tinyint_mult(self):
588
+ self.cur.execute(
589
+ 'select numpy_nullable_tinyint_mult(value, 100) as res '
590
+ 'from data_with_nulls order by id',
591
+ )
592
+
593
+ assert [tuple(x) for x in self.cur] == \
594
+ [(127,), (127,), (127,), (0,), (0,)]
595
+
596
+ desc = self.cur.description
597
+ assert len(desc) == 1
598
+ assert desc[0].name == 'res'
599
+ assert desc[0].type_code == ft.TINY
600
+ assert desc[0].null_ok is True
601
+
602
+ def test_numpy_nullable_tinyint_mult_with_masks(self):
603
+ self.cur.execute(
604
+ 'select numpy_nullable_tinyint_mult_with_masks(value, 100) '
605
+ 'as res from data_with_nulls order by id',
606
+ )
607
+
608
+ assert [tuple(x) for x in self.cur] == \
609
+ [(127,), (127,), (127,), (None,), (0,)]
610
+
611
+ desc = self.cur.description
612
+ assert len(desc) == 1
613
+ assert desc[0].name == 'res'
614
+ assert desc[0].type_code == ft.TINY
615
+ assert desc[0].null_ok is True
616
+
617
+ def test_arrow_nullable_tinyint_mult(self):
618
+ self.cur.execute(
619
+ 'select arrow_nullable_tinyint_mult(value, 100) as res '
620
+ 'from data_with_nulls order by id',
621
+ )
622
+
623
+ assert [tuple(x) for x in self.cur] == \
624
+ [(127,), (127,), (127,), (None,), (0,)]
625
+
626
+ desc = self.cur.description
627
+ assert len(desc) == 1
628
+ assert desc[0].name == 'res'
629
+ assert desc[0].type_code == ft.TINY
630
+ assert desc[0].null_ok is True
631
+
632
+ def test_arrow_nullable_tinyint_mult_with_masks(self):
633
+ self.cur.execute(
634
+ 'select arrow_nullable_tinyint_mult_with_masks(value, 100) '
635
+ 'as res from data_with_nulls order by id',
636
+ )
637
+
638
+ assert [tuple(x) for x in self.cur] == \
639
+ [(127,), (127,), (127,), (None,), (0,)]
640
+
641
+ desc = self.cur.description
642
+ assert len(desc) == 1
643
+ assert desc[0].name == 'res'
644
+ assert desc[0].type_code == ft.TINY
645
+ assert desc[0].null_ok is True
646
+
647
+ def test_smallint_mult(self):
648
+ self.cur.execute(
649
+ 'select smallint_mult(value, 100) as res '
650
+ 'from data order by id',
651
+ )
652
+
653
+ assert [tuple(x) for x in self.cur] == \
654
+ [(200,), (200,), (500,), (400,), (0,)]
655
+
656
+ desc = self.cur.description
657
+ assert len(desc) == 1
658
+ assert desc[0].name == 'res'
659
+ assert desc[0].type_code == ft.SHORT
660
+ assert desc[0].null_ok is False
661
+
662
+ # NULL is not valid
663
+ with self.assertRaises(self.conn.OperationalError):
664
+ self.cur.execute(
665
+ 'select smallint_mult(value, NULL) as res '
666
+ 'from data order by id',
667
+ )
668
+
669
+ def test_pandas_smallint_mult(self):
670
+ self.cur.execute(
671
+ 'select pandas_smallint_mult(value, 100) as res '
672
+ 'from data order by id',
673
+ )
674
+
675
+ assert [tuple(x) for x in self.cur] == \
676
+ [(200,), (200,), (500,), (400,), (0,)]
677
+
678
+ desc = self.cur.description
679
+ assert len(desc) == 1
680
+ assert desc[0].name == 'res'
681
+ assert desc[0].type_code == ft.SHORT
682
+ assert desc[0].null_ok is False
683
+
684
+ # NULL is not valid
685
+ with self.assertRaises(self.conn.OperationalError):
686
+ self.cur.execute(
687
+ 'select pandas_smallint_mult(value, NULL) as res '
688
+ 'from data order by id',
689
+ )
690
+
691
+ def test_polars_smallint_mult(self):
692
+ self.cur.execute(
693
+ 'select polars_smallint_mult(value, 100) as res '
694
+ 'from data order by id',
695
+ )
696
+
697
+ assert [tuple(x) for x in self.cur] == \
698
+ [(200,), (200,), (500,), (400,), (0,)]
699
+
700
+ desc = self.cur.description
701
+ assert len(desc) == 1
702
+ assert desc[0].name == 'res'
703
+ assert desc[0].type_code == ft.SHORT
704
+ assert desc[0].null_ok is False
705
+
706
+ # NULL is not valid
707
+ with self.assertRaises(self.conn.OperationalError):
708
+ self.cur.execute(
709
+ 'select polars_smallint_mult(value, NULL) as res '
710
+ 'from data order by id',
711
+ )
712
+
713
+ def test_numpy_smallint_mult(self):
714
+ self.cur.execute(
715
+ 'select numpy_smallint_mult(value, 100) as res '
716
+ 'from data order by id',
717
+ )
718
+
719
+ assert [tuple(x) for x in self.cur] == \
720
+ [(200,), (200,), (500,), (400,), (0,)]
721
+
722
+ desc = self.cur.description
723
+ assert len(desc) == 1
724
+ assert desc[0].name == 'res'
725
+ assert desc[0].type_code == ft.SHORT
726
+ assert desc[0].null_ok is False
727
+
728
+ # NULL is not valid
729
+ with self.assertRaises(self.conn.OperationalError):
730
+ self.cur.execute(
731
+ 'select numpy_smallint_mult(value, NULL) as res '
732
+ 'from data order by id',
733
+ )
734
+
735
+ def test_arrow_smallint_mult(self):
736
+ self.cur.execute(
737
+ 'select arrow_smallint_mult(value, 100) as res '
738
+ 'from data order by id',
739
+ )
740
+
741
+ assert [tuple(x) for x in self.cur] == \
742
+ [(200,), (200,), (500,), (400,), (0,)]
743
+
744
+ desc = self.cur.description
745
+ assert len(desc) == 1
746
+ assert desc[0].name == 'res'
747
+ assert desc[0].type_code == ft.SHORT
748
+ assert desc[0].null_ok is False
749
+
750
+ # NULL is not valid
751
+ with self.assertRaises(self.conn.OperationalError):
752
+ self.cur.execute(
753
+ 'select arrow_smallint_mult(value, NULL) as res '
754
+ 'from data order by id',
755
+ )
756
+
757
+ def test_nullable_smallint_mult(self):
758
+ self.cur.execute(
759
+ 'select nullable_smallint_mult(value, 100) as res '
760
+ 'from data_with_nulls order by id',
761
+ )
762
+
763
+ assert [tuple(x) for x in self.cur] == \
764
+ [(200,), (200,), (500,), (None,), (0,)]
765
+
766
+ desc = self.cur.description
767
+ assert len(desc) == 1
768
+ assert desc[0].name == 'res'
769
+ assert desc[0].type_code == ft.SHORT
770
+ assert desc[0].null_ok is True
771
+
772
+ def test_mediumint_mult(self):
773
+ self.cur.execute(
774
+ 'select mediumint_mult(value, 100) as res '
775
+ 'from data order by id',
776
+ )
777
+
778
+ assert [tuple(x) for x in self.cur] == \
779
+ [(200,), (200,), (500,), (400,), (0,)]
780
+
781
+ desc = self.cur.description
782
+ assert len(desc) == 1
783
+ assert desc[0].name == 'res'
784
+ assert desc[0].type_code == ft.INT24
785
+ assert desc[0].null_ok is False
786
+
787
+ # NULL is not valid
788
+ with self.assertRaises(self.conn.OperationalError):
789
+ self.cur.execute(
790
+ 'select mediumint_mult(value, NULL) as res '
791
+ 'from data order by id',
792
+ )
793
+
794
+ def test_pandas_mediumint_mult(self):
795
+ self.cur.execute(
796
+ 'select pandas_mediumint_mult(value, 100) as res '
797
+ 'from data order by id',
798
+ )
799
+
800
+ assert [tuple(x) for x in self.cur] == \
801
+ [(200,), (200,), (500,), (400,), (0,)]
802
+
803
+ desc = self.cur.description
804
+ assert len(desc) == 1
805
+ assert desc[0].name == 'res'
806
+ assert desc[0].type_code == ft.INT24
807
+ assert desc[0].null_ok is False
808
+
809
+ # NULL is not valid
810
+ with self.assertRaises(self.conn.OperationalError):
811
+ self.cur.execute(
812
+ 'select pandas_mediumint_mult(value, NULL) as res '
813
+ 'from data order by id',
814
+ )
815
+
816
+ def test_polars_mediumint_mult(self):
817
+ self.cur.execute(
818
+ 'select polars_mediumint_mult(value, 100) as res '
819
+ 'from data order by id',
820
+ )
821
+
822
+ assert [tuple(x) for x in self.cur] == \
823
+ [(200,), (200,), (500,), (400,), (0,)]
824
+
825
+ desc = self.cur.description
826
+ assert len(desc) == 1
827
+ assert desc[0].name == 'res'
828
+ assert desc[0].type_code == ft.INT24
829
+ assert desc[0].null_ok is False
830
+
831
+ # NULL is not valid
832
+ with self.assertRaises(self.conn.OperationalError):
833
+ self.cur.execute(
834
+ 'select polars_mediumint_mult(value, NULL) as res '
835
+ 'from data order by id',
836
+ )
837
+
838
+ def test_numpy_mediumint_mult(self):
839
+ self.cur.execute(
840
+ 'select numpy_mediumint_mult(value, 100) as res '
841
+ 'from data order by id',
842
+ )
843
+
844
+ assert [tuple(x) for x in self.cur] == \
845
+ [(200,), (200,), (500,), (400,), (0,)]
846
+
847
+ desc = self.cur.description
848
+ assert len(desc) == 1
849
+ assert desc[0].name == 'res'
850
+ assert desc[0].type_code == ft.INT24
851
+ assert desc[0].null_ok is False
852
+
853
+ # NULL is not valid
854
+ with self.assertRaises(self.conn.OperationalError):
855
+ self.cur.execute(
856
+ 'select numpy_mediumint_mult(value, NULL) as res '
857
+ 'from data order by id',
858
+ )
859
+
860
+ def test_arrow_mediumint_mult(self):
861
+ self.cur.execute(
862
+ 'select arrow_mediumint_mult(value, 100) as res '
863
+ 'from data order by id',
864
+ )
865
+
866
+ assert [tuple(x) for x in self.cur] == \
867
+ [(200,), (200,), (500,), (400,), (0,)]
868
+
869
+ desc = self.cur.description
870
+ assert len(desc) == 1
871
+ assert desc[0].name == 'res'
872
+ assert desc[0].type_code == ft.INT24
873
+ assert desc[0].null_ok is False
874
+
875
+ # NULL is not valid
876
+ with self.assertRaises(self.conn.OperationalError):
877
+ self.cur.execute(
878
+ 'select arrow_mediumint_mult(value, NULL) as res '
879
+ 'from data order by id',
880
+ )
881
+
882
+ def test_nullable_mediumint_mult(self):
883
+ self.cur.execute(
884
+ 'select nullable_mediumint_mult(value, 100) as res '
885
+ 'from data_with_nulls order by id',
886
+ )
887
+
888
+ assert [tuple(x) for x in self.cur] == \
889
+ [(200,), (200,), (500,), (None,), (0,)]
890
+
891
+ desc = self.cur.description
892
+ assert len(desc) == 1
893
+ assert desc[0].name == 'res'
894
+ assert desc[0].type_code == ft.INT24
895
+ assert desc[0].null_ok is True
896
+
897
+ def test_bigint_mult(self):
898
+ self.cur.execute(
899
+ 'select bigint_mult(value, 100) as res '
900
+ 'from data order by id',
901
+ )
902
+
903
+ assert [tuple(x) for x in self.cur] == \
904
+ [(200,), (200,), (500,), (400,), (0,)]
905
+
906
+ desc = self.cur.description
907
+ assert len(desc) == 1
908
+ assert desc[0].name == 'res'
909
+ assert desc[0].type_code == ft.LONGLONG
910
+ assert desc[0].null_ok is False
911
+
912
+ # NULL is not valid
913
+ with self.assertRaises(self.conn.OperationalError):
914
+ self.cur.execute(
915
+ 'select bigint_mult(value, NULL) as res '
916
+ 'from data order by id',
917
+ )
918
+
919
+ def test_pandas_bigint_mult(self):
920
+ self.cur.execute(
921
+ 'select pandas_bigint_mult(value, 100) as res '
922
+ 'from data order by id',
923
+ )
924
+
925
+ assert [tuple(x) for x in self.cur] == \
926
+ [(200,), (200,), (500,), (400,), (0,)]
927
+
928
+ desc = self.cur.description
929
+ assert len(desc) == 1
930
+ assert desc[0].name == 'res'
931
+ assert desc[0].type_code == ft.LONGLONG
932
+ assert desc[0].null_ok is False
933
+
934
+ # NULL is not valid
935
+ with self.assertRaises(self.conn.OperationalError):
936
+ self.cur.execute(
937
+ 'select pandas_bigint_mult(value, NULL) as res '
938
+ 'from data order by id',
939
+ )
940
+
941
+ def test_polars_bigint_mult(self):
942
+ self.cur.execute(
943
+ 'select polars_bigint_mult(value, 100) as res '
944
+ 'from data order by id',
945
+ )
946
+
947
+ assert [tuple(x) for x in self.cur] == \
948
+ [(200,), (200,), (500,), (400,), (0,)]
949
+
950
+ desc = self.cur.description
951
+ assert len(desc) == 1
952
+ assert desc[0].name == 'res'
953
+ assert desc[0].type_code == ft.LONGLONG
954
+ assert desc[0].null_ok is False
955
+
956
+ # NULL is not valid
957
+ with self.assertRaises(self.conn.OperationalError):
958
+ self.cur.execute(
959
+ 'select polars_bigint_mult(value, NULL) as res '
960
+ 'from data order by id',
961
+ )
962
+
963
+ def test_numpy_bigint_mult(self):
964
+ self.cur.execute(
965
+ 'select numpy_bigint_mult(value, 100) as res '
966
+ 'from data order by id',
967
+ )
968
+
969
+ assert [tuple(x) for x in self.cur] == \
970
+ [(200,), (200,), (500,), (400,), (0,)]
971
+
972
+ desc = self.cur.description
973
+ assert len(desc) == 1
974
+ assert desc[0].name == 'res'
975
+ assert desc[0].type_code == ft.LONGLONG
976
+ assert desc[0].null_ok is False
977
+
978
+ # NULL is not valid
979
+ with self.assertRaises(self.conn.OperationalError):
980
+ self.cur.execute(
981
+ 'select numpy_bigint_mult(value, NULL) as res '
982
+ 'from data order by id',
983
+ )
984
+
985
+ def test_numpy_nullable_bigint_mult(self):
986
+ self.cur.execute(
987
+ 'select numpy_nullable_bigint_mult(value, 100) as res '
988
+ 'from data_with_nulls order by id',
989
+ )
990
+
991
+ # assert [tuple(x) for x in self.cur] == \
992
+ # [(200,), (200,), (500,), (None,), (0,)]
993
+ assert [tuple(x) for x in self.cur] == \
994
+ [(200,), (200,), (500,), (0,), (0,)]
995
+
996
+ desc = self.cur.description
997
+ assert len(desc) == 1
998
+ assert desc[0].name == 'res'
999
+ assert desc[0].type_code == ft.LONGLONG
1000
+ assert desc[0].null_ok is True
1001
+
1002
+ def test_arrow_bigint_mult(self):
1003
+ self.cur.execute(
1004
+ 'select arrow_bigint_mult(value, 100) as res '
1005
+ 'from data order by id',
1006
+ )
1007
+
1008
+ assert [tuple(x) for x in self.cur] == \
1009
+ [(200,), (200,), (500,), (400,), (0,)]
1010
+
1011
+ desc = self.cur.description
1012
+ assert len(desc) == 1
1013
+ assert desc[0].name == 'res'
1014
+ assert desc[0].type_code == ft.LONGLONG
1015
+ assert desc[0].null_ok is False
1016
+
1017
+ # NULL is not valid
1018
+ with self.assertRaises(self.conn.OperationalError):
1019
+ self.cur.execute(
1020
+ 'select arrow_bigint_mult(value, NULL) as res '
1021
+ 'from data order by id',
1022
+ )
1023
+
1024
+ def test_nullable_bigint_mult(self):
1025
+ self.cur.execute(
1026
+ 'select nullable_bigint_mult(value, 100) as res '
1027
+ 'from data_with_nulls order by id',
1028
+ )
1029
+
1030
+ assert [tuple(x) for x in self.cur] == \
1031
+ [(200,), (200,), (500,), (None,), (0,)]
1032
+
1033
+ desc = self.cur.description
1034
+ assert len(desc) == 1
1035
+ assert desc[0].name == 'res'
1036
+ assert desc[0].type_code == ft.LONGLONG
1037
+ assert desc[0].null_ok is True
1038
+
1039
+ def test_nullable_int_mult(self):
1040
+ self.cur.execute(
1041
+ 'select nullable_int_mult(value, 100) as res '
1042
+ 'from data_with_nulls order by id',
1043
+ )
1044
+
1045
+ assert [tuple(x) for x in self.cur] == \
1046
+ [(200,), (200,), (500,), (None,), (0,)]
1047
+
1048
+ desc = self.cur.description
1049
+ assert len(desc) == 1
1050
+ assert desc[0].name == 'res'
1051
+ assert desc[0].type_code == ft.LONGLONG
1052
+ assert desc[0].null_ok is True
1053
+
1054
+ def test_string_mult(self):
1055
+ self.cur.execute(
1056
+ 'select string_mult(name, value) as res '
1057
+ 'from data order by id',
1058
+ )
1059
+
1060
+ assert [tuple(x) for x in self.cur] == [
1061
+ ('antelopesantelopes',),
1062
+ ('bearsbears',),
1063
+ ('catscatscatscatscats',),
1064
+ ('dogsdogsdogsdogs',),
1065
+ ('',),
1066
+ ]
1067
+
1068
+ desc = self.cur.description
1069
+ assert len(desc) == 1
1070
+ assert desc[0].name == 'res'
1071
+ assert desc[0].type_code == ft.BLOB
1072
+ assert desc[0].null_ok is False
1073
+
1074
+ # NULL is not valid
1075
+ with self.assertRaises(self.conn.OperationalError):
1076
+ self.cur.execute(
1077
+ 'select string_mult(NULL, value) as res '
1078
+ 'from data order by id',
1079
+ )
1080
+
1081
+ def test_pandas_string_mult(self):
1082
+ self.cur.execute(
1083
+ 'select pandas_string_mult(name, value) as res '
1084
+ 'from data order by id',
1085
+ )
1086
+
1087
+ assert [tuple(x) for x in self.cur] == [
1088
+ ('antelopesantelopes',),
1089
+ ('bearsbears',),
1090
+ ('catscatscatscatscats',),
1091
+ ('dogsdogsdogsdogs',),
1092
+ ('',),
1093
+ ]
1094
+
1095
+ desc = self.cur.description
1096
+ assert len(desc) == 1
1097
+ assert desc[0].name == 'res'
1098
+ assert desc[0].type_code == ft.BLOB
1099
+ assert desc[0].null_ok is False
1100
+
1101
+ # NULL is not valid
1102
+ with self.assertRaises(self.conn.OperationalError):
1103
+ self.cur.execute(
1104
+ 'select pandas_string_mult(NULL, value) as res '
1105
+ 'from data order by id',
1106
+ )
1107
+
1108
+ def test_numpy_string_mult(self):
1109
+ self.cur.execute(
1110
+ 'select numpy_string_mult(name, value) as res '
1111
+ 'from data order by id',
1112
+ )
1113
+
1114
+ assert [tuple(x) for x in self.cur] == [
1115
+ ('antelopesantelopes',),
1116
+ ('bearsbears',),
1117
+ ('catscatscatscatscats',),
1118
+ ('dogsdogsdogsdogs',),
1119
+ ('',),
1120
+ ]
1121
+
1122
+ desc = self.cur.description
1123
+ assert len(desc) == 1
1124
+ assert desc[0].name == 'res'
1125
+ assert desc[0].type_code == ft.BLOB
1126
+ assert desc[0].null_ok is False
1127
+
1128
+ # NULL is not valid
1129
+ with self.assertRaises(self.conn.OperationalError):
1130
+ self.cur.execute(
1131
+ 'select numpy_string_mult(NULL, value) as res '
1132
+ 'from data order by id',
1133
+ )
1134
+
1135
+ def _test_polars_string_mult(self):
1136
+ self.cur.execute(
1137
+ 'select polars_string_mult(name, value) as res '
1138
+ 'from data order by id',
1139
+ )
1140
+
1141
+ assert [tuple(x) for x in self.cur] == [
1142
+ ('antelopesantelopes',),
1143
+ ('bearsbears',),
1144
+ ('catscatscatscatscats',),
1145
+ ('dogsdogsdogsdogs',),
1146
+ ('',),
1147
+ ]
1148
+
1149
+ desc = self.cur.description
1150
+ assert len(desc) == 1
1151
+ assert desc[0].name == 'res'
1152
+ assert desc[0].type_code == ft.BLOB
1153
+ assert desc[0].null_ok is False
1154
+
1155
+ # NULL is not valid
1156
+ with self.assertRaises(self.conn.OperationalError):
1157
+ self.cur.execute(
1158
+ 'select polars_string_mult(NULL, value) as res '
1159
+ 'from data order by id',
1160
+ )
1161
+
1162
+ def _test_arrow_string_mult(self):
1163
+ self.cur.execute(
1164
+ 'select arrow_string_mult(name, value) as res '
1165
+ 'from data order by id',
1166
+ )
1167
+
1168
+ assert [tuple(x) for x in self.cur] == [
1169
+ ('antelopesantelopes',),
1170
+ ('bearsbears',),
1171
+ ('catscatscatscatscats',),
1172
+ ('dogsdogsdogsdogs',),
1173
+ ('',),
1174
+ ]
1175
+
1176
+ desc = self.cur.description
1177
+ assert len(desc) == 1
1178
+ assert desc[0].name == 'res'
1179
+ assert desc[0].type_code == ft.BLOB
1180
+ assert desc[0].null_ok is False
1181
+
1182
+ # NULL is not valid
1183
+ with self.assertRaises(self.conn.OperationalError):
1184
+ self.cur.execute(
1185
+ 'select arrow_string_mult(NULL, value) as res '
1186
+ 'from data order by id',
1187
+ )
1188
+
1189
+ def test_nullable_string_mult(self):
1190
+ self.cur.execute(
1191
+ 'select nullable_string_mult(name, value) as res '
1192
+ 'from data_with_nulls order by id',
1193
+ )
1194
+
1195
+ assert [tuple(x) for x in self.cur] == [
1196
+ ('antelopesantelopes',),
1197
+ (None,),
1198
+ (None,),
1199
+ (None,),
1200
+ ('',),
1201
+ ]
1202
+
1203
+ desc = self.cur.description
1204
+ assert len(desc) == 1
1205
+ assert desc[0].name == 'res'
1206
+ assert desc[0].type_code == ft.BLOB
1207
+ assert desc[0].null_ok is True
1208
+
1209
+ def _test_varchar_mult(self):
1210
+ self.cur.execute(
1211
+ 'select varchar_mult(name, value) as res '
1212
+ 'from data order by id',
1213
+ )
1214
+
1215
+ assert [tuple(x) for x in self.cur] == [
1216
+ ('antelopesantelopes',),
1217
+ ('bearsbears',),
1218
+ ('catscatscatscatscats',),
1219
+ ('dogsdogsdogsdogs',),
1220
+ ('',),
1221
+ ]
1222
+
1223
+ desc = self.cur.description
1224
+ assert len(desc) == 1
1225
+ assert desc[0].name == 'res'
1226
+ assert desc[0].type_code == ft.BLOB
1227
+ assert desc[0].null_ok is False
1228
+
1229
+ # NULL is not valid
1230
+ with self.assertRaises(self.conn.OperationalError):
1231
+ self.cur.execute(
1232
+ 'select varchar_mult(NULL, value) as res '
1233
+ 'from data order by id',
1234
+ )
1235
+
1236
+ def _test_nullable_varchar_mult(self):
1237
+ self.cur.execute(
1238
+ 'select nullable_varchar_mult(name, value) as res '
1239
+ 'from data_with_nulls order by id',
1240
+ )
1241
+
1242
+ assert [tuple(x) for x in self.cur] == [
1243
+ ('antelopesantelopes',),
1244
+ (None,),
1245
+ (None,),
1246
+ (None,),
1247
+ ('',),
1248
+ ]
1249
+
1250
+ desc = self.cur.description
1251
+ assert len(desc) == 1
1252
+ assert desc[0].name == 'res'
1253
+ assert desc[0].type_code == ft.BLOB
1254
+ assert desc[0].null_ok is True
1255
+
1256
+ def test_numpy_fixed_strings(self):
1257
+ self.cur.execute('select * from numpy_fixed_strings()')
1258
+
1259
+ assert [tuple(x) for x in self.cur] == [
1260
+ ('hello',),
1261
+ ('hi there 😜',),
1262
+ ('😜 bye',),
1263
+ ]
1264
+
1265
+ desc = self.cur.description
1266
+ assert len(desc) == 1
1267
+ assert desc[0].name == 'res'
1268
+ assert desc[0].type_code == ft.BLOB
1269
+ assert desc[0].null_ok is False
1270
+
1271
+ def test_numpy_fixed_binary(self):
1272
+ self.cur.execute('select * from numpy_fixed_binary()')
1273
+
1274
+ assert [tuple(x) for x in self.cur] == [
1275
+ ('hello'.encode('utf8'),),
1276
+ ('hi there 😜'.encode('utf8'),),
1277
+ ('😜 bye'.encode('utf8'),),
1278
+ ]
1279
+
1280
+ desc = self.cur.description
1281
+ assert len(desc) == 1
1282
+ assert desc[0].name == 'res'
1283
+ assert desc[0].type_code == ft.BLOB
1284
+ assert desc[0].null_ok is False
1285
+
1286
+ def test_no_args_no_return_value(self):
1287
+ self.cur.execute('select no_args_no_return_value() as res')
1288
+
1289
+ assert [tuple(x) for x in self.cur] == [(None,)]
1290
+
1291
+ desc = self.cur.description
1292
+ assert len(desc) == 1
1293
+ assert desc[0].name == 'res'
1294
+ assert desc[0].type_code == ft.TINY
1295
+ assert desc[0].null_ok is True
1296
+
1297
+ def test_table_function(self):
1298
+ self.cur.execute('select * from table_function(5)')
1299
+
1300
+ assert [x[0] for x in self.cur] == [10, 10, 10, 10, 10]
1301
+
1302
+ desc = self.cur.description
1303
+ assert len(desc) == 1
1304
+ assert desc[0].name == 'a'
1305
+ assert desc[0].type_code == ft.LONGLONG
1306
+ assert desc[0].null_ok is False
1307
+
1308
+ def test_async_table_function(self):
1309
+ self.cur.execute('select * from async_table_function(5)')
1310
+
1311
+ assert [x[0] for x in self.cur] == [10, 10, 10, 10, 10]
1312
+
1313
+ desc = self.cur.description
1314
+ assert len(desc) == 1
1315
+ assert desc[0].name == 'a'
1316
+ assert desc[0].type_code == ft.LONGLONG
1317
+ assert desc[0].null_ok is False
1318
+
1319
+ def test_table_function_tuple(self):
1320
+ self.cur.execute('select * from table_function_tuple(3)')
1321
+
1322
+ out = list(self.cur)
1323
+
1324
+ assert out == [
1325
+ (10, 10.0, 'ten'),
1326
+ (10, 10.0, 'ten'),
1327
+ (10, 10.0, 'ten'),
1328
+ ]
1329
+
1330
+ desc = self.cur.description
1331
+ assert len(desc) == 3
1332
+ assert desc[0].name == 'c_int'
1333
+ assert desc[1].name == 'c_float'
1334
+ assert desc[2].name == 'c_str'
1335
+
1336
+ def test_table_function_struct(self):
1337
+ self.cur.execute('select * from table_function_struct(3)')
1338
+
1339
+ out = list(self.cur)
1340
+
1341
+ assert out == [
1342
+ (10, 10.0, 'ten'),
1343
+ (10, 10.0, 'ten'),
1344
+ (10, 10.0, 'ten'),
1345
+ ]
1346
+
1347
+ desc = self.cur.description
1348
+ assert len(desc) == 3
1349
+ assert desc[0].name == 'c_int'
1350
+ assert desc[1].name == 'c_float'
1351
+ assert desc[2].name == 'c_str'
1352
+
1353
+ def test_vec_function(self):
1354
+ self.cur.execute('select vec_function(5, 10) as res')
1355
+
1356
+ assert [tuple(x) for x in self.cur] == [(50.0,)]
1357
+
1358
+ def test_vec_function_ints(self):
1359
+ self.cur.execute('select vec_function_ints(5, 10) as res')
1360
+
1361
+ assert [tuple(x) for x in self.cur] == [(50,)]
1362
+
1363
+ def test_vec_function_df(self):
1364
+ self.cur.execute('select * from vec_function_df(5, 10)')
1365
+
1366
+ out = list(self.cur)
1367
+
1368
+ assert out == [
1369
+ (1, 1.1),
1370
+ (2, 2.2),
1371
+ (3, 3.3),
1372
+ ]
1373
+
1374
+ desc = self.cur.description
1375
+ assert len(desc) == 2
1376
+ assert desc[0].name == 'res'
1377
+ assert desc[0].type_code == ft.SHORT
1378
+ assert desc[0].null_ok is False
1379
+ assert desc[1].name == 'res2'
1380
+ assert desc[1].type_code == ft.DOUBLE
1381
+ assert desc[1].null_ok is False
1382
+
1383
+ def test_async_vec_function_df(self):
1384
+ self.cur.execute('select * from async_vec_function_df(5, 10)')
1385
+
1386
+ out = list(self.cur)
1387
+
1388
+ assert out == [
1389
+ (1, 1.1),
1390
+ (2, 2.2),
1391
+ (3, 3.3),
1392
+ ]
1393
+
1394
+ desc = self.cur.description
1395
+ assert len(desc) == 2
1396
+ assert desc[0].name == 'res'
1397
+ assert desc[0].type_code == ft.SHORT
1398
+ assert desc[0].null_ok is False
1399
+ assert desc[1].name == 'res2'
1400
+ assert desc[1].type_code == ft.DOUBLE
1401
+ assert desc[1].null_ok is False
1402
+
1403
+ def test_vec_function_ints_masked(self):
1404
+ self.cur.execute('select * from vec_function_ints_masked(5, 10)')
1405
+
1406
+ assert [tuple(x) for x in self.cur] == [(50,)]
1407
+
1408
+ desc = self.cur.description
1409
+ assert len(desc) == 1
1410
+ assert desc[0].name == 'res'
1411
+ assert desc[0].type_code == ft.SHORT
1412
+ assert desc[0].null_ok is True
1413
+
1414
+ self.cur.execute('select * from vec_function_ints_masked(NULL, 10)')
1415
+
1416
+ assert [tuple(x) for x in self.cur] == [(None,)]
1417
+
1418
+ desc = self.cur.description
1419
+ assert len(desc) == 1
1420
+ assert desc[0].name == 'res'
1421
+ assert desc[0].type_code == ft.SHORT
1422
+ assert desc[0].null_ok is True
1423
+
1424
+ self.cur.execute('select * from vec_function_ints_masked(5, NULL)')
1425
+
1426
+ assert [tuple(x) for x in self.cur] == [(None,)]
1427
+
1428
+ desc = self.cur.description
1429
+ assert len(desc) == 1
1430
+ assert desc[0].name == 'res'
1431
+ assert desc[0].type_code == ft.SHORT
1432
+ assert desc[0].null_ok is True
1433
+
1434
+ def test_vec_function_ints_masked2(self):
1435
+ self.cur.execute('select * from vec_function_ints_masked2(5, 10)')
1436
+
1437
+ assert [tuple(x) for x in self.cur] == [(50, 50)]
1438
+
1439
+ desc = self.cur.description
1440
+ assert len(desc) == 2
1441
+ assert desc[0].name == 'res'
1442
+ assert desc[0].type_code == ft.SHORT
1443
+ assert desc[0].null_ok is True
1444
+ assert desc[1].name == 'res2'
1445
+ assert desc[1].type_code == ft.SHORT
1446
+ assert desc[1].null_ok is True
1447
+
1448
+ self.cur.execute('select * from vec_function_ints_masked2(NULL, 10)')
1449
+
1450
+ assert [tuple(x) for x in self.cur] == [(None, None)]
1451
+
1452
+ desc = self.cur.description
1453
+ assert len(desc) == 2
1454
+ assert desc[0].name == 'res'
1455
+ assert desc[0].type_code == ft.SHORT
1456
+ assert desc[0].null_ok is True
1457
+ assert desc[1].name == 'res2'
1458
+ assert desc[1].type_code == ft.SHORT
1459
+ assert desc[1].null_ok is True
1460
+
1461
+ self.cur.execute('select * from vec_function_ints_masked2(5, NULL)')
1462
+
1463
+ assert [tuple(x) for x in self.cur] == [(None, None)]
1464
+
1465
+ desc = self.cur.description
1466
+ assert len(desc) == 2
1467
+ assert desc[0].name == 'res'
1468
+ assert desc[0].type_code == ft.SHORT
1469
+ assert desc[0].null_ok is True
1470
+ assert desc[1].name == 'res2'
1471
+ assert desc[1].type_code == ft.SHORT
1472
+ assert desc[1].null_ok is True