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}