Path: blob/main/singlestoredb/tests/test_udf.py
801 views
#!/usr/bin/env python1# type: ignore2"""SingleStoreDB UDF testing."""3import dataclasses4import datetime5import re6import unittest7from typing import List8from typing import Optional9from typing import Tuple10from typing import TypeVar11from typing import Union1213import numpy as np14import pydantic1516from ..functions import dtypes as dt17from ..functions import signature as sig18from ..functions import Table19from ..functions import udf202122A = TypeVar('A', bytearray, bytes, None)23B = TypeVar('B', int, float, np.int64, np.int32, np.uint16)24C = TypeVar('C', B, np.int8)25D = TypeVar('D', bound=str)26E = Optional[List[Optional[Union[float, int]]]]272829def to_sql(x):30out = sig.signature_to_sql(sig.get_signature(x))31out = re.sub(r'^CREATE EXTERNAL FUNCTION ', r'', out)32out = re.sub(r' AS REMOTE SERVICE.+$', r'', out)33return out.strip()343536class TestUDF(unittest.TestCase):3738def test_invalid_signature(self):3940def foo(x: np.ndarray, y: np.ndarray) -> str: ...41with self.assertRaises(TypeError):42to_sql(foo)4344def foo(x: str, y: str) -> np.ndarray: ...45with self.assertRaises(TypeError):46to_sql(foo)4748def foo(x: str, y: np.ndarray) -> np.ndarray: ...49with self.assertRaises(TypeError):50to_sql(foo)5152def foo(x: np.ndarray, y: str) -> np.ndarray: ...53with self.assertRaises(TypeError):54to_sql(foo)5556def foo(x: str, y: np.ndarray) -> str: ...57with self.assertRaises(TypeError):58to_sql(foo)5960def foo(x: np.ndarray, y: str) -> str: ...61with self.assertRaises(TypeError):62to_sql(foo)6364def test_return_annotations(self):6566# No annotations67def foo(): ...68with self.assertRaises(TypeError):69to_sql(foo)7071# NULL return value72def foo() -> None: ...73assert to_sql(foo) == '`foo`() RETURNS TINYINT NULL'7475# Simple return value76def foo() -> int: ...77assert to_sql(foo) == '`foo`() RETURNS BIGINT NOT NULL'7879# Simple return value80def foo() -> np.int8: ...81assert to_sql(foo) == '`foo`() RETURNS TINYINT NOT NULL'8283# Optional return value84def foo() -> Optional[int]: ...85assert to_sql(foo) == '`foo`() RETURNS BIGINT NULL'8687# Optional return value88def foo() -> Union[int, None]: ...89assert to_sql(foo) == '`foo`() RETURNS BIGINT NULL'9091# Optional return value with multiple types92def foo() -> Union[int, float, None]: ...93assert to_sql(foo) == '`foo`() RETURNS DOUBLE NULL'9495# Optional return value with custom type96def foo() -> Optional[B]: ...97assert to_sql(foo) == '`foo`() RETURNS DOUBLE NULL'9899# Optional return value with nested custom type100def foo() -> Optional[C]: ...101assert to_sql(foo) == '`foo`() RETURNS DOUBLE NULL'102103# Optional return value with collection type104# def foo() -> Optional[List[str]]: ...105# assert to_sql(foo) == '`foo`() RETURNS ARRAY(TEXT NOT NULL) NULL'106107# Optional return value with nested collection type108# def foo() -> Optional[List[List[str]]]: ...109# assert to_sql(foo) == '`foo`()110# RETURNS ARRAY(ARRAY(TEXT NOT NULL) NOT NULL) NULL'111112# Optional return value with collection type with nulls113# def foo() -> Optional[List[Optional[str]]]: ...114# assert to_sql(foo) == '`foo`() RETURNS ARRAY(TEXT NULL) NULL'115116# Custom type with bound117def foo() -> D: ...118assert to_sql(foo) == '`foo`() RETURNS TEXT NOT NULL'119120# Return value with custom collection type with nulls121# def foo() -> E: ...122# assert to_sql(foo) == '`foo`() RETURNS ARRAY(DOUBLE NULL) NULL'123124# Incompatible types125def foo() -> Union[int, str]: ...126with self.assertRaises(TypeError):127to_sql(foo)128129# Tuple130with self.assertRaises(TypeError):131def foo() -> Tuple[int, float, str]: ...132to_sql(foo)133134# Optional tuple135with self.assertRaises(TypeError):136def foo() -> Optional[Tuple[int, float, str]]: ...137to_sql(foo)138139# Optional tuple with optional element140with self.assertRaises(TypeError):141def foo() -> Optional[Tuple[int, float, Optional[str]]]: ...142to_sql(foo)143144# Optional tuple with optional union element145with self.assertRaises(TypeError):146def foo() -> Optional[Tuple[int, Optional[Union[float, int]], str]]: ...147to_sql(foo)148149# Unknown type150def foo() -> set: ...151with self.assertRaises(TypeError) as exc:152to_sql(foo)153assert 'unsupported type annotation' in str(exc.exception)154155def test_parameter_annotations(self):156157# No annotations158def foo(x) -> None: ...159with self.assertRaises(TypeError):160to_sql(foo)161162# Simple parameter163def foo(x: int) -> None: ...164assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS TINYINT NULL'165166# Optional parameter167def foo(x: Optional[int]) -> None: ...168assert to_sql(foo) == '`foo`(`x` BIGINT NULL) RETURNS TINYINT NULL'169170# Optional parameter171def foo(x: Union[int, None]) -> None: ...172assert to_sql(foo) == '`foo`(`x` BIGINT NULL) RETURNS TINYINT NULL'173174# Optional multiple parameter types175def foo(x: Union[int, float, None]) -> None: ...176assert to_sql(foo) == '`foo`(`x` DOUBLE NULL) RETURNS TINYINT NULL'177178# Optional parameter with custom type179def foo(x: Optional[B]) -> None: ...180assert to_sql(foo) == '`foo`(`x` DOUBLE NULL) RETURNS TINYINT NULL'181182# Optional parameter with nested custom type183def foo(x: Optional[C]) -> None: ...184assert to_sql(foo) == '`foo`(`x` DOUBLE NULL) RETURNS TINYINT NULL'185186# Optional parameter with collection type187# def foo(x: Optional[List[str]]) -> None: ...188# assert to_sql(foo) == '`foo`(`x`189# ARRAY(TEXT NOT NULL) NULL) RETURNS TINYINT NULL'190191# Optional parameter with nested collection type192# def foo(x: Optional[List[List[str]]]) -> None: ...193# assert to_sql(foo) == '`foo`(`x` ARRAY(ARRAY(TEXT NOT NULL) NOT NULL) NULL) ' \194# 'RETURNS TINYINT NULL'195196# Optional parameter with collection type with nulls197# def foo(x: Optional[List[Optional[str]]]) -> None: ...198# assert to_sql(foo) == '`foo`(`x` ARRAY(TEXT NULL) NULL) RETURNS TINYINT NULL'199200# Custom type with bound201def foo(x: D) -> None: ...202assert to_sql(foo) == '`foo`(`x` TEXT NOT NULL) RETURNS TINYINT NULL'203204# Incompatible types205def foo(x: Union[int, str]) -> None: ...206with self.assertRaises(TypeError):207to_sql(foo)208209# Tuple210with self.assertRaises(TypeError):211def foo(x: Tuple[int, float, str]) -> None: ...212to_sql(foo)213214# Optional tuple with optional element215with self.assertRaises(TypeError):216def foo(x: Optional[Tuple[int, float, Optional[str]]]) -> None: ...217to_sql(foo)218219# Optional tuple with optional union element220with self.assertRaises(TypeError):221def foo(222x: Optional[Tuple[int, Optional[Union[float, int]], str]],223) -> None: ...224to_sql(foo)225226# Unknown type227def foo(x: set) -> None: ...228with self.assertRaises(TypeError) as exc:229to_sql(foo)230assert 'unsupported type annotation' in str(exc.exception)231232def test_datetimes(self):233234# Datetime235def foo(x: datetime.datetime) -> None: ...236assert to_sql(foo) == '`foo`(`x` DATETIME NOT NULL) RETURNS TINYINT NULL'237238# Date239def foo(x: datetime.date) -> None: ...240assert to_sql(foo) == '`foo`(`x` DATE NOT NULL) RETURNS TINYINT NULL'241242# Time243def foo(x: datetime.timedelta) -> None: ...244assert to_sql(foo) == '`foo`(`x` TIME NOT NULL) RETURNS TINYINT NULL'245246# Datetime + Date247def foo(x: Union[datetime.datetime, datetime.date]) -> None: ...248with self.assertRaises(TypeError):249to_sql(foo)250251def test_numerics(self):252#253# Bools254#255def foo(x: bool) -> None: ...256assert to_sql(foo) == '`foo`(`x` BOOL NOT NULL) RETURNS TINYINT NULL'257258def foo(x: np.bool_) -> None: ...259assert to_sql(foo) == '`foo`(`x` BOOL NOT NULL) RETURNS TINYINT NULL'260261def foo(x: Optional[bool]) -> None: ...262assert to_sql(foo) == '`foo`(`x` BOOL NULL) RETURNS TINYINT NULL'263264def foo(x: Optional[np.bool_]) -> None: ...265assert to_sql(foo) == '`foo`(`x` BOOL NULL) RETURNS TINYINT NULL'266267# Bool return types268def foo() -> bool: ...269assert to_sql(foo) == '`foo`() RETURNS BOOL NOT NULL'270271def foo() -> np.bool_: ...272assert to_sql(foo) == '`foo`() RETURNS BOOL NOT NULL'273274def foo() -> Optional[bool]: ...275assert to_sql(foo) == '`foo`() RETURNS BOOL NULL'276277# Vector bool (List)278def foo(x: List[bool]) -> List[bool]: ...279assert to_sql(foo) == '`foo`(`x` BOOL NOT NULL) RETURNS BOOL NOT NULL'280281def foo(x: List[np.bool_]) -> List[np.bool_]: ...282assert to_sql(foo) == '`foo`(`x` BOOL NOT NULL) RETURNS BOOL NOT NULL'283284#285# Ints286#287def foo(x: int) -> None: ...288assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS TINYINT NULL'289290def foo(x: np.int8) -> None: ...291assert to_sql(foo) == '`foo`(`x` TINYINT NOT NULL) RETURNS TINYINT NULL'292293def foo(x: np.int16) -> None: ...294assert to_sql(foo) == '`foo`(`x` SMALLINT NOT NULL) RETURNS TINYINT NULL'295296def foo(x: np.int32) -> None: ...297assert to_sql(foo) == '`foo`(`x` INT NOT NULL) RETURNS TINYINT NULL'298299def foo(x: np.int64) -> None: ...300assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS TINYINT NULL'301302#303# Unsigned ints304#305def foo(x: np.uint8) -> None: ...306assert to_sql(foo) == '`foo`(`x` TINYINT UNSIGNED NOT NULL) RETURNS TINYINT NULL'307308def foo(x: np.uint16) -> None: ...309assert to_sql(foo) == '`foo`(`x` SMALLINT UNSIGNED NOT NULL) RETURNS TINYINT NULL'310311def foo(x: np.uint32) -> None: ...312assert to_sql(foo) == '`foo`(`x` INT UNSIGNED NOT NULL) RETURNS TINYINT NULL'313314def foo(x: np.uint64) -> None: ...315assert to_sql(foo) == '`foo`(`x` BIGINT UNSIGNED NOT NULL) RETURNS TINYINT NULL'316317#318# Floats319#320def foo(x: float) -> None: ...321assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'322323def foo(x: np.float16) -> None: ...324assert to_sql(foo) == '`foo`(`x` FLOAT NOT NULL) RETURNS TINYINT NULL'325326def foo(x: np.float32) -> None: ...327assert to_sql(foo) == '`foo`(`x` FLOAT NOT NULL) RETURNS TINYINT NULL'328329def foo(x: np.float64) -> None: ...330assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'331332# Vector float16 (List)333def foo(x: List[np.float16]) -> List[np.float16]: ...334assert to_sql(foo) == '`foo`(`x` FLOAT NOT NULL) RETURNS FLOAT NOT NULL'335336# Vector float32 (List)337def foo(x: List[np.float32]) -> List[np.float32]: ...338assert to_sql(foo) == '`foo`(`x` FLOAT NOT NULL) RETURNS FLOAT NOT NULL'339340# Vector float64 (List)341def foo(x: List[np.float64]) -> List[np.float64]: ...342assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS DOUBLE NOT NULL'343344#345# Type collapsing346#347def foo(x: Union[np.int8, np.int16]) -> None: ...348assert to_sql(foo) == '`foo`(`x` SMALLINT NOT NULL) RETURNS TINYINT NULL'349350def foo(x: Union[np.int64, np.double]) -> None: ...351assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'352353def foo(x: Union[int, float]) -> None: ...354assert to_sql(foo) == '`foo`(`x` DOUBLE NOT NULL) RETURNS TINYINT NULL'355356def test_positional_and_keyword_parameters(self):357# Keyword only358def foo(x: int = 100) -> None: ...359assert to_sql(foo) == \360'`foo`(`x` BIGINT NOT NULL DEFAULT 100) RETURNS TINYINT NULL'361362# Multiple keywords363def foo(x: int = 100, y: float = 3.14) -> None: ...364assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL DEFAULT 100, ' \365'`y` DOUBLE NOT NULL DEFAULT 3.14e0) RETURNS TINYINT NULL'366367# Keywords and positional368def foo(a: str, b: str, x: int = 100, y: float = 3.14) -> None: ...369assert to_sql(foo) == '`foo`(`a` TEXT NOT NULL, ' \370'`b` TEXT NOT NULL, ' \371'`x` BIGINT NOT NULL DEFAULT 100, ' \372'`y` DOUBLE NOT NULL DEFAULT 3.14e0) RETURNS TINYINT NULL'373374# Variable positional375def foo(*args: int) -> None: ...376with self.assertRaises(TypeError):377to_sql(foo)378379# Variable keywords380def foo(x: int = 100, **kwargs: float) -> None: ...381with self.assertRaises(TypeError):382to_sql(foo)383384def test_udf(self):385386# No parameters387@udf388def foo(x: int) -> int: ...389assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS BIGINT NOT NULL'390391# No parameters392@udf()393def foo(x: int) -> int: ...394assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS BIGINT NOT NULL'395396# Override return value with callable397@udf(returns=dt.SMALLINT)398def foo(x: int) -> int: ...399assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS SMALLINT NULL'400401# Override return value with string402@udf(returns=dt.SMALLINT(nullable=False))403def foo(x: int) -> int: ...404assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) RETURNS SMALLINT NOT NULL'405406# Override multiple params with one type407@udf(args=dt.SMALLINT(nullable=False))408def foo(x: int, y: float, z: np.int8) -> int: ...409with self.assertRaises(ValueError):410to_sql(foo)411412# Override with list413@udf(args=[dt.SMALLINT, dt.FLOAT, dt.CHAR(30)])414def foo(x: int, y: float, z: str) -> int: ...415assert to_sql(foo) == '`foo`(`x` SMALLINT NULL, ' \416'`y` FLOAT NULL, ' \417'`z` CHAR(30) NULL) RETURNS BIGINT NOT NULL'418419# Override with too short of a list420@udf(args=[dt.SMALLINT, dt.FLOAT])421def foo(x: int, y: float, z: str) -> int: ...422with self.assertRaises(ValueError):423to_sql(foo)424425# Override with too long of a list426@udf(args=[dt.SMALLINT, dt.FLOAT, dt.CHAR(30), dt.TEXT])427def foo(x: int, y: float, z: str) -> int: ...428with self.assertRaises(ValueError):429to_sql(foo)430431# Override with list432@udf(args=[dt.SMALLINT, dt.FLOAT, dt.CHAR(30)])433def foo(x: int, y: float, z: str) -> int: ...434assert to_sql(foo) == '`foo`(`x` SMALLINT NULL, ' \435'`y` FLOAT NULL, ' \436'`z` CHAR(30) NULL) RETURNS BIGINT NOT NULL'437438# Override with dict439with self.assertRaises(TypeError):440@udf(args=dict(x=dt.SMALLINT, z=dt.CHAR(30)))441def foo(x: int, y: float, z: str) -> int: ...442assert to_sql(foo)443444# Change function name445@udf(name='hello_world')446def foo(x: int) -> int: ...447assert to_sql(foo) == '`hello_world`(`x` BIGINT NOT NULL) ' \448'RETURNS BIGINT NOT NULL'449450@udf(name='hello`_`world')451def foo(x: int) -> int: ...452assert to_sql(foo) == '`hello``_``world`(`x` BIGINT NOT NULL) ' \453'RETURNS BIGINT NOT NULL'454455@dataclasses.dataclass456class MyData:457one: Optional[int]458two: str459three: float460461with self.assertRaises(TypeError):462@udf463def foo(x: int) -> MyData: ...464to_sql(foo)465466@udf467def foo(x: int) -> Table[List[MyData]]: ...468assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \469'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \470'`three` DOUBLE NOT NULL)'471472@udf(returns=MyData)473def foo(x: int) -> Table[List[Tuple[int, int, int]]]: ...474assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \475'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \476'`three` DOUBLE NOT NULL)'477478class MyData(pydantic.BaseModel):479one: Optional[int]480two: str481three: float482483@udf484def foo(x: int) -> Table[List[MyData]]: ...485assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \486'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \487'`three` DOUBLE NOT NULL)'488489@udf(returns=MyData)490def foo(x: int) -> Table[List[Tuple[int, int, int]]]: ...491assert to_sql(foo) == '`foo`(`x` BIGINT NOT NULL) ' \492'RETURNS TABLE(`one` BIGINT NULL, `two` TEXT NOT NULL, ' \493'`three` DOUBLE NOT NULL)'494495def test_dtypes(self):496assert dt.BOOL() == 'BOOL NULL'497assert dt.BOOL(nullable=False) == 'BOOL NOT NULL'498assert dt.BOOL(default=False) == 'BOOL NULL DEFAULT 0'499assert dt.BOOL(default=True) == 'BOOL NULL DEFAULT 1'500assert dt.BOOL(default='a') == 'BOOL NULL DEFAULT 1'501502assert dt.BOOLEAN() == 'BOOLEAN NULL'503assert dt.BOOLEAN(nullable=False) == 'BOOLEAN NOT NULL'504assert dt.BOOLEAN(default=False) == 'BOOLEAN NULL DEFAULT 0'505assert dt.BOOLEAN(default=True) == 'BOOLEAN NULL DEFAULT 1'506assert dt.BOOLEAN(default='a') == 'BOOLEAN NULL DEFAULT 1'507508assert dt.BIT() == 'BIT NULL'509assert dt.BIT(nullable=False) == 'BIT NOT NULL'510assert dt.BIT(default=100) == 'BIT NULL DEFAULT 100'511512assert dt.TINYINT() == 'TINYINT NULL'513assert dt.TINYINT(5) == 'TINYINT(5) NULL'514assert dt.TINYINT(nullable=False) == 'TINYINT NOT NULL'515assert dt.TINYINT(default=100) == 'TINYINT NULL DEFAULT 100'516assert dt.TINYINT(unsigned=True, default=100) == \517'TINYINT UNSIGNED NULL DEFAULT 100'518519assert dt.TINYINT_UNSIGNED() == 'TINYINT UNSIGNED NULL'520assert dt.TINYINT_UNSIGNED(5) == 'TINYINT(5) UNSIGNED NULL'521assert dt.TINYINT_UNSIGNED(nullable=False) == 'TINYINT UNSIGNED NOT NULL'522assert dt.TINYINT_UNSIGNED(default=100) == 'TINYINT UNSIGNED NULL DEFAULT 100'523524assert dt.SMALLINT() == 'SMALLINT NULL'525assert dt.SMALLINT(5) == 'SMALLINT(5) NULL'526assert dt.SMALLINT(nullable=False) == 'SMALLINT NOT NULL'527assert dt.SMALLINT(default=100) == 'SMALLINT NULL DEFAULT 100'528assert dt.SMALLINT(unsigned=True, default=100) == \529'SMALLINT UNSIGNED NULL DEFAULT 100'530531assert dt.SMALLINT_UNSIGNED() == 'SMALLINT UNSIGNED NULL'532assert dt.SMALLINT_UNSIGNED(5) == 'SMALLINT(5) UNSIGNED NULL'533assert dt.SMALLINT_UNSIGNED(nullable=False) == 'SMALLINT UNSIGNED NOT NULL'534assert dt.SMALLINT_UNSIGNED(default=100) == \535'SMALLINT UNSIGNED NULL DEFAULT 100'536537assert dt.MEDIUMINT() == 'MEDIUMINT NULL'538assert dt.MEDIUMINT(5) == 'MEDIUMINT(5) NULL'539assert dt.MEDIUMINT(nullable=False) == 'MEDIUMINT NOT NULL'540assert dt.MEDIUMINT(default=100) == 'MEDIUMINT NULL DEFAULT 100'541assert dt.MEDIUMINT(unsigned=True, default=100) == \542'MEDIUMINT UNSIGNED NULL DEFAULT 100'543544assert dt.MEDIUMINT_UNSIGNED() == 'MEDIUMINT UNSIGNED NULL'545assert dt.MEDIUMINT_UNSIGNED(5) == 'MEDIUMINT(5) UNSIGNED NULL'546assert dt.MEDIUMINT_UNSIGNED(nullable=False) == 'MEDIUMINT UNSIGNED NOT NULL'547assert dt.MEDIUMINT_UNSIGNED(default=100) == \548'MEDIUMINT UNSIGNED NULL DEFAULT 100'549550assert dt.INT() == 'INT NULL'551assert dt.INT(5) == 'INT(5) NULL'552assert dt.INT(nullable=False) == 'INT NOT NULL'553assert dt.INT(default=100) == 'INT NULL DEFAULT 100'554assert dt.INT(unsigned=True, default=100) == \555'INT UNSIGNED NULL DEFAULT 100'556557assert dt.INT_UNSIGNED() == 'INT UNSIGNED NULL'558assert dt.INT_UNSIGNED(5) == 'INT(5) UNSIGNED NULL'559assert dt.INT_UNSIGNED(nullable=False) == 'INT UNSIGNED NOT NULL'560assert dt.INT_UNSIGNED(default=100) == \561'INT UNSIGNED NULL DEFAULT 100'562563assert dt.INTEGER() == 'INTEGER NULL'564assert dt.INTEGER(5) == 'INTEGER(5) NULL'565assert dt.INTEGER(nullable=False) == 'INTEGER NOT NULL'566assert dt.INTEGER(default=100) == 'INTEGER NULL DEFAULT 100'567assert dt.INTEGER(unsigned=True, default=100) == \568'INTEGER UNSIGNED NULL DEFAULT 100'569570assert dt.INTEGER_UNSIGNED() == 'INTEGER UNSIGNED NULL'571assert dt.INTEGER_UNSIGNED(5) == 'INTEGER(5) UNSIGNED NULL'572assert dt.INTEGER_UNSIGNED(nullable=False) == 'INTEGER UNSIGNED NOT NULL'573assert dt.INTEGER_UNSIGNED(default=100) == \574'INTEGER UNSIGNED NULL DEFAULT 100'575576assert dt.BIGINT() == 'BIGINT NULL'577assert dt.BIGINT(5) == 'BIGINT(5) NULL'578assert dt.BIGINT(nullable=False) == 'BIGINT NOT NULL'579assert dt.BIGINT(default=100) == 'BIGINT NULL DEFAULT 100'580assert dt.BIGINT(unsigned=True, default=100) == \581'BIGINT UNSIGNED NULL DEFAULT 100'582583assert dt.BIGINT_UNSIGNED() == 'BIGINT UNSIGNED NULL'584assert dt.BIGINT_UNSIGNED(5) == 'BIGINT(5) UNSIGNED NULL'585assert dt.BIGINT_UNSIGNED(nullable=False) == 'BIGINT UNSIGNED NOT NULL'586assert dt.BIGINT_UNSIGNED(default=100) == \587'BIGINT UNSIGNED NULL DEFAULT 100'588589assert dt.BIGINT() == 'BIGINT NULL'590assert dt.BIGINT(5) == 'BIGINT(5) NULL'591assert dt.BIGINT(nullable=False) == 'BIGINT NOT NULL'592assert dt.BIGINT(default=100) == 'BIGINT NULL DEFAULT 100'593assert dt.BIGINT(unsigned=True, default=100) == \594'BIGINT UNSIGNED NULL DEFAULT 100'595596assert dt.FLOAT() == 'FLOAT NULL'597assert dt.FLOAT(5) == 'FLOAT(5) NULL'598assert dt.FLOAT(nullable=False) == 'FLOAT NOT NULL'599assert dt.FLOAT(default=1.234) == 'FLOAT NULL DEFAULT 1.234e0'600601assert dt.DOUBLE() == 'DOUBLE NULL'602assert dt.DOUBLE(5) == 'DOUBLE(5) NULL'603assert dt.DOUBLE(nullable=False) == 'DOUBLE NOT NULL'604assert dt.DOUBLE(default=1.234) == 'DOUBLE NULL DEFAULT 1.234e0'605606assert dt.REAL() == 'REAL NULL'607assert dt.REAL(5) == 'REAL(5) NULL'608assert dt.REAL(nullable=False) == 'REAL NOT NULL'609assert dt.REAL(default=1.234) == 'REAL NULL DEFAULT 1.234e0'610611with self.assertRaises(TypeError):612dt.DECIMAL()613with self.assertRaises(TypeError):614dt.DECIMAL(5)615assert dt.DECIMAL(10, 5) == 'DECIMAL(10, 5) NULL'616assert dt.DECIMAL(10, 5, nullable=False) == 'DECIMAL(10, 5) NOT NULL'617assert dt.DECIMAL(10, 5, default=1.234) == \618'DECIMAL(10, 5) NULL DEFAULT 1.234e0'619620with self.assertRaises(TypeError):621dt.DEC()622with self.assertRaises(TypeError):623dt.DEC(5)624assert dt.DEC(10, 5) == 'DEC(10, 5) NULL'625assert dt.DEC(10, 5, nullable=False) == 'DEC(10, 5) NOT NULL'626assert dt.DEC(10, 5, default=1.234) == \627'DEC(10, 5) NULL DEFAULT 1.234e0'628629with self.assertRaises(TypeError):630dt.FIXED()631with self.assertRaises(TypeError):632dt.FIXED(5)633assert dt.FIXED(10, 5) == 'FIXED(10, 5) NULL'634assert dt.FIXED(10, 5, nullable=False) == 'FIXED(10, 5) NOT NULL'635assert dt.FIXED(10, 5, default=1.234) == \636'FIXED(10, 5) NULL DEFAULT 1.234e0'637638with self.assertRaises(TypeError):639dt.NUMERIC()640with self.assertRaises(TypeError):641dt.NUMERIC(5)642assert dt.NUMERIC(10, 5) == 'NUMERIC(10, 5) NULL'643assert dt.NUMERIC(10, 5, nullable=False) == 'NUMERIC(10, 5) NOT NULL'644assert dt.NUMERIC(10, 5, default=1.234) == \645'NUMERIC(10, 5) NULL DEFAULT 1.234e0'646647assert dt.DATE() == 'DATE NULL'648assert dt.DATE(nullable=False) == 'DATE NOT NULL'649assert dt.DATE(default=datetime.date(2020, 1, 2)) == \650"DATE NULL DEFAULT '2020-01-02'"651652assert dt.TIME() == 'TIME NULL'653assert dt.TIME(6) == 'TIME(6) NULL'654assert dt.TIME(nullable=False) == 'TIME NOT NULL'655assert dt.TIME(default=datetime.timedelta(seconds=1000)) == \656"TIME NULL DEFAULT '00:16:40'"657658assert dt.DATETIME() == 'DATETIME NULL'659assert dt.DATETIME(6) == 'DATETIME(6) NULL'660assert dt.DATETIME(nullable=False) == 'DATETIME NOT NULL'661assert dt.DATETIME(default=datetime.datetime(2020, 1, 2, 3, 4, 5)) == \662"DATETIME NULL DEFAULT '2020-01-02 03:04:05'"663664assert dt.TIMESTAMP() == 'TIMESTAMP NULL'665assert dt.TIMESTAMP(6) == 'TIMESTAMP(6) NULL'666assert dt.TIMESTAMP(nullable=False) == 'TIMESTAMP NOT NULL'667assert dt.TIMESTAMP(default=datetime.datetime(2020, 1, 2, 3, 4, 5)) == \668"TIMESTAMP NULL DEFAULT '2020-01-02 03:04:05'"669670assert dt.YEAR() == 'YEAR NULL'671assert dt.YEAR(nullable=False) == 'YEAR NOT NULL'672assert dt.YEAR(default=1961) == 'YEAR NULL DEFAULT 1961'673674assert dt.CHAR() == 'CHAR NULL'675assert dt.CHAR(10) == 'CHAR(10) NULL'676assert dt.CHAR(charset=dt.utf8, collate=dt.utf8_bin) == \677'CHAR CHARACTER SET utf8 COLLATE utf8_bin NULL'678assert dt.CHAR(nullable=False) == 'CHAR NOT NULL'679assert dt.CHAR(default='hi') == "CHAR NULL DEFAULT 'hi'"680681assert dt.VARCHAR() == 'VARCHAR NULL'682assert dt.VARCHAR(10) == 'VARCHAR(10) NULL'683assert dt.VARCHAR(charset=dt.utf8, collate=dt.utf8_bin) == \684'VARCHAR CHARACTER SET utf8 COLLATE utf8_bin NULL'685assert dt.VARCHAR(nullable=False) == 'VARCHAR NOT NULL'686assert dt.VARCHAR(default='hi') == "VARCHAR NULL DEFAULT 'hi'"687688assert dt.LONGTEXT() == 'LONGTEXT NULL'689assert dt.LONGTEXT(10) == 'LONGTEXT(10) NULL'690assert dt.LONGTEXT(charset=dt.utf8, collate=dt.utf8_bin) == \691'LONGTEXT CHARACTER SET utf8 COLLATE utf8_bin NULL'692assert dt.LONGTEXT(nullable=False) == 'LONGTEXT NOT NULL'693assert dt.LONGTEXT(default='hi') == "LONGTEXT NULL DEFAULT 'hi'"694695assert dt.MEDIUMTEXT() == 'MEDIUMTEXT NULL'696assert dt.MEDIUMTEXT(10) == 'MEDIUMTEXT(10) NULL'697assert dt.MEDIUMTEXT(charset=dt.utf8, collate=dt.utf8_bin) == \698'MEDIUMTEXT CHARACTER SET utf8 COLLATE utf8_bin NULL'699assert dt.MEDIUMTEXT(nullable=False) == 'MEDIUMTEXT NOT NULL'700assert dt.MEDIUMTEXT(default='hi') == "MEDIUMTEXT NULL DEFAULT 'hi'"701702assert dt.TEXT() == 'TEXT NULL'703assert dt.TEXT(10) == 'TEXT(10) NULL'704assert dt.TEXT(charset=dt.utf8, collate=dt.utf8_bin) == \705'TEXT CHARACTER SET utf8 COLLATE utf8_bin NULL'706assert dt.TEXT(nullable=False) == 'TEXT NOT NULL'707assert dt.TEXT(default='hi') == "TEXT NULL DEFAULT 'hi'"708709assert dt.TINYTEXT() == 'TINYTEXT NULL'710assert dt.TINYTEXT(10) == 'TINYTEXT(10) NULL'711assert dt.TINYTEXT(charset=dt.utf8, collate=dt.utf8_bin) == \712'TINYTEXT CHARACTER SET utf8 COLLATE utf8_bin NULL'713assert dt.TINYTEXT(nullable=False) == 'TINYTEXT NOT NULL'714assert dt.TINYTEXT(default='hi') == "TINYTEXT NULL DEFAULT 'hi'"715716assert dt.BINARY() == 'BINARY NULL'717assert dt.BINARY(10) == 'BINARY(10) NULL'718assert dt.BINARY(collate=dt.utf8_bin) == \719'BINARY COLLATE utf8_bin NULL'720assert dt.BINARY(nullable=False) == 'BINARY NOT NULL'721assert dt.BINARY(default='hi') == "BINARY NULL DEFAULT 'hi'"722723assert dt.VARBINARY() == 'VARBINARY NULL'724assert dt.VARBINARY(10) == 'VARBINARY(10) NULL'725assert dt.VARBINARY(collate=dt.utf8_bin) == \726'VARBINARY COLLATE utf8_bin NULL'727assert dt.VARBINARY(nullable=False) == 'VARBINARY NOT NULL'728assert dt.VARBINARY(default='hi') == "VARBINARY NULL DEFAULT 'hi'"729730assert dt.BLOB() == 'BLOB NULL'731assert dt.BLOB(10) == 'BLOB(10) NULL'732assert dt.BLOB(collate=dt.utf8_bin) == \733'BLOB COLLATE utf8_bin NULL'734assert dt.BLOB(nullable=False) == 'BLOB NOT NULL'735assert dt.BLOB(default='hi') == "BLOB NULL DEFAULT 'hi'"736737assert dt.TINYBLOB() == 'TINYBLOB NULL'738assert dt.TINYBLOB(10) == 'TINYBLOB(10) NULL'739assert dt.TINYBLOB(collate=dt.utf8_bin) == \740'TINYBLOB COLLATE utf8_bin NULL'741assert dt.TINYBLOB(nullable=False) == 'TINYBLOB NOT NULL'742assert dt.TINYBLOB(default='hi') == "TINYBLOB NULL DEFAULT 'hi'"743744assert dt.JSON() == 'JSON NULL'745assert dt.JSON(10) == 'JSON(10) NULL'746assert dt.JSON(charset=dt.utf8, collate=dt.utf8_bin) == \747'JSON CHARACTER SET utf8 COLLATE utf8_bin NULL'748assert dt.JSON(nullable=False) == 'JSON NOT NULL'749assert dt.JSON(default='hi') == "JSON NULL DEFAULT 'hi'"750751assert dt.GEOGRAPHYPOINT() == 'GEOGRAPHYPOINT NULL'752assert dt.GEOGRAPHYPOINT(nullable=False) == 'GEOGRAPHYPOINT NOT NULL'753assert dt.GEOGRAPHYPOINT(default='hi') == "GEOGRAPHYPOINT NULL DEFAULT 'hi'"754755assert dt.GEOGRAPHY() == 'GEOGRAPHY NULL'756assert dt.GEOGRAPHY(nullable=False) == 'GEOGRAPHY NOT NULL'757assert dt.GEOGRAPHY(default='hi') == "GEOGRAPHY NULL DEFAULT 'hi'"758759# with self.assertRaises(AssertionError):760# dt.RECORD()761# assert dt.RECORD(('a', dt.INT), ('b', dt.FLOAT)) == \762# 'RECORD(`a` INT NULL, `b` FLOAT NULL) NULL'763# assert dt.RECORD(('a', dt.INT), ('b', dt.FLOAT), nullable=False) == \764# 'RECORD(`a` INT NULL, `b` FLOAT NULL) NOT NULL'765766# assert dt.ARRAY(dt.INT) == 'ARRAY(INT NULL) NULL'767# assert dt.ARRAY(dt.INT, nullable=False) == 'ARRAY(INT NULL) NOT NULL'768769# assert dt.VECTOR(8) == 'VECTOR(8, F32) NULL'770# assert dt.VECTOR(8, dt.F32) == 'VECTOR(8, F32) NULL'771# assert dt.VECTOR(8, dt.F64) == 'VECTOR(8, F64) NULL'772# assert dt.VECTOR(8, dt.I8) == 'VECTOR(8, I8) NULL'773# assert dt.VECTOR(8, dt.I16) == 'VECTOR(8, I16) NULL'774# assert dt.VECTOR(8, dt.I32) == 'VECTOR(8, I32) NULL'775# assert dt.VECTOR(8, dt.I64) == 'VECTOR(8, I64) NULL'776777# assert dt.VECTOR(8, nullable=False) == 'VECTOR(8, F32) NOT NULL'778# assert dt.VECTOR(8, dt.F32, nullable=False) == 'VECTOR(8, F32) NOT NULL'779# assert dt.VECTOR(8, dt.F64, nullable=False) == 'VECTOR(8, F64) NOT NULL'780# assert dt.VECTOR(8, dt.I8, nullable=False) == 'VECTOR(8, I8) NOT NULL'781# assert dt.VECTOR(8, dt.I16, nullable=False) == 'VECTOR(8, I16) NOT NULL'782# assert dt.VECTOR(8, dt.I32, nullable=False) == 'VECTOR(8, I32) NOT NULL'783# assert dt.VECTOR(8, dt.I64, nullable=False) == 'VECTOR(8, I64) NOT NULL'784785786