Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
singlestore-labs
GitHub Repository: singlestore-labs/singlestoredb-python
Path: blob/main/singlestoredb/tests/test_udf.py
801 views
1
#!/usr/bin/env python
2
# type: ignore
3
"""SingleStoreDB UDF testing."""
4
import dataclasses
5
import datetime
6
import re
7
import unittest
8
from typing import List
9
from typing import Optional
10
from typing import Tuple
11
from typing import TypeVar
12
from typing import Union
13
14
import numpy as np
15
import pydantic
16
17
from ..functions import dtypes as dt
18
from ..functions import signature as sig
19
from ..functions import Table
20
from ..functions import udf
21
22
23
A = TypeVar('A', bytearray, bytes, None)
24
B = TypeVar('B', int, float, np.int64, np.int32, np.uint16)
25
C = TypeVar('C', B, np.int8)
26
D = TypeVar('D', bound=str)
27
E = Optional[List[Optional[Union[float, int]]]]
28
29
30
def to_sql(x):
31
out = sig.signature_to_sql(sig.get_signature(x))
32
out = re.sub(r'^CREATE EXTERNAL FUNCTION ', r'', out)
33
out = re.sub(r' AS REMOTE SERVICE.+$', r'', out)
34
return out.strip()
35
36
37
class TestUDF(unittest.TestCase):
38
39
def test_invalid_signature(self):
40
41
def foo(x: np.ndarray, y: np.ndarray) -> str: ...
42
with self.assertRaises(TypeError):
43
to_sql(foo)
44
45
def foo(x: str, y: str) -> np.ndarray: ...
46
with self.assertRaises(TypeError):
47
to_sql(foo)
48
49
def foo(x: str, y: np.ndarray) -> np.ndarray: ...
50
with self.assertRaises(TypeError):
51
to_sql(foo)
52
53
def foo(x: np.ndarray, y: str) -> np.ndarray: ...
54
with self.assertRaises(TypeError):
55
to_sql(foo)
56
57
def foo(x: str, y: np.ndarray) -> str: ...
58
with self.assertRaises(TypeError):
59
to_sql(foo)
60
61
def foo(x: np.ndarray, y: str) -> str: ...
62
with self.assertRaises(TypeError):
63
to_sql(foo)
64
65
def test_return_annotations(self):
66
67
# No annotations
68
def foo(): ...
69
with self.assertRaises(TypeError):
70
to_sql(foo)
71
72
# NULL return value
73
def foo() -> None: ...
74
assert to_sql(foo) == '`foo`() RETURNS TINYINT NULL'
75
76
# Simple return value
77
def foo() -> int: ...
78
assert to_sql(foo) == '`foo`() RETURNS BIGINT NOT NULL'
79
80
# Simple return value
81
def foo() -> np.int8: ...
82
assert to_sql(foo) == '`foo`() RETURNS TINYINT NOT NULL'
83
84
# Optional return value
85
def foo() -> Optional[int]: ...
86
assert to_sql(foo) == '`foo`() RETURNS BIGINT NULL'
87
88
# Optional return value
89
def foo() -> Union[int, None]: ...
90
assert to_sql(foo) == '`foo`() RETURNS BIGINT NULL'
91
92
# Optional return value with multiple types
93
def foo() -> Union[int, float, None]: ...
94
assert to_sql(foo) == '`foo`() RETURNS DOUBLE NULL'
95
96
# Optional return value with custom type
97
def foo() -> Optional[B]: ...
98
assert to_sql(foo) == '`foo`() RETURNS DOUBLE NULL'
99
100
# Optional return value with nested custom type
101
def foo() -> Optional[C]: ...
102
assert to_sql(foo) == '`foo`() RETURNS DOUBLE NULL'
103
104
# Optional return value with collection type
105
# def foo() -> Optional[List[str]]: ...
106
# assert to_sql(foo) == '`foo`() RETURNS ARRAY(TEXT NOT NULL) NULL'
107
108
# Optional return value with nested collection type
109
# def foo() -> Optional[List[List[str]]]: ...
110
# assert to_sql(foo) == '`foo`()
111
# RETURNS ARRAY(ARRAY(TEXT NOT NULL) NOT NULL) NULL'
112
113
# Optional return value with collection type with nulls
114
# def foo() -> Optional[List[Optional[str]]]: ...
115
# assert to_sql(foo) == '`foo`() RETURNS ARRAY(TEXT NULL) NULL'
116
117
# Custom type with bound
118
def foo() -> D: ...
119
assert to_sql(foo) == '`foo`() RETURNS TEXT NOT NULL'
120
121
# Return value with custom collection type with nulls
122
# def foo() -> E: ...
123
# assert to_sql(foo) == '`foo`() RETURNS ARRAY(DOUBLE NULL) NULL'
124
125
# Incompatible types
126
def foo() -> Union[int, str]: ...
127
with self.assertRaises(TypeError):
128
to_sql(foo)
129
130
# Tuple
131
with self.assertRaises(TypeError):
132
def foo() -> Tuple[int, float, str]: ...
133
to_sql(foo)
134
135
# Optional tuple
136
with self.assertRaises(TypeError):
137
def foo() -> Optional[Tuple[int, float, str]]: ...
138
to_sql(foo)
139
140
# Optional tuple with optional element
141
with self.assertRaises(TypeError):
142
def foo() -> Optional[Tuple[int, float, Optional[str]]]: ...
143
to_sql(foo)
144
145
# Optional tuple with optional union element
146
with self.assertRaises(TypeError):
147
def foo() -> Optional[Tuple[int, Optional[Union[float, int]], str]]: ...
148
to_sql(foo)
149
150
# Unknown type
151
def foo() -> set: ...
152
with self.assertRaises(TypeError) as exc:
153
to_sql(foo)
154
assert 'unsupported type annotation' in str(exc.exception)
155
156
def test_parameter_annotations(self):
157
158
# No annotations
159
def foo(x) -> None: ...
160
with self.assertRaises(TypeError):
161
to_sql(foo)
162
163
# Simple parameter
164
def foo(x: int) -> None: ...
165
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS TINYINT NULL'
166
167
# Optional parameter
168
def foo(x: Optional[int]) -> None: ...
169
assert to_sql(foo) == '`foo`(`x` BIGINT NULL) RETURNS TINYINT NULL'
170
171
# Optional parameter
172
def foo(x: Union[int, None]) -> None: ...
173
assert to_sql(foo) == '`foo`(`x` BIGINT NULL) RETURNS TINYINT NULL'
174
175
# Optional multiple parameter types
176
def foo(x: Union[int, float, None]) -> None: ...
177
assert to_sql(foo) == '`foo`(`x` DOUBLE NULL) RETURNS TINYINT NULL'
178
179
# Optional parameter with custom type
180
def foo(x: Optional[B]) -> None: ...
181
assert to_sql(foo) == '`foo`(`x` DOUBLE NULL) RETURNS TINYINT NULL'
182
183
# Optional parameter with nested custom type
184
def foo(x: Optional[C]) -> None: ...
185
assert to_sql(foo) == '`foo`(`x` DOUBLE NULL) RETURNS TINYINT NULL'
186
187
# Optional parameter with collection type
188
# def foo(x: Optional[List[str]]) -> None: ...
189
# assert to_sql(foo) == '`foo`(`x`
190
# ARRAY(TEXT NOT NULL) NULL) RETURNS TINYINT NULL'
191
192
# Optional parameter with nested collection type
193
# def foo(x: Optional[List[List[str]]]) -> None: ...
194
# assert to_sql(foo) == '`foo`(`x` ARRAY(ARRAY(TEXT NOT NULL) NOT NULL) NULL) ' \
195
# 'RETURNS TINYINT NULL'
196
197
# Optional parameter with collection type with nulls
198
# def foo(x: Optional[List[Optional[str]]]) -> None: ...
199
# assert to_sql(foo) == '`foo`(`x` ARRAY(TEXT NULL) NULL) RETURNS TINYINT NULL'
200
201
# Custom type with bound
202
def foo(x: D) -> None: ...
203
assert to_sql(foo) == '`foo`(`x` TEXT NOT NULL) RETURNS TINYINT NULL'
204
205
# Incompatible types
206
def foo(x: Union[int, str]) -> None: ...
207
with self.assertRaises(TypeError):
208
to_sql(foo)
209
210
# Tuple
211
with self.assertRaises(TypeError):
212
def foo(x: Tuple[int, float, str]) -> None: ...
213
to_sql(foo)
214
215
# Optional tuple with optional element
216
with self.assertRaises(TypeError):
217
def foo(x: Optional[Tuple[int, float, Optional[str]]]) -> None: ...
218
to_sql(foo)
219
220
# Optional tuple with optional union element
221
with self.assertRaises(TypeError):
222
def foo(
223
x: Optional[Tuple[int, Optional[Union[float, int]], str]],
224
) -> None: ...
225
to_sql(foo)
226
227
# Unknown type
228
def foo(x: set) -> None: ...
229
with self.assertRaises(TypeError) as exc:
230
to_sql(foo)
231
assert 'unsupported type annotation' in str(exc.exception)
232
233
def test_datetimes(self):
234
235
# Datetime
236
def foo(x: datetime.datetime) -> None: ...
237
assert to_sql(foo) == '`foo`(`x` DATETIME NOT NULL) RETURNS TINYINT NULL'
238
239
# Date
240
def foo(x: datetime.date) -> None: ...
241
assert to_sql(foo) == '`foo`(`x` DATE NOT NULL) RETURNS TINYINT NULL'
242
243
# Time
244
def foo(x: datetime.timedelta) -> None: ...
245
assert to_sql(foo) == '`foo`(`x` TIME NOT NULL) RETURNS TINYINT NULL'
246
247
# Datetime + Date
248
def foo(x: Union[datetime.datetime, datetime.date]) -> None: ...
249
with self.assertRaises(TypeError):
250
to_sql(foo)
251
252
def test_numerics(self):
253
#
254
# Bools
255
#
256
def foo(x: bool) -> None: ...
257
assert to_sql(foo) == '`foo`(`x` BOOL NOT NULL) RETURNS TINYINT NULL'
258
259
def foo(x: np.bool_) -> None: ...
260
assert to_sql(foo) == '`foo`(`x` BOOL NOT NULL) RETURNS TINYINT NULL'
261
262
def foo(x: Optional[bool]) -> None: ...
263
assert to_sql(foo) == '`foo`(`x` BOOL NULL) RETURNS TINYINT NULL'
264
265
def foo(x: Optional[np.bool_]) -> None: ...
266
assert to_sql(foo) == '`foo`(`x` BOOL NULL) RETURNS TINYINT NULL'
267
268
# Bool return types
269
def foo() -> bool: ...
270
assert to_sql(foo) == '`foo`() RETURNS BOOL NOT NULL'
271
272
def foo() -> np.bool_: ...
273
assert to_sql(foo) == '`foo`() RETURNS BOOL NOT NULL'
274
275
def foo() -> Optional[bool]: ...
276
assert to_sql(foo) == '`foo`() RETURNS BOOL NULL'
277
278
# Vector bool (List)
279
def foo(x: List[bool]) -> List[bool]: ...
280
assert to_sql(foo) == '`foo`(`x` BOOL NOT NULL) RETURNS BOOL NOT NULL'
281
282
def foo(x: List[np.bool_]) -> List[np.bool_]: ...
283
assert to_sql(foo) == '`foo`(`x` BOOL NOT NULL) RETURNS BOOL NOT NULL'
284
285
#
286
# Ints
287
#
288
def foo(x: int) -> None: ...
289
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS TINYINT NULL'
290
291
def foo(x: np.int8) -> None: ...
292
assert to_sql(foo) == '`foo`(`x` TINYINT NOT NULL) RETURNS TINYINT NULL'
293
294
def foo(x: np.int16) -> None: ...
295
assert to_sql(foo) == '`foo`(`x` SMALLINT NOT NULL) RETURNS TINYINT NULL'
296
297
def foo(x: np.int32) -> None: ...
298
assert to_sql(foo) == '`foo`(`x` INT NOT NULL) RETURNS TINYINT NULL'
299
300
def foo(x: np.int64) -> None: ...
301
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS TINYINT NULL'
302
303
#
304
# Unsigned ints
305
#
306
def foo(x: np.uint8) -> None: ...
307
assert to_sql(foo) == '`foo`(`x` TINYINT UNSIGNED NOT NULL) RETURNS TINYINT NULL'
308
309
def foo(x: np.uint16) -> None: ...
310
assert to_sql(foo) == '`foo`(`x` SMALLINT UNSIGNED NOT NULL) RETURNS TINYINT NULL'
311
312
def foo(x: np.uint32) -> None: ...
313
assert to_sql(foo) == '`foo`(`x` INT UNSIGNED NOT NULL) RETURNS TINYINT NULL'
314
315
def foo(x: np.uint64) -> None: ...
316
assert to_sql(foo) == '`foo`(`x` BIGINT UNSIGNED NOT NULL) RETURNS TINYINT NULL'
317
318
#
319
# Floats
320
#
321
def foo(x: float) -> None: ...
322
assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'
323
324
def foo(x: np.float16) -> None: ...
325
assert to_sql(foo) == '`foo`(`x` FLOAT NOT NULL) RETURNS TINYINT NULL'
326
327
def foo(x: np.float32) -> None: ...
328
assert to_sql(foo) == '`foo`(`x` FLOAT NOT NULL) RETURNS TINYINT NULL'
329
330
def foo(x: np.float64) -> None: ...
331
assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'
332
333
# Vector float16 (List)
334
def foo(x: List[np.float16]) -> List[np.float16]: ...
335
assert to_sql(foo) == '`foo`(`x` FLOAT NOT NULL) RETURNS FLOAT NOT NULL'
336
337
# Vector float32 (List)
338
def foo(x: List[np.float32]) -> List[np.float32]: ...
339
assert to_sql(foo) == '`foo`(`x` FLOAT NOT NULL) RETURNS FLOAT NOT NULL'
340
341
# Vector float64 (List)
342
def foo(x: List[np.float64]) -> List[np.float64]: ...
343
assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS DOUBLE NOT NULL'
344
345
#
346
# Type collapsing
347
#
348
def foo(x: Union[np.int8, np.int16]) -> None: ...
349
assert to_sql(foo) == '`foo`(`x` SMALLINT NOT NULL) RETURNS TINYINT NULL'
350
351
def foo(x: Union[np.int64, np.double]) -> None: ...
352
assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'
353
354
def foo(x: Union[int, float]) -> None: ...
355
assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'
356
357
def test_positional_and_keyword_parameters(self):
358
# Keyword only
359
def foo(x: int = 100) -> None: ...
360
assert to_sql(foo) == \
361
'`foo`(`x` BIGINT NOT NULL DEFAULT 100) RETURNS TINYINT NULL'
362
363
# Multiple keywords
364
def foo(x: int = 100, y: float = 3.14) -> None: ...
365
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL DEFAULT 100, ' \
366
'`y` DOUBLE NOT NULL DEFAULT 3.14e0) RETURNS TINYINT NULL'
367
368
# Keywords and positional
369
def foo(a: str, b: str, x: int = 100, y: float = 3.14) -> None: ...
370
assert to_sql(foo) == '`foo`(`a` TEXT NOT NULL, ' \
371
'`b` TEXT NOT NULL, ' \
372
'`x` BIGINT NOT NULL DEFAULT 100, ' \
373
'`y` DOUBLE NOT NULL DEFAULT 3.14e0) RETURNS TINYINT NULL'
374
375
# Variable positional
376
def foo(*args: int) -> None: ...
377
with self.assertRaises(TypeError):
378
to_sql(foo)
379
380
# Variable keywords
381
def foo(x: int = 100, **kwargs: float) -> None: ...
382
with self.assertRaises(TypeError):
383
to_sql(foo)
384
385
def test_udf(self):
386
387
# No parameters
388
@udf
389
def foo(x: int) -> int: ...
390
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS BIGINT NOT NULL'
391
392
# No parameters
393
@udf()
394
def foo(x: int) -> int: ...
395
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS BIGINT NOT NULL'
396
397
# Override return value with callable
398
@udf(returns=dt.SMALLINT)
399
def foo(x: int) -> int: ...
400
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS SMALLINT NULL'
401
402
# Override return value with string
403
@udf(returns=dt.SMALLINT(nullable=False))
404
def foo(x: int) -> int: ...
405
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS SMALLINT NOT NULL'
406
407
# Override multiple params with one type
408
@udf(args=dt.SMALLINT(nullable=False))
409
def foo(x: int, y: float, z: np.int8) -> int: ...
410
with self.assertRaises(ValueError):
411
to_sql(foo)
412
413
# Override with list
414
@udf(args=[dt.SMALLINT, dt.FLOAT, dt.CHAR(30)])
415
def foo(x: int, y: float, z: str) -> int: ...
416
assert to_sql(foo) == '`foo`(`x` SMALLINT NULL, ' \
417
'`y` FLOAT NULL, ' \
418
'`z` CHAR(30) NULL) RETURNS BIGINT NOT NULL'
419
420
# Override with too short of a list
421
@udf(args=[dt.SMALLINT, dt.FLOAT])
422
def foo(x: int, y: float, z: str) -> int: ...
423
with self.assertRaises(ValueError):
424
to_sql(foo)
425
426
# Override with too long of a list
427
@udf(args=[dt.SMALLINT, dt.FLOAT, dt.CHAR(30), dt.TEXT])
428
def foo(x: int, y: float, z: str) -> int: ...
429
with self.assertRaises(ValueError):
430
to_sql(foo)
431
432
# Override with list
433
@udf(args=[dt.SMALLINT, dt.FLOAT, dt.CHAR(30)])
434
def foo(x: int, y: float, z: str) -> int: ...
435
assert to_sql(foo) == '`foo`(`x` SMALLINT NULL, ' \
436
'`y` FLOAT NULL, ' \
437
'`z` CHAR(30) NULL) RETURNS BIGINT NOT NULL'
438
439
# Override with dict
440
with self.assertRaises(TypeError):
441
@udf(args=dict(x=dt.SMALLINT, z=dt.CHAR(30)))
442
def foo(x: int, y: float, z: str) -> int: ...
443
assert to_sql(foo)
444
445
# Change function name
446
@udf(name='hello_world')
447
def foo(x: int) -> int: ...
448
assert to_sql(foo) == '`hello_world`(`x` BIGINT NOT NULL) ' \
449
'RETURNS BIGINT NOT NULL'
450
451
@udf(name='hello`_`world')
452
def foo(x: int) -> int: ...
453
assert to_sql(foo) == '`hello``_``world`(`x` BIGINT NOT NULL) ' \
454
'RETURNS BIGINT NOT NULL'
455
456
@dataclasses.dataclass
457
class MyData:
458
one: Optional[int]
459
two: str
460
three: float
461
462
with self.assertRaises(TypeError):
463
@udf
464
def foo(x: int) -> MyData: ...
465
to_sql(foo)
466
467
@udf
468
def foo(x: int) -> Table[List[MyData]]: ...
469
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
470
'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
471
'`three` DOUBLE NOT NULL)'
472
473
@udf(returns=MyData)
474
def foo(x: int) -> Table[List[Tuple[int, int, int]]]: ...
475
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
476
'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
477
'`three` DOUBLE NOT NULL)'
478
479
class MyData(pydantic.BaseModel):
480
one: Optional[int]
481
two: str
482
three: float
483
484
@udf
485
def foo(x: int) -> Table[List[MyData]]: ...
486
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
487
'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
488
'`three` DOUBLE NOT NULL)'
489
490
@udf(returns=MyData)
491
def foo(x: int) -> Table[List[Tuple[int, int, int]]]: ...
492
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
493
'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
494
'`three` DOUBLE NOT NULL)'
495
496
def test_dtypes(self):
497
assert dt.BOOL() == 'BOOL NULL'
498
assert dt.BOOL(nullable=False) == 'BOOL NOT NULL'
499
assert dt.BOOL(default=False) == 'BOOL NULL DEFAULT 0'
500
assert dt.BOOL(default=True) == 'BOOL NULL DEFAULT 1'
501
assert dt.BOOL(default='a') == 'BOOL NULL DEFAULT 1'
502
503
assert dt.BOOLEAN() == 'BOOLEAN NULL'
504
assert dt.BOOLEAN(nullable=False) == 'BOOLEAN NOT NULL'
505
assert dt.BOOLEAN(default=False) == 'BOOLEAN NULL DEFAULT 0'
506
assert dt.BOOLEAN(default=True) == 'BOOLEAN NULL DEFAULT 1'
507
assert dt.BOOLEAN(default='a') == 'BOOLEAN NULL DEFAULT 1'
508
509
assert dt.BIT() == 'BIT NULL'
510
assert dt.BIT(nullable=False) == 'BIT NOT NULL'
511
assert dt.BIT(default=100) == 'BIT NULL DEFAULT 100'
512
513
assert dt.TINYINT() == 'TINYINT NULL'
514
assert dt.TINYINT(5) == 'TINYINT(5) NULL'
515
assert dt.TINYINT(nullable=False) == 'TINYINT NOT NULL'
516
assert dt.TINYINT(default=100) == 'TINYINT NULL DEFAULT 100'
517
assert dt.TINYINT(unsigned=True, default=100) == \
518
'TINYINT UNSIGNED NULL DEFAULT 100'
519
520
assert dt.TINYINT_UNSIGNED() == 'TINYINT UNSIGNED NULL'
521
assert dt.TINYINT_UNSIGNED(5) == 'TINYINT(5) UNSIGNED NULL'
522
assert dt.TINYINT_UNSIGNED(nullable=False) == 'TINYINT UNSIGNED NOT NULL'
523
assert dt.TINYINT_UNSIGNED(default=100) == 'TINYINT UNSIGNED NULL DEFAULT 100'
524
525
assert dt.SMALLINT() == 'SMALLINT NULL'
526
assert dt.SMALLINT(5) == 'SMALLINT(5) NULL'
527
assert dt.SMALLINT(nullable=False) == 'SMALLINT NOT NULL'
528
assert dt.SMALLINT(default=100) == 'SMALLINT NULL DEFAULT 100'
529
assert dt.SMALLINT(unsigned=True, default=100) == \
530
'SMALLINT UNSIGNED NULL DEFAULT 100'
531
532
assert dt.SMALLINT_UNSIGNED() == 'SMALLINT UNSIGNED NULL'
533
assert dt.SMALLINT_UNSIGNED(5) == 'SMALLINT(5) UNSIGNED NULL'
534
assert dt.SMALLINT_UNSIGNED(nullable=False) == 'SMALLINT UNSIGNED NOT NULL'
535
assert dt.SMALLINT_UNSIGNED(default=100) == \
536
'SMALLINT UNSIGNED NULL DEFAULT 100'
537
538
assert dt.MEDIUMINT() == 'MEDIUMINT NULL'
539
assert dt.MEDIUMINT(5) == 'MEDIUMINT(5) NULL'
540
assert dt.MEDIUMINT(nullable=False) == 'MEDIUMINT NOT NULL'
541
assert dt.MEDIUMINT(default=100) == 'MEDIUMINT NULL DEFAULT 100'
542
assert dt.MEDIUMINT(unsigned=True, default=100) == \
543
'MEDIUMINT UNSIGNED NULL DEFAULT 100'
544
545
assert dt.MEDIUMINT_UNSIGNED() == 'MEDIUMINT UNSIGNED NULL'
546
assert dt.MEDIUMINT_UNSIGNED(5) == 'MEDIUMINT(5) UNSIGNED NULL'
547
assert dt.MEDIUMINT_UNSIGNED(nullable=False) == 'MEDIUMINT UNSIGNED NOT NULL'
548
assert dt.MEDIUMINT_UNSIGNED(default=100) == \
549
'MEDIUMINT UNSIGNED NULL DEFAULT 100'
550
551
assert dt.INT() == 'INT NULL'
552
assert dt.INT(5) == 'INT(5) NULL'
553
assert dt.INT(nullable=False) == 'INT NOT NULL'
554
assert dt.INT(default=100) == 'INT NULL DEFAULT 100'
555
assert dt.INT(unsigned=True, default=100) == \
556
'INT UNSIGNED NULL DEFAULT 100'
557
558
assert dt.INT_UNSIGNED() == 'INT UNSIGNED NULL'
559
assert dt.INT_UNSIGNED(5) == 'INT(5) UNSIGNED NULL'
560
assert dt.INT_UNSIGNED(nullable=False) == 'INT UNSIGNED NOT NULL'
561
assert dt.INT_UNSIGNED(default=100) == \
562
'INT UNSIGNED NULL DEFAULT 100'
563
564
assert dt.INTEGER() == 'INTEGER NULL'
565
assert dt.INTEGER(5) == 'INTEGER(5) NULL'
566
assert dt.INTEGER(nullable=False) == 'INTEGER NOT NULL'
567
assert dt.INTEGER(default=100) == 'INTEGER NULL DEFAULT 100'
568
assert dt.INTEGER(unsigned=True, default=100) == \
569
'INTEGER UNSIGNED NULL DEFAULT 100'
570
571
assert dt.INTEGER_UNSIGNED() == 'INTEGER UNSIGNED NULL'
572
assert dt.INTEGER_UNSIGNED(5) == 'INTEGER(5) UNSIGNED NULL'
573
assert dt.INTEGER_UNSIGNED(nullable=False) == 'INTEGER UNSIGNED NOT NULL'
574
assert dt.INTEGER_UNSIGNED(default=100) == \
575
'INTEGER UNSIGNED NULL DEFAULT 100'
576
577
assert dt.BIGINT() == 'BIGINT NULL'
578
assert dt.BIGINT(5) == 'BIGINT(5) NULL'
579
assert dt.BIGINT(nullable=False) == 'BIGINT NOT NULL'
580
assert dt.BIGINT(default=100) == 'BIGINT NULL DEFAULT 100'
581
assert dt.BIGINT(unsigned=True, default=100) == \
582
'BIGINT UNSIGNED NULL DEFAULT 100'
583
584
assert dt.BIGINT_UNSIGNED() == 'BIGINT UNSIGNED NULL'
585
assert dt.BIGINT_UNSIGNED(5) == 'BIGINT(5) UNSIGNED NULL'
586
assert dt.BIGINT_UNSIGNED(nullable=False) == 'BIGINT UNSIGNED NOT NULL'
587
assert dt.BIGINT_UNSIGNED(default=100) == \
588
'BIGINT UNSIGNED NULL DEFAULT 100'
589
590
assert dt.BIGINT() == 'BIGINT NULL'
591
assert dt.BIGINT(5) == 'BIGINT(5) NULL'
592
assert dt.BIGINT(nullable=False) == 'BIGINT NOT NULL'
593
assert dt.BIGINT(default=100) == 'BIGINT NULL DEFAULT 100'
594
assert dt.BIGINT(unsigned=True, default=100) == \
595
'BIGINT UNSIGNED NULL DEFAULT 100'
596
597
assert dt.FLOAT() == 'FLOAT NULL'
598
assert dt.FLOAT(5) == 'FLOAT(5) NULL'
599
assert dt.FLOAT(nullable=False) == 'FLOAT NOT NULL'
600
assert dt.FLOAT(default=1.234) == 'FLOAT NULL DEFAULT 1.234e0'
601
602
assert dt.DOUBLE() == 'DOUBLE NULL'
603
assert dt.DOUBLE(5) == 'DOUBLE(5) NULL'
604
assert dt.DOUBLE(nullable=False) == 'DOUBLE NOT NULL'
605
assert dt.DOUBLE(default=1.234) == 'DOUBLE NULL DEFAULT 1.234e0'
606
607
assert dt.REAL() == 'REAL NULL'
608
assert dt.REAL(5) == 'REAL(5) NULL'
609
assert dt.REAL(nullable=False) == 'REAL NOT NULL'
610
assert dt.REAL(default=1.234) == 'REAL NULL DEFAULT 1.234e0'
611
612
with self.assertRaises(TypeError):
613
dt.DECIMAL()
614
with self.assertRaises(TypeError):
615
dt.DECIMAL(5)
616
assert dt.DECIMAL(10, 5) == 'DECIMAL(10, 5) NULL'
617
assert dt.DECIMAL(10, 5, nullable=False) == 'DECIMAL(10, 5) NOT NULL'
618
assert dt.DECIMAL(10, 5, default=1.234) == \
619
'DECIMAL(10, 5) NULL DEFAULT 1.234e0'
620
621
with self.assertRaises(TypeError):
622
dt.DEC()
623
with self.assertRaises(TypeError):
624
dt.DEC(5)
625
assert dt.DEC(10, 5) == 'DEC(10, 5) NULL'
626
assert dt.DEC(10, 5, nullable=False) == 'DEC(10, 5) NOT NULL'
627
assert dt.DEC(10, 5, default=1.234) == \
628
'DEC(10, 5) NULL DEFAULT 1.234e0'
629
630
with self.assertRaises(TypeError):
631
dt.FIXED()
632
with self.assertRaises(TypeError):
633
dt.FIXED(5)
634
assert dt.FIXED(10, 5) == 'FIXED(10, 5) NULL'
635
assert dt.FIXED(10, 5, nullable=False) == 'FIXED(10, 5) NOT NULL'
636
assert dt.FIXED(10, 5, default=1.234) == \
637
'FIXED(10, 5) NULL DEFAULT 1.234e0'
638
639
with self.assertRaises(TypeError):
640
dt.NUMERIC()
641
with self.assertRaises(TypeError):
642
dt.NUMERIC(5)
643
assert dt.NUMERIC(10, 5) == 'NUMERIC(10, 5) NULL'
644
assert dt.NUMERIC(10, 5, nullable=False) == 'NUMERIC(10, 5) NOT NULL'
645
assert dt.NUMERIC(10, 5, default=1.234) == \
646
'NUMERIC(10, 5) NULL DEFAULT 1.234e0'
647
648
assert dt.DATE() == 'DATE NULL'
649
assert dt.DATE(nullable=False) == 'DATE NOT NULL'
650
assert dt.DATE(default=datetime.date(2020, 1, 2)) == \
651
"DATE NULL DEFAULT '2020-01-02'"
652
653
assert dt.TIME() == 'TIME NULL'
654
assert dt.TIME(6) == 'TIME(6) NULL'
655
assert dt.TIME(nullable=False) == 'TIME NOT NULL'
656
assert dt.TIME(default=datetime.timedelta(seconds=1000)) == \
657
"TIME NULL DEFAULT '00:16:40'"
658
659
assert dt.DATETIME() == 'DATETIME NULL'
660
assert dt.DATETIME(6) == 'DATETIME(6) NULL'
661
assert dt.DATETIME(nullable=False) == 'DATETIME NOT NULL'
662
assert dt.DATETIME(default=datetime.datetime(2020, 1, 2, 3, 4, 5)) == \
663
"DATETIME NULL DEFAULT '2020-01-02 03:04:05'"
664
665
assert dt.TIMESTAMP() == 'TIMESTAMP NULL'
666
assert dt.TIMESTAMP(6) == 'TIMESTAMP(6) NULL'
667
assert dt.TIMESTAMP(nullable=False) == 'TIMESTAMP NOT NULL'
668
assert dt.TIMESTAMP(default=datetime.datetime(2020, 1, 2, 3, 4, 5)) == \
669
"TIMESTAMP NULL DEFAULT '2020-01-02 03:04:05'"
670
671
assert dt.YEAR() == 'YEAR NULL'
672
assert dt.YEAR(nullable=False) == 'YEAR NOT NULL'
673
assert dt.YEAR(default=1961) == 'YEAR NULL DEFAULT 1961'
674
675
assert dt.CHAR() == 'CHAR NULL'
676
assert dt.CHAR(10) == 'CHAR(10) NULL'
677
assert dt.CHAR(charset=dt.utf8, collate=dt.utf8_bin) == \
678
'CHAR CHARACTER SET utf8 COLLATE utf8_bin NULL'
679
assert dt.CHAR(nullable=False) == 'CHAR NOT NULL'
680
assert dt.CHAR(default='hi') == "CHAR NULL DEFAULT 'hi'"
681
682
assert dt.VARCHAR() == 'VARCHAR NULL'
683
assert dt.VARCHAR(10) == 'VARCHAR(10) NULL'
684
assert dt.VARCHAR(charset=dt.utf8, collate=dt.utf8_bin) == \
685
'VARCHAR CHARACTER SET utf8 COLLATE utf8_bin NULL'
686
assert dt.VARCHAR(nullable=False) == 'VARCHAR NOT NULL'
687
assert dt.VARCHAR(default='hi') == "VARCHAR NULL DEFAULT 'hi'"
688
689
assert dt.LONGTEXT() == 'LONGTEXT NULL'
690
assert dt.LONGTEXT(10) == 'LONGTEXT(10) NULL'
691
assert dt.LONGTEXT(charset=dt.utf8, collate=dt.utf8_bin) == \
692
'LONGTEXT CHARACTER SET utf8 COLLATE utf8_bin NULL'
693
assert dt.LONGTEXT(nullable=False) == 'LONGTEXT NOT NULL'
694
assert dt.LONGTEXT(default='hi') == "LONGTEXT NULL DEFAULT 'hi'"
695
696
assert dt.MEDIUMTEXT() == 'MEDIUMTEXT NULL'
697
assert dt.MEDIUMTEXT(10) == 'MEDIUMTEXT(10) NULL'
698
assert dt.MEDIUMTEXT(charset=dt.utf8, collate=dt.utf8_bin) == \
699
'MEDIUMTEXT CHARACTER SET utf8 COLLATE utf8_bin NULL'
700
assert dt.MEDIUMTEXT(nullable=False) == 'MEDIUMTEXT NOT NULL'
701
assert dt.MEDIUMTEXT(default='hi') == "MEDIUMTEXT NULL DEFAULT 'hi'"
702
703
assert dt.TEXT() == 'TEXT NULL'
704
assert dt.TEXT(10) == 'TEXT(10) NULL'
705
assert dt.TEXT(charset=dt.utf8, collate=dt.utf8_bin) == \
706
'TEXT CHARACTER SET utf8 COLLATE utf8_bin NULL'
707
assert dt.TEXT(nullable=False) == 'TEXT NOT NULL'
708
assert dt.TEXT(default='hi') == "TEXT NULL DEFAULT 'hi'"
709
710
assert dt.TINYTEXT() == 'TINYTEXT NULL'
711
assert dt.TINYTEXT(10) == 'TINYTEXT(10) NULL'
712
assert dt.TINYTEXT(charset=dt.utf8, collate=dt.utf8_bin) == \
713
'TINYTEXT CHARACTER SET utf8 COLLATE utf8_bin NULL'
714
assert dt.TINYTEXT(nullable=False) == 'TINYTEXT NOT NULL'
715
assert dt.TINYTEXT(default='hi') == "TINYTEXT NULL DEFAULT 'hi'"
716
717
assert dt.BINARY() == 'BINARY NULL'
718
assert dt.BINARY(10) == 'BINARY(10) NULL'
719
assert dt.BINARY(collate=dt.utf8_bin) == \
720
'BINARY COLLATE utf8_bin NULL'
721
assert dt.BINARY(nullable=False) == 'BINARY NOT NULL'
722
assert dt.BINARY(default='hi') == "BINARY NULL DEFAULT 'hi'"
723
724
assert dt.VARBINARY() == 'VARBINARY NULL'
725
assert dt.VARBINARY(10) == 'VARBINARY(10) NULL'
726
assert dt.VARBINARY(collate=dt.utf8_bin) == \
727
'VARBINARY COLLATE utf8_bin NULL'
728
assert dt.VARBINARY(nullable=False) == 'VARBINARY NOT NULL'
729
assert dt.VARBINARY(default='hi') == "VARBINARY NULL DEFAULT 'hi'"
730
731
assert dt.BLOB() == 'BLOB NULL'
732
assert dt.BLOB(10) == 'BLOB(10) NULL'
733
assert dt.BLOB(collate=dt.utf8_bin) == \
734
'BLOB COLLATE utf8_bin NULL'
735
assert dt.BLOB(nullable=False) == 'BLOB NOT NULL'
736
assert dt.BLOB(default='hi') == "BLOB NULL DEFAULT 'hi'"
737
738
assert dt.TINYBLOB() == 'TINYBLOB NULL'
739
assert dt.TINYBLOB(10) == 'TINYBLOB(10) NULL'
740
assert dt.TINYBLOB(collate=dt.utf8_bin) == \
741
'TINYBLOB COLLATE utf8_bin NULL'
742
assert dt.TINYBLOB(nullable=False) == 'TINYBLOB NOT NULL'
743
assert dt.TINYBLOB(default='hi') == "TINYBLOB NULL DEFAULT 'hi'"
744
745
assert dt.JSON() == 'JSON NULL'
746
assert dt.JSON(10) == 'JSON(10) NULL'
747
assert dt.JSON(charset=dt.utf8, collate=dt.utf8_bin) == \
748
'JSON CHARACTER SET utf8 COLLATE utf8_bin NULL'
749
assert dt.JSON(nullable=False) == 'JSON NOT NULL'
750
assert dt.JSON(default='hi') == "JSON NULL DEFAULT 'hi'"
751
752
assert dt.GEOGRAPHYPOINT() == 'GEOGRAPHYPOINT NULL'
753
assert dt.GEOGRAPHYPOINT(nullable=False) == 'GEOGRAPHYPOINT NOT NULL'
754
assert dt.GEOGRAPHYPOINT(default='hi') == "GEOGRAPHYPOINT NULL DEFAULT 'hi'"
755
756
assert dt.GEOGRAPHY() == 'GEOGRAPHY NULL'
757
assert dt.GEOGRAPHY(nullable=False) == 'GEOGRAPHY NOT NULL'
758
assert dt.GEOGRAPHY(default='hi') == "GEOGRAPHY NULL DEFAULT 'hi'"
759
760
# with self.assertRaises(AssertionError):
761
# dt.RECORD()
762
# assert dt.RECORD(('a', dt.INT), ('b', dt.FLOAT)) == \
763
# 'RECORD(`a` INT NULL, `b` FLOAT NULL) NULL'
764
# assert dt.RECORD(('a', dt.INT), ('b', dt.FLOAT), nullable=False) == \
765
# 'RECORD(`a` INT NULL, `b` FLOAT NULL) NOT NULL'
766
767
# assert dt.ARRAY(dt.INT) == 'ARRAY(INT NULL) NULL'
768
# assert dt.ARRAY(dt.INT, nullable=False) == 'ARRAY(INT NULL) NOT NULL'
769
770
# assert dt.VECTOR(8) == 'VECTOR(8, F32) NULL'
771
# assert dt.VECTOR(8, dt.F32) == 'VECTOR(8, F32) NULL'
772
# assert dt.VECTOR(8, dt.F64) == 'VECTOR(8, F64) NULL'
773
# assert dt.VECTOR(8, dt.I8) == 'VECTOR(8, I8) NULL'
774
# assert dt.VECTOR(8, dt.I16) == 'VECTOR(8, I16) NULL'
775
# assert dt.VECTOR(8, dt.I32) == 'VECTOR(8, I32) NULL'
776
# assert dt.VECTOR(8, dt.I64) == 'VECTOR(8, I64) NULL'
777
778
# assert dt.VECTOR(8, nullable=False) == 'VECTOR(8, F32) NOT NULL'
779
# assert dt.VECTOR(8, dt.F32, nullable=False) == 'VECTOR(8, F32) NOT NULL'
780
# assert dt.VECTOR(8, dt.F64, nullable=False) == 'VECTOR(8, F64) NOT NULL'
781
# assert dt.VECTOR(8, dt.I8, nullable=False) == 'VECTOR(8, I8) NOT NULL'
782
# assert dt.VECTOR(8, dt.I16, nullable=False) == 'VECTOR(8, I16) NOT NULL'
783
# assert dt.VECTOR(8, dt.I32, nullable=False) == 'VECTOR(8, I32) NOT NULL'
784
# assert dt.VECTOR(8, dt.I64, nullable=False) == 'VECTOR(8, I64) NOT NULL'
785
786