singlestoredb 1.16.1__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.
Files changed (183) hide show
  1. singlestoredb/__init__.py +75 -0
  2. singlestoredb/ai/__init__.py +2 -0
  3. singlestoredb/ai/chat.py +139 -0
  4. singlestoredb/ai/embeddings.py +128 -0
  5. singlestoredb/alchemy/__init__.py +90 -0
  6. singlestoredb/apps/__init__.py +3 -0
  7. singlestoredb/apps/_cloud_functions.py +90 -0
  8. singlestoredb/apps/_config.py +72 -0
  9. singlestoredb/apps/_connection_info.py +18 -0
  10. singlestoredb/apps/_dashboards.py +47 -0
  11. singlestoredb/apps/_process.py +32 -0
  12. singlestoredb/apps/_python_udfs.py +100 -0
  13. singlestoredb/apps/_stdout_supress.py +30 -0
  14. singlestoredb/apps/_uvicorn_util.py +36 -0
  15. singlestoredb/auth.py +245 -0
  16. singlestoredb/config.py +484 -0
  17. singlestoredb/connection.py +1487 -0
  18. singlestoredb/converters.py +950 -0
  19. singlestoredb/docstring/__init__.py +33 -0
  20. singlestoredb/docstring/attrdoc.py +126 -0
  21. singlestoredb/docstring/common.py +230 -0
  22. singlestoredb/docstring/epydoc.py +267 -0
  23. singlestoredb/docstring/google.py +412 -0
  24. singlestoredb/docstring/numpydoc.py +562 -0
  25. singlestoredb/docstring/parser.py +100 -0
  26. singlestoredb/docstring/py.typed +1 -0
  27. singlestoredb/docstring/rest.py +256 -0
  28. singlestoredb/docstring/tests/__init__.py +1 -0
  29. singlestoredb/docstring/tests/_pydoctor.py +21 -0
  30. singlestoredb/docstring/tests/test_epydoc.py +729 -0
  31. singlestoredb/docstring/tests/test_google.py +1007 -0
  32. singlestoredb/docstring/tests/test_numpydoc.py +1100 -0
  33. singlestoredb/docstring/tests/test_parse_from_object.py +109 -0
  34. singlestoredb/docstring/tests/test_parser.py +248 -0
  35. singlestoredb/docstring/tests/test_rest.py +547 -0
  36. singlestoredb/docstring/tests/test_util.py +70 -0
  37. singlestoredb/docstring/util.py +141 -0
  38. singlestoredb/exceptions.py +120 -0
  39. singlestoredb/functions/__init__.py +16 -0
  40. singlestoredb/functions/decorator.py +201 -0
  41. singlestoredb/functions/dtypes.py +1793 -0
  42. singlestoredb/functions/ext/__init__.py +1 -0
  43. singlestoredb/functions/ext/arrow.py +375 -0
  44. singlestoredb/functions/ext/asgi.py +2133 -0
  45. singlestoredb/functions/ext/json.py +420 -0
  46. singlestoredb/functions/ext/mmap.py +413 -0
  47. singlestoredb/functions/ext/rowdat_1.py +724 -0
  48. singlestoredb/functions/ext/timer.py +89 -0
  49. singlestoredb/functions/ext/utils.py +218 -0
  50. singlestoredb/functions/signature.py +1578 -0
  51. singlestoredb/functions/typing/__init__.py +41 -0
  52. singlestoredb/functions/typing/numpy.py +20 -0
  53. singlestoredb/functions/typing/pandas.py +2 -0
  54. singlestoredb/functions/typing/polars.py +2 -0
  55. singlestoredb/functions/typing/pyarrow.py +2 -0
  56. singlestoredb/functions/utils.py +421 -0
  57. singlestoredb/fusion/__init__.py +11 -0
  58. singlestoredb/fusion/graphql.py +213 -0
  59. singlestoredb/fusion/handler.py +916 -0
  60. singlestoredb/fusion/handlers/__init__.py +0 -0
  61. singlestoredb/fusion/handlers/export.py +525 -0
  62. singlestoredb/fusion/handlers/files.py +690 -0
  63. singlestoredb/fusion/handlers/job.py +660 -0
  64. singlestoredb/fusion/handlers/models.py +250 -0
  65. singlestoredb/fusion/handlers/stage.py +502 -0
  66. singlestoredb/fusion/handlers/utils.py +324 -0
  67. singlestoredb/fusion/handlers/workspace.py +956 -0
  68. singlestoredb/fusion/registry.py +249 -0
  69. singlestoredb/fusion/result.py +399 -0
  70. singlestoredb/http/__init__.py +27 -0
  71. singlestoredb/http/connection.py +1267 -0
  72. singlestoredb/magics/__init__.py +34 -0
  73. singlestoredb/magics/run_personal.py +137 -0
  74. singlestoredb/magics/run_shared.py +134 -0
  75. singlestoredb/management/__init__.py +9 -0
  76. singlestoredb/management/billing_usage.py +148 -0
  77. singlestoredb/management/cluster.py +462 -0
  78. singlestoredb/management/export.py +295 -0
  79. singlestoredb/management/files.py +1102 -0
  80. singlestoredb/management/inference_api.py +105 -0
  81. singlestoredb/management/job.py +887 -0
  82. singlestoredb/management/manager.py +373 -0
  83. singlestoredb/management/organization.py +226 -0
  84. singlestoredb/management/region.py +169 -0
  85. singlestoredb/management/utils.py +423 -0
  86. singlestoredb/management/workspace.py +1927 -0
  87. singlestoredb/mysql/__init__.py +177 -0
  88. singlestoredb/mysql/_auth.py +298 -0
  89. singlestoredb/mysql/charset.py +214 -0
  90. singlestoredb/mysql/connection.py +2032 -0
  91. singlestoredb/mysql/constants/CLIENT.py +38 -0
  92. singlestoredb/mysql/constants/COMMAND.py +32 -0
  93. singlestoredb/mysql/constants/CR.py +78 -0
  94. singlestoredb/mysql/constants/ER.py +474 -0
  95. singlestoredb/mysql/constants/EXTENDED_TYPE.py +3 -0
  96. singlestoredb/mysql/constants/FIELD_TYPE.py +48 -0
  97. singlestoredb/mysql/constants/FLAG.py +15 -0
  98. singlestoredb/mysql/constants/SERVER_STATUS.py +10 -0
  99. singlestoredb/mysql/constants/VECTOR_TYPE.py +6 -0
  100. singlestoredb/mysql/constants/__init__.py +0 -0
  101. singlestoredb/mysql/converters.py +271 -0
  102. singlestoredb/mysql/cursors.py +896 -0
  103. singlestoredb/mysql/err.py +92 -0
  104. singlestoredb/mysql/optionfile.py +20 -0
  105. singlestoredb/mysql/protocol.py +450 -0
  106. singlestoredb/mysql/tests/__init__.py +19 -0
  107. singlestoredb/mysql/tests/base.py +126 -0
  108. singlestoredb/mysql/tests/conftest.py +37 -0
  109. singlestoredb/mysql/tests/test_DictCursor.py +132 -0
  110. singlestoredb/mysql/tests/test_SSCursor.py +141 -0
  111. singlestoredb/mysql/tests/test_basic.py +452 -0
  112. singlestoredb/mysql/tests/test_connection.py +851 -0
  113. singlestoredb/mysql/tests/test_converters.py +58 -0
  114. singlestoredb/mysql/tests/test_cursor.py +141 -0
  115. singlestoredb/mysql/tests/test_err.py +16 -0
  116. singlestoredb/mysql/tests/test_issues.py +514 -0
  117. singlestoredb/mysql/tests/test_load_local.py +75 -0
  118. singlestoredb/mysql/tests/test_nextset.py +88 -0
  119. singlestoredb/mysql/tests/test_optionfile.py +27 -0
  120. singlestoredb/mysql/tests/thirdparty/__init__.py +6 -0
  121. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +9 -0
  122. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/capabilities.py +323 -0
  123. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/dbapi20.py +865 -0
  124. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +110 -0
  125. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +224 -0
  126. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +101 -0
  127. singlestoredb/mysql/times.py +23 -0
  128. singlestoredb/notebook/__init__.py +16 -0
  129. singlestoredb/notebook/_objects.py +213 -0
  130. singlestoredb/notebook/_portal.py +352 -0
  131. singlestoredb/py.typed +0 -0
  132. singlestoredb/pytest.py +352 -0
  133. singlestoredb/server/__init__.py +0 -0
  134. singlestoredb/server/docker.py +452 -0
  135. singlestoredb/server/free_tier.py +267 -0
  136. singlestoredb/tests/__init__.py +0 -0
  137. singlestoredb/tests/alltypes.sql +307 -0
  138. singlestoredb/tests/alltypes_no_nulls.sql +208 -0
  139. singlestoredb/tests/empty.sql +0 -0
  140. singlestoredb/tests/ext_funcs/__init__.py +702 -0
  141. singlestoredb/tests/local_infile.csv +3 -0
  142. singlestoredb/tests/test.ipynb +18 -0
  143. singlestoredb/tests/test.sql +680 -0
  144. singlestoredb/tests/test2.ipynb +18 -0
  145. singlestoredb/tests/test2.sql +1 -0
  146. singlestoredb/tests/test_basics.py +1332 -0
  147. singlestoredb/tests/test_config.py +318 -0
  148. singlestoredb/tests/test_connection.py +3103 -0
  149. singlestoredb/tests/test_dbapi.py +27 -0
  150. singlestoredb/tests/test_exceptions.py +45 -0
  151. singlestoredb/tests/test_ext_func.py +1472 -0
  152. singlestoredb/tests/test_ext_func_data.py +1101 -0
  153. singlestoredb/tests/test_fusion.py +1527 -0
  154. singlestoredb/tests/test_http.py +288 -0
  155. singlestoredb/tests/test_management.py +1599 -0
  156. singlestoredb/tests/test_plugin.py +33 -0
  157. singlestoredb/tests/test_results.py +171 -0
  158. singlestoredb/tests/test_types.py +132 -0
  159. singlestoredb/tests/test_udf.py +737 -0
  160. singlestoredb/tests/test_udf_returns.py +459 -0
  161. singlestoredb/tests/test_vectorstore.py +51 -0
  162. singlestoredb/tests/test_xdict.py +333 -0
  163. singlestoredb/tests/utils.py +141 -0
  164. singlestoredb/types.py +373 -0
  165. singlestoredb/utils/__init__.py +0 -0
  166. singlestoredb/utils/config.py +950 -0
  167. singlestoredb/utils/convert_rows.py +69 -0
  168. singlestoredb/utils/debug.py +13 -0
  169. singlestoredb/utils/dtypes.py +205 -0
  170. singlestoredb/utils/events.py +65 -0
  171. singlestoredb/utils/mogrify.py +151 -0
  172. singlestoredb/utils/results.py +585 -0
  173. singlestoredb/utils/xdict.py +425 -0
  174. singlestoredb/vectorstore.py +192 -0
  175. singlestoredb/warnings.py +5 -0
  176. singlestoredb-1.16.1.dist-info/METADATA +165 -0
  177. singlestoredb-1.16.1.dist-info/RECORD +183 -0
  178. singlestoredb-1.16.1.dist-info/WHEEL +5 -0
  179. singlestoredb-1.16.1.dist-info/entry_points.txt +2 -0
  180. singlestoredb-1.16.1.dist-info/licenses/LICENSE +201 -0
  181. singlestoredb-1.16.1.dist-info/top_level.txt +3 -0
  182. sqlx/__init__.py +4 -0
  183. sqlx/magic.py +113 -0
@@ -0,0 +1,737 @@
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'