sqlparser/ast/
data_type.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13#[cfg(not(feature = "std"))]
14use alloc::{boxed::Box, format, string::String, vec::Vec};
15use core::fmt;
16
17#[cfg(feature = "serde")]
18use serde::{Deserialize, Serialize};
19
20#[cfg(feature = "visitor")]
21use sqlparser_derive::{Visit, VisitMut};
22
23use crate::ast::{display_comma_separated, ObjectName, StructField};
24
25use super::value::escape_single_quote_string;
26
27/// SQL data types
28#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
29#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
30#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
31pub enum DataType {
32    /// Fixed-length character type e.g. CHARACTER(10)
33    Character(Option<CharacterLength>),
34    /// Fixed-length char type e.g. CHAR(10)
35    Char(Option<CharacterLength>),
36    /// Character varying type e.g. CHARACTER VARYING(10)
37    CharacterVarying(Option<CharacterLength>),
38    /// Char varying type e.g. CHAR VARYING(10)
39    CharVarying(Option<CharacterLength>),
40    /// Variable-length character type e.g. VARCHAR(10)
41    Varchar(Option<CharacterLength>),
42    /// Variable-length character type e.g. NVARCHAR(10)
43    Nvarchar(Option<u64>),
44    /// Uuid type
45    Uuid,
46    /// Large character object with optional length e.g. CHARACTER LARGE OBJECT, CHARACTER LARGE OBJECT(1000), [standard]
47    ///
48    /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-type
49    CharacterLargeObject(Option<u64>),
50    /// Large character object with optional length e.g. CHAR LARGE OBJECT, CHAR LARGE OBJECT(1000), [standard]
51    ///
52    /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-type
53    CharLargeObject(Option<u64>),
54    /// Large character object with optional length e.g. CLOB, CLOB(1000), [standard]
55    ///
56    /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-type
57    /// [Oracle]: https://docs.oracle.com/javadb/10.10.1.2/ref/rrefclob.html
58    Clob(Option<u64>),
59    /// Fixed-length binary type with optional length e.g.  [standard], [MS SQL Server]
60    ///
61    /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-string-type
62    /// [MS SQL Server]: https://learn.microsoft.com/pt-br/sql/t-sql/data-types/binary-and-varbinary-transact-sql?view=sql-server-ver16
63    Binary(Option<u64>),
64    /// Variable-length binary with optional length type e.g. [standard], [MS SQL Server]
65    ///
66    /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-string-type
67    /// [MS SQL Server]: https://learn.microsoft.com/pt-br/sql/t-sql/data-types/binary-and-varbinary-transact-sql?view=sql-server-ver16
68    Varbinary(Option<u64>),
69    /// Large binary object with optional length e.g. BLOB, BLOB(1000), [standard], [Oracle]
70    ///
71    /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-large-object-string-type
72    /// [Oracle]: https://docs.oracle.com/javadb/10.8.3.0/ref/rrefblob.html
73    Blob(Option<u64>),
74    /// Variable-length binary data with optional length.
75    ///
76    /// [bigquery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#bytes_type
77    Bytes(Option<u64>),
78    /// Numeric type with optional precision and scale e.g. NUMERIC(10,2), [standard][1]
79    ///
80    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type
81    Numeric(ExactNumberInfo),
82    /// Decimal type with optional precision and scale e.g. DECIMAL(10,2), [standard][1]
83    ///
84    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type
85    Decimal(ExactNumberInfo),
86    /// [BigNumeric] type used in BigQuery
87    ///
88    /// [BigNumeric]: https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#bignumeric_literals
89    BigNumeric(ExactNumberInfo),
90    /// This is alias for `BigNumeric` type used in BigQuery
91    ///
92    /// [BigDecimal]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#decimal_types
93    BigDecimal(ExactNumberInfo),
94    /// Dec type with optional precision and scale e.g. DEC(10,2), [standard][1]
95    ///
96    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type
97    Dec(ExactNumberInfo),
98    /// Floating point with optional precision e.g. FLOAT(8)
99    Float(Option<u64>),
100    /// Tiny integer with optional display width e.g. TINYINT or TINYINT(3)
101    TinyInt(Option<u64>),
102    /// Unsigned tiny integer with optional display width e.g. TINYINT UNSIGNED or TINYINT(3) UNSIGNED
103    UnsignedTinyInt(Option<u64>),
104    /// Int2 as alias for SmallInt in [postgresql]
105    /// Note: Int2 mean 2 bytes in postgres (not 2 bits)
106    /// Int2 with optional display width e.g. INT2 or INT2(5)
107    ///
108    /// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
109    Int2(Option<u64>),
110    /// Unsigned Int2 with optional display width e.g. INT2 Unsigned or INT2(5) Unsigned
111    UnsignedInt2(Option<u64>),
112    /// Small integer with optional display width e.g. SMALLINT or SMALLINT(5)
113    SmallInt(Option<u64>),
114    /// Unsigned small integer with optional display width e.g. SMALLINT UNSIGNED or SMALLINT(5) UNSIGNED
115    UnsignedSmallInt(Option<u64>),
116    /// MySQL medium integer ([1]) with optional display width e.g. MEDIUMINT or MEDIUMINT(5)
117    ///
118    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/integer-types.html
119    MediumInt(Option<u64>),
120    /// Unsigned medium integer ([1]) with optional display width e.g. MEDIUMINT UNSIGNED or MEDIUMINT(5) UNSIGNED
121    ///
122    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/integer-types.html
123    UnsignedMediumInt(Option<u64>),
124    /// Int with optional display width e.g. INT or INT(11)
125    Int(Option<u64>),
126    /// Int4 as alias for Integer in [postgresql]
127    /// Note: Int4 mean 4 bytes in postgres (not 4 bits)
128    /// Int4 with optional display width e.g. Int4 or Int4(11)
129    ///
130    /// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
131    Int4(Option<u64>),
132    /// Integer type in [bigquery]
133    ///
134    /// [bigquery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#integer_types
135    Int64,
136    /// Integer with optional display width e.g. INTEGER or INTEGER(11)
137    Integer(Option<u64>),
138    /// Unsigned int with optional display width e.g. INT UNSIGNED or INT(11) UNSIGNED
139    UnsignedInt(Option<u64>),
140    /// Unsigned int4 with optional display width e.g. INT4 UNSIGNED or INT4(11) UNSIGNED
141    UnsignedInt4(Option<u64>),
142    /// Unsigned integer with optional display width e.g. INTGER UNSIGNED or INTEGER(11) UNSIGNED
143    UnsignedInteger(Option<u64>),
144    /// Big integer with optional display width e.g. BIGINT or BIGINT(20)
145    BigInt(Option<u64>),
146    /// Unsigned big integer with optional display width e.g. BIGINT UNSIGNED or BIGINT(20) UNSIGNED
147    UnsignedBigInt(Option<u64>),
148    /// Int8 as alias for Bigint in [postgresql]
149    /// Note: Int8 mean 8 bytes in postgres (not 8 bits)
150    /// Int8 with optional display width e.g. INT8 or INT8(11)
151    ///
152    /// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
153    Int8(Option<u64>),
154    /// Unsigned Int8 with optional display width e.g. INT8 UNSIGNED or INT8(11) UNSIGNED
155    UnsignedInt8(Option<u64>),
156    /// Float4 as alias for Real in [postgresql]
157    ///
158    /// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
159    Float4,
160    /// Floating point in [bigquery]
161    ///
162    /// [bigquery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#floating_point_types
163    Float64,
164    /// Floating point e.g. REAL
165    Real,
166    /// Float8 as alias for Double in [postgresql]
167    ///
168    /// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
169    Float8,
170    /// Double
171    Double,
172    /// Double PRECISION e.g. [standard], [postgresql]
173    ///
174    /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#approximate-numeric-type
175    /// [postgresql]: https://www.postgresql.org/docs/current/datatype-numeric.html
176    DoublePrecision,
177    /// Bool as alias for Boolean in [postgresql]
178    ///
179    /// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
180    Bool,
181    /// Boolean
182    Boolean,
183    /// Date
184    Date,
185    /// Time with optional time precision and time zone information e.g. [standard][1].
186    ///
187    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#datetime-type
188    Time(Option<u64>, TimezoneInfo),
189    /// Datetime with optional time precision e.g. [MySQL][1].
190    ///
191    /// [1]: https://dev.mysql.com/doc/refman/8.0/en/datetime.html
192    Datetime(Option<u64>),
193    /// Timestamp with optional time precision and time zone information e.g. [standard][1].
194    ///
195    /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#datetime-type
196    Timestamp(Option<u64>, TimezoneInfo),
197    /// Interval
198    Interval,
199    /// JSON type
200    JSON,
201    /// Binary JSON type
202    JSONB,
203    /// Regclass used in postgresql serial
204    Regclass,
205    /// Text
206    Text,
207    /// String with optional length.
208    String(Option<u64>),
209    /// Bytea
210    Bytea,
211    /// Custom type such as enums
212    Custom(ObjectName, Vec<String>),
213    /// Arrays
214    Array(ArrayElemTypeDef),
215    /// Enums
216    Enum(Vec<String>),
217    /// Set
218    Set(Vec<String>),
219    /// Struct
220    ///
221    /// [hive]: https://docs.cloudera.com/cdw-runtime/cloud/impala-sql-reference/topics/impala-struct.html
222    /// [bigquery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
223    Struct(Vec<StructField>),
224    /// No type specified - only used with
225    /// [`SQLiteDialect`](crate::dialect::SQLiteDialect), from statements such
226    /// as `CREATE TABLE t1 (a)`.
227    Unspecified,
228}
229
230impl fmt::Display for DataType {
231    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
232        match self {
233            DataType::Character(size) => format_character_string_type(f, "CHARACTER", size),
234            DataType::Char(size) => format_character_string_type(f, "CHAR", size),
235            DataType::CharacterVarying(size) => {
236                format_character_string_type(f, "CHARACTER VARYING", size)
237            }
238
239            DataType::CharVarying(size) => format_character_string_type(f, "CHAR VARYING", size),
240            DataType::Varchar(size) => format_character_string_type(f, "VARCHAR", size),
241            DataType::Nvarchar(size) => {
242                format_type_with_optional_length(f, "NVARCHAR", size, false)
243            }
244            DataType::Uuid => write!(f, "UUID"),
245            DataType::CharacterLargeObject(size) => {
246                format_type_with_optional_length(f, "CHARACTER LARGE OBJECT", size, false)
247            }
248            DataType::CharLargeObject(size) => {
249                format_type_with_optional_length(f, "CHAR LARGE OBJECT", size, false)
250            }
251            DataType::Clob(size) => format_type_with_optional_length(f, "CLOB", size, false),
252            DataType::Binary(size) => format_type_with_optional_length(f, "BINARY", size, false),
253            DataType::Varbinary(size) => {
254                format_type_with_optional_length(f, "VARBINARY", size, false)
255            }
256            DataType::Blob(size) => format_type_with_optional_length(f, "BLOB", size, false),
257            DataType::Bytes(size) => format_type_with_optional_length(f, "BYTES", size, false),
258            DataType::Numeric(info) => {
259                write!(f, "NUMERIC{info}")
260            }
261            DataType::Decimal(info) => {
262                write!(f, "DECIMAL{info}")
263            }
264            DataType::Dec(info) => {
265                write!(f, "DEC{info}")
266            }
267            DataType::BigNumeric(info) => write!(f, "BIGNUMERIC{info}"),
268            DataType::BigDecimal(info) => write!(f, "BIGDECIMAL{info}"),
269            DataType::Float(size) => format_type_with_optional_length(f, "FLOAT", size, false),
270            DataType::TinyInt(zerofill) => {
271                format_type_with_optional_length(f, "TINYINT", zerofill, false)
272            }
273            DataType::UnsignedTinyInt(zerofill) => {
274                format_type_with_optional_length(f, "TINYINT", zerofill, true)
275            }
276            DataType::Int2(zerofill) => {
277                format_type_with_optional_length(f, "INT2", zerofill, false)
278            }
279            DataType::UnsignedInt2(zerofill) => {
280                format_type_with_optional_length(f, "INT2", zerofill, true)
281            }
282            DataType::SmallInt(zerofill) => {
283                format_type_with_optional_length(f, "SMALLINT", zerofill, false)
284            }
285            DataType::UnsignedSmallInt(zerofill) => {
286                format_type_with_optional_length(f, "SMALLINT", zerofill, true)
287            }
288            DataType::MediumInt(zerofill) => {
289                format_type_with_optional_length(f, "MEDIUMINT", zerofill, false)
290            }
291            DataType::UnsignedMediumInt(zerofill) => {
292                format_type_with_optional_length(f, "MEDIUMINT", zerofill, true)
293            }
294            DataType::Int(zerofill) => format_type_with_optional_length(f, "INT", zerofill, false),
295            DataType::UnsignedInt(zerofill) => {
296                format_type_with_optional_length(f, "INT", zerofill, true)
297            }
298            DataType::Int4(zerofill) => {
299                format_type_with_optional_length(f, "INT4", zerofill, false)
300            }
301            DataType::Int64 => {
302                write!(f, "INT64")
303            }
304            DataType::UnsignedInt4(zerofill) => {
305                format_type_with_optional_length(f, "INT4", zerofill, true)
306            }
307            DataType::Integer(zerofill) => {
308                format_type_with_optional_length(f, "INTEGER", zerofill, false)
309            }
310            DataType::UnsignedInteger(zerofill) => {
311                format_type_with_optional_length(f, "INTEGER", zerofill, true)
312            }
313            DataType::BigInt(zerofill) => {
314                format_type_with_optional_length(f, "BIGINT", zerofill, false)
315            }
316            DataType::UnsignedBigInt(zerofill) => {
317                format_type_with_optional_length(f, "BIGINT", zerofill, true)
318            }
319            DataType::Int8(zerofill) => {
320                format_type_with_optional_length(f, "INT8", zerofill, false)
321            }
322            DataType::UnsignedInt8(zerofill) => {
323                format_type_with_optional_length(f, "INT8", zerofill, true)
324            }
325            DataType::Real => write!(f, "REAL"),
326            DataType::Float4 => write!(f, "FLOAT4"),
327            DataType::Float64 => write!(f, "FLOAT64"),
328            DataType::Double => write!(f, "DOUBLE"),
329            DataType::Float8 => write!(f, "FLOAT8"),
330            DataType::DoublePrecision => write!(f, "DOUBLE PRECISION"),
331            DataType::Bool => write!(f, "BOOL"),
332            DataType::Boolean => write!(f, "BOOLEAN"),
333            DataType::Date => write!(f, "DATE"),
334            DataType::Time(precision, timezone_info) => {
335                format_datetime_precision_and_tz(f, "TIME", precision, timezone_info)
336            }
337            DataType::Datetime(precision) => {
338                format_type_with_optional_length(f, "DATETIME", precision, false)
339            }
340            DataType::Timestamp(precision, timezone_info) => {
341                format_datetime_precision_and_tz(f, "TIMESTAMP", precision, timezone_info)
342            }
343            DataType::Interval => write!(f, "INTERVAL"),
344            DataType::JSON => write!(f, "JSON"),
345            DataType::JSONB => write!(f, "JSONB"),
346            DataType::Regclass => write!(f, "REGCLASS"),
347            DataType::Text => write!(f, "TEXT"),
348            DataType::String(size) => format_type_with_optional_length(f, "STRING", size, false),
349            DataType::Bytea => write!(f, "BYTEA"),
350            DataType::Array(ty) => match ty {
351                ArrayElemTypeDef::None => write!(f, "ARRAY"),
352                ArrayElemTypeDef::SquareBracket(t) => write!(f, "{t}[]"),
353                ArrayElemTypeDef::AngleBracket(t) => write!(f, "ARRAY<{t}>"),
354            },
355            DataType::Custom(ty, modifiers) => {
356                if modifiers.is_empty() {
357                    write!(f, "{ty}")
358                } else {
359                    write!(f, "{}({})", ty, modifiers.join(", "))
360                }
361            }
362            DataType::Enum(vals) => {
363                write!(f, "ENUM(")?;
364                for (i, v) in vals.iter().enumerate() {
365                    if i != 0 {
366                        write!(f, ", ")?;
367                    }
368                    write!(f, "'{}'", escape_single_quote_string(v))?;
369                }
370                write!(f, ")")
371            }
372            DataType::Set(vals) => {
373                write!(f, "SET(")?;
374                for (i, v) in vals.iter().enumerate() {
375                    if i != 0 {
376                        write!(f, ", ")?;
377                    }
378                    write!(f, "'{}'", escape_single_quote_string(v))?;
379                }
380                write!(f, ")")
381            }
382            DataType::Struct(fields) => {
383                if !fields.is_empty() {
384                    write!(f, "STRUCT<{}>", display_comma_separated(fields))
385                } else {
386                    write!(f, "STRUCT")
387                }
388            }
389            DataType::Unspecified => Ok(()),
390        }
391    }
392}
393
394fn format_type_with_optional_length(
395    f: &mut fmt::Formatter,
396    sql_type: &'static str,
397    len: &Option<u64>,
398    unsigned: bool,
399) -> fmt::Result {
400    write!(f, "{sql_type}")?;
401    if let Some(len) = len {
402        write!(f, "({len})")?;
403    }
404    if unsigned {
405        write!(f, " UNSIGNED")?;
406    }
407    Ok(())
408}
409
410fn format_character_string_type(
411    f: &mut fmt::Formatter,
412    sql_type: &str,
413    size: &Option<CharacterLength>,
414) -> fmt::Result {
415    write!(f, "{sql_type}")?;
416    if let Some(size) = size {
417        write!(f, "({size})")?;
418    }
419    Ok(())
420}
421
422fn format_datetime_precision_and_tz(
423    f: &mut fmt::Formatter,
424    sql_type: &'static str,
425    len: &Option<u64>,
426    time_zone: &TimezoneInfo,
427) -> fmt::Result {
428    write!(f, "{sql_type}")?;
429    let len_fmt = len.as_ref().map(|l| format!("({l})")).unwrap_or_default();
430
431    match time_zone {
432        TimezoneInfo::Tz => {
433            write!(f, "{time_zone}{len_fmt}")?;
434        }
435        _ => {
436            write!(f, "{len_fmt}{time_zone}")?;
437        }
438    }
439
440    Ok(())
441}
442
443/// Timestamp and Time data types information about TimeZone formatting.
444///
445/// This is more related to a display information than real differences between each variant. To
446/// guarantee compatibility with the input query we must maintain its exact information.
447#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
448#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
449#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
450pub enum TimezoneInfo {
451    /// No information about time zone. E.g., TIMESTAMP
452    None,
453    /// Temporal type 'WITH TIME ZONE'. E.g., TIMESTAMP WITH TIME ZONE, [standard], [Oracle]
454    ///
455    /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#datetime-type
456    /// [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
457    WithTimeZone,
458    /// Temporal type 'WITHOUT TIME ZONE'. E.g., TIME WITHOUT TIME ZONE, [standard], [Postgresql]
459    ///
460    /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#datetime-type
461    /// [Postgresql]: https://www.postgresql.org/docs/current/datatype-datetime.html
462    WithoutTimeZone,
463    /// Postgresql specific `WITH TIME ZONE` formatting, for both TIME and TIMESTAMP. E.g., TIMETZ, [Postgresql]
464    ///
465    /// [Postgresql]: https://www.postgresql.org/docs/current/datatype-datetime.html
466    Tz,
467}
468
469impl fmt::Display for TimezoneInfo {
470    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
471        match self {
472            TimezoneInfo::None => {
473                write!(f, "")
474            }
475            TimezoneInfo::WithTimeZone => {
476                write!(f, " WITH TIME ZONE")
477            }
478            TimezoneInfo::WithoutTimeZone => {
479                write!(f, " WITHOUT TIME ZONE")
480            }
481            TimezoneInfo::Tz => {
482                // TZ is the only one that is displayed BEFORE the precision, so the datatype display
483                // must be aware of that. Check <https://www.postgresql.org/docs/14/datatype-datetime.html>
484                // for more information
485                write!(f, "TZ")
486            }
487        }
488    }
489}
490
491/// Additional information for `NUMERIC`, `DECIMAL`, and `DEC` data types
492/// following the 2016 [standard].
493///
494/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type
495#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
496#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
497#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
498pub enum ExactNumberInfo {
499    /// No additional information e.g. `DECIMAL`
500    None,
501    /// Only precision information e.g. `DECIMAL(10)`
502    Precision(u64),
503    /// Precision and scale information e.g. `DECIMAL(10,2)`
504    PrecisionAndScale(u64, u64),
505}
506
507impl fmt::Display for ExactNumberInfo {
508    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
509        match self {
510            ExactNumberInfo::None => {
511                write!(f, "")
512            }
513            ExactNumberInfo::Precision(p) => {
514                write!(f, "({p})")
515            }
516            ExactNumberInfo::PrecisionAndScale(p, s) => {
517                write!(f, "({p},{s})")
518            }
519        }
520    }
521}
522
523/// Information about [character length][1], including length and possibly unit.
524///
525/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-length
526#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
527#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
528#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
529pub enum CharacterLength {
530    IntegerLength {
531        /// Default (if VARYING) or maximum (if not VARYING) length
532        length: u64,
533        /// Optional unit. If not informed, the ANSI handles it as CHARACTERS implicitly
534        unit: Option<CharLengthUnits>,
535    },
536    /// VARCHAR(MAX) or NVARCHAR(MAX), used in T-SQL (Miscrosoft SQL Server)
537    Max,
538}
539
540impl fmt::Display for CharacterLength {
541    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
542        match self {
543            CharacterLength::IntegerLength { length, unit } => {
544                write!(f, "{}", length)?;
545                if let Some(unit) = unit {
546                    write!(f, " {unit}")?;
547                }
548            }
549            CharacterLength::Max => {
550                write!(f, "MAX")?;
551            }
552        }
553        Ok(())
554    }
555}
556
557/// Possible units for characters, initially based on 2016 ANSI [standard][1].
558///
559/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#char-length-units
560#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
561#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
562#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
563pub enum CharLengthUnits {
564    /// CHARACTERS unit
565    Characters,
566    /// OCTETS unit
567    Octets,
568}
569
570impl fmt::Display for CharLengthUnits {
571    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
572        match self {
573            Self::Characters => {
574                write!(f, "CHARACTERS")
575            }
576            Self::Octets => {
577                write!(f, "OCTETS")
578            }
579        }
580    }
581}
582
583/// Represents the data type of the elements in an array (if any) as well as
584/// the syntax used to declare the array.
585///
586/// For example: Bigquery/Hive use `ARRAY<INT>` whereas snowflake uses ARRAY.
587#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
588#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
589#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
590pub enum ArrayElemTypeDef {
591    /// `ARRAY`
592    None,
593    /// `ARRAY<INT>`
594    AngleBracket(Box<DataType>),
595    /// `[]INT`
596    SquareBracket(Box<DataType>),
597}