singlestoredb 1.14.2__py3-none-any.whl → 1.15.0__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.

Potentially problematic release.


This version of singlestoredb might be problematic. Click here for more details.

@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
  # mypy: disable-error-code="type-arg"
3
+ import asyncio
4
+ import time
3
5
  import typing
4
6
  from typing import List
5
7
  from typing import NamedTuple
@@ -7,10 +9,6 @@ from typing import Optional
7
9
  from typing import Tuple
8
10
 
9
11
  import numpy as np
10
- import numpy.typing as npt
11
- import pandas as pd
12
- import polars as pl
13
- import pyarrow as pa
14
12
 
15
13
  import singlestoredb.functions.dtypes as dt
16
14
  from singlestoredb.functions import Masked
@@ -24,6 +22,10 @@ from singlestoredb.functions.dtypes import MEDIUMINT
24
22
  from singlestoredb.functions.dtypes import SMALLINT
25
23
  from singlestoredb.functions.dtypes import TEXT
26
24
  from singlestoredb.functions.dtypes import TINYINT
25
+ from singlestoredb.functions.typing import numpy as npt
26
+ from singlestoredb.functions.typing import pandas as pdt
27
+ from singlestoredb.functions.typing import polars as plt
28
+ from singlestoredb.functions.typing import pyarrow as pat
27
29
 
28
30
 
29
31
  @udf
@@ -36,19 +38,44 @@ def double_mult(x: float, y: float) -> float:
36
38
  return x * y
37
39
 
38
40
 
41
+ @udf(timeout=2)
42
+ def timeout_double_mult(x: float, y: float) -> float:
43
+ time.sleep(5)
44
+ return x * y
45
+
46
+
47
+ @udf
48
+ async def async_double_mult(x: float, y: float) -> float:
49
+ return x * y
50
+
51
+
52
+ @udf(timeout=2)
53
+ async def async_timeout_double_mult(x: float, y: float) -> float:
54
+ await asyncio.sleep(5)
55
+ return x * y
56
+
57
+
39
58
  @udf(
40
59
  args=[DOUBLE(nullable=False), DOUBLE(nullable=False)],
41
60
  returns=DOUBLE(nullable=False),
42
61
  )
43
- def pandas_double_mult(x: pd.Series, y: pd.Series) -> pd.Series:
62
+ def pandas_double_mult(x: pdt.Series, y: pdt.Series) -> pdt.Series:
44
63
  return x * y
45
64
 
46
65
 
47
66
  @udf
48
67
  def numpy_double_mult(
49
- x: npt.NDArray[np.float64],
50
- y: npt.NDArray[np.float64],
51
- ) -> npt.NDArray[np.float64]:
68
+ x: npt.Float64Array,
69
+ y: npt.Float64Array,
70
+ ) -> npt.Float64Array:
71
+ return x * y
72
+
73
+
74
+ @udf
75
+ async def async_numpy_double_mult(
76
+ x: npt.Float64Array,
77
+ y: npt.Float64Array,
78
+ ) -> npt.Float64Array:
52
79
  return x * y
53
80
 
54
81
 
@@ -56,7 +83,7 @@ def numpy_double_mult(
56
83
  args=[DOUBLE(nullable=False), DOUBLE(nullable=False)],
57
84
  returns=DOUBLE(nullable=False),
58
85
  )
59
- def arrow_double_mult(x: pa.Array, y: pa.Array) -> pa.Array:
86
+ def arrow_double_mult(x: pat.Array, y: pat.Array) -> pat.Array:
60
87
  import pyarrow.compute as pc
61
88
  return pc.multiply(x, y)
62
89
 
@@ -65,7 +92,7 @@ def arrow_double_mult(x: pa.Array, y: pa.Array) -> pa.Array:
65
92
  args=[DOUBLE(nullable=False), DOUBLE(nullable=False)],
66
93
  returns=DOUBLE(nullable=False),
67
94
  )
68
- def polars_double_mult(x: pl.Series, y: pl.Series) -> pl.Series:
95
+ def polars_double_mult(x: plt.Series, y: plt.Series) -> plt.Series:
69
96
  return x * y
70
97
 
71
98
 
@@ -106,12 +133,12 @@ def tinyint_mult(x: Optional[int], y: Optional[int]) -> Optional[int]:
106
133
 
107
134
 
108
135
  @tinyint_udf
