Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
singlestore-labs
GitHub Repository: singlestore-labs/singlestoredb-python
Path: blob/main/singlestoredb/tests/test_ext_func.py
469 views
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
1473
1474