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