109
- def pandas_tinyint_mult(x: pd.Series, y: pd.Series) -> pd.Series:
136
+ def pandas_tinyint_mult(x: pdt.Series, y: pdt.Series) -> pdt.Series:
110
137
  return x * y
111
138
 
112
139
 
113
140
  @tinyint_udf
114
- def polars_tinyint_mult(x: pl.Series, y: pl.Series) -> pl.Series:
141
+ def polars_tinyint_mult(x: plt.Series, y: plt.Series) -> plt.Series:
115
142
  return x * y
116
143
 
117
144
 
@@ -121,7 +148,7 @@ def numpy_tinyint_mult(x: np.ndarray, y: np.ndarray) -> np.ndarray:
121
148
 
122
149
 
123
150
  @tinyint_udf
124
- def arrow_tinyint_mult(x: pa.Array, y: pa.Array) -> pa.Array:
151
+ def arrow_tinyint_mult(x: pat.Array, y: pat.Array) -> pat.Array:
125
152
  import pyarrow.compute as pc
126
153
  return pc.multiply(x, y)
127
154
 
@@ -144,12 +171,12 @@ def smallint_mult(x: Optional[int], y: Optional[int]) -> Optional[int]:
144
171
 
145
172
 
146
173
  @smallint_udf
147
- def pandas_smallint_mult(x: pd.Series, y: pd.Series) -> pd.Series:
174
+ def pandas_smallint_mult(x: pdt.Series, y: pdt.Series) -> pdt.Series:
148
175
  return x * y
149
176
 
150
177
 
151
178
  @smallint_udf
152
- def polars_smallint_mult(x: pl.Series, y: pl.Series) -> pl.Series:
179
+ def polars_smallint_mult(x: plt.Series, y: plt.Series) -> plt.Series:
153
180
  return x * y
154
181
 
155
182
 
@@ -159,7 +186,7 @@ def numpy_smallint_mult(x: np.ndarray, y: np.ndarray) -> np.ndarray:
159
186
 
160
187
 
161
188
  @smallint_udf
162
- def arrow_smallint_mult(x: pa.Array, y: pa.Array) -> pa.Array:
189
+ def arrow_smallint_mult(x: pat.Array, y: pat.Array) -> pat.Array:
163
190
  import pyarrow.compute as pc
164
191
  return pc.multiply(x, y)
165
192
 
@@ -183,12 +210,12 @@ def mediumint_mult(x: Optional[int], y: Optional[int]) -> Optional[int]:
183
210
 
184
211
 
185
212
  @mediumint_udf
186
- def pandas_mediumint_mult(x: pd.Series, y: pd.Series) -> pd.Series:
213
+ def pandas_mediumint_mult(x: pdt.Series, y: pdt.Series) -> pdt.Series:
187
214
  return x * y
188
215
 
189
216
 
190
217
  @mediumint_udf
191
- def polars_mediumint_mult(x: pl.Series, y: pl.Series) -> pl.Series:
218
+ def polars_mediumint_mult(x: plt.Series, y: plt.Series) -> plt.Series:
192
219
  return x * y
193
220
 
194
221
 
@@ -198,7 +225,7 @@ def numpy_mediumint_mult(x: np.ndarray, y: np.ndarray) -> np.ndarray:
198
225
 
199
226
 
200
227
  @mediumint_udf
201
- def arrow_mediumint_mult(x: pa.Array, y: pa.Array) -> pa.Array:
228
+ def arrow_mediumint_mult(x: pat.Array, y: pat.Array) -> pat.Array:
202
229
  import pyarrow.compute as pc
203
230
  return pc.multiply(x, y)
204
231
 
@@ -222,12 +249,12 @@ def bigint_mult(x: Optional[int], y: Optional[int]) -> Optional[int]:
222
249
 
223
250
 
224
251
  @bigint_udf
225
- def pandas_bigint_mult(x: pd.Series, y: pd.Series) -> pd.Series:
252
+ def pandas_bigint_mult(x: pdt.Series, y: pdt.Series) -> pdt.Series:
226
253
  return x * y
227
254
 
228
255
 
229
256
  @bigint_udf
230
- def polars_bigint_mult(x: pl.Series, y: pl.Series) -> pl.Series:
257
+ def polars_bigint_mult(x: plt.Series, y: plt.Series) -> plt.Series:
231
258
  return x * y
