Thanks to visit codestin.com
Credit goes to docs.rs

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