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}