singlestoredb 1.12.3__py3-none-any.whl → 1.13.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.

Files changed (31) hide show
  1. singlestoredb/__init__.py +1 -1
  2. singlestoredb/apps/__init__.py +1 -0
  3. singlestoredb/apps/_config.py +6 -0
  4. singlestoredb/apps/_connection_info.py +8 -0
  5. singlestoredb/apps/_python_udfs.py +85 -0
  6. singlestoredb/config.py +14 -2
  7. singlestoredb/functions/__init__.py +11 -1
  8. singlestoredb/functions/decorator.py +102 -252
  9. singlestoredb/functions/dtypes.py +545 -198
  10. singlestoredb/functions/ext/asgi.py +288 -90
  11. singlestoredb/functions/ext/json.py +29 -36
  12. singlestoredb/functions/ext/mmap.py +1 -1
  13. singlestoredb/functions/ext/rowdat_1.py +50 -70
  14. singlestoredb/functions/signature.py +816 -144
  15. singlestoredb/functions/typing.py +41 -0
  16. singlestoredb/functions/utils.py +342 -0
  17. singlestoredb/http/connection.py +3 -1
  18. singlestoredb/management/manager.py +6 -1
  19. singlestoredb/management/utils.py +2 -2
  20. singlestoredb/mysql/connection.py +17 -11
  21. singlestoredb/tests/ext_funcs/__init__.py +476 -237
  22. singlestoredb/tests/test_basics.py +2 -0
  23. singlestoredb/tests/test_ext_func.py +192 -3
  24. singlestoredb/tests/test_udf.py +101 -131
  25. singlestoredb/tests/test_udf_returns.py +459 -0
  26. {singlestoredb-1.12.3.dist-info → singlestoredb-1.13.0.dist-info}/METADATA +2 -1
  27. {singlestoredb-1.12.3.dist-info → singlestoredb-1.13.0.dist-info}/RECORD +31 -27
  28. {singlestoredb-1.12.3.dist-info → singlestoredb-1.13.0.dist-info}/LICENSE +0 -0
  29. {singlestoredb-1.12.3.dist-info → singlestoredb-1.13.0.dist-info}/WHEEL +0 -0
  30. {singlestoredb-1.12.3.dist-info → singlestoredb-1.13.0.dist-info}/entry_points.txt +0 -0
  31. {singlestoredb-1.12.3.dist-info → singlestoredb-1.13.0.dist-info}/top_level.txt +0 -0
@@ -1308,6 +1308,8 @@ class TestBasics(unittest.TestCase):
1308
1308
  )
1309
1309
 
1310
1310
  def test_charset(self):
1311
+ self.skipTest('Skip until charset commands are re-implemented')
1312
+
1311
1313
  with s2.connect(database=type(self).dbname) as conn:
1312
1314
  with conn.cursor() as cur:
1313
1315
  cur.execute('''
@@ -929,8 +929,10 @@ class TestExtFunc(unittest.TestCase):
929
929
  'from data_with_nulls order by id',
930
930
  )
931
931
 
932
+ # assert [tuple(x) for x in self.cur] == \
933
+ # [(200,), (200,), (500,), (None,), (0,)]
932
934
  assert [tuple(x) for x in self.cur] == \
933
- [(200,), (200,), (500,), (None,), (0,)]
935
+ [(200,), (200,), (500,), (0,), (0,)]
934
936
 
935
937
  desc = self.cur.description
936
938
  assert len(desc) == 1
@@ -1145,7 +1147,7 @@ class TestExtFunc(unittest.TestCase):
1145
1147
  assert desc[0].type_code == ft.BLOB
1146
1148
  assert desc[0].null_ok is True
1147
1149
 
1148
- def test_varchar_mult(self):
1150
+ def _test_varchar_mult(self):
1149
1151
  self.cur.execute(
1150
1152
  'select varchar_mult(name, value) as res '
1151
1153
  'from data order by id',
@@ -1172,7 +1174,7 @@ class TestExtFunc(unittest.TestCase):
1172
1174
  'from data order by id',
1173
1175
  )
1174
1176
 
1175
- def test_nullable_varchar_mult(self):
1177
+ def _test_nullable_varchar_mult(self):
1176
1178
  self.cur.execute(
1177
1179
  'select nullable_varchar_mult(name, value) as res '
1178
1180
  'from data_with_nulls order by id',
@@ -1191,3 +1193,190 @@ class TestExtFunc(unittest.TestCase):
1191
1193
  assert desc[0].name == 'res'
1192
1194
  assert desc[0].type_code == ft.BLOB
1193
1195
  assert desc[0].null_ok is True
1196
+
1197
+ def test_numpy_fixed_strings(self):
1198
+ self.cur.execute('select * from numpy_fixed_strings()')
1199
+
1200
+ assert [tuple(x) for x in self.cur] == [
1201
+ ('hello',),
1202
+ ('hi there 😜',),
1203
+ ('😜 bye',),
1204
+ ]
1205
+
1206
+ desc = self.cur.description
1207
+ assert len(desc) == 1
1208
+ assert desc[0].name == 'res'
1209
+ assert desc[0].type_code == ft.BLOB
1210
+ assert desc[0].null_ok is False
1211
+
1212
+ def test_numpy_fixed_binary(self):
1213
+ self.cur.execute('select * from numpy_fixed_binary()')
1214
+
1215
+ assert [tuple(x) for x in self.cur] == [
1216
+ ('hello'.encode('utf8'),),
1217
+ ('hi there 😜'.encode('utf8'),),
1218
+ ('😜 bye'.encode('utf8'),),
1219
+ ]
1220
+
1221
+ desc = self.cur.description
1222
+ assert len(desc) == 1
1223
+ assert desc[0].name == 'res'
1224
+ assert desc[0].type_code == ft.BLOB
1225
+ assert desc[0].null_ok is False
1226
+
1227
+ def test_no_args_no_return_value(self):
1228
+ self.cur.execute('select no_args_no_return_value() as res')
1229
+
1230
+ assert [tuple(x) for x in self.cur] == [(None,)]
1231
+
1232
+ desc = self.cur.description
1233
+ assert len(desc) == 1
1234
+ assert desc[0].name == 'res'
1235
+ assert desc[0].type_code == ft.TINY
1236
+ assert desc[0].null_ok is True
1237
+
1238
+ def test_table_function(self):
1239
+ self.cur.execute('select * from table_function(5)')
1240
+
1241
+ assert [x[0] for x in self.cur] == [10, 10, 10, 10, 10]
1242
+
1243
+ desc = self.cur.description
1244
+ assert len(desc) == 1
1245
+ assert desc[0].name == 'a'
1246
+ assert desc[0].type_code == ft.LONGLONG
1247
+ assert desc[0].null_ok is False
1248
+
1249
+ def test_table_function_tuple(self):
1250
+ self.cur.execute('select * from table_function_tuple(3)')
1251
+
1252
+ out = list(self.cur)
1253
+
1254
+ assert out == [
1255
+ (10, 10.0, 'ten'),
1256
+ (10, 10.0, 'ten'),
1257
+ (10, 10.0, 'ten'),
1258
+ ]
1259
+
1260
+ desc = self.cur.description
1261
+ assert len(desc) == 3
1262
+ assert desc[0].name == 'c_int'
1263
+ assert desc[1].name == 'c_float'
1264
+ assert desc[2].name == 'c_str'
1265
+
1266
+ def test_table_function_struct(self):
1267
+ self.cur.execute('select * from table_function_struct(3)')
1268
+
1269
+ out = list(self.cur)
1270
+
1271
+ assert out == [
1272
+ (10, 10.0, 'ten'),
1273
+ (10, 10.0, 'ten'),
1274
+ (10, 10.0, 'ten'),
1275
+ ]
1276
+
1277
+ desc = self.cur.description
1278
+ assert len(desc) == 3
1279
+ assert desc[0].name == 'c_int'
1280
+ assert desc[1].name == 'c_float'
1281
+ assert desc[2].name == 'c_str'
1282
+
1283
+ def test_vec_function(self):
1284
+ self.cur.execute('select vec_function(5, 10) as res')
1285
+
1286
+ assert [tuple(x) for x in self.cur] == [(50.0,)]
1287
+
1288
+ def test_vec_function_ints(self):
1289
+ self.cur.execute('select vec_function_ints(5, 10) as res')
1290
+
1291
+ assert [tuple(x) for x in self.cur] == [(50,)]
1292
+
1293
+ def test_vec_function_df(self):
1294
+ self.cur.execute('select * from vec_function_df(5, 10)')
1295
+
1296
+ out = list(self.cur)
1297
+
1298
+ assert out == [
1299
+ (1, 1.1),
1300
+ (2, 2.2),
1301
+ (3, 3.3),
1302
+ ]
1303
+
1304
+ desc = self.cur.description
1305
+ assert len(desc) == 2
1306
+ assert desc[0].name == 'res'
1307
+ assert desc[0].type_code == ft.SHORT
1308
+ assert desc[0].null_ok is False
1309
+ assert desc[1].name == 'res2'
1310
+ assert desc[1].type_code == ft.DOUBLE
1311
+ assert desc[1].null_ok is False
1312
+
1313
+ def test_vec_function_ints_masked(self):
1314
+ self.cur.execute('select * from vec_function_ints_masked(5, 10)')
1315
+
1316
+ assert [tuple(x) for x in self.cur] == [(50,)]
1317
+
1318
+ desc = self.cur.description
1319
+ assert len(desc) == 1
1320
+ assert desc[0].name == 'res'
1321
+ assert desc[0].type_code == ft.SHORT
1322
+ assert desc[0].null_ok is True
1323
+
1324
+ self.cur.execute('select * from vec_function_ints_masked(NULL, 10)')
1325
+
1326
+ assert [tuple(x) for x in self.cur] == [(None,)]
1327
+
1328
+ desc = self.cur.description
1329
+ assert len(desc) == 1
1330
+ assert desc[0].name == 'res'
1331
+ assert desc[0].type_code == ft.SHORT
1332
+ assert desc[0].null_ok is True
1333
+
1334
+ self.cur.execute('select * from vec_function_ints_masked(5, NULL)')
1335
+
1336
+ assert [tuple(x) for x in self.cur] == [(None,)]
1337
+
1338
+ desc = self.cur.description
1339
+ assert len(desc) == 1
1340
+ assert desc[0].name == 'res'
1341
+ assert desc[0].type_code == ft.SHORT
1342
+ assert desc[0].null_ok is True
1343
+
1344
+ def test_vec_function_ints_masked2(self):
1345
+ self.cur.execute('select * from vec_function_ints_masked2(5, 10)')
1346
+
1347
+ assert [tuple(x) for x in self.cur] == [(50, 50)]
1348
+
1349
+ desc = self.cur.description
1350
+ assert len(desc) == 2
1351
+ assert desc[0].name == 'res'
1352
+ assert desc[0].type_code == ft.SHORT
1353
+ assert desc[0].null_ok is True
1354
+ assert desc[1].name == 'res2'
1355
+ assert desc[1].type_code == ft.SHORT
1356
+ assert desc[1].null_ok is True
1357
+
1358
+ self.cur.execute('select * from vec_function_ints_masked2(NULL, 10)')
1359
+
1360
+ assert [tuple(x) for x in self.cur] == [(None, None)]
1361
+
1362
+ desc = self.cur.description
1363
+ assert len(desc) == 2
1364
+ assert desc[0].name == 'res'
1365
+ assert desc[0].type_code == ft.SHORT
1366
+ assert desc[0].null_ok is True
1367
+ assert desc[1].name == 'res2'
1368
+ assert desc[1].type_code == ft.SHORT
1369
+ assert desc[1].null_ok is True
1370
+
1371
+ self.cur.execute('select * from vec_function_ints_masked2(5, NULL)')
1372
+
1373
+ assert [tuple(x) for x in self.cur] == [(None, None)]
1374
+
1375
+ desc = self.cur.description
1376
+ assert len(desc) == 2
1377
+ assert desc[0].name == 'res'
1378
+ assert desc[0].type_code == ft.SHORT
1379
+ assert desc[0].null_ok is True
1380
+ assert desc[1].name == 'res2'
1381
+ assert desc[1].type_code == ft.SHORT
1382
+ assert desc[1].null_ok is True
@@ -16,7 +16,7 @@ import pydantic
16
16
 
17
17
  from ..functions import dtypes as dt
18
18
  from ..functions import signature as sig
19
- from ..functions import tvf
19
+ from ..functions import Table
20
20
  from ..functions import udf
21
21
 
22
22
 
@@ -45,7 +45,7 @@ class TestUDF(unittest.TestCase):
45
45
 
46
46
  # NULL return value
47
47
  def foo() -> None: ...
48
- assert to_sql(foo) == '`foo`() RETURNS NULL'
48
+ assert to_sql(foo) == '`foo`() RETURNS TINYINT NULL'
49
49
 
50
50
  # Simple return value
51
51
  def foo() -> int: ...
@@ -101,28 +101,24 @@ class TestUDF(unittest.TestCase):
101
101
  to_sql(foo)
102
102
 
103
103
  # Tuple
104
- def foo() -> Tuple[int, float, str]: ...
105
- assert to_sql(foo) == '`foo`() RETURNS RECORD(`a` BIGINT NOT NULL, ' \
106
- '`b` DOUBLE NOT NULL, ' \
107
- '`c` TEXT NOT NULL) NOT NULL'
104
+ with self.assertRaises(TypeError):
105
+ def foo() -> Tuple[int, float, str]: ...
106
+ to_sql(foo)
108
107
 
109
108
  # Optional tuple
110
- def foo() -> Optional[Tuple[int, float, str]]: ...
111
- assert to_sql(foo) == '`foo`() RETURNS RECORD(`a` BIGINT NOT NULL, ' \
112
- '`b` DOUBLE NOT NULL, ' \
113
- '`c` TEXT NOT NULL) NULL'
109
+ with self.assertRaises(TypeError):
110
+ def foo() -> Optional[Tuple[int, float, str]]: ...
111
+ to_sql(foo)
114
112
 
115
113
  # Optional tuple with optional element
116
- def foo() -> Optional[Tuple[int, float, Optional[str]]]: ...
117
- assert to_sql(foo) == '`foo`() RETURNS RECORD(`a` BIGINT NOT NULL, ' \
118
- '`b` DOUBLE NOT NULL, ' \
119
- '`c` TEXT NULL) NULL'
114
+ with self.assertRaises(TypeError):
115
+ def foo() -> Optional[Tuple[int, float, Optional[str]]]: ...
116
+ to_sql(foo)
120
117
 
121
118
  # Optional tuple with optional union element
122
- def foo() -> Optional[Tuple[int, Optional[Union[float, int]], str]]: ...
123
- assert to_sql(foo) == '`foo`() RETURNS RECORD(`a` BIGINT NOT NULL, ' \
124
- '`b` DOUBLE NULL, ' \
125
- '`c` TEXT NOT NULL) NULL'
119
+ with self.assertRaises(TypeError):
120
+ def foo() -> Optional[Tuple[int, Optional[Union[float, int]], str]]: ...
121
+ to_sql(foo)
126
122
 
127
123
  # Unknown type
128
124
  def foo() -> set: ...
@@ -139,44 +135,44 @@ class TestUDF(unittest.TestCase):
139
135
 
140
136
  # Simple parameter
141
137
  def foo(x: int) -> None: ...
142
- assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS NULL'
138
+ assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS TINYINT NULL'
143
139
 
144
140
  # Optional parameter
145
141
  def foo(x: Optional[int]) -> None: ...
146
- assert to_sql(foo) == '`foo`(`x` BIGINT NULL) RETURNS NULL'
142
+ assert to_sql(foo) == '`foo`(`x` BIGINT NULL) RETURNS TINYINT NULL'
147
143
 
148
144
  # Optional parameter
149
145
  def foo(x: Union[int, None]) -> None: ...
150
- assert to_sql(foo) == '`foo`(`x` BIGINT NULL) RETURNS NULL'
146
+ assert to_sql(foo) == '`foo`(`x` BIGINT NULL) RETURNS TINYINT NULL'
151
147
 
152
148
  # Optional multiple parameter types
153
149
  def foo(x: Union[int, float, None]) -> None: ...
154
- assert to_sql(foo) == '`foo`(`x` DOUBLE NULL) RETURNS NULL'
150
+ assert to_sql(foo) == '`foo`(`x` DOUBLE NULL) RETURNS TINYINT NULL'
155
151
 
156
152
  # Optional parameter with custom type
157
153
  def foo(x: Optional[B]) -> None: ...
158
- assert to_sql(foo) == '`foo`(`x` DOUBLE NULL) RETURNS NULL'
154
+ assert to_sql(foo) == '`foo`(`x` DOUBLE NULL) RETURNS TINYINT NULL'
159
155
 
160
156
  # Optional parameter with nested custom type
161
157
  def foo(x: Optional[C]) -> None: ...
162
- assert to_sql(foo) == '`foo`(`x` DOUBLE NULL) RETURNS NULL'
158
+ assert to_sql(foo) == '`foo`(`x` DOUBLE NULL) RETURNS TINYINT NULL'
163
159
 
164
160
  # Optional parameter with collection type
165
161
  def foo(x: Optional[List[str]]) -> None: ...
166
- assert to_sql(foo) == '`foo`(`x` ARRAY(TEXT NOT NULL) NULL) RETURNS NULL'
162
+ assert to_sql(foo) == '`foo`(`x` ARRAY(TEXT NOT NULL) NULL) RETURNS TINYINT NULL'
167
163
 
168
164
  # Optional parameter with nested collection type
169
165
  def foo(x: Optional[List[List[str]]]) -> None: ...
170
166
  assert to_sql(foo) == '`foo`(`x` ARRAY(ARRAY(TEXT NOT NULL) NOT NULL) NULL) ' \
171
- 'RETURNS NULL'
167
+ 'RETURNS TINYINT NULL'
172
168
 
173
169
  # Optional parameter with collection type with nulls
174
170
  def foo(x: Optional[List[Optional[str]]]) -> None: ...
175
- assert to_sql(foo) == '`foo`(`x` ARRAY(TEXT NULL) NULL) RETURNS NULL'
171
+ assert to_sql(foo) == '`foo`(`x` ARRAY(TEXT NULL) NULL) RETURNS TINYINT NULL'
176
172
 
177
173
  # Custom type with bound
178
174
  def foo(x: D) -> None: ...
179
- assert to_sql(foo) == '`foo`(`x` TEXT NOT NULL) RETURNS NULL'
175
+ assert to_sql(foo) == '`foo`(`x` TEXT NOT NULL) RETURNS TINYINT NULL'
180
176
 
181
177
  # Incompatible types
182
178
  def foo(x: Union[int, str]) -> None: ...
@@ -184,22 +180,21 @@ class TestUDF(unittest.TestCase):
184
180
  to_sql(foo)
185
181
 
186
182
  # Tuple
187
- def foo(x: Tuple[int, float, str]) -> None: ...
188
- assert to_sql(foo) == '`foo`(`x` RECORD(`a` BIGINT NOT NULL, ' \
189
- '`b` DOUBLE NOT NULL, ' \
190
- '`c` TEXT NOT NULL) NOT NULL) RETURNS NULL'
183
+ with self.assertRaises(TypeError):
184
+ def foo(x: Tuple[int, float, str]) -> None: ...
185
+ to_sql(foo)
191
186
 
192
187
  # Optional tuple with optional element
193
- def foo(x: Optional[Tuple[int, float, Optional[str]]]) -> None: ...
194
- assert to_sql(foo) == '`foo`(`x` RECORD(`a` BIGINT NOT NULL, ' \
195
- '`b` DOUBLE NOT NULL, ' \
196
- '`c` TEXT NULL) NULL) RETURNS NULL'
188
+ with self.assertRaises(TypeError):
189
+ def foo(x: Optional[Tuple[int, float, Optional[str]]]) -> None: ...
190
+ to_sql(foo)
197
191
 
198
192
  # Optional tuple with optional union element
199
- def foo(x: Optional[Tuple[int, Optional[Union[float, int]], str]]) -> None: ...
200
- assert to_sql(foo) == '`foo`(`x` RECORD(`a` BIGINT NOT NULL, ' \
201
- '`b` DOUBLE NULL, ' \
202
- '`c` TEXT NOT NULL) NULL) RETURNS NULL'
193
+ with self.assertRaises(TypeError):
194
+ def foo(
195
+ x: Optional[Tuple[int, Optional[Union[float, int]], str]],
196
+ ) -> None: ...
197
+ to_sql(foo)
203
198
 
204
199
  # Unknown type
205
200
  def foo(x: set) -> None: ...
@@ -211,15 +206,15 @@ class TestUDF(unittest.TestCase):
211
206
 
212
207
  # Datetime
213
208
  def foo(x: datetime.datetime) -> None: ...
214
- assert to_sql(foo) == '`foo`(`x` DATETIME NOT NULL) RETURNS NULL'
209
+ assert to_sql(foo) == '`foo`(`x` DATETIME NOT NULL) RETURNS TINYINT NULL'
215
210
 
216
211
  # Date
217
212
  def foo(x: datetime.date) -> None: ...
218
- assert to_sql(foo) == '`foo`(`x` DATE NOT NULL) RETURNS NULL'
213
+ assert to_sql(foo) == '`foo`(`x` DATE NOT NULL) RETURNS TINYINT NULL'
219
214
 
220
215
  # Time
221
216
  def foo(x: datetime.timedelta) -> None: ...
222
- assert to_sql(foo) == '`foo`(`x` TIME NOT NULL) RETURNS NULL'
217
+ assert to_sql(foo) == '`foo`(`x` TIME NOT NULL) RETURNS TINYINT NULL'
223
218
 
224
219
  # Datetime + Date
225
220
  def foo(x: Union[datetime.datetime, datetime.date]) -> None: ...
@@ -231,75 +226,76 @@ class TestUDF(unittest.TestCase):
231
226
  # Ints
232
227
  #
233
228
  def foo(x: int) -> None: ...
234
- assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS NULL'
229
+ assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS TINYINT NULL'
235
230
 
236
231
  def foo(x: np.int8) -> None: ...
237
- assert to_sql(foo) == '`foo`(`x` TINYINT NOT NULL) RETURNS NULL'
232
+ assert to_sql(foo) == '`foo`(`x` TINYINT NOT NULL) RETURNS TINYINT NULL'
238
233
 
239
234
  def foo(x: np.int16) -> None: ...
240
- assert to_sql(foo) == '`foo`(`x` SMALLINT NOT NULL) RETURNS NULL'
235
+ assert to_sql(foo) == '`foo`(`x` SMALLINT NOT NULL) RETURNS TINYINT NULL'
241
236
 
242
237
  def foo(x: np.int32) -> None: ...
243
- assert to_sql(foo) == '`foo`(`x` INT NOT NULL) RETURNS NULL'
238
+ assert to_sql(foo) == '`foo`(`x` INT NOT NULL) RETURNS TINYINT NULL'
244
239
 
245
240
  def foo(x: np.int64) -> None: ...
246
- assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS NULL'
241
+ assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS TINYINT NULL'
247
242
 
248
243
  #
249
244
  # Unsigned ints
250
245
  #
251
246
  def foo(x: np.uint8) -> None: ...
252
- assert to_sql(foo) == '`foo`(`x` TINYINT UNSIGNED NOT NULL) RETURNS NULL'
247
+ assert to_sql(foo) == '`foo`(`x` TINYINT UNSIGNED NOT NULL) RETURNS TINYINT NULL'
253
248
 
254
249
  def foo(x: np.uint16) -> None: ...
255
- assert to_sql(foo) == '`foo`(`x` SMALLINT UNSIGNED NOT NULL) RETURNS NULL'
250
+ assert to_sql(foo) == '`foo`(`x` SMALLINT UNSIGNED NOT NULL) RETURNS TINYINT NULL'
256
251
 
257
252
  def foo(x: np.uint32) -> None: ...
258
- assert to_sql(foo) == '`foo`(`x` INT UNSIGNED NOT NULL) RETURNS NULL'
253
+ assert to_sql(foo) == '`foo`(`x` INT UNSIGNED NOT NULL) RETURNS TINYINT NULL'
259
254
 
260
255
  def foo(x: np.uint64) -> None: ...
261
- assert to_sql(foo) == '`foo`(`x` BIGINT UNSIGNED NOT NULL) RETURNS NULL'
256
+ assert to_sql(foo) == '`foo`(`x` BIGINT UNSIGNED NOT NULL) RETURNS TINYINT NULL'
262
257
 
263
258
  #
264
259
  # Floats
265
260
  #
266
261
  def foo(x: float) -> None: ...
267
- assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS NULL'
262
+ assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'
268
263
 
269
264
  def foo(x: np.float32) -> None: ...
270
- assert to_sql(foo) == '`foo`(`x` FLOAT NOT NULL) RETURNS NULL'
265
+ assert to_sql(foo) == '`foo`(`x` FLOAT NOT NULL) RETURNS TINYINT NULL'
271
266
 
272
267
  def foo(x: np.float64) -> None: ...
273
- assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS NULL'
268
+ assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'
274
269
 
275
270
  #
276
271
  # Type collapsing
277
272
  #
278
273
  def foo(x: Union[np.int8, np.int16]) -> None: ...
279
- assert to_sql(foo) == '`foo`(`x` SMALLINT NOT NULL) RETURNS NULL'
274
+ assert to_sql(foo) == '`foo`(`x` SMALLINT NOT NULL) RETURNS TINYINT NULL'
280
275
 
281
276
  def foo(x: Union[np.int64, np.double]) -> None: ...
282
- assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS NULL'
277
+ assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'
283
278
 
284
279
  def foo(x: Union[int, float]) -> None: ...
285
- assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS NULL'
280
+ assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'
286
281
 
287
282
  def test_positional_and_keyword_parameters(self):
288
283
  # Keyword only
289
284
  def foo(x: int = 100) -> None: ...
290
- assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL DEFAULT 100) RETURNS NULL'
285
+ assert to_sql(foo) == \
286
+ '`foo`(`x` BIGINT NOT NULL DEFAULT 100) RETURNS TINYINT NULL'
291
287
 
292
288
  # Multiple keywords
293
289
  def foo(x: int = 100, y: float = 3.14) -> None: ...
294
290
  assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL DEFAULT 100, ' \
295
- '`y` DOUBLE NOT NULL DEFAULT 3.14e0) RETURNS NULL'
291
+ '`y` DOUBLE NOT NULL DEFAULT 3.14e0) RETURNS TINYINT NULL'
296
292
 
297
293
  # Keywords and positional
298
294
  def foo(a: str, b: str, x: int = 100, y: float = 3.14) -> None: ...
299
295
  assert to_sql(foo) == '`foo`(`a` TEXT NOT NULL, ' \
300
296
  '`b` TEXT NOT NULL, ' \
301
297
  '`x` BIGINT NOT NULL DEFAULT 100, ' \
302
- '`y` DOUBLE NOT NULL DEFAULT 3.14e0) RETURNS NULL'
298
+ '`y` DOUBLE NOT NULL DEFAULT 3.14e0) RETURNS TINYINT NULL'
303
299
 
304
300
  # Variable positional
305
301
  def foo(*args: int) -> None: ...
@@ -336,9 +332,8 @@ class TestUDF(unittest.TestCase):
336
332
  # Override multiple params with one type
337
333
  @udf(args=dt.SMALLINT(nullable=False))
338
334
  def foo(x: int, y: float, z: np.int8) -> int: ...
339
- assert to_sql(foo) == '`foo`(`x` SMALLINT NOT NULL, ' \
340
- '`y` SMALLINT NOT NULL, ' \
341
- '`z` SMALLINT NOT NULL) RETURNS BIGINT NOT NULL'
335
+ with self.assertRaises(ValueError):
336
+ to_sql(foo)
342
337
 
343
338
  # Override with list
344
339
  @udf(args=[dt.SMALLINT, dt.FLOAT, dt.CHAR(30)])
@@ -350,13 +345,13 @@ class TestUDF(unittest.TestCase):
350
345
  # Override with too short of a list
351
346
  @udf(args=[dt.SMALLINT, dt.FLOAT])
352
347
  def foo(x: int, y: float, z: str) -> int: ...
353
- with self.assertRaises(TypeError):
348
+ with self.assertRaises(ValueError):
354
349
  to_sql(foo)
355
350
 
356
351
  # Override with too long of a list
357
352
  @udf(args=[dt.SMALLINT, dt.FLOAT, dt.CHAR(30), dt.TEXT])
358
353
  def foo(x: int, y: float, z: str) -> int: ...
359
- with self.assertRaises(TypeError):
354
+ with self.assertRaises(ValueError):
360
355
  to_sql(foo)
361
356
 
362
357
  # Override with list
@@ -367,32 +362,10 @@ class TestUDF(unittest.TestCase):
367
362
  '`z` CHAR(30) NULL) RETURNS BIGINT NOT NULL'
368
363
 
369
364
  # Override with dict
370
- @udf(args=dict(x=dt.SMALLINT, z=dt.CHAR(30)))
371
- def foo(x: int, y: float, z: str) -> int: ...
372
- assert to_sql(foo) == '`foo`(`x` SMALLINT NULL, ' \
373
- '`y` DOUBLE NOT NULL, ' \
374
- '`z` CHAR(30) NULL) RETURNS BIGINT NOT NULL'
375
-
376
- # Override with empty dict
377
- @udf(args=dict())
378
- def foo(x: int, y: float, z: str) -> int: ...
379
- assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL, ' \
380
- '`y` DOUBLE NOT NULL, ' \
381
- '`z` TEXT NOT NULL) RETURNS BIGINT NOT NULL'
382
-
383
- # Override with dict with extra keys
384
- @udf(args=dict(bar=dt.INT))
385
- def foo(x: int, y: float, z: str) -> int: ...
386
- assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL, ' \
387
- '`y` DOUBLE NOT NULL, ' \
388
- '`z` TEXT NOT NULL) RETURNS BIGINT NOT NULL'
389
-
390
- # Override parameters and return value
391
- @udf(args=dict(x=dt.SMALLINT, z=dt.CHAR(30)), returns=dt.SMALLINT(nullable=False))
392
- def foo(x: int, y: float, z: str) -> int: ...
393
- assert to_sql(foo) == '`foo`(`x` SMALLINT NULL, ' \
394
- '`y` DOUBLE NOT NULL, ' \
395
- '`z` CHAR(30) NULL) RETURNS SMALLINT NOT NULL'
365
+ with self.assertRaises(TypeError):
366
+ @udf(args=dict(x=dt.SMALLINT, z=dt.CHAR(30)))
367
+ def foo(x: int, y: float, z: str) -> int: ...
368
+ assert to_sql(foo)
396
369
 
397
370
  # Change function name
398
371
  @udf(name='hello_world')
@@ -411,26 +384,19 @@ class TestUDF(unittest.TestCase):
411
384
  two: str
412
385
  three: float
413
386
 
414
- @udf
415
- def foo(x: int) -> MyData: ...
416
- assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
417
- 'RETURNS RECORD(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
418
- '`three` DOUBLE NOT NULL) NOT NULL'
419
-
420
- @udf(returns=MyData)
421
- def foo(x: int) -> Tuple[int, int, int]: ...
422
- assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
423
- 'RETURNS RECORD(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
424
- '`three` DOUBLE NOT NULL) NOT NULL'
387
+ with self.assertRaises(TypeError):
388
+ @udf
389
+ def foo(x: int) -> MyData: ...
390
+ to_sql(foo)
425
391
 
426
- @tvf
427
- def foo(x: int) -> MyData: ...
392
+ @udf
393
+ def foo(x: int) -> Table[List[MyData]]: ...
428
394
  assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
429
395
  'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
430
396
  '`three` DOUBLE NOT NULL)'
431
397
 
432
- @tvf(returns=MyData)
433
- def foo(x: int) -> Tuple[int, int, int]: ...
398
+ @udf(returns=MyData)
399
+ def foo(x: int) -> Table[List[Tuple[int, int, int]]]: ...
434
400
  assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
435
401
  'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
436
402
  '`three` DOUBLE NOT NULL)'
@@ -441,25 +407,13 @@ class TestUDF(unittest.TestCase):
441
407
  three: float
442
408
 
443
409
  @udf
444
- def foo(x: int) -> MyData: ...
445
- assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
446
- 'RETURNS RECORD(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
447
- '`three` DOUBLE NOT NULL) NOT NULL'
448
-
449
- @udf(returns=MyData)
450
- def foo(x: int) -> Tuple[int, int, int]: ...
451
- assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
452
- 'RETURNS RECORD(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
453
- '`three` DOUBLE NOT NULL) NOT NULL'
454
-
455
- @tvf
456
- def foo(x: int) -> MyData: ...
410
+ def foo(x: int) -> Table[List[MyData]]: ...
457
411
  assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
458
412
  'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
459
413
  '`three` DOUBLE NOT NULL)'
460
414
 
461
- @tvf(returns=MyData)
462
- def foo(x: int) -> Tuple[int, int, int]: ...
415
+ @udf(returns=MyData)
416
+ def foo(x: int) -> Table[List[Tuple[int, int, int]]]: ...
463
417
  assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
464
418
  'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
465
419
  '`three` DOUBLE NOT NULL)'
@@ -728,12 +682,28 @@ class TestUDF(unittest.TestCase):
728
682
  assert dt.GEOGRAPHY(nullable=False) == 'GEOGRAPHY NOT NULL'
729
683
  assert dt.GEOGRAPHY(default='hi') == "GEOGRAPHY NULL DEFAULT 'hi'"
730
684
 
731
- with self.assertRaises(AssertionError):
732
- dt.RECORD()
733
- assert dt.RECORD(('a', dt.INT), ('b', dt.FLOAT)) == \
734
- 'RECORD(`a` INT NULL, `b` FLOAT NULL) NULL'
735
- assert dt.RECORD(('a', dt.INT), ('b', dt.FLOAT), nullable=False) == \
736
- 'RECORD(`a` INT NULL, `b` FLOAT NULL) NOT NULL'
737
-
738
- assert dt.ARRAY(dt.INT) == 'ARRAY(INT NULL) NULL'
739
- assert dt.ARRAY(dt.INT, nullable=False) == 'ARRAY(INT NULL) NOT NULL'
685
+ # with self.assertRaises(AssertionError):
686
+ # dt.RECORD()
687
+ # assert dt.RECORD(('a', dt.INT), ('b', dt.FLOAT)) == \
688
+ # 'RECORD(`a` INT NULL, `b` FLOAT NULL) NULL'
689
+ # assert dt.RECORD(('a', dt.INT), ('b', dt.FLOAT), nullable=False) == \
690
+ # 'RECORD(`a` INT NULL, `b` FLOAT NULL) NOT NULL'
691
+
692
+ # assert dt.ARRAY(dt.INT) == 'ARRAY(INT NULL) NULL'
693
+ # assert dt.ARRAY(dt.INT, nullable=False) == 'ARRAY(INT NULL) NOT NULL'
694
+
695
+ # assert dt.VECTOR(8) == 'VECTOR(8, F32) NULL'
696
+ # assert dt.VECTOR(8, dt.F32) == 'VECTOR(8, F32) NULL'
697
+ # assert dt.VECTOR(8, dt.F64) == 'VECTOR(8, F64) NULL'
698
+ # assert dt.VECTOR(8, dt.I8) == 'VECTOR(8, I8) NULL'
699
+ # assert dt.VECTOR(8, dt.I16) == 'VECTOR(8, I16) NULL'
700
+ # assert dt.VECTOR(8, dt.I32) == 'VECTOR(8, I32) NULL'
701
+ # assert dt.VECTOR(8, dt.I64) == 'VECTOR(8, I64) NULL'
702
+
703
+ # assert dt.VECTOR(8, nullable=False) == 'VECTOR(8, F32) NOT NULL'
704
+ # assert dt.VECTOR(8, dt.F32, nullable=False) == 'VECTOR(8, F32) NOT NULL'
705
+ # assert dt.VECTOR(8, dt.F64, nullable=False) == 'VECTOR(8, F64) NOT NULL'
706
+ # assert dt.VECTOR(8, dt.I8, nullable=False) == 'VECTOR(8, I8) NOT NULL'
707
+ # assert dt.VECTOR(8, dt.I16, nullable=False) == 'VECTOR(8, I16) NOT NULL'
708
+ # assert dt.VECTOR(8, dt.I32, nullable=False) == 'VECTOR(8, I32) NOT NULL'
709
+ # assert dt.VECTOR(8, dt.I64, nullable=False) == 'VECTOR(8, I64) NOT NULL'