232
259
 
233
260
 
@@ -237,7 +264,7 @@ def numpy_bigint_mult(x: np.ndarray, y: np.ndarray) -> np.ndarray:
237
264
 
238
265
 
239
266
  @bigint_udf
240
- def arrow_bigint_mult(x: pa.Array, y: pa.Array) -> pa.Array:
267
+ def arrow_bigint_mult(x: pat.Array, y: pat.Array) -> pat.Array:
241
268
  import pyarrow.compute as pc
242
269
  return pc.multiply(x, y)
243
270
 
@@ -261,12 +288,12 @@ def nullable_tinyint_mult(x: Optional[int], y: Optional[int]) -> Optional[int]:
261
288
 
262
289
 
263
290
  @nullable_tinyint_udf
264
- def pandas_nullable_tinyint_mult(x: pd.Series, y: pd.Series) -> pd.Series:
291
+ def pandas_nullable_tinyint_mult(x: pdt.Series, y: pdt.Series) -> pdt.Series:
265
292
  return x * y
266
293
 
267
294
 
268
295
  @nullable_tinyint_udf
269
- def polars_nullable_tinyint_mult(x: pl.Series, y: pl.Series) -> pl.Series:
296
+ def polars_nullable_tinyint_mult(x: plt.Series, y: plt.Series) -> plt.Series:
270
297
  return x * y
271
298
 
272
299
 
@@ -276,7 +303,7 @@ def numpy_nullable_tinyint_mult(x: np.ndarray, y: np.ndarray) -> np.ndarray:
276
303
 
277
304
 
278
305
  @nullable_tinyint_udf
279
- def arrow_nullable_tinyint_mult(x: pa.Array, y: pa.Array) -> pa.Array:
306
+ def arrow_nullable_tinyint_mult(x: pat.Array, y: pat.Array) -> pat.Array:
280
307
  import pyarrow.compute as pc
281
308
  return pc.multiply(x, y)
282
309
 
@@ -299,12 +326,12 @@ def nullable_smallint_mult(x: Optional[int], y: Optional[int]) -> Optional[int]:
299
326
 
300
327
 
301
328
  @nullable_smallint_udf
302
- def pandas_nullable_smallint_mult(x: pd.Series, y: pd.Series) -> pd.Series:
329
+ def pandas_nullable_smallint_mult(x: pdt.Series, y: pdt.Series) -> pdt.Series:
303
330
  return x * y
304
331
 
305
332
 
306
333
  @nullable_smallint_udf
307
- def polars_nullable_smallint_mult(x: pl.Series, y: pl.Series) -> pl.Series:
334
+ def polars_nullable_smallint_mult(x: plt.Series, y: plt.Series) -> plt.Series:
308
335
  return x * y
309
336
 
310
337
 
@@ -314,7 +341,7 @@ def numpy_nullable_smallint_mult(x: np.ndarray, y: np.ndarray) -> np.ndarray:
314
341
 
315
342
 
316
343
  @nullable_smallint_udf
317
- def arrow_nullable_smallint_mult(x: pa.Array, y: pa.Array) -> pa.Array:
344
+ def arrow_nullable_smallint_mult(x: pat.Array, y: pat.Array) -> pat.Array:
318
345
  import pyarrow.compute as pc
319
346
  return pc.multiply(x, y)
320
347
 
@@ -338,12 +365,12 @@ def nullable_mediumint_mult(x: Optional[int], y: Optional[int]) -> Optional[int]
338
365
 
339
366
 
340
367
  @nullable_mediumint_udf
341
- def pandas_nullable_mediumint_mult(x: pd.Series, y: pd.Series) -> pd.Series:
368
+ def pandas_nullable_mediumint_mult(x: pdt.Series, y: pdt.Series) -> pdt.Series:
342
369
  return x * y
343
370
 
344
371
 
345
372
  @nullable_mediumint_udf
346
- def polars_nullable_mediumint_mult(x: pl.Series, y: pl.Series) -> pl.Series:
373
+ def polars_nullable_mediumint_mult(x: plt.Series, y: plt.Series) -> plt.Series:
347
374
  return x * y
348
375
 
349
376
 
@@ -353,7 +380,7 @@ def numpy_nullable_mediumint_mult(x: np.ndarray, y: np.ndarray) -> np.ndarray:
353
380
 
