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
469 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
# Ints
255
#
256
def foo(x: int) -> None: ...
257
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS TINYINT NULL'
258
259
def foo(x: np.int8) -> None: ...
260
assert to_sql(foo) == '`foo`(`x` TINYINT NOT NULL) RETURNS TINYINT NULL'
261
262
def foo(x: np.int16) -> None: ...
263
assert to_sql(foo) == '`foo`(`x` SMALLINT NOT NULL) RETURNS TINYINT NULL'
264
265
def foo(x: np.int32) -> None: ...
266
assert to_sql(foo) == '`foo`(`x` INT NOT NULL) RETURNS TINYINT NULL'
267
268
def foo(x: np.int64) -> None: ...
269
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS TINYINT NULL'
270
271
#
272
# Unsigned ints
273
#
274
def foo(x: np.uint8) -> None: ...
275
assert to_sql(foo) == '`foo`(`x` TINYINT UNSIGNED NOT NULL) RETURNS TINYINT NULL'
276
277
def foo(x: np.uint16) -> None: ...
278
assert to_sql(foo) == '`foo`(`x` SMALLINT UNSIGNED NOT NULL) RETURNS TINYINT NULL'
279
280
def foo(x: np.uint32) -> None: ...
281
assert to_sql(foo) == '`foo`(`x` INT UNSIGNED NOT NULL) RETURNS TINYINT NULL'
282
283
def foo(x: np.uint64) -> None: ...
284
assert to_sql(foo) == '`foo`(`x` BIGINT UNSIGNED NOT NULL) RETURNS TINYINT NULL'
285
286
#
287
# Floats
288
#
289
def foo(x: float) -> None: ...
290
assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'
291
292
def foo(x: np.float32) -> None: ...
293
assert to_sql(foo) == '`foo`(`x` FLOAT NOT NULL) RETURNS TINYINT NULL'
294
295
def foo(x: np.float64) -> None: ...
296
assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'
297
298
#
299
# Type collapsing
300
#
301
def foo(x: Union[np.int8, np.int16]) -> None: ...
302
assert to_sql(foo) == '`foo`(`x` SMALLINT NOT NULL) RETURNS TINYINT NULL'
303
304
def foo(x: Union[np.int64, np.double]) -> None: ...
305
assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'
306
307
def foo(x: Union[int, float]) -> None: ...
308
assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'
309
310
def test_positional_and_keyword_parameters(self):
311
# Keyword only
312
def foo(x: int = 100) -> None: ...
313
assert to_sql(foo) == \
314
'`foo`(`x` BIGINT NOT NULL DEFAULT 100) RETURNS TINYINT NULL'
315
316
# Multiple keywords
317
def foo(x: int = 100, y: float = 3.14) -> None: ...
318
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL DEFAULT 100, ' \
319
'`y` DOUBLE NOT NULL DEFAULT 3.14e0) RETURNS TINYINT NULL'
320
321
# Keywords and positional
322
def foo(a: str, b: str, x: int = 100, y: float = 3.14) -> None: ...
323
assert to_sql(foo) == '`foo`(`a` TEXT NOT NULL, ' \
324
'`b` TEXT NOT NULL, ' \
325
'`x` BIGINT NOT NULL DEFAULT 100, ' \
326
'`y` DOUBLE NOT NULL DEFAULT 3.14e0) RETURNS TINYINT NULL'
327
328
# Variable positional
329
def foo(*args: int) -> None: ...
330
with self.assertRaises(TypeError):
331
to_sql(foo)
332
333
# Variable keywords
334
def foo(x: int = 100, **kwargs: float) -> None: ...
335
with self.assertRaises(TypeError):
336
to_sql(foo)
337
338
def test_udf(self):
339
340
# No parameters
341
@udf
342
def foo(x: int) -> int: ...
343
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS BIGINT NOT NULL'
344
345
# No parameters
346
@udf()
347
def foo(x: int) -> int: ...
348
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS BIGINT NOT NULL'
349
350
# Override return value with callable
351
@udf(returns=dt.SMALLINT)
352
def foo(x: int) -> int: ...
353
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS SMALLINT NULL'
354
355
# Override return value with string
356
@udf(returns=dt.SMALLINT(nullable=False))
357
def foo(x: int) -> int: ...
358
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS SMALLINT NOT NULL'
359
360
# Override multiple params with one type
361
@udf(args=dt.SMALLINT(nullable=False))
362
def foo(x: int, y: float, z: np.int8) -> int: ...
363
with self.assertRaises(ValueError):
364
to_sql(foo)
365
366
# Override with list
367
@udf(args=[dt.SMALLINT, dt.FLOAT, dt.CHAR(30)])
368
def foo(x: int, y: float, z: str) -> int: ...
369
assert to_sql(foo) == '`foo`(`x` SMALLINT NULL, ' \
370
'`y` FLOAT NULL, ' \
371
'`z` CHAR(30) NULL) RETURNS BIGINT NOT NULL'
372
373
# Override with too short of a list
374
@udf(args=[dt.SMALLINT, dt.FLOAT])
375
def foo(x: int, y: float, z: str) -> int: ...
376
with self.assertRaises(ValueError):
377
to_sql(foo)
378
379
# Override with too long of a list
380
@udf(args=[dt.SMALLINT, dt.FLOAT, dt.CHAR(30), dt.TEXT])
381
def foo(x: int, y: float, z: str) -> int: ...
382
with self.assertRaises(ValueError):
383
to_sql(foo)
384
385
# Override with list
386
@udf(args=[dt.SMALLINT, dt.FLOAT, dt.CHAR(30)])
387
def foo(x: int, y: float, z: str) -> int: ...
388
assert to_sql(foo) == '`foo`(`x` SMALLINT NULL, ' \
389
'`y` FLOAT NULL, ' \
390
'`z` CHAR(30) NULL) RETURNS BIGINT NOT NULL'
391
392
# Override with dict
393
with self.assertRaises(TypeError):
394
@udf(args=dict(x=dt.SMALLINT, z=dt.CHAR(30)))
395
def foo(x: int, y: float, z: str) -> int: ...
396
assert to_sql(foo)
397
398
# Change function name
399
@udf(name='hello_world')
400
def foo(x: int) -> int: ...
401
assert to_sql(foo) == '`hello_world`(`x` BIGINT NOT NULL) ' \
402
'RETURNS BIGINT NOT NULL'
403
404
@udf(name='hello`_`world')
405
def foo(x: int) -> int: ...
406
assert to_sql(foo) == '`hello``_``world`(`x` BIGINT NOT NULL) ' \
407
'RETURNS BIGINT NOT NULL'
408
409
@dataclasses.dataclass
410
class MyData:
411
one: Optional[int]
412
two: str
413
three: float
414
415
with self.assertRaises(TypeError):
416
@udf
417
def foo(x: int) -> MyData: ...
418
to_sql(foo)
419
420
@udf
421
def foo(x: int) -> Table[List[MyData]]: ...
422
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
423
'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
424
'`three` DOUBLE NOT NULL)'
425
426
@udf(returns=MyData)
427
def foo(x: int) -> Table[List[Tuple[int, int, int]]]: ...
428
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
429
'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
430
'`three` DOUBLE NOT NULL)'
431
432
class MyData(pydantic.BaseModel):
433
one: Optional[int]
434
two: str
435
three: float
436
437
@udf
438
def foo(x: int) -> Table[List[MyData]]: ...
439
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
440
'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
441
'`three` DOUBLE NOT NULL)'
442
443
@udf(returns=MyData)
444
def foo(x: int) -> Table[List[Tuple[int, int, int]]]: ...
445
assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \
446
'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \
447
'`three` DOUBLE NOT NULL)'
448
449
def test_dtypes(self):
450
assert dt.BOOL() == 'BOOL NULL'
451
assert dt.BOOL(nullable=False) == 'BOOL NOT NULL'
452
assert dt.BOOL(default=False) == 'BOOL NULL DEFAULT 0'
453
assert dt.BOOL(default=True) == 'BOOL NULL DEFAULT 1'
454
assert dt.BOOL(default='a') == 'BOOL NULL DEFAULT 1'
455
456
assert dt.BOOLEAN() == 'BOOLEAN NULL'
457
assert dt.BOOLEAN(nullable=False) == 'BOOLEAN NOT NULL'
458
assert dt.BOOLEAN(default=False) == 'BOOLEAN NULL DEFAULT 0'
459
assert dt.BOOLEAN(default=True) == 'BOOLEAN NULL DEFAULT 1'
460
assert dt.BOOLEAN(default='a') == 'BOOLEAN NULL DEFAULT 1'
461
462
assert dt.BIT() == 'BIT NULL'
463
assert dt.BIT(nullable=False) == 'BIT NOT NULL'
464
assert dt.BIT(default=100) == 'BIT NULL DEFAULT 100'
465
466
assert dt.TINYINT() == 'TINYINT NULL'
467
assert dt.TINYINT(5) == 'TINYINT(5) NULL'
468
assert dt.TINYINT(nullable=False) == 'TINYINT NOT NULL'
469
assert dt.TINYINT(default=100) == 'TINYINT NULL DEFAULT 100'
470
assert dt.TINYINT(unsigned=True, default=100) == \
471
'TINYINT UNSIGNED NULL DEFAULT 100'
472
473
assert dt.TINYINT_UNSIGNED() == 'TINYINT UNSIGNED NULL'
474
assert dt.TINYINT_UNSIGNED(5) == 'TINYINT(5) UNSIGNED NULL'
475
assert dt.TINYINT_UNSIGNED(nullable=False) == 'TINYINT UNSIGNED NOT NULL'
476
assert dt.TINYINT_UNSIGNED(default=100) == 'TINYINT UNSIGNED NULL DEFAULT 100'
477
478
assert dt.SMALLINT() == 'SMALLINT NULL'
479
assert dt.SMALLINT(5) == 'SMALLINT(5) NULL'
480
assert dt.SMALLINT(nullable=False) == 'SMALLINT NOT NULL'
481
assert dt.SMALLINT(default=100) == 'SMALLINT NULL DEFAULT 100'
482
assert dt.SMALLINT(unsigned=True, default=100) == \
483
'SMALLINT UNSIGNED NULL DEFAULT 100'
484
485
assert dt.SMALLINT_UNSIGNED() == 'SMALLINT UNSIGNED NULL'
486
assert dt.SMALLINT_UNSIGNED(5) == 'SMALLINT(5) UNSIGNED NULL'
487
assert dt.SMALLINT_UNSIGNED(nullable=False) == 'SMALLINT UNSIGNED NOT NULL'
488
assert dt.SMALLINT_UNSIGNED(default=100) == \
489
'SMALLINT UNSIGNED NULL DEFAULT 100'
490
491
assert dt.MEDIUMINT() == 'MEDIUMINT NULL'
492
assert dt.MEDIUMINT(5) == 'MEDIUMINT(5) NULL'
493
assert dt.MEDIUMINT(nullable=False) == 'MEDIUMINT NOT NULL'
494
assert dt.MEDIUMINT(default=100) == 'MEDIUMINT NULL DEFAULT 100'
495
assert dt.MEDIUMINT(unsigned=True, default=100) == \
496
'MEDIUMINT UNSIGNED NULL DEFAULT 100'
497
498
assert dt.MEDIUMINT_UNSIGNED() == 'MEDIUMINT UNSIGNED NULL'
499
assert dt.MEDIUMINT_UNSIGNED(5) == 'MEDIUMINT(5) UNSIGNED NULL'
500
assert dt.MEDIUMINT_UNSIGNED(nullable=False) == 'MEDIUMINT UNSIGNED NOT NULL'
501
assert dt.MEDIUMINT_UNSIGNED(default=100) == \
502
'MEDIUMINT UNSIGNED NULL DEFAULT 100'
503
504
assert dt.INT() == 'INT NULL'
505
assert dt.INT(5) == 'INT(5) NULL'
506
assert dt.INT(nullable=False) == 'INT NOT NULL'
507
assert dt.INT(default=100) == 'INT NULL DEFAULT 100'
508
assert dt.INT(unsigned=True, default=100) == \
509
'INT UNSIGNED NULL DEFAULT 100'
510
511
assert dt.INT_UNSIGNED() == 'INT UNSIGNED NULL'
512
assert dt.INT_UNSIGNED(5) == 'INT(5) UNSIGNED NULL'
513
assert dt.INT_UNSIGNED(nullable=False) == 'INT UNSIGNED NOT NULL'
514
assert dt.INT_UNSIGNED(default=100) == \
515
'INT UNSIGNED NULL DEFAULT 100'
516
517
assert dt.INTEGER() == 'INTEGER NULL'
518
assert dt.INTEGER(5) == 'INTEGER(5) NULL'
519
assert dt.INTEGER(nullable=False) == 'INTEGER NOT NULL'
520
assert dt.INTEGER(default=100) == 'INTEGER NULL DEFAULT 100'
521
assert dt.INTEGER(unsigned=True, default=100) == \
522
'INTEGER UNSIGNED NULL DEFAULT 100'
523
524
assert dt.INTEGER_UNSIGNED() == 'INTEGER UNSIGNED NULL'
525
assert dt.INTEGER_UNSIGNED(5) == 'INTEGER(5) UNSIGNED NULL'
526
assert dt.INTEGER_UNSIGNED(nullable=False) == 'INTEGER UNSIGNED NOT NULL'
527
assert dt.INTEGER_UNSIGNED(default=100) == \
528
'INTEGER UNSIGNED NULL DEFAULT 100'
529
530
assert dt.BIGINT() == 'BIGINT NULL'
531
assert dt.BIGINT(5) == 'BIGINT(5) NULL'
532
assert dt.BIGINT(nullable=False) == 'BIGINT NOT NULL'
533
assert dt.BIGINT(default=100) == 'BIGINT NULL DEFAULT 100'
534
assert dt.BIGINT(unsigned=True, default=100) == \
535
'BIGINT UNSIGNED NULL DEFAULT 100'
536
537
assert dt.BIGINT_UNSIGNED() == 'BIGINT UNSIGNED NULL'
538
assert dt.BIGINT_UNSIGNED(5) == 'BIGINT(5) UNSIGNED NULL'
539
assert dt.BIGINT_UNSIGNED(nullable=False) == 'BIGINT UNSIGNED NOT NULL'
540
assert dt.BIGINT_UNSIGNED(default=100) == \
541
'BIGINT UNSIGNED NULL DEFAULT 100'
542
543
assert dt.BIGINT() == 'BIGINT NULL'
544
assert dt.BIGINT(5) == 'BIGINT(5) NULL'
545
assert dt.BIGINT(nullable=False) == 'BIGINT NOT NULL'
546
assert dt.BIGINT(default=100) == 'BIGINT NULL DEFAULT 100'
547
assert dt.BIGINT(unsigned=True, default=100) == \
548
'BIGINT UNSIGNED NULL DEFAULT 100'
549
550
assert dt.FLOAT() == 'FLOAT NULL'
551
assert dt.FLOAT(5) == 'FLOAT(5) NULL'
552
assert dt.FLOAT(nullable=False) == 'FLOAT NOT NULL'
553
assert dt.FLOAT(default=1.234) == 'FLOAT NULL DEFAULT 1.234e0'
554
555
assert dt.DOUBLE() == 'DOUBLE NULL'
556
assert dt.DOUBLE(5) == 'DOUBLE(5) NULL'
557
assert dt.DOUBLE(nullable=False) == 'DOUBLE NOT NULL'
558
assert dt.DOUBLE(default=1.234) == 'DOUBLE NULL DEFAULT 1.234e0'
559
560
assert dt.REAL() == 'REAL NULL'
561
assert dt.REAL(5) == 'REAL(5) NULL'
562
assert dt.REAL(nullable=False) == 'REAL NOT NULL'
563
assert dt.REAL(default=1.234) == 'REAL NULL DEFAULT 1.234e0'
564
565
with self.assertRaises(TypeError):
566
dt.DECIMAL()
567
with self.assertRaises(TypeError):
568
dt.DECIMAL(5)
569
assert dt.DECIMAL(10, 5) == 'DECIMAL(10, 5) NULL'
570
assert dt.DECIMAL(10, 5, nullable=False) == 'DECIMAL(10, 5) NOT NULL'
571
assert dt.DECIMAL(10, 5, default=1.234) == \
572
'DECIMAL(10, 5) NULL DEFAULT 1.234e0'
573
574
with self.assertRaises(TypeError):
575
dt.DEC()
576
with self.assertRaises(TypeError):
577
dt.DEC(5)
578
assert dt.DEC(10, 5) == 'DEC(10, 5) NULL'
579
assert dt.DEC(10, 5, nullable=False) == 'DEC(10, 5) NOT NULL'
580
assert dt.DEC(10, 5, default=1.234) == \
581
'DEC(10, 5) NULL DEFAULT 1.234e0'
582
583
with self.assertRaises(TypeError):
584
dt.FIXED()
585
with self.assertRaises(TypeError):
586
dt.FIXED(5)
587
assert dt.FIXED(10, 5) == 'FIXED(10, 5) NULL'
588
assert dt.FIXED(10, 5, nullable=False) == 'FIXED(10, 5) NOT NULL'
589
assert dt.FIXED(10, 5, default=1.234) == \
590
'FIXED(10, 5) NULL DEFAULT 1.234e0'
591
592
with self.assertRaises(TypeError):
593
dt.NUMERIC()
594
with self.assertRaises(TypeError):
595
dt.NUMERIC(5)
596
assert dt.NUMERIC(10, 5) == 'NUMERIC(10, 5) NULL'
597
assert dt.NUMERIC(10, 5, nullable=False) == 'NUMERIC(10, 5) NOT NULL'
598
assert dt.NUMERIC(10, 5, default=1.234) == \
599
'NUMERIC(10, 5) NULL DEFAULT 1.234e0'
600
601
assert dt.DATE() == 'DATE NULL'
602
assert dt.DATE(nullable=False) == 'DATE NOT NULL'
603
assert dt.DATE(default=datetime.date(2020, 1, 2)) == \
604
"DATE NULL DEFAULT '2020-01-02'"
605
606
assert dt.TIME() == 'TIME NULL'
607
assert dt.TIME(6) == 'TIME(6) NULL'
608
assert dt.TIME(nullable=False) == 'TIME NOT NULL'
609
assert dt.TIME(default=datetime.timedelta(seconds=1000)) == \
610
"TIME NULL DEFAULT '00:16:40'"
611
612
assert dt.DATETIME() == 'DATETIME NULL'
613
assert dt.DATETIME(6) == 'DATETIME(6) NULL'
614
assert dt.DATETIME(nullable=False) == 'DATETIME NOT NULL'
615
assert dt.DATETIME(default=datetime.datetime(2020, 1, 2, 3, 4, 5)) == \
616
"DATETIME NULL DEFAULT '2020-01-02 03:04:05'"
617
618
assert dt.TIMESTAMP() == 'TIMESTAMP NULL'
619
assert dt.TIMESTAMP(6) == 'TIMESTAMP(6) NULL'
620
assert dt.TIMESTAMP(nullable=False) == 'TIMESTAMP NOT NULL'
621
assert dt.TIMESTAMP(default=datetime.datetime(2020, 1, 2, 3, 4, 5)) == \
622
"TIMESTAMP NULL DEFAULT '2020-01-02 03:04:05'"
623
624
assert dt.YEAR() == 'YEAR NULL'
625
assert dt.YEAR(nullable=False) == 'YEAR NOT NULL'
626
assert dt.YEAR(default=1961) == 'YEAR NULL DEFAULT 1961'
627
628
assert dt.CHAR() == 'CHAR NULL'
629
assert dt.CHAR(10) == 'CHAR(10) NULL'
630
assert dt.CHAR(charset=dt.utf8, collate=dt.utf8_bin) == \
631
'CHAR CHARACTER SET utf8 COLLATE utf8_bin NULL'
632
assert dt.CHAR(nullable=False) == 'CHAR NOT NULL'
633
assert dt.CHAR(default='hi') == "CHAR NULL DEFAULT 'hi'"
634
635
assert dt.VARCHAR() == 'VARCHAR NULL'
636
assert dt.VARCHAR(10) == 'VARCHAR(10) NULL'
637
assert dt.VARCHAR(charset=dt.utf8, collate=dt.utf8_bin) == \
638
'VARCHAR CHARACTER SET utf8 COLLATE utf8_bin NULL'
639
assert dt.VARCHAR(nullable=False) == 'VARCHAR NOT NULL'
640
assert dt.VARCHAR(default='hi') == "VARCHAR NULL DEFAULT 'hi'"
641
642
assert dt.LONGTEXT() == 'LONGTEXT NULL'
643
assert dt.LONGTEXT(10) == 'LONGTEXT(10) NULL'
644
assert dt.LONGTEXT(charset=dt.utf8, collate=dt.utf8_bin) == \
645
'LONGTEXT CHARACTER SET utf8 COLLATE utf8_bin NULL'
646
assert dt.LONGTEXT(nullable=False) == 'LONGTEXT NOT NULL'
647
assert dt.LONGTEXT(default='hi') == "LONGTEXT NULL DEFAULT 'hi'"
648
649
assert dt.MEDIUMTEXT() == 'MEDIUMTEXT NULL'
650
assert dt.MEDIUMTEXT(10) == 'MEDIUMTEXT(10) NULL'
651
assert dt.MEDIUMTEXT(charset=dt.utf8, collate=dt.utf8_bin) == \
652
'MEDIUMTEXT CHARACTER SET utf8 COLLATE utf8_bin NULL'
653
assert dt.MEDIUMTEXT(nullable=False) == 'MEDIUMTEXT NOT NULL'
654
assert dt.MEDIUMTEXT(default='hi') == "MEDIUMTEXT NULL DEFAULT 'hi'"
655
656
assert dt.TEXT() == 'TEXT NULL'
657
assert dt.TEXT(10) == 'TEXT(10) NULL'
658
assert dt.TEXT(charset=dt.utf8, collate=dt.utf8_bin) == \
659
'TEXT CHARACTER SET utf8 COLLATE utf8_bin NULL'
660
assert dt.TEXT(nullable=False) == 'TEXT NOT NULL'
661
assert dt.TEXT(default='hi') == "TEXT NULL DEFAULT 'hi'"
662
663
assert dt.TINYTEXT() == 'TINYTEXT NULL'
664
assert dt.TINYTEXT(10) == 'TINYTEXT(10) NULL'
665
assert dt.TINYTEXT(charset=dt.utf8, collate=dt.utf8_bin) == \
666
'TINYTEXT CHARACTER SET utf8 COLLATE utf8_bin NULL'
667
assert dt.TINYTEXT(nullable=False) == 'TINYTEXT NOT NULL'
668
assert dt.TINYTEXT(default='hi') == "TINYTEXT NULL DEFAULT 'hi'"
669
670
assert dt.BINARY() == 'BINARY NULL'
671
assert dt.BINARY(10) == 'BINARY(10) NULL'
672
assert dt.BINARY(collate=dt.utf8_bin) == \
673
'BINARY COLLATE utf8_bin NULL'
674
assert dt.BINARY(nullable=False) == 'BINARY NOT NULL'
675
assert dt.BINARY(default='hi') == "BINARY NULL DEFAULT 'hi'"
676
677
assert dt.VARBINARY() == 'VARBINARY NULL'
678
assert dt.VARBINARY(10) == 'VARBINARY(10) NULL'
679
assert dt.VARBINARY(collate=dt.utf8_bin) == \
680
'VARBINARY COLLATE utf8_bin NULL'
681
assert dt.VARBINARY(nullable=False) == 'VARBINARY NOT NULL'
682
assert dt.VARBINARY(default='hi') == "VARBINARY NULL DEFAULT 'hi'"
683
684
assert dt.BLOB() == 'BLOB NULL'
685
assert dt.BLOB(10) == 'BLOB(10) NULL'
686
assert dt.BLOB(collate=dt.utf8_bin) == \
687
'BLOB COLLATE utf8_bin NULL'
688
assert dt.BLOB(nullable=False) == 'BLOB NOT NULL'
689
assert dt.BLOB(default='hi') == "BLOB NULL DEFAULT 'hi'"
690
691
assert dt.TINYBLOB() == 'TINYBLOB NULL'
692
assert dt.TINYBLOB(10) == 'TINYBLOB(10) NULL'
693
assert dt.TINYBLOB(collate=dt.utf8_bin) == \
694
'TINYBLOB COLLATE utf8_bin NULL'
695
assert dt.TINYBLOB(nullable=False) == 'TINYBLOB NOT NULL'
696
assert dt.TINYBLOB(default='hi') == "TINYBLOB NULL DEFAULT 'hi'"
697
698
assert dt.JSON() == 'JSON NULL'
699
assert dt.JSON(10) == 'JSON(10) NULL'
700
assert dt.JSON(charset=dt.utf8, collate=dt.utf8_bin) == \
701
'JSON CHARACTER SET utf8 COLLATE utf8_bin NULL'
702
assert dt.JSON(nullable=False) == 'JSON NOT NULL'
703
assert dt.JSON(default='hi') == "JSON NULL DEFAULT 'hi'"
704
705
assert dt.GEOGRAPHYPOINT() == 'GEOGRAPHYPOINT NULL'
706
assert dt.GEOGRAPHYPOINT(nullable=False) == 'GEOGRAPHYPOINT NOT NULL'
707
assert dt.GEOGRAPHYPOINT(default='hi') == "GEOGRAPHYPOINT NULL DEFAULT 'hi'"
708
709
assert dt.GEOGRAPHY() == 'GEOGRAPHY NULL'
710
assert dt.GEOGRAPHY(nullable=False) == 'GEOGRAPHY NOT NULL'
711
assert dt.GEOGRAPHY(default='hi') == "GEOGRAPHY NULL DEFAULT 'hi'"
712
713
# with self.assertRaises(AssertionError):
714
# dt.RECORD()
715
# assert dt.RECORD(('a', dt.INT), ('b', dt.FLOAT)) == \
716
# 'RECORD(`a` INT NULL, `b` FLOAT NULL) NULL'
717
# assert dt.RECORD(('a', dt.INT), ('b', dt.FLOAT), nullable=False) == \
718
# 'RECORD(`a` INT NULL, `b` FLOAT NULL) NOT NULL'
719
720
# assert dt.ARRAY(dt.INT) == 'ARRAY(INT NULL) NULL'
721
# assert dt.ARRAY(dt.INT, nullable=False) == 'ARRAY(INT NULL) NOT NULL'
722
723
# assert dt.VECTOR(8) == 'VECTOR(8, F32) NULL'
724
# assert dt.VECTOR(8, dt.F32) == 'VECTOR(8, F32) NULL'
725
# assert dt.VECTOR(8, dt.F64) == 'VECTOR(8, F64) NULL'
726
# assert dt.VECTOR(8, dt.I8) == 'VECTOR(8, I8) NULL'
727
# assert dt.VECTOR(8, dt.I16) == 'VECTOR(8, I16) NULL'
728
# assert dt.VECTOR(8, dt.I32) == 'VECTOR(8, I32) NULL'
729
# assert dt.VECTOR(8, dt.I64) == 'VECTOR(8, I64) NULL'
730
731
# assert dt.VECTOR(8, nullable=False) == 'VECTOR(8, F32) NOT NULL'
732
# assert dt.VECTOR(8, dt.F32, nullable=False) == 'VECTOR(8, F32) NOT NULL'
733
# assert dt.VECTOR(8, dt.F64, nullable=False) == 'VECTOR(8, F64) NOT NULL'
734
# assert dt.VECTOR(8, dt.I8, nullable=False) == 'VECTOR(8, I8) NOT NULL'
735
# assert dt.VECTOR(8, dt.I16, nullable=False) == 'VECTOR(8, I16) NOT NULL'
736
# assert dt.VECTOR(8, dt.I32, nullable=False) == 'VECTOR(8, I32) NOT NULL'
737
# assert dt.VECTOR(8, dt.I64, nullable=False) == 'VECTOR(8, I64) NOT NULL'
738
739