sqltk_parser/ast/data_type.rs
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18#[cfg(not(feature = "std"))]
19use alloc::{boxed::Box, format, string::String, vec::Vec};
20use core::fmt;
21
22#[cfg(feature = "serde")]
23use serde::{Deserialize, Serialize};
24
25#[cfg(feature = "visitor")]
26use sqltk_parser_derive::{Visit, VisitMut};
27
28use crate::ast::{display_comma_separated, Expr, ObjectName, StructField, UnionField};
29
30use super::{value::escape_single_quote_string, ColumnDef};
31
32#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
33#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
34#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
35pub enum EnumMember {
36 Name(String),
37 /// ClickHouse allows to specify an integer value for each enum value.
38 ///
39 /// [clickhouse](https://clickhouse.com/docs/en/sql-reference/data-types/enum)
40 NamedValue(String, Expr),
41}
42
43/// SQL data types
44#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
46#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
47pub enum DataType {
48 /// Fixed-length character type e.g. CHARACTER(10)
49 Character(Option<CharacterLength>),
50 /// Fixed-length char type e.g. CHAR(10)
51 Char(Option<CharacterLength>),
52 /// Character varying type e.g. CHARACTER VARYING(10)
53 CharacterVarying(Option<CharacterLength>),
54 /// Char varying type e.g. CHAR VARYING(10)
55 CharVarying(Option<CharacterLength>),
56 /// Variable-length character type e.g. VARCHAR(10)
57 Varchar(Option<CharacterLength>),
58 /// Variable-length character type e.g. NVARCHAR(10)
59 Nvarchar(Option<CharacterLength>),
60 /// Uuid type
61 Uuid,
62 /// Large character object with optional length e.g. CHARACTER LARGE OBJECT, CHARACTER LARGE OBJECT(1000), [standard]
63 ///
64 /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-type
65 CharacterLargeObject(Option<u64>),
66 /// Large character object with optional length e.g. CHAR LARGE OBJECT, CHAR LARGE OBJECT(1000), [standard]
67 ///
68 /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-type
69 CharLargeObject(Option<u64>),
70 /// Large character object with optional length e.g. CLOB, CLOB(1000), [standard]
71 ///
72 /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-type
73 /// [Oracle]: https://docs.oracle.com/javadb/10.10.1.2/ref/rrefclob.html
74 Clob(Option<u64>),
75 /// Fixed-length binary type with optional length e.g. [standard], [MS SQL Server]
76 ///
77 /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-string-type
78 /// [MS SQL Server]: https://learn.microsoft.com/pt-br/sql/t-sql/data-types/binary-and-varbinary-transact-sql?view=sql-server-ver16
79 Binary(Option<u64>),
80 /// Variable-length binary with optional length type e.g. [standard], [MS SQL Server]
81 ///
82 /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-string-type
83 /// [MS SQL Server]: https://learn.microsoft.com/pt-br/sql/t-sql/data-types/binary-and-varbinary-transact-sql?view=sql-server-ver16
84 Varbinary(Option<u64>),
85 /// Large binary object with optional length e.g. BLOB, BLOB(1000), [standard], [Oracle]
86 ///
87 /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-large-object-string-type
88 /// [Oracle]: https://docs.oracle.com/javadb/10.8.3.0/ref/rrefblob.html
89 Blob(Option<u64>),
90 /// [MySQL] blob with up to 2**8 bytes
91 ///
92 /// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/blob.html
93 TinyBlob,
94 /// [MySQL] blob with up to 2**24 bytes
95 ///
96 /// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/blob.html
97 MediumBlob,
98 /// [MySQL] blob with up to 2**32 bytes
99 ///
100 /// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/blob.html
101 LongBlob,
102 /// Variable-length binary data with optional length.
103 ///
104 /// [bigquery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#bytes_type
105 Bytes(Option<u64>),
106 /// Numeric type with optional precision and scale e.g. NUMERIC(10,2), [standard][1]
107 ///
108 /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type
109 Numeric(ExactNumberInfo),
110 /// Decimal type with optional precision and scale e.g. DECIMAL(10,2), [standard][1]
111 ///
112 /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type
113 Decimal(ExactNumberInfo),
114 /// [BigNumeric] type used in BigQuery
115 ///
116 /// [BigNumeric]: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#bignumeric_literals
117 BigNumeric(ExactNumberInfo),
118 /// This is alias for `BigNumeric` type used in BigQuery
119 ///
120 /// [BigDecimal]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#decimal_types
121 BigDecimal(ExactNumberInfo),
122 /// Dec type with optional precision and scale e.g. DEC(10,2), [standard][1]
123 ///
124 /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type
125 Dec(ExactNumberInfo),
126 /// Floating point with optional precision e.g. FLOAT(8)
127 Float(Option<u64>),
128 /// Tiny integer with optional display width e.g. TINYINT or TINYINT(3)
129 TinyInt(Option<u64>),
130 /// Unsigned tiny integer with optional display width e.g. TINYINT UNSIGNED or TINYINT(3) UNSIGNED
131 UnsignedTinyInt(Option<u64>),
132 /// Int2 as alias for SmallInt in [postgresql]
133 /// Note: Int2 mean 2 bytes in postgres (not 2 bits)
134 /// Int2 with optional display width e.g. INT2 or INT2(5)
135 ///
136 /// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
137 Int2(Option<u64>),
138 /// Unsigned Int2 with optional display width e.g. INT2 Unsigned or INT2(5) Unsigned
139 UnsignedInt2(Option<u64>),
140 /// Small integer with optional display width e.g. SMALLINT or SMALLINT(5)
141 SmallInt(Option<u64>),
142 /// Unsigned small integer with optional display width e.g. SMALLINT UNSIGNED or SMALLINT(5) UNSIGNED
143 UnsignedSmallInt(Option<u64>),
144 /// MySQL medium integer ([1]) with optional display width e.g. MEDIUMINT or MEDIUMINT(5)
145 ///
146 /// [1]: https://dev.mysql.com/doc/refman/8.0/en/integer-types.html
147 MediumInt(Option<u64>),
148 /// Unsigned medium integer ([1]) with optional display width e.g. MEDIUMINT UNSIGNED or MEDIUMINT(5) UNSIGNED
149 ///
150 /// [1]: https://dev.mysql.com/doc/refman/8.0/en/integer-types.html
151 UnsignedMediumInt(Option<u64>),
152 /// Int with optional display width e.g. INT or INT(11)
153 Int(Option<u64>),
154 /// Int4 as alias for Integer in [postgresql]
155 /// Note: Int4 mean 4 bytes in postgres (not 4 bits)
156 /// Int4 with optional display width e.g. Int4 or Int4(11)
157 ///
158 /// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
159 Int4(Option<u64>),
160 /// Int8 as alias for Bigint in [postgresql] and integer type in [clickhouse]
161 /// Note: Int8 mean 8 bytes in [postgresql] (not 8 bits)
162 /// Int8 with optional display width e.g. INT8 or INT8(11)
163 /// Note: Int8 mean 8 bits in [clickhouse]
164 ///
165 /// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
166 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/int-uint
167 Int8(Option<u64>),
168 /// Integer type in [clickhouse]
169 /// Note: Int16 mean 16 bits in [clickhouse]
170 ///
171 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/int-uint
172 Int16,
173 /// Integer type in [clickhouse]
174 /// Note: Int16 mean 32 bits in [clickhouse]
175 ///
176 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/int-uint
177 Int32,
178 /// Integer type in [bigquery], [clickhouse]
179 ///
180 /// [bigquery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#integer_types
181 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/int-uint
182 Int64,
183 /// Integer type in [clickhouse]
184 /// Note: Int128 mean 128 bits in [clickhouse]
185 ///
186 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/int-uint
187 Int128,
188 /// Integer type in [clickhouse]
189 /// Note: Int256 mean 256 bits in [clickhouse]
190 ///
191 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/int-uint
192 Int256,
193 /// Integer with optional display width e.g. INTEGER or INTEGER(11)
194 Integer(Option<u64>),
195 /// Unsigned int with optional display width e.g. INT UNSIGNED or INT(11) UNSIGNED
196 UnsignedInt(Option<u64>),
197 /// Unsigned int4 with optional display width e.g. INT4 UNSIGNED or INT4(11) UNSIGNED
198 UnsignedInt4(Option<u64>),
199 /// Unsigned integer with optional display width e.g. INTEGER UNSIGNED or INTEGER(11) UNSIGNED
200 UnsignedInteger(Option<u64>),
201 /// Unsigned integer type in [clickhouse]
202 /// Note: UInt8 mean 8 bits in [clickhouse]
203 ///
204 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/int-uint
205 UInt8,
206 /// Unsigned integer type in [clickhouse]
207 /// Note: UInt16 mean 16 bits in [clickhouse]
208 ///
209 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/int-uint
210 UInt16,
211 /// Unsigned integer type in [clickhouse]
212 /// Note: UInt32 mean 32 bits in [clickhouse]
213 ///
214 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/int-uint
215 UInt32,
216 /// Unsigned integer type in [clickhouse]
217 /// Note: UInt64 mean 64 bits in [clickhouse]
218 ///
219 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/int-uint
220 UInt64,
221 /// Unsigned integer type in [clickhouse]
222 /// Note: UInt128 mean 128 bits in [clickhouse]
223 ///
224 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/int-uint
225 UInt128,
226 /// Unsigned integer type in [clickhouse]
227 /// Note: UInt256 mean 256 bits in [clickhouse]
228 ///
229 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/int-uint
230 UInt256,
231 /// Big integer with optional display width e.g. BIGINT or BIGINT(20)
232 BigInt(Option<u64>),
233 /// Unsigned big integer with optional display width e.g. BIGINT UNSIGNED or BIGINT(20) UNSIGNED
234 UnsignedBigInt(Option<u64>),
235 /// Unsigned Int8 with optional display width e.g. INT8 UNSIGNED or INT8(11) UNSIGNED
236 UnsignedInt8(Option<u64>),
237 /// Float4 as alias for Real in [postgresql]
238 ///
239 /// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
240 Float4,
241 /// Floating point in [clickhouse]
242 ///
243 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/float
244 Float32,
245 /// Floating point in [bigquery]
246 ///
247 /// [bigquery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#floating_point_types
248 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/float
249 Float64,
250 /// Floating point e.g. REAL
251 Real,
252 /// Float8 as alias for Double in [postgresql]
253 ///
254 /// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
255 Float8,
256 /// Double
257 Double,
258 /// Double PRECISION e.g. [standard], [postgresql]
259 ///
260 /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#approximate-numeric-type
261 /// [postgresql]: https://www.postgresql.org/docs/current/datatype-numeric.html
262 DoublePrecision,
263 /// Bool as alias for Boolean in [postgresql]
264 ///
265 /// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
266 Bool,
267 /// Boolean
268 Boolean,
269 /// Date
270 Date,
271 /// Date32 with the same range as Datetime64
272 ///
273 /// [1]: https://clickhouse.com/docs/en/sql-reference/data-types/date32
274 Date32,
275 /// Time with optional time precision and time zone information e.g. [standard][1].
276 ///
277 /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#datetime-type
278 Time(Option<u64>, TimezoneInfo),
279 /// Datetime with optional time precision e.g. [MySQL][1].
280 ///
281 /// [1]: https://dev.mysql.com/doc/refman/8.0/en/datetime.html
282 Datetime(Option<u64>),
283 /// Datetime with time precision and optional timezone e.g. [ClickHouse][1].
284 ///
285 /// [1]: https://clickhouse.com/docs/en/sql-reference/data-types/datetime64
286 Datetime64(u64, Option<String>),
287 /// Timestamp with optional time precision and time zone information e.g. [standard][1].
288 ///
289 /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#datetime-type
290 Timestamp(Option<u64>, TimezoneInfo),
291 /// Interval
292 Interval,
293 /// JSON type
294 JSON,
295 /// Binary JSON type
296 JSONB,
297 /// Regclass used in postgresql serial
298 Regclass,
299 /// Text
300 Text,
301 /// [MySQL] text with up to 2**8 bytes
302 ///
303 /// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/blob.html
304 TinyText,
305 /// [MySQL] text with up to 2**24 bytes
306 ///
307 /// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/blob.html
308 MediumText,
309 /// [MySQL] text with up to 2**32 bytes
310 ///
311 /// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/blob.html
312 LongText,
313 /// String with optional length.
314 String(Option<u64>),
315 /// A fixed-length string e.g [ClickHouse][1].
316 ///
317 /// [1]: https://clickhouse.com/docs/en/sql-reference/data-types/fixedstring
318 FixedString(u64),
319 /// Bytea
320 Bytea,
321 /// Bit string, e.g. [Postgres], [MySQL], or [MSSQL]
322 ///
323 /// [Postgres]: https://www.postgresql.org/docs/current/datatype-bit.html
324 /// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/bit-type.html
325 /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/data-types/bit-transact-sql?view=sql-server-ver16
326 Bit(Option<u64>),
327 /// Variable-length bit string e.g. [Postgres]
328 ///
329 /// [Postgres]: https://www.postgresql.org/docs/current/datatype-bit.html
330 BitVarying(Option<u64>),
331 /// Custom type such as enums
332 Custom(ObjectName, Vec<String>),
333 /// Arrays
334 Array(ArrayElemTypeDef),
335 /// Map
336 ///
337 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/map
338 Map(Box<DataType>, Box<DataType>),
339 /// Tuple
340 ///
341 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/tuple
342 Tuple(Vec<StructField>),
343 /// Nested
344 ///
345 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/nested-data-structures/nested
346 Nested(Vec<ColumnDef>),
347 /// Enums
348 Enum(Vec<EnumMember>, Option<u8>),
349 /// Set
350 Set(Vec<String>),
351 /// Struct
352 ///
353 /// [hive]: https://docs.cloudera.com/cdw-runtime/cloud/impala-sql-reference/topics/impala-struct.html
354 /// [bigquery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
355 Struct(Vec<StructField>, StructBracketKind),
356 /// Union
357 ///
358 /// [duckdb]: https://duckdb.org/docs/sql/data_types/union.html
359 Union(Vec<UnionField>),
360 /// Nullable - special marker NULL represents in ClickHouse as a data type.
361 ///
362 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/nullable
363 Nullable(Box<DataType>),
364 /// LowCardinality - changes the internal representation of other data types to be dictionary-encoded.
365 ///
366 /// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/lowcardinality
367 LowCardinality(Box<DataType>),
368 /// No type specified - only used with
369 /// [`SQLiteDialect`](crate::dialect::SQLiteDialect), from statements such
370 /// as `CREATE TABLE t1 (a)`.
371 Unspecified,
372 /// Trigger data type, returned by functions associated with triggers
373 ///
374 /// [postgresql]: https://www.postgresql.org/docs/current/plpgsql-trigger.html
375 Trigger,
376}
377
378impl fmt::Display for DataType {
379 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
380 match self {
381 DataType::Character(size) => format_character_string_type(f, "CHARACTER", size),
382 DataType::Char(size) => format_character_string_type(f, "CHAR", size),
383 DataType::CharacterVarying(size) => {
384 format_character_string_type(f, "CHARACTER VARYING", size)
385 }
386
387 DataType::CharVarying(size) => format_character_string_type(f, "CHAR VARYING", size),
388 DataType::Varchar(size) => format_character_string_type(f, "VARCHAR", size),
389 DataType::Nvarchar(size) => format_character_string_type(f, "NVARCHAR", size),
390 DataType::Uuid => write!(f, "UUID"),
391 DataType::CharacterLargeObject(size) => {
392 format_type_with_optional_length(f, "CHARACTER LARGE OBJECT", size, false)
393 }
394 DataType::CharLargeObject(size) => {
395 format_type_with_optional_length(f, "CHAR LARGE OBJECT", size, false)
396 }
397 DataType::Clob(size) => format_type_with_optional_length(f, "CLOB", size, false),
398 DataType::Binary(size) => format_type_with_optional_length(f, "BINARY", size, false),
399 DataType::Varbinary(size) => {
400 format_type_with_optional_length(f, "VARBINARY", size, false)
401 }
402 DataType::Blob(size) => format_type_with_optional_length(f, "BLOB", size, false),
403 DataType::TinyBlob => write!(f, "TINYBLOB"),
404 DataType::MediumBlob => write!(f, "MEDIUMBLOB"),
405 DataType::LongBlob => write!(f, "LONGBLOB"),
406 DataType::Bytes(size) => format_type_with_optional_length(f, "BYTES", size, false),
407 DataType::Numeric(info) => {
408 write!(f, "NUMERIC{info}")
409 }
410 DataType::Decimal(info) => {
411 write!(f, "DECIMAL{info}")
412 }
413 DataType::Dec(info) => {
414 write!(f, "DEC{info}")
415 }
416 DataType::BigNumeric(info) => write!(f, "BIGNUMERIC{info}"),
417 DataType::BigDecimal(info) => write!(f, "BIGDECIMAL{info}"),
418 DataType::Float(size) => format_type_with_optional_length(f, "FLOAT", size, false),
419 DataType::TinyInt(zerofill) => {
420 format_type_with_optional_length(f, "TINYINT", zerofill, false)
421 }
422 DataType::UnsignedTinyInt(zerofill) => {
423 format_type_with_optional_length(f, "TINYINT", zerofill, true)
424 }
425 DataType::Int2(zerofill) => {
426 format_type_with_optional_length(f, "INT2", zerofill, false)
427 }
428 DataType::UnsignedInt2(zerofill) => {
429 format_type_with_optional_length(f, "INT2", zerofill, true)
430 }
431 DataType::SmallInt(zerofill) => {
432 format_type_with_optional_length(f, "SMALLINT", zerofill, false)
433 }
434 DataType::UnsignedSmallInt(zerofill) => {
435 format_type_with_optional_length(f, "SMALLINT", zerofill, true)
436 }
437 DataType::MediumInt(zerofill) => {
438 format_type_with_optional_length(f, "MEDIUMINT", zerofill, false)
439 }
440 DataType::UnsignedMediumInt(zerofill) => {
441 format_type_with_optional_length(f, "MEDIUMINT", zerofill, true)
442 }
443 DataType::Int(zerofill) => format_type_with_optional_length(f, "INT", zerofill, false),
444 DataType::UnsignedInt(zerofill) => {
445 format_type_with_optional_length(f, "INT", zerofill, true)
446 }
447 DataType::Int4(zerofill) => {
448 format_type_with_optional_length(f, "INT4", zerofill, false)
449 }
450 DataType::Int8(zerofill) => {
451 format_type_with_optional_length(f, "INT8", zerofill, false)
452 }
453 DataType::Int16 => {
454 write!(f, "Int16")
455 }
456 DataType::Int32 => {
457 write!(f, "Int32")
458 }
459 DataType::Int64 => {
460 write!(f, "INT64")
461 }
462 DataType::Int128 => {
463 write!(f, "Int128")
464 }
465 DataType::Int256 => {
466 write!(f, "Int256")
467 }
468 DataType::UnsignedInt4(zerofill) => {
469 format_type_with_optional_length(f, "INT4", zerofill, true)
470 }
471 DataType::Integer(zerofill) => {
472 format_type_with_optional_length(f, "INTEGER", zerofill, false)
473 }
474 DataType::UnsignedInteger(zerofill) => {
475 format_type_with_optional_length(f, "INTEGER", zerofill, true)
476 }
477 DataType::BigInt(zerofill) => {
478 format_type_with_optional_length(f, "BIGINT", zerofill, false)
479 }
480 DataType::UnsignedBigInt(zerofill) => {
481 format_type_with_optional_length(f, "BIGINT", zerofill, true)
482 }
483 DataType::UnsignedInt8(zerofill) => {
484 format_type_with_optional_length(f, "INT8", zerofill, true)
485 }
486 DataType::UInt8 => {
487 write!(f, "UInt8")
488 }
489 DataType::UInt16 => {
490 write!(f, "UInt16")
491 }
492 DataType::UInt32 => {
493 write!(f, "UInt32")
494 }
495 DataType::UInt64 => {
496 write!(f, "UInt64")
497 }
498 DataType::UInt128 => {
499 write!(f, "UInt128")
500 }
501 DataType::UInt256 => {
502 write!(f, "UInt256")
503 }
504 DataType::Real => write!(f, "REAL"),
505 DataType::Float4 => write!(f, "FLOAT4"),
506 DataType::Float32 => write!(f, "Float32"),
507 DataType::Float64 => write!(f, "FLOAT64"),
508 DataType::Double => write!(f, "DOUBLE"),
509 DataType::Float8 => write!(f, "FLOAT8"),
510 DataType::DoublePrecision => write!(f, "DOUBLE PRECISION"),
511 DataType::Bool => write!(f, "BOOL"),
512 DataType::Boolean => write!(f, "BOOLEAN"),
513 DataType::Date => write!(f, "DATE"),
514 DataType::Date32 => write!(f, "Date32"),
515 DataType::Time(precision, timezone_info) => {
516 format_datetime_precision_and_tz(f, "TIME", precision, timezone_info)
517 }
518 DataType::Datetime(precision) => {
519 format_type_with_optional_length(f, "DATETIME", precision, false)
520 }
521 DataType::Timestamp(precision, timezone_info) => {
522 format_datetime_precision_and_tz(f, "TIMESTAMP", precision, timezone_info)
523 }
524 DataType::Datetime64(precision, timezone) => {
525 format_clickhouse_datetime_precision_and_timezone(
526 f,
527 "DateTime64",
528 precision,
529 timezone,
530 )
531 }
532 DataType::Interval => write!(f, "INTERVAL"),
533 DataType::JSON => write!(f, "JSON"),
534 DataType::JSONB => write!(f, "JSONB"),
535 DataType::Regclass => write!(f, "REGCLASS"),
536 DataType::Text => write!(f, "TEXT"),
537 DataType::TinyText => write!(f, "TINYTEXT"),
538 DataType::MediumText => write!(f, "MEDIUMTEXT"),
539 DataType::LongText => write!(f, "LONGTEXT"),
540 DataType::String(size) => format_type_with_optional_length(f, "STRING", size, false),
541 DataType::Bytea => write!(f, "BYTEA"),
542 DataType::Bit(size) => format_type_with_optional_length(f, "BIT", size, false),
543 DataType::BitVarying(size) => {
544 format_type_with_optional_length(f, "BIT VARYING", size, false)
545 }
546 DataType::Array(ty) => match ty {
547 ArrayElemTypeDef::None => write!(f, "ARRAY"),
548 ArrayElemTypeDef::SquareBracket(t, None) => write!(f, "{t}[]"),
549 ArrayElemTypeDef::SquareBracket(t, Some(size)) => write!(f, "{t}[{size}]"),
550 ArrayElemTypeDef::AngleBracket(t) => write!(f, "ARRAY<{t}>"),
551 ArrayElemTypeDef::Parenthesis(t) => write!(f, "Array({t})"),
552 },
553 DataType::Custom(ty, modifiers) => {
554 if modifiers.is_empty() {
555 write!(f, "{ty}")
556 } else {
557 write!(f, "{}({})", ty, modifiers.join(", "))
558 }
559 }
560 DataType::Enum(vals, bits) => {
561 match bits {
562 Some(bits) => write!(f, "ENUM{}", bits),
563 None => write!(f, "ENUM"),
564 }?;
565 write!(f, "(")?;
566 for (i, v) in vals.iter().enumerate() {
567 if i != 0 {
568 write!(f, ", ")?;
569 }
570 match v {
571 EnumMember::Name(name) => {
572 write!(f, "'{}'", escape_single_quote_string(name))?
573 }
574 EnumMember::NamedValue(name, value) => {
575 write!(f, "'{}' = {}", escape_single_quote_string(name), value)?
576 }
577 }
578 }
579 write!(f, ")")
580 }
581 DataType::Set(vals) => {
582 write!(f, "SET(")?;
583 for (i, v) in vals.iter().enumerate() {
584 if i != 0 {
585 write!(f, ", ")?;
586 }
587 write!(f, "'{}'", escape_single_quote_string(v))?;
588 }
589 write!(f, ")")
590 }
591 DataType::Struct(fields, bracket) => {
592 if !fields.is_empty() {
593 match bracket {
594 StructBracketKind::Parentheses => {
595 write!(f, "STRUCT({})", display_comma_separated(fields))
596 }
597 StructBracketKind::AngleBrackets => {
598 write!(f, "STRUCT<{}>", display_comma_separated(fields))
599 }
600 }
601 } else {
602 write!(f, "STRUCT")
603 }
604 }
605 DataType::Union(fields) => {
606 write!(f, "UNION({})", display_comma_separated(fields))
607 }
608 // ClickHouse
609 DataType::Nullable(data_type) => {
610 write!(f, "Nullable({})", data_type)
611 }
612 DataType::FixedString(character_length) => {
613 write!(f, "FixedString({})", character_length)
614 }
615 DataType::LowCardinality(data_type) => {
616 write!(f, "LowCardinality({})", data_type)
617 }
618 DataType::Map(key_data_type, value_data_type) => {
619 write!(f, "Map({}, {})", key_data_type, value_data_type)
620 }
621 DataType::Tuple(fields) => {
622 write!(f, "Tuple({})", display_comma_separated(fields))
623 }
624 DataType::Nested(fields) => {
625 write!(f, "Nested({})", display_comma_separated(fields))
626 }
627 DataType::Unspecified => Ok(()),
628 DataType::Trigger => write!(f, "TRIGGER"),
629 }
630 }
631}
632
633fn format_type_with_optional_length(
634 f: &mut fmt::Formatter,
635 sql_type: &'static str,
636 len: &Option<u64>,
637 unsigned: bool,
638) -> fmt::Result {
639 write!(f, "{sql_type}")?;
640 if let Some(len) = len {
641 write!(f, "({len})")?;
642 }
643 if unsigned {
644 write!(f, " UNSIGNED")?;
645 }
646 Ok(())
647}
648
649fn format_character_string_type(
650 f: &mut fmt::Formatter,
651 sql_type: &str,
652 size: &Option<CharacterLength>,
653) -> fmt::Result {
654 write!(f, "{sql_type}")?;
655 if let Some(size) = size {
656 write!(f, "({size})")?;
657 }
658 Ok(())
659}
660
661fn format_datetime_precision_and_tz(
662 f: &mut fmt::Formatter,
663 sql_type: &'static str,
664 len: &Option<u64>,
665 time_zone: &TimezoneInfo,
666) -> fmt::Result {
667 write!(f, "{sql_type}")?;
668 let len_fmt = len.as_ref().map(|l| format!("({l})")).unwrap_or_default();
669
670 match time_zone {
671 TimezoneInfo::Tz => {
672 write!(f, "{time_zone}{len_fmt}")?;
673 }
674 _ => {
675 write!(f, "{len_fmt}{time_zone}")?;
676 }
677 }
678
679 Ok(())
680}
681
682fn format_clickhouse_datetime_precision_and_timezone(
683 f: &mut fmt::Formatter,
684 sql_type: &'static str,
685 len: &u64,
686 time_zone: &Option<String>,
687) -> fmt::Result {
688 write!(f, "{sql_type}({len}")?;
689
690 if let Some(time_zone) = time_zone {
691 write!(f, ", '{time_zone}'")?;
692 }
693
694 write!(f, ")")?;
695
696 Ok(())
697}
698
699/// Type of brackets used for `STRUCT` literals.
700#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
701#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
702#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
703pub enum StructBracketKind {
704 /// Example: `STRUCT(a INT, b STRING)`
705 Parentheses,
706 /// Example: `STRUCT<a INT, b STRING>`
707 AngleBrackets,
708}
709
710/// Timestamp and Time data types information about TimeZone formatting.
711///
712/// This is more related to a display information than real differences between each variant. To
713/// guarantee compatibility with the input query we must maintain its exact information.
714#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
715#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
716#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
717pub enum TimezoneInfo {
718 /// No information about time zone. E.g., TIMESTAMP
719 None,
720 /// Temporal type 'WITH TIME ZONE'. E.g., TIMESTAMP WITH TIME ZONE, [standard], [Oracle]
721 ///
722 /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#datetime-type
723 /// [Oracle]: https://docs.oracle.com/en/database/oracle/oracle-database/12.2/nlspg/datetime-data-types-and-time-zone-support.html#GUID-3F1C388E-C651-43D5-ADBC-1A49E5C2CA05
724 WithTimeZone,
725 /// Temporal type 'WITHOUT TIME ZONE'. E.g., TIME WITHOUT TIME ZONE, [standard], [Postgresql]
726 ///
727 /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#datetime-type
728 /// [Postgresql]: https://www.postgresql.org/docs/current/datatype-datetime.html
729 WithoutTimeZone,
730 /// Postgresql specific `WITH TIME ZONE` formatting, for both TIME and TIMESTAMP. E.g., TIMETZ, [Postgresql]
731 ///
732 /// [Postgresql]: https://www.postgresql.org/docs/current/datatype-datetime.html
733 Tz,
734}
735
736impl fmt::Display for TimezoneInfo {
737 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
738 match self {
739 TimezoneInfo::None => {
740 write!(f, "")
741 }
742 TimezoneInfo::WithTimeZone => {
743 write!(f, " WITH TIME ZONE")
744 }
745 TimezoneInfo::WithoutTimeZone => {
746 write!(f, " WITHOUT TIME ZONE")
747 }
748 TimezoneInfo::Tz => {
749 // TZ is the only one that is displayed BEFORE the precision, so the datatype display
750 // must be aware of that. Check <https://www.postgresql.org/docs/14/datatype-datetime.html>
751 // for more information
752 write!(f, "TZ")
753 }
754 }
755 }
756}
757
758/// Additional information for `NUMERIC`, `DECIMAL`, and `DEC` data types
759/// following the 2016 [standard].
760///
761/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type
762#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
763#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
764#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
765pub enum ExactNumberInfo {
766 /// No additional information e.g. `DECIMAL`
767 None,
768 /// Only precision information e.g. `DECIMAL(10)`
769 Precision(u64),
770 /// Precision and scale information e.g. `DECIMAL(10,2)`
771 PrecisionAndScale(u64, u64),
772}
773
774impl fmt::Display for ExactNumberInfo {
775 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
776 match self {
777 ExactNumberInfo::None => {
778 write!(f, "")
779 }
780 ExactNumberInfo::Precision(p) => {
781 write!(f, "({p})")
782 }
783 ExactNumberInfo::PrecisionAndScale(p, s) => {
784 write!(f, "({p},{s})")
785 }
786 }
787 }
788}
789
790/// Information about [character length][1], including length and possibly unit.
791///
792/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-length
793#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
794#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
795#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
796pub enum CharacterLength {
797 IntegerLength {
798 /// Default (if VARYING) or maximum (if not VARYING) length
799 length: u64,
800 /// Optional unit. If not informed, the ANSI handles it as CHARACTERS implicitly
801 unit: Option<CharLengthUnits>,
802 },
803 /// VARCHAR(MAX) or NVARCHAR(MAX), used in T-SQL (Microsoft SQL Server)
804 Max,
805}
806
807impl fmt::Display for CharacterLength {
808 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
809 match self {
810 CharacterLength::IntegerLength { length, unit } => {
811 write!(f, "{}", length)?;
812 if let Some(unit) = unit {
813 write!(f, " {unit}")?;
814 }
815 }
816 CharacterLength::Max => {
817 write!(f, "MAX")?;
818 }
819 }
820 Ok(())
821 }
822}
823
824/// Possible units for characters, initially based on 2016 ANSI [standard][1].
825///
826/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#char-length-units
827#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
828#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
829#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
830pub enum CharLengthUnits {
831 /// CHARACTERS unit
832 Characters,
833 /// OCTETS unit
834 Octets,
835}
836
837impl fmt::Display for CharLengthUnits {
838 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
839 match self {
840 Self::Characters => {
841 write!(f, "CHARACTERS")
842 }
843 Self::Octets => {
844 write!(f, "OCTETS")
845 }
846 }
847 }
848}
849
850/// Represents the data type of the elements in an array (if any) as well as
851/// the syntax used to declare the array.
852///
853/// For example: Bigquery/Hive use `ARRAY<INT>` whereas snowflake uses ARRAY.
854#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
855#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
856#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
857pub enum ArrayElemTypeDef {
858 /// `ARRAY`
859 None,
860 /// `ARRAY<INT>`
861 AngleBracket(Box<DataType>),
862 /// `INT[]` or `INT[2]`
863 SquareBracket(Box<DataType>, Option<u64>),
864 /// `Array(Int64)`
865 Parenthesis(Box<DataType>),
866}