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}