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 used in BigQuery
200    JSON,
201    /// Regclass used in postgresql serial
202    Regclass,
203    /// Text
204    Text,
205    /// String with optional length.
206    String(Option<u64>),
207    /// Bytea
208    Bytea,
209    /// Custom type such as enums
210    Custom(ObjectName, Vec<String>),
211    /// Arrays
212    Array(ArrayElemTypeDef),
213    /// Enums
214    Enum(Vec<String>),
215    /// Set
216    Set(Vec<String>),
217    /// Struct
218    ///
219    /// [hive]: https://docs.cloudera.com/cdw-runtime/cloud/impala-sql-reference/topics/impala-struct.html
220    /// [bigquery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
221    Struct(Vec<StructField>),
222}
223
224impl fmt::Display for DataType {
225    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
226        match self {
227            DataType::Character(size) => format_character_string_type(f, "CHARACTER", size),
228            DataType::Char(size) => format_character_string_type(f, "CHAR", size),
229            DataType::CharacterVarying(size) => {
230                format_character_string_type(f, "CHARACTER VARYING", size)
231            }
232
233            DataType::CharVarying(size) => format_character_string_type(f, "CHAR VARYING", size),
234            DataType::Varchar(size) => format_character_string_type(f, "VARCHAR", size),
235            DataType::Nvarchar(size) => {
236                format_type_with_optional_length(f, "NVARCHAR", size, false)
237            }
238            DataType::Uuid => write!(f, "UUID"),
239            DataType::CharacterLargeObject(size) => {
240                format_type_with_optional_length(f, "CHARACTER LARGE OBJECT", size, false)
241            }
242            DataType::CharLargeObject(size) => {
243                format_type_with_optional_length(f, "CHAR LARGE OBJECT", size, false)
244            }
245            DataType::Clob(size) => format_type_with_optional_length(f, "CLOB", size, false),
246            DataType::Binary(size) => format_type_with_optional_length(f, "BINARY", size, false),
247            DataType::Varbinary(size) => {
248                format_type_with_optional_length(f, "VARBINARY", size, false)
249            }
250            DataType::Blob(size) => format_type_with_optional_length(f, "BLOB", size, false),
251            DataType::Bytes(size) => format_type_with_optional_length(f, "BYTES", size, false),
252            DataType::Numeric(info) => {
253                write!(f, "NUMERIC{info}")
254            }
255            DataType::Decimal(info) => {
256                write!(f, "DECIMAL{info}")
257            }
258            DataType::Dec(info) => {
259                write!(f, "DEC{info}")
260            }
261            DataType::BigNumeric(info) => write!(f, "BIGNUMERIC{info}"),
262            DataType::BigDecimal(info) => write!(f, "BIGDECIMAL{info}"),
263            DataType::Float(size) => format_type_with_optional_length(f, "FLOAT", size, false),
264            DataType::TinyInt(zerofill) => {
265                format_type_with_optional_length(f, "TINYINT", zerofill, false)
266            }
267            DataType::UnsignedTinyInt(zerofill) => {
268                format_type_with_optional_length(f, "TINYINT", zerofill, true)
269            }
270            DataType::Int2(zerofill) => {
271                format_type_with_optional_length(f, "INT2", zerofill, false)
272            }
273            DataType::UnsignedInt2(zerofill) => {
274                format_type_with_optional_length(f, "INT2", zerofill, true)
275            }
276            DataType::SmallInt(zerofill) => {
277                format_type_with_optional_length(f, "SMALLINT", zerofill, false)
278            }
279            DataType::UnsignedSmallInt(zerofill) => {
280                format_type_with_optional_length(f, "SMALLINT", zerofill, true)
281            }
282            DataType::MediumInt(zerofill) => {
283                format_type_with_optional_length(f, "MEDIUMINT", zerofill, false)
284            }
285            DataType::UnsignedMediumInt(zerofill) => {
286                format_type_with_optional_length(f, "MEDIUMINT", zerofill, true)
287            }
288            DataType::Int(zerofill) => format_type_with_optional_length(f, "INT", zerofill, false),
289            DataType::UnsignedInt(zerofill) => {
290                format_type_with_optional_length(f, "INT", zerofill, true)
291            }
292            DataType::Int4(zerofill) => {
293                format_type_with_optional_length(f, "INT4", zerofill, false)
294            }
295            DataType::Int64 => {
296                write!(f, "INT64")
297            }
298            DataType::UnsignedInt4(zerofill) => {
299                format_type_with_optional_length(f, "INT4", zerofill, true)
300            }
301            DataType::Integer(zerofill) => {
302                format_type_with_optional_length(f, "INTEGER", zerofill, false)
303            }
304            DataType::UnsignedInteger(zerofill) => {
305                format_type_with_optional_length(f, "INTEGER", zerofill, true)
306            }
307            DataType::BigInt(zerofill) => {
308                format_type_with_optional_length(f, "BIGINT", zerofill, false)
309            }
310            DataType::UnsignedBigInt(zerofill) => {
311                format_type_with_optional_length(f, "BIGINT", zerofill, true)
312            }
313            DataType::Int8(zerofill) => {
314                format_type_with_optional_length(f, "INT8", zerofill, false)
315            }
316            DataType::UnsignedInt8(zerofill) => {
317                format_type_with_optional_length(f, "INT8", zerofill, true)
318            }
319            DataType::Real => write!(f, "REAL"),
320            DataType::Float4 => write!(f, "FLOAT4"),
321            DataType::Float64 => write!(f, "FLOAT64"),
322            DataType::Double => write!(f, "DOUBLE"),
323            DataType::Float8 => write!(f, "FLOAT8"),
324            DataType::DoublePrecision => write!(f, "DOUBLE PRECISION"),
325            DataType::Bool => write!(f, "BOOL"),
326            DataType::Boolean => write!(f, "BOOLEAN"),
327            DataType::Date => write!(f, "DATE"),
328            DataType::Time(precision, timezone_info) => {
329                format_datetime_precision_and_tz(f, "TIME", precision, timezone_info)
330            }
331            DataType::Datetime(precision) => {
332                format_type_with_optional_length(f, "DATETIME", precision, false)
333            }
334            DataType::Timestamp(precision, timezone_info) => {
335                format_datetime_precision_and_tz(f, "TIMESTAMP", precision, timezone_info)
336            }
337            DataType::Interval => write!(f, "INTERVAL"),
338            DataType::JSON => write!(f, "JSON"),
339            DataType::Regclass => write!(f, "REGCLASS"),
340            DataType::Text => write!(f, "TEXT"),
341            DataType::String(size) => format_type_with_optional_length(f, "STRING", size, false),
342            DataType::Bytea => write!(f, "BYTEA"),
343            DataType::Array(ty) => match ty {
344                ArrayElemTypeDef::None => write!(f, "ARRAY"),
345                ArrayElemTypeDef::SquareBracket(t) => write!(f, "{t}[]"),
346                ArrayElemTypeDef::AngleBracket(t) => write!(f, "ARRAY<{t}>"),
347            },
348            DataType::Custom(ty, modifiers) => {
349                if modifiers.is_empty() {
350                    write!(f, "{ty}")
351                } else {
352                    write!(f, "{}({})", ty, modifiers.join(", "))
353                }
354            }
355            DataType::Enum(vals) => {
356                write!(f, "ENUM(")?;
357                for (i, v) in vals.iter().enumerate() {
358                    if i != 0 {
359                        write!(f, ", ")?;
360                    }
361                    write!(f, "'{}'", escape_single_quote_string(v))?;
362                }
363                write!(f, ")")
364            }
365            DataType::Set(vals) => {
366                write!(f, "SET(")?;
367                for (i, v) in vals.iter().enumerate() {
368                    if i != 0 {
369                        write!(f, ", ")?;
370                    }
371                    write!(f, "'{}'", escape_single_quote_string(v))?;
372                }
373                write!(f, ")")
374            }
375            DataType::Struct(fields) => {
376                if !fields.is_empty() {
377                    write!(f, "STRUCT<{}>", display_comma_separated(fields))
378                } else {
379                    write!(f, "STRUCT")
380                }
381            }
382        }
383    }
384}
385
386fn format_type_with_optional_length(
387    f: &mut fmt::Formatter,
388    sql_type: &'static str,
389    len: &Option<u64>,
390    unsigned: bool,
391) -> fmt::Result {
392    write!(f, "{sql_type}")?;
393    if let Some(len) = len {
394        write!(f, "({len})")?;
395    }
396    if unsigned {
397        write!(f, " UNSIGNED")?;
398    }
399    Ok(())
400}
401
402fn format_character_string_type(
403    f: &mut fmt::Formatter,
404    sql_type: &str,
405    size: &Option<CharacterLength>,
406) -> fmt::Result {
407    write!(f, "{sql_type}")?;
408    if let Some(size) = size {
409        write!(f, "({size})")?;
410    }
411    Ok(())
412}
413
414fn format_datetime_precision_and_tz(
415    f: &mut fmt::Formatter,
416    sql_type: &'static str,
417    len: &Option<u64>,
418    time_zone: &TimezoneInfo,
419) -> fmt::Result {
420    write!(f, "{sql_type}")?;
421    let len_fmt = len.as_ref().map(|l| format!("({l})")).unwrap_or_default();
422
423    match time_zone {
424        TimezoneInfo::Tz => {
425            write!(f, "{time_zone}{len_fmt}")?;
426        }
427        _ => {
428            write!(f, "{len_fmt}{time_zone}")?;
429        }
430    }
431
432    Ok(())
433}
434
435/// Timestamp and Time data types information about TimeZone formatting.
436///
437/// This is more related to a display information than real differences between each variant. To
438/// guarantee compatibility with the input query we must maintain its exact information.
439#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
440#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
441#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
442pub enum TimezoneInfo {
443    /// No information about time zone. E.g., TIMESTAMP
444    None,
445    /// Temporal type 'WITH TIME ZONE'. E.g., TIMESTAMP WITH TIME ZONE, [standard], [Oracle]
446    ///
447    /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#datetime-type
448    /// [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
449    WithTimeZone,
450    /// Temporal type 'WITHOUT TIME ZONE'. E.g., TIME WITHOUT TIME ZONE, [standard], [Postgresql]
451    ///
452    /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#datetime-type
453    /// [Postgresql]: https://www.postgresql.org/docs/current/datatype-datetime.html
454    WithoutTimeZone,
455    /// Postgresql specific `WITH TIME ZONE` formatting, for both TIME and TIMESTAMP. E.g., TIMETZ, [Postgresql]
456    ///
457    /// [Postgresql]: https://www.postgresql.org/docs/current/datatype-datetime.html
458    Tz,
459}
460
461impl fmt::Display for TimezoneInfo {
462    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
463        match self {
464            TimezoneInfo::None => {
465                write!(f, "")
466            }
467            TimezoneInfo::WithTimeZone => {
468                write!(f, " WITH TIME ZONE")
469            }
470            TimezoneInfo::WithoutTimeZone => {
471                write!(f, " WITHOUT TIME ZONE")
472            }
473            TimezoneInfo::Tz => {
474                // TZ is the only one that is displayed BEFORE the precision, so the datatype display
475                // must be aware of that. Check <https://www.postgresql.org/docs/14/datatype-datetime.html>
476                // for more information
477                write!(f, "TZ")
478            }
479        }
480    }
481}
482
483/// Additional information for `NUMERIC`, `DECIMAL`, and `DEC` data types
484/// following the 2016 [standard].
485///
486/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type
487#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
488#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
489#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
490pub enum ExactNumberInfo {
491    /// No additional information e.g. `DECIMAL`
492    None,
493    /// Only precision information e.g. `DECIMAL(10)`
494    Precision(u64),
495    /// Precision and scale information e.g. `DECIMAL(10,2)`
496    PrecisionAndScale(u64, u64),
497}
498
499impl fmt::Display for ExactNumberInfo {
500    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
501        match self {
502            ExactNumberInfo::None => {
503                write!(f, "")
504            }
505            ExactNumberInfo::Precision(p) => {
506                write!(f, "({p})")
507            }
508            ExactNumberInfo::PrecisionAndScale(p, s) => {
509                write!(f, "({p},{s})")
510            }
511        }
512    }
513}
514
515/// Information about [character length][1], including length and possibly unit.
516///
517/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-length
518#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
519#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
520#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
521pub struct CharacterLength {
522    /// Default (if VARYING) or maximum (if not VARYING) length
523    pub length: u64,
524    /// Optional unit. If not informed, the ANSI handles it as CHARACTERS implicitly
525    pub unit: Option<CharLengthUnits>,
526}
527
528impl fmt::Display for CharacterLength {
529    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
530        write!(f, "{}", self.length)?;
531        if let Some(unit) = &self.unit {
532            write!(f, " {unit}")?;
533        }
534        Ok(())
535    }
536}
537
538/// Possible units for characters, initially based on 2016 ANSI [standard][1].
539///
540/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#char-length-units
541#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
542#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
543#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
544pub enum CharLengthUnits {
545    /// CHARACTERS unit
546    Characters,
547    /// OCTETS unit
548    Octets,
549}
550
551impl fmt::Display for CharLengthUnits {
552    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
553        match self {
554            Self::Characters => {
555                write!(f, "CHARACTERS")
556            }
557            Self::Octets => {
558                write!(f, "OCTETS")
559            }
560        }
561    }
562}
563
564/// Represents the data type of the elements in an array (if any) as well as
565/// the syntax used to declare the array.
566///
567/// For example: Bigquery/Hive use `ARRAY<INT>` whereas snowflake uses ARRAY.
568#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
569#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
570#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
571pub enum ArrayElemTypeDef {
572    /// `ARRAY`
573    None,
574    /// `ARRAY<INT>`
575    AngleBracket(Box<DataType>),
576    /// `[]INT`
577    SquareBracket(Box<DataType>),
578}