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