Path: blob/main/singlestoredb/tests/test_ext_func.py
469 views
#!/usr/bin/env python1# type: ignore2"""Test SingleStoreDB external functions."""3import os4import socket5import subprocess6import time7import unittest89import requests1011import singlestoredb as s212import singlestoredb.mysql.constants.FIELD_TYPE as ft13from . import ext_funcs14from . import utils15from singlestoredb.functions.ext.asgi import create_app161718try:19s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)20s.connect(('8.8.8.8', 80))21HTTP_HOST = s.getsockname()[0]22except Exception:23HTTP_HOST = '127.0.0.1'24finally:25s.close()262728def get_open_port() -> int:29"""Find an open port number."""30s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)31s.bind(('', 0))32s.listen(1)33port = s.getsockname()[1]34s.close()35return port363738def start_http_server(database, data_format='rowdat_1'):39"""Start an external function server."""40port = get_open_port()41print(f'Start UDF HTTP server on http://{HTTP_HOST}:{port}')42proc = subprocess.Popen(43['uvicorn', 'singlestoredb.functions.ext.asgi:create_app'],44env=dict(45PATH=os.environ['PATH'],46PYTHONPATH=os.environ.get('PYTHONPATH', ''),47UVICORN_HOST=str(HTTP_HOST),48UVICORN_PORT=str(port),49UVICORN_FACTORY='1',50SINGLESTOREDB_EXT_FUNCTIONS='singlestoredb.tests.ext_funcs',51SINGLESTOREDB_PURE_PYTHON=os.environ.get('SINGLESTOREDB_PURE_PYTHON', '0'),52),53)5455# Wait for server to be available56retries = 1057while retries > 0:58try:59out = requests.get(f'http://{HTTP_HOST}:{port}/show/create_function')60if out.status_code == 200:61break62except Exception:63pass64time.sleep(3)65retries -= 16667app = create_app(68ext_funcs,69url=f'http://{HTTP_HOST}:{port}/invoke',70data_format=data_format,71)72app.register_functions(73database=database,74)7576with s2.connect(database=database) as conn:77with conn.cursor() as cur:78cur.execute('set global enable_external_functions=on')79cur.execute('show functions')80for item in list(cur):81cur.execute(f'show create function `{item[0]}`')82for func in list(cur):83print(*func)8485return proc, HTTP_HOST, port868788def stop_http_server(proc, database):89"""Stop the external function server."""90proc.terminate()91app = create_app(ext_funcs)92app.drop_functions(database=database)939495class TestExtFunc(unittest.TestCase):9697dbname: str = ''98dbexisted: bool = False99http_server = None100http_host = '127.0.0.1'101http_port = 0102103@classmethod104def setUpClass(cls):105sql_file = os.path.join(os.path.dirname(__file__), 'test.sql')106cls.dbname, cls.dbexisted = utils.load_sql(sql_file)107cls.http_server, cls.http_host, cls.http_port = \108start_http_server(cls.dbname, 'rowdat_1')109110@classmethod111def tearDownClass(cls):112stop_http_server(cls.http_server, cls.dbname)113cls.http_server = None114cls.http_host = '127.0.0.1'115cls.http_port = 0116if not cls.dbexisted:117utils.drop_database(cls.dbname)118119def setUp(self):120self.conn = s2.connect(database=type(self).dbname)121self.cur = self.conn.cursor()122123def tearDown(self):124try:125if self.cur is not None:126self.cur.close()127except Exception:128# traceback.print_exc()129pass130131try:132if self.conn is not None:133self.conn.close()134except Exception:135# traceback.print_exc()136pass137138def test_show_create_function(self):139out = requests.get(140f'http://{type(self).http_host}:{type(self).http_port}'141'/show/create_function',142)143print(out.text)144145def test_double_mult(self):146self.cur.execute('select double_mult(value, 100) as res from data order by id')147148assert [tuple(x) for x in self.cur] == \149[(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]150151desc = self.cur.description152assert len(desc) == 1153assert desc[0].name == 'res'154assert desc[0].type_code == ft.DOUBLE155assert desc[0].null_ok is False156157# NULL is not valid158with self.assertRaises(self.conn.OperationalError):159self.cur.execute(160'select double_mult(value, NULL) as res '161'from data order by id',162)163164def test_timeout_double_mult(self):165with self.assertRaises(self.conn.OperationalError) as exc:166self.cur.execute(167'select timeout_double_mult(value, 100) as res '168'from longer_data order by id',169)170assert 'timeout' in str(exc.exception).lower()171172def test_async_double_mult(self):173self.cur.execute(174'select async_double_mult(value, 100) as res from data order by id',175)176177assert [tuple(x) for x in self.cur] == \178[(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]179180desc = self.cur.description181assert len(desc) == 1182assert desc[0].name == 'res'183assert desc[0].type_code == ft.DOUBLE184assert desc[0].null_ok is False185186# NULL is not valid187with self.assertRaises(self.conn.OperationalError):188self.cur.execute(189'select async_double_mult(value, NULL) as res '190'from data order by id',191)192193def test_async_timeout_double_mult(self):194with self.assertRaises(self.conn.OperationalError) as exc:195self.cur.execute(196'select async_timeout_double_mult(value, 100) as res '197'from longer_data order by id',198)199assert 'timeout' in str(exc.exception).lower()200201def test_pandas_double_mult(self):202self.cur.execute(203'select pandas_double_mult(value, 100) as res '204'from data order by id',205)206207assert [tuple(x) for x in self.cur] == \208[(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]209210desc = self.cur.description211assert len(desc) == 1212assert desc[0].name == 'res'213assert desc[0].type_code == ft.DOUBLE214assert desc[0].null_ok is False215216# NULL is not valid217with self.assertRaises(self.conn.OperationalError):218self.cur.execute(219'select pandas_double_mult(value, NULL) as res '220'from data order by id',221)222223def test_numpy_double_mult(self):224self.cur.execute(225'select numpy_double_mult(value, 100) as res '226'from data order by id',227)228229assert [tuple(x) for x in self.cur] == \230[(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]231232desc = self.cur.description233assert len(desc) == 1234assert desc[0].name == 'res'235assert desc[0].type_code == ft.DOUBLE236assert desc[0].null_ok is False237238# NULL is not valid239with self.assertRaises(self.conn.OperationalError):240self.cur.execute(241'select numpy_double_mult(value, NULL) as res '242'from data order by id',243)244245def test_async_numpy_double_mult(self):246self.cur.execute(247'select async_numpy_double_mult(value, 100) as res '248'from data order by id',249)250251assert [tuple(x) for x in self.cur] == \252[(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]253254desc = self.cur.description255assert len(desc) == 1256assert desc[0].name == 'res'257assert desc[0].type_code == ft.DOUBLE258assert desc[0].null_ok is False259260# NULL is not valid261with self.assertRaises(self.conn.OperationalError):262self.cur.execute(263'select async_numpy_double_mult(value, NULL) as res '264'from data order by id',265)266267def test_arrow_double_mult(self):268self.cur.execute(269'select arrow_double_mult(value, 100) as res '270'from data order by id',271)272273assert [tuple(x) for x in self.cur] == \274[(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]275276desc = self.cur.description277assert len(desc) == 1278assert desc[0].name == 'res'279assert desc[0].type_code == ft.DOUBLE280assert desc[0].null_ok is False281282# NULL is not valid283with self.assertRaises(self.conn.OperationalError):284self.cur.execute(285'select arrow_double_mult(value, NULL) as res '286'from data order by id',287)288289def test_polars_double_mult(self):290self.cur.execute(291'select polars_double_mult(value, 100) as res '292'from data order by id',293)294295assert [tuple(x) for x in self.cur] == \296[(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]297298desc = self.cur.description299assert len(desc) == 1300assert desc[0].name == 'res'301assert desc[0].type_code == ft.DOUBLE302assert desc[0].null_ok is False303304# NULL is not valid305with self.assertRaises(self.conn.OperationalError):306self.cur.execute(307'select polars_double_mult(value, NULL) as res '308'from data order by id',309)310311def test_nullable_double_mult(self):312self.cur.execute(313'select nullable_double_mult(value, 100) as res from '314'data_with_nulls order by id',315)316317assert [tuple(x) for x in self.cur] == \318[(200.0,), (200.0,), (500.0,), (None,), (0.0,)]319320desc = self.cur.description321assert len(desc) == 1322assert desc[0].name == 'res'323assert desc[0].type_code == ft.DOUBLE324assert desc[0].null_ok is True325326self.cur.execute(327'select nullable_double_mult(value, NULL) as res '328'from data_with_nulls order by id',329)330331assert [tuple(x) for x in self.cur] == \332[(None,), (None,), (None,), (None,), (None,)]333334def test_float_mult(self):335self.cur.execute(336'select float_mult(value, 100) as res '337'from data order by id',338)339340assert [tuple(x) for x in self.cur] == \341[(200.0,), (200.0,), (500.0,), (400.0,), (0.0,)]342343desc = self.cur.description344assert len(desc) == 1345assert desc[0].name == 'res'346assert desc[0].type_code == ft.FLOAT347assert desc[0].null_ok is False348349# NULL is not valid350with self.assertRaises(self.conn.OperationalError):351self.cur.execute(352'select float_mult(value, NULL) as res '353'from data order by id',354)355356def test_nullable_float_mult(self):357self.cur.execute(358'select nullable_float_mult(value, 100) as res '359'from data_with_nulls order by id',360)361362assert [tuple(x) for x in self.cur] == \363[(200.0,), (200.0,), (500.0,), (None,), (0.0,)]364365desc = self.cur.description366assert len(desc) == 1367assert desc[0].name == 'res'368assert desc[0].type_code == ft.FLOAT369assert desc[0].null_ok is True370371self.cur.execute(372'select nullable_float_mult(value, NULL) as res '373'from data_with_nulls order by id',374)375376assert [tuple(x) for x in self.cur] == \377[(None,), (None,), (None,), (None,), (None,)]378379def test_int_mult(self):380self.cur.execute(381'select int_mult(value, 100) as res '382'from data order by id',383)384385assert [tuple(x) for x in self.cur] == \386[(200,), (200,), (500,), (400,), (0,)]387388desc = self.cur.description389assert len(desc) == 1390assert desc[0].name == 'res'391assert desc[0].type_code == ft.LONGLONG392assert desc[0].null_ok is False393394# NULL is not valid395with self.assertRaises(self.conn.OperationalError):396self.cur.execute(397'select int_mult(value, NULL) as res '398'from data order by id',399)400401def test_tinyint_mult(self):402self.cur.execute(403'select tinyint_mult(value, 100) as res '404'from data order by id',405)406407assert [tuple(x) for x in self.cur] == \408[(127,), (127,), (127,), (127,), (0,)]409410desc = self.cur.description411assert len(desc) == 1412assert desc[0].name == 'res'413assert desc[0].type_code == ft.TINY414assert desc[0].null_ok is False415416# NULL is not valid417with self.assertRaises(self.conn.OperationalError):418self.cur.execute(419'select tinyint_mult(value, NULL) as res '420'from data order by id',421)422423def test_pandas_tinyint_mult(self):424self.cur.execute(425'select pandas_tinyint_mult(value, 100) as res '426'from data order by id',427)428429assert [tuple(x) for x in self.cur] == \430[(127,), (127,), (127,), (127,), (0,)]431432desc = self.cur.description433assert len(desc) == 1434assert desc[0].name == 'res'435assert desc[0].type_code == ft.TINY436assert desc[0].null_ok is False437438# NULL is not valid439with self.assertRaises(self.conn.OperationalError):440self.cur.execute(441'select pandas_tinyint_mult(value, NULL) as res '442'from data order by id',443)444445def test_polars_tinyint_mult(self):446self.cur.execute(447'select polars_tinyint_mult(value, 100) as res '448'from data order by id',449)450451assert [tuple(x) for x in self.cur] == \452[(127,), (127,), (127,), (127,), (0,)]453454desc = self.cur.description455assert len(desc) == 1456assert desc[0].name == 'res'457assert desc[0].type_code == ft.TINY458assert desc[0].null_ok is False459460# NULL is not valid461with self.assertRaises(self.conn.OperationalError):462self.cur.execute(463'select polars_tinyint_mult(value, NULL) as res '464'from data order by id',465)466467def test_numpy_tinyint_mult(self):468self.cur.execute(469'select numpy_tinyint_mult(value, 100) as res '470'from data order by id',471)472473assert [tuple(x) for x in self.cur] == \474[(127,), (127,), (127,), (127,), (0,)]475476desc = self.cur.description477assert len(desc) == 1478assert desc[0].name == 'res'479assert desc[0].type_code == ft.TINY480assert desc[0].null_ok is False481482# NULL is not valid483with self.assertRaises(self.conn.OperationalError):484self.cur.execute(485'select numpy_tinyint_mult(value, NULL) as res '486'from data order by id',487)488489def test_arrow_tinyint_mult(self):490self.cur.execute(491'select arrow_tinyint_mult(value, 100) as res from '492'data order by id',493)494495assert [tuple(x) for x in self.cur] == \496[(127,), (127,), (127,), (127,), (0,)]497498desc = self.cur.description499assert len(desc) == 1500assert desc[0].name == 'res'501assert desc[0].type_code == ft.TINY502assert desc[0].null_ok is False503504# NULL is not valid505with self.assertRaises(self.conn.OperationalError):506self.cur.execute(507'select arrow_tinyint_mult(value, NULL) as res '508'from data order by id',509)510511def test_nullable_tinyint_mult(self):512self.cur.execute(513'select nullable_tinyint_mult(value, 100) as res from '514'data_with_nulls order by id',515)516517assert [tuple(x) for x in self.cur] == \518[(127,), (127,), (127,), (None,), (0,)]519520desc = self.cur.description521assert len(desc) == 1522assert desc[0].name == 'res'523assert desc[0].type_code == ft.TINY524assert desc[0].null_ok is True525526def test_pandas_nullable_tinyint_mult(self):527self.cur.execute(528'select pandas_nullable_tinyint_mult(value, 100) as res '529'from data_with_nulls order by id',530)531532assert [tuple(x) for x in self.cur] == \533[(127,), (127,), (127,), (0,), (0,)]534535desc = self.cur.description536assert len(desc) == 1537assert desc[0].name == 'res'538assert desc[0].type_code == ft.TINY539assert desc[0].null_ok is True540541def test_pandas_nullable_tinyint_mult_with_masks(self):542self.cur.execute(543'select pandas_nullable_tinyint_mult_with_masks(value, 100) '544'as res from data_with_nulls order by id',545)546547assert [tuple(x) for x in self.cur] == \548[(127,), (127,), (127,), (None,), (0,)]549550desc = self.cur.description551assert len(desc) == 1552assert desc[0].name == 'res'553assert desc[0].type_code == ft.TINY554assert desc[0].null_ok is True555556def test_polars_nullable_tinyint_mult(self):557self.cur.execute(558'select polars_nullable_tinyint_mult(value, 100) as res '559'from data_with_nulls order by id',560)561562assert [tuple(x) for x in self.cur] == \563[(127,), (127,), (127,), (0,), (0,)]564565desc = self.cur.description566assert len(desc) == 1567assert desc[0].name == 'res'568assert desc[0].type_code == ft.TINY569assert desc[0].null_ok is True570571def test_polars_nullable_tinyint_mult_with_masks(self):572self.cur.execute(573'select polars_nullable_tinyint_mult_with_masks(value, 100) '574'as res from data_with_nulls order by id',575)576577assert [tuple(x) for x in self.cur] == \578[(127,), (127,), (127,), (None,), (0,)]579580desc = self.cur.description581assert len(desc) == 1582assert desc[0].name == 'res'583assert desc[0].type_code == ft.TINY584assert desc[0].null_ok is True585586def test_numpy_nullable_tinyint_mult(self):587self.cur.execute(588'select numpy_nullable_tinyint_mult(value, 100) as res '589'from data_with_nulls order by id',590)591592assert [tuple(x) for x in self.cur] == \593[(127,), (127,), (127,), (0,), (0,)]594595desc = self.cur.description596assert len(desc) == 1597assert desc[0].name == 'res'598assert desc[0].type_code == ft.TINY599assert desc[0].null_ok is True600601def test_numpy_nullable_tinyint_mult_with_masks(self):602self.cur.execute(603'select numpy_nullable_tinyint_mult_with_masks(value, 100) '604'as res from data_with_nulls order by id',605)606607assert [tuple(x) for x in self.cur] == \608[(127,), (127,), (127,), (None,), (0,)]609610desc = self.cur.description611assert len(desc) == 1612assert desc[0].name == 'res'613assert desc[0].type_code == ft.TINY614assert desc[0].null_ok is True615616def test_arrow_nullable_tinyint_mult(self):617self.cur.execute(618'select arrow_nullable_tinyint_mult(value, 100) as res '619'from data_with_nulls order by id',620)621622assert [tuple(x) for x in self.cur] == \623[(127,), (127,), (127,), (None,), (0,)]624625desc = self.cur.description626assert len(desc) == 1627assert desc[0].name == 'res'628assert desc[0].type_code == ft.TINY629assert desc[0].null_ok is True630631def test_arrow_nullable_tinyint_mult_with_masks(self):632self.cur.execute(633'select arrow_nullable_tinyint_mult_with_masks(value, 100) '634'as res from data_with_nulls order by id',635)636637assert [tuple(x) for x in self.cur] == \638[(127,), (127,), (127,), (None,), (0,)]639640desc = self.cur.description641assert len(desc) == 1642assert desc[0].name == 'res'643assert desc[0].type_code == ft.TINY644assert desc[0].null_ok is True645646def test_smallint_mult(self):647self.cur.execute(648'select smallint_mult(value, 100) as res '649'from data order by id',650)651652assert [tuple(x) for x in self.cur] == \653[(200,), (200,), (500,), (400,), (0,)]654655desc = self.cur.description656assert len(desc) == 1657assert desc[0].name == 'res'658assert desc[0].type_code == ft.SHORT659assert desc[0].null_ok is False660661# NULL is not valid662with self.assertRaises(self.conn.OperationalError):663self.cur.execute(664'select smallint_mult(value, NULL) as res '665'from data order by id',666)667668def test_pandas_smallint_mult(self):669self.cur.execute(670'select pandas_smallint_mult(value, 100) as res '671'from data order by id',672)673674assert [tuple(x) for x in self.cur] == \675[(200,), (200,), (500,), (400,), (0,)]676677desc = self.cur.description678assert len(desc) == 1679assert desc[0].name == 'res'680assert desc[0].type_code == ft.SHORT681assert desc[0].null_ok is False682683# NULL is not valid684with self.assertRaises(self.conn.OperationalError):685self.cur.execute(686'select pandas_smallint_mult(value, NULL) as res '687'from data order by id',688)689690def test_polars_smallint_mult(self):691self.cur.execute(692'select polars_smallint_mult(value, 100) as res '693'from data order by id',694)695696assert [tuple(x) for x in self.cur] == \697[(200,), (200,), (500,), (400,), (0,)]698699desc = self.cur.description700assert len(desc) == 1701assert desc[0].name == 'res'702assert desc[0].type_code == ft.SHORT703assert desc[0].null_ok is False704705# NULL is not valid706with self.assertRaises(self.conn.OperationalError):707self.cur.execute(708'select polars_smallint_mult(value, NULL) as res '709'from data order by id',710)711712def test_numpy_smallint_mult(self):713self.cur.execute(714'select numpy_smallint_mult(value, 100) as res '715'from data order by id',716)717718assert [tuple(x) for x in self.cur] == \719[(200,), (200,), (500,), (400,), (0,)]720721desc = self.cur.description722assert len(desc) == 1723assert desc[0].name == 'res'724assert desc[0].type_code == ft.SHORT725assert desc[0].null_ok is False726727# NULL is not valid728with self.assertRaises(self.conn.OperationalError):729self.cur.execute(730'select numpy_smallint_mult(value, NULL) as res '731'from data order by id',732)733734def test_arrow_smallint_mult(self):735self.cur.execute(736'select arrow_smallint_mult(value, 100) as res '737'from data order by id',738)739740assert [tuple(x) for x in self.cur] == \741[(200,), (200,), (500,), (400,), (0,)]742743desc = self.cur.description744assert len(desc) == 1745assert desc[0].name == 'res'746assert desc[0].type_code == ft.SHORT747assert desc[0].null_ok is False748749# NULL is not valid750with self.assertRaises(self.conn.OperationalError):751self.cur.execute(752'select arrow_smallint_mult(value, NULL) as res '753'from data order by id',754)755756def test_nullable_smallint_mult(self):757self.cur.execute(758'select nullable_smallint_mult(value, 100) as res '759'from data_with_nulls order by id',760)761762assert [tuple(x) for x in self.cur] == \763[(200,), (200,), (500,), (None,), (0,)]764765desc = self.cur.description766assert len(desc) == 1767assert desc[0].name == 'res'768assert desc[0].type_code == ft.SHORT769assert desc[0].null_ok is True770771def test_mediumint_mult(self):772self.cur.execute(773'select mediumint_mult(value, 100) as res '774'from data order by id',775)776777assert [tuple(x) for x in self.cur] == \778[(200,), (200,), (500,), (400,), (0,)]779780desc = self.cur.description781assert len(desc) == 1782assert desc[0].name == 'res'783assert desc[0].type_code == ft.INT24784assert desc[0].null_ok is False785786# NULL is not valid787with self.assertRaises(self.conn.OperationalError):788self.cur.execute(789'select mediumint_mult(value, NULL) as res '790'from data order by id',791)792793def test_pandas_mediumint_mult(self):794self.cur.execute(795'select pandas_mediumint_mult(value, 100) as res '796'from data order by id',797)798799assert [tuple(x) for x in self.cur] == \800[(200,), (200,), (500,), (400,), (0,)]801802desc = self.cur.description803assert len(desc) == 1804assert desc[0].name == 'res'805assert desc[0].type_code == ft.INT24806assert desc[0].null_ok is False807808# NULL is not valid809with self.assertRaises(self.conn.OperationalError):810self.cur.execute(811'select pandas_mediumint_mult(value, NULL) as res '812'from data order by id',813)814815def test_polars_mediumint_mult(self):816self.cur.execute(817'select polars_mediumint_mult(value, 100) as res '818'from data order by id',819)820821assert [tuple(x) for x in self.cur] == \822[(200,), (200,), (500,), (400,), (0,)]823824desc = self.cur.description825assert len(desc) == 1826assert desc[0].name == 'res'827assert desc[0].type_code == ft.INT24828assert desc[0].null_ok is False829830# NULL is not valid831with self.assertRaises(self.conn.OperationalError):832self.cur.execute(833'select polars_mediumint_mult(value, NULL) as res '834'from data order by id',835)836837def test_numpy_mediumint_mult(self):838self.cur.execute(839'select numpy_mediumint_mult(value, 100) as res '840'from data order by id',841)842843assert [tuple(x) for x in self.cur] == \844[(200,), (200,), (500,), (400,), (0,)]845846desc = self.cur.description847assert len(desc) == 1848assert desc[0].name == 'res'849assert desc[0].type_code == ft.INT24850assert desc[0].null_ok is False851852# NULL is not valid853with self.assertRaises(self.conn.OperationalError):854self.cur.execute(855'select numpy_mediumint_mult(value, NULL) as res '856'from data order by id',857)858859def test_arrow_mediumint_mult(self):860self.cur.execute(861'select arrow_mediumint_mult(value, 100) as res '862'from data order by id',863)864865assert [tuple(x) for x in self.cur] == \866[(200,), (200,), (500,), (400,), (0,)]867868desc = self.cur.description869assert len(desc) == 1870assert desc[0].name == 'res'871assert desc[0].type_code == ft.INT24872assert desc[0].null_ok is False873874# NULL is not valid875with self.assertRaises(self.conn.OperationalError):876self.cur.execute(877'select arrow_mediumint_mult(value, NULL) as res '878'from data order by id',879)880881def test_nullable_mediumint_mult(self):882self.cur.execute(883'select nullable_mediumint_mult(value, 100) as res '884'from data_with_nulls order by id',885)886887assert [tuple(x) for x in self.cur] == \888[(200,), (200,), (500,), (None,), (0,)]889890desc = self.cur.description891assert len(desc) == 1892assert desc[0].name == 'res'893assert desc[0].type_code == ft.INT24894assert desc[0].null_ok is True895896def test_bigint_mult(self):897self.cur.execute(898'select bigint_mult(value, 100) as res '899'from data order by id',900)901902assert [tuple(x) for x in self.cur] == \903[(200,), (200,), (500,), (400,), (0,)]904905desc = self.cur.description906assert len(desc) == 1907assert desc[0].name == 'res'908assert desc[0].type_code == ft.LONGLONG909assert desc[0].null_ok is False910911# NULL is not valid912with self.assertRaises(self.conn.OperationalError):913self.cur.execute(914'select bigint_mult(value, NULL) as res '915'from data order by id',916)917918def test_pandas_bigint_mult(self):919self.cur.execute(920'select pandas_bigint_mult(value, 100) as res '921'from data order by id',922)923924assert [tuple(x) for x in self.cur] == \925[(200,), (200,), (500,), (400,), (0,)]926927desc = self.cur.description928assert len(desc) == 1929assert desc[0].name == 'res'930assert desc[0].type_code == ft.LONGLONG931assert desc[0].null_ok is False932933# NULL is not valid934with self.assertRaises(self.conn.OperationalError):935self.cur.execute(936'select pandas_bigint_mult(value, NULL) as res '937'from data order by id',938)939940def test_polars_bigint_mult(self):941self.cur.execute(942'select polars_bigint_mult(value, 100) as res '943'from data order by id',944)945946assert [tuple(x) for x in self.cur] == \947[(200,), (200,), (500,), (400,), (0,)]948949desc = self.cur.description950assert len(desc) == 1951assert desc[0].name == 'res'952assert desc[0].type_code == ft.LONGLONG953assert desc[0].null_ok is False954955# NULL is not valid956with self.assertRaises(self.conn.OperationalError):957self.cur.execute(958'select polars_bigint_mult(value, NULL) as res '959'from data order by id',960)961962def test_numpy_bigint_mult(self):963self.cur.execute(964'select numpy_bigint_mult(value, 100) as res '965'from data order by id',966)967968assert [tuple(x) for x in self.cur] == \969[(200,), (200,), (500,), (400,), (0,)]970971desc = self.cur.description972assert len(desc) == 1973assert desc[0].name == 'res'974assert desc[0].type_code == ft.LONGLONG975assert desc[0].null_ok is False976977# NULL is not valid978with self.assertRaises(self.conn.OperationalError):979self.cur.execute(980'select numpy_bigint_mult(value, NULL) as res '981'from data order by id',982)983984def test_numpy_nullable_bigint_mult(self):985self.cur.execute(986'select numpy_nullable_bigint_mult(value, 100) as res '987'from data_with_nulls order by id',988)989990# assert [tuple(x) for x in self.cur] == \991# [(200,), (200,), (500,), (None,), (0,)]992assert [tuple(x) for x in self.cur] == \993[(200,), (200,), (500,), (0,), (0,)]994995desc = self.cur.description996assert len(desc) == 1997assert desc[0].name == 'res'998assert desc[0].type_code == ft.LONGLONG999assert desc[0].null_ok is True10001001def test_arrow_bigint_mult(self):1002self.cur.execute(1003'select arrow_bigint_mult(value, 100) as res '1004'from data order by id',1005)10061007assert [tuple(x) for x in self.cur] == \1008[(200,), (200,), (500,), (400,), (0,)]10091010desc = self.cur.description1011assert len(desc) == 11012assert desc[0].name == 'res'1013assert desc[0].type_code == ft.LONGLONG1014assert desc[0].null_ok is False10151016# NULL is not valid1017with self.assertRaises(self.conn.OperationalError):1018self.cur.execute(1019'select arrow_bigint_mult(value, NULL) as res '1020'from data order by id',1021)10221023def test_nullable_bigint_mult(self):1024self.cur.execute(1025'select nullable_bigint_mult(value, 100) as res '1026'from data_with_nulls order by id',1027)10281029assert [tuple(x) for x in self.cur] == \1030[(200,), (200,), (500,), (None,), (0,)]10311032desc = self.cur.description1033assert len(desc) == 11034assert desc[0].name == 'res'1035assert desc[0].type_code == ft.LONGLONG1036assert desc[0].null_ok is True10371038def test_nullable_int_mult(self):1039self.cur.execute(1040'select nullable_int_mult(value, 100) as res '1041'from data_with_nulls order by id',1042)10431044assert [tuple(x) for x in self.cur] == \1045[(200,), (200,), (500,), (None,), (0,)]10461047desc = self.cur.description1048assert len(desc) == 11049assert desc[0].name == 'res'1050assert desc[0].type_code == ft.LONGLONG1051assert desc[0].null_ok is True10521053def test_string_mult(self):1054self.cur.execute(1055'select string_mult(name, value) as res '1056'from data order by id',1057)10581059assert [tuple(x) for x in self.cur] == [1060('antelopesantelopes',),1061('bearsbears',),1062('catscatscatscatscats',),1063('dogsdogsdogsdogs',),1064('',),1065]10661067desc = self.cur.description1068assert len(desc) == 11069assert desc[0].name == 'res'1070assert desc[0].type_code == ft.BLOB1071assert desc[0].null_ok is False10721073# NULL is not valid1074with self.assertRaises(self.conn.OperationalError):1075self.cur.execute(1076'select string_mult(NULL, value) as res '1077'from data order by id',1078)10791080def test_pandas_string_mult(self):1081self.cur.execute(1082'select pandas_string_mult(name, value) as res '1083'from data order by id',1084)10851086assert [tuple(x) for x in self.cur] == [1087('antelopesantelopes',),1088('bearsbears',),1089('catscatscatscatscats',),1090('dogsdogsdogsdogs',),1091('',),1092]10931094desc = self.cur.description1095assert len(desc) == 11096assert desc[0].name == 'res'1097assert desc[0].type_code == ft.BLOB1098assert desc[0].null_ok is False10991100# NULL is not valid1101with self.assertRaises(self.conn.OperationalError):1102self.cur.execute(1103'select pandas_string_mult(NULL, value) as res '1104'from data order by id',1105)11061107def test_numpy_string_mult(self):1108self.cur.execute(1109'select numpy_string_mult(name, value) as res '1110'from data order by id',1111)11121113assert [tuple(x) for x in self.cur] == [1114('antelopesantelopes',),1115('bearsbears',),1116('catscatscatscatscats',),1117('dogsdogsdogsdogs',),1118('',),1119]11201121desc = self.cur.description1122assert len(desc) == 11123assert desc[0].name == 'res'1124assert desc[0].type_code == ft.BLOB1125assert desc[0].null_ok is False11261127# NULL is not valid1128with self.assertRaises(self.conn.OperationalError):1129self.cur.execute(1130'select numpy_string_mult(NULL, value) as res '1131'from data order by id',1132)11331134def _test_polars_string_mult(self):1135self.cur.execute(1136'select polars_string_mult(name, value) as res '1137'from data order by id',1138)11391140assert [tuple(x) for x in self.cur] == [1141('antelopesantelopes',),1142('bearsbears',),1143('catscatscatscatscats',),1144('dogsdogsdogsdogs',),1145('',),1146]11471148desc = self.cur.description1149assert len(desc) == 11150assert desc[0].name == 'res'1151assert desc[0].type_code == ft.BLOB1152assert desc[0].null_ok is False11531154# NULL is not valid1155with self.assertRaises(self.conn.OperationalError):1156self.cur.execute(1157'select polars_string_mult(NULL, value) as res '1158'from data order by id',1159)11601161def _test_arrow_string_mult(self):1162self.cur.execute(1163'select arrow_string_mult(name, value) as res '1164'from data order by id',1165)11661167assert [tuple(x) for x in self.cur] == [1168('antelopesantelopes',),1169('bearsbears',),1170('catscatscatscatscats',),1171('dogsdogsdogsdogs',),1172('',),1173]11741175desc = self.cur.description1176assert len(desc) == 11177assert desc[0].name == 'res'1178assert desc[0].type_code == ft.BLOB1179assert desc[0].null_ok is False11801181# NULL is not valid1182with self.assertRaises(self.conn.OperationalError):1183self.cur.execute(1184'select arrow_string_mult(NULL, value) as res '1185'from data order by id',1186)11871188def test_nullable_string_mult(self):1189self.cur.execute(1190'select nullable_string_mult(name, value) as res '1191'from data_with_nulls order by id',1192)11931194assert [tuple(x) for x in self.cur] == [1195('antelopesantelopes',),1196(None,),1197(None,),1198(None,),1199('',),1200]12011202desc = self.cur.description1203assert len(desc) == 11204assert desc[0].name == 'res'1205assert desc[0].type_code == ft.BLOB1206assert desc[0].null_ok is True12071208def _test_varchar_mult(self):1209self.cur.execute(1210'select varchar_mult(name, value) as res '1211'from data order by id',1212)12131214assert [tuple(x) for x in self.cur] == [1215('antelopesantelopes',),1216('bearsbears',),1217('catscatscatscatscats',),1218('dogsdogsdogsdogs',),1219('',),1220]12211222desc = self.cur.description1223assert len(desc) == 11224assert desc[0].name == 'res'1225assert desc[0].type_code == ft.BLOB1226assert desc[0].null_ok is False12271228# NULL is not valid1229with self.assertRaises(self.conn.OperationalError):1230self.cur.execute(1231'select varchar_mult(NULL, value) as res '1232'from data order by id',1233)12341235def _test_nullable_varchar_mult(self):1236self.cur.execute(1237'select nullable_varchar_mult(name, value) as res '1238'from data_with_nulls order by id',1239)12401241assert [tuple(x) for x in self.cur] == [1242('antelopesantelopes',),1243(None,),1244(None,),1245(None,),1246('',),1247]12481249desc = self.cur.description1250assert len(desc) == 11251assert desc[0].name == 'res'1252assert desc[0].type_code == ft.BLOB1253assert desc[0].null_ok is True12541255def test_numpy_fixed_strings(self):1256self.cur.execute('select * from numpy_fixed_strings()')12571258assert [tuple(x) for x in self.cur] == [1259('hello',),1260('hi there 😜',),1261('😜 bye',),1262]12631264desc = self.cur.description1265assert len(desc) == 11266assert desc[0].name == 'res'1267assert desc[0].type_code == ft.BLOB1268assert desc[0].null_ok is False12691270def test_numpy_fixed_binary(self):1271self.cur.execute('select * from numpy_fixed_binary()')12721273assert [tuple(x) for x in self.cur] == [1274('hello'.encode('utf8'),),1275('hi there 😜'.encode('utf8'),),1276('😜 bye'.encode('utf8'),),1277]12781279desc = self.cur.description1280assert len(desc) == 11281assert desc[0].name == 'res'1282assert desc[0].type_code == ft.BLOB1283assert desc[0].null_ok is False12841285def test_no_args_no_return_value(self):1286self.cur.execute('select no_args_no_return_value() as res')12871288assert [tuple(x) for x in self.cur] == [(None,)]12891290desc = self.cur.description1291assert len(desc) == 11292assert desc[0].name == 'res'1293assert desc[0].type_code == ft.TINY1294assert desc[0].null_ok is True12951296def test_table_function(self):1297self.cur.execute('select * from table_function(5)')12981299assert [x[0] for x in self.cur] == [10, 10, 10, 10, 10]13001301desc = self.cur.description1302assert len(desc) == 11303assert desc[0].name == 'a'1304assert desc[0].type_code == ft.LONGLONG1305assert desc[0].null_ok is False13061307def test_async_table_function(self):1308self.cur.execute('select * from async_table_function(5)')13091310assert [x[0] for x in self.cur] == [10, 10, 10, 10, 10]13111312desc = self.cur.description1313assert len(desc) == 11314assert desc[0].name == 'a'1315assert desc[0].type_code == ft.LONGLONG1316assert desc[0].null_ok is False13171318def test_table_function_tuple(self):1319self.cur.execute('select * from table_function_tuple(3)')13201321out = list(self.cur)13221323assert out == [1324(10, 10.0, 'ten'),1325(10, 10.0, 'ten'),1326(10, 10.0, 'ten'),1327]13281329desc = self.cur.description1330assert len(desc) == 31331assert desc[0].name == 'c_int'1332assert desc[1].name == 'c_float'1333assert desc[2].name == 'c_str'13341335def test_table_function_struct(self):1336self.cur.execute('select * from table_function_struct(3)')13371338out = list(self.cur)13391340assert out == [1341(10, 10.0, 'ten'),1342(10, 10.0, 'ten'),1343(10, 10.0, 'ten'),1344]13451346desc = self.cur.description1347assert len(desc) == 31348assert desc[0].name == 'c_int'1349assert desc[1].name == 'c_float'1350assert desc[2].name == 'c_str'13511352def test_vec_function(self):1353self.cur.execute('select vec_function(5, 10) as res')13541355assert [tuple(x) for x in self.cur] == [(50.0,)]13561357def test_vec_function_ints(self):1358self.cur.execute('select vec_function_ints(5, 10) as res')13591360assert [tuple(x) for x in self.cur] == [(50,)]13611362def test_vec_function_df(self):1363self.cur.execute('select * from vec_function_df(5, 10)')13641365out = list(self.cur)13661367assert out == [1368(1, 1.1),1369(2, 2.2),1370(3, 3.3),1371]13721373desc = self.cur.description1374assert len(desc) == 21375assert desc[0].name == 'res'1376assert desc[0].type_code == ft.SHORT1377assert desc[0].null_ok is False1378assert desc[1].name == 'res2'1379assert desc[1].type_code == ft.DOUBLE1380assert desc[1].null_ok is False13811382def test_async_vec_function_df(self):1383self.cur.execute('select * from async_vec_function_df(5, 10)')13841385out = list(self.cur)13861387assert out == [1388(1, 1.1),1389(2, 2.2),1390(3, 3.3),1391]13921393desc = self.cur.description1394assert len(desc) == 21395assert desc[0].name == 'res'1396assert desc[0].type_code == ft.SHORT1397assert desc[0].null_ok is False1398assert desc[1].name == 'res2'1399assert desc[1].type_code == ft.DOUBLE1400assert desc[1].null_ok is False14011402def test_vec_function_ints_masked(self):1403self.cur.execute('select * from vec_function_ints_masked(5, 10)')14041405assert [tuple(x) for x in self.cur] == [(50,)]14061407desc = self.cur.description1408assert len(desc) == 11409assert desc[0].name == 'res'1410assert desc[0].type_code == ft.SHORT1411assert desc[0].null_ok is True14121413self.cur.execute('select * from vec_function_ints_masked(NULL, 10)')14141415assert [tuple(x) for x in self.cur] == [(None,)]14161417desc = self.cur.description1418assert len(desc) == 11419assert desc[0].name == 'res'1420assert desc[0].type_code == ft.SHORT1421assert desc[0].null_ok is True14221423self.cur.execute('select * from vec_function_ints_masked(5, NULL)')14241425assert [tuple(x) for x in self.cur] == [(None,)]14261427desc = self.cur.description1428assert len(desc) == 11429assert desc[0].name == 'res'1430assert desc[0].type_code == ft.SHORT1431assert desc[0].null_ok is True14321433def test_vec_function_ints_masked2(self):1434self.cur.execute('select * from vec_function_ints_masked2(5, 10)')14351436assert [tuple(x) for x in self.cur] == [(50, 50)]14371438desc = self.cur.description1439assert len(desc) == 21440assert desc[0].name == 'res'1441assert desc[0].type_code == ft.SHORT1442assert desc[0].null_ok is True1443assert desc[1].name == 'res2'1444assert desc[1].type_code == ft.SHORT1445assert desc[1].null_ok is True14461447self.cur.execute('select * from vec_function_ints_masked2(NULL, 10)')14481449assert [tuple(x) for x in self.cur] == [(None, None)]14501451desc = self.cur.description1452assert len(desc) == 21453assert desc[0].name == 'res'1454assert desc[0].type_code == ft.SHORT1455assert desc[0].null_ok is True1456assert desc[1].name == 'res2'1457assert desc[1].type_code == ft.SHORT1458assert desc[1].null_ok is True14591460self.cur.execute('select * from vec_function_ints_masked2(5, NULL)')14611462assert [tuple(x) for x in self.cur] == [(None, None)]14631464desc = self.cur.description1465assert len(desc) == 21466assert desc[0].name == 'res'1467assert desc[0].type_code == ft.SHORT1468assert desc[0].null_ok is True1469assert desc[1].name == 'res2'1470assert desc[1].type_code == ft.SHORT1471assert desc[1].null_ok is True147214731474