354
381
 
355
382
  @nullable_mediumint_udf
356
- def arrow_nullable_mediumint_mult(x: pa.Array, y: pa.Array) -> pa.Array:
383
+ def arrow_nullable_mediumint_mult(x: pat.Array, y: pat.Array) -> pat.Array:
357
384
  import pyarrow.compute as pc
358
385
  return pc.multiply(x, y)
359
386
 
@@ -377,12 +404,12 @@ def nullable_bigint_mult(x: Optional[int], y: Optional[int]) -> Optional[int]:
377
404
 
378
405
 
379
406
  @nullable_bigint_udf
380
- def pandas_nullable_bigint_mult(x: pd.Series, y: pd.Series) -> pd.Series:
407
+ def pandas_nullable_bigint_mult(x: pdt.Series, y: pdt.Series) -> pdt.Series:
381
408
  return x * y
382
409
 
383
410
 
384
411
  @nullable_bigint_udf
385
- def polars_nullable_bigint_mult(x: pl.Series, y: pl.Series) -> pl.Series:
412
+ def polars_nullable_bigint_mult(x: plt.Series, y: plt.Series) -> plt.Series:
386
413
  return x * y
387
414
 
388
415
 
@@ -392,7 +419,7 @@ def numpy_nullable_bigint_mult(x: np.ndarray, y: np.ndarray) -> np.ndarray:
392
419
 
393
420
 
394
421
  @nullable_bigint_udf
395
- def arrow_nullable_bigint_mult(x: pa.Array, y: pa.Array) -> pa.Array:
422
+ def arrow_nullable_bigint_mult(x: pat.Array, y: pat.Array) -> pat.Array:
396
423
  import pyarrow.compute as pc
397
424
  return pc.multiply(x, y)
398
425
 
@@ -410,7 +437,7 @@ def string_mult(x: str, times: int) -> str:
410
437
 
411
438
 
412
439
  @udf(args=[TEXT(nullable=False), BIGINT(nullable=False)], returns=TEXT(nullable=False))
413
- def pandas_string_mult(x: pd.Series, times: pd.Series) -> pd.Series:
440
+ def pandas_string_mult(x: pdt.Series, times: pdt.Series) -> pdt.Series:
414
441
  return x * times
415
442
 
416
443
 
@@ -447,8 +474,8 @@ def nullable_string_mult(x: Optional[str], times: Optional[int]) -> Optional[str
447
474
  returns=TINYINT(nullable=True),
448
475
  )
449
476
  def pandas_nullable_tinyint_mult_with_masks(
450
- x: Masked[pd.Series], y: Masked[pd.Series],
451
- ) -> Masked[pd.Series]:
477
+ x: Masked[pdt.Series], y: Masked[pdt.Series],
478
+ ) -> Masked[pdt.Series]:
452
479
  x_data, x_nulls = x
453
480
  y_data, y_nulls = y
454
481
  return Masked(x_data * y_data, x_nulls | y_nulls)
@@ -468,8 +495,8 @@ def numpy_nullable_tinyint_mult_with_masks(
468
495
  returns=TINYINT(nullable=True),
469
496
  )
470
497
  def polars_nullable_tinyint_mult_with_masks(
471
- x: Masked[pl.Series], y: Masked[pl.Series],
472
- ) -> Masked[pl.Series]:
498
+ x: Masked[plt.Series], y: Masked[plt.Series],
499
+ ) -> Masked[plt.Series]:
473
500
  x_data, x_nulls = x
474
501
  y_data, y_nulls = y
475
502
  return Masked(x_data * y_data, x_nulls | y_nulls)
@@ -480,8 +507,8 @@ def polars_nullable_tinyint_mult_with_masks(
480
507
  returns=TINYINT(nullable=True),
481
508
  )
482
509
  def arrow_nullable_tinyint_mult_with_masks(
483
- x: Masked[pa.Array], y: Masked[pa.Array],
484
- ) -> Masked[pa.Array]:
510
+ x: Masked[pat.Array], y: Masked[pat.Array],
511
+ ) -> Masked[pat.Array]:
485
512
  import pyarrow.compute as pc
486
513
  x_data, x_nulls = x
487
514
  y_data, y_nulls = y
@@ -489,7 +516,7 @@ def arrow_nullable_tinyint_mult_with_masks(
489
516
 
490
517
 
491
518
  @udf(returns=[TEXT(nullable=False, name='res')])
492
- def numpy_fixed_strings() -> Table[npt.NDArray[np.str_]]:
519
+ def numpy_fixed_strings() -> Table[npt.StrArray]:
493
520
  out = np.array(
494
521
  [
495
522
  'hello',
@@ -502,7 +529,7 @@ def numpy_fixed_strings() -> Table[npt.NDArray[np.str_]]:
502
529
 
503
530
 
504
531
  @udf(returns=[TEXT(nullable=False, name='res'), TINYINT(nullable=False, name='res2')])
505
- def numpy_fixed_strings_2() -> Table[npt.NDArray[np.str_], npt.NDArray[np.int8]]:
532
+ def numpy_fixed_strings_2() -> Table[npt.StrArray, npt.Int8Array]:
506
533
  out = np.array(
507
534
  [
508
535
  'hello',
@@ -515,7 +542,7 @@ def numpy_fixed_strings_2() -> Table[npt.NDArray[np.str_], npt.NDArray[np.int8]]
515
542
 
516
543
 
517
544
  @udf(returns=[BLOB(nullable=False, name='res')])
518
- def numpy_fixed_binary() -> Table[npt.NDArray[np.bytes_]]:
545
+ def numpy_fixed_binary() -> Table[npt.BytesArray]:
519
546
  out = np.array(
520
547
  [
521
548
  'hello'.encode('utf8'),
@@ -537,6 +564,11 @@ def table_function(n: int) -> Table[List[int]]:
537
564
  return Table([10] * n)
538
565
 
539
566
 
567
+ @udf
568
+ async def async_table_function(n: int) -> Table[List[int]]:
569
+ return Table([10] * n)
570
+
571
+
540
572
  @udf(
541
573
  returns=[
542
574
  dt.INT(name='c_int', nullable=False),
@@ -561,8 +593,8 @@ def table_function_struct(n: int) -> Table[List[MyTable]]:
561
593
 
562
594
  @udf
563
595
  def vec_function(
564
- x: npt.NDArray[np.float64], y: npt.NDArray[np.float64],
565
- ) -> npt.NDArray[np.float64]:
596
+ x: npt.Float64Array, y: npt.Float64Array,
597
+ ) -> npt.Float64Array:
566
598
  return x * y
567
599
 
568
600
 
@@ -577,8 +609,8 @@ class VecOutputs(typing.NamedTuple):
577
609
 
578
610
  @udf(args=VecInputs, returns=VecOutputs)
579
611
  def vec_function_ints(
580
- x: npt.NDArray[np.int_], y: npt.NDArray[np.int_],
581
- ) -> npt.NDArray[np.int_]:
612
+ x: npt.IntArray, y: npt.IntArray,
613
+ ) -> npt.IntArray:
582
614
  return x * y
583
615
 
584
616
 
@@ -589,9 +621,16 @@ class DFOutputs(typing.NamedTuple):
589
621
 
590
622
  @udf(args=VecInputs, returns=DFOutputs)
591
623
  def vec_function_df(
592
- x: npt.NDArray[np.int_], y: npt.NDArray[np.int_],
593
- ) -> Table[pd.DataFrame]:
594
- return pd.DataFrame(dict(res=[1, 2, 3], res2=[1.1, 2.2, 3.3]))
624
+ x: npt.IntArray, y: npt.IntArray,
625
+ ) -> Table[pdt.DataFrame]:
626
+ return pdt.DataFrame(dict(res=[1, 2, 3], res2=[1.1, 2.2, 3.3]))
627
+
628
+
629
+ @udf(args=VecInputs, returns=DFOutputs)
630
+ async def async_vec_function_df(
631
+ x: npt.IntArray, y: npt.IntArray,
632
+ ) -> Table[pdt.DataFrame]:
633
+ return pdt.DataFrame(dict(res=[1, 2, 3], res2=[1.1, 2.2, 3.3]))
595
634
 
596
635
 
597
636
  class MaskOutputs(typing.NamedTuple):
@@ -600,8 +639,8 @@ class MaskOutputs(typing.NamedTuple):
600
639
 
601
640
  @udf(args=VecInputs, returns=MaskOutputs)
602
641
  def vec_function_ints_masked(
603
- x: Masked[npt.NDArray[np.int_]], y: Masked[npt.NDArray[np.int_]],
604
- ) -> Table[Masked[npt.NDArray[np.int_]]]:
642
+ x: Masked[npt.IntArray], y: Masked[npt.IntArray],
643
+ ) -> Table[Masked[npt.IntArray]]:
605
644
  x_data, x_nulls = x
606
645
  y_data, y_nulls = y
607
646
  return Table(Masked(x_data * y_data, x_nulls | y_nulls))
@@ -614,8 +653,8 @@ class MaskOutputs2(typing.NamedTuple):
614
653
 
615
654
  @udf(args=VecInputs, returns=MaskOutputs2)
616
655
  def vec_function_ints_masked2(
617
- x: Masked[npt.NDArray[np.int_]], y: Masked[npt.NDArray[np.int_]],
618
- ) -> Table[Masked[npt.NDArray[np.int_]], Masked[npt.NDArray[np.int_]]]:
656
+ x: Masked[npt.IntArray], y: Masked[npt.IntArray],
657
+ ) -> Table[Masked[npt.IntArray], Masked[npt.IntArray]]:
619
658
  x_data, x_nulls = x
620
659
  y_data, y_nulls = y
621
660
  return Table(
@@ -14,6 +14,28 @@ INSERT INTO data SET id='e', name='elephants', value=0;
14
14
 
15
15
  COMMIT;
16
16
 
17
+ CREATE ROWSTORE TABLE IF NOT EXISTS longer_data (
18
+ id VARCHAR(255) NOT NULL,
19
+ name VARCHAR(255) NOT NULL,
20
+ value BIGINT NOT NULL,
21
+ PRIMARY KEY (id) USING HASH
22
+ ) DEFAULT CHARSET = utf8 COLLATE = utf8_unicode_ci;
23
+
24
+ INSERT INTO longer_data SET id='a', name='antelopes', value=2;
25
+ INSERT INTO longer_data SET id='b', name='bears', value=2;
26
+ INSERT INTO longer_data SET id='c', name='cats', value=5;
27
+ INSERT INTO longer_data SET id='d', name='dogs', value=4;
28
+ INSERT INTO longer_data SET id='e', name='elephants', value=0;
29
+ INSERT INTO longer_data SET id='f', name='ferrets', value=2;
30
+ INSERT INTO longer_data SET id='g', name='gorillas', value=4;
31
+ INSERT INTO longer_data SET id='h', name='horses', value=6;
32
+ INSERT INTO longer_data SET id='i', name='iguanas', value=2;
33
+ INSERT INTO longer_data SET id='j', name='jaguars', value=0;
34
+ INSERT INTO longer_data SET id='k', name='kiwis', value=0;
35
+ INSERT INTO longer_data SET id='l', name='leopards', value=1;
36
+
37
+ COMMIT;
38
+
17
39
  CREATE ROWSTORE TABLE IF NOT EXISTS data_with_nulls (
18
40
  id VARCHAR(255) NOT NULL,
19
41
  name VARCHAR(255),
@@ -162,6 +162,43 @@ class TestExtFunc(unittest.TestCase):
162
162
  'from data order by id',
163
163
  )
164
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
+
165
202
  def test_pandas_double_mult(self):
166
203
  self.cur.execute(
167
204
  'select pandas_double_mult(value, 100) as res '
@@ -206,6 +243,28 @@ class TestExtFunc(unittest.TestCase):
206
243
  'from data order by id',
207
244
  )
208
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
+
209
268
  def test_arrow_double_mult(self):
210
269
  self.cur.execute(
211
270
  'select arrow_double_mult(value, 100) as res '
@@ -1246,6 +1305,17 @@ class TestExtFunc(unittest.TestCase):
1246
1305
  assert desc[0].type_code == ft.LONGLONG
1247
1306
  assert desc[0].null_ok is False
1248
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
+
1249
1319
  def test_table_function_tuple(self):
1250
1320
  self.cur.execute('select * from table_function_tuple(3)')
1251
1321
 
@@ -1310,6 +1380,26 @@ class TestExtFunc(unittest.TestCase):
1310
1380
  assert desc[1].type_code == ft.DOUBLE
1311
1381
  assert desc[1].null_ok is False
1312
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
+
1313
1403
  def test_vec_function_ints_masked(self):
1314
1404
  self.cur.execute('select * from vec_function_ints_masked(5, 10)')
1315
1405