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