sqlparser/ast/
mod.rs1// 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//! SQL Abstract Syntax Tree (AST) types
19#[cfg(not(feature = "std"))]
20use alloc::{
21 boxed::Box,
22 format,
23 string::{String, ToString},
24 vec,
25 vec::Vec,
26};
27use helpers::{
28 attached_token::AttachedToken,
29 stmt_data_loading::{FileStagingCommand, StageLoadSelectItemKind},
30};
31
32use core::cmp::Ordering;
33use core::ops::Deref;
34use core::{
35 fmt::{self, Display},
36 hash,
37};
38
39#[cfg(feature = "serde")]
40use serde::{Deserialize, Serialize};
41
42#[cfg(feature = "visitor")]
43use sqlparser_derive::{Visit, VisitMut};
44
45use crate::{
46 display_utils::SpaceOrNewline,
47 tokenizer::{Span, Token},
48};
49use crate::{
50 display_utils::{Indent, NewLine},
51 keywords::Keyword,
52};
53
54pub use self::data_type::{
55 ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
56 ExactNumberInfo, IntervalFields, StructBracketKind, TimezoneInfo,
57};
58pub use self::dcl::{
59 AlterRoleOperation, CreateRole, Grant, ResetConfig, Revoke, RoleOption, SecondaryRoles,
60 SetConfigValue, Use,
61};
62pub use self::ddl::{
63 Alignment, AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterOperator,
64 AlterOperatorClass, AlterOperatorClassOperation, AlterOperatorFamily,
65 AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy, AlterPolicyOperation,
66 AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm, AlterTableLock,
67 AlterTableOperation, AlterTableType, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
68 AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, ClusteredBy, ColumnDef,
69 ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy, ColumnPolicyProperty,
70 ConstraintCharacteristics, CreateConnector, CreateDomain, CreateExtension, CreateFunction,
71 CreateIndex, CreateOperator, CreateOperatorClass, CreateOperatorFamily, CreatePolicy,
72 CreatePolicyCommand, CreatePolicyType, CreateTable, CreateTrigger, CreateView, Deduplicate,
73 DeferrableInitial, DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass,
74 DropOperatorFamily, DropOperatorSignature, DropPolicy, DropTrigger, ForValues, GeneratedAs,
75 GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
76 IdentityPropertyKind, IdentityPropertyOrder, IndexColumn, IndexOption, IndexType,
77 KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes, OperatorClassItem,
78 OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose, Owner, Partition,
79 PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity,
80 TagsColumnOption, TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
81 UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
82 UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef,
83};
84pub use self::dml::{
85 Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
86 MergeInsertKind, MergeUpdateExpr, OutputClause, Update,
87};
88pub use self::operator::{BinaryOperator, UnaryOperator};
89pub use self::query::{
90 AfterMatchSkip, ConnectByKind, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
91 ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, ExprWithAliasAndOrderBy, Fetch, ForClause,
92 ForJson, ForXml, FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias,
93 IlikeSelectItem, InputFormatClause, Interpolate, InterpolateExpr, Join, JoinConstraint,
94 JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn,
95 JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
96 MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
97 OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
98 PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
99 RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
100 SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
101 SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
102 TableAliasColumnDef, TableFactor, TableFunctionArgs, TableIndexHintForClause,
103 TableIndexHintType, TableIndexHints, TableIndexType, TableSample, TableSampleBucket,
104 TableSampleKind, TableSampleMethod, TableSampleModifier, TableSampleQuantity, TableSampleSeed,
105 TableSampleSeedModifier, TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity,
106 UpdateTableFromKind, ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
107 XmlNamespaceDefinition, XmlPassingArgument, XmlPassingClause, XmlTableColumn,
108 XmlTableColumnOption,
109};
110
111pub use self::trigger::{
112 TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
113 TriggerReferencing, TriggerReferencingType,
114};
115
116pub use self::value::{
117 escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
118 NormalizationForm, QuoteDelimitedString, TrimWhereField, Value, ValueWithSpan,
119};
120
121use crate::ast::helpers::key_value_options::KeyValueOptions;
122use crate::ast::helpers::stmt_data_loading::StageParamsObject;
123
124#[cfg(feature = "visitor")]
125pub use visitor::*;
126
127pub use self::data_type::GeometricTypeKind;
128
129mod data_type;
130mod dcl;
131mod ddl;
132mod dml;
133/// Helper modules for building and manipulating AST nodes.
134pub mod helpers;
135pub mod table_constraints;
136pub use table_constraints::{
137 CheckConstraint, ForeignKeyConstraint, FullTextOrSpatialConstraint, IndexConstraint,
138 PrimaryKeyConstraint, TableConstraint, UniqueConstraint,
139};
140mod operator;
141mod query;
142mod spans;
143pub use spans::Spanned;
144
145pub mod comments;
146mod trigger;
147mod value;
148
149#[cfg(feature = "visitor")]
150mod visitor;
151
152/// Helper used to format a slice using a separator string (e.g., `", "`).
153pub struct DisplaySeparated<'a, T>
154where
155 T: fmt::Display,
156{
157 slice: &'a [T],
158 sep: &'static str,
159}
160
161impl<T> fmt::Display for DisplaySeparated<'_, T>
162where
163 T: fmt::Display,
164{
165 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
166 let mut delim = "";
167 for t in self.slice {
168 f.write_str(delim)?;
169 delim = self.sep;
170 t.fmt(f)?;
171 }
172 Ok(())
173 }
174}
175
176pub(crate) fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
177where
178 T: fmt::Display,
179{
180 DisplaySeparated { slice, sep }
181}
182
183pub(crate) fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
184where
185 T: fmt::Display,
186{
187 DisplaySeparated { slice, sep: ", " }
188}
189
190/// Writes the given statements to the formatter, each ending with
191/// a semicolon and space separated.
192fn format_statement_list(f: &mut fmt::Formatter, statements: &[Statement]) -> fmt::Result {
193 write!(f, "{}", display_separated(statements, "; "))?;
194 // We manually insert semicolon for the last statement,
195 // since display_separated doesn't handle that case.
196 write!(f, ";")
197}
198
199/// An identifier, decomposed into its value or character data and the quote style.
200#[derive(Debug, Clone)]
201#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
202#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
203pub struct Ident {
204 /// The value of the identifier without quotes.
205 pub value: String,
206 /// The starting quote if any. Valid quote characters are the single quote,
207 /// double quote, backtick, and opening square bracket.
208 pub quote_style: Option<char>,
209 /// The span of the identifier in the original SQL string.
210 pub span: Span,
211}
212
213impl PartialEq for Ident {
214 fn eq(&self, other: &Self) -> bool {
215 let Ident {
216 value,
217 quote_style,
218 // exhaustiveness check; we ignore spans in comparisons
219 span: _,
220 } = self;
221
222 value == &other.value && quote_style == &other.quote_style
223 }
224}
225
226impl core::hash::Hash for Ident {
227 fn hash<H: hash::Hasher>(&self, state: &mut H) {
228 let Ident {
229 value,
230 quote_style,
231 // exhaustiveness check; we ignore spans in hashes
232 span: _,
233 } = self;
234
235 value.hash(state);
236 quote_style.hash(state);
237 }
238}
239
240impl Eq for Ident {}
241
242impl PartialOrd for Ident {
243 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
244 Some(self.cmp(other))
245 }
246}
247
248impl Ord for Ident {
249 fn cmp(&self, other: &Self) -> Ordering {
250 let Ident {
251 value,
252 quote_style,
253 // exhaustiveness check; we ignore spans in ordering
254 span: _,
255 } = self;
256
257 let Ident {
258 value: other_value,
259 quote_style: other_quote_style,
260 // exhaustiveness check; we ignore spans in ordering
261 span: _,
262 } = other;
263
264 // First compare by value, then by quote_style
265 value
266 .cmp(other_value)
267 .then_with(|| quote_style.cmp(other_quote_style))
268 }
269}
270
271impl Ident {
272 /// Create a new identifier with the given value and no quotes and an empty span.
273 pub fn new<S>(value: S) -> Self
274 where
275 S: Into<String>,
276 {
277 Ident {
278 value: value.into(),
279 quote_style: None,
280 span: Span::empty(),
281 }
282 }
283
284 /// Create a new quoted identifier with the given quote and value. This function
285 /// panics if the given quote is not a valid quote character.
286 pub fn with_quote<S>(quote: char, value: S) -> Self
287 where
288 S: Into<String>,
289 {
290 assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
291 Ident {
292 value: value.into(),
293 quote_style: Some(quote),
294 span: Span::empty(),
295 }
296 }
297
298 /// Create an `Ident` with the given `span` and `value` (unquoted).
299 pub fn with_span<S>(span: Span, value: S) -> Self
300 where
301 S: Into<String>,
302 {
303 Ident {
304 value: value.into(),
305 quote_style: None,
306 span,
307 }
308 }
309
310 /// Create a quoted `Ident` with the given `quote` and `span`.
311 pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
312 where
313 S: Into<String>,
314 {
315 assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
316 Ident {
317 value: value.into(),
318 quote_style: Some(quote),
319 span,
320 }
321 }
322}
323
324impl From<&str> for Ident {
325 fn from(value: &str) -> Self {
326 Ident {
327 value: value.to_string(),
328 quote_style: None,
329 span: Span::empty(),
330 }
331 }
332}
333
334impl fmt::Display for Ident {
335 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
336 match self.quote_style {
337 Some(q) if q == '"' || q == '\'' || q == '`' => {
338 let escaped = value::escape_quoted_string(&self.value, q);
339 write!(f, "{q}{escaped}{q}")
340 }
341 Some('[') => write!(f, "[{}]", self.value),
342 None => f.write_str(&self.value),
343 _ => panic!("unexpected quote style"),
344 }
345 }
346}
347
348/// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj
349#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
350#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
351#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
352pub struct ObjectName(pub Vec<ObjectNamePart>);
353
354impl From<Vec<Ident>> for ObjectName {
355 fn from(idents: Vec<Ident>) -> Self {
356 ObjectName(idents.into_iter().map(ObjectNamePart::Identifier).collect())
357 }
358}
359
360impl From<Ident> for ObjectName {
361 fn from(ident: Ident) -> Self {
362 ObjectName(vec![ObjectNamePart::Identifier(ident)])
363 }
364}
365
366impl fmt::Display for ObjectName {
367 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
368 write!(f, "{}", display_separated(&self.0, "."))
369 }
370}
371
372/// A single part of an ObjectName
373#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
374#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
375#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
376pub enum ObjectNamePart {
377 /// A single identifier part, e.g. `schema` or `table`.
378 Identifier(Ident),
379 /// A function that returns an identifier (dialect-specific).
380 Function(ObjectNamePartFunction),
381}
382
383impl ObjectNamePart {
384 /// Return the identifier if this is an `Identifier` variant.
385 pub fn as_ident(&self) -> Option<&Ident> {
386 match self {
387 ObjectNamePart::Identifier(ident) => Some(ident),
388 ObjectNamePart::Function(_) => None,
389 }
390 }
391}
392
393impl fmt::Display for ObjectNamePart {
394 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
395 match self {
396 ObjectNamePart::Identifier(ident) => write!(f, "{ident}"),
397 ObjectNamePart::Function(func) => write!(f, "{func}"),
398 }
399 }
400}
401
402/// An object name part that consists of a function that dynamically
403/// constructs identifiers.
404///
405/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/identifier-literal)
406#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
407#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
408#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
409pub struct ObjectNamePartFunction {
410 /// The function name that produces the object name part.
411 pub name: Ident,
412 /// Function arguments used to compute the identifier.
413 pub args: Vec<FunctionArg>,
414}
415
416impl fmt::Display for ObjectNamePartFunction {
417 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
418 write!(f, "{}(", self.name)?;
419 write!(f, "{})", display_comma_separated(&self.args))
420 }
421}
422
423/// Represents an Array Expression, either
424/// `ARRAY[..]`, or `[..]`
425#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
426#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
427#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
428pub struct Array {
429 /// The list of expressions between brackets
430 pub elem: Vec<Expr>,
431
432 /// `true` for `ARRAY[..]`, `false` for `[..]`
433 pub named: bool,
434}
435
436impl fmt::Display for Array {
437 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
438 write!(
439 f,
440 "{}[{}]",
441 if self.named { "ARRAY" } else { "" },
442 display_comma_separated(&self.elem)
443 )
444 }
445}
446
447/// Represents an INTERVAL expression, roughly in the following format:
448/// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
449/// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
450/// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
451///
452/// The parser does not validate the `<value>`, nor does it ensure
453/// that the `<leading_field>` units >= the units in `<last_field>`,
454/// so the user will have to reject intervals like `HOUR TO YEAR`.
455#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
456#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
457#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
458pub struct Interval {
459 /// The interval value expression (commonly a string literal).
460 pub value: Box<Expr>,
461 /// Optional leading time unit (e.g., `HOUR`, `MINUTE`).
462 pub leading_field: Option<DateTimeField>,
463 /// Optional leading precision for the leading field.
464 pub leading_precision: Option<u64>,
465 /// Optional trailing time unit for a range (e.g., `SECOND`).
466 pub last_field: Option<DateTimeField>,
467 /// The fractional seconds precision, when specified.
468 ///
469 /// See SQL `SECOND(n)` or `SECOND(m, n)` forms.
470 pub fractional_seconds_precision: Option<u64>,
471}
472
473impl fmt::Display for Interval {
474 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
475 let value = self.value.as_ref();
476 match (
477 &self.leading_field,
478 self.leading_precision,
479 self.fractional_seconds_precision,
480 ) {
481 (
482 Some(DateTimeField::Second),
483 Some(leading_precision),
484 Some(fractional_seconds_precision),
485 ) => {
486 // When the leading field is SECOND, the parser guarantees that
487 // the last field is None.
488 assert!(self.last_field.is_none());
489 write!(
490 f,
491 "INTERVAL {value} SECOND ({leading_precision}, {fractional_seconds_precision})"
492 )
493 }
494 _ => {
495 write!(f, "INTERVAL {value}")?;
496 if let Some(leading_field) = &self.leading_field {
497 write!(f, " {leading_field}")?;
498 }
499 if let Some(leading_precision) = self.leading_precision {
500 write!(f, " ({leading_precision})")?;
501 }
502 if let Some(last_field) = &self.last_field {
503 write!(f, " TO {last_field}")?;
504 }
505 if let Some(fractional_seconds_precision) = self.fractional_seconds_precision {
506 write!(f, " ({fractional_seconds_precision})")?;
507 }
508 Ok(())
509 }
510 }
511 }
512}
513
514/// A field definition within a struct
515///
516/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
517#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
518#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
519#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
520pub struct StructField {
521 /// Optional name of the struct field.
522 pub field_name: Option<Ident>,
523 /// The field data type.
524 pub field_type: DataType,
525 /// Struct field options (e.g., `OPTIONS(...)` on BigQuery).
526 /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema)
527 pub options: Option<Vec<SqlOption>>,
528}
529
530impl fmt::Display for StructField {
531 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
532 if let Some(name) = &self.field_name {
533 write!(f, "{name} {}", self.field_type)?;
534 } else {
535 write!(f, "{}", self.field_type)?;
536 }
537 if let Some(options) = &self.options {
538 write!(f, " OPTIONS({})", display_separated(options, ", "))
539 } else {
540 Ok(())
541 }
542 }
543}
544
545/// A field definition within a union
546///
547/// [DuckDB]: https://duckdb.org/docs/sql/data_types/union.html
548#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
549#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
550#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
551pub struct UnionField {
552 /// Name of the union field.
553 pub field_name: Ident,
554 /// Type of the union field.
555 pub field_type: DataType,
556}
557
558impl fmt::Display for UnionField {
559 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
560 write!(f, "{} {}", self.field_name, self.field_type)
561 }
562}
563
564/// A dictionary field within a dictionary.
565///
566/// [DuckDB]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
567#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
568#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
569#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
570pub struct DictionaryField {
571 /// Dictionary key identifier.
572 pub key: Ident,
573 /// Value expression for the dictionary entry.
574 pub value: Box<Expr>,
575}
576
577impl fmt::Display for DictionaryField {
578 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
579 write!(f, "{}: {}", self.key, self.value)
580 }
581}
582
583/// Represents a Map expression.
584#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
585#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
586#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
587pub struct Map {
588 /// Entries of the map as key/value pairs.
589 pub entries: Vec<MapEntry>,
590}
591
592impl Display for Map {
593 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
594 write!(f, "MAP {{{}}}", display_comma_separated(&self.entries))
595 }
596}
597
598/// A map field within a map.
599///
600/// [DuckDB]: https://duckdb.org/docs/sql/data_types/map.html#creating-maps
601#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
602#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
603#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
604pub struct MapEntry {
605 /// Key expression of the map entry.
606 pub key: Box<Expr>,
607 /// Value expression of the map entry.
608 pub value: Box<Expr>,
609}
610
611impl fmt::Display for MapEntry {
612 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
613 write!(f, "{}: {}", self.key, self.value)
614 }
615}
616
617/// Options for `CAST` / `TRY_CAST`
618/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
619#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
620#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
621#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
622pub enum CastFormat {
623 /// A simple cast format specified by a `Value`.
624 Value(Value),
625 /// A cast format with an explicit time zone: `(format, timezone)`.
626 ValueAtTimeZone(Value, Value),
627}
628
629/// An element of a JSON path.
630#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
631#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
632#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
633pub enum JsonPathElem {
634 /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`.
635 ///
636 /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#dot-notation>.
637 Dot {
638 /// The object key text (without quotes).
639 key: String,
640 /// `true` when the key was quoted in the source.
641 quoted: bool,
642 },
643 /// Accesses an object field or array element using bracket notation,
644 /// e.g. `obj['foo']`.
645 ///
646 /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured#bracket-notation>.
647 Bracket {
648 /// The expression used as the bracket key (string or numeric expression).
649 key: Expr,
650 },
651}
652
653/// A JSON path.
654///
655/// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
656/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-json-path-expression.html>.
657#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
658#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
659#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
660pub struct JsonPath {
661 /// Sequence of path elements that form the JSON path.
662 pub path: Vec<JsonPathElem>,
663}
664
665impl fmt::Display for JsonPath {
666 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
667 for (i, elem) in self.path.iter().enumerate() {
668 match elem {
669 JsonPathElem::Dot { key, quoted } => {
670 if i == 0 {
671 write!(f, ":")?;
672 } else {
673 write!(f, ".")?;
674 }
675
676 if *quoted {
677 write!(f, "\"{}\"", escape_double_quote_string(key))?;
678 } else {
679 write!(f, "{key}")?;
680 }
681 }
682 JsonPathElem::Bracket { key } => {
683 write!(f, "[{key}]")?;
684 }
685 }
686 }
687 Ok(())
688 }
689}
690
691/// The syntax used for in a cast expression.
692#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
693#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
694#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
695pub enum CastKind {
696 /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
697 Cast,
698 /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
699 ///
700 /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
701 /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
702 TryCast,
703 /// A cast that returns `NULL` on failure, bigQuery-specific , e.g. `SAFE_CAST(<expr> as <datatype>)`.
704 ///
705 /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
706 SafeCast,
707 /// `<expr> :: <datatype>`
708 DoubleColon,
709}
710
711/// `MATCH` type for constraint references
712///
713/// See: <https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES>
714#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
715#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
716#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
717pub enum ConstraintReferenceMatchKind {
718 /// `MATCH FULL`
719 Full,
720 /// `MATCH PARTIAL`
721 Partial,
722 /// `MATCH SIMPLE`
723 Simple,
724}
725
726impl fmt::Display for ConstraintReferenceMatchKind {
727 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
728 match self {
729 Self::Full => write!(f, "MATCH FULL"),
730 Self::Partial => write!(f, "MATCH PARTIAL"),
731 Self::Simple => write!(f, "MATCH SIMPLE"),
732 }
733 }
734}
735
736/// `EXTRACT` syntax variants.
737///
738/// In Snowflake dialect, the `EXTRACT` expression can support either the `from` syntax
739/// or the comma syntax.
740///
741/// See <https://docs.snowflake.com/en/sql-reference/functions/extract>
742#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
743#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
744#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
745pub enum ExtractSyntax {
746 /// `EXTRACT( <date_or_time_part> FROM <date_or_time_expr> )`
747 From,
748 /// `EXTRACT( <date_or_time_part> , <date_or_timestamp_expr> )`
749 Comma,
750}
751
752/// The syntax used in a CEIL or FLOOR expression.
753///
754/// The `CEIL/FLOOR(<datetime value expression> TO <time unit>)` is an Amazon Kinesis Data Analytics extension.
755/// See <https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-ceil.html> for
756/// details.
757///
758/// Other dialects either support `CEIL/FLOOR( <expr> [, <scale>])` format or just
759/// `CEIL/FLOOR(<expr>)`.
760#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
761#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
762#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
763pub enum CeilFloorKind {
764 /// `CEIL( <expr> TO <DateTimeField>)`
765 DateTimeField(DateTimeField),
766 /// `CEIL( <expr> [, <scale>])`
767 Scale(Value),
768}
769
770/// A WHEN clause in a CASE expression containing both
771/// the condition and its corresponding result
772#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
773#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
774#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
775pub struct CaseWhen {
776 /// The `WHEN` condition expression.
777 pub condition: Expr,
778 /// The expression returned when `condition` matches.
779 pub result: Expr,
780}
781
782impl fmt::Display for CaseWhen {
783 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
784 f.write_str("WHEN ")?;
785 self.condition.fmt(f)?;
786 f.write_str(" THEN")?;
787 SpaceOrNewline.fmt(f)?;
788 Indent(&self.result).fmt(f)?;
789 Ok(())
790 }
791}
792
793/// An SQL expression of any type.
794///
795/// # Semantics / Type Checking
796///
797/// The parser does not distinguish between expressions of different types
798/// (e.g. boolean vs string). The caller is responsible for detecting and
799/// validating types as necessary (for example `WHERE 1` vs `SELECT 1=1`)
800/// See the [README.md] for more details.
801///
802/// [README.md]: https://github.com/apache/datafusion-sqlparser-rs/blob/main/README.md#syntax-vs-semantics
803///
804/// # Equality and Hashing Does not Include Source Locations
805///
806/// The `Expr` type implements `PartialEq` and `Eq` based on the semantic value
807/// of the expression (not bitwise comparison). This means that `Expr` instances
808/// that are semantically equivalent but have different spans (locations in the
809/// source tree) will compare as equal.
810#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
811#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
812#[cfg_attr(
813 feature = "visitor",
814 derive(Visit, VisitMut),
815 visit(with = "visit_expr")
816)]
817pub enum Expr {
818 /// Identifier e.g. table name or column name
819 Identifier(Ident),
820 /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
821 CompoundIdentifier(Vec<Ident>),
822 /// Multi-part expression access.
823 ///
824 /// This structure represents an access chain in structured / nested types
825 /// such as maps, arrays, and lists:
826 /// - Array
827 /// - A 1-dim array `a[1]` will be represented like:
828 /// `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
829 /// - A 2-dim array `a[1][2]` will be represented like:
830 /// `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
831 /// - Map or Struct (Bracket-style)
832 /// - A map `a['field1']` will be represented like:
833 /// `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
834 /// - A 2-dim map `a['field1']['field2']` will be represented like:
835 /// `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
836 /// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
837 /// - A struct access `a[field1].field2` will be represented like:
838 /// `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
839 /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
840 CompoundFieldAccess {
841 /// The base expression being accessed.
842 root: Box<Expr>,
843 /// Sequence of access operations (subscript or identifier accesses).
844 access_chain: Vec<AccessExpr>,
845 },
846 /// Access data nested in a value containing semi-structured data, such as
847 /// the `VARIANT` type on Snowflake. for example `src:customer[0].name`.
848 ///
849 /// See <https://docs.snowflake.com/en/user-guide/querying-semistructured>.
850 /// See <https://docs.databricks.com/en/sql/language-manual/functions/colonsign.html>.
851 JsonAccess {
852 /// The value being queried.
853 value: Box<Expr>,
854 /// The path to the data to extract.
855 path: JsonPath,
856 },
857 /// `IS FALSE` operator
858 IsFalse(Box<Expr>),
859 /// `IS NOT FALSE` operator
860 IsNotFalse(Box<Expr>),
861 /// `IS TRUE` operator
862 IsTrue(Box<Expr>),
863 /// `IS NOT TRUE` operator
864 IsNotTrue(Box<Expr>),
865 /// `IS NULL` operator
866 IsNull(Box<Expr>),
867 /// `IS NOT NULL` operator
868 IsNotNull(Box<Expr>),
869 /// `IS UNKNOWN` operator
870 IsUnknown(Box<Expr>),
871 /// `IS NOT UNKNOWN` operator
872 IsNotUnknown(Box<Expr>),
873 /// `IS DISTINCT FROM` operator
874 IsDistinctFrom(Box<Expr>, Box<Expr>),
875 /// `IS NOT DISTINCT FROM` operator
876 IsNotDistinctFrom(Box<Expr>, Box<Expr>),
877 /// `<expr> IS [ NOT ] [ form ] NORMALIZED`
878 IsNormalized {
879 /// Expression being tested.
880 expr: Box<Expr>,
881 /// Optional normalization `form` (e.g., NFC, NFD).
882 form: Option<NormalizationForm>,
883 /// `true` when `NOT` is present.
884 negated: bool,
885 },
886 /// `[ NOT ] IN (val1, val2, ...)`
887 InList {
888 /// Left-hand expression to test for membership.
889 expr: Box<Expr>,
890 /// Literal list of expressions to check against.
891 list: Vec<Expr>,
892 /// `true` when the `NOT` modifier is present.
893 negated: bool,
894 },
895 /// `[ NOT ] IN (SELECT ...)`
896 InSubquery {
897 /// Left-hand expression to test for membership.
898 expr: Box<Expr>,
899 /// The subquery providing the candidate values.
900 subquery: Box<Query>,
901 /// `true` when the `NOT` modifier is present.
902 negated: bool,
903 },
904 /// `[ NOT ] IN UNNEST(array_expression)`
905 InUnnest {
906 /// Left-hand expression to test for membership.
907 expr: Box<Expr>,
908 /// Array expression being unnested.
909 array_expr: Box<Expr>,
910 /// `true` when the `NOT` modifier is present.
911 negated: bool,
912 },
913 /// `<expr> [ NOT ] BETWEEN <low> AND <high>`
914 Between {
915 /// Expression being compared.
916 expr: Box<Expr>,
917 /// `true` when the `NOT` modifier is present.
918 negated: bool,
919 /// Lower bound.
920 low: Box<Expr>,
921 /// Upper bound.
922 high: Box<Expr>,
923 },
924 /// Binary operation e.g. `1 + 1` or `foo > bar`
925 BinaryOp {
926 /// Left operand.
927 left: Box<Expr>,
928 /// Operator between operands.
929 op: BinaryOperator,
930 /// Right operand.
931 right: Box<Expr>,
932 },
933 /// `[NOT] LIKE <pattern> [ESCAPE <escape_character>]`
934 Like {
935 /// `true` when `NOT` is present.
936 negated: bool,
937 /// Snowflake supports the ANY keyword to match against a list of patterns
938 /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
939 any: bool,
940 /// Expression to match.
941 expr: Box<Expr>,
942 /// Pattern expression.
943 pattern: Box<Expr>,
944 /// Optional escape character.
945 escape_char: Option<Value>,
946 },
947 /// `ILIKE` (case-insensitive `LIKE`)
948 ILike {
949 /// `true` when `NOT` is present.
950 negated: bool,
951 /// Snowflake supports the ANY keyword to match against a list of patterns
952 /// <https://docs.snowflake.com/en/sql-reference/functions/like_any>
953 any: bool,
954 /// Expression to match.
955 expr: Box<Expr>,
956 /// Pattern expression.
957 pattern: Box<Expr>,
958 /// Optional escape character.
959 escape_char: Option<Value>,
960 },
961 /// `SIMILAR TO` regex
962 SimilarTo {
963 /// `true` when `NOT` is present.
964 negated: bool,
965 /// Expression to test.
966 expr: Box<Expr>,
967 /// Pattern expression.
968 pattern: Box<Expr>,
969 /// Optional escape character.
970 escape_char: Option<Value>,
971 },
972 /// MySQL: `RLIKE` regex or `REGEXP` regex
973 RLike {
974 /// `true` when `NOT` is present.
975 negated: bool,
976 /// Expression to test.
977 expr: Box<Expr>,
978 /// Pattern expression.
979 pattern: Box<Expr>,
980 /// true for REGEXP, false for RLIKE (no difference in semantics)
981 regexp: bool,
982 },
983 /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
984 /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
985 AnyOp {
986 /// Left operand.
987 left: Box<Expr>,
988 /// Comparison operator.
989 compare_op: BinaryOperator,
990 /// Right-hand subquery expression.
991 right: Box<Expr>,
992 /// ANY and SOME are synonymous: <https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html>
993 is_some: bool,
994 },
995 /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]`
996 /// <https://docs.snowflake.com/en/sql-reference/operators-subquery#all-any>
997 AllOp {
998 /// Left operand.
999 left: Box<Expr>,
1000 /// Comparison operator.
1001 compare_op: BinaryOperator,
1002 /// Right-hand subquery expression.
1003 right: Box<Expr>,
1004 },
1005
1006 /// Unary operation e.g. `NOT foo`
1007 UnaryOp {
1008 /// The unary operator (e.g., `NOT`, `-`).
1009 op: UnaryOperator,
1010 /// Operand expression.
1011 expr: Box<Expr>,
1012 },
1013 /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)`
1014 Convert {
1015 /// CONVERT (false) or TRY_CONVERT (true)
1016 /// <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-convert-transact-sql?view=sql-server-ver16>
1017 is_try: bool,
1018 /// The expression to convert.
1019 expr: Box<Expr>,
1020 /// The target data type, if provided.
1021 data_type: Option<DataType>,
1022 /// Optional target character encoding (e.g., `utf8mb4`).
1023 charset: Option<ObjectName>,
1024 /// `true` when target precedes the value (MSSQL syntax).
1025 target_before_value: bool,
1026 /// How to translate the expression.
1027 ///
1028 /// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
1029 styles: Vec<Expr>,
1030 },
1031 /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
1032 Cast {
1033 /// The cast kind (e.g., `CAST`, `TRY_CAST`).
1034 kind: CastKind,
1035 /// Expression being cast.
1036 expr: Box<Expr>,
1037 /// Target data type.
1038 data_type: DataType,
1039 /// [MySQL] allows CAST(... AS type ARRAY) in functional index definitions for InnoDB
1040 /// multi-valued indices. It's not really a datatype, and is only allowed in `CAST` in key
1041 /// specifications, so it's a flag here.
1042 ///
1043 /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/cast-functions.html#function_cast
1044 array: bool,
1045 /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery]
1046 ///
1047 /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
1048 format: Option<CastFormat>,
1049 },
1050 /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
1051 AtTimeZone {
1052 /// Timestamp expression to shift.
1053 timestamp: Box<Expr>,
1054 /// Time zone expression to apply.
1055 time_zone: Box<Expr>,
1056 },
1057 /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)`
1058 /// Or `EXTRACT(MONTH, foo)`
1059 ///
1060 /// Syntax:
1061 /// ```sql
1062 /// EXTRACT(DateTimeField FROM <expr>) | EXTRACT(DateTimeField, <expr>)
1063 /// ```
1064 Extract {
1065 /// Which datetime field is being extracted.
1066 field: DateTimeField,
1067 /// Syntax variant used (`From` or `Comma`).
1068 syntax: ExtractSyntax,
1069 /// Expression to extract from.
1070 expr: Box<Expr>,
1071 },
1072 /// ```sql
1073 /// CEIL(<expr> [TO DateTimeField])
1074 /// ```
1075 /// ```sql
1076 /// CEIL( <input_expr> [, <scale_expr> ] )
1077 /// ```
1078 Ceil {
1079 /// Expression to ceil.
1080 expr: Box<Expr>,
1081 /// The CEIL/FLOOR kind (datetime field or scale).
1082 field: CeilFloorKind,
1083 },
1084 /// ```sql
1085 /// FLOOR(<expr> [TO DateTimeField])
1086 /// ```
1087 /// ```sql
1088 /// FLOOR( <input_expr> [, <scale_expr> ] )
1089 ///
1090 Floor {
1091 /// Expression to floor.
1092 expr: Box<Expr>,
1093 /// The CEIL/FLOOR kind (datetime field or scale).
1094 field: CeilFloorKind,
1095 },
1096 /// ```sql
1097 /// POSITION(<expr> in <expr>)
1098 /// ```
1099 Position {
1100 /// Expression to search for.
1101 expr: Box<Expr>,
1102 /// Expression to search in.
1103 r#in: Box<Expr>,
1104 },
1105 /// ```sql
1106 /// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
1107 /// ```
1108 /// or
1109 /// ```sql
1110 /// SUBSTRING(<expr>, <expr>, <expr>)
1111 /// ```
1112 Substring {
1113 /// Source expression.
1114 expr: Box<Expr>,
1115 /// Optional `FROM` expression.
1116 substring_from: Option<Box<Expr>>,
1117 /// Optional `FOR` expression.
1118 substring_for: Option<Box<Expr>>,
1119
1120 /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax
1121 /// true if the expression is represented using the `SUBSTRING(expr, start, len)` syntax
1122 /// This flag is used for formatting.
1123 special: bool,
1124
1125 /// true if the expression is represented using the `SUBSTR` shorthand
1126 /// This flag is used for formatting.
1127 shorthand: bool,
1128 },
1129 /// ```sql
1130 /// TRIM([BOTH | LEADING | TRAILING] [<expr> FROM] <expr>)
1131 /// TRIM(<expr>)
1132 /// TRIM(<expr>, [, characters]) -- only Snowflake or Bigquery
1133 /// ```
1134 Trim {
1135 /// The expression to trim from.
1136 expr: Box<Expr>,
1137 /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`.
1138 trim_where: Option<TrimWhereField>,
1139 /// Optional expression specifying what to trim from the value.
1140 trim_what: Option<Box<Expr>>,
1141 /// Optional list of characters to trim (dialect-specific).
1142 trim_characters: Option<Vec<Expr>>,
1143 },
1144 /// ```sql
1145 /// OVERLAY(<expr> PLACING <expr> FROM <expr>[ FOR <expr> ]
1146 /// ```
1147 Overlay {
1148 /// The target expression being overlayed.
1149 expr: Box<Expr>,
1150 /// The expression to place into the target.
1151 overlay_what: Box<Expr>,
1152 /// The `FROM` position expression indicating where to start overlay.
1153 overlay_from: Box<Expr>,
1154 /// Optional `FOR` length expression limiting the overlay span.
1155 overlay_for: Option<Box<Expr>>,
1156 },
1157 /// `expr COLLATE collation`
1158 Collate {
1159 /// The expression being collated.
1160 expr: Box<Expr>,
1161 /// The collation name to apply to the expression.
1162 collation: ObjectName,
1163 },
1164 /// Nested expression e.g. `(foo > bar)` or `(1)`
1165 Nested(Box<Expr>),
1166 /// A literal value, such as string, number, date or NULL
1167 Value(ValueWithSpan),
1168 /// Prefixed expression, e.g. introducer strings, projection prefix
1169 /// <https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html>
1170 /// <https://docs.snowflake.com/en/sql-reference/constructs/connect-by>
1171 Prefixed {
1172 /// The prefix identifier (introducer or projection prefix).
1173 prefix: Ident,
1174 /// The value expression being prefixed.
1175 /// Hint: you can unwrap the string value using `value.into_string()`.
1176 value: Box<Expr>,
1177 },
1178 /// A constant of form `<data_type> 'value'`.
1179 /// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
1180 /// as well as constants of other types (a non-standard PostgreSQL extension).
1181 TypedString(TypedString),
1182 /// Scalar function call e.g. `LEFT(foo, 5)`
1183 Function(Function),
1184 /// `CASE [<operand>] WHEN <condition> THEN <result> ... [ELSE <result>] END`
1185 ///
1186 /// Note we only recognize a complete single expression as `<condition>`,
1187 /// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
1188 /// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
1189 Case {
1190 /// The attached `CASE` token (keeps original spacing/comments).
1191 case_token: AttachedToken,
1192 /// The attached `END` token (keeps original spacing/comments).
1193 end_token: AttachedToken,
1194 /// Optional operand expression after `CASE` (for simple CASE).
1195 operand: Option<Box<Expr>>,
1196 /// The `WHEN ... THEN` conditions and results.
1197 conditions: Vec<CaseWhen>,
1198 /// Optional `ELSE` result expression.
1199 else_result: Option<Box<Expr>>,
1200 },
1201 /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
1202 /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
1203 Exists {
1204 /// The subquery checked by `EXISTS`.
1205 subquery: Box<Query>,
1206 /// Whether the `EXISTS` is negated (`NOT EXISTS`).
1207 negated: bool,
1208 },
1209 /// A parenthesized subquery `(SELECT ...)`, used in expression like
1210 /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
1211 Subquery(Box<Query>),
1212 /// The `GROUPING SETS` expr.
1213 GroupingSets(Vec<Vec<Expr>>),
1214 /// The `CUBE` expr.
1215 Cube(Vec<Vec<Expr>>),
1216 /// The `ROLLUP` expr.
1217 Rollup(Vec<Vec<Expr>>),
1218 /// ROW / TUPLE a single value, such as `SELECT (1, 2)`
1219 Tuple(Vec<Expr>),
1220 /// `Struct` literal expression
1221 /// Syntax:
1222 /// ```sql
1223 /// STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
1224 ///
1225 /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type)
1226 /// [Databricks](https://docs.databricks.com/en/sql/language-manual/functions/struct.html)
1227 /// ```
1228 Struct {
1229 /// Struct values.
1230 values: Vec<Expr>,
1231 /// Struct field definitions.
1232 fields: Vec<StructField>,
1233 },
1234 /// `BigQuery` specific: An named expression in a typeless struct [1]
1235 ///
1236 /// Syntax
1237 /// ```sql
1238 /// 1 AS A
1239 /// ```
1240 /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
1241 Named {
1242 /// The expression being named.
1243 expr: Box<Expr>,
1244 /// The assigned identifier name for the expression.
1245 name: Ident,
1246 },
1247 /// `DuckDB` specific `Struct` literal expression [1]
1248 ///
1249 /// Syntax:
1250 /// ```sql
1251 /// syntax: {'field_name': expr1[, ... ]}
1252 /// ```
1253 /// [1]: https://duckdb.org/docs/sql/data_types/struct#creating-structs
1254 Dictionary(Vec<DictionaryField>),
1255 /// `DuckDB` specific `Map` literal expression [1]
1256 ///
1257 /// Syntax:
1258 /// ```sql
1259 /// syntax: Map {key1: value1[, ... ]}
1260 /// ```
1261 /// [1]: https://duckdb.org/docs/sql/data_types/map#creating-maps
1262 Map(Map),
1263 /// An array expression e.g. `ARRAY[1, 2]`
1264 Array(Array),
1265 /// An interval expression e.g. `INTERVAL '1' YEAR`
1266 Interval(Interval),
1267 /// `MySQL` specific text search function [(1)].
1268 ///
1269 /// Syntax:
1270 /// ```sql
1271 /// MATCH (<col>, <col>, ...) AGAINST (<expr> [<search modifier>])
1272 ///
1273 /// <col> = CompoundIdentifier
1274 /// <expr> = String literal
1275 /// ```
1276 /// [(1)]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
1277 MatchAgainst {
1278 /// `(<col>, <col>, ...)`.
1279 columns: Vec<ObjectName>,
1280 /// `<expr>`.
1281 match_value: Value,
1282 /// `<search modifier>`
1283 opt_search_modifier: Option<SearchModifier>,
1284 },
1285 /// An unqualified `*` wildcard token (e.g. `*`).
1286 Wildcard(AttachedToken),
1287 /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
1288 /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
1289 QualifiedWildcard(ObjectName, AttachedToken),
1290 /// Some dialects support an older syntax for outer joins where columns are
1291 /// marked with the `(+)` operator in the WHERE clause, for example:
1292 ///
1293 /// ```sql
1294 /// SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+)
1295 /// ```
1296 ///
1297 /// which is equivalent to
1298 ///
1299 /// ```sql
1300 /// SELECT t1.c1, t2.c2 FROM t1 LEFT OUTER JOIN t2 ON t1.c1 = t2.c2
1301 /// ```
1302 ///
1303 /// See <https://docs.snowflake.com/en/sql-reference/constructs/where#joins-in-the-where-clause>.
1304 OuterJoin(Box<Expr>),
1305 /// A reference to the prior level in a CONNECT BY clause.
1306 Prior(Box<Expr>),
1307 /// A lambda function.
1308 ///
1309 /// Syntax:
1310 /// ```plaintext
1311 /// param -> expr | (param1, ...) -> expr
1312 /// ```
1313 ///
1314 /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/functions#higher-order-functions---operator-and-lambdaparams-expr-function)
1315 /// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-lambda-functions.html)
1316 /// [DuckDB](https://duckdb.org/docs/stable/sql/functions/lambda)
1317 Lambda(LambdaFunction),
1318 /// Checks membership of a value in a JSON array
1319 MemberOf(MemberOf),
1320}
1321
1322impl Expr {
1323 /// Creates a new [`Expr::Value`]
1324 pub fn value(value: impl Into<ValueWithSpan>) -> Self {
1325 Expr::Value(value.into())
1326 }
1327}
1328
1329/// The contents inside the `[` and `]` in a subscript expression.
1330#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1331#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1332#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1333pub enum Subscript {
1334 /// Accesses the element of the array at the given index.
1335 Index {
1336 /// The index expression used to access the array element.
1337 index: Expr,
1338 },
1339
1340 /// Accesses a slice of an array on PostgreSQL, e.g.
1341 ///
1342 /// ```plaintext
1343 /// => select (array[1,2,3,4,5,6])[2:5];
1344 /// -----------
1345 /// {2,3,4,5}
1346 /// ```
1347 ///
1348 /// The lower and/or upper bound can be omitted to slice from the start or
1349 /// end of the array respectively.
1350 ///
1351 /// See <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-ACCESSING>.
1352 ///
1353 /// Also supports an optional "stride" as the last element (this is not
1354 /// supported by postgres), e.g.
1355 ///
1356 /// ```plaintext
1357 /// => select (array[1,2,3,4,5,6])[1:6:2];
1358 /// -----------
1359 /// {1,3,5}
1360 /// ```
1361 Slice {
1362 /// Optional lower bound for the slice (inclusive).
1363 lower_bound: Option<Expr>,
1364 /// Optional upper bound for the slice (inclusive).
1365 upper_bound: Option<Expr>,
1366 /// Optional stride for the slice (step size).
1367 stride: Option<Expr>,
1368 },
1369}
1370
1371impl fmt::Display for Subscript {
1372 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1373 match self {
1374 Subscript::Index { index } => write!(f, "{index}"),
1375 Subscript::Slice {
1376 lower_bound,
1377 upper_bound,
1378 stride,
1379 } => {
1380 if let Some(lower) = lower_bound {
1381 write!(f, "{lower}")?;
1382 }
1383 write!(f, ":")?;
1384 if let Some(upper) = upper_bound {
1385 write!(f, "{upper}")?;
1386 }
1387 if let Some(stride) = stride {
1388 write!(f, ":")?;
1389 write!(f, "{stride}")?;
1390 }
1391 Ok(())
1392 }
1393 }
1394 }
1395}
1396
1397/// An element of a [`Expr::CompoundFieldAccess`].
1398/// It can be an expression or a subscript.
1399#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1400#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1401#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1402pub enum AccessExpr {
1403 /// Accesses a field using dot notation, e.g. `foo.bar.baz`.
1404 Dot(Expr),
1405 /// Accesses a field or array element using bracket notation, e.g. `foo['bar']`.
1406 Subscript(Subscript),
1407}
1408
1409impl fmt::Display for AccessExpr {
1410 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1411 match self {
1412 AccessExpr::Dot(expr) => write!(f, ".{expr}"),
1413 AccessExpr::Subscript(subscript) => write!(f, "[{subscript}]"),
1414 }
1415 }
1416}
1417
1418/// A lambda function.
1419#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1420#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1421#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1422pub struct LambdaFunction {
1423 /// The parameters to the lambda function.
1424 pub params: OneOrManyWithParens<Ident>,
1425 /// The body of the lambda function.
1426 pub body: Box<Expr>,
1427 /// The syntax style used to write the lambda function.
1428 pub syntax: LambdaSyntax,
1429}
1430
1431impl fmt::Display for LambdaFunction {
1432 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1433 match self.syntax {
1434 LambdaSyntax::Arrow => write!(f, "{} -> {}", self.params, self.body),
1435 LambdaSyntax::LambdaKeyword => {
1436 // For lambda keyword syntax, display params without parentheses
1437 // e.g., `lambda x, y : expr` not `lambda (x, y) : expr`
1438 write!(f, "lambda ")?;
1439 match &self.params {
1440 OneOrManyWithParens::One(p) => write!(f, "{p}")?,
1441 OneOrManyWithParens::Many(ps) => write!(f, "{}", display_comma_separated(ps))?,
1442 };
1443 write!(f, " : {}", self.body)
1444 }
1445 }
1446 }
1447}
1448
1449/// The syntax style for a lambda function.
1450#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy)]
1451#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1452#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1453pub enum LambdaSyntax {
1454 /// Arrow syntax: `param -> expr` or `(param1, param2) -> expr`
1455 ///
1456 /// <https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-lambda-functions>
1457 ///
1458 /// Supported, but deprecated in DuckDB:
1459 /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1460 Arrow,
1461 /// Lambda keyword syntax: `lambda param : expr` or `lambda param1, param2 : expr`
1462 ///
1463 /// Recommended in DuckDB:
1464 /// <https://duckdb.org/docs/stable/sql/functions/lambda>
1465 LambdaKeyword,
1466}
1467
1468/// Encapsulates the common pattern in SQL where either one unparenthesized item
1469/// such as an identifier or expression is permitted, or multiple of the same
1470/// item in a parenthesized list. For accessing items regardless of the form,
1471/// `OneOrManyWithParens` implements `Deref<Target = [T]>` and `IntoIterator`,
1472/// so you can call slice methods on it and iterate over items
1473/// # Examples
1474/// Accessing as a slice:
1475/// ```
1476/// # use sqlparser::ast::OneOrManyWithParens;
1477/// let one = OneOrManyWithParens::One("a");
1478///
1479/// assert_eq!(one[0], "a");
1480/// assert_eq!(one.len(), 1);
1481/// ```
1482/// Iterating:
1483/// ```
1484/// # use sqlparser::ast::OneOrManyWithParens;
1485/// let one = OneOrManyWithParens::One("a");
1486/// let many = OneOrManyWithParens::Many(vec!["a", "b"]);
1487///
1488/// assert_eq!(one.into_iter().chain(many).collect::<Vec<_>>(), vec!["a", "a", "b"] );
1489/// ```
1490#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1491#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1492#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1493pub enum OneOrManyWithParens<T> {
1494 /// A single `T`, unparenthesized.
1495 One(T),
1496 /// One or more `T`s, parenthesized.
1497 Many(Vec<T>),
1498}
1499
1500impl<T> Deref for OneOrManyWithParens<T> {
1501 type Target = [T];
1502
1503 fn deref(&self) -> &[T] {
1504 match self {
1505 OneOrManyWithParens::One(one) => core::slice::from_ref(one),
1506 OneOrManyWithParens::Many(many) => many,
1507 }
1508 }
1509}
1510
1511impl<T> AsRef<[T]> for OneOrManyWithParens<T> {
1512 fn as_ref(&self) -> &[T] {
1513 self
1514 }
1515}
1516
1517impl<'a, T> IntoIterator for &'a OneOrManyWithParens<T> {
1518 type Item = &'a T;
1519 type IntoIter = core::slice::Iter<'a, T>;
1520
1521 fn into_iter(self) -> Self::IntoIter {
1522 self.iter()
1523 }
1524}
1525
1526/// Owned iterator implementation of `OneOrManyWithParens`
1527#[derive(Debug, Clone)]
1528pub struct OneOrManyWithParensIntoIter<T> {
1529 inner: OneOrManyWithParensIntoIterInner<T>,
1530}
1531
1532#[derive(Debug, Clone)]
1533enum OneOrManyWithParensIntoIterInner<T> {
1534 One(core::iter::Once<T>),
1535 Many(<Vec<T> as IntoIterator>::IntoIter),
1536}
1537
1538impl<T> core::iter::FusedIterator for OneOrManyWithParensIntoIter<T>
1539where
1540 core::iter::Once<T>: core::iter::FusedIterator,
1541 <Vec<T> as IntoIterator>::IntoIter: core::iter::FusedIterator,
1542{
1543}
1544
1545impl<T> core::iter::ExactSizeIterator for OneOrManyWithParensIntoIter<T>
1546where
1547 core::iter::Once<T>: core::iter::ExactSizeIterator,
1548 <Vec<T> as IntoIterator>::IntoIter: core::iter::ExactSizeIterator,
1549{
1550}
1551
1552impl<T> core::iter::Iterator for OneOrManyWithParensIntoIter<T> {
1553 type Item = T;
1554
1555 fn next(&mut self) -> Option<Self::Item> {
1556 match &mut self.inner {
1557 OneOrManyWithParensIntoIterInner::One(one) => one.next(),
1558 OneOrManyWithParensIntoIterInner::Many(many) => many.next(),
1559 }
1560 }
1561
1562 fn size_hint(&self) -> (usize, Option<usize>) {
1563 match &self.inner {
1564 OneOrManyWithParensIntoIterInner::One(one) => one.size_hint(),
1565 OneOrManyWithParensIntoIterInner::Many(many) => many.size_hint(),
1566 }
1567 }
1568
1569 fn count(self) -> usize
1570 where
1571 Self: Sized,
1572 {
1573 match self.inner {
1574 OneOrManyWithParensIntoIterInner::One(one) => one.count(),
1575 OneOrManyWithParensIntoIterInner::Many(many) => many.count(),
1576 }
1577 }
1578
1579 fn fold<B, F>(mut self, init: B, f: F) -> B
1580 where
1581 Self: Sized,
1582 F: FnMut(B, Self::Item) -> B,
1583 {
1584 match &mut self.inner {
1585 OneOrManyWithParensIntoIterInner::One(one) => one.fold(init, f),
1586 OneOrManyWithParensIntoIterInner::Many(many) => many.fold(init, f),
1587 }
1588 }
1589}
1590
1591impl<T> core::iter::DoubleEndedIterator for OneOrManyWithParensIntoIter<T> {
1592 fn next_back(&mut self) -> Option<Self::Item> {
1593 match &mut self.inner {
1594 OneOrManyWithParensIntoIterInner::One(one) => one.next_back(),
1595 OneOrManyWithParensIntoIterInner::Many(many) => many.next_back(),
1596 }
1597 }
1598}
1599
1600impl<T> IntoIterator for OneOrManyWithParens<T> {
1601 type Item = T;
1602
1603 type IntoIter = OneOrManyWithParensIntoIter<T>;
1604
1605 fn into_iter(self) -> Self::IntoIter {
1606 let inner = match self {
1607 OneOrManyWithParens::One(one) => {
1608 OneOrManyWithParensIntoIterInner::One(core::iter::once(one))
1609 }
1610 OneOrManyWithParens::Many(many) => {
1611 OneOrManyWithParensIntoIterInner::Many(many.into_iter())
1612 }
1613 };
1614
1615 OneOrManyWithParensIntoIter { inner }
1616 }
1617}
1618
1619impl<T> fmt::Display for OneOrManyWithParens<T>
1620where
1621 T: fmt::Display,
1622{
1623 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1624 match self {
1625 OneOrManyWithParens::One(value) => write!(f, "{value}"),
1626 OneOrManyWithParens::Many(values) => {
1627 write!(f, "({})", display_comma_separated(values))
1628 }
1629 }
1630 }
1631}
1632
1633impl fmt::Display for CastFormat {
1634 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1635 match self {
1636 CastFormat::Value(v) => write!(f, "{v}"),
1637 CastFormat::ValueAtTimeZone(v, tz) => write!(f, "{v} AT TIME ZONE {tz}"),
1638 }
1639 }
1640}
1641
1642impl fmt::Display for Expr {
1643 #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
1644 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1645 match self {
1646 Expr::Identifier(s) => write!(f, "{s}"),
1647 Expr::Wildcard(_) => f.write_str("*"),
1648 Expr::QualifiedWildcard(prefix, _) => write!(f, "{prefix}.*"),
1649 Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
1650 Expr::CompoundFieldAccess { root, access_chain } => {
1651 write!(f, "{root}")?;
1652 for field in access_chain {
1653 write!(f, "{field}")?;
1654 }
1655 Ok(())
1656 }
1657 Expr::IsTrue(ast) => write!(f, "{ast} IS TRUE"),
1658 Expr::IsNotTrue(ast) => write!(f, "{ast} IS NOT TRUE"),
1659 Expr::IsFalse(ast) => write!(f, "{ast} IS FALSE"),
1660 Expr::IsNotFalse(ast) => write!(f, "{ast} IS NOT FALSE"),
1661 Expr::IsNull(ast) => write!(f, "{ast} IS NULL"),
1662 Expr::IsNotNull(ast) => write!(f, "{ast} IS NOT NULL"),
1663 Expr::IsUnknown(ast) => write!(f, "{ast} IS UNKNOWN"),
1664 Expr::IsNotUnknown(ast) => write!(f, "{ast} IS NOT UNKNOWN"),
1665 Expr::InList {
1666 expr,
1667 list,
1668 negated,
1669 } => write!(
1670 f,
1671 "{} {}IN ({})",
1672 expr,
1673 if *negated { "NOT " } else { "" },
1674 display_comma_separated(list)
1675 ),
1676 Expr::InSubquery {
1677 expr,
1678 subquery,
1679 negated,
1680 } => write!(
1681 f,
1682 "{} {}IN ({})",
1683 expr,
1684 if *negated { "NOT " } else { "" },
1685 subquery
1686 ),
1687 Expr::InUnnest {
1688 expr,
1689 array_expr,
1690 negated,
1691 } => write!(
1692 f,
1693 "{} {}IN UNNEST({})",
1694 expr,
1695 if *negated { "NOT " } else { "" },
1696 array_expr
1697 ),
1698 Expr::Between {
1699 expr,
1700 negated,
1701 low,
1702 high,
1703 } => write!(
1704 f,
1705 "{} {}BETWEEN {} AND {}",
1706 expr,
1707 if *negated { "NOT " } else { "" },
1708 low,
1709 high
1710 ),
1711 Expr::BinaryOp { left, op, right } => write!(f, "{left} {op} {right}"),
1712 Expr::Like {
1713 negated,
1714 expr,
1715 pattern,
1716 escape_char,
1717 any,
1718 } => match escape_char {
1719 Some(ch) => write!(
1720 f,
1721 "{} {}LIKE {}{} ESCAPE {}",
1722 expr,
1723 if *negated { "NOT " } else { "" },
1724 if *any { "ANY " } else { "" },
1725 pattern,
1726 ch
1727 ),
1728 _ => write!(
1729 f,
1730 "{} {}LIKE {}{}",
1731 expr,
1732 if *negated { "NOT " } else { "" },
1733 if *any { "ANY " } else { "" },
1734 pattern
1735 ),
1736 },
1737 Expr::ILike {
1738 negated,
1739 expr,
1740 pattern,
1741 escape_char,
1742 any,
1743 } => match escape_char {
1744 Some(ch) => write!(
1745 f,
1746 "{} {}ILIKE {}{} ESCAPE {}",
1747 expr,
1748 if *negated { "NOT " } else { "" },
1749 if *any { "ANY" } else { "" },
1750 pattern,
1751 ch
1752 ),
1753 _ => write!(
1754 f,
1755 "{} {}ILIKE {}{}",
1756 expr,
1757 if *negated { "NOT " } else { "" },
1758 if *any { "ANY " } else { "" },
1759 pattern
1760 ),
1761 },
1762 Expr::RLike {
1763 negated,
1764 expr,
1765 pattern,
1766 regexp,
1767 } => write!(
1768 f,
1769 "{} {}{} {}",
1770 expr,
1771 if *negated { "NOT " } else { "" },
1772 if *regexp { "REGEXP" } else { "RLIKE" },
1773 pattern
1774 ),
1775 Expr::IsNormalized {
1776 expr,
1777 form,
1778 negated,
1779 } => {
1780 let not_ = if *negated { "NOT " } else { "" };
1781 if form.is_none() {
1782 write!(f, "{expr} IS {not_}NORMALIZED")
1783 } else {
1784 write!(
1785 f,
1786 "{} IS {}{} NORMALIZED",
1787 expr,
1788 not_,
1789 form.as_ref().unwrap()
1790 )
1791 }
1792 }
1793 Expr::SimilarTo {
1794 negated,
1795 expr,
1796 pattern,
1797 escape_char,
1798 } => match escape_char {
1799 Some(ch) => write!(
1800 f,
1801 "{} {}SIMILAR TO {} ESCAPE {}",
1802 expr,
1803 if *negated { "NOT " } else { "" },
1804 pattern,
1805 ch
1806 ),
1807 _ => write!(
1808 f,
1809 "{} {}SIMILAR TO {}",
1810 expr,
1811 if *negated { "NOT " } else { "" },
1812 pattern
1813 ),
1814 },
1815 Expr::AnyOp {
1816 left,
1817 compare_op,
1818 right,
1819 is_some,
1820 } => {
1821 let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1822 write!(
1823 f,
1824 "{left} {compare_op} {}{}{right}{}",
1825 if *is_some { "SOME" } else { "ANY" },
1826 if add_parens { "(" } else { "" },
1827 if add_parens { ")" } else { "" },
1828 )
1829 }
1830 Expr::AllOp {
1831 left,
1832 compare_op,
1833 right,
1834 } => {
1835 let add_parens = !matches!(right.as_ref(), Expr::Subquery(_));
1836 write!(
1837 f,
1838 "{left} {compare_op} ALL{}{right}{}",
1839 if add_parens { "(" } else { "" },
1840 if add_parens { ")" } else { "" },
1841 )
1842 }
1843 Expr::UnaryOp { op, expr } => {
1844 if op == &UnaryOperator::PGPostfixFactorial {
1845 write!(f, "{expr}{op}")
1846 } else if matches!(
1847 op,
1848 UnaryOperator::Not
1849 | UnaryOperator::Hash
1850 | UnaryOperator::AtDashAt
1851 | UnaryOperator::DoubleAt
1852 | UnaryOperator::QuestionDash
1853 | UnaryOperator::QuestionPipe
1854 ) {
1855 write!(f, "{op} {expr}")
1856 } else {
1857 write!(f, "{op}{expr}")
1858 }
1859 }
1860 Expr::Convert {
1861 is_try,
1862 expr,
1863 target_before_value,
1864 data_type,
1865 charset,
1866 styles,
1867 } => {
1868 write!(f, "{}CONVERT(", if *is_try { "TRY_" } else { "" })?;
1869 if let Some(data_type) = data_type {
1870 if let Some(charset) = charset {
1871 write!(f, "{expr}, {data_type} CHARACTER SET {charset}")
1872 } else if *target_before_value {
1873 write!(f, "{data_type}, {expr}")
1874 } else {
1875 write!(f, "{expr}, {data_type}")
1876 }
1877 } else if let Some(charset) = charset {
1878 write!(f, "{expr} USING {charset}")
1879 } else {
1880 write!(f, "{expr}") // This should never happen
1881 }?;
1882 if !styles.is_empty() {
1883 write!(f, ", {}", display_comma_separated(styles))?;
1884 }
1885 write!(f, ")")
1886 }
1887 Expr::Cast {
1888 kind,
1889 expr,
1890 data_type,
1891 array,
1892 format,
1893 } => match kind {
1894 CastKind::Cast => {
1895 write!(f, "CAST({expr} AS {data_type}")?;
1896 if *array {
1897 write!(f, " ARRAY")?;
1898 }
1899 if let Some(format) = format {
1900 write!(f, " FORMAT {format}")?;
1901 }
1902 write!(f, ")")
1903 }
1904 CastKind::TryCast => {
1905 if let Some(format) = format {
1906 write!(f, "TRY_CAST({expr} AS {data_type} FORMAT {format})")
1907 } else {
1908 write!(f, "TRY_CAST({expr} AS {data_type})")
1909 }
1910 }
1911 CastKind::SafeCast => {
1912 if let Some(format) = format {
1913 write!(f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})")
1914 } else {
1915 write!(f, "SAFE_CAST({expr} AS {data_type})")
1916 }
1917 }
1918 CastKind::DoubleColon => {
1919 write!(f, "{expr}::{data_type}")
1920 }
1921 },
1922 Expr::Extract {
1923 field,
1924 syntax,
1925 expr,
1926 } => match syntax {
1927 ExtractSyntax::From => write!(f, "EXTRACT({field} FROM {expr})"),
1928 ExtractSyntax::Comma => write!(f, "EXTRACT({field}, {expr})"),
1929 },
1930 Expr::Ceil { expr, field } => match field {
1931 CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1932 write!(f, "CEIL({expr})")
1933 }
1934 CeilFloorKind::DateTimeField(dt_field) => write!(f, "CEIL({expr} TO {dt_field})"),
1935 CeilFloorKind::Scale(s) => write!(f, "CEIL({expr}, {s})"),
1936 },
1937 Expr::Floor { expr, field } => match field {
1938 CeilFloorKind::DateTimeField(DateTimeField::NoDateTime) => {
1939 write!(f, "FLOOR({expr})")
1940 }
1941 CeilFloorKind::DateTimeField(dt_field) => write!(f, "FLOOR({expr} TO {dt_field})"),
1942 CeilFloorKind::Scale(s) => write!(f, "FLOOR({expr}, {s})"),
1943 },
1944 Expr::Position { expr, r#in } => write!(f, "POSITION({expr} IN {in})"),
1945 Expr::Collate { expr, collation } => write!(f, "{expr} COLLATE {collation}"),
1946 Expr::Nested(ast) => write!(f, "({ast})"),
1947 Expr::Value(v) => write!(f, "{v}"),
1948 Expr::Prefixed { prefix, value } => write!(f, "{prefix} {value}"),
1949 Expr::TypedString(ts) => ts.fmt(f),
1950 Expr::Function(fun) => fun.fmt(f),
1951 Expr::Case {
1952 case_token: _,
1953 end_token: _,
1954 operand,
1955 conditions,
1956 else_result,
1957 } => {
1958 f.write_str("CASE")?;
1959 if let Some(operand) = operand {
1960 f.write_str(" ")?;
1961 operand.fmt(f)?;
1962 }
1963 for when in conditions {
1964 SpaceOrNewline.fmt(f)?;
1965 Indent(when).fmt(f)?;
1966 }
1967 if let Some(else_result) = else_result {
1968 SpaceOrNewline.fmt(f)?;
1969 Indent("ELSE").fmt(f)?;
1970 SpaceOrNewline.fmt(f)?;
1971 Indent(Indent(else_result)).fmt(f)?;
1972 }
1973 SpaceOrNewline.fmt(f)?;
1974 f.write_str("END")
1975 }
1976 Expr::Exists { subquery, negated } => write!(
1977 f,
1978 "{}EXISTS ({})",
1979 if *negated { "NOT " } else { "" },
1980 subquery
1981 ),
1982 Expr::Subquery(s) => write!(f, "({s})"),
1983 Expr::GroupingSets(sets) => {
1984 write!(f, "GROUPING SETS (")?;
1985 let mut sep = "";
1986 for set in sets {
1987 write!(f, "{sep}")?;
1988 sep = ", ";
1989 write!(f, "({})", display_comma_separated(set))?;
1990 }
1991 write!(f, ")")
1992 }
1993 Expr::Cube(sets) => {
1994 write!(f, "CUBE (")?;
1995 let mut sep = "";
1996 for set in sets {
1997 write!(f, "{sep}")?;
1998 sep = ", ";
1999 if set.len() == 1 {
2000 write!(f, "{}", set[0])?;
2001 } else {
2002 write!(f, "({})", display_comma_separated(set))?;
2003 }
2004 }
2005 write!(f, ")")
2006 }
2007 Expr::Rollup(sets) => {
2008 write!(f, "ROLLUP (")?;
2009 let mut sep = "";
2010 for set in sets {
2011 write!(f, "{sep}")?;
2012 sep = ", ";
2013 if set.len() == 1 {
2014 write!(f, "{}", set[0])?;
2015 } else {
2016 write!(f, "({})", display_comma_separated(set))?;
2017 }
2018 }
2019 write!(f, ")")
2020 }
2021 Expr::Substring {
2022 expr,
2023 substring_from,
2024 substring_for,
2025 special,
2026 shorthand,
2027 } => {
2028 f.write_str("SUBSTR")?;
2029 if !*shorthand {
2030 f.write_str("ING")?;
2031 }
2032 write!(f, "({expr}")?;
2033 if let Some(from_part) = substring_from {
2034 if *special {
2035 write!(f, ", {from_part}")?;
2036 } else {
2037 write!(f, " FROM {from_part}")?;
2038 }
2039 }
2040 if let Some(for_part) = substring_for {
2041 if *special {
2042 write!(f, ", {for_part}")?;
2043 } else {
2044 write!(f, " FOR {for_part}")?;
2045 }
2046 }
2047
2048 write!(f, ")")
2049 }
2050 Expr::Overlay {
2051 expr,
2052 overlay_what,
2053 overlay_from,
2054 overlay_for,
2055 } => {
2056 write!(
2057 f,
2058 "OVERLAY({expr} PLACING {overlay_what} FROM {overlay_from}"
2059 )?;
2060 if let Some(for_part) = overlay_for {
2061 write!(f, " FOR {for_part}")?;
2062 }
2063
2064 write!(f, ")")
2065 }
2066 Expr::IsDistinctFrom(a, b) => write!(f, "{a} IS DISTINCT FROM {b}"),
2067 Expr::IsNotDistinctFrom(a, b) => write!(f, "{a} IS NOT DISTINCT FROM {b}"),
2068 Expr::Trim {
2069 expr,
2070 trim_where,
2071 trim_what,
2072 trim_characters,
2073 } => {
2074 write!(f, "TRIM(")?;
2075 if let Some(ident) = trim_where {
2076 write!(f, "{ident} ")?;
2077 }
2078 if let Some(trim_char) = trim_what {
2079 write!(f, "{trim_char} FROM {expr}")?;
2080 } else {
2081 write!(f, "{expr}")?;
2082 }
2083 if let Some(characters) = trim_characters {
2084 write!(f, ", {}", display_comma_separated(characters))?;
2085 }
2086
2087 write!(f, ")")
2088 }
2089 Expr::Tuple(exprs) => {
2090 write!(f, "({})", display_comma_separated(exprs))
2091 }
2092 Expr::Struct { values, fields } => {
2093 if !fields.is_empty() {
2094 write!(
2095 f,
2096 "STRUCT<{}>({})",
2097 display_comma_separated(fields),
2098 display_comma_separated(values)
2099 )
2100 } else {
2101 write!(f, "STRUCT({})", display_comma_separated(values))
2102 }
2103 }
2104 Expr::Named { expr, name } => {
2105 write!(f, "{expr} AS {name}")
2106 }
2107 Expr::Dictionary(fields) => {
2108 write!(f, "{{{}}}", display_comma_separated(fields))
2109 }
2110 Expr::Map(map) => {
2111 write!(f, "{map}")
2112 }
2113 Expr::Array(set) => {
2114 write!(f, "{set}")
2115 }
2116 Expr::JsonAccess { value, path } => {
2117 write!(f, "{value}{path}")
2118 }
2119 Expr::AtTimeZone {
2120 timestamp,
2121 time_zone,
2122 } => {
2123 write!(f, "{timestamp} AT TIME ZONE {time_zone}")
2124 }
2125 Expr::Interval(interval) => {
2126 write!(f, "{interval}")
2127 }
2128 Expr::MatchAgainst {
2129 columns,
2130 match_value: match_expr,
2131 opt_search_modifier,
2132 } => {
2133 write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
2134
2135 if let Some(search_modifier) = opt_search_modifier {
2136 write!(f, "({match_expr} {search_modifier})")?;
2137 } else {
2138 write!(f, "({match_expr})")?;
2139 }
2140
2141 Ok(())
2142 }
2143 Expr::OuterJoin(expr) => {
2144 write!(f, "{expr} (+)")
2145 }
2146 Expr::Prior(expr) => write!(f, "PRIOR {expr}"),
2147 Expr::Lambda(lambda) => write!(f, "{lambda}"),
2148 Expr::MemberOf(member_of) => write!(f, "{member_of}"),
2149 }
2150 }
2151}
2152
2153/// The type of a window used in `OVER` clauses.
2154///
2155/// A window can be either an inline specification (`WindowSpec`) or a
2156/// reference to a previously defined named window.
2157///
2158/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g.
2159/// `OVER (PARTITION BY ... ORDER BY ...)`.
2160/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere.
2161#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2162#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2163#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2164pub enum WindowType {
2165 /// An inline window specification.
2166 WindowSpec(WindowSpec),
2167 /// A reference to a previously defined named window.
2168 NamedWindow(Ident),
2169}
2170
2171impl Display for WindowType {
2172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2173 match self {
2174 WindowType::WindowSpec(spec) => {
2175 f.write_str("(")?;
2176 NewLine.fmt(f)?;
2177 Indent(spec).fmt(f)?;
2178 NewLine.fmt(f)?;
2179 f.write_str(")")
2180 }
2181 WindowType::NamedWindow(name) => name.fmt(f),
2182 }
2183 }
2184}
2185
2186/// A window specification (i.e. `OVER ([window_name] PARTITION BY .. ORDER BY .. etc.)`)
2187#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2188#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2189#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2190pub struct WindowSpec {
2191 /// Optional window name.
2192 ///
2193 /// You can find it at least in [MySQL][1], [BigQuery][2], [PostgreSQL][3]
2194 ///
2195 /// [1]: https://dev.mysql.com/doc/refman/8.0/en/window-functions-named-windows.html
2196 /// [2]: https://cloud.google.com/bigquery/docs/reference/standard-sql/window-function-calls
2197 /// [3]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS
2198 pub window_name: Option<Ident>,
2199 /// `OVER (PARTITION BY ...)`
2200 pub partition_by: Vec<Expr>,
2201 /// `OVER (ORDER BY ...)`
2202 pub order_by: Vec<OrderByExpr>,
2203 /// `OVER (window frame)`
2204 pub window_frame: Option<WindowFrame>,
2205}
2206
2207impl fmt::Display for WindowSpec {
2208 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2209 let mut is_first = true;
2210 if let Some(window_name) = &self.window_name {
2211 if !is_first {
2212 SpaceOrNewline.fmt(f)?;
2213 }
2214 is_first = false;
2215 write!(f, "{window_name}")?;
2216 }
2217 if !self.partition_by.is_empty() {
2218 if !is_first {
2219 SpaceOrNewline.fmt(f)?;
2220 }
2221 is_first = false;
2222 write!(
2223 f,
2224 "PARTITION BY {}",
2225 display_comma_separated(&self.partition_by)
2226 )?;
2227 }
2228 if !self.order_by.is_empty() {
2229 if !is_first {
2230 SpaceOrNewline.fmt(f)?;
2231 }
2232 is_first = false;
2233 write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
2234 }
2235 if let Some(window_frame) = &self.window_frame {
2236 if !is_first {
2237 SpaceOrNewline.fmt(f)?;
2238 }
2239 if let Some(end_bound) = &window_frame.end_bound {
2240 write!(
2241 f,
2242 "{} BETWEEN {} AND {}",
2243 window_frame.units, window_frame.start_bound, end_bound
2244 )?;
2245 } else {
2246 write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
2247 }
2248 }
2249 Ok(())
2250 }
2251}
2252
2253/// Specifies the data processed by a window function, e.g.
2254/// `RANGE UNBOUNDED PRECEDING` or `ROWS BETWEEN 5 PRECEDING AND CURRENT ROW`.
2255///
2256/// Note: The parser does not validate the specified bounds; the caller should
2257/// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution.
2258#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2259#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2260#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2261pub struct WindowFrame {
2262 /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`).
2263 pub units: WindowFrameUnits,
2264 /// The start bound of the window frame.
2265 pub start_bound: WindowFrameBound,
2266 /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None`
2267 /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must
2268 /// behave the same as `end_bound = WindowFrameBound::CurrentRow`.
2269 pub end_bound: Option<WindowFrameBound>,
2270 // TBD: EXCLUDE
2271}
2272
2273impl Default for WindowFrame {
2274 /// Returns default value for window frame
2275 ///
2276 /// See [this page](https://www.sqlite.org/windowfunctions.html#frame_specifications) for more details.
2277 fn default() -> Self {
2278 Self {
2279 units: WindowFrameUnits::Range,
2280 start_bound: WindowFrameBound::Preceding(None),
2281 end_bound: None,
2282 }
2283 }
2284}
2285
2286#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2287#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2288#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2289/// Units used to describe the window frame scope.
2290pub enum WindowFrameUnits {
2291 /// `ROWS` unit.
2292 Rows,
2293 /// `RANGE` unit.
2294 Range,
2295 /// `GROUPS` unit.
2296 Groups,
2297}
2298
2299impl fmt::Display for WindowFrameUnits {
2300 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2301 f.write_str(match self {
2302 WindowFrameUnits::Rows => "ROWS",
2303 WindowFrameUnits::Range => "RANGE",
2304 WindowFrameUnits::Groups => "GROUPS",
2305 })
2306 }
2307}
2308
2309/// Specifies Ignore / Respect NULL within window functions.
2310/// For example
2311/// `FIRST_VALUE(column2) IGNORE NULLS OVER (PARTITION BY column1)`
2312#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2313#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2314#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2315/// How NULL values are treated in certain window functions.
2316pub enum NullTreatment {
2317 /// Ignore NULL values (e.g. `IGNORE NULLS`).
2318 IgnoreNulls,
2319 /// Respect NULL values (e.g. `RESPECT NULLS`).
2320 RespectNulls,
2321}
2322
2323impl fmt::Display for NullTreatment {
2324 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2325 f.write_str(match self {
2326 NullTreatment::IgnoreNulls => "IGNORE NULLS",
2327 NullTreatment::RespectNulls => "RESPECT NULLS",
2328 })
2329 }
2330}
2331
2332/// Specifies [WindowFrame]'s `start_bound` and `end_bound`
2333#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2334#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2335#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2336pub enum WindowFrameBound {
2337 /// `CURRENT ROW`
2338 CurrentRow,
2339 /// `<N> PRECEDING` or `UNBOUNDED PRECEDING`
2340 Preceding(Option<Box<Expr>>),
2341 /// `<N> FOLLOWING` or `UNBOUNDED FOLLOWING`.
2342 Following(Option<Box<Expr>>),
2343}
2344
2345impl fmt::Display for WindowFrameBound {
2346 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2347 match self {
2348 WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
2349 WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
2350 WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
2351 WindowFrameBound::Preceding(Some(n)) => write!(f, "{n} PRECEDING"),
2352 WindowFrameBound::Following(Some(n)) => write!(f, "{n} FOLLOWING"),
2353 }
2354 }
2355}
2356
2357#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2359#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2360/// Indicates partition operation type for partition management statements.
2361pub enum AddDropSync {
2362 /// Add partitions.
2363 ADD,
2364 /// Drop partitions.
2365 DROP,
2366 /// Sync partitions.
2367 SYNC,
2368}
2369
2370impl fmt::Display for AddDropSync {
2371 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2372 match self {
2373 AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
2374 AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
2375 AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
2376 }
2377 }
2378}
2379
2380#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2381#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2382#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2383/// Object kinds supported by `SHOW CREATE` statements.
2384pub enum ShowCreateObject {
2385 /// An event object for `SHOW CREATE EVENT`.
2386 Event,
2387 /// A function object for `SHOW CREATE FUNCTION`.
2388 Function,
2389 /// A procedure object for `SHOW CREATE PROCEDURE`.
2390 Procedure,
2391 /// A table object for `SHOW CREATE TABLE`.
2392 Table,
2393 /// A trigger object for `SHOW CREATE TRIGGER`.
2394 Trigger,
2395 /// A view object for `SHOW CREATE VIEW`.
2396 View,
2397}
2398
2399impl fmt::Display for ShowCreateObject {
2400 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2401 match self {
2402 ShowCreateObject::Event => f.write_str("EVENT"),
2403 ShowCreateObject::Function => f.write_str("FUNCTION"),
2404 ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
2405 ShowCreateObject::Table => f.write_str("TABLE"),
2406 ShowCreateObject::Trigger => f.write_str("TRIGGER"),
2407 ShowCreateObject::View => f.write_str("VIEW"),
2408 }
2409 }
2410}
2411
2412#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2413#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2414#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2415/// Objects that can be targeted by a `COMMENT` statement.
2416pub enum CommentObject {
2417 /// A table column.
2418 Column,
2419 /// A table.
2420 Table,
2421 /// An extension.
2422 Extension,
2423 /// A schema.
2424 Schema,
2425 /// A database.
2426 Database,
2427 /// A user.
2428 User,
2429 /// A role.
2430 Role,
2431}
2432
2433impl fmt::Display for CommentObject {
2434 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2435 match self {
2436 CommentObject::Column => f.write_str("COLUMN"),
2437 CommentObject::Table => f.write_str("TABLE"),
2438 CommentObject::Extension => f.write_str("EXTENSION"),
2439 CommentObject::Schema => f.write_str("SCHEMA"),
2440 CommentObject::Database => f.write_str("DATABASE"),
2441 CommentObject::User => f.write_str("USER"),
2442 CommentObject::Role => f.write_str("ROLE"),
2443 }
2444 }
2445}
2446
2447#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2448#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2449#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2450/// Password specification variants used in user-related statements.
2451pub enum Password {
2452 /// A concrete password expression.
2453 Password(Expr),
2454 /// Represents a `NULL` password.
2455 NullPassword,
2456}
2457
2458/// A `CASE` statement.
2459///
2460/// Examples:
2461/// ```sql
2462/// CASE
2463/// WHEN EXISTS(SELECT 1)
2464/// THEN SELECT 1 FROM T;
2465/// WHEN EXISTS(SELECT 2)
2466/// THEN SELECT 1 FROM U;
2467/// ELSE
2468/// SELECT 1 FROM V;
2469/// END CASE;
2470/// ```
2471///
2472/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2473/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2474#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2475#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2476#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2477pub struct CaseStatement {
2478 /// The `CASE` token that starts the statement.
2479 pub case_token: AttachedToken,
2480 /// Optional expression to match against in `CASE ... WHEN`.
2481 pub match_expr: Option<Expr>,
2482 /// The `WHEN ... THEN` blocks of the `CASE` statement.
2483 pub when_blocks: Vec<ConditionalStatementBlock>,
2484 /// Optional `ELSE` block for the `CASE` statement.
2485 pub else_block: Option<ConditionalStatementBlock>,
2486 /// The last token of the statement (`END` or `CASE`).
2487 pub end_case_token: AttachedToken,
2488}
2489
2490impl fmt::Display for CaseStatement {
2491 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2492 let CaseStatement {
2493 case_token: _,
2494 match_expr,
2495 when_blocks,
2496 else_block,
2497 end_case_token: AttachedToken(end),
2498 } = self;
2499
2500 write!(f, "CASE")?;
2501
2502 if let Some(expr) = match_expr {
2503 write!(f, " {expr}")?;
2504 }
2505
2506 if !when_blocks.is_empty() {
2507 write!(f, " {}", display_separated(when_blocks, " "))?;
2508 }
2509
2510 if let Some(else_block) = else_block {
2511 write!(f, " {else_block}")?;
2512 }
2513
2514 write!(f, " END")?;
2515
2516 if let Token::Word(w) = &end.token {
2517 if w.keyword == Keyword::CASE {
2518 write!(f, " CASE")?;
2519 }
2520 }
2521
2522 Ok(())
2523 }
2524}
2525
2526/// An `IF` statement.
2527///
2528/// Example (BigQuery or Snowflake):
2529/// ```sql
2530/// IF TRUE THEN
2531/// SELECT 1;
2532/// SELECT 2;
2533/// ELSEIF TRUE THEN
2534/// SELECT 3;
2535/// ELSE
2536/// SELECT 4;
2537/// END IF
2538/// ```
2539/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2540/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2541///
2542/// Example (MSSQL):
2543/// ```sql
2544/// IF 1=1 SELECT 1 ELSE SELECT 2
2545/// ```
2546/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2547#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2548#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2549#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2550pub struct IfStatement {
2551 /// The initial `IF` block containing the condition and statements.
2552 pub if_block: ConditionalStatementBlock,
2553 /// Additional `ELSEIF` blocks.
2554 pub elseif_blocks: Vec<ConditionalStatementBlock>,
2555 /// Optional `ELSE` block.
2556 pub else_block: Option<ConditionalStatementBlock>,
2557 /// Optional trailing `END` token for the `IF` statement.
2558 pub end_token: Option<AttachedToken>,
2559}
2560
2561impl fmt::Display for IfStatement {
2562 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2563 let IfStatement {
2564 if_block,
2565 elseif_blocks,
2566 else_block,
2567 end_token,
2568 } = self;
2569
2570 write!(f, "{if_block}")?;
2571
2572 for elseif_block in elseif_blocks {
2573 write!(f, " {elseif_block}")?;
2574 }
2575
2576 if let Some(else_block) = else_block {
2577 write!(f, " {else_block}")?;
2578 }
2579
2580 if let Some(AttachedToken(end_token)) = end_token {
2581 write!(f, " END {end_token}")?;
2582 }
2583
2584 Ok(())
2585 }
2586}
2587
2588/// A `WHILE` statement.
2589///
2590/// Example:
2591/// ```sql
2592/// WHILE @@FETCH_STATUS = 0
2593/// BEGIN
2594/// FETCH NEXT FROM c1 INTO @var1, @var2;
2595/// END
2596/// ```
2597///
2598/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql)
2599#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2600#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2601#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2602pub struct WhileStatement {
2603 /// Block executed while the condition holds.
2604 pub while_block: ConditionalStatementBlock,
2605}
2606
2607impl fmt::Display for WhileStatement {
2608 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2609 let WhileStatement { while_block } = self;
2610 write!(f, "{while_block}")?;
2611 Ok(())
2612 }
2613}
2614
2615/// A block within a [Statement::Case] or [Statement::If] or [Statement::While]-like statement
2616///
2617/// Example 1:
2618/// ```sql
2619/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2620/// ```
2621///
2622/// Example 2:
2623/// ```sql
2624/// IF TRUE THEN SELECT 1; SELECT 2;
2625/// ```
2626///
2627/// Example 3:
2628/// ```sql
2629/// ELSE SELECT 1; SELECT 2;
2630/// ```
2631///
2632/// Example 4:
2633/// ```sql
2634/// WHILE @@FETCH_STATUS = 0
2635/// BEGIN
2636/// FETCH NEXT FROM c1 INTO @var1, @var2;
2637/// END
2638/// ```
2639#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2640#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2641#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2642pub struct ConditionalStatementBlock {
2643 /// Token representing the start of the block (e.g., WHEN/IF/WHILE).
2644 pub start_token: AttachedToken,
2645 /// Optional condition expression for the block.
2646 pub condition: Option<Expr>,
2647 /// Optional token for the `THEN` keyword.
2648 pub then_token: Option<AttachedToken>,
2649 /// The statements contained in this conditional block.
2650 pub conditional_statements: ConditionalStatements,
2651}
2652
2653impl ConditionalStatementBlock {
2654 /// Get the statements in this conditional block.
2655 pub fn statements(&self) -> &Vec<Statement> {
2656 self.conditional_statements.statements()
2657 }
2658}
2659
2660impl fmt::Display for ConditionalStatementBlock {
2661 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2662 let ConditionalStatementBlock {
2663 start_token: AttachedToken(start_token),
2664 condition,
2665 then_token,
2666 conditional_statements,
2667 } = self;
2668
2669 write!(f, "{start_token}")?;
2670
2671 if let Some(condition) = condition {
2672 write!(f, " {condition}")?;
2673 }
2674
2675 if then_token.is_some() {
2676 write!(f, " THEN")?;
2677 }
2678
2679 if !conditional_statements.statements().is_empty() {
2680 write!(f, " {conditional_statements}")?;
2681 }
2682
2683 Ok(())
2684 }
2685}
2686
2687/// A list of statements in a [ConditionalStatementBlock].
2688#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2689#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2690#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2691/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`).
2692pub enum ConditionalStatements {
2693 /// Simple sequence of statements (no `BEGIN`/`END`).
2694 Sequence {
2695 /// The statements in the sequence.
2696 statements: Vec<Statement>,
2697 },
2698 /// Block enclosed by `BEGIN` and `END`.
2699 BeginEnd(BeginEndStatements),
2700}
2701
2702impl ConditionalStatements {
2703 /// Get the statements in this conditional statements block.
2704 pub fn statements(&self) -> &Vec<Statement> {
2705 match self {
2706 ConditionalStatements::Sequence { statements } => statements,
2707 ConditionalStatements::BeginEnd(bes) => &bes.statements,
2708 }
2709 }
2710}
2711
2712impl fmt::Display for ConditionalStatements {
2713 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2714 match self {
2715 ConditionalStatements::Sequence { statements } => {
2716 if !statements.is_empty() {
2717 format_statement_list(f, statements)?;
2718 }
2719 Ok(())
2720 }
2721 ConditionalStatements::BeginEnd(bes) => write!(f, "{bes}"),
2722 }
2723 }
2724}
2725
2726/// Represents a list of statements enclosed within `BEGIN` and `END` keywords.
2727/// Example:
2728/// ```sql
2729/// BEGIN
2730/// SELECT 1;
2731/// SELECT 2;
2732/// END
2733/// ```
2734#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2735#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2736#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2737pub struct BeginEndStatements {
2738 /// Token representing the `BEGIN` keyword (may include span info).
2739 pub begin_token: AttachedToken,
2740 /// Statements contained within the block.
2741 pub statements: Vec<Statement>,
2742 /// Token representing the `END` keyword (may include span info).
2743 pub end_token: AttachedToken,
2744}
2745
2746impl fmt::Display for BeginEndStatements {
2747 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2748 let BeginEndStatements {
2749 begin_token: AttachedToken(begin_token),
2750 statements,
2751 end_token: AttachedToken(end_token),
2752 } = self;
2753
2754 if begin_token.token != Token::EOF {
2755 write!(f, "{begin_token} ")?;
2756 }
2757 if !statements.is_empty() {
2758 format_statement_list(f, statements)?;
2759 }
2760 if end_token.token != Token::EOF {
2761 write!(f, " {end_token}")?;
2762 }
2763 Ok(())
2764 }
2765}
2766
2767/// A `RAISE` statement.
2768///
2769/// Examples:
2770/// ```sql
2771/// RAISE USING MESSAGE = 'error';
2772///
2773/// RAISE myerror;
2774/// ```
2775///
2776/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
2777/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
2778#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2779#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2780#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2781pub struct RaiseStatement {
2782 /// Optional value provided to the RAISE statement.
2783 pub value: Option<RaiseStatementValue>,
2784}
2785
2786impl fmt::Display for RaiseStatement {
2787 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2788 let RaiseStatement { value } = self;
2789
2790 write!(f, "RAISE")?;
2791 if let Some(value) = value {
2792 write!(f, " {value}")?;
2793 }
2794
2795 Ok(())
2796 }
2797}
2798
2799/// Represents the error value of a [RaiseStatement].
2800#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2801#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2802#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2803pub enum RaiseStatementValue {
2804 /// `RAISE USING MESSAGE = 'error'`
2805 UsingMessage(Expr),
2806 /// `RAISE myerror`
2807 Expr(Expr),
2808}
2809
2810impl fmt::Display for RaiseStatementValue {
2811 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2812 match self {
2813 RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
2814 RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
2815 }
2816 }
2817}
2818
2819/// Represents an expression assignment within a variable `DECLARE` statement.
2820///
2821/// Examples:
2822/// ```sql
2823/// DECLARE variable_name := 42
2824/// DECLARE variable_name DEFAULT 42
2825/// ```
2826#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2827#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2828#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2829pub enum DeclareAssignment {
2830 /// Plain expression specified.
2831 Expr(Box<Expr>),
2832
2833 /// Expression assigned via the `DEFAULT` keyword
2834 Default(Box<Expr>),
2835
2836 /// Expression assigned via the `:=` syntax
2837 ///
2838 /// Example:
2839 /// ```sql
2840 /// DECLARE variable_name := 42;
2841 /// ```
2842 DuckAssignment(Box<Expr>),
2843
2844 /// Expression via the `FOR` keyword
2845 ///
2846 /// Example:
2847 /// ```sql
2848 /// DECLARE c1 CURSOR FOR res
2849 /// ```
2850 For(Box<Expr>),
2851
2852 /// Expression via the `=` syntax.
2853 ///
2854 /// Example:
2855 /// ```sql
2856 /// DECLARE @variable AS INT = 100
2857 /// ```
2858 MsSqlAssignment(Box<Expr>),
2859}
2860
2861impl fmt::Display for DeclareAssignment {
2862 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2863 match self {
2864 DeclareAssignment::Expr(expr) => {
2865 write!(f, "{expr}")
2866 }
2867 DeclareAssignment::Default(expr) => {
2868 write!(f, "DEFAULT {expr}")
2869 }
2870 DeclareAssignment::DuckAssignment(expr) => {
2871 write!(f, ":= {expr}")
2872 }
2873 DeclareAssignment::MsSqlAssignment(expr) => {
2874 write!(f, "= {expr}")
2875 }
2876 DeclareAssignment::For(expr) => {
2877 write!(f, "FOR {expr}")
2878 }
2879 }
2880 }
2881}
2882
2883/// Represents the type of a `DECLARE` statement.
2884#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2885#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2886#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2887pub enum DeclareType {
2888 /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
2889 ///
2890 /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
2891 /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
2892 /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
2893 Cursor,
2894
2895 /// Result set variable type. [Snowflake]
2896 ///
2897 /// Syntax:
2898 /// ```text
2899 /// <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
2900 /// ```
2901 /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#resultset-declaration-syntax
2902 ResultSet,
2903
2904 /// Exception declaration syntax. [Snowflake]
2905 ///
2906 /// Syntax:
2907 /// ```text
2908 /// <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
2909 /// ```
2910 /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare#exception-declaration-syntax
2911 Exception,
2912}
2913
2914impl fmt::Display for DeclareType {
2915 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2916 match self {
2917 DeclareType::Cursor => {
2918 write!(f, "CURSOR")
2919 }
2920 DeclareType::ResultSet => {
2921 write!(f, "RESULTSET")
2922 }
2923 DeclareType::Exception => {
2924 write!(f, "EXCEPTION")
2925 }
2926 }
2927 }
2928}
2929
2930/// A `DECLARE` statement.
2931/// [PostgreSQL] [Snowflake] [BigQuery]
2932///
2933/// Examples:
2934/// ```sql
2935/// DECLARE variable_name := 42
2936/// DECLARE liahona CURSOR FOR SELECT * FROM films;
2937/// ```
2938///
2939/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-declare.html
2940/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/snowflake-scripting/declare
2941/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#declare
2942#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2943#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2944#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2945pub struct Declare {
2946 /// The name(s) being declared.
2947 /// Example: `DECLARE a, b, c DEFAULT 42;
2948 pub names: Vec<Ident>,
2949 /// Data-type assigned to the declared variable.
2950 /// Example: `DECLARE x INT64 DEFAULT 42;
2951 pub data_type: Option<DataType>,
2952 /// Expression being assigned to the declared variable.
2953 pub assignment: Option<DeclareAssignment>,
2954 /// Represents the type of the declared variable.
2955 pub declare_type: Option<DeclareType>,
2956 /// Causes the cursor to return data in binary rather than in text format.
2957 pub binary: Option<bool>,
2958 /// None = Not specified
2959 /// Some(true) = INSENSITIVE
2960 /// Some(false) = ASENSITIVE
2961 pub sensitive: Option<bool>,
2962 /// None = Not specified
2963 /// Some(true) = SCROLL
2964 /// Some(false) = NO SCROLL
2965 pub scroll: Option<bool>,
2966 /// None = Not specified
2967 /// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
2968 /// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
2969 pub hold: Option<bool>,
2970 /// `FOR <query>` clause in a CURSOR declaration.
2971 pub for_query: Option<Box<Query>>,
2972}
2973
2974impl fmt::Display for Declare {
2975 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2976 let Declare {
2977 names,
2978 data_type,
2979 assignment,
2980 declare_type,
2981 binary,
2982 sensitive,
2983 scroll,
2984 hold,
2985 for_query,
2986 } = self;
2987 write!(f, "{}", display_comma_separated(names))?;
2988
2989 if let Some(true) = binary {
2990 write!(f, " BINARY")?;
2991 }
2992
2993 if let Some(sensitive) = sensitive {
2994 if *sensitive {
2995 write!(f, " INSENSITIVE")?;
2996 } else {
2997 write!(f, " ASENSITIVE")?;
2998 }
2999 }
3000
3001 if let Some(scroll) = scroll {
3002 if *scroll {
3003 write!(f, " SCROLL")?;
3004 } else {
3005 write!(f, " NO SCROLL")?;
3006 }
3007 }
3008
3009 if let Some(declare_type) = declare_type {
3010 write!(f, " {declare_type}")?;
3011 }
3012
3013 if let Some(hold) = hold {
3014 if *hold {
3015 write!(f, " WITH HOLD")?;
3016 } else {
3017 write!(f, " WITHOUT HOLD")?;
3018 }
3019 }
3020
3021 if let Some(query) = for_query {
3022 write!(f, " FOR {query}")?;
3023 }
3024
3025 if let Some(data_type) = data_type {
3026 write!(f, " {data_type}")?;
3027 }
3028
3029 if let Some(expr) = assignment {
3030 write!(f, " {expr}")?;
3031 }
3032 Ok(())
3033 }
3034}
3035
3036/// Sql options of a `CREATE TABLE` statement.
3037#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3038#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3039#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3040/// Options allowed within a `CREATE TABLE` statement.
3041pub enum CreateTableOptions {
3042 /// No options specified.
3043 #[default]
3044 None,
3045 /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`.
3046 With(Vec<SqlOption>),
3047 /// Options specified using the `OPTIONS(...)` clause.
3048 Options(Vec<SqlOption>),
3049 /// Plain space-separated options.
3050 Plain(Vec<SqlOption>),
3051 /// Table properties (e.g., TBLPROPERTIES / storage properties).
3052 TableProperties(Vec<SqlOption>),
3053}
3054
3055impl fmt::Display for CreateTableOptions {
3056 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3057 match self {
3058 CreateTableOptions::With(with_options) => {
3059 write!(f, "WITH ({})", display_comma_separated(with_options))
3060 }
3061 CreateTableOptions::Options(options) => {
3062 write!(f, "OPTIONS({})", display_comma_separated(options))
3063 }
3064 CreateTableOptions::TableProperties(options) => {
3065 write!(f, "TBLPROPERTIES ({})", display_comma_separated(options))
3066 }
3067 CreateTableOptions::Plain(options) => {
3068 write!(f, "{}", display_separated(options, " "))
3069 }
3070 CreateTableOptions::None => Ok(()),
3071 }
3072 }
3073}
3074
3075/// A `FROM` clause within a `DELETE` statement.
3076///
3077/// Syntax
3078/// ```sql
3079/// [FROM] table
3080/// ```
3081#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3082#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3083#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3084pub enum FromTable {
3085 /// An explicit `FROM` keyword was specified.
3086 WithFromKeyword(Vec<TableWithJoins>),
3087 /// BigQuery: `FROM` keyword was omitted.
3088 /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#delete_statement>
3089 WithoutKeyword(Vec<TableWithJoins>),
3090}
3091impl Display for FromTable {
3092 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3093 match self {
3094 FromTable::WithFromKeyword(tables) => {
3095 write!(f, "FROM {}", display_comma_separated(tables))
3096 }
3097 FromTable::WithoutKeyword(tables) => {
3098 write!(f, "{}", display_comma_separated(tables))
3099 }
3100 }
3101 }
3102}
3103
3104#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3105#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3106#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3107/// Variants for the `SET` family of statements.
3108pub enum Set {
3109 /// SQL Standard-style
3110 /// SET a = 1;
3111 /// `SET var = value` (standard SQL-style assignment).
3112 SingleAssignment {
3113 /// Optional scope modifier (`SESSION` / `LOCAL`).
3114 scope: Option<ContextModifier>,
3115 /// Whether this is a Hive-style `HIVEVAR:` assignment.
3116 hivevar: bool,
3117 /// Variable name to assign.
3118 variable: ObjectName,
3119 /// Values assigned to the variable.
3120 values: Vec<Expr>,
3121 },
3122 /// Snowflake-style
3123 /// SET (a, b, ..) = (1, 2, ..);
3124 /// `SET (a, b) = (1, 2)` (tuple assignment syntax).
3125 ParenthesizedAssignments {
3126 /// Variables being assigned in tuple form.
3127 variables: Vec<ObjectName>,
3128 /// Corresponding values for the variables.
3129 values: Vec<Expr>,
3130 },
3131 /// MySQL-style
3132 /// SET a = 1, b = 2, ..;
3133 /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments).
3134 MultipleAssignments {
3135 /// List of `SET` assignments (MySQL-style comma-separated).
3136 assignments: Vec<SetAssignment>,
3137 },
3138 /// Session authorization for Postgres/Redshift
3139 ///
3140 /// ```sql
3141 /// SET SESSION AUTHORIZATION { user_name | DEFAULT }
3142 /// ```
3143 ///
3144 /// See <https://www.postgresql.org/docs/current/sql-set-session-authorization.html>
3145 /// See <https://docs.aws.amazon.com/redshift/latest/dg/r_SET_SESSION_AUTHORIZATION.html>
3146 SetSessionAuthorization(SetSessionAuthorizationParam),
3147 /// MS-SQL session
3148 ///
3149 /// See <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-statements-transact-sql>
3150 SetSessionParam(SetSessionParamKind),
3151 /// ```sql
3152 /// SET [ SESSION | LOCAL ] ROLE role_name
3153 /// ```
3154 ///
3155 /// Sets session state. Examples: [ANSI][1], [Postgresql][2], [MySQL][3], and [Oracle][4]
3156 ///
3157 /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#set-role-statement
3158 /// [2]: https://www.postgresql.org/docs/14/sql-set-role.html
3159 /// [3]: https://dev.mysql.com/doc/refman/8.0/en/set-role.html
3160 /// [4]: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10004.htm
3161 SetRole {
3162 /// Non-ANSI optional identifier to inform if the role is defined inside the current session (`SESSION`) or transaction (`LOCAL`).
3163 context_modifier: Option<ContextModifier>,
3164 /// Role name. If NONE is specified, then the current role name is removed.
3165 role_name: Option<Ident>,
3166 },
3167 /// ```sql
3168 /// SET TIME ZONE <value>
3169 /// ```
3170 ///
3171 /// Note: this is a PostgreSQL-specific statements
3172 /// `SET TIME ZONE <value>` is an alias for `SET timezone TO <value>` in PostgreSQL
3173 /// However, we allow it for all dialects.
3174 /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword.
3175 /// `SET TIME ZONE <value>` statement.
3176 SetTimeZone {
3177 /// Whether the `LOCAL` keyword was specified.
3178 local: bool,
3179 /// Time zone expression value.
3180 value: Expr,
3181 },
3182 /// ```sql
3183 /// SET NAMES 'charset_name' [COLLATE 'collation_name']
3184 /// ```
3185 SetNames {
3186 /// Character set name to set.
3187 charset_name: Ident,
3188 /// Optional collation name.
3189 collation_name: Option<String>,
3190 },
3191 /// ```sql
3192 /// SET NAMES DEFAULT
3193 /// ```
3194 ///
3195 /// Note: this is a MySQL-specific statement.
3196 SetNamesDefault {},
3197 /// ```sql
3198 /// SET TRANSACTION ...
3199 /// ```
3200 SetTransaction {
3201 /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY).
3202 modes: Vec<TransactionMode>,
3203 /// Optional snapshot value for transaction snapshot control.
3204 snapshot: Option<Value>,
3205 /// `true` when the `SESSION` keyword was used.
3206 session: bool,
3207 },
3208}
3209
3210impl Display for Set {
3211 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3212 match self {
3213 Self::ParenthesizedAssignments { variables, values } => write!(
3214 f,
3215 "SET ({}) = ({})",
3216 display_comma_separated(variables),
3217 display_comma_separated(values)
3218 ),
3219 Self::MultipleAssignments { assignments } => {
3220 write!(f, "SET {}", display_comma_separated(assignments))
3221 }
3222 Self::SetRole {
3223 context_modifier,
3224 role_name,
3225 } => {
3226 let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
3227 write!(
3228 f,
3229 "SET {modifier}ROLE {role_name}",
3230 modifier = context_modifier.map(|m| format!("{m}")).unwrap_or_default()
3231 )
3232 }
3233 Self::SetSessionAuthorization(kind) => write!(f, "SET SESSION AUTHORIZATION {kind}"),
3234 Self::SetSessionParam(kind) => write!(f, "SET {kind}"),
3235 Self::SetTransaction {
3236 modes,
3237 snapshot,
3238 session,
3239 } => {
3240 if *session {
3241 write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
3242 } else {
3243 write!(f, "SET TRANSACTION")?;
3244 }
3245 if !modes.is_empty() {
3246 write!(f, " {}", display_comma_separated(modes))?;
3247 }
3248 if let Some(snapshot_id) = snapshot {
3249 write!(f, " SNAPSHOT {snapshot_id}")?;
3250 }
3251 Ok(())
3252 }
3253 Self::SetTimeZone { local, value } => {
3254 f.write_str("SET ")?;
3255 if *local {
3256 f.write_str("LOCAL ")?;
3257 }
3258 write!(f, "TIME ZONE {value}")
3259 }
3260 Self::SetNames {
3261 charset_name,
3262 collation_name,
3263 } => {
3264 write!(f, "SET NAMES {charset_name}")?;
3265
3266 if let Some(collation) = collation_name {
3267 f.write_str(" COLLATE ")?;
3268 f.write_str(collation)?;
3269 };
3270
3271 Ok(())
3272 }
3273 Self::SetNamesDefault {} => {
3274 f.write_str("SET NAMES DEFAULT")?;
3275
3276 Ok(())
3277 }
3278 Set::SingleAssignment {
3279 scope,
3280 hivevar,
3281 variable,
3282 values,
3283 } => {
3284 write!(
3285 f,
3286 "SET {}{}{} = {}",
3287 scope.map(|s| format!("{s}")).unwrap_or_default(),
3288 if *hivevar { "HIVEVAR:" } else { "" },
3289 variable,
3290 display_comma_separated(values)
3291 )
3292 }
3293 }
3294 }
3295}
3296
3297/// A representation of a `WHEN` arm with all the identifiers catched and the statements to execute
3298/// for the arm.
3299///
3300/// Snowflake: <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
3301/// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
3302#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3303#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3304#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3305pub struct ExceptionWhen {
3306 /// Identifiers that trigger this branch (error conditions).
3307 pub idents: Vec<Ident>,
3308 /// Statements to execute when the condition matches.
3309 pub statements: Vec<Statement>,
3310}
3311
3312impl Display for ExceptionWhen {
3313 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3314 write!(
3315 f,
3316 "WHEN {idents} THEN",
3317 idents = display_separated(&self.idents, " OR ")
3318 )?;
3319
3320 if !self.statements.is_empty() {
3321 write!(f, " ")?;
3322 format_statement_list(f, &self.statements)?;
3323 }
3324
3325 Ok(())
3326 }
3327}
3328
3329/// ANALYZE statement
3330///
3331/// Supported syntax varies by dialect:
3332/// - Hive: `ANALYZE TABLE t [PARTITION (...)] COMPUTE STATISTICS [NOSCAN] [FOR COLUMNS [col1, ...]] [CACHE METADATA]`
3333/// - PostgreSQL: `ANALYZE [VERBOSE] [t [(col1, ...)]]` See <https://www.postgresql.org/docs/current/sql-analyze.html>
3334/// - General: `ANALYZE [TABLE] t`
3335#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3336#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3337#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3338pub struct Analyze {
3339 #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3340 /// Name of the table to analyze. `None` for bare `ANALYZE`.
3341 pub table_name: Option<ObjectName>,
3342 /// Optional partition expressions to restrict the analysis.
3343 pub partitions: Option<Vec<Expr>>,
3344 /// `true` when analyzing specific columns (Hive `FOR COLUMNS` syntax).
3345 pub for_columns: bool,
3346 /// Columns to analyze.
3347 pub columns: Vec<Ident>,
3348 /// Whether to cache metadata before analyzing.
3349 pub cache_metadata: bool,
3350 /// Whether to skip scanning the table.
3351 pub noscan: bool,
3352 /// Whether to compute statistics during analysis.
3353 pub compute_statistics: bool,
3354 /// Whether the `TABLE` keyword was present.
3355 pub has_table_keyword: bool,
3356}
3357
3358impl fmt::Display for Analyze {
3359 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3360 write!(f, "ANALYZE")?;
3361 if let Some(ref table_name) = self.table_name {
3362 if self.has_table_keyword {
3363 write!(f, " TABLE")?;
3364 }
3365 write!(f, " {table_name}")?;
3366 }
3367 if !self.for_columns && !self.columns.is_empty() {
3368 write!(f, " ({})", display_comma_separated(&self.columns))?;
3369 }
3370 if let Some(ref parts) = self.partitions {
3371 if !parts.is_empty() {
3372 write!(f, " PARTITION ({})", display_comma_separated(parts))?;
3373 }
3374 }
3375 if self.compute_statistics {
3376 write!(f, " COMPUTE STATISTICS")?;
3377 }
3378 if self.noscan {
3379 write!(f, " NOSCAN")?;
3380 }
3381 if self.cache_metadata {
3382 write!(f, " CACHE METADATA")?;
3383 }
3384 if self.for_columns {
3385 write!(f, " FOR COLUMNS")?;
3386 if !self.columns.is_empty() {
3387 write!(f, " {}", display_comma_separated(&self.columns))?;
3388 }
3389 }
3390 Ok(())
3391 }
3392}
3393
3394/// A top-level statement (SELECT, INSERT, CREATE, etc.)
3395#[allow(clippy::large_enum_variant)]
3396#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3397#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3398#[cfg_attr(
3399 feature = "visitor",
3400 derive(Visit, VisitMut),
3401 visit(with = "visit_statement")
3402)]
3403pub enum Statement {
3404 /// ```sql
3405 /// ANALYZE
3406 /// ```
3407 /// Analyze (Hive)
3408 Analyze(Analyze),
3409 /// `SET` statements (session, transaction, timezone, etc.).
3410 Set(Set),
3411 /// ```sql
3412 /// TRUNCATE
3413 /// ```
3414 /// Truncate (Hive)
3415 Truncate(Truncate),
3416 /// ```sql
3417 /// MSCK
3418 /// ```
3419 /// Msck (Hive)
3420 Msck(Msck),
3421 /// ```sql
3422 /// SELECT
3423 /// ```
3424 Query(Box<Query>),
3425 /// ```sql
3426 /// INSERT
3427 /// ```
3428 Insert(Insert),
3429 /// ```sql
3430 /// INSTALL
3431 /// ```
3432 Install {
3433 /// Only for DuckDB
3434 extension_name: Ident,
3435 },
3436 /// ```sql
3437 /// LOAD
3438 /// ```
3439 Load {
3440 /// Only for DuckDB
3441 extension_name: Ident,
3442 },
3443 // TODO: Support ROW FORMAT
3444 /// LOAD DATA from a directory or query source.
3445 Directory {
3446 /// Whether to overwrite existing files.
3447 overwrite: bool,
3448 /// Whether the directory is local to the server.
3449 local: bool,
3450 /// Path to the directory or files.
3451 path: String,
3452 /// Optional file format for the data.
3453 file_format: Option<FileFormat>,
3454 /// Source query providing data to load.
3455 source: Box<Query>,
3456 },
3457 /// A `CASE` statement.
3458 Case(CaseStatement),
3459 /// An `IF` statement.
3460 If(IfStatement),
3461 /// A `WHILE` statement.
3462 While(WhileStatement),
3463 /// A `RAISE` statement.
3464 Raise(RaiseStatement),
3465 /// ```sql
3466 /// CALL <function>
3467 /// ```
3468 Call(Function),
3469 /// ```sql
3470 /// COPY [TO | FROM] ...
3471 /// ```
3472 Copy {
3473 /// The source of 'COPY TO', or the target of 'COPY FROM'
3474 source: CopySource,
3475 /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
3476 to: bool,
3477 /// The target of 'COPY TO', or the source of 'COPY FROM'
3478 target: CopyTarget,
3479 /// WITH options (from PostgreSQL version 9.0)
3480 options: Vec<CopyOption>,
3481 /// WITH options (before PostgreSQL version 9.0)
3482 legacy_options: Vec<CopyLegacyOption>,
3483 /// VALUES a vector of values to be copied
3484 values: Vec<Option<String>>,
3485 },
3486 /// ```sql
3487 /// COPY INTO <table> | <location>
3488 /// ```
3489 /// See:
3490 /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
3491 /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
3492 ///
3493 /// Copy Into syntax available for Snowflake is different than the one implemented in
3494 /// Postgres. Although they share common prefix, it is reasonable to implement them
3495 /// in different enums. This can be refactored later once custom dialects
3496 /// are allowed to have custom Statements.
3497 CopyIntoSnowflake {
3498 /// Kind of COPY INTO operation (table or location).
3499 kind: CopyIntoSnowflakeKind,
3500 /// Target object for the COPY INTO operation.
3501 into: ObjectName,
3502 /// Optional list of target columns.
3503 into_columns: Option<Vec<Ident>>,
3504 /// Optional source object name (staged data).
3505 from_obj: Option<ObjectName>,
3506 /// Optional alias for the source object.
3507 from_obj_alias: Option<Ident>,
3508 /// Stage-specific parameters (e.g., credentials, path).
3509 stage_params: StageParamsObject,
3510 /// Optional list of transformations applied when loading.
3511 from_transformations: Option<Vec<StageLoadSelectItemKind>>,
3512 /// Optional source query instead of a staged object.
3513 from_query: Option<Box<Query>>,
3514 /// Optional list of specific file names to load.
3515 files: Option<Vec<String>>,
3516 /// Optional filename matching pattern.
3517 pattern: Option<String>,
3518 /// File format options.
3519 file_format: KeyValueOptions,
3520 /// Additional copy options.
3521 copy_options: KeyValueOptions,
3522 /// Optional validation mode string.
3523 validation_mode: Option<String>,
3524 /// Optional partition expression for loading.
3525 partition: Option<Box<Expr>>,
3526 },
3527 /// ```sql
3528 /// OPEN cursor_name
3529 /// ```
3530 /// Opens a cursor.
3531 Open(OpenStatement),
3532 /// ```sql
3533 /// CLOSE
3534 /// ```
3535 /// Closes the portal underlying an open cursor.
3536 Close {
3537 /// Cursor name
3538 cursor: CloseCursor,
3539 },
3540 /// ```sql
3541 /// UPDATE
3542 /// ```
3543 Update(Update),
3544 /// ```sql
3545 /// DELETE
3546 /// ```
3547 Delete(Delete),
3548 /// ```sql
3549 /// CREATE VIEW
3550 /// ```
3551 CreateView(CreateView),
3552 /// ```sql
3553 /// CREATE TABLE
3554 /// ```
3555 CreateTable(CreateTable),
3556 /// ```sql
3557 /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
3558 /// ```
3559 /// Sqlite specific statement
3560 CreateVirtualTable {
3561 #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3562 /// Name of the virtual table module instance.
3563 name: ObjectName,
3564 /// `true` when `IF NOT EXISTS` was specified.
3565 if_not_exists: bool,
3566 /// Module name used by the virtual table.
3567 module_name: Ident,
3568 /// Arguments passed to the module.
3569 module_args: Vec<Ident>,
3570 },
3571 /// ```sql
3572 /// `CREATE INDEX`
3573 /// ```
3574 CreateIndex(CreateIndex),
3575 /// ```sql
3576 /// CREATE ROLE
3577 /// ```
3578 /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
3579 CreateRole(CreateRole),
3580 /// ```sql
3581 /// CREATE SECRET
3582 /// ```
3583 /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
3584 CreateSecret {
3585 /// `true` when `OR REPLACE` was specified.
3586 or_replace: bool,
3587 /// Optional `TEMPORARY` flag.
3588 temporary: Option<bool>,
3589 /// `true` when `IF NOT EXISTS` was present.
3590 if_not_exists: bool,
3591 /// Optional secret name.
3592 name: Option<Ident>,
3593 /// Optional storage specifier identifier.
3594 storage_specifier: Option<Ident>,
3595 /// The secret type identifier.
3596 secret_type: Ident,
3597 /// Additional secret options.
3598 options: Vec<SecretOption>,
3599 },
3600 /// A `CREATE SERVER` statement.
3601 CreateServer(CreateServerStatement),
3602 /// ```sql
3603 /// CREATE POLICY
3604 /// ```
3605 /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html)
3606 CreatePolicy(CreatePolicy),
3607 /// ```sql
3608 /// CREATE CONNECTOR
3609 /// ```
3610 /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-CreateDataConnectorCreateConnector)
3611 CreateConnector(CreateConnector),
3612 /// ```sql
3613 /// CREATE OPERATOR
3614 /// ```
3615 /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createoperator.html)
3616 CreateOperator(CreateOperator),
3617 /// ```sql
3618 /// CREATE OPERATOR FAMILY
3619 /// ```
3620 /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopfamily.html)
3621 CreateOperatorFamily(CreateOperatorFamily),
3622 /// ```sql
3623 /// CREATE OPERATOR CLASS
3624 /// ```
3625 /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
3626 CreateOperatorClass(CreateOperatorClass),
3627 /// ```sql
3628 /// ALTER TABLE
3629 /// ```
3630 AlterTable(AlterTable),
3631 /// ```sql
3632 /// ALTER SCHEMA
3633 /// ```
3634 /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3635 AlterSchema(AlterSchema),
3636 /// ```sql
3637 /// ALTER INDEX
3638 /// ```
3639 AlterIndex {
3640 /// Name of the index to alter.
3641 name: ObjectName,
3642 /// The operation to perform on the index.
3643 operation: AlterIndexOperation,
3644 },
3645 /// ```sql
3646 /// ALTER VIEW
3647 /// ```
3648 AlterView {
3649 /// View name being altered.
3650 #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
3651 name: ObjectName,
3652 /// Optional new column list for the view.
3653 columns: Vec<Ident>,
3654 /// Replacement query for the view definition.
3655 query: Box<Query>,
3656 /// Additional WITH options for the view.
3657 with_options: Vec<SqlOption>,
3658 },
3659 /// ```sql
3660 /// ALTER TYPE
3661 /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
3662 /// ```
3663 AlterType(AlterType),
3664 /// ```sql
3665 /// ALTER OPERATOR
3666 /// ```
3667 /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3668 AlterOperator(AlterOperator),
3669 /// ```sql
3670 /// ALTER OPERATOR FAMILY
3671 /// ```
3672 /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html)
3673 AlterOperatorFamily(AlterOperatorFamily),
3674 /// ```sql
3675 /// ALTER OPERATOR CLASS
3676 /// ```
3677 /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
3678 AlterOperatorClass(AlterOperatorClass),
3679 /// ```sql
3680 /// ALTER ROLE
3681 /// ```
3682 AlterRole {
3683 /// Role name being altered.
3684 name: Ident,
3685 /// Operation to perform on the role.
3686 operation: AlterRoleOperation,
3687 },
3688 /// ```sql
3689 /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
3690 /// ```
3691 /// (Postgresql-specific)
3692 AlterPolicy(AlterPolicy),
3693 /// ```sql
3694 /// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
3695 /// or
3696 /// ALTER CONNECTOR connector_name SET URL new_url;
3697 /// or
3698 /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
3699 /// ```
3700 /// (Hive-specific)
3701 AlterConnector {
3702 /// Name of the connector to alter.
3703 name: Ident,
3704 /// Optional connector properties to set.
3705 properties: Option<Vec<SqlOption>>,
3706 /// Optional new URL for the connector.
3707 url: Option<String>,
3708 /// Optional new owner specification.
3709 owner: Option<ddl::AlterConnectorOwner>,
3710 },
3711 /// ```sql
3712 /// ALTER SESSION SET sessionParam
3713 /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
3714 /// ```
3715 /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
3716 AlterSession {
3717 /// true is to set for the session parameters, false is to unset
3718 set: bool,
3719 /// The session parameters to set or unset
3720 session_params: KeyValueOptions,
3721 },
3722 /// ```sql
3723 /// ATTACH DATABASE 'path/to/file' AS alias
3724 /// ```
3725 /// (SQLite-specific)
3726 AttachDatabase {
3727 /// The name to bind to the newly attached database
3728 schema_name: Ident,
3729 /// An expression that indicates the path to the database file
3730 database_file_name: Expr,
3731 /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
3732 database: bool,
3733 },
3734 /// (DuckDB-specific)
3735 /// ```sql
3736 /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
3737 /// ```
3738 /// See <https://duckdb.org/docs/sql/statements/attach.html>
3739 AttachDuckDBDatabase {
3740 /// `true` when `IF NOT EXISTS` was present.
3741 if_not_exists: bool,
3742 /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
3743 database: bool,
3744 /// The path identifier to the database file being attached.
3745 database_path: Ident,
3746 /// Optional alias assigned to the attached database.
3747 database_alias: Option<Ident>,
3748 /// Dialect-specific attach options (e.g., `READ_ONLY`).
3749 attach_options: Vec<AttachDuckDBDatabaseOption>,
3750 },
3751 /// (DuckDB-specific)
3752 /// ```sql
3753 /// DETACH db_alias;
3754 /// ```
3755 /// See <https://duckdb.org/docs/sql/statements/attach.html>
3756 DetachDuckDBDatabase {
3757 /// `true` when `IF EXISTS` was present.
3758 if_exists: bool,
3759 /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
3760 database: bool,
3761 /// Alias of the database to detach.
3762 database_alias: Ident,
3763 },
3764 /// ```sql
3765 /// DROP [TABLE, VIEW, ...]
3766 /// ```
3767 Drop {
3768 /// The type of the object to drop: TABLE, VIEW, etc.
3769 object_type: ObjectType,
3770 /// An optional `IF EXISTS` clause. (Non-standard.)
3771 if_exists: bool,
3772 /// One or more objects to drop. (ANSI SQL requires exactly one.)
3773 names: Vec<ObjectName>,
3774 /// Whether `CASCADE` was specified. This will be `false` when
3775 /// `RESTRICT` or no drop behavior at all was specified.
3776 cascade: bool,
3777 /// Whether `RESTRICT` was specified. This will be `false` when
3778 /// `CASCADE` or no drop behavior at all was specified.
3779 restrict: bool,
3780 /// Hive allows you specify whether the table's stored data will be
3781 /// deleted along with the dropped table
3782 purge: bool,
3783 /// MySQL-specific "TEMPORARY" keyword
3784 temporary: bool,
3785 /// MySQL-specific drop index syntax, which requires table specification
3786 /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
3787 table: Option<ObjectName>,
3788 },
3789 /// ```sql
3790 /// DROP FUNCTION
3791 /// ```
3792 DropFunction(DropFunction),
3793 /// ```sql
3794 /// DROP DOMAIN
3795 /// ```
3796 /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html)
3797 ///
3798 /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3799 ///
3800 DropDomain(DropDomain),
3801 /// ```sql
3802 /// DROP PROCEDURE
3803 /// ```
3804 DropProcedure {
3805 /// `true` when `IF EXISTS` was present.
3806 if_exists: bool,
3807 /// One or more functions/procedures to drop.
3808 proc_desc: Vec<FunctionDesc>,
3809 /// Optional drop behavior (`CASCADE` or `RESTRICT`).
3810 drop_behavior: Option<DropBehavior>,
3811 },
3812 /// ```sql
3813 /// DROP SECRET
3814 /// ```
3815 DropSecret {
3816 /// `true` when `IF EXISTS` was present.
3817 if_exists: bool,
3818 /// Optional `TEMPORARY` marker.
3819 temporary: Option<bool>,
3820 /// Name of the secret to drop.
3821 name: Ident,
3822 /// Optional storage specifier identifier.
3823 storage_specifier: Option<Ident>,
3824 },
3825 ///```sql
3826 /// DROP POLICY
3827 /// ```
3828 /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
3829 DropPolicy(DropPolicy),
3830 /// ```sql
3831 /// DROP CONNECTOR
3832 /// ```
3833 /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
3834 DropConnector {
3835 /// `true` when `IF EXISTS` was present.
3836 if_exists: bool,
3837 /// Name of the connector to drop.
3838 name: Ident,
3839 },
3840 /// ```sql
3841 /// DECLARE
3842 /// ```
3843 /// Declare Cursor Variables
3844 ///
3845 /// Note: this is a PostgreSQL-specific statement,
3846 /// but may also compatible with other SQL.
3847 Declare {
3848 /// Cursor declaration statements collected by `DECLARE`.
3849 stmts: Vec<Declare>,
3850 },
3851 /// ```sql
3852 /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
3853 /// [ WITH ] [ SCHEMA schema_name ]
3854 /// [ VERSION version ]
3855 /// [ CASCADE ]
3856 /// ```
3857 ///
3858 /// Note: this is a PostgreSQL-specific statement,
3859 CreateExtension(CreateExtension),
3860 /// ```sql
3861 /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
3862 /// ```
3863 /// Note: this is a PostgreSQL-specific statement.
3864 /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
3865 DropExtension(DropExtension),
3866 /// ```sql
3867 /// DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , right_type ) [, ...] [ CASCADE | RESTRICT ]
3868 /// ```
3869 /// Note: this is a PostgreSQL-specific statement.
3870 /// <https://www.postgresql.org/docs/current/sql-dropoperator.html>
3871 DropOperator(DropOperator),
3872 /// ```sql
3873 /// DROP OPERATOR FAMILY [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
3874 /// ```
3875 /// Note: this is a PostgreSQL-specific statement.
3876 /// <https://www.postgresql.org/docs/current/sql-dropopfamily.html>
3877 DropOperatorFamily(DropOperatorFamily),
3878 /// ```sql
3879 /// DROP OPERATOR CLASS [ IF EXISTS ] name USING index_method [ CASCADE | RESTRICT ]
3880 /// ```
3881 /// Note: this is a PostgreSQL-specific statement.
3882 /// <https://www.postgresql.org/docs/current/sql-dropopclass.html>
3883 DropOperatorClass(DropOperatorClass),
3884 /// ```sql
3885 /// FETCH
3886 /// ```
3887 /// Retrieve rows from a query using a cursor
3888 ///
3889 /// Note: this is a PostgreSQL-specific statement,
3890 /// but may also compatible with other SQL.
3891 Fetch {
3892 /// Cursor name
3893 name: Ident,
3894 /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
3895 direction: FetchDirection,
3896 /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
3897 position: FetchPosition,
3898 /// Optional target table to fetch rows into.
3899 into: Option<ObjectName>,
3900 },
3901 /// ```sql
3902 /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
3903 /// ```
3904 ///
3905 /// Note: this is a Mysql-specific statement,
3906 /// but may also compatible with other SQL.
3907 Flush {
3908 /// The specific flush option or object to flush.
3909 object_type: FlushType,
3910 /// Optional flush location (dialect-specific).
3911 location: Option<FlushLocation>,
3912 /// Optional channel name used for flush operations.
3913 channel: Option<String>,
3914 /// Whether a read lock was requested.
3915 read_lock: bool,
3916 /// Whether this is an export flush operation.
3917 export: bool,
3918 /// Optional list of tables involved in the flush.
3919 tables: Vec<ObjectName>,
3920 },
3921 /// ```sql
3922 /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
3923 /// ```
3924 ///
3925 /// Note: this is a PostgreSQL-specific statement,
3926 /// but may also compatible with other SQL.
3927 Discard {
3928 /// The kind of object(s) to discard (ALL, PLANS, etc.).
3929 object_type: DiscardObject,
3930 },
3931 /// `SHOW FUNCTIONS`
3932 ///
3933 /// Note: this is a Presto-specific statement.
3934 ShowFunctions {
3935 /// Optional filter for which functions to display.
3936 filter: Option<ShowStatementFilter>,
3937 },
3938 /// ```sql
3939 /// SHOW <variable>
3940 /// ```
3941 ///
3942 /// Note: this is a PostgreSQL-specific statement.
3943 ShowVariable {
3944 /// Variable name as one or more identifiers.
3945 variable: Vec<Ident>,
3946 },
3947 /// ```sql
3948 /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
3949 /// ```
3950 ///
3951 /// Note: this is a MySQL-specific statement.
3952 ShowStatus {
3953 /// Optional filter for which status entries to display.
3954 filter: Option<ShowStatementFilter>,
3955 /// `true` when `GLOBAL` scope was requested.
3956 global: bool,
3957 /// `true` when `SESSION` scope was requested.
3958 session: bool,
3959 },
3960 /// ```sql
3961 /// SHOW VARIABLES
3962 /// ```
3963 ///
3964 /// Note: this is a MySQL-specific statement.
3965 ShowVariables {
3966 /// Optional filter for which variables to display.
3967 filter: Option<ShowStatementFilter>,
3968 /// `true` when `GLOBAL` scope was requested.
3969 global: bool,
3970 /// `true` when `SESSION` scope was requested.
3971 session: bool,
3972 },
3973 /// ```sql
3974 /// SHOW CREATE TABLE
3975 /// ```
3976 ///
3977 /// Note: this is a MySQL-specific statement.
3978 ShowCreate {
3979 /// The kind of object being shown (TABLE, VIEW, etc.).
3980 obj_type: ShowCreateObject,
3981 /// The name of the object to show create statement for.
3982 obj_name: ObjectName,
3983 },
3984 /// ```sql
3985 /// SHOW COLUMNS
3986 /// ```
3987 ShowColumns {
3988 /// `true` when extended column information was requested.
3989 extended: bool,
3990 /// `true` when full column details were requested.
3991 full: bool,
3992 /// Additional options for `SHOW COLUMNS`.
3993 show_options: ShowStatementOptions,
3994 },
3995 /// ```sql
3996 /// SHOW DATABASES
3997 /// ```
3998 ShowDatabases {
3999 /// `true` when terse output format was requested.
4000 terse: bool,
4001 /// `true` when history information was requested.
4002 history: bool,
4003 /// Additional options for `SHOW DATABASES`.
4004 show_options: ShowStatementOptions,
4005 },
4006 /// ```sql
4007 /// SHOW SCHEMAS
4008 /// ```
4009 ShowSchemas {
4010 /// `true` when terse (compact) output was requested.
4011 terse: bool,
4012 /// `true` when history information was requested.
4013 history: bool,
4014 /// Additional options for `SHOW SCHEMAS`.
4015 show_options: ShowStatementOptions,
4016 },
4017 // ```sql
4018 // SHOW {CHARACTER SET | CHARSET}
4019 // ```
4020 // [MySQL]:
4021 // <https://dev.mysql.com/doc/refman/8.4/en/show.html#:~:text=SHOW%20%7BCHARACTER%20SET%20%7C%20CHARSET%7D%20%5Blike_or_where%5D>
4022 /// Show the available character sets (alias `CHARSET`).
4023 ShowCharset(ShowCharset),
4024 /// ```sql
4025 /// SHOW OBJECTS LIKE 'line%' IN mydb.public
4026 /// ```
4027 /// Snowflake-specific statement
4028 /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
4029 ShowObjects(ShowObjects),
4030 /// ```sql
4031 /// SHOW TABLES
4032 /// ```
4033 ShowTables {
4034 /// `true` when terse output format was requested (compact listing).
4035 terse: bool,
4036 /// `true` when history rows are requested.
4037 history: bool,
4038 /// `true` when extended information should be shown.
4039 extended: bool,
4040 /// `true` when a full listing was requested.
4041 full: bool,
4042 /// `true` when external tables should be included.
4043 external: bool,
4044 /// Additional options for `SHOW` statements.
4045 show_options: ShowStatementOptions,
4046 },
4047 /// ```sql
4048 /// SHOW VIEWS
4049 /// ```
4050 ShowViews {
4051 /// `true` when terse output format was requested.
4052 terse: bool,
4053 /// `true` when materialized views should be included.
4054 materialized: bool,
4055 /// Additional options for `SHOW` statements.
4056 show_options: ShowStatementOptions,
4057 },
4058 /// ```sql
4059 /// SHOW COLLATION
4060 /// ```
4061 ///
4062 /// Note: this is a MySQL-specific statement.
4063 ShowCollation {
4064 /// Optional filter for which collations to display.
4065 filter: Option<ShowStatementFilter>,
4066 },
4067 /// ```sql
4068 /// `USE ...`
4069 /// ```
4070 Use(Use),
4071 /// ```sql
4072 /// START [ TRANSACTION | WORK ] | START TRANSACTION } ...
4073 /// ```
4074 /// If `begin` is false.
4075 ///
4076 /// ```sql
4077 /// `BEGIN [ TRANSACTION | WORK ] | START TRANSACTION } ...`
4078 /// ```
4079 /// If `begin` is true
4080 StartTransaction {
4081 /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
4082 modes: Vec<TransactionMode>,
4083 /// `true` when this was parsed as `BEGIN` instead of `START`.
4084 begin: bool,
4085 /// Optional specific keyword used: `TRANSACTION` or `WORK`.
4086 transaction: Option<BeginTransactionKind>,
4087 /// Optional transaction modifier (e.g., `AND NO CHAIN`).
4088 modifier: Option<TransactionModifier>,
4089 /// List of statements belonging to the `BEGIN` block.
4090 /// Example:
4091 /// ```sql
4092 /// BEGIN
4093 /// SELECT 1;
4094 /// SELECT 2;
4095 /// END;
4096 /// ```
4097 statements: Vec<Statement>,
4098 /// Exception handling with exception clauses.
4099 /// Example:
4100 /// ```sql
4101 /// EXCEPTION
4102 /// WHEN EXCEPTION_1 THEN
4103 /// SELECT 2;
4104 /// WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
4105 /// SELECT 3;
4106 /// WHEN OTHER THEN
4107 /// SELECT 4;
4108 /// ```
4109 /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
4110 /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
4111 exception: Option<Vec<ExceptionWhen>>,
4112 /// TRUE if the statement has an `END` keyword.
4113 has_end_keyword: bool,
4114 },
4115 /// ```sql
4116 /// COMMENT ON ...
4117 /// ```
4118 ///
4119 /// Note: this is a PostgreSQL-specific statement.
4120 Comment {
4121 /// Type of object being commented (table, column, etc.).
4122 object_type: CommentObject,
4123 /// Name of the object the comment applies to.
4124 object_name: ObjectName,
4125 /// Optional comment text (None to remove comment).
4126 comment: Option<String>,
4127 /// An optional `IF EXISTS` clause. (Non-standard.)
4128 /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
4129 if_exists: bool,
4130 },
4131 /// ```sql
4132 /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
4133 /// ```
4134 /// If `end` is false
4135 ///
4136 /// ```sql
4137 /// END [ TRY | CATCH ]
4138 /// ```
4139 /// If `end` is true
4140 Commit {
4141 /// `true` when `AND [ NO ] CHAIN` was present.
4142 chain: bool,
4143 /// `true` when this `COMMIT` was parsed as an `END` block terminator.
4144 end: bool,
4145 /// Optional transaction modifier for commit semantics.
4146 modifier: Option<TransactionModifier>,
4147 },
4148 /// ```sql
4149 /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
4150 /// ```
4151 Rollback {
4152 /// `true` when `AND [ NO ] CHAIN` was present.
4153 chain: bool,
4154 /// Optional savepoint name to roll back to.
4155 savepoint: Option<Ident>,
4156 },
4157 /// ```sql
4158 /// CREATE SCHEMA
4159 /// ```
4160 CreateSchema {
4161 /// `<schema name> | AUTHORIZATION <schema authorization identifier> | <schema name> AUTHORIZATION <schema authorization identifier>`
4162 schema_name: SchemaName,
4163 /// `true` when `IF NOT EXISTS` was present.
4164 if_not_exists: bool,
4165 /// Schema properties.
4166 ///
4167 /// ```sql
4168 /// CREATE SCHEMA myschema WITH (key1='value1');
4169 /// ```
4170 ///
4171 /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
4172 with: Option<Vec<SqlOption>>,
4173 /// Schema options.
4174 ///
4175 /// ```sql
4176 /// CREATE SCHEMA myschema OPTIONS(key1='value1');
4177 /// ```
4178 ///
4179 /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4180 options: Option<Vec<SqlOption>>,
4181 /// Default collation specification for the schema.
4182 ///
4183 /// ```sql
4184 /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
4185 /// ```
4186 ///
4187 /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
4188 default_collate_spec: Option<Expr>,
4189 /// Clones a schema
4190 ///
4191 /// ```sql
4192 /// CREATE SCHEMA myschema CLONE otherschema
4193 /// ```
4194 ///
4195 /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
4196 clone: Option<ObjectName>,
4197 },
4198 /// ```sql
4199 /// CREATE DATABASE
4200 /// ```
4201 /// See:
4202 /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
4203 CreateDatabase {
4204 /// Database name.
4205 db_name: ObjectName,
4206 /// `IF NOT EXISTS` flag.
4207 if_not_exists: bool,
4208 /// Optional location URI.
4209 location: Option<String>,
4210 /// Optional managed location.
4211 managed_location: Option<String>,
4212 /// `OR REPLACE` flag.
4213 or_replace: bool,
4214 /// `TRANSIENT` flag.
4215 transient: bool,
4216 /// Optional clone source.
4217 clone: Option<ObjectName>,
4218 /// Optional data retention time in days.
4219 data_retention_time_in_days: Option<u64>,
4220 /// Optional maximum data extension time in days.
4221 max_data_extension_time_in_days: Option<u64>,
4222 /// Optional external volume identifier.
4223 external_volume: Option<String>,
4224 /// Optional catalog name.
4225 catalog: Option<String>,
4226 /// Whether to replace invalid characters.
4227 replace_invalid_characters: Option<bool>,
4228 /// Default DDL collation string.
4229 default_ddl_collation: Option<String>,
4230 /// Storage serialization policy.
4231 storage_serialization_policy: Option<StorageSerializationPolicy>,
4232 /// Optional comment.
4233 comment: Option<String>,
4234 /// Optional default character set (MySQL).
4235 default_charset: Option<String>,
4236 /// Optional default collation (MySQL).
4237 default_collation: Option<String>,
4238 /// Optional catalog sync identifier.
4239 catalog_sync: Option<String>,
4240 /// Catalog sync namespace mode.
4241 catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
4242 /// Optional flatten delimiter for namespace sync.
4243 catalog_sync_namespace_flatten_delimiter: Option<String>,
4244 /// Optional tags for the database.
4245 with_tags: Option<Vec<Tag>>,
4246 /// Optional contact entries for the database.
4247 with_contacts: Option<Vec<ContactEntry>>,
4248 },
4249 /// ```sql
4250 /// CREATE FUNCTION
4251 /// ```
4252 ///
4253 /// Supported variants:
4254 /// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
4255 /// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
4256 /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
4257 /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
4258 CreateFunction(CreateFunction),
4259 /// CREATE TRIGGER statement. See struct [CreateTrigger] for details.
4260 CreateTrigger(CreateTrigger),
4261 /// DROP TRIGGER statement. See struct [DropTrigger] for details.
4262 DropTrigger(DropTrigger),
4263 /// ```sql
4264 /// CREATE PROCEDURE
4265 /// ```
4266 CreateProcedure {
4267 /// `OR ALTER` flag.
4268 or_alter: bool,
4269 /// Procedure name.
4270 name: ObjectName,
4271 /// Optional procedure parameters.
4272 params: Option<Vec<ProcedureParam>>,
4273 /// Optional language identifier.
4274 language: Option<Ident>,
4275 /// Procedure body statements.
4276 body: ConditionalStatements,
4277 },
4278 /// ```sql
4279 /// CREATE MACRO
4280 /// ```
4281 ///
4282 /// Supported variants:
4283 /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
4284 CreateMacro {
4285 /// `OR REPLACE` flag.
4286 or_replace: bool,
4287 /// Whether macro is temporary.
4288 temporary: bool,
4289 /// Macro name.
4290 name: ObjectName,
4291 /// Optional macro arguments.
4292 args: Option<Vec<MacroArg>>,
4293 /// Macro definition body.
4294 definition: MacroDefinition,
4295 },
4296 /// ```sql
4297 /// CREATE STAGE
4298 /// ```
4299 /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
4300 CreateStage {
4301 /// `OR REPLACE` flag for stage.
4302 or_replace: bool,
4303 /// Whether stage is temporary.
4304 temporary: bool,
4305 /// `IF NOT EXISTS` flag.
4306 if_not_exists: bool,
4307 /// Stage name.
4308 name: ObjectName,
4309 /// Stage parameters.
4310 stage_params: StageParamsObject,
4311 /// Directory table parameters.
4312 directory_table_params: KeyValueOptions,
4313 /// File format options.
4314 file_format: KeyValueOptions,
4315 /// Copy options for stage.
4316 copy_options: KeyValueOptions,
4317 /// Optional comment.
4318 comment: Option<String>,
4319 },
4320 /// ```sql
4321 /// ASSERT <condition> [AS <message>]
4322 /// ```
4323 Assert {
4324 /// Assertion condition expression.
4325 condition: Expr,
4326 /// Optional message expression.
4327 message: Option<Expr>,
4328 },
4329 /// ```sql
4330 /// GRANT privileges ON objects TO grantees
4331 /// ```
4332 Grant(Grant),
4333 /// ```sql
4334 /// DENY privileges ON object TO grantees
4335 /// ```
4336 Deny(DenyStatement),
4337 /// ```sql
4338 /// REVOKE privileges ON objects FROM grantees
4339 /// ```
4340 Revoke(Revoke),
4341 /// ```sql
4342 /// DEALLOCATE [ PREPARE ] { name | ALL }
4343 /// ```
4344 ///
4345 /// Note: this is a PostgreSQL-specific statement.
4346 Deallocate {
4347 /// Name to deallocate (or `ALL`).
4348 name: Ident,
4349 /// Whether `PREPARE` keyword was present.
4350 prepare: bool,
4351 },
4352 /// ```sql
4353 /// An `EXECUTE` statement
4354 /// ```
4355 ///
4356 /// Postgres: <https://www.postgresql.org/docs/current/sql-execute.html>
4357 /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
4358 /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
4359 /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
4360 Execute {
4361 /// Optional function/procedure name.
4362 name: Option<ObjectName>,
4363 /// Parameter expressions passed to execute.
4364 parameters: Vec<Expr>,
4365 /// Whether parentheses were present.
4366 has_parentheses: bool,
4367 /// Is this an `EXECUTE IMMEDIATE`.
4368 immediate: bool,
4369 /// Identifiers to capture results into.
4370 into: Vec<Ident>,
4371 /// `USING` expressions with optional aliases.
4372 using: Vec<ExprWithAlias>,
4373 /// Whether the last parameter is the return value of the procedure
4374 /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
4375 output: bool,
4376 /// Whether to invoke the procedure with the default parameter values
4377 /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
4378 default: bool,
4379 },
4380 /// ```sql
4381 /// PREPARE name [ ( data_type [, ...] ) ] AS statement
4382 /// ```
4383 ///
4384 /// Note: this is a PostgreSQL-specific statement.
4385 Prepare {
4386 /// Name of the prepared statement.
4387 name: Ident,
4388 /// Optional data types for parameters.
4389 data_types: Vec<DataType>,
4390 /// Statement being prepared.
4391 statement: Box<Statement>,
4392 },
4393 /// ```sql
4394 /// KILL [CONNECTION | QUERY | MUTATION]
4395 /// ```
4396 ///
4397 /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
4398 /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
4399 Kill {
4400 /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
4401 modifier: Option<KillType>,
4402 // processlist_id
4403 /// The id of the process to kill.
4404 id: u64,
4405 },
4406 /// ```sql
4407 /// [EXPLAIN | DESC | DESCRIBE] TABLE
4408 /// ```
4409 /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
4410 ExplainTable {
4411 /// `EXPLAIN | DESC | DESCRIBE`
4412 describe_alias: DescribeAlias,
4413 /// Hive style `FORMATTED | EXTENDED`
4414 hive_format: Option<HiveDescribeFormat>,
4415 /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
4416 ///
4417 /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
4418 /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
4419 has_table_keyword: bool,
4420 /// Table name
4421 #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4422 table_name: ObjectName,
4423 },
4424 /// ```sql
4425 /// [EXPLAIN | DESC | DESCRIBE] <statement>
4426 /// ```
4427 Explain {
4428 /// `EXPLAIN | DESC | DESCRIBE`
4429 describe_alias: DescribeAlias,
4430 /// Carry out the command and show actual run times and other statistics.
4431 analyze: bool,
4432 /// Display additional information regarding the plan.
4433 verbose: bool,
4434 /// `EXPLAIN QUERY PLAN`
4435 /// Display the query plan without running the query.
4436 ///
4437 /// [SQLite](https://sqlite.org/lang_explain.html)
4438 query_plan: bool,
4439 /// `EXPLAIN ESTIMATE`
4440 /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
4441 estimate: bool,
4442 /// A SQL query that specifies what to explain
4443 statement: Box<Statement>,
4444 /// Optional output format of explain
4445 format: Option<AnalyzeFormatKind>,
4446 /// Postgres style utility options, `(analyze, verbose true)`
4447 options: Option<Vec<UtilityOption>>,
4448 },
4449 /// ```sql
4450 /// SAVEPOINT
4451 /// ```
4452 /// Define a new savepoint within the current transaction
4453 Savepoint {
4454 /// Name of the savepoint being defined.
4455 name: Ident,
4456 },
4457 /// ```sql
4458 /// RELEASE [ SAVEPOINT ] savepoint_name
4459 /// ```
4460 ReleaseSavepoint {
4461 /// Name of the savepoint to release.
4462 name: Ident,
4463 },
4464 /// A `MERGE` statement.
4465 ///
4466 /// ```sql
4467 /// MERGE INTO <target_table> USING <source> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]
4468 /// ```
4469 /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/merge)
4470 /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement)
4471 /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver16)
4472 Merge(Merge),
4473 /// ```sql
4474 /// CACHE [ FLAG ] TABLE <table_name> [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ <query> ]
4475 /// ```
4476 ///
4477 /// See [Spark SQL docs] for more details.
4478 ///
4479 /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
4480 Cache {
4481 /// Table flag
4482 table_flag: Option<ObjectName>,
4483 /// Table name
4484 #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4485 table_name: ObjectName,
4486 /// `true` if `AS` keyword was present before the query.
4487 has_as: bool,
4488 /// Table confs
4489 options: Vec<SqlOption>,
4490 /// Cache table as a Query
4491 query: Option<Box<Query>>,
4492 },
4493 /// ```sql
4494 /// UNCACHE TABLE [ IF EXISTS ] <table_name>
4495 /// ```
4496 UNCache {
4497 /// Table name
4498 #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
4499 table_name: ObjectName,
4500 /// `true` when `IF EXISTS` was present.
4501 if_exists: bool,
4502 },
4503 /// ```sql
4504 /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
4505 /// ```
4506 /// Define a new sequence:
4507 CreateSequence {
4508 /// Whether the sequence is temporary.
4509 temporary: bool,
4510 /// `IF NOT EXISTS` flag.
4511 if_not_exists: bool,
4512 /// Sequence name.
4513 name: ObjectName,
4514 /// Optional data type for the sequence.
4515 data_type: Option<DataType>,
4516 /// Sequence options (INCREMENT, MINVALUE, etc.).
4517 sequence_options: Vec<SequenceOptions>,
4518 /// Optional `OWNED BY` target.
4519 owned_by: Option<ObjectName>,
4520 },
4521 /// A `CREATE DOMAIN` statement.
4522 CreateDomain(CreateDomain),
4523 /// ```sql
4524 /// CREATE TYPE <name>
4525 /// ```
4526 CreateType {
4527 /// Type name to create.
4528 name: ObjectName,
4529 /// Optional type representation details.
4530 representation: Option<UserDefinedTypeRepresentation>,
4531 },
4532 /// ```sql
4533 /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
4534 /// ```
4535 Pragma {
4536 /// Pragma name (possibly qualified).
4537 name: ObjectName,
4538 /// Optional pragma value.
4539 value: Option<Value>,
4540 /// Whether the pragma used `=`.
4541 is_eq: bool,
4542 },
4543 /// ```sql
4544 /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
4545 /// ```
4546 /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4547 LockTables {
4548 /// List of tables to lock with modes.
4549 tables: Vec<LockTable>,
4550 },
4551 /// ```sql
4552 /// UNLOCK TABLES
4553 /// ```
4554 /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4555 UnlockTables,
4556 /// Unloads the result of a query to file
4557 ///
4558 /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4559 /// ```sql
4560 /// UNLOAD(statement) TO <destination> [ WITH options ]
4561 /// ```
4562 ///
4563 /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4564 /// ```sql
4565 /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4566 /// ```
4567 Unload {
4568 /// Optional query AST to unload.
4569 query: Option<Box<Query>>,
4570 /// Optional original query text.
4571 query_text: Option<String>,
4572 /// Destination identifier.
4573 to: Ident,
4574 /// Optional IAM role/auth information.
4575 auth: Option<IamRoleKind>,
4576 /// Additional `WITH` options.
4577 with: Vec<SqlOption>,
4578 /// Legacy copy-style options.
4579 options: Vec<CopyLegacyOption>,
4580 },
4581 /// ```sql
4582 /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
4583 /// ```
4584 ///
4585 /// See ClickHouse <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
4586 OptimizeTable {
4587 /// Table name to optimize.
4588 name: ObjectName,
4589 /// Optional cluster identifier.
4590 on_cluster: Option<Ident>,
4591 /// Optional partition spec.
4592 partition: Option<Partition>,
4593 /// Whether `FINAL` was specified.
4594 include_final: bool,
4595 /// Optional deduplication settings.
4596 deduplicate: Option<Deduplicate>,
4597 },
4598 /// ```sql
4599 /// LISTEN
4600 /// ```
4601 /// listen for a notification channel
4602 ///
4603 /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
4604 LISTEN {
4605 /// Notification channel identifier.
4606 channel: Ident,
4607 },
4608 /// ```sql
4609 /// UNLISTEN
4610 /// ```
4611 /// stop listening for a notification
4612 ///
4613 /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
4614 UNLISTEN {
4615 /// Notification channel identifier.
4616 channel: Ident,
4617 },
4618 /// ```sql
4619 /// NOTIFY channel [ , payload ]
4620 /// ```
4621 /// send a notification event together with an optional "payload" string to channel
4622 ///
4623 /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
4624 NOTIFY {
4625 /// Notification channel identifier.
4626 channel: Ident,
4627 /// Optional payload string.
4628 payload: Option<String>,
4629 },
4630 /// ```sql
4631 /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
4632 /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
4633 /// [INPUTFORMAT 'inputformat' SERDE 'serde']
4634 /// ```
4635 /// Loading files into tables
4636 ///
4637 /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
4638 LoadData {
4639 /// Whether `LOCAL` is present.
4640 local: bool,
4641 /// Input path for files to load.
4642 inpath: String,
4643 /// Whether `OVERWRITE` was specified.
4644 overwrite: bool,
4645 /// Target table name to load into.
4646 table_name: ObjectName,
4647 /// Optional partition specification.
4648 partitioned: Option<Vec<Expr>>,
4649 /// Optional table format information.
4650 table_format: Option<HiveLoadDataFormat>,
4651 },
4652 /// ```sql
4653 /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
4654 /// ```
4655 /// Renames one or more tables
4656 ///
4657 /// See Mysql <https://dev.mysql.com/doc/refman/9.1/en/rename-table.html>
4658 RenameTable(Vec<RenameTable>),
4659 /// Snowflake `LIST`
4660 /// See: <https://docs.snowflake.com/en/sql-reference/sql/list>
4661 List(FileStagingCommand),
4662 /// Snowflake `REMOVE`
4663 /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
4664 Remove(FileStagingCommand),
4665 /// RaiseError (MSSQL)
4666 /// RAISERROR ( { msg_id | msg_str | @local_variable }
4667 /// { , severity , state }
4668 /// [ , argument [ , ...n ] ] )
4669 /// [ WITH option [ , ...n ] ]
4670 /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
4671 RaisError {
4672 /// Error message expression or identifier.
4673 message: Box<Expr>,
4674 /// Severity expression.
4675 severity: Box<Expr>,
4676 /// State expression.
4677 state: Box<Expr>,
4678 /// Substitution arguments for the message.
4679 arguments: Vec<Expr>,
4680 /// Additional `WITH` options for RAISERROR.
4681 options: Vec<RaisErrorOption>,
4682 },
4683 /// ```sql
4684 /// PRINT msg_str | @local_variable | string_expr
4685 /// ```
4686 ///
4687 /// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
4688 Print(PrintStatement),
4689 /// ```sql
4690 /// RETURN [ expression ]
4691 /// ```
4692 ///
4693 /// See [ReturnStatement]
4694 Return(ReturnStatement),
4695 /// Export data statement
4696 ///
4697 /// Example:
4698 /// ```sql
4699 /// EXPORT DATA OPTIONS(uri='gs://bucket/folder/*', format='PARQUET', overwrite=true) AS
4700 /// SELECT field1, field2 FROM mydataset.table1 ORDER BY field1 LIMIT 10
4701 /// ```
4702 /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/export-statements)
4703 ExportData(ExportData),
4704 /// ```sql
4705 /// CREATE [OR REPLACE] USER <user> [IF NOT EXISTS]
4706 /// ```
4707 /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
4708 CreateUser(CreateUser),
4709 /// ```sql
4710 /// ALTER USER \[ IF EXISTS \] \[ <name> \]
4711 /// ```
4712 /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
4713 AlterUser(AlterUser),
4714 /// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
4715 ///
4716 /// ```sql
4717 /// VACUUM tbl
4718 /// ```
4719 /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
4720 Vacuum(VacuumStatement),
4721 /// Restore the value of a run-time parameter to the default value.
4722 ///
4723 /// ```sql
4724 /// RESET configuration_parameter;
4725 /// RESET ALL;
4726 /// ```
4727 /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
4728 Reset(ResetStatement),
4729}
4730
4731impl From<Analyze> for Statement {
4732 fn from(analyze: Analyze) -> Self {
4733 Statement::Analyze(analyze)
4734 }
4735}
4736
4737impl From<ddl::Truncate> for Statement {
4738 fn from(truncate: ddl::Truncate) -> Self {
4739 Statement::Truncate(truncate)
4740 }
4741}
4742
4743impl From<ddl::Msck> for Statement {
4744 fn from(msck: ddl::Msck) -> Self {
4745 Statement::Msck(msck)
4746 }
4747}
4748
4749/// ```sql
4750/// {COPY | REVOKE} CURRENT GRANTS
4751/// ```
4752///
4753/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters)
4754#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4755#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4756#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4757pub enum CurrentGrantsKind {
4758 /// `COPY CURRENT GRANTS` (copy current grants to target).
4759 CopyCurrentGrants,
4760 /// `REVOKE CURRENT GRANTS` (revoke current grants from target).
4761 RevokeCurrentGrants,
4762}
4763
4764impl fmt::Display for CurrentGrantsKind {
4765 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4766 match self {
4767 CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"),
4768 CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"),
4769 }
4770 }
4771}
4772
4773#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4774#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4775#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4776/// `RAISERROR` options
4777/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16#options>
4778pub enum RaisErrorOption {
4779 /// Log the error.
4780 Log,
4781 /// Do not wait for completion.
4782 NoWait,
4783 /// Set the error state.
4784 SetError,
4785}
4786
4787impl fmt::Display for RaisErrorOption {
4788 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4789 match self {
4790 RaisErrorOption::Log => write!(f, "LOG"),
4791 RaisErrorOption::NoWait => write!(f, "NOWAIT"),
4792 RaisErrorOption::SetError => write!(f, "SETERROR"),
4793 }
4794 }
4795}
4796
4797impl fmt::Display for Statement {
4798 /// Formats a SQL statement with support for pretty printing.
4799 ///
4800 /// When using the alternate flag (`{:#}`), the statement will be formatted with proper
4801 /// indentation and line breaks. For example:
4802 ///
4803 /// ```
4804 /// # use sqlparser::dialect::GenericDialect;
4805 /// # use sqlparser::parser::Parser;
4806 /// let sql = "SELECT a, b FROM table_1";
4807 /// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
4808 ///
4809 /// // Regular formatting
4810 /// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
4811 ///
4812 /// // Pretty printing
4813 /// assert_eq!(format!("{:#}", ast[0]),
4814 /// r#"SELECT
4815 /// a,
4816 /// b
4817 /// FROM
4818 /// table_1"#);
4819 /// ```
4820 // Clippy thinks this function is too complicated, but it is painful to
4821 // split up without extracting structs for each `Statement` variant.
4822 #[allow(clippy::cognitive_complexity)]
4823 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4824 match self {
4825 Statement::Flush {
4826 object_type,
4827 location,
4828 channel,
4829 read_lock,
4830 export,
4831 tables,
4832 } => {
4833 write!(f, "FLUSH")?;
4834 if let Some(location) = location {
4835 f.write_str(" ")?;
4836 location.fmt(f)?;
4837 }
4838 write!(f, " {object_type}")?;
4839
4840 if let Some(channel) = channel {
4841 write!(f, " FOR CHANNEL {channel}")?;
4842 }
4843
4844 write!(
4845 f,
4846 "{tables}{read}{export}",
4847 tables = if !tables.is_empty() {
4848 format!(" {}", display_comma_separated(tables))
4849 } else {
4850 String::new()
4851 },
4852 export = if *export { " FOR EXPORT" } else { "" },
4853 read = if *read_lock { " WITH READ LOCK" } else { "" }
4854 )
4855 }
4856 Statement::Kill { modifier, id } => {
4857 write!(f, "KILL ")?;
4858
4859 if let Some(m) = modifier {
4860 write!(f, "{m} ")?;
4861 }
4862
4863 write!(f, "{id}")
4864 }
4865 Statement::ExplainTable {
4866 describe_alias,
4867 hive_format,
4868 has_table_keyword,
4869 table_name,
4870 } => {
4871 write!(f, "{describe_alias} ")?;
4872
4873 if let Some(format) = hive_format {
4874 write!(f, "{format} ")?;
4875 }
4876 if *has_table_keyword {
4877 write!(f, "TABLE ")?;
4878 }
4879
4880 write!(f, "{table_name}")
4881 }
4882 Statement::Explain {
4883 describe_alias,
4884 verbose,
4885 analyze,
4886 query_plan,
4887 estimate,
4888 statement,
4889 format,
4890 options,
4891 } => {
4892 write!(f, "{describe_alias} ")?;
4893
4894 if *query_plan {
4895 write!(f, "QUERY PLAN ")?;
4896 }
4897 if *analyze {
4898 write!(f, "ANALYZE ")?;
4899 }
4900 if *estimate {
4901 write!(f, "ESTIMATE ")?;
4902 }
4903
4904 if *verbose {
4905 write!(f, "VERBOSE ")?;
4906 }
4907
4908 if let Some(format) = format {
4909 write!(f, "{format} ")?;
4910 }
4911
4912 if let Some(options) = options {
4913 write!(f, "({}) ", display_comma_separated(options))?;
4914 }
4915
4916 write!(f, "{statement}")
4917 }
4918 Statement::Query(s) => s.fmt(f),
4919 Statement::Declare { stmts } => {
4920 write!(f, "DECLARE ")?;
4921 write!(f, "{}", display_separated(stmts, "; "))
4922 }
4923 Statement::Fetch {
4924 name,
4925 direction,
4926 position,
4927 into,
4928 } => {
4929 write!(f, "FETCH {direction} {position} {name}")?;
4930
4931 if let Some(into) = into {
4932 write!(f, " INTO {into}")?;
4933 }
4934
4935 Ok(())
4936 }
4937 Statement::Directory {
4938 overwrite,
4939 local,
4940 path,
4941 file_format,
4942 source,
4943 } => {
4944 write!(
4945 f,
4946 "INSERT{overwrite}{local} DIRECTORY '{path}'",
4947 overwrite = if *overwrite { " OVERWRITE" } else { "" },
4948 local = if *local { " LOCAL" } else { "" },
4949 path = path
4950 )?;
4951 if let Some(ref ff) = file_format {
4952 write!(f, " STORED AS {ff}")?
4953 }
4954 write!(f, " {source}")
4955 }
4956 Statement::Msck(msck) => msck.fmt(f),
4957 Statement::Truncate(truncate) => truncate.fmt(f),
4958 Statement::Case(stmt) => {
4959 write!(f, "{stmt}")
4960 }
4961 Statement::If(stmt) => {
4962 write!(f, "{stmt}")
4963 }
4964 Statement::While(stmt) => {
4965 write!(f, "{stmt}")
4966 }
4967 Statement::Raise(stmt) => {
4968 write!(f, "{stmt}")
4969 }
4970 Statement::AttachDatabase {
4971 schema_name,
4972 database_file_name,
4973 database,
4974 } => {
4975 let keyword = if *database { "DATABASE " } else { "" };
4976 write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
4977 }
4978 Statement::AttachDuckDBDatabase {
4979 if_not_exists,
4980 database,
4981 database_path,
4982 database_alias,
4983 attach_options,
4984 } => {
4985 write!(
4986 f,
4987 "ATTACH{database}{if_not_exists} {database_path}",
4988 database = if *database { " DATABASE" } else { "" },
4989 if_not_exists = if *if_not_exists { " IF NOT EXISTS" } else { "" },
4990 )?;
4991 if let Some(alias) = database_alias {
4992 write!(f, " AS {alias}")?;
4993 }
4994 if !attach_options.is_empty() {
4995 write!(f, " ({})", display_comma_separated(attach_options))?;
4996 }
4997 Ok(())
4998 }
4999 Statement::DetachDuckDBDatabase {
5000 if_exists,
5001 database,
5002 database_alias,
5003 } => {
5004 write!(
5005 f,
5006 "DETACH{database}{if_exists} {database_alias}",
5007 database = if *database { " DATABASE" } else { "" },
5008 if_exists = if *if_exists { " IF EXISTS" } else { "" },
5009 )?;
5010 Ok(())
5011 }
5012 Statement::Analyze(analyze) => analyze.fmt(f),
5013 Statement::Insert(insert) => insert.fmt(f),
5014 Statement::Install {
5015 extension_name: name,
5016 } => write!(f, "INSTALL {name}"),
5017
5018 Statement::Load {
5019 extension_name: name,
5020 } => write!(f, "LOAD {name}"),
5021
5022 Statement::Call(function) => write!(f, "CALL {function}"),
5023
5024 Statement::Copy {
5025 source,
5026 to,
5027 target,
5028 options,
5029 legacy_options,
5030 values,
5031 } => {
5032 write!(f, "COPY")?;
5033 match source {
5034 CopySource::Query(query) => write!(f, " ({query})")?,
5035 CopySource::Table {
5036 table_name,
5037 columns,
5038 } => {
5039 write!(f, " {table_name}")?;
5040 if !columns.is_empty() {
5041 write!(f, " ({})", display_comma_separated(columns))?;
5042 }
5043 }
5044 }
5045 write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
5046 if !options.is_empty() {
5047 write!(f, " ({})", display_comma_separated(options))?;
5048 }
5049 if !legacy_options.is_empty() {
5050 write!(f, " {}", display_separated(legacy_options, " "))?;
5051 }
5052 if !values.is_empty() {
5053 writeln!(f, ";")?;
5054 let mut delim = "";
5055 for v in values {
5056 write!(f, "{delim}")?;
5057 delim = "\t";
5058 if let Some(v) = v {
5059 write!(f, "{v}")?;
5060 } else {
5061 write!(f, "\\N")?;
5062 }
5063 }
5064 write!(f, "\n\\.")?;
5065 }
5066 Ok(())
5067 }
5068 Statement::Update(update) => update.fmt(f),
5069 Statement::Delete(delete) => delete.fmt(f),
5070 Statement::Open(open) => open.fmt(f),
5071 Statement::Close { cursor } => {
5072 write!(f, "CLOSE {cursor}")?;
5073
5074 Ok(())
5075 }
5076 Statement::CreateDatabase {
5077 db_name,
5078 if_not_exists,
5079 location,
5080 managed_location,
5081 or_replace,
5082 transient,
5083 clone,
5084 data_retention_time_in_days,
5085 max_data_extension_time_in_days,
5086 external_volume,
5087 catalog,
5088 replace_invalid_characters,
5089 default_ddl_collation,
5090 storage_serialization_policy,
5091 comment,
5092 default_charset,
5093 default_collation,
5094 catalog_sync,
5095 catalog_sync_namespace_mode,
5096 catalog_sync_namespace_flatten_delimiter,
5097 with_tags,
5098 with_contacts,
5099 } => {
5100 write!(
5101 f,
5102 "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
5103 or_replace = if *or_replace { "OR REPLACE " } else { "" },
5104 transient = if *transient { "TRANSIENT " } else { "" },
5105 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5106 name = db_name,
5107 )?;
5108
5109 if let Some(l) = location {
5110 write!(f, " LOCATION '{l}'")?;
5111 }
5112 if let Some(ml) = managed_location {
5113 write!(f, " MANAGEDLOCATION '{ml}'")?;
5114 }
5115 if let Some(clone) = clone {
5116 write!(f, " CLONE {clone}")?;
5117 }
5118
5119 if let Some(value) = data_retention_time_in_days {
5120 write!(f, " DATA_RETENTION_TIME_IN_DAYS = {value}")?;
5121 }
5122
5123 if let Some(value) = max_data_extension_time_in_days {
5124 write!(f, " MAX_DATA_EXTENSION_TIME_IN_DAYS = {value}")?;
5125 }
5126
5127 if let Some(vol) = external_volume {
5128 write!(f, " EXTERNAL_VOLUME = '{vol}'")?;
5129 }
5130
5131 if let Some(cat) = catalog {
5132 write!(f, " CATALOG = '{cat}'")?;
5133 }
5134
5135 if let Some(true) = replace_invalid_characters {
5136 write!(f, " REPLACE_INVALID_CHARACTERS = TRUE")?;
5137 } else if let Some(false) = replace_invalid_characters {
5138 write!(f, " REPLACE_INVALID_CHARACTERS = FALSE")?;
5139 }
5140
5141 if let Some(collation) = default_ddl_collation {
5142 write!(f, " DEFAULT_DDL_COLLATION = '{collation}'")?;
5143 }
5144
5145 if let Some(policy) = storage_serialization_policy {
5146 write!(f, " STORAGE_SERIALIZATION_POLICY = {policy}")?;
5147 }
5148
5149 if let Some(comment) = comment {
5150 write!(f, " COMMENT = '{comment}'")?;
5151 }
5152
5153 if let Some(charset) = default_charset {
5154 write!(f, " DEFAULT CHARACTER SET {charset}")?;
5155 }
5156
5157 if let Some(collation) = default_collation {
5158 write!(f, " DEFAULT COLLATE {collation}")?;
5159 }
5160
5161 if let Some(sync) = catalog_sync {
5162 write!(f, " CATALOG_SYNC = '{sync}'")?;
5163 }
5164
5165 if let Some(mode) = catalog_sync_namespace_mode {
5166 write!(f, " CATALOG_SYNC_NAMESPACE_MODE = {mode}")?;
5167 }
5168
5169 if let Some(delim) = catalog_sync_namespace_flatten_delimiter {
5170 write!(f, " CATALOG_SYNC_NAMESPACE_FLATTEN_DELIMITER = '{delim}'")?;
5171 }
5172
5173 if let Some(tags) = with_tags {
5174 write!(f, " WITH TAG ({})", display_comma_separated(tags))?;
5175 }
5176
5177 if let Some(contacts) = with_contacts {
5178 write!(f, " WITH CONTACT ({})", display_comma_separated(contacts))?;
5179 }
5180 Ok(())
5181 }
5182 Statement::CreateFunction(create_function) => create_function.fmt(f),
5183 Statement::CreateDomain(create_domain) => create_domain.fmt(f),
5184 Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
5185 Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
5186 Statement::CreateProcedure {
5187 name,
5188 or_alter,
5189 params,
5190 language,
5191 body,
5192 } => {
5193 write!(
5194 f,
5195 "CREATE {or_alter}PROCEDURE {name}",
5196 or_alter = if *or_alter { "OR ALTER " } else { "" },
5197 name = name
5198 )?;
5199
5200 if let Some(p) = params {
5201 if !p.is_empty() {
5202 write!(f, " ({})", display_comma_separated(p))?;
5203 }
5204 }
5205
5206 if let Some(language) = language {
5207 write!(f, " LANGUAGE {language}")?;
5208 }
5209
5210 write!(f, " AS {body}")
5211 }
5212 Statement::CreateMacro {
5213 or_replace,
5214 temporary,
5215 name,
5216 args,
5217 definition,
5218 } => {
5219 write!(
5220 f,
5221 "CREATE {or_replace}{temp}MACRO {name}",
5222 temp = if *temporary { "TEMPORARY " } else { "" },
5223 or_replace = if *or_replace { "OR REPLACE " } else { "" },
5224 )?;
5225 if let Some(args) = args {
5226 write!(f, "({})", display_comma_separated(args))?;
5227 }
5228 match definition {
5229 MacroDefinition::Expr(expr) => write!(f, " AS {expr}")?,
5230 MacroDefinition::Table(query) => write!(f, " AS TABLE {query}")?,
5231 }
5232 Ok(())
5233 }
5234 Statement::CreateView(create_view) => create_view.fmt(f),
5235 Statement::CreateTable(create_table) => create_table.fmt(f),
5236 Statement::LoadData {
5237 local,
5238 inpath,
5239 overwrite,
5240 table_name,
5241 partitioned,
5242 table_format,
5243 } => {
5244 write!(
5245 f,
5246 "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
5247 local = if *local { "LOCAL " } else { "" },
5248 inpath = inpath,
5249 overwrite = if *overwrite { "OVERWRITE " } else { "" },
5250 table_name = table_name,
5251 )?;
5252 if let Some(ref parts) = &partitioned {
5253 if !parts.is_empty() {
5254 write!(f, " PARTITION ({})", display_comma_separated(parts))?;
5255 }
5256 }
5257 if let Some(HiveLoadDataFormat {
5258 serde,
5259 input_format,
5260 }) = &table_format
5261 {
5262 write!(f, " INPUTFORMAT {input_format} SERDE {serde}")?;
5263 }
5264 Ok(())
5265 }
5266 Statement::CreateVirtualTable {
5267 name,
5268 if_not_exists,
5269 module_name,
5270 module_args,
5271 } => {
5272 write!(
5273 f,
5274 "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
5275 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5276 name = name,
5277 module_name = module_name
5278 )?;
5279 if !module_args.is_empty() {
5280 write!(f, " ({})", display_comma_separated(module_args))?;
5281 }
5282 Ok(())
5283 }
5284 Statement::CreateIndex(create_index) => create_index.fmt(f),
5285 Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
5286 Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
5287 Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
5288 Statement::DropOperatorFamily(drop_operator_family) => {
5289 write!(f, "{drop_operator_family}")
5290 }
5291 Statement::DropOperatorClass(drop_operator_class) => {
5292 write!(f, "{drop_operator_class}")
5293 }
5294 Statement::CreateRole(create_role) => write!(f, "{create_role}"),
5295 Statement::CreateSecret {
5296 or_replace,
5297 temporary,
5298 if_not_exists,
5299 name,
5300 storage_specifier,
5301 secret_type,
5302 options,
5303 } => {
5304 write!(
5305 f,
5306 "CREATE {or_replace}",
5307 or_replace = if *or_replace { "OR REPLACE " } else { "" },
5308 )?;
5309 if let Some(t) = temporary {
5310 write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5311 }
5312 write!(
5313 f,
5314 "SECRET {if_not_exists}",
5315 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5316 )?;
5317 if let Some(n) = name {
5318 write!(f, "{n} ")?;
5319 };
5320 if let Some(s) = storage_specifier {
5321 write!(f, "IN {s} ")?;
5322 }
5323 write!(f, "( TYPE {secret_type}",)?;
5324 if !options.is_empty() {
5325 write!(f, ", {o}", o = display_comma_separated(options))?;
5326 }
5327 write!(f, " )")?;
5328 Ok(())
5329 }
5330 Statement::CreateServer(stmt) => {
5331 write!(f, "{stmt}")
5332 }
5333 Statement::CreatePolicy(policy) => write!(f, "{policy}"),
5334 Statement::CreateConnector(create_connector) => create_connector.fmt(f),
5335 Statement::CreateOperator(create_operator) => create_operator.fmt(f),
5336 Statement::CreateOperatorFamily(create_operator_family) => {
5337 create_operator_family.fmt(f)
5338 }
5339 Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5340 Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
5341 Statement::AlterIndex { name, operation } => {
5342 write!(f, "ALTER INDEX {name} {operation}")
5343 }
5344 Statement::AlterView {
5345 name,
5346 columns,
5347 query,
5348 with_options,
5349 } => {
5350 write!(f, "ALTER VIEW {name}")?;
5351 if !with_options.is_empty() {
5352 write!(f, " WITH ({})", display_comma_separated(with_options))?;
5353 }
5354 if !columns.is_empty() {
5355 write!(f, " ({})", display_comma_separated(columns))?;
5356 }
5357 write!(f, " AS {query}")
5358 }
5359 Statement::AlterType(AlterType { name, operation }) => {
5360 write!(f, "ALTER TYPE {name} {operation}")
5361 }
5362 Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
5363 Statement::AlterOperatorFamily(alter_operator_family) => {
5364 write!(f, "{alter_operator_family}")
5365 }
5366 Statement::AlterOperatorClass(alter_operator_class) => {
5367 write!(f, "{alter_operator_class}")
5368 }
5369 Statement::AlterRole { name, operation } => {
5370 write!(f, "ALTER ROLE {name} {operation}")
5371 }
5372 Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
5373 Statement::AlterConnector {
5374 name,
5375 properties,
5376 url,
5377 owner,
5378 } => {
5379 write!(f, "ALTER CONNECTOR {name}")?;
5380 if let Some(properties) = properties {
5381 write!(
5382 f,
5383 " SET DCPROPERTIES({})",
5384 display_comma_separated(properties)
5385 )?;
5386 }
5387 if let Some(url) = url {
5388 write!(f, " SET URL '{url}'")?;
5389 }
5390 if let Some(owner) = owner {
5391 write!(f, " SET OWNER {owner}")?;
5392 }
5393 Ok(())
5394 }
5395 Statement::AlterSession {
5396 set,
5397 session_params,
5398 } => {
5399 write!(
5400 f,
5401 "ALTER SESSION {set}",
5402 set = if *set { "SET" } else { "UNSET" }
5403 )?;
5404 if !session_params.options.is_empty() {
5405 if *set {
5406 write!(f, " {session_params}")?;
5407 } else {
5408 let options = session_params
5409 .options
5410 .iter()
5411 .map(|p| p.option_name.clone())
5412 .collect::<Vec<_>>();
5413 write!(f, " {}", display_separated(&options, ", "))?;
5414 }
5415 }
5416 Ok(())
5417 }
5418 Statement::Drop {
5419 object_type,
5420 if_exists,
5421 names,
5422 cascade,
5423 restrict,
5424 purge,
5425 temporary,
5426 table,
5427 } => {
5428 write!(
5429 f,
5430 "DROP {}{}{} {}{}{}{}",
5431 if *temporary { "TEMPORARY " } else { "" },
5432 object_type,
5433 if *if_exists { " IF EXISTS" } else { "" },
5434 display_comma_separated(names),
5435 if *cascade { " CASCADE" } else { "" },
5436 if *restrict { " RESTRICT" } else { "" },
5437 if *purge { " PURGE" } else { "" },
5438 )?;
5439 if let Some(table_name) = table.as_ref() {
5440 write!(f, " ON {table_name}")?;
5441 };
5442 Ok(())
5443 }
5444 Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
5445 Statement::DropDomain(DropDomain {
5446 if_exists,
5447 name,
5448 drop_behavior,
5449 }) => {
5450 write!(
5451 f,
5452 "DROP DOMAIN{} {name}",
5453 if *if_exists { " IF EXISTS" } else { "" },
5454 )?;
5455 if let Some(op) = drop_behavior {
5456 write!(f, " {op}")?;
5457 }
5458 Ok(())
5459 }
5460 Statement::DropProcedure {
5461 if_exists,
5462 proc_desc,
5463 drop_behavior,
5464 } => {
5465 write!(
5466 f,
5467 "DROP PROCEDURE{} {}",
5468 if *if_exists { " IF EXISTS" } else { "" },
5469 display_comma_separated(proc_desc),
5470 )?;
5471 if let Some(op) = drop_behavior {
5472 write!(f, " {op}")?;
5473 }
5474 Ok(())
5475 }
5476 Statement::DropSecret {
5477 if_exists,
5478 temporary,
5479 name,
5480 storage_specifier,
5481 } => {
5482 write!(f, "DROP ")?;
5483 if let Some(t) = temporary {
5484 write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
5485 }
5486 write!(
5487 f,
5488 "SECRET {if_exists}{name}",
5489 if_exists = if *if_exists { "IF EXISTS " } else { "" },
5490 )?;
5491 if let Some(s) = storage_specifier {
5492 write!(f, " FROM {s}")?;
5493 }
5494 Ok(())
5495 }
5496 Statement::DropPolicy(policy) => write!(f, "{policy}"),
5497 Statement::DropConnector { if_exists, name } => {
5498 write!(
5499 f,
5500 "DROP CONNECTOR {if_exists}{name}",
5501 if_exists = if *if_exists { "IF EXISTS " } else { "" }
5502 )?;
5503 Ok(())
5504 }
5505 Statement::Discard { object_type } => {
5506 write!(f, "DISCARD {object_type}")?;
5507 Ok(())
5508 }
5509 Self::Set(set) => write!(f, "{set}"),
5510 Statement::ShowVariable { variable } => {
5511 write!(f, "SHOW")?;
5512 if !variable.is_empty() {
5513 write!(f, " {}", display_separated(variable, " "))?;
5514 }
5515 Ok(())
5516 }
5517 Statement::ShowStatus {
5518 filter,
5519 global,
5520 session,
5521 } => {
5522 write!(f, "SHOW")?;
5523 if *global {
5524 write!(f, " GLOBAL")?;
5525 }
5526 if *session {
5527 write!(f, " SESSION")?;
5528 }
5529 write!(f, " STATUS")?;
5530 if filter.is_some() {
5531 write!(f, " {}", filter.as_ref().unwrap())?;
5532 }
5533 Ok(())
5534 }
5535 Statement::ShowVariables {
5536 filter,
5537 global,
5538 session,
5539 } => {
5540 write!(f, "SHOW")?;
5541 if *global {
5542 write!(f, " GLOBAL")?;
5543 }
5544 if *session {
5545 write!(f, " SESSION")?;
5546 }
5547 write!(f, " VARIABLES")?;
5548 if filter.is_some() {
5549 write!(f, " {}", filter.as_ref().unwrap())?;
5550 }
5551 Ok(())
5552 }
5553 Statement::ShowCreate { obj_type, obj_name } => {
5554 write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
5555 Ok(())
5556 }
5557 Statement::ShowColumns {
5558 extended,
5559 full,
5560 show_options,
5561 } => {
5562 write!(
5563 f,
5564 "SHOW {extended}{full}COLUMNS{show_options}",
5565 extended = if *extended { "EXTENDED " } else { "" },
5566 full = if *full { "FULL " } else { "" },
5567 )?;
5568 Ok(())
5569 }
5570 Statement::ShowDatabases {
5571 terse,
5572 history,
5573 show_options,
5574 } => {
5575 write!(
5576 f,
5577 "SHOW {terse}DATABASES{history}{show_options}",
5578 terse = if *terse { "TERSE " } else { "" },
5579 history = if *history { " HISTORY" } else { "" },
5580 )?;
5581 Ok(())
5582 }
5583 Statement::ShowSchemas {
5584 terse,
5585 history,
5586 show_options,
5587 } => {
5588 write!(
5589 f,
5590 "SHOW {terse}SCHEMAS{history}{show_options}",
5591 terse = if *terse { "TERSE " } else { "" },
5592 history = if *history { " HISTORY" } else { "" },
5593 )?;
5594 Ok(())
5595 }
5596 Statement::ShowObjects(ShowObjects {
5597 terse,
5598 show_options,
5599 }) => {
5600 write!(
5601 f,
5602 "SHOW {terse}OBJECTS{show_options}",
5603 terse = if *terse { "TERSE " } else { "" },
5604 )?;
5605 Ok(())
5606 }
5607 Statement::ShowTables {
5608 terse,
5609 history,
5610 extended,
5611 full,
5612 external,
5613 show_options,
5614 } => {
5615 write!(
5616 f,
5617 "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
5618 terse = if *terse { "TERSE " } else { "" },
5619 extended = if *extended { "EXTENDED " } else { "" },
5620 full = if *full { "FULL " } else { "" },
5621 external = if *external { "EXTERNAL " } else { "" },
5622 history = if *history { " HISTORY" } else { "" },
5623 )?;
5624 Ok(())
5625 }
5626 Statement::ShowViews {
5627 terse,
5628 materialized,
5629 show_options,
5630 } => {
5631 write!(
5632 f,
5633 "SHOW {terse}{materialized}VIEWS{show_options}",
5634 terse = if *terse { "TERSE " } else { "" },
5635 materialized = if *materialized { "MATERIALIZED " } else { "" }
5636 )?;
5637 Ok(())
5638 }
5639 Statement::ShowFunctions { filter } => {
5640 write!(f, "SHOW FUNCTIONS")?;
5641 if let Some(filter) = filter {
5642 write!(f, " {filter}")?;
5643 }
5644 Ok(())
5645 }
5646 Statement::Use(use_expr) => use_expr.fmt(f),
5647 Statement::ShowCollation { filter } => {
5648 write!(f, "SHOW COLLATION")?;
5649 if let Some(filter) = filter {
5650 write!(f, " {filter}")?;
5651 }
5652 Ok(())
5653 }
5654 Statement::ShowCharset(show_stm) => show_stm.fmt(f),
5655 Statement::StartTransaction {
5656 modes,
5657 begin: syntax_begin,
5658 transaction,
5659 modifier,
5660 statements,
5661 exception,
5662 has_end_keyword,
5663 } => {
5664 if *syntax_begin {
5665 if let Some(modifier) = *modifier {
5666 write!(f, "BEGIN {modifier}")?;
5667 } else {
5668 write!(f, "BEGIN")?;
5669 }
5670 } else {
5671 write!(f, "START")?;
5672 }
5673 if let Some(transaction) = transaction {
5674 write!(f, " {transaction}")?;
5675 }
5676 if !modes.is_empty() {
5677 write!(f, " {}", display_comma_separated(modes))?;
5678 }
5679 if !statements.is_empty() {
5680 write!(f, " ")?;
5681 format_statement_list(f, statements)?;
5682 }
5683 if let Some(exception_when) = exception {
5684 write!(f, " EXCEPTION")?;
5685 for when in exception_when {
5686 write!(f, " {when}")?;
5687 }
5688 }
5689 if *has_end_keyword {
5690 write!(f, " END")?;
5691 }
5692 Ok(())
5693 }
5694 Statement::Commit {
5695 chain,
5696 end: end_syntax,
5697 modifier,
5698 } => {
5699 if *end_syntax {
5700 write!(f, "END")?;
5701 if let Some(modifier) = *modifier {
5702 write!(f, " {modifier}")?;
5703 }
5704 if *chain {
5705 write!(f, " AND CHAIN")?;
5706 }
5707 } else {
5708 write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" })?;
5709 }
5710 Ok(())
5711 }
5712 Statement::Rollback { chain, savepoint } => {
5713 write!(f, "ROLLBACK")?;
5714
5715 if *chain {
5716 write!(f, " AND CHAIN")?;
5717 }
5718
5719 if let Some(savepoint) = savepoint {
5720 write!(f, " TO SAVEPOINT {savepoint}")?;
5721 }
5722
5723 Ok(())
5724 }
5725 Statement::CreateSchema {
5726 schema_name,
5727 if_not_exists,
5728 with,
5729 options,
5730 default_collate_spec,
5731 clone,
5732 } => {
5733 write!(
5734 f,
5735 "CREATE SCHEMA {if_not_exists}{name}",
5736 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5737 name = schema_name
5738 )?;
5739
5740 if let Some(collate) = default_collate_spec {
5741 write!(f, " DEFAULT COLLATE {collate}")?;
5742 }
5743
5744 if let Some(with) = with {
5745 write!(f, " WITH ({})", display_comma_separated(with))?;
5746 }
5747
5748 if let Some(options) = options {
5749 write!(f, " OPTIONS({})", display_comma_separated(options))?;
5750 }
5751
5752 if let Some(clone) = clone {
5753 write!(f, " CLONE {clone}")?;
5754 }
5755 Ok(())
5756 }
5757 Statement::Assert { condition, message } => {
5758 write!(f, "ASSERT {condition}")?;
5759 if let Some(m) = message {
5760 write!(f, " AS {m}")?;
5761 }
5762 Ok(())
5763 }
5764 Statement::Grant(grant) => write!(f, "{grant}"),
5765 Statement::Deny(s) => write!(f, "{s}"),
5766 Statement::Revoke(revoke) => write!(f, "{revoke}"),
5767 Statement::Deallocate { name, prepare } => write!(
5768 f,
5769 "DEALLOCATE {prepare}{name}",
5770 prepare = if *prepare { "PREPARE " } else { "" },
5771 name = name,
5772 ),
5773 Statement::Execute {
5774 name,
5775 parameters,
5776 has_parentheses,
5777 immediate,
5778 into,
5779 using,
5780 output,
5781 default,
5782 } => {
5783 let (open, close) = if *has_parentheses {
5784 ("(", ")")
5785 } else {
5786 (if parameters.is_empty() { "" } else { " " }, "")
5787 };
5788 write!(f, "EXECUTE")?;
5789 if *immediate {
5790 write!(f, " IMMEDIATE")?;
5791 }
5792 if let Some(name) = name {
5793 write!(f, " {name}")?;
5794 }
5795 write!(f, "{open}{}{close}", display_comma_separated(parameters),)?;
5796 if !into.is_empty() {
5797 write!(f, " INTO {}", display_comma_separated(into))?;
5798 }
5799 if !using.is_empty() {
5800 write!(f, " USING {}", display_comma_separated(using))?;
5801 };
5802 if *output {
5803 write!(f, " OUTPUT")?;
5804 }
5805 if *default {
5806 write!(f, " DEFAULT")?;
5807 }
5808 Ok(())
5809 }
5810 Statement::Prepare {
5811 name,
5812 data_types,
5813 statement,
5814 } => {
5815 write!(f, "PREPARE {name} ")?;
5816 if !data_types.is_empty() {
5817 write!(f, "({}) ", display_comma_separated(data_types))?;
5818 }
5819 write!(f, "AS {statement}")
5820 }
5821 Statement::Comment {
5822 object_type,
5823 object_name,
5824 comment,
5825 if_exists,
5826 } => {
5827 write!(f, "COMMENT ")?;
5828 if *if_exists {
5829 write!(f, "IF EXISTS ")?
5830 };
5831 write!(f, "ON {object_type} {object_name} IS ")?;
5832 if let Some(c) = comment {
5833 write!(f, "'{c}'")
5834 } else {
5835 write!(f, "NULL")
5836 }
5837 }
5838 Statement::Savepoint { name } => {
5839 write!(f, "SAVEPOINT ")?;
5840 write!(f, "{name}")
5841 }
5842 Statement::ReleaseSavepoint { name } => {
5843 write!(f, "RELEASE SAVEPOINT {name}")
5844 }
5845 Statement::Merge(merge) => merge.fmt(f),
5846 Statement::Cache {
5847 table_name,
5848 table_flag,
5849 has_as,
5850 options,
5851 query,
5852 } => {
5853 if let Some(table_flag) = table_flag {
5854 write!(f, "CACHE {table_flag} TABLE {table_name}")?;
5855 } else {
5856 write!(f, "CACHE TABLE {table_name}")?;
5857 }
5858
5859 if !options.is_empty() {
5860 write!(f, " OPTIONS({})", display_comma_separated(options))?;
5861 }
5862
5863 match (*has_as, query) {
5864 (true, Some(query)) => write!(f, " AS {query}"),
5865 (true, None) => f.write_str(" AS"),
5866 (false, Some(query)) => write!(f, " {query}"),
5867 (false, None) => Ok(()),
5868 }
5869 }
5870 Statement::UNCache {
5871 table_name,
5872 if_exists,
5873 } => {
5874 if *if_exists {
5875 write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
5876 } else {
5877 write!(f, "UNCACHE TABLE {table_name}")
5878 }
5879 }
5880 Statement::CreateSequence {
5881 temporary,
5882 if_not_exists,
5883 name,
5884 data_type,
5885 sequence_options,
5886 owned_by,
5887 } => {
5888 let as_type: String = if let Some(dt) = data_type.as_ref() {
5889 //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
5890 // " AS ".to_owned() + &dt.to_string()
5891 [" AS ", &dt.to_string()].concat()
5892 } else {
5893 "".to_string()
5894 };
5895 write!(
5896 f,
5897 "CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
5898 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5899 temporary = if *temporary { "TEMPORARY " } else { "" },
5900 name = name,
5901 as_type = as_type
5902 )?;
5903 for sequence_option in sequence_options {
5904 write!(f, "{sequence_option}")?;
5905 }
5906 if let Some(ob) = owned_by.as_ref() {
5907 write!(f, " OWNED BY {ob}")?;
5908 }
5909 write!(f, "")
5910 }
5911 Statement::CreateStage {
5912 or_replace,
5913 temporary,
5914 if_not_exists,
5915 name,
5916 stage_params,
5917 directory_table_params,
5918 file_format,
5919 copy_options,
5920 comment,
5921 ..
5922 } => {
5923 write!(
5924 f,
5925 "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
5926 temp = if *temporary { "TEMPORARY " } else { "" },
5927 or_replace = if *or_replace { "OR REPLACE " } else { "" },
5928 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
5929 )?;
5930 if !directory_table_params.options.is_empty() {
5931 write!(f, " DIRECTORY=({directory_table_params})")?;
5932 }
5933 if !file_format.options.is_empty() {
5934 write!(f, " FILE_FORMAT=({file_format})")?;
5935 }
5936 if !copy_options.options.is_empty() {
5937 write!(f, " COPY_OPTIONS=({copy_options})")?;
5938 }
5939 if comment.is_some() {
5940 write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
5941 }
5942 Ok(())
5943 }
5944 Statement::CopyIntoSnowflake {
5945 kind,
5946 into,
5947 into_columns,
5948 from_obj,
5949 from_obj_alias,
5950 stage_params,
5951 from_transformations,
5952 from_query,
5953 files,
5954 pattern,
5955 file_format,
5956 copy_options,
5957 validation_mode,
5958 partition,
5959 } => {
5960 write!(f, "COPY INTO {into}")?;
5961 if let Some(into_columns) = into_columns {
5962 write!(f, " ({})", display_comma_separated(into_columns))?;
5963 }
5964 if let Some(from_transformations) = from_transformations {
5965 // Data load with transformation
5966 if let Some(from_stage) = from_obj {
5967 write!(
5968 f,
5969 " FROM (SELECT {} FROM {}{}",
5970 display_separated(from_transformations, ", "),
5971 from_stage,
5972 stage_params
5973 )?;
5974 }
5975 if let Some(from_obj_alias) = from_obj_alias {
5976 write!(f, " AS {from_obj_alias}")?;
5977 }
5978 write!(f, ")")?;
5979 } else if let Some(from_obj) = from_obj {
5980 // Standard data load
5981 write!(f, " FROM {from_obj}{stage_params}")?;
5982 if let Some(from_obj_alias) = from_obj_alias {
5983 write!(f, " AS {from_obj_alias}")?;
5984 }
5985 } else if let Some(from_query) = from_query {
5986 // Data unload from query
5987 write!(f, " FROM ({from_query})")?;
5988 }
5989
5990 if let Some(files) = files {
5991 write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
5992 }
5993 if let Some(pattern) = pattern {
5994 write!(f, " PATTERN = '{pattern}'")?;
5995 }
5996 if let Some(partition) = partition {
5997 write!(f, " PARTITION BY {partition}")?;
5998 }
5999 if !file_format.options.is_empty() {
6000 write!(f, " FILE_FORMAT=({file_format})")?;
6001 }
6002 if !copy_options.options.is_empty() {
6003 match kind {
6004 CopyIntoSnowflakeKind::Table => {
6005 write!(f, " COPY_OPTIONS=({copy_options})")?
6006 }
6007 CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
6008 }
6009 }
6010 if let Some(validation_mode) = validation_mode {
6011 write!(f, " VALIDATION_MODE = {validation_mode}")?;
6012 }
6013 Ok(())
6014 }
6015 Statement::CreateType {
6016 name,
6017 representation,
6018 } => {
6019 write!(f, "CREATE TYPE {name}")?;
6020 if let Some(repr) = representation {
6021 write!(f, " {repr}")?;
6022 }
6023 Ok(())
6024 }
6025 Statement::Pragma { name, value, is_eq } => {
6026 write!(f, "PRAGMA {name}")?;
6027 if value.is_some() {
6028 let val = value.as_ref().unwrap();
6029 if *is_eq {
6030 write!(f, " = {val}")?;
6031 } else {
6032 write!(f, "({val})")?;
6033 }
6034 }
6035 Ok(())
6036 }
6037 Statement::LockTables { tables } => {
6038 write!(f, "LOCK TABLES {}", display_comma_separated(tables))
6039 }
6040 Statement::UnlockTables => {
6041 write!(f, "UNLOCK TABLES")
6042 }
6043 Statement::Unload {
6044 query,
6045 query_text,
6046 to,
6047 auth,
6048 with,
6049 options,
6050 } => {
6051 write!(f, "UNLOAD(")?;
6052 if let Some(query) = query {
6053 write!(f, "{query}")?;
6054 }
6055 if let Some(query_text) = query_text {
6056 write!(f, "'{query_text}'")?;
6057 }
6058 write!(f, ") TO {to}")?;
6059 if let Some(auth) = auth {
6060 write!(f, " IAM_ROLE {auth}")?;
6061 }
6062 if !with.is_empty() {
6063 write!(f, " WITH ({})", display_comma_separated(with))?;
6064 }
6065 if !options.is_empty() {
6066 write!(f, " {}", display_separated(options, " "))?;
6067 }
6068 Ok(())
6069 }
6070 Statement::OptimizeTable {
6071 name,
6072 on_cluster,
6073 partition,
6074 include_final,
6075 deduplicate,
6076 } => {
6077 write!(f, "OPTIMIZE TABLE {name}")?;
6078 if let Some(on_cluster) = on_cluster {
6079 write!(f, " ON CLUSTER {on_cluster}")?;
6080 }
6081 if let Some(partition) = partition {
6082 write!(f, " {partition}")?;
6083 }
6084 if *include_final {
6085 write!(f, " FINAL")?;
6086 }
6087 if let Some(deduplicate) = deduplicate {
6088 write!(f, " {deduplicate}")?;
6089 }
6090 Ok(())
6091 }
6092 Statement::LISTEN { channel } => {
6093 write!(f, "LISTEN {channel}")?;
6094 Ok(())
6095 }
6096 Statement::UNLISTEN { channel } => {
6097 write!(f, "UNLISTEN {channel}")?;
6098 Ok(())
6099 }
6100 Statement::NOTIFY { channel, payload } => {
6101 write!(f, "NOTIFY {channel}")?;
6102 if let Some(payload) = payload {
6103 write!(f, ", '{payload}'")?;
6104 }
6105 Ok(())
6106 }
6107 Statement::RenameTable(rename_tables) => {
6108 write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
6109 }
6110 Statement::RaisError {
6111 message,
6112 severity,
6113 state,
6114 arguments,
6115 options,
6116 } => {
6117 write!(f, "RAISERROR({message}, {severity}, {state}")?;
6118 if !arguments.is_empty() {
6119 write!(f, ", {}", display_comma_separated(arguments))?;
6120 }
6121 write!(f, ")")?;
6122 if !options.is_empty() {
6123 write!(f, " WITH {}", display_comma_separated(options))?;
6124 }
6125 Ok(())
6126 }
6127 Statement::Print(s) => write!(f, "{s}"),
6128 Statement::Return(r) => write!(f, "{r}"),
6129 Statement::List(command) => write!(f, "LIST {command}"),
6130 Statement::Remove(command) => write!(f, "REMOVE {command}"),
6131 Statement::ExportData(e) => write!(f, "{e}"),
6132 Statement::CreateUser(s) => write!(f, "{s}"),
6133 Statement::AlterSchema(s) => write!(f, "{s}"),
6134 Statement::Vacuum(s) => write!(f, "{s}"),
6135 Statement::AlterUser(s) => write!(f, "{s}"),
6136 Statement::Reset(s) => write!(f, "{s}"),
6137 }
6138 }
6139}
6140
6141/// Can use to describe options in create sequence or table column type identity
6142/// ```sql
6143/// [ INCREMENT [ BY ] increment ]
6144/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6145/// [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
6146/// ```
6147#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6148#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6149#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6150pub enum SequenceOptions {
6151 /// `INCREMENT [BY] <expr>` option; second value indicates presence of `BY` keyword.
6152 IncrementBy(Expr, bool),
6153 /// `MINVALUE <expr>` or `NO MINVALUE`.
6154 MinValue(Option<Expr>),
6155 /// `MAXVALUE <expr>` or `NO MAXVALUE`.
6156 MaxValue(Option<Expr>),
6157 /// `START [WITH] <expr>`; second value indicates presence of `WITH`.
6158 StartWith(Expr, bool),
6159 /// `CACHE <expr>` option.
6160 Cache(Expr),
6161 /// `CYCLE` or `NO CYCLE` option.
6162 Cycle(bool),
6163}
6164
6165impl fmt::Display for SequenceOptions {
6166 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6167 match self {
6168 SequenceOptions::IncrementBy(increment, by) => {
6169 write!(
6170 f,
6171 " INCREMENT{by} {increment}",
6172 by = if *by { " BY" } else { "" },
6173 increment = increment
6174 )
6175 }
6176 SequenceOptions::MinValue(Some(expr)) => {
6177 write!(f, " MINVALUE {expr}")
6178 }
6179 SequenceOptions::MinValue(None) => {
6180 write!(f, " NO MINVALUE")
6181 }
6182 SequenceOptions::MaxValue(Some(expr)) => {
6183 write!(f, " MAXVALUE {expr}")
6184 }
6185 SequenceOptions::MaxValue(None) => {
6186 write!(f, " NO MAXVALUE")
6187 }
6188 SequenceOptions::StartWith(start, with) => {
6189 write!(
6190 f,
6191 " START{with} {start}",
6192 with = if *with { " WITH" } else { "" },
6193 start = start
6194 )
6195 }
6196 SequenceOptions::Cache(cache) => {
6197 write!(f, " CACHE {}", *cache)
6198 }
6199 SequenceOptions::Cycle(no) => {
6200 write!(f, " {}CYCLE", if *no { "NO " } else { "" })
6201 }
6202 }
6203 }
6204}
6205
6206/// Assignment for a `SET` statement (name [=|TO] value)
6207#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6208#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6209#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6210pub struct SetAssignment {
6211 /// Optional context scope (e.g., SESSION or LOCAL).
6212 pub scope: Option<ContextModifier>,
6213 /// Assignment target name.
6214 pub name: ObjectName,
6215 /// Assigned expression value.
6216 pub value: Expr,
6217}
6218
6219impl fmt::Display for SetAssignment {
6220 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6221 write!(
6222 f,
6223 "{}{} = {}",
6224 self.scope.map(|s| format!("{s}")).unwrap_or_default(),
6225 self.name,
6226 self.value
6227 )
6228 }
6229}
6230
6231/// Target of a `TRUNCATE TABLE` command
6232///
6233/// Note this is its own struct because `visit_relation` requires an `ObjectName` (not a `Vec<ObjectName>`)
6234#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6235#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6236#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6237pub struct TruncateTableTarget {
6238 /// name of the table being truncated
6239 #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
6240 pub name: ObjectName,
6241 /// Postgres-specific option: explicitly exclude descendants (also default without ONLY)
6242 /// ```sql
6243 /// TRUNCATE TABLE ONLY name
6244 /// ```
6245 /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6246 pub only: bool,
6247 /// Postgres-specific option: asterisk after table name to explicitly indicate descendants
6248 /// ```sql
6249 /// TRUNCATE TABLE name [ * ]
6250 /// ```
6251 /// <https://www.postgresql.org/docs/current/sql-truncate.html>
6252 pub has_asterisk: bool,
6253}
6254
6255impl fmt::Display for TruncateTableTarget {
6256 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6257 if self.only {
6258 write!(f, "ONLY ")?;
6259 };
6260 write!(f, "{}", self.name)?;
6261 if self.has_asterisk {
6262 write!(f, " *")?;
6263 };
6264 Ok(())
6265 }
6266}
6267
6268/// PostgreSQL identity option for TRUNCATE table
6269/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
6270#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6271#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6272#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6273pub enum TruncateIdentityOption {
6274 /// Restart identity values (RESTART IDENTITY).
6275 Restart,
6276 /// Continue identity values (CONTINUE IDENTITY).
6277 Continue,
6278}
6279
6280/// Cascade/restrict option for Postgres TRUNCATE table, MySQL GRANT/REVOKE, etc.
6281/// [ CASCADE | RESTRICT ]
6282#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6283#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6284#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6285pub enum CascadeOption {
6286 /// Apply cascading action (e.g., CASCADE).
6287 Cascade,
6288 /// Restrict the action (e.g., RESTRICT).
6289 Restrict,
6290}
6291
6292impl Display for CascadeOption {
6293 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6294 match self {
6295 CascadeOption::Cascade => write!(f, "CASCADE"),
6296 CascadeOption::Restrict => write!(f, "RESTRICT"),
6297 }
6298 }
6299}
6300
6301/// Transaction started with [ TRANSACTION | WORK ]
6302#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6303#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6304#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6305pub enum BeginTransactionKind {
6306 /// Standard `TRANSACTION` keyword.
6307 Transaction,
6308 /// Alternate `WORK` keyword.
6309 Work,
6310}
6311
6312impl Display for BeginTransactionKind {
6313 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6314 match self {
6315 BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
6316 BeginTransactionKind::Work => write!(f, "WORK"),
6317 }
6318 }
6319}
6320
6321/// Can use to describe options in create sequence or table column type identity
6322/// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
6323#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6324#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6325#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6326pub enum MinMaxValue {
6327 /// Clause is not specified.
6328 Empty,
6329 /// NO MINVALUE / NO MAXVALUE.
6330 None,
6331 /// `MINVALUE <expr>` / `MAXVALUE <expr>`.
6332 Some(Expr),
6333}
6334
6335#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6336#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6337#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6338#[non_exhaustive]
6339/// Behavior to apply for `INSERT` when a conflict occurs.
6340pub enum OnInsert {
6341 /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead)
6342 DuplicateKeyUpdate(Vec<Assignment>),
6343 /// ON CONFLICT is a PostgreSQL and Sqlite extension
6344 OnConflict(OnConflict),
6345}
6346
6347#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6348#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6349#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6350/// Optional aliases for `INSERT` targets: row alias and optional column aliases.
6351pub struct InsertAliases {
6352 /// Row alias (table-style alias) for the inserted values.
6353 pub row_alias: ObjectName,
6354 /// Optional list of column aliases for the inserted values.
6355 pub col_aliases: Option<Vec<Ident>>,
6356}
6357
6358#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6359#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6360#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6361/// `ON CONFLICT` clause representation.
6362pub struct OnConflict {
6363 /// Optional conflict target specifying columns or constraint.
6364 pub conflict_target: Option<ConflictTarget>,
6365 /// Action to take when a conflict occurs.
6366 pub action: OnConflictAction,
6367}
6368#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6369#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6370#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6371/// Target specification for an `ON CONFLICT` clause.
6372pub enum ConflictTarget {
6373 /// Target specified as a list of columns.
6374 Columns(Vec<Ident>),
6375 /// Target specified as a named constraint.
6376 OnConstraint(ObjectName),
6377}
6378#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6379#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6380#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6381/// Action to perform when an `ON CONFLICT` target is matched.
6382pub enum OnConflictAction {
6383 /// Do nothing on conflict.
6384 DoNothing,
6385 /// Perform an update on conflict.
6386 DoUpdate(DoUpdate),
6387}
6388
6389#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6390#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6391#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6392/// Details for `DO UPDATE` action of an `ON CONFLICT` clause.
6393pub struct DoUpdate {
6394 /// Column assignments to perform on update.
6395 pub assignments: Vec<Assignment>,
6396 /// Optional WHERE clause limiting the update.
6397 pub selection: Option<Expr>,
6398}
6399
6400impl fmt::Display for OnInsert {
6401 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6402 match self {
6403 Self::DuplicateKeyUpdate(expr) => write!(
6404 f,
6405 " ON DUPLICATE KEY UPDATE {}",
6406 display_comma_separated(expr)
6407 ),
6408 Self::OnConflict(o) => write!(f, "{o}"),
6409 }
6410 }
6411}
6412impl fmt::Display for OnConflict {
6413 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6414 write!(f, " ON CONFLICT")?;
6415 if let Some(target) = &self.conflict_target {
6416 write!(f, "{target}")?;
6417 }
6418 write!(f, " {}", self.action)
6419 }
6420}
6421impl fmt::Display for ConflictTarget {
6422 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6423 match self {
6424 ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
6425 ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {name}"),
6426 }
6427 }
6428}
6429impl fmt::Display for OnConflictAction {
6430 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6431 match self {
6432 Self::DoNothing => write!(f, "DO NOTHING"),
6433 Self::DoUpdate(do_update) => {
6434 write!(f, "DO UPDATE")?;
6435 if !do_update.assignments.is_empty() {
6436 write!(
6437 f,
6438 " SET {}",
6439 display_comma_separated(&do_update.assignments)
6440 )?;
6441 }
6442 if let Some(selection) = &do_update.selection {
6443 write!(f, " WHERE {selection}")?;
6444 }
6445 Ok(())
6446 }
6447 }
6448 }
6449}
6450
6451/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
6452#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6453#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6454#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6455pub enum Privileges {
6456 /// All privileges applicable to the object type
6457 All {
6458 /// Optional keyword from the spec, ignored in practice
6459 with_privileges_keyword: bool,
6460 },
6461 /// Specific privileges (e.g. `SELECT`, `INSERT`)
6462 Actions(Vec<Action>),
6463}
6464
6465impl fmt::Display for Privileges {
6466 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6467 match self {
6468 Privileges::All {
6469 with_privileges_keyword,
6470 } => {
6471 write!(
6472 f,
6473 "ALL{}",
6474 if *with_privileges_keyword {
6475 " PRIVILEGES"
6476 } else {
6477 ""
6478 }
6479 )
6480 }
6481 Privileges::Actions(actions) => {
6482 write!(f, "{}", display_comma_separated(actions))
6483 }
6484 }
6485 }
6486}
6487
6488/// Specific direction for FETCH statement
6489#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6490#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6491#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6492pub enum FetchDirection {
6493 /// Fetch a specific count of rows.
6494 Count {
6495 /// The limit value for the count.
6496 limit: Value,
6497 },
6498 /// Fetch the next row.
6499 Next,
6500 /// Fetch the prior row.
6501 Prior,
6502 /// Fetch the first row.
6503 First,
6504 /// Fetch the last row.
6505 Last,
6506 /// Fetch an absolute row by index.
6507 Absolute {
6508 /// The absolute index value.
6509 limit: Value,
6510 },
6511 /// Fetch a row relative to the current position.
6512 Relative {
6513 /// The relative offset value.
6514 limit: Value,
6515 },
6516 /// Fetch all rows.
6517 All,
6518 // FORWARD
6519 // FORWARD count
6520 /// Fetch forward by an optional limit.
6521 Forward {
6522 /// Optional forward limit.
6523 limit: Option<Value>,
6524 },
6525 /// Fetch all forward rows.
6526 ForwardAll,
6527 // BACKWARD
6528 // BACKWARD count
6529 /// Fetch backward by an optional limit.
6530 Backward {
6531 /// Optional backward limit.
6532 limit: Option<Value>,
6533 },
6534 /// Fetch all backward rows.
6535 BackwardAll,
6536}
6537
6538impl fmt::Display for FetchDirection {
6539 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6540 match self {
6541 FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
6542 FetchDirection::Next => f.write_str("NEXT")?,
6543 FetchDirection::Prior => f.write_str("PRIOR")?,
6544 FetchDirection::First => f.write_str("FIRST")?,
6545 FetchDirection::Last => f.write_str("LAST")?,
6546 FetchDirection::Absolute { limit } => {
6547 f.write_str("ABSOLUTE ")?;
6548 f.write_str(&limit.to_string())?;
6549 }
6550 FetchDirection::Relative { limit } => {
6551 f.write_str("RELATIVE ")?;
6552 f.write_str(&limit.to_string())?;
6553 }
6554 FetchDirection::All => f.write_str("ALL")?,
6555 FetchDirection::Forward { limit } => {
6556 f.write_str("FORWARD")?;
6557
6558 if let Some(l) = limit {
6559 f.write_str(" ")?;
6560 f.write_str(&l.to_string())?;
6561 }
6562 }
6563 FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
6564 FetchDirection::Backward { limit } => {
6565 f.write_str("BACKWARD")?;
6566
6567 if let Some(l) = limit {
6568 f.write_str(" ")?;
6569 f.write_str(&l.to_string())?;
6570 }
6571 }
6572 FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
6573 };
6574
6575 Ok(())
6576 }
6577}
6578
6579/// The "position" for a FETCH statement.
6580///
6581/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/fetch-transact-sql)
6582#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6583#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6584#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6585pub enum FetchPosition {
6586 /// Use `FROM <pos>` position specifier.
6587 From,
6588 /// Use `IN <pos>` position specifier.
6589 In,
6590}
6591
6592impl fmt::Display for FetchPosition {
6593 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6594 match self {
6595 FetchPosition::From => f.write_str("FROM")?,
6596 FetchPosition::In => f.write_str("IN")?,
6597 };
6598
6599 Ok(())
6600 }
6601}
6602
6603/// A privilege on a database object (table, sequence, etc.).
6604#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6605#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6606#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6607pub enum Action {
6608 /// Add a search optimization.
6609 AddSearchOptimization,
6610 /// Apply an `APPLY` operation with a specific type.
6611 Apply {
6612 /// The type of apply operation.
6613 apply_type: ActionApplyType,
6614 },
6615 /// Apply a budget operation.
6616 ApplyBudget,
6617 /// Attach a listing.
6618 AttachListing,
6619 /// Attach a policy.
6620 AttachPolicy,
6621 /// Audit operation.
6622 Audit,
6623 /// Bind a service endpoint.
6624 BindServiceEndpoint,
6625 /// Connect permission.
6626 Connect,
6627 /// Create action, optionally specifying an object type.
6628 Create {
6629 /// Optional object type to create.
6630 obj_type: Option<ActionCreateObjectType>,
6631 },
6632 /// Actions related to database roles.
6633 DatabaseRole {
6634 /// The role name.
6635 role: ObjectName,
6636 },
6637 /// Delete permission.
6638 Delete,
6639 /// Drop permission.
6640 Drop,
6641 /// Evolve schema permission.
6642 EvolveSchema,
6643 /// Exec action (execute) with optional object type.
6644 Exec {
6645 /// Optional execute object type.
6646 obj_type: Option<ActionExecuteObjectType>,
6647 },
6648 /// Execute action with optional object type.
6649 Execute {
6650 /// Optional execute object type.
6651 obj_type: Option<ActionExecuteObjectType>,
6652 },
6653 /// Failover operation.
6654 Failover,
6655 /// Use imported privileges.
6656 ImportedPrivileges,
6657 /// Import a share.
6658 ImportShare,
6659 /// Insert rows with optional column list.
6660 Insert {
6661 /// Optional list of target columns for insert.
6662 columns: Option<Vec<Ident>>,
6663 },
6664 /// Manage operation with a specific manage type.
6665 Manage {
6666 /// The specific manage sub-type.
6667 manage_type: ActionManageType,
6668 },
6669 /// Manage releases.
6670 ManageReleases,
6671 /// Manage versions.
6672 ManageVersions,
6673 /// Modify operation with an optional modify type.
6674 Modify {
6675 /// The optional modify sub-type.
6676 modify_type: Option<ActionModifyType>,
6677 },
6678 /// Monitor operation with an optional monitor type.
6679 Monitor {
6680 /// The optional monitor sub-type.
6681 monitor_type: Option<ActionMonitorType>,
6682 },
6683 /// Operate permission.
6684 Operate,
6685 /// Override share restrictions.
6686 OverrideShareRestrictions,
6687 /// Ownership permission.
6688 Ownership,
6689 /// Purchase a data exchange listing.
6690 PurchaseDataExchangeListing,
6691
6692 /// Read access.
6693 Read,
6694 /// Read session-level access.
6695 ReadSession,
6696 /// References with optional column list.
6697 References {
6698 /// Optional list of referenced column identifiers.
6699 columns: Option<Vec<Ident>>,
6700 },
6701 /// Replication permission.
6702 Replicate,
6703 /// Resolve all references.
6704 ResolveAll,
6705 /// Role-related permission with target role name.
6706 Role {
6707 /// The target role name.
6708 role: ObjectName,
6709 },
6710 /// Select permission with optional column list.
6711 Select {
6712 /// Optional list of selected columns.
6713 columns: Option<Vec<Ident>>,
6714 },
6715 /// Temporary object permission.
6716 Temporary,
6717 /// Trigger-related permission.
6718 Trigger,
6719 /// Truncate permission.
6720 Truncate,
6721 /// Update permission with optional affected columns.
6722 Update {
6723 /// Optional list of columns affected by update.
6724 columns: Option<Vec<Ident>>,
6725 },
6726 /// Usage permission.
6727 Usage,
6728}
6729
6730impl fmt::Display for Action {
6731 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6732 match self {
6733 Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
6734 Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
6735 Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
6736 Action::AttachListing => f.write_str("ATTACH LISTING")?,
6737 Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
6738 Action::Audit => f.write_str("AUDIT")?,
6739 Action::BindServiceEndpoint => f.write_str("BIND SERVICE ENDPOINT")?,
6740 Action::Connect => f.write_str("CONNECT")?,
6741 Action::Create { obj_type } => {
6742 f.write_str("CREATE")?;
6743 if let Some(obj_type) = obj_type {
6744 write!(f, " {obj_type}")?
6745 }
6746 }
6747 Action::DatabaseRole { role } => write!(f, "DATABASE ROLE {role}")?,
6748 Action::Delete => f.write_str("DELETE")?,
6749 Action::Drop => f.write_str("DROP")?,
6750 Action::EvolveSchema => f.write_str("EVOLVE SCHEMA")?,
6751 Action::Exec { obj_type } => {
6752 f.write_str("EXEC")?;
6753 if let Some(obj_type) = obj_type {
6754 write!(f, " {obj_type}")?
6755 }
6756 }
6757 Action::Execute { obj_type } => {
6758 f.write_str("EXECUTE")?;
6759 if let Some(obj_type) = obj_type {
6760 write!(f, " {obj_type}")?
6761 }
6762 }
6763 Action::Failover => f.write_str("FAILOVER")?,
6764 Action::ImportedPrivileges => f.write_str("IMPORTED PRIVILEGES")?,
6765 Action::ImportShare => f.write_str("IMPORT SHARE")?,
6766 Action::Insert { .. } => f.write_str("INSERT")?,
6767 Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
6768 Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
6769 Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
6770 Action::Modify { modify_type } => {
6771 write!(f, "MODIFY")?;
6772 if let Some(modify_type) = modify_type {
6773 write!(f, " {modify_type}")?;
6774 }
6775 }
6776 Action::Monitor { monitor_type } => {
6777 write!(f, "MONITOR")?;
6778 if let Some(monitor_type) = monitor_type {
6779 write!(f, " {monitor_type}")?
6780 }
6781 }
6782 Action::Operate => f.write_str("OPERATE")?,
6783 Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
6784 Action::Ownership => f.write_str("OWNERSHIP")?,
6785 Action::PurchaseDataExchangeListing => f.write_str("PURCHASE DATA EXCHANGE LISTING")?,
6786 Action::Read => f.write_str("READ")?,
6787 Action::ReadSession => f.write_str("READ SESSION")?,
6788 Action::References { .. } => f.write_str("REFERENCES")?,
6789 Action::Replicate => f.write_str("REPLICATE")?,
6790 Action::ResolveAll => f.write_str("RESOLVE ALL")?,
6791 Action::Role { role } => write!(f, "ROLE {role}")?,
6792 Action::Select { .. } => f.write_str("SELECT")?,
6793 Action::Temporary => f.write_str("TEMPORARY")?,
6794 Action::Trigger => f.write_str("TRIGGER")?,
6795 Action::Truncate => f.write_str("TRUNCATE")?,
6796 Action::Update { .. } => f.write_str("UPDATE")?,
6797 Action::Usage => f.write_str("USAGE")?,
6798 };
6799 match self {
6800 Action::Insert { columns }
6801 | Action::References { columns }
6802 | Action::Select { columns }
6803 | Action::Update { columns } => {
6804 if let Some(columns) = columns {
6805 write!(f, " ({})", display_comma_separated(columns))?;
6806 }
6807 }
6808 _ => (),
6809 };
6810 Ok(())
6811 }
6812}
6813
6814#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6815#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6816#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6817/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6818/// under `globalPrivileges` in the `CREATE` privilege.
6819pub enum ActionCreateObjectType {
6820 /// An account-level object.
6821 Account,
6822 /// An application object.
6823 Application,
6824 /// An application package object.
6825 ApplicationPackage,
6826 /// A compute pool object.
6827 ComputePool,
6828 /// A data exchange listing.
6829 DataExchangeListing,
6830 /// A database object.
6831 Database,
6832 /// An external volume object.
6833 ExternalVolume,
6834 /// A failover group object.
6835 FailoverGroup,
6836 /// An integration object.
6837 Integration,
6838 /// A network policy object.
6839 NetworkPolicy,
6840 /// An organization listing.
6841 OrganiationListing,
6842 /// A replication group object.
6843 ReplicationGroup,
6844 /// A role object.
6845 Role,
6846 /// A schema object.
6847 Schema,
6848 /// A share object.
6849 Share,
6850 /// A user object.
6851 User,
6852 /// A warehouse object.
6853 Warehouse,
6854}
6855
6856impl fmt::Display for ActionCreateObjectType {
6857 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6858 match self {
6859 ActionCreateObjectType::Account => write!(f, "ACCOUNT"),
6860 ActionCreateObjectType::Application => write!(f, "APPLICATION"),
6861 ActionCreateObjectType::ApplicationPackage => write!(f, "APPLICATION PACKAGE"),
6862 ActionCreateObjectType::ComputePool => write!(f, "COMPUTE POOL"),
6863 ActionCreateObjectType::DataExchangeListing => write!(f, "DATA EXCHANGE LISTING"),
6864 ActionCreateObjectType::Database => write!(f, "DATABASE"),
6865 ActionCreateObjectType::ExternalVolume => write!(f, "EXTERNAL VOLUME"),
6866 ActionCreateObjectType::FailoverGroup => write!(f, "FAILOVER GROUP"),
6867 ActionCreateObjectType::Integration => write!(f, "INTEGRATION"),
6868 ActionCreateObjectType::NetworkPolicy => write!(f, "NETWORK POLICY"),
6869 ActionCreateObjectType::OrganiationListing => write!(f, "ORGANIZATION LISTING"),
6870 ActionCreateObjectType::ReplicationGroup => write!(f, "REPLICATION GROUP"),
6871 ActionCreateObjectType::Role => write!(f, "ROLE"),
6872 ActionCreateObjectType::Schema => write!(f, "SCHEMA"),
6873 ActionCreateObjectType::Share => write!(f, "SHARE"),
6874 ActionCreateObjectType::User => write!(f, "USER"),
6875 ActionCreateObjectType::Warehouse => write!(f, "WAREHOUSE"),
6876 }
6877 }
6878}
6879
6880#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6881#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6882#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6883/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6884/// under `globalPrivileges` in the `APPLY` privilege.
6885pub enum ActionApplyType {
6886 /// Apply an aggregation policy.
6887 AggregationPolicy,
6888 /// Apply an authentication policy.
6889 AuthenticationPolicy,
6890 /// Apply a join policy.
6891 JoinPolicy,
6892 /// Apply a masking policy.
6893 MaskingPolicy,
6894 /// Apply a packages policy.
6895 PackagesPolicy,
6896 /// Apply a password policy.
6897 PasswordPolicy,
6898 /// Apply a projection policy.
6899 ProjectionPolicy,
6900 /// Apply a row access policy.
6901 RowAccessPolicy,
6902 /// Apply a session policy.
6903 SessionPolicy,
6904 /// Apply a tag.
6905 Tag,
6906}
6907
6908impl fmt::Display for ActionApplyType {
6909 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6910 match self {
6911 ActionApplyType::AggregationPolicy => write!(f, "AGGREGATION POLICY"),
6912 ActionApplyType::AuthenticationPolicy => write!(f, "AUTHENTICATION POLICY"),
6913 ActionApplyType::JoinPolicy => write!(f, "JOIN POLICY"),
6914 ActionApplyType::MaskingPolicy => write!(f, "MASKING POLICY"),
6915 ActionApplyType::PackagesPolicy => write!(f, "PACKAGES POLICY"),
6916 ActionApplyType::PasswordPolicy => write!(f, "PASSWORD POLICY"),
6917 ActionApplyType::ProjectionPolicy => write!(f, "PROJECTION POLICY"),
6918 ActionApplyType::RowAccessPolicy => write!(f, "ROW ACCESS POLICY"),
6919 ActionApplyType::SessionPolicy => write!(f, "SESSION POLICY"),
6920 ActionApplyType::Tag => write!(f, "TAG"),
6921 }
6922 }
6923}
6924
6925#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6926#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6927#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6928/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6929/// under `globalPrivileges` in the `EXECUTE` privilege.
6930pub enum ActionExecuteObjectType {
6931 /// Alert object.
6932 Alert,
6933 /// Data metric function object.
6934 DataMetricFunction,
6935 /// Managed alert object.
6936 ManagedAlert,
6937 /// Managed task object.
6938 ManagedTask,
6939 /// Task object.
6940 Task,
6941}
6942
6943impl fmt::Display for ActionExecuteObjectType {
6944 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6945 match self {
6946 ActionExecuteObjectType::Alert => write!(f, "ALERT"),
6947 ActionExecuteObjectType::DataMetricFunction => write!(f, "DATA METRIC FUNCTION"),
6948 ActionExecuteObjectType::ManagedAlert => write!(f, "MANAGED ALERT"),
6949 ActionExecuteObjectType::ManagedTask => write!(f, "MANAGED TASK"),
6950 ActionExecuteObjectType::Task => write!(f, "TASK"),
6951 }
6952 }
6953}
6954
6955#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6956#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6957#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6958/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6959/// under `globalPrivileges` in the `MANAGE` privilege.
6960pub enum ActionManageType {
6961 /// Account support cases management.
6962 AccountSupportCases,
6963 /// Event sharing management.
6964 EventSharing,
6965 /// Grants management.
6966 Grants,
6967 /// Listing auto-fulfillment management.
6968 ListingAutoFulfillment,
6969 /// Organization support cases management.
6970 OrganizationSupportCases,
6971 /// User support cases management.
6972 UserSupportCases,
6973 /// Warehouses management.
6974 Warehouses,
6975}
6976
6977impl fmt::Display for ActionManageType {
6978 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6979 match self {
6980 ActionManageType::AccountSupportCases => write!(f, "ACCOUNT SUPPORT CASES"),
6981 ActionManageType::EventSharing => write!(f, "EVENT SHARING"),
6982 ActionManageType::Grants => write!(f, "GRANTS"),
6983 ActionManageType::ListingAutoFulfillment => write!(f, "LISTING AUTO FULFILLMENT"),
6984 ActionManageType::OrganizationSupportCases => write!(f, "ORGANIZATION SUPPORT CASES"),
6985 ActionManageType::UserSupportCases => write!(f, "USER SUPPORT CASES"),
6986 ActionManageType::Warehouses => write!(f, "WAREHOUSES"),
6987 }
6988 }
6989}
6990
6991#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6992#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6993#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6994/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
6995/// under `globalPrivileges` in the `MODIFY` privilege.
6996pub enum ActionModifyType {
6997 /// Modify log level.
6998 LogLevel,
6999 /// Modify trace level.
7000 TraceLevel,
7001 /// Modify session log level.
7002 SessionLogLevel,
7003 /// Modify session trace level.
7004 SessionTraceLevel,
7005}
7006
7007impl fmt::Display for ActionModifyType {
7008 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7009 match self {
7010 ActionModifyType::LogLevel => write!(f, "LOG LEVEL"),
7011 ActionModifyType::TraceLevel => write!(f, "TRACE LEVEL"),
7012 ActionModifyType::SessionLogLevel => write!(f, "SESSION LOG LEVEL"),
7013 ActionModifyType::SessionTraceLevel => write!(f, "SESSION TRACE LEVEL"),
7014 }
7015 }
7016}
7017
7018#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7019#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7020#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7021/// See <https://docs.snowflake.com/en/sql-reference/sql/grant-privilege>
7022/// under `globalPrivileges` in the `MONITOR` privilege.
7023pub enum ActionMonitorType {
7024 /// Monitor execution.
7025 Execution,
7026 /// Monitor security.
7027 Security,
7028 /// Monitor usage.
7029 Usage,
7030}
7031
7032impl fmt::Display for ActionMonitorType {
7033 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7034 match self {
7035 ActionMonitorType::Execution => write!(f, "EXECUTION"),
7036 ActionMonitorType::Security => write!(f, "SECURITY"),
7037 ActionMonitorType::Usage => write!(f, "USAGE"),
7038 }
7039 }
7040}
7041
7042/// The principal that receives the privileges
7043#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7044#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7045#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7046pub struct Grantee {
7047 /// The category/type of grantee (role, user, share, etc.).
7048 pub grantee_type: GranteesType,
7049 /// Optional name of the grantee (identifier or user@host).
7050 pub name: Option<GranteeName>,
7051}
7052
7053impl fmt::Display for Grantee {
7054 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7055 match self.grantee_type {
7056 GranteesType::Role => {
7057 write!(f, "ROLE ")?;
7058 }
7059 GranteesType::Share => {
7060 write!(f, "SHARE ")?;
7061 }
7062 GranteesType::User => {
7063 write!(f, "USER ")?;
7064 }
7065 GranteesType::Group => {
7066 write!(f, "GROUP ")?;
7067 }
7068 GranteesType::Public => {
7069 write!(f, "PUBLIC ")?;
7070 }
7071 GranteesType::DatabaseRole => {
7072 write!(f, "DATABASE ROLE ")?;
7073 }
7074 GranteesType::Application => {
7075 write!(f, "APPLICATION ")?;
7076 }
7077 GranteesType::ApplicationRole => {
7078 write!(f, "APPLICATION ROLE ")?;
7079 }
7080 GranteesType::None => (),
7081 }
7082 if let Some(ref name) = self.name {
7083 name.fmt(f)?;
7084 }
7085 Ok(())
7086 }
7087}
7088
7089#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7090#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7091#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7092/// The kind of principal receiving privileges.
7093pub enum GranteesType {
7094 /// A role principal.
7095 Role,
7096 /// A share principal.
7097 Share,
7098 /// A user principal.
7099 User,
7100 /// A group principal.
7101 Group,
7102 /// The public principal.
7103 Public,
7104 /// A database role principal.
7105 DatabaseRole,
7106 /// An application principal.
7107 Application,
7108 /// An application role principal.
7109 ApplicationRole,
7110 /// No specific principal (e.g. `NONE`).
7111 None,
7112}
7113
7114/// Users/roles designated in a GRANT/REVOKE
7115#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7116#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7117#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7118pub enum GranteeName {
7119 /// A bare identifier
7120 ObjectName(ObjectName),
7121 /// A MySQL user/host pair such as 'root'@'%'
7122 UserHost {
7123 /// The user identifier portion.
7124 user: Ident,
7125 /// The host identifier portion.
7126 host: Ident,
7127 },
7128}
7129
7130impl fmt::Display for GranteeName {
7131 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7132 match self {
7133 GranteeName::ObjectName(name) => name.fmt(f),
7134 GranteeName::UserHost { user, host } => {
7135 write!(f, "{user}@{host}")
7136 }
7137 }
7138 }
7139}
7140
7141/// Objects on which privileges are granted in a GRANT statement.
7142#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7143#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7144#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7145pub enum GrantObjects {
7146 /// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
7147 AllSequencesInSchema {
7148 /// The target schema names.
7149 schemas: Vec<ObjectName>,
7150 },
7151 /// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
7152 AllTablesInSchema {
7153 /// The target schema names.
7154 schemas: Vec<ObjectName>,
7155 },
7156 /// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
7157 AllViewsInSchema {
7158 /// The target schema names.
7159 schemas: Vec<ObjectName>,
7160 },
7161 /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7162 AllMaterializedViewsInSchema {
7163 /// The target schema names.
7164 schemas: Vec<ObjectName>,
7165 },
7166 /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7167 AllExternalTablesInSchema {
7168 /// The target schema names.
7169 schemas: Vec<ObjectName>,
7170 },
7171 /// Grant privileges on `ALL FUNCTIONS IN SCHEMA <schema_name> [, ...]`
7172 AllFunctionsInSchema {
7173 /// The target schema names.
7174 schemas: Vec<ObjectName>,
7175 },
7176 /// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
7177 FutureSchemasInDatabase {
7178 /// The target database names.
7179 databases: Vec<ObjectName>,
7180 },
7181 /// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
7182 FutureTablesInSchema {
7183 /// The target schema names.
7184 schemas: Vec<ObjectName>,
7185 },
7186 /// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
7187 FutureViewsInSchema {
7188 /// The target schema names.
7189 schemas: Vec<ObjectName>,
7190 },
7191 /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
7192 FutureExternalTablesInSchema {
7193 /// The target schema names.
7194 schemas: Vec<ObjectName>,
7195 },
7196 /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
7197 FutureMaterializedViewsInSchema {
7198 /// The target schema names.
7199 schemas: Vec<ObjectName>,
7200 },
7201 /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
7202 FutureSequencesInSchema {
7203 /// The target schema names.
7204 schemas: Vec<ObjectName>,
7205 },
7206 /// Grant privileges on specific databases
7207 Databases(Vec<ObjectName>),
7208 /// Grant privileges on specific schemas
7209 Schemas(Vec<ObjectName>),
7210 /// Grant privileges on specific sequences
7211 Sequences(Vec<ObjectName>),
7212 /// Grant privileges on specific tables
7213 Tables(Vec<ObjectName>),
7214 /// Grant privileges on specific views
7215 Views(Vec<ObjectName>),
7216 /// Grant privileges on specific warehouses
7217 Warehouses(Vec<ObjectName>),
7218 /// Grant privileges on specific integrations
7219 Integrations(Vec<ObjectName>),
7220 /// Grant privileges on resource monitors
7221 ResourceMonitors(Vec<ObjectName>),
7222 /// Grant privileges on users
7223 Users(Vec<ObjectName>),
7224 /// Grant privileges on compute pools
7225 ComputePools(Vec<ObjectName>),
7226 /// Grant privileges on connections
7227 Connections(Vec<ObjectName>),
7228 /// Grant privileges on failover groups
7229 FailoverGroup(Vec<ObjectName>),
7230 /// Grant privileges on replication group
7231 ReplicationGroup(Vec<ObjectName>),
7232 /// Grant privileges on external volumes
7233 ExternalVolumes(Vec<ObjectName>),
7234 /// Grant privileges on a procedure. In dialects that
7235 /// support overloading, the argument types must be specified.
7236 ///
7237 /// For example:
7238 /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1`
7239 Procedure {
7240 /// The procedure name.
7241 name: ObjectName,
7242 /// Optional argument types for overloaded procedures.
7243 arg_types: Vec<DataType>,
7244 },
7245
7246 /// Grant privileges on a function. In dialects that
7247 /// support overloading, the argument types must be specified.
7248 ///
7249 /// For example:
7250 /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1`
7251 Function {
7252 /// The function name.
7253 name: ObjectName,
7254 /// Optional argument types for overloaded functions.
7255 arg_types: Vec<DataType>,
7256 },
7257}
7258
7259impl fmt::Display for GrantObjects {
7260 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7261 match self {
7262 GrantObjects::Sequences(sequences) => {
7263 write!(f, "SEQUENCE {}", display_comma_separated(sequences))
7264 }
7265 GrantObjects::Databases(databases) => {
7266 write!(f, "DATABASE {}", display_comma_separated(databases))
7267 }
7268 GrantObjects::Schemas(schemas) => {
7269 write!(f, "SCHEMA {}", display_comma_separated(schemas))
7270 }
7271 GrantObjects::Tables(tables) => {
7272 write!(f, "{}", display_comma_separated(tables))
7273 }
7274 GrantObjects::Views(views) => {
7275 write!(f, "VIEW {}", display_comma_separated(views))
7276 }
7277 GrantObjects::Warehouses(warehouses) => {
7278 write!(f, "WAREHOUSE {}", display_comma_separated(warehouses))
7279 }
7280 GrantObjects::Integrations(integrations) => {
7281 write!(f, "INTEGRATION {}", display_comma_separated(integrations))
7282 }
7283 GrantObjects::AllSequencesInSchema { schemas } => {
7284 write!(
7285 f,
7286 "ALL SEQUENCES IN SCHEMA {}",
7287 display_comma_separated(schemas)
7288 )
7289 }
7290 GrantObjects::AllTablesInSchema { schemas } => {
7291 write!(
7292 f,
7293 "ALL TABLES IN SCHEMA {}",
7294 display_comma_separated(schemas)
7295 )
7296 }
7297 GrantObjects::AllExternalTablesInSchema { schemas } => {
7298 write!(
7299 f,
7300 "ALL EXTERNAL TABLES IN SCHEMA {}",
7301 display_comma_separated(schemas)
7302 )
7303 }
7304 GrantObjects::AllViewsInSchema { schemas } => {
7305 write!(
7306 f,
7307 "ALL VIEWS IN SCHEMA {}",
7308 display_comma_separated(schemas)
7309 )
7310 }
7311 GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7312 write!(
7313 f,
7314 "ALL MATERIALIZED VIEWS IN SCHEMA {}",
7315 display_comma_separated(schemas)
7316 )
7317 }
7318 GrantObjects::AllFunctionsInSchema { schemas } => {
7319 write!(
7320 f,
7321 "ALL FUNCTIONS IN SCHEMA {}",
7322 display_comma_separated(schemas)
7323 )
7324 }
7325 GrantObjects::FutureSchemasInDatabase { databases } => {
7326 write!(
7327 f,
7328 "FUTURE SCHEMAS IN DATABASE {}",
7329 display_comma_separated(databases)
7330 )
7331 }
7332 GrantObjects::FutureTablesInSchema { schemas } => {
7333 write!(
7334 f,
7335 "FUTURE TABLES IN SCHEMA {}",
7336 display_comma_separated(schemas)
7337 )
7338 }
7339 GrantObjects::FutureExternalTablesInSchema { schemas } => {
7340 write!(
7341 f,
7342 "FUTURE EXTERNAL TABLES IN SCHEMA {}",
7343 display_comma_separated(schemas)
7344 )
7345 }
7346 GrantObjects::FutureViewsInSchema { schemas } => {
7347 write!(
7348 f,
7349 "FUTURE VIEWS IN SCHEMA {}",
7350 display_comma_separated(schemas)
7351 )
7352 }
7353 GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7354 write!(
7355 f,
7356 "FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7357 display_comma_separated(schemas)
7358 )
7359 }
7360 GrantObjects::FutureSequencesInSchema { schemas } => {
7361 write!(
7362 f,
7363 "FUTURE SEQUENCES IN SCHEMA {}",
7364 display_comma_separated(schemas)
7365 )
7366 }
7367 GrantObjects::ResourceMonitors(objects) => {
7368 write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
7369 }
7370 GrantObjects::Users(objects) => {
7371 write!(f, "USER {}", display_comma_separated(objects))
7372 }
7373 GrantObjects::ComputePools(objects) => {
7374 write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
7375 }
7376 GrantObjects::Connections(objects) => {
7377 write!(f, "CONNECTION {}", display_comma_separated(objects))
7378 }
7379 GrantObjects::FailoverGroup(objects) => {
7380 write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
7381 }
7382 GrantObjects::ReplicationGroup(objects) => {
7383 write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
7384 }
7385 GrantObjects::ExternalVolumes(objects) => {
7386 write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
7387 }
7388 GrantObjects::Procedure { name, arg_types } => {
7389 write!(f, "PROCEDURE {name}")?;
7390 if !arg_types.is_empty() {
7391 write!(f, "({})", display_comma_separated(arg_types))?;
7392 }
7393 Ok(())
7394 }
7395 GrantObjects::Function { name, arg_types } => {
7396 write!(f, "FUNCTION {name}")?;
7397 if !arg_types.is_empty() {
7398 write!(f, "({})", display_comma_separated(arg_types))?;
7399 }
7400 Ok(())
7401 }
7402 }
7403 }
7404}
7405
7406/// A `DENY` statement
7407///
7408/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
7409#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7410#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7411#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7412pub struct DenyStatement {
7413 /// The privileges to deny.
7414 pub privileges: Privileges,
7415 /// The objects the privileges apply to.
7416 pub objects: GrantObjects,
7417 /// The grantees (users/roles) to whom the denial applies.
7418 pub grantees: Vec<Grantee>,
7419 /// Optional identifier of the principal that performed the grant.
7420 pub granted_by: Option<Ident>,
7421 /// Optional cascade option controlling dependent objects.
7422 pub cascade: Option<CascadeOption>,
7423}
7424
7425impl fmt::Display for DenyStatement {
7426 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7427 write!(f, "DENY {}", self.privileges)?;
7428 write!(f, " ON {}", self.objects)?;
7429 if !self.grantees.is_empty() {
7430 write!(f, " TO {}", display_comma_separated(&self.grantees))?;
7431 }
7432 if let Some(cascade) = &self.cascade {
7433 write!(f, " {cascade}")?;
7434 }
7435 if let Some(granted_by) = &self.granted_by {
7436 write!(f, " AS {granted_by}")?;
7437 }
7438 Ok(())
7439 }
7440}
7441
7442/// SQL assignment `foo = expr` as used in SQLUpdate
7443#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7444#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7445#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7446pub struct Assignment {
7447 /// The left-hand side of the assignment.
7448 pub target: AssignmentTarget,
7449 /// The expression assigned to the target.
7450 pub value: Expr,
7451}
7452
7453impl fmt::Display for Assignment {
7454 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7455 write!(f, "{} = {}", self.target, self.value)
7456 }
7457}
7458
7459/// Left-hand side of an assignment in an UPDATE statement,
7460/// e.g. `foo` in `foo = 5` (ColumnName assignment) or
7461/// `(a, b)` in `(a, b) = (1, 2)` (Tuple assignment).
7462#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7463#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7464#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7465pub enum AssignmentTarget {
7466 /// A single column
7467 ColumnName(ObjectName),
7468 /// A tuple of columns
7469 Tuple(Vec<ObjectName>),
7470}
7471
7472impl fmt::Display for AssignmentTarget {
7473 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7474 match self {
7475 AssignmentTarget::ColumnName(column) => write!(f, "{column}"),
7476 AssignmentTarget::Tuple(columns) => write!(f, "({})", display_comma_separated(columns)),
7477 }
7478 }
7479}
7480
7481#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7482#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7483#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7484/// Expression forms allowed as a function argument.
7485pub enum FunctionArgExpr {
7486 /// A normal expression argument.
7487 Expr(Expr),
7488 /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
7489 QualifiedWildcard(ObjectName),
7490 /// An unqualified `*` wildcard.
7491 Wildcard,
7492}
7493
7494impl From<Expr> for FunctionArgExpr {
7495 fn from(wildcard_expr: Expr) -> Self {
7496 match wildcard_expr {
7497 Expr::QualifiedWildcard(prefix, _) => Self::QualifiedWildcard(prefix),
7498 Expr::Wildcard(_) => Self::Wildcard,
7499 expr => Self::Expr(expr),
7500 }
7501 }
7502}
7503
7504impl fmt::Display for FunctionArgExpr {
7505 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7506 match self {
7507 FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
7508 FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
7509 FunctionArgExpr::Wildcard => f.write_str("*"),
7510 }
7511 }
7512}
7513
7514#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7515#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7516#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7517/// Operator used to separate function arguments
7518pub enum FunctionArgOperator {
7519 /// function(arg1 = value1)
7520 Equals,
7521 /// function(arg1 => value1)
7522 RightArrow,
7523 /// function(arg1 := value1)
7524 Assignment,
7525 /// function(arg1 : value1)
7526 Colon,
7527 /// function(arg1 VALUE value1)
7528 Value,
7529}
7530
7531impl fmt::Display for FunctionArgOperator {
7532 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7533 match self {
7534 FunctionArgOperator::Equals => f.write_str("="),
7535 FunctionArgOperator::RightArrow => f.write_str("=>"),
7536 FunctionArgOperator::Assignment => f.write_str(":="),
7537 FunctionArgOperator::Colon => f.write_str(":"),
7538 FunctionArgOperator::Value => f.write_str("VALUE"),
7539 }
7540 }
7541}
7542
7543#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7544#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7545#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7546/// Forms of function arguments (named, expression-named, or positional).
7547pub enum FunctionArg {
7548 /// `name` is identifier
7549 ///
7550 /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false'
7551 Named {
7552 /// The identifier name of the argument.
7553 name: Ident,
7554 /// The argument expression or wildcard form.
7555 arg: FunctionArgExpr,
7556 /// The operator separating name and value.
7557 operator: FunctionArgOperator,
7558 },
7559 /// `name` is arbitrary expression
7560 ///
7561 /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true'
7562 ExprNamed {
7563 /// The expression used as the argument name.
7564 name: Expr,
7565 /// The argument expression or wildcard form.
7566 arg: FunctionArgExpr,
7567 /// The operator separating name and value.
7568 operator: FunctionArgOperator,
7569 },
7570 /// An unnamed argument (positional), given by expression or wildcard.
7571 Unnamed(FunctionArgExpr),
7572}
7573
7574impl fmt::Display for FunctionArg {
7575 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7576 match self {
7577 FunctionArg::Named {
7578 name,
7579 arg,
7580 operator,
7581 } => write!(f, "{name} {operator} {arg}"),
7582 FunctionArg::ExprNamed {
7583 name,
7584 arg,
7585 operator,
7586 } => write!(f, "{name} {operator} {arg}"),
7587 FunctionArg::Unnamed(unnamed_arg) => write!(f, "{unnamed_arg}"),
7588 }
7589 }
7590}
7591
7592#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7593#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7594#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7595/// Which cursor(s) to close.
7596pub enum CloseCursor {
7597 /// Close all cursors.
7598 All,
7599 /// Close a specific cursor by name.
7600 Specific {
7601 /// The name of the cursor to close.
7602 name: Ident,
7603 },
7604}
7605
7606impl fmt::Display for CloseCursor {
7607 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7608 match self {
7609 CloseCursor::All => write!(f, "ALL"),
7610 CloseCursor::Specific { name } => write!(f, "{name}"),
7611 }
7612 }
7613}
7614
7615/// A Drop Domain statement
7616#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7617#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7618#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7619pub struct DropDomain {
7620 /// Whether to drop the domain if it exists
7621 pub if_exists: bool,
7622 /// The name of the domain to drop
7623 pub name: ObjectName,
7624 /// The behavior to apply when dropping the domain
7625 pub drop_behavior: Option<DropBehavior>,
7626}
7627
7628/// A constant of form `<data_type> 'value'`.
7629/// This can represent ANSI SQL `DATE`, `TIME`, and `TIMESTAMP` literals (such as `DATE '2020-01-01'`),
7630/// as well as constants of other types (a non-standard PostgreSQL extension).
7631#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7632#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7633#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7634pub struct TypedString {
7635 /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP).
7636 pub data_type: DataType,
7637 /// The value of the constant.
7638 /// Hint: you can unwrap the string value using `value.into_string()`.
7639 pub value: ValueWithSpan,
7640 /// Flags whether this TypedString uses the [ODBC syntax].
7641 ///
7642 /// Example:
7643 /// ```sql
7644 /// -- An ODBC date literal:
7645 /// SELECT {d '2025-07-16'}
7646 /// -- This is equivalent to the standard ANSI SQL literal:
7647 /// SELECT DATE '2025-07-16'
7648 ///
7649 /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/date-time-and-timestamp-literals?view=sql-server-2017
7650 pub uses_odbc_syntax: bool,
7651}
7652
7653impl fmt::Display for TypedString {
7654 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7655 let data_type = &self.data_type;
7656 let value = &self.value;
7657 match self.uses_odbc_syntax {
7658 false => {
7659 write!(f, "{data_type}")?;
7660 write!(f, " {value}")
7661 }
7662 true => {
7663 let prefix = match data_type {
7664 DataType::Date => "d",
7665 DataType::Time(..) => "t",
7666 DataType::Timestamp(..) => "ts",
7667 _ => "?",
7668 };
7669 write!(f, "{{{prefix} {value}}}")
7670 }
7671 }
7672 }
7673}
7674
7675/// A function call
7676#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7677#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7678#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7679pub struct Function {
7680 /// The function name (may be qualified).
7681 pub name: ObjectName,
7682 /// Flags whether this function call uses the [ODBC syntax].
7683 ///
7684 /// Example:
7685 /// ```sql
7686 /// SELECT {fn CONCAT('foo', 'bar')}
7687 /// ```
7688 ///
7689 /// [ODBC syntax]: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/scalar-function-calls?view=sql-server-2017
7690 pub uses_odbc_syntax: bool,
7691 /// The parameters to the function, including any options specified within the
7692 /// delimiting parentheses.
7693 ///
7694 /// Example:
7695 /// ```plaintext
7696 /// HISTOGRAM(0.5, 0.6)(x, y)
7697 /// ```
7698 ///
7699 /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions)
7700 pub parameters: FunctionArguments,
7701 /// The arguments to the function, including any options specified within the
7702 /// delimiting parentheses.
7703 pub args: FunctionArguments,
7704 /// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
7705 pub filter: Option<Box<Expr>>,
7706 /// Indicates how `NULL`s should be handled in the calculation.
7707 ///
7708 /// Example:
7709 /// ```plaintext
7710 /// FIRST_VALUE( <expr> ) [ { IGNORE | RESPECT } NULLS ] OVER ...
7711 /// ```
7712 ///
7713 /// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/first_value)
7714 pub null_treatment: Option<NullTreatment>,
7715 /// The `OVER` clause, indicating a window function call.
7716 pub over: Option<WindowType>,
7717 /// A clause used with certain aggregate functions to control the ordering
7718 /// within grouped sets before the function is applied.
7719 ///
7720 /// Syntax:
7721 /// ```plaintext
7722 /// <aggregate_function>(expression) WITHIN GROUP (ORDER BY key [ASC | DESC], ...)
7723 /// ```
7724 pub within_group: Vec<OrderByExpr>,
7725}
7726
7727impl fmt::Display for Function {
7728 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7729 if self.uses_odbc_syntax {
7730 write!(f, "{{fn ")?;
7731 }
7732
7733 write!(f, "{}{}{}", self.name, self.parameters, self.args)?;
7734
7735 if !self.within_group.is_empty() {
7736 write!(
7737 f,
7738 " WITHIN GROUP (ORDER BY {})",
7739 display_comma_separated(&self.within_group)
7740 )?;
7741 }
7742
7743 if let Some(filter_cond) = &self.filter {
7744 write!(f, " FILTER (WHERE {filter_cond})")?;
7745 }
7746
7747 if let Some(null_treatment) = &self.null_treatment {
7748 write!(f, " {null_treatment}")?;
7749 }
7750
7751 if let Some(o) = &self.over {
7752 f.write_str(" OVER ")?;
7753 o.fmt(f)?;
7754 }
7755
7756 if self.uses_odbc_syntax {
7757 write!(f, "}}")?;
7758 }
7759
7760 Ok(())
7761 }
7762}
7763
7764/// The arguments passed to a function call.
7765#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7766#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7767#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7768pub enum FunctionArguments {
7769 /// Used for special functions like `CURRENT_TIMESTAMP` that are invoked
7770 /// without parentheses.
7771 None,
7772 /// On some dialects, a subquery can be passed without surrounding
7773 /// parentheses if it's the sole argument to the function.
7774 Subquery(Box<Query>),
7775 /// A normal function argument list, including any clauses within it such as
7776 /// `DISTINCT` or `ORDER BY`.
7777 List(FunctionArgumentList),
7778}
7779
7780impl fmt::Display for FunctionArguments {
7781 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7782 match self {
7783 FunctionArguments::None => Ok(()),
7784 FunctionArguments::Subquery(query) => write!(f, "({query})"),
7785 FunctionArguments::List(args) => write!(f, "({args})"),
7786 }
7787 }
7788}
7789
7790/// This represents everything inside the parentheses when calling a function.
7791#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7792#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7793#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7794pub struct FunctionArgumentList {
7795 /// `[ ALL | DISTINCT ]`
7796 pub duplicate_treatment: Option<DuplicateTreatment>,
7797 /// The function arguments.
7798 pub args: Vec<FunctionArg>,
7799 /// Additional clauses specified within the argument list.
7800 pub clauses: Vec<FunctionArgumentClause>,
7801}
7802
7803impl fmt::Display for FunctionArgumentList {
7804 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7805 if let Some(duplicate_treatment) = self.duplicate_treatment {
7806 write!(f, "{duplicate_treatment} ")?;
7807 }
7808 write!(f, "{}", display_comma_separated(&self.args))?;
7809 if !self.clauses.is_empty() {
7810 if !self.args.is_empty() {
7811 write!(f, " ")?;
7812 }
7813 write!(f, "{}", display_separated(&self.clauses, " "))?;
7814 }
7815 Ok(())
7816 }
7817}
7818
7819#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7820#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7821#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7822/// Clauses that can appear inside a function argument list.
7823pub enum FunctionArgumentClause {
7824 /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery].
7825 ///
7826 /// Syntax:
7827 /// ```plaintext
7828 /// { IGNORE | RESPECT } NULLS ]
7829 /// ```
7830 ///
7831 /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/navigation_functions#first_value
7832 IgnoreOrRespectNulls(NullTreatment),
7833 /// Specifies the the ordering for some ordered set aggregates, e.g. `ARRAY_AGG` on [BigQuery].
7834 ///
7835 /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
7836 OrderBy(Vec<OrderByExpr>),
7837 /// Specifies a limit for the `ARRAY_AGG` and `ARRAY_CONCAT_AGG` functions on BigQuery.
7838 Limit(Expr),
7839 /// Specifies the behavior on overflow of the `LISTAGG` function.
7840 ///
7841 /// See <https://trino.io/docs/current/functions/aggregate.html>.
7842 OnOverflow(ListAggOnOverflow),
7843 /// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
7844 ///
7845 /// Syntax:
7846 /// ```plaintext
7847 /// HAVING { MAX | MIN } expression
7848 /// ```
7849 ///
7850 /// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
7851 Having(HavingBound),
7852 /// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
7853 ///
7854 /// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
7855 Separator(Value),
7856 /// The `ON NULL` clause for some JSON functions.
7857 ///
7858 /// [MSSQL `JSON_ARRAY`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=sql-server-ver16)
7859 /// [MSSQL `JSON_OBJECT`](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16>)
7860 /// [PostgreSQL JSON functions](https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSON-PROCESSING)
7861 JsonNullClause(JsonNullClause),
7862 /// The `RETURNING` clause for some JSON functions in PostgreSQL
7863 ///
7864 /// [`JSON_OBJECT`](https://www.postgresql.org/docs/current/functions-json.html#:~:text=json_object)
7865 JsonReturningClause(JsonReturningClause),
7866}
7867
7868impl fmt::Display for FunctionArgumentClause {
7869 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7870 match self {
7871 FunctionArgumentClause::IgnoreOrRespectNulls(null_treatment) => {
7872 write!(f, "{null_treatment}")
7873 }
7874 FunctionArgumentClause::OrderBy(order_by) => {
7875 write!(f, "ORDER BY {}", display_comma_separated(order_by))
7876 }
7877 FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
7878 FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
7879 FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
7880 FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
7881 FunctionArgumentClause::JsonNullClause(null_clause) => write!(f, "{null_clause}"),
7882 FunctionArgumentClause::JsonReturningClause(returning_clause) => {
7883 write!(f, "{returning_clause}")
7884 }
7885 }
7886 }
7887}
7888
7889/// A method call
7890#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7891#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7892#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7893pub struct Method {
7894 /// The expression on which the method is invoked.
7895 pub expr: Box<Expr>,
7896 // always non-empty
7897 /// The sequence of chained method calls.
7898 pub method_chain: Vec<Function>,
7899}
7900
7901impl fmt::Display for Method {
7902 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7903 write!(
7904 f,
7905 "{}.{}",
7906 self.expr,
7907 display_separated(&self.method_chain, ".")
7908 )
7909 }
7910}
7911
7912#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7913#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7914#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7915/// How duplicate values are treated inside function argument lists.
7916pub enum DuplicateTreatment {
7917 /// Consider only unique values.
7918 Distinct,
7919 /// Retain all duplicate values (the default).
7920 All,
7921}
7922
7923impl fmt::Display for DuplicateTreatment {
7924 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7925 match self {
7926 DuplicateTreatment::Distinct => write!(f, "DISTINCT"),
7927 DuplicateTreatment::All => write!(f, "ALL"),
7928 }
7929 }
7930}
7931
7932#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7933#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7934#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7935/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified.
7936pub enum AnalyzeFormatKind {
7937 /// Format provided as a keyword, e.g. `FORMAT JSON`.
7938 Keyword(AnalyzeFormat),
7939 /// Format provided as an assignment, e.g. `FORMAT=JSON`.
7940 Assignment(AnalyzeFormat),
7941}
7942
7943impl fmt::Display for AnalyzeFormatKind {
7944 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7945 match self {
7946 AnalyzeFormatKind::Keyword(format) => write!(f, "FORMAT {format}"),
7947 AnalyzeFormatKind::Assignment(format) => write!(f, "FORMAT={format}"),
7948 }
7949 }
7950}
7951
7952#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7953#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7954#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7955/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`.
7956pub enum AnalyzeFormat {
7957 /// Plain text format.
7958 TEXT,
7959 /// Graphviz DOT format.
7960 GRAPHVIZ,
7961 /// JSON format.
7962 JSON,
7963 /// Traditional explain output.
7964 TRADITIONAL,
7965 /// Tree-style explain output.
7966 TREE,
7967}
7968
7969impl fmt::Display for AnalyzeFormat {
7970 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7971 f.write_str(match self {
7972 AnalyzeFormat::TEXT => "TEXT",
7973 AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
7974 AnalyzeFormat::JSON => "JSON",
7975 AnalyzeFormat::TRADITIONAL => "TRADITIONAL",
7976 AnalyzeFormat::TREE => "TREE",
7977 })
7978 }
7979}
7980
7981/// External table's available file format
7982#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7983#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7984#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7985pub enum FileFormat {
7986 /// Text file format.
7987 TEXTFILE,
7988 /// Sequence file format.
7989 SEQUENCEFILE,
7990 /// ORC file format.
7991 ORC,
7992 /// Parquet file format.
7993 PARQUET,
7994 /// Avro file format.
7995 AVRO,
7996 /// RCFile format.
7997 RCFILE,
7998 /// JSON file format.
7999 JSONFILE,
8000}
8001
8002impl fmt::Display for FileFormat {
8003 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8004 use self::FileFormat::*;
8005 f.write_str(match self {
8006 TEXTFILE => "TEXTFILE",
8007 SEQUENCEFILE => "SEQUENCEFILE",
8008 ORC => "ORC",
8009 PARQUET => "PARQUET",
8010 AVRO => "AVRO",
8011 RCFILE => "RCFILE",
8012 JSONFILE => "JSONFILE",
8013 })
8014 }
8015}
8016
8017/// The `ON OVERFLOW` clause of a LISTAGG invocation
8018#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8019#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8020#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8021pub enum ListAggOnOverflow {
8022 /// `ON OVERFLOW ERROR`
8023 Error,
8024
8025 /// `ON OVERFLOW TRUNCATE [ <filler> ] WITH[OUT] COUNT`
8026 Truncate {
8027 /// Optional filler expression used when truncating.
8028 filler: Option<Box<Expr>>,
8029 /// Whether to include a count when truncating.
8030 with_count: bool,
8031 },
8032}
8033
8034impl fmt::Display for ListAggOnOverflow {
8035 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8036 write!(f, "ON OVERFLOW")?;
8037 match self {
8038 ListAggOnOverflow::Error => write!(f, " ERROR"),
8039 ListAggOnOverflow::Truncate { filler, with_count } => {
8040 write!(f, " TRUNCATE")?;
8041 if let Some(filler) = filler {
8042 write!(f, " {filler}")?;
8043 }
8044 if *with_count {
8045 write!(f, " WITH")?;
8046 } else {
8047 write!(f, " WITHOUT")?;
8048 }
8049 write!(f, " COUNT")
8050 }
8051 }
8052 }
8053}
8054
8055/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
8056#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8057#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8058#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8059pub struct HavingBound(pub HavingBoundKind, pub Expr);
8060
8061impl fmt::Display for HavingBound {
8062 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8063 write!(f, "HAVING {} {}", self.0, self.1)
8064 }
8065}
8066
8067#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8068#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8069#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8070/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery.
8071pub enum HavingBoundKind {
8072 /// The minimum bound.
8073 Min,
8074 /// The maximum bound.
8075 Max,
8076}
8077
8078impl fmt::Display for HavingBoundKind {
8079 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8080 match self {
8081 HavingBoundKind::Min => write!(f, "MIN"),
8082 HavingBoundKind::Max => write!(f, "MAX"),
8083 }
8084 }
8085}
8086
8087#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8088#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8089#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8090/// Types of database objects referenced by DDL statements.
8091pub enum ObjectType {
8092 /// A table.
8093 Table,
8094 /// A view.
8095 View,
8096 /// A materialized view.
8097 MaterializedView,
8098 /// An index.
8099 Index,
8100 /// A schema.
8101 Schema,
8102 /// A database.
8103 Database,
8104 /// A role.
8105 Role,
8106 /// A sequence.
8107 Sequence,
8108 /// A stage.
8109 Stage,
8110 /// A type definition.
8111 Type,
8112 /// A user.
8113 User,
8114 /// A stream.
8115 Stream,
8116}
8117
8118impl fmt::Display for ObjectType {
8119 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8120 f.write_str(match self {
8121 ObjectType::Table => "TABLE",
8122 ObjectType::View => "VIEW",
8123 ObjectType::MaterializedView => "MATERIALIZED VIEW",
8124 ObjectType::Index => "INDEX",
8125 ObjectType::Schema => "SCHEMA",
8126 ObjectType::Database => "DATABASE",
8127 ObjectType::Role => "ROLE",
8128 ObjectType::Sequence => "SEQUENCE",
8129 ObjectType::Stage => "STAGE",
8130 ObjectType::Type => "TYPE",
8131 ObjectType::User => "USER",
8132 ObjectType::Stream => "STREAM",
8133 })
8134 }
8135}
8136
8137#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8138#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8139#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8140/// Types supported by `KILL` statements.
8141pub enum KillType {
8142 /// Kill a connection.
8143 Connection,
8144 /// Kill a running query.
8145 Query,
8146 /// Kill a mutation (ClickHouse).
8147 Mutation,
8148}
8149
8150impl fmt::Display for KillType {
8151 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8152 f.write_str(match self {
8153 // MySQL
8154 KillType::Connection => "CONNECTION",
8155 KillType::Query => "QUERY",
8156 // Clickhouse supports Mutation
8157 KillType::Mutation => "MUTATION",
8158 })
8159 }
8160}
8161
8162#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8163#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8164#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8165/// Distribution style options for Hive tables.
8166pub enum HiveDistributionStyle {
8167 /// Partitioned distribution with the given columns.
8168 PARTITIONED {
8169 /// Columns used for partitioning.
8170 columns: Vec<ColumnDef>,
8171 },
8172 /// Skewed distribution definition.
8173 SKEWED {
8174 /// Columns participating in the skew definition.
8175 columns: Vec<ColumnDef>,
8176 /// Columns listed in the `ON` clause for skewing.
8177 on: Vec<ColumnDef>,
8178 /// Whether skewed data is stored as directories.
8179 stored_as_directories: bool,
8180 },
8181 /// No distribution style specified.
8182 NONE,
8183}
8184
8185#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8186#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8187#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8188/// Row format specification for Hive tables (SERDE or DELIMITED).
8189pub enum HiveRowFormat {
8190 /// SerDe class specification with the implementing class name.
8191 SERDE {
8192 /// The SerDe implementation class name.
8193 class: String,
8194 },
8195 /// Delimited row format with one or more delimiter specifications.
8196 DELIMITED {
8197 /// The list of delimiters used for delimiting fields/lines.
8198 delimiters: Vec<HiveRowDelimiter>,
8199 },
8200}
8201
8202#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8203#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8204#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8205/// Format specification for `LOAD DATA` Hive operations.
8206pub struct HiveLoadDataFormat {
8207 /// SerDe expression used for the table.
8208 pub serde: Expr,
8209 /// Input format expression.
8210 pub input_format: Expr,
8211}
8212
8213#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8215#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8216/// A single row delimiter specification for Hive `ROW FORMAT`.
8217pub struct HiveRowDelimiter {
8218 /// The delimiter kind (fields/lines/etc.).
8219 pub delimiter: HiveDelimiter,
8220 /// The delimiter character identifier.
8221 pub char: Ident,
8222}
8223
8224impl fmt::Display for HiveRowDelimiter {
8225 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8226 write!(f, "{} ", self.delimiter)?;
8227 write!(f, "{}", self.char)
8228 }
8229}
8230
8231#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8233#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8234/// Kind of delimiter used in Hive `ROW FORMAT` definitions.
8235pub enum HiveDelimiter {
8236 /// Fields terminated by a delimiter.
8237 FieldsTerminatedBy,
8238 /// Fields escaped by a character.
8239 FieldsEscapedBy,
8240 /// Collection items terminated by a delimiter.
8241 CollectionItemsTerminatedBy,
8242 /// Map keys terminated by a delimiter.
8243 MapKeysTerminatedBy,
8244 /// Lines terminated by a delimiter.
8245 LinesTerminatedBy,
8246 /// Null represented by a specific token.
8247 NullDefinedAs,
8248}
8249
8250impl fmt::Display for HiveDelimiter {
8251 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8252 use HiveDelimiter::*;
8253 f.write_str(match self {
8254 FieldsTerminatedBy => "FIELDS TERMINATED BY",
8255 FieldsEscapedBy => "ESCAPED BY",
8256 CollectionItemsTerminatedBy => "COLLECTION ITEMS TERMINATED BY",
8257 MapKeysTerminatedBy => "MAP KEYS TERMINATED BY",
8258 LinesTerminatedBy => "LINES TERMINATED BY",
8259 NullDefinedAs => "NULL DEFINED AS",
8260 })
8261 }
8262}
8263
8264#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8265#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8266#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8267/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`.
8268pub enum HiveDescribeFormat {
8269 /// Extended describe output.
8270 Extended,
8271 /// Formatted describe output.
8272 Formatted,
8273}
8274
8275impl fmt::Display for HiveDescribeFormat {
8276 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8277 use HiveDescribeFormat::*;
8278 f.write_str(match self {
8279 Extended => "EXTENDED",
8280 Formatted => "FORMATTED",
8281 })
8282 }
8283}
8284
8285#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8286#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8287#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8288/// Aliases accepted for describe-style commands.
8289pub enum DescribeAlias {
8290 /// `DESCRIBE` alias.
8291 Describe,
8292 /// `EXPLAIN` alias.
8293 Explain,
8294 /// `DESC` alias.
8295 Desc,
8296}
8297
8298impl fmt::Display for DescribeAlias {
8299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8300 use DescribeAlias::*;
8301 f.write_str(match self {
8302 Describe => "DESCRIBE",
8303 Explain => "EXPLAIN",
8304 Desc => "DESC",
8305 })
8306 }
8307}
8308
8309#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8310#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8311#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8312#[allow(clippy::large_enum_variant)]
8313/// Hive input/output format specification used in `CREATE TABLE`.
8314pub enum HiveIOFormat {
8315 /// Generic IO format with separate input and output expressions.
8316 IOF {
8317 /// Expression for the input format.
8318 input_format: Expr,
8319 /// Expression for the output format.
8320 output_format: Expr,
8321 },
8322 /// File format wrapper referencing a `FileFormat` variant.
8323 FileFormat {
8324 /// The file format used for storage.
8325 format: FileFormat,
8326 },
8327}
8328
8329#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
8330#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8331#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8332/// Hive table format and storage-related options.
8333pub struct HiveFormat {
8334 /// Optional row format specification.
8335 pub row_format: Option<HiveRowFormat>,
8336 /// Optional SerDe properties expressed as SQL options.
8337 pub serde_properties: Option<Vec<SqlOption>>,
8338 /// Optional input/output storage format details.
8339 pub storage: Option<HiveIOFormat>,
8340 /// Optional location (URI or path) for table data.
8341 pub location: Option<String>,
8342}
8343
8344#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8345#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8346#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8347/// A clustered index column specification.
8348pub struct ClusteredIndex {
8349 /// Column identifier for the clustered index entry.
8350 pub name: Ident,
8351 /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified.
8352 pub asc: Option<bool>,
8353}
8354
8355impl fmt::Display for ClusteredIndex {
8356 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8357 write!(f, "{}", self.name)?;
8358 match self.asc {
8359 Some(true) => write!(f, " ASC"),
8360 Some(false) => write!(f, " DESC"),
8361 _ => Ok(()),
8362 }
8363 }
8364}
8365
8366#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8367#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8368#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8369/// Clustered options used for `CREATE TABLE` clustered/indexed storage.
8370pub enum TableOptionsClustered {
8371 /// Use a columnstore index.
8372 ColumnstoreIndex,
8373 /// Columnstore index with an explicit ordering of columns.
8374 ColumnstoreIndexOrder(Vec<Ident>),
8375 /// A named clustered index with one or more columns.
8376 Index(Vec<ClusteredIndex>),
8377}
8378
8379impl fmt::Display for TableOptionsClustered {
8380 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8381 match self {
8382 TableOptionsClustered::ColumnstoreIndex => {
8383 write!(f, "CLUSTERED COLUMNSTORE INDEX")
8384 }
8385 TableOptionsClustered::ColumnstoreIndexOrder(values) => {
8386 write!(
8387 f,
8388 "CLUSTERED COLUMNSTORE INDEX ORDER ({})",
8389 display_comma_separated(values)
8390 )
8391 }
8392 TableOptionsClustered::Index(values) => {
8393 write!(f, "CLUSTERED INDEX ({})", display_comma_separated(values))
8394 }
8395 }
8396 }
8397}
8398
8399/// Specifies which partition the boundary values on table partitioning belongs to.
8400#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
8401#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8402#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8403pub enum PartitionRangeDirection {
8404 /// LEFT range direction.
8405 Left,
8406 /// RIGHT range direction.
8407 Right,
8408}
8409
8410#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8411#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8412#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8413/// SQL option syntax used in table and server definitions.
8414pub enum SqlOption {
8415 /// Clustered represents the clustered version of table storage for MSSQL.
8416 ///
8417 /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8418 Clustered(TableOptionsClustered),
8419 /// Single identifier options, e.g. `HEAP` for MSSQL.
8420 ///
8421 /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TableOptions>
8422 Ident(Ident),
8423 /// Any option that consists of a key value pair where the value is an expression. e.g.
8424 ///
8425 /// WITH(DISTRIBUTION = ROUND_ROBIN)
8426 KeyValue {
8427 /// The option key identifier.
8428 key: Ident,
8429 /// The expression value for the option.
8430 value: Expr,
8431 },
8432 /// One or more table partitions and represents which partition the boundary values belong to,
8433 /// e.g.
8434 ///
8435 /// PARTITION (id RANGE LEFT FOR VALUES (10, 20, 30, 40))
8436 ///
8437 /// <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-azure-sql-data-warehouse?view=aps-pdw-2016-au7#TablePartitionOptions>
8438 Partition {
8439 /// The partition column name.
8440 column_name: Ident,
8441 /// Optional direction for the partition range (LEFT/RIGHT).
8442 range_direction: Option<PartitionRangeDirection>,
8443 /// Values that define the partition boundaries.
8444 for_values: Vec<Expr>,
8445 },
8446 /// Comment parameter (supports `=` and no `=` syntax)
8447 Comment(CommentDef),
8448 /// MySQL TableSpace option
8449 /// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8450 TableSpace(TablespaceOption),
8451 /// An option representing a key value pair, where the value is a parenthesized list and with an optional name
8452 /// e.g.
8453 ///
8454 /// UNION = (tbl_name\[,tbl_name\]...) <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8455 /// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication>
8456 /// ENGINE = SummingMergeTree(\[columns\]) <https://clickhouse.com/docs/engines/table-engines/mergetree-family/summingmergetree>
8457 NamedParenthesizedList(NamedParenthesizedList),
8458}
8459
8460impl fmt::Display for SqlOption {
8461 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8462 match self {
8463 SqlOption::Clustered(c) => write!(f, "{c}"),
8464 SqlOption::Ident(ident) => {
8465 write!(f, "{ident}")
8466 }
8467 SqlOption::KeyValue { key: name, value } => {
8468 write!(f, "{name} = {value}")
8469 }
8470 SqlOption::Partition {
8471 column_name,
8472 range_direction,
8473 for_values,
8474 } => {
8475 let direction = match range_direction {
8476 Some(PartitionRangeDirection::Left) => " LEFT",
8477 Some(PartitionRangeDirection::Right) => " RIGHT",
8478 None => "",
8479 };
8480
8481 write!(
8482 f,
8483 "PARTITION ({} RANGE{} FOR VALUES ({}))",
8484 column_name,
8485 direction,
8486 display_comma_separated(for_values)
8487 )
8488 }
8489 SqlOption::TableSpace(tablespace_option) => {
8490 write!(f, "TABLESPACE {}", tablespace_option.name)?;
8491 match tablespace_option.storage {
8492 Some(StorageType::Disk) => write!(f, " STORAGE DISK"),
8493 Some(StorageType::Memory) => write!(f, " STORAGE MEMORY"),
8494 None => Ok(()),
8495 }
8496 }
8497 SqlOption::Comment(comment) => match comment {
8498 CommentDef::WithEq(comment) => {
8499 write!(f, "COMMENT = '{comment}'")
8500 }
8501 CommentDef::WithoutEq(comment) => {
8502 write!(f, "COMMENT '{comment}'")
8503 }
8504 },
8505 SqlOption::NamedParenthesizedList(value) => {
8506 write!(f, "{} = ", value.key)?;
8507 if let Some(key) = &value.name {
8508 write!(f, "{key}")?;
8509 }
8510 if !value.values.is_empty() {
8511 write!(f, "({})", display_comma_separated(&value.values))?
8512 }
8513 Ok(())
8514 }
8515 }
8516 }
8517}
8518
8519#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8520#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8521#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8522/// Storage type options for a tablespace.
8523pub enum StorageType {
8524 /// Store on disk.
8525 Disk,
8526 /// Store in memory.
8527 Memory,
8528}
8529
8530#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
8531#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8532#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8533/// MySql TableSpace option
8534/// <https://dev.mysql.com/doc/refman/8.4/en/create-table.html>
8535pub struct TablespaceOption {
8536 /// Name of the tablespace.
8537 pub name: String,
8538 /// Optional storage type for the tablespace.
8539 pub storage: Option<StorageType>,
8540}
8541
8542#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8543#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8544#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8545/// A key/value identifier pair used for secret or key-based options.
8546pub struct SecretOption {
8547 /// The option key identifier.
8548 pub key: Ident,
8549 /// The option value identifier.
8550 pub value: Ident,
8551}
8552
8553impl fmt::Display for SecretOption {
8554 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8555 write!(f, "{} {}", self.key, self.value)
8556 }
8557}
8558
8559/// A `CREATE SERVER` statement.
8560///
8561/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
8562#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8563#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8564#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8565pub struct CreateServerStatement {
8566 /// The server name.
8567 pub name: ObjectName,
8568 /// Whether `IF NOT EXISTS` was specified.
8569 pub if_not_exists: bool,
8570 /// Optional server type identifier.
8571 pub server_type: Option<Ident>,
8572 /// Optional server version identifier.
8573 pub version: Option<Ident>,
8574 /// Foreign-data wrapper object name.
8575 pub foreign_data_wrapper: ObjectName,
8576 /// Optional list of server options.
8577 pub options: Option<Vec<CreateServerOption>>,
8578}
8579
8580impl fmt::Display for CreateServerStatement {
8581 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8582 let CreateServerStatement {
8583 name,
8584 if_not_exists,
8585 server_type,
8586 version,
8587 foreign_data_wrapper,
8588 options,
8589 } = self;
8590
8591 write!(
8592 f,
8593 "CREATE SERVER {if_not_exists}{name} ",
8594 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
8595 )?;
8596
8597 if let Some(st) = server_type {
8598 write!(f, "TYPE {st} ")?;
8599 }
8600
8601 if let Some(v) = version {
8602 write!(f, "VERSION {v} ")?;
8603 }
8604
8605 write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
8606
8607 if let Some(o) = options {
8608 write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
8609 }
8610
8611 Ok(())
8612 }
8613}
8614
8615/// A key/value option for `CREATE SERVER`.
8616#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8617#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8618#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8619pub struct CreateServerOption {
8620 /// Option key identifier.
8621 pub key: Ident,
8622 /// Option value identifier.
8623 pub value: Ident,
8624}
8625
8626impl fmt::Display for CreateServerOption {
8627 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8628 write!(f, "{} {}", self.key, self.value)
8629 }
8630}
8631
8632#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8633#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8634#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8635/// Options supported by DuckDB for `ATTACH DATABASE`.
8636pub enum AttachDuckDBDatabaseOption {
8637 /// READ_ONLY option, optional boolean value.
8638 ReadOnly(Option<bool>),
8639 /// TYPE option specifying a database type identifier.
8640 Type(Ident),
8641}
8642
8643impl fmt::Display for AttachDuckDBDatabaseOption {
8644 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8645 match self {
8646 AttachDuckDBDatabaseOption::ReadOnly(Some(true)) => write!(f, "READ_ONLY true"),
8647 AttachDuckDBDatabaseOption::ReadOnly(Some(false)) => write!(f, "READ_ONLY false"),
8648 AttachDuckDBDatabaseOption::ReadOnly(None) => write!(f, "READ_ONLY"),
8649 AttachDuckDBDatabaseOption::Type(t) => write!(f, "TYPE {t}"),
8650 }
8651 }
8652}
8653
8654#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8655#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8656#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8657/// Mode for transactions: access mode or isolation level.
8658pub enum TransactionMode {
8659 /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`).
8660 AccessMode(TransactionAccessMode),
8661 /// Isolation level for a transaction (e.g. `SERIALIZABLE`).
8662 IsolationLevel(TransactionIsolationLevel),
8663}
8664
8665impl fmt::Display for TransactionMode {
8666 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8667 use TransactionMode::*;
8668 match self {
8669 AccessMode(access_mode) => write!(f, "{access_mode}"),
8670 IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {iso_level}"),
8671 }
8672 }
8673}
8674
8675#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8676#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8677#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8678/// Transaction access mode (READ ONLY / READ WRITE).
8679pub enum TransactionAccessMode {
8680 /// READ ONLY access mode.
8681 ReadOnly,
8682 /// READ WRITE access mode.
8683 ReadWrite,
8684}
8685
8686impl fmt::Display for TransactionAccessMode {
8687 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8688 use TransactionAccessMode::*;
8689 f.write_str(match self {
8690 ReadOnly => "READ ONLY",
8691 ReadWrite => "READ WRITE",
8692 })
8693 }
8694}
8695
8696#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8697#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8698#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8699/// Transaction isolation levels.
8700pub enum TransactionIsolationLevel {
8701 /// READ UNCOMMITTED isolation level.
8702 ReadUncommitted,
8703 /// READ COMMITTED isolation level.
8704 ReadCommitted,
8705 /// REPEATABLE READ isolation level.
8706 RepeatableRead,
8707 /// SERIALIZABLE isolation level.
8708 Serializable,
8709 /// SNAPSHOT isolation level.
8710 Snapshot,
8711}
8712
8713impl fmt::Display for TransactionIsolationLevel {
8714 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8715 use TransactionIsolationLevel::*;
8716 f.write_str(match self {
8717 ReadUncommitted => "READ UNCOMMITTED",
8718 ReadCommitted => "READ COMMITTED",
8719 RepeatableRead => "REPEATABLE READ",
8720 Serializable => "SERIALIZABLE",
8721 Snapshot => "SNAPSHOT",
8722 })
8723 }
8724}
8725
8726/// Modifier for the transaction in the `BEGIN` syntax
8727///
8728/// SQLite: <https://sqlite.org/lang_transaction.html>
8729/// MS-SQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql>
8730#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8731#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8732#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8733pub enum TransactionModifier {
8734 /// DEFERRED transaction modifier.
8735 Deferred,
8736 /// IMMEDIATE transaction modifier.
8737 Immediate,
8738 /// EXCLUSIVE transaction modifier.
8739 Exclusive,
8740 /// TRY block modifier (MS-SQL style TRY/CATCH).
8741 Try,
8742 /// CATCH block modifier (MS-SQL style TRY/CATCH).
8743 Catch,
8744}
8745
8746impl fmt::Display for TransactionModifier {
8747 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8748 use TransactionModifier::*;
8749 f.write_str(match self {
8750 Deferred => "DEFERRED",
8751 Immediate => "IMMEDIATE",
8752 Exclusive => "EXCLUSIVE",
8753 Try => "TRY",
8754 Catch => "CATCH",
8755 })
8756 }
8757}
8758
8759#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8760#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8761#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8762/// Filter forms usable in SHOW statements.
8763pub enum ShowStatementFilter {
8764 /// Filter using LIKE pattern.
8765 Like(String),
8766 /// Filter using ILIKE pattern.
8767 ILike(String),
8768 /// Filter using a WHERE expression.
8769 Where(Expr),
8770 /// Filter provided without a keyword (raw string).
8771 NoKeyword(String),
8772}
8773
8774impl fmt::Display for ShowStatementFilter {
8775 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8776 use ShowStatementFilter::*;
8777 match self {
8778 Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
8779 ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
8780 Where(expr) => write!(f, "WHERE {expr}"),
8781 NoKeyword(pattern) => write!(f, "'{}'", value::escape_single_quote_string(pattern)),
8782 }
8783 }
8784}
8785
8786#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8787#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8788#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8789/// Clause types used with SHOW ... IN/FROM.
8790pub enum ShowStatementInClause {
8791 /// Use the `IN` clause.
8792 IN,
8793 /// Use the `FROM` clause.
8794 FROM,
8795}
8796
8797impl fmt::Display for ShowStatementInClause {
8798 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8799 use ShowStatementInClause::*;
8800 match self {
8801 FROM => write!(f, "FROM"),
8802 IN => write!(f, "IN"),
8803 }
8804 }
8805}
8806
8807/// Sqlite specific syntax
8808///
8809/// See [Sqlite documentation](https://sqlite.org/lang_conflict.html)
8810/// for more details.
8811#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8812#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8813#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8814pub enum SqliteOnConflict {
8815 /// Use ROLLBACK on conflict.
8816 Rollback,
8817 /// Use ABORT on conflict.
8818 Abort,
8819 /// Use FAIL on conflict.
8820 Fail,
8821 /// Use IGNORE on conflict.
8822 Ignore,
8823 /// Use REPLACE on conflict.
8824 Replace,
8825}
8826
8827impl fmt::Display for SqliteOnConflict {
8828 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8829 use SqliteOnConflict::*;
8830 match self {
8831 Rollback => write!(f, "OR ROLLBACK"),
8832 Abort => write!(f, "OR ABORT"),
8833 Fail => write!(f, "OR FAIL"),
8834 Ignore => write!(f, "OR IGNORE"),
8835 Replace => write!(f, "OR REPLACE"),
8836 }
8837 }
8838}
8839
8840/// Mysql specific syntax
8841///
8842/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/replace.html)
8843/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.0/en/insert.html)
8844/// for more details.
8845#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8846#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8847#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8848pub enum MysqlInsertPriority {
8849 /// LOW_PRIORITY modifier for INSERT/REPLACE.
8850 LowPriority,
8851 /// DELAYED modifier for INSERT/REPLACE.
8852 Delayed,
8853 /// HIGH_PRIORITY modifier for INSERT/REPLACE.
8854 HighPriority,
8855}
8856
8857impl fmt::Display for crate::ast::MysqlInsertPriority {
8858 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8859 use MysqlInsertPriority::*;
8860 match self {
8861 LowPriority => write!(f, "LOW_PRIORITY"),
8862 Delayed => write!(f, "DELAYED"),
8863 HighPriority => write!(f, "HIGH_PRIORITY"),
8864 }
8865 }
8866}
8867
8868#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8869#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8870#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8871/// Source for the `COPY` command: a table or a query.
8872pub enum CopySource {
8873 /// Copy from a table with optional column list.
8874 Table {
8875 /// The name of the table to copy from.
8876 table_name: ObjectName,
8877 /// A list of column names to copy. Empty list means that all columns
8878 /// are copied.
8879 columns: Vec<Ident>,
8880 },
8881 /// Copy from the results of a query.
8882 Query(Box<Query>),
8883}
8884
8885#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8886#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8887#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8888/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program.
8889pub enum CopyTarget {
8890 /// Use standard input as the source.
8891 Stdin,
8892 /// Use standard output as the target.
8893 Stdout,
8894 /// Read from or write to a file.
8895 File {
8896 /// The path name of the input or output file.
8897 filename: String,
8898 },
8899 /// Use a program as the source or target (shell command).
8900 Program {
8901 /// A command to execute
8902 command: String,
8903 },
8904}
8905
8906impl fmt::Display for CopyTarget {
8907 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8908 use CopyTarget::*;
8909 match self {
8910 Stdin => write!(f, "STDIN"),
8911 Stdout => write!(f, "STDOUT"),
8912 File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
8913 Program { command } => write!(
8914 f,
8915 "PROGRAM '{}'",
8916 value::escape_single_quote_string(command)
8917 ),
8918 }
8919 }
8920}
8921
8922#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8923#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8924#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8925/// Action to take `ON COMMIT` for temporary tables.
8926pub enum OnCommit {
8927 /// Delete rows on commit.
8928 DeleteRows,
8929 /// Preserve rows on commit.
8930 PreserveRows,
8931 /// Drop the table on commit.
8932 Drop,
8933}
8934
8935/// An option in `COPY` statement.
8936///
8937/// <https://www.postgresql.org/docs/14/sql-copy.html>
8938#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8939#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8940#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8941pub enum CopyOption {
8942 /// FORMAT format_name
8943 Format(Ident),
8944 /// FREEZE \[ boolean \]
8945 Freeze(bool),
8946 /// DELIMITER 'delimiter_character'
8947 Delimiter(char),
8948 /// NULL 'null_string'
8949 Null(String),
8950 /// HEADER \[ boolean \]
8951 Header(bool),
8952 /// QUOTE 'quote_character'
8953 Quote(char),
8954 /// ESCAPE 'escape_character'
8955 Escape(char),
8956 /// FORCE_QUOTE { ( column_name [, ...] ) | * }
8957 ForceQuote(Vec<Ident>),
8958 /// FORCE_NOT_NULL ( column_name [, ...] )
8959 ForceNotNull(Vec<Ident>),
8960 /// FORCE_NULL ( column_name [, ...] )
8961 ForceNull(Vec<Ident>),
8962 /// ENCODING 'encoding_name'
8963 Encoding(String),
8964}
8965
8966impl fmt::Display for CopyOption {
8967 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8968 use CopyOption::*;
8969 match self {
8970 Format(name) => write!(f, "FORMAT {name}"),
8971 Freeze(true) => write!(f, "FREEZE"),
8972 Freeze(false) => write!(f, "FREEZE FALSE"),
8973 Delimiter(char) => write!(f, "DELIMITER '{char}'"),
8974 Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
8975 Header(true) => write!(f, "HEADER"),
8976 Header(false) => write!(f, "HEADER FALSE"),
8977 Quote(char) => write!(f, "QUOTE '{char}'"),
8978 Escape(char) => write!(f, "ESCAPE '{char}'"),
8979 ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
8980 ForceNotNull(columns) => {
8981 write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
8982 }
8983 ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
8984 Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
8985 }
8986 }
8987}
8988
8989/// An option in `COPY` statement before PostgreSQL version 9.0.
8990///
8991/// [PostgreSQL](https://www.postgresql.org/docs/8.4/sql-copy.html)
8992/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_COPY-alphabetical-parm-list.html)
8993#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8994#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8995#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8996pub enum CopyLegacyOption {
8997 /// ACCEPTANYDATE
8998 AcceptAnyDate,
8999 /// ACCEPTINVCHARS
9000 AcceptInvChars(Option<String>),
9001 /// ADDQUOTES
9002 AddQuotes,
9003 /// ALLOWOVERWRITE
9004 AllowOverwrite,
9005 /// BINARY
9006 Binary,
9007 /// BLANKSASNULL
9008 BlankAsNull,
9009 /// BZIP2
9010 Bzip2,
9011 /// CLEANPATH
9012 CleanPath,
9013 /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
9014 CompUpdate {
9015 /// Whether the COMPUPDATE PRESET option was used.
9016 preset: bool,
9017 /// Optional enabled flag for COMPUPDATE.
9018 enabled: Option<bool>,
9019 },
9020 /// CSV ...
9021 Csv(Vec<CopyLegacyCsvOption>),
9022 /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
9023 DateFormat(Option<String>),
9024 /// DELIMITER \[ AS \] 'delimiter_character'
9025 Delimiter(char),
9026 /// EMPTYASNULL
9027 EmptyAsNull,
9028 /// `ENCRYPTED \[ AUTO \]`
9029 Encrypted {
9030 /// Whether `AUTO` was specified for encryption.
9031 auto: bool,
9032 },
9033 /// ESCAPE
9034 Escape,
9035 /// EXTENSION 'extension-name'
9036 Extension(String),
9037 /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
9038 FixedWidth(String),
9039 /// GZIP
9040 Gzip,
9041 /// HEADER
9042 Header,
9043 /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
9044 IamRole(IamRoleKind),
9045 /// IGNOREHEADER \[ AS \] number_rows
9046 IgnoreHeader(u64),
9047 /// JSON \[ AS \] 'json_option'
9048 Json(Option<String>),
9049 /// MANIFEST \[ VERBOSE \]
9050 Manifest {
9051 /// Whether the MANIFEST is verbose.
9052 verbose: bool,
9053 },
9054 /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
9055 MaxFileSize(FileSize),
9056 /// `NULL \[ AS \] 'null_string'`
9057 Null(String),
9058 /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]`
9059 Parallel(Option<bool>),
9060 /// PARQUET
9061 Parquet,
9062 /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
9063 PartitionBy(UnloadPartitionBy),
9064 /// REGION \[ AS \] 'aws-region' }
9065 Region(String),
9066 /// REMOVEQUOTES
9067 RemoveQuotes,
9068 /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
9069 RowGroupSize(FileSize),
9070 /// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
9071 StatUpdate(Option<bool>),
9072 /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
9073 TimeFormat(Option<String>),
9074 /// TRUNCATECOLUMNS
9075 TruncateColumns,
9076 /// ZSTD
9077 Zstd,
9078}
9079
9080impl fmt::Display for CopyLegacyOption {
9081 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9082 use CopyLegacyOption::*;
9083 match self {
9084 AcceptAnyDate => write!(f, "ACCEPTANYDATE"),
9085 AcceptInvChars(ch) => {
9086 write!(f, "ACCEPTINVCHARS")?;
9087 if let Some(ch) = ch {
9088 write!(f, " '{}'", value::escape_single_quote_string(ch))?;
9089 }
9090 Ok(())
9091 }
9092 AddQuotes => write!(f, "ADDQUOTES"),
9093 AllowOverwrite => write!(f, "ALLOWOVERWRITE"),
9094 Binary => write!(f, "BINARY"),
9095 BlankAsNull => write!(f, "BLANKSASNULL"),
9096 Bzip2 => write!(f, "BZIP2"),
9097 CleanPath => write!(f, "CLEANPATH"),
9098 CompUpdate { preset, enabled } => {
9099 write!(f, "COMPUPDATE")?;
9100 if *preset {
9101 write!(f, " PRESET")?;
9102 } else if let Some(enabled) = enabled {
9103 write!(
9104 f,
9105 "{}",
9106 match enabled {
9107 true => " TRUE",
9108 false => " FALSE",
9109 }
9110 )?;
9111 }
9112 Ok(())
9113 }
9114 Csv(opts) => {
9115 write!(f, "CSV")?;
9116 if !opts.is_empty() {
9117 write!(f, " {}", display_separated(opts, " "))?;
9118 }
9119 Ok(())
9120 }
9121 DateFormat(fmt) => {
9122 write!(f, "DATEFORMAT")?;
9123 if let Some(fmt) = fmt {
9124 write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9125 }
9126 Ok(())
9127 }
9128 Delimiter(char) => write!(f, "DELIMITER '{char}'"),
9129 EmptyAsNull => write!(f, "EMPTYASNULL"),
9130 Encrypted { auto } => write!(f, "ENCRYPTED{}", if *auto { " AUTO" } else { "" }),
9131 Escape => write!(f, "ESCAPE"),
9132 Extension(ext) => write!(f, "EXTENSION '{}'", value::escape_single_quote_string(ext)),
9133 FixedWidth(spec) => write!(
9134 f,
9135 "FIXEDWIDTH '{}'",
9136 value::escape_single_quote_string(spec)
9137 ),
9138 Gzip => write!(f, "GZIP"),
9139 Header => write!(f, "HEADER"),
9140 IamRole(role) => write!(f, "IAM_ROLE {role}"),
9141 IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"),
9142 Json(opt) => {
9143 write!(f, "JSON")?;
9144 if let Some(opt) = opt {
9145 write!(f, " AS '{}'", value::escape_single_quote_string(opt))?;
9146 }
9147 Ok(())
9148 }
9149 Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }),
9150 MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"),
9151 Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
9152 Parallel(enabled) => {
9153 write!(
9154 f,
9155 "PARALLEL{}",
9156 match enabled {
9157 Some(true) => " TRUE",
9158 Some(false) => " FALSE",
9159 _ => "",
9160 }
9161 )
9162 }
9163 Parquet => write!(f, "PARQUET"),
9164 PartitionBy(p) => write!(f, "{p}"),
9165 Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
9166 RemoveQuotes => write!(f, "REMOVEQUOTES"),
9167 RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
9168 StatUpdate(enabled) => {
9169 write!(
9170 f,
9171 "STATUPDATE{}",
9172 match enabled {
9173 Some(true) => " TRUE",
9174 Some(false) => " FALSE",
9175 _ => "",
9176 }
9177 )
9178 }
9179 TimeFormat(fmt) => {
9180 write!(f, "TIMEFORMAT")?;
9181 if let Some(fmt) = fmt {
9182 write!(f, " '{}'", value::escape_single_quote_string(fmt))?;
9183 }
9184 Ok(())
9185 }
9186 TruncateColumns => write!(f, "TRUNCATECOLUMNS"),
9187 Zstd => write!(f, "ZSTD"),
9188 }
9189 }
9190}
9191
9192/// ```sql
9193/// SIZE \[ MB | GB \]
9194/// ```
9195#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9196#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9197#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9198pub struct FileSize {
9199 /// Numeric size value.
9200 pub size: Value,
9201 /// Optional unit for the size (MB or GB).
9202 pub unit: Option<FileSizeUnit>,
9203}
9204
9205impl fmt::Display for FileSize {
9206 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9207 write!(f, "{}", self.size)?;
9208 if let Some(unit) = &self.unit {
9209 write!(f, " {unit}")?;
9210 }
9211 Ok(())
9212 }
9213}
9214
9215/// Units for `FileSize` (MB or GB).
9216#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9217#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9218#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9219pub enum FileSizeUnit {
9220 /// Megabytes.
9221 MB,
9222 /// Gigabytes.
9223 GB,
9224}
9225
9226impl fmt::Display for FileSizeUnit {
9227 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9228 match self {
9229 FileSizeUnit::MB => write!(f, "MB"),
9230 FileSizeUnit::GB => write!(f, "GB"),
9231 }
9232 }
9233}
9234
9235/// Specifies the partition keys for the unload operation
9236///
9237/// ```sql
9238/// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9239/// ```
9240#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9241#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9242#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9243pub struct UnloadPartitionBy {
9244 /// Columns used to partition the unload output.
9245 pub columns: Vec<Ident>,
9246 /// Whether to include the partition in the output.
9247 pub include: bool,
9248}
9249
9250impl fmt::Display for UnloadPartitionBy {
9251 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9252 write!(
9253 f,
9254 "PARTITION BY ({}){}",
9255 display_comma_separated(&self.columns),
9256 if self.include { " INCLUDE" } else { "" }
9257 )
9258 }
9259}
9260
9261/// An `IAM_ROLE` option in the AWS ecosystem
9262///
9263/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
9264#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9265#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9266#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9267pub enum IamRoleKind {
9268 /// Default role
9269 Default,
9270 /// Specific role ARN, for example: `arn:aws:iam::123456789:role/role1`
9271 Arn(String),
9272}
9273
9274impl fmt::Display for IamRoleKind {
9275 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9276 match self {
9277 IamRoleKind::Default => write!(f, "DEFAULT"),
9278 IamRoleKind::Arn(arn) => write!(f, "'{arn}'"),
9279 }
9280 }
9281}
9282
9283/// A `CSV` option in `COPY` statement before PostgreSQL version 9.0.
9284///
9285/// <https://www.postgresql.org/docs/8.4/sql-copy.html>
9286#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9287#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9288#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9289pub enum CopyLegacyCsvOption {
9290 /// HEADER
9291 Header,
9292 /// QUOTE \[ AS \] 'quote_character'
9293 Quote(char),
9294 /// ESCAPE \[ AS \] 'escape_character'
9295 Escape(char),
9296 /// FORCE QUOTE { column_name [, ...] | * }
9297 ForceQuote(Vec<Ident>),
9298 /// FORCE NOT NULL column_name [, ...]
9299 ForceNotNull(Vec<Ident>),
9300}
9301
9302impl fmt::Display for CopyLegacyCsvOption {
9303 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9304 use CopyLegacyCsvOption::*;
9305 match self {
9306 Header => write!(f, "HEADER"),
9307 Quote(char) => write!(f, "QUOTE '{char}'"),
9308 Escape(char) => write!(f, "ESCAPE '{char}'"),
9309 ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
9310 ForceNotNull(columns) => {
9311 write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
9312 }
9313 }
9314 }
9315}
9316
9317/// Objects that can be discarded with `DISCARD`.
9318#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9319#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9320#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9321pub enum DiscardObject {
9322 /// Discard all session state.
9323 ALL,
9324 /// Discard cached plans.
9325 PLANS,
9326 /// Discard sequence values.
9327 SEQUENCES,
9328 /// Discard temporary objects.
9329 TEMP,
9330}
9331
9332impl fmt::Display for DiscardObject {
9333 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9334 match self {
9335 DiscardObject::ALL => f.write_str("ALL"),
9336 DiscardObject::PLANS => f.write_str("PLANS"),
9337 DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
9338 DiscardObject::TEMP => f.write_str("TEMP"),
9339 }
9340 }
9341}
9342
9343/// Types of flush operations supported by `FLUSH`.
9344#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9345#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9346#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9347pub enum FlushType {
9348 /// Flush binary logs.
9349 BinaryLogs,
9350 /// Flush engine logs.
9351 EngineLogs,
9352 /// Flush error logs.
9353 ErrorLogs,
9354 /// Flush general logs.
9355 GeneralLogs,
9356 /// Flush hosts information.
9357 Hosts,
9358 /// Flush logs.
9359 Logs,
9360 /// Flush privileges.
9361 Privileges,
9362 /// Flush optimizer costs.
9363 OptimizerCosts,
9364 /// Flush relay logs.
9365 RelayLogs,
9366 /// Flush slow logs.
9367 SlowLogs,
9368 /// Flush status.
9369 Status,
9370 /// Flush user resources.
9371 UserResources,
9372 /// Flush table data.
9373 Tables,
9374}
9375
9376impl fmt::Display for FlushType {
9377 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9378 match self {
9379 FlushType::BinaryLogs => f.write_str("BINARY LOGS"),
9380 FlushType::EngineLogs => f.write_str("ENGINE LOGS"),
9381 FlushType::ErrorLogs => f.write_str("ERROR LOGS"),
9382 FlushType::GeneralLogs => f.write_str("GENERAL LOGS"),
9383 FlushType::Hosts => f.write_str("HOSTS"),
9384 FlushType::Logs => f.write_str("LOGS"),
9385 FlushType::Privileges => f.write_str("PRIVILEGES"),
9386 FlushType::OptimizerCosts => f.write_str("OPTIMIZER_COSTS"),
9387 FlushType::RelayLogs => f.write_str("RELAY LOGS"),
9388 FlushType::SlowLogs => f.write_str("SLOW LOGS"),
9389 FlushType::Status => f.write_str("STATUS"),
9390 FlushType::UserResources => f.write_str("USER_RESOURCES"),
9391 FlushType::Tables => f.write_str("TABLES"),
9392 }
9393 }
9394}
9395
9396/// Location modifier for flush commands.
9397#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9398#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9399#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9400pub enum FlushLocation {
9401 /// Do not write changes to the binary log.
9402 NoWriteToBinlog,
9403 /// Apply flush locally.
9404 Local,
9405}
9406
9407impl fmt::Display for FlushLocation {
9408 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9409 match self {
9410 FlushLocation::NoWriteToBinlog => f.write_str("NO_WRITE_TO_BINLOG"),
9411 FlushLocation::Local => f.write_str("LOCAL"),
9412 }
9413 }
9414}
9415
9416/// Optional context modifier for statements that can be or `LOCAL`, `GLOBAL`, or `SESSION`.
9417#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9418#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9419#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9420pub enum ContextModifier {
9421 /// `LOCAL` identifier, usually related to transactional states.
9422 Local,
9423 /// `SESSION` identifier
9424 Session,
9425 /// `GLOBAL` identifier
9426 Global,
9427}
9428
9429impl fmt::Display for ContextModifier {
9430 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9431 match self {
9432 Self::Local => {
9433 write!(f, "LOCAL ")
9434 }
9435 Self::Session => {
9436 write!(f, "SESSION ")
9437 }
9438 Self::Global => {
9439 write!(f, "GLOBAL ")
9440 }
9441 }
9442 }
9443}
9444
9445/// Function describe in DROP FUNCTION.
9446#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9447#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9448pub enum DropFunctionOption {
9449 /// `RESTRICT` option for DROP FUNCTION.
9450 Restrict,
9451 /// `CASCADE` option for DROP FUNCTION.
9452 Cascade,
9453}
9454
9455impl fmt::Display for DropFunctionOption {
9456 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9457 match self {
9458 DropFunctionOption::Restrict => write!(f, "RESTRICT "),
9459 DropFunctionOption::Cascade => write!(f, "CASCADE "),
9460 }
9461 }
9462}
9463
9464/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
9465#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9466#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9467#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9468pub struct FunctionDesc {
9469 /// The function name.
9470 pub name: ObjectName,
9471 /// Optional list of function arguments.
9472 pub args: Option<Vec<OperateFunctionArg>>,
9473}
9474
9475impl fmt::Display for FunctionDesc {
9476 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9477 write!(f, "{}", self.name)?;
9478 if let Some(args) = &self.args {
9479 write!(f, "({})", display_comma_separated(args))?;
9480 }
9481 Ok(())
9482 }
9483}
9484
9485/// Function argument in CREATE OR DROP FUNCTION.
9486#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9487#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9488#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9489pub struct OperateFunctionArg {
9490 /// Optional argument mode (`IN`, `OUT`, `INOUT`).
9491 pub mode: Option<ArgMode>,
9492 /// Optional argument identifier/name.
9493 pub name: Option<Ident>,
9494 /// The data type of the argument.
9495 pub data_type: DataType,
9496 /// Optional default expression for the argument.
9497 pub default_expr: Option<Expr>,
9498}
9499
9500impl OperateFunctionArg {
9501 /// Returns an unnamed argument.
9502 pub fn unnamed(data_type: DataType) -> Self {
9503 Self {
9504 mode: None,
9505 name: None,
9506 data_type,
9507 default_expr: None,
9508 }
9509 }
9510
9511 /// Returns an argument with name.
9512 pub fn with_name(name: &str, data_type: DataType) -> Self {
9513 Self {
9514 mode: None,
9515 name: Some(name.into()),
9516 data_type,
9517 default_expr: None,
9518 }
9519 }
9520}
9521
9522impl fmt::Display for OperateFunctionArg {
9523 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9524 if let Some(mode) = &self.mode {
9525 write!(f, "{mode} ")?;
9526 }
9527 if let Some(name) = &self.name {
9528 write!(f, "{name} ")?;
9529 }
9530 write!(f, "{}", self.data_type)?;
9531 if let Some(default_expr) = &self.default_expr {
9532 write!(f, " = {default_expr}")?;
9533 }
9534 Ok(())
9535 }
9536}
9537
9538/// The mode of an argument in CREATE FUNCTION.
9539#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9540#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9541#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9542pub enum ArgMode {
9543 /// `IN` mode.
9544 In,
9545 /// `OUT` mode.
9546 Out,
9547 /// `INOUT` mode.
9548 InOut,
9549}
9550
9551impl fmt::Display for ArgMode {
9552 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9553 match self {
9554 ArgMode::In => write!(f, "IN"),
9555 ArgMode::Out => write!(f, "OUT"),
9556 ArgMode::InOut => write!(f, "INOUT"),
9557 }
9558 }
9559}
9560
9561/// These attributes inform the query optimizer about the behavior of the function.
9562#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9563#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9564#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9565pub enum FunctionBehavior {
9566 /// Function is immutable.
9567 Immutable,
9568 /// Function is stable.
9569 Stable,
9570 /// Function is volatile.
9571 Volatile,
9572}
9573
9574impl fmt::Display for FunctionBehavior {
9575 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9576 match self {
9577 FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
9578 FunctionBehavior::Stable => write!(f, "STABLE"),
9579 FunctionBehavior::Volatile => write!(f, "VOLATILE"),
9580 }
9581 }
9582}
9583
9584/// Security attribute for functions: SECURITY DEFINER or SECURITY INVOKER.
9585///
9586/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9587#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9588#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9589#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9590pub enum FunctionSecurity {
9591 /// Execute the function with the privileges of the user who defined it.
9592 Definer,
9593 /// Execute the function with the privileges of the user who invokes it.
9594 Invoker,
9595}
9596
9597impl fmt::Display for FunctionSecurity {
9598 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9599 match self {
9600 FunctionSecurity::Definer => write!(f, "SECURITY DEFINER"),
9601 FunctionSecurity::Invoker => write!(f, "SECURITY INVOKER"),
9602 }
9603 }
9604}
9605
9606/// Value for a SET configuration parameter in a CREATE FUNCTION statement.
9607///
9608/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9609#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9610#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9611#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9612pub enum FunctionSetValue {
9613 /// SET param = value1, value2, ...
9614 Values(Vec<Expr>),
9615 /// SET param FROM CURRENT
9616 FromCurrent,
9617}
9618
9619/// A SET configuration_parameter clause in a CREATE FUNCTION statement.
9620///
9621/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
9622#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9623#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9624#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9625pub struct FunctionDefinitionSetParam {
9626 /// The name of the configuration parameter.
9627 pub name: Ident,
9628 /// The value to set for the parameter.
9629 pub value: FunctionSetValue,
9630}
9631
9632impl fmt::Display for FunctionDefinitionSetParam {
9633 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9634 write!(f, "SET {} ", self.name)?;
9635 match &self.value {
9636 FunctionSetValue::Values(values) => {
9637 write!(f, "= {}", display_comma_separated(values))
9638 }
9639 FunctionSetValue::FromCurrent => write!(f, "FROM CURRENT"),
9640 }
9641 }
9642}
9643
9644/// These attributes describe the behavior of the function when called with a null argument.
9645#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9646#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9647#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9648pub enum FunctionCalledOnNull {
9649 /// Function is called even when inputs are null.
9650 CalledOnNullInput,
9651 /// Function returns null when any input is null.
9652 ReturnsNullOnNullInput,
9653 /// Function is strict about null inputs.
9654 Strict,
9655}
9656
9657impl fmt::Display for FunctionCalledOnNull {
9658 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9659 match self {
9660 FunctionCalledOnNull::CalledOnNullInput => write!(f, "CALLED ON NULL INPUT"),
9661 FunctionCalledOnNull::ReturnsNullOnNullInput => write!(f, "RETURNS NULL ON NULL INPUT"),
9662 FunctionCalledOnNull::Strict => write!(f, "STRICT"),
9663 }
9664 }
9665}
9666
9667/// If it is safe for PostgreSQL to call the function from multiple threads at once
9668#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9669#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9670#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9671pub enum FunctionParallel {
9672 /// The function is not safe to run in parallel.
9673 Unsafe,
9674 /// The function is restricted for parallel execution.
9675 Restricted,
9676 /// The function is safe to run in parallel.
9677 Safe,
9678}
9679
9680impl fmt::Display for FunctionParallel {
9681 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9682 match self {
9683 FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
9684 FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
9685 FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
9686 }
9687 }
9688}
9689
9690/// [BigQuery] Determinism specifier used in a UDF definition.
9691///
9692/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9693#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9694#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9695#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9696pub enum FunctionDeterminismSpecifier {
9697 /// Function is deterministic.
9698 Deterministic,
9699 /// Function is not deterministic.
9700 NotDeterministic,
9701}
9702
9703impl fmt::Display for FunctionDeterminismSpecifier {
9704 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9705 match self {
9706 FunctionDeterminismSpecifier::Deterministic => {
9707 write!(f, "DETERMINISTIC")
9708 }
9709 FunctionDeterminismSpecifier::NotDeterministic => {
9710 write!(f, "NOT DETERMINISTIC")
9711 }
9712 }
9713 }
9714}
9715
9716/// Represent the expression body of a `CREATE FUNCTION` statement as well as
9717/// where within the statement, the body shows up.
9718///
9719/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9720/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
9721/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9722#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9723#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9724#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9725pub enum CreateFunctionBody {
9726 /// A function body expression using the 'AS' keyword and shows up
9727 /// before any `OPTIONS` clause.
9728 ///
9729 /// Example:
9730 /// ```sql
9731 /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
9732 /// AS (x * y)
9733 /// OPTIONS(description="desc");
9734 /// ```
9735 ///
9736 /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9737 /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
9738 AsBeforeOptions {
9739 /// The primary expression.
9740 body: Expr,
9741 /// Link symbol if the primary expression contains the name of shared library file.
9742 ///
9743 /// Example:
9744 /// ```sql
9745 /// CREATE FUNCTION cas_in(input cstring) RETURNS cas
9746 /// AS 'MODULE_PATHNAME', 'cas_in_wrapper'
9747 /// ```
9748 /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
9749 link_symbol: Option<Expr>,
9750 },
9751 /// A function body expression using the 'AS' keyword and shows up
9752 /// after any `OPTIONS` clause.
9753 ///
9754 /// Example:
9755 /// ```sql
9756 /// CREATE FUNCTION myfunc(x FLOAT64, y FLOAT64) RETURNS FLOAT64
9757 /// OPTIONS(description="desc")
9758 /// AS (x * y);
9759 /// ```
9760 ///
9761 /// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
9762 AsAfterOptions(Expr),
9763 /// Function body with statements before the `RETURN` keyword.
9764 ///
9765 /// Example:
9766 /// ```sql
9767 /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
9768 /// RETURNS INT
9769 /// AS
9770 /// BEGIN
9771 /// DECLARE c INT;
9772 /// SET c = a + b;
9773 /// RETURN c;
9774 /// END
9775 /// ```
9776 ///
9777 /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9778 AsBeginEnd(BeginEndStatements),
9779 /// Function body expression using the 'RETURN' keyword.
9780 ///
9781 /// Example:
9782 /// ```sql
9783 /// CREATE FUNCTION myfunc(a INTEGER, IN b INTEGER = 1) RETURNS INTEGER
9784 /// LANGUAGE SQL
9785 /// RETURN a + b;
9786 /// ```
9787 ///
9788 /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
9789 Return(Expr),
9790
9791 /// Function body expression using the 'AS RETURN' keywords
9792 ///
9793 /// Example:
9794 /// ```sql
9795 /// CREATE FUNCTION myfunc(a INT, b INT)
9796 /// RETURNS TABLE
9797 /// AS RETURN (SELECT a + b AS sum);
9798 /// ```
9799 ///
9800 /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
9801 AsReturnExpr(Expr),
9802
9803 /// Function body expression using the 'AS RETURN' keywords, with an un-parenthesized SELECT query
9804 ///
9805 /// Example:
9806 /// ```sql
9807 /// CREATE FUNCTION myfunc(a INT, b INT)
9808 /// RETURNS TABLE
9809 /// AS RETURN SELECT a + b AS sum;
9810 /// ```
9811 ///
9812 /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#select_stmt
9813 AsReturnSelect(Select),
9814}
9815
9816#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9817#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9818#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9819/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE).
9820pub enum CreateFunctionUsing {
9821 /// Use a JAR file located at the given URI.
9822 Jar(String),
9823 /// Use a file located at the given URI.
9824 File(String),
9825 /// Use an archive located at the given URI.
9826 Archive(String),
9827}
9828
9829impl fmt::Display for CreateFunctionUsing {
9830 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9831 write!(f, "USING ")?;
9832 match self {
9833 CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
9834 CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
9835 CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
9836 }
9837 }
9838}
9839
9840/// `NAME = <EXPR>` arguments for DuckDB macros
9841///
9842/// See [Create Macro - DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
9843/// for more details
9844#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9845#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9846#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9847pub struct MacroArg {
9848 /// The argument name.
9849 pub name: Ident,
9850 /// Optional default expression for the argument.
9851 pub default_expr: Option<Expr>,
9852}
9853
9854impl MacroArg {
9855 /// Returns an argument with name.
9856 pub fn new(name: &str) -> Self {
9857 Self {
9858 name: name.into(),
9859 default_expr: None,
9860 }
9861 }
9862}
9863
9864impl fmt::Display for MacroArg {
9865 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9866 write!(f, "{}", self.name)?;
9867 if let Some(default_expr) = &self.default_expr {
9868 write!(f, " := {default_expr}")?;
9869 }
9870 Ok(())
9871 }
9872}
9873
9874#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9875#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9876#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9877/// Definition for a DuckDB macro: either an expression or a table-producing query.
9878pub enum MacroDefinition {
9879 /// The macro is defined as an expression.
9880 Expr(Expr),
9881 /// The macro is defined as a table (query).
9882 Table(Box<Query>),
9883}
9884
9885impl fmt::Display for MacroDefinition {
9886 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9887 match self {
9888 MacroDefinition::Expr(expr) => write!(f, "{expr}")?,
9889 MacroDefinition::Table(query) => write!(f, "{query}")?,
9890 }
9891 Ok(())
9892 }
9893}
9894
9895/// Schema possible naming variants ([1]).
9896///
9897/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition
9898#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9899#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9900#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9901pub enum SchemaName {
9902 /// Only schema name specified: `<schema name>`.
9903 Simple(ObjectName),
9904 /// Only authorization identifier specified: `AUTHORIZATION <schema authorization identifier>`.
9905 UnnamedAuthorization(Ident),
9906 /// Both schema name and authorization identifier specified: `<schema name> AUTHORIZATION <schema authorization identifier>`.
9907 NamedAuthorization(ObjectName, Ident),
9908}
9909
9910impl fmt::Display for SchemaName {
9911 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9912 match self {
9913 SchemaName::Simple(name) => {
9914 write!(f, "{name}")
9915 }
9916 SchemaName::UnnamedAuthorization(authorization) => {
9917 write!(f, "AUTHORIZATION {authorization}")
9918 }
9919 SchemaName::NamedAuthorization(name, authorization) => {
9920 write!(f, "{name} AUTHORIZATION {authorization}")
9921 }
9922 }
9923 }
9924}
9925
9926/// Fulltext search modifiers ([1]).
9927///
9928/// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match
9929#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9930#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9931#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9932pub enum SearchModifier {
9933 /// `IN NATURAL LANGUAGE MODE`.
9934 InNaturalLanguageMode,
9935 /// `IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION`.
9936 InNaturalLanguageModeWithQueryExpansion,
9937 ///`IN BOOLEAN MODE`.
9938 InBooleanMode,
9939 ///`WITH QUERY EXPANSION`.
9940 WithQueryExpansion,
9941}
9942
9943impl fmt::Display for SearchModifier {
9944 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9945 match self {
9946 Self::InNaturalLanguageMode => {
9947 write!(f, "IN NATURAL LANGUAGE MODE")?;
9948 }
9949 Self::InNaturalLanguageModeWithQueryExpansion => {
9950 write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
9951 }
9952 Self::InBooleanMode => {
9953 write!(f, "IN BOOLEAN MODE")?;
9954 }
9955 Self::WithQueryExpansion => {
9956 write!(f, "WITH QUERY EXPANSION")?;
9957 }
9958 }
9959
9960 Ok(())
9961 }
9962}
9963
9964/// Represents a `LOCK TABLE` clause with optional alias and lock type.
9965#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9966#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9967#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9968pub struct LockTable {
9969 /// The table identifier to lock.
9970 pub table: Ident,
9971 /// Optional alias for the table.
9972 pub alias: Option<Ident>,
9973 /// The type of lock to apply to the table.
9974 pub lock_type: LockTableType,
9975}
9976
9977impl fmt::Display for LockTable {
9978 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9979 let Self {
9980 table: tbl_name,
9981 alias,
9982 lock_type,
9983 } = self;
9984
9985 write!(f, "{tbl_name} ")?;
9986 if let Some(alias) = alias {
9987 write!(f, "AS {alias} ")?;
9988 }
9989 write!(f, "{lock_type}")?;
9990 Ok(())
9991 }
9992}
9993
9994#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
9995#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9996#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
9997/// The type of lock used in `LOCK TABLE` statements.
9998pub enum LockTableType {
9999 /// Shared/read lock. If `local` is true, it's a local read lock.
10000 Read {
10001 /// Whether the read lock is local.
10002 local: bool,
10003 },
10004 /// Exclusive/write lock. If `low_priority` is true, the write is low priority.
10005 Write {
10006 /// Whether the write lock is low priority.
10007 low_priority: bool,
10008 },
10009}
10010
10011impl fmt::Display for LockTableType {
10012 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10013 match self {
10014 Self::Read { local } => {
10015 write!(f, "READ")?;
10016 if *local {
10017 write!(f, " LOCAL")?;
10018 }
10019 }
10020 Self::Write { low_priority } => {
10021 if *low_priority {
10022 write!(f, "LOW_PRIORITY ")?;
10023 }
10024 write!(f, "WRITE")?;
10025 }
10026 }
10027
10028 Ok(())
10029 }
10030}
10031
10032#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10033#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10034#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10035/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements.
10036pub struct HiveSetLocation {
10037 /// Whether the `SET` keyword was present.
10038 pub has_set: bool,
10039 /// The location identifier.
10040 pub location: Ident,
10041}
10042
10043impl fmt::Display for HiveSetLocation {
10044 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10045 if self.has_set {
10046 write!(f, "SET ")?;
10047 }
10048 write!(f, "LOCATION {}", self.location)
10049 }
10050}
10051
10052/// MySQL `ALTER TABLE` only [FIRST | AFTER column_name]
10053#[allow(clippy::large_enum_variant)]
10054#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10055#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10056#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10057/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER <column>`.
10058pub enum MySQLColumnPosition {
10059 /// Place the column first in the table.
10060 First,
10061 /// Place the column after the specified identifier.
10062 After(Ident),
10063}
10064
10065impl Display for MySQLColumnPosition {
10066 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10067 match self {
10068 MySQLColumnPosition::First => write!(f, "FIRST"),
10069 MySQLColumnPosition::After(ident) => {
10070 let column_name = &ident.value;
10071 write!(f, "AFTER {column_name}")
10072 }
10073 }
10074 }
10075}
10076
10077/// MySQL `CREATE VIEW` algorithm parameter: [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
10078#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10079#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10080#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10081/// MySQL `CREATE VIEW` algorithm options.
10082pub enum CreateViewAlgorithm {
10083 /// `UNDEFINED` algorithm.
10084 Undefined,
10085 /// `MERGE` algorithm.
10086 Merge,
10087 /// `TEMPTABLE` algorithm.
10088 TempTable,
10089}
10090
10091impl Display for CreateViewAlgorithm {
10092 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10093 match self {
10094 CreateViewAlgorithm::Undefined => write!(f, "UNDEFINED"),
10095 CreateViewAlgorithm::Merge => write!(f, "MERGE"),
10096 CreateViewAlgorithm::TempTable => write!(f, "TEMPTABLE"),
10097 }
10098 }
10099}
10100/// MySQL `CREATE VIEW` security parameter: [SQL SECURITY { DEFINER | INVOKER }]
10101#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10103#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10104/// MySQL `CREATE VIEW` SQL SECURITY options.
10105pub enum CreateViewSecurity {
10106 /// The view runs with the privileges of the definer.
10107 Definer,
10108 /// The view runs with the privileges of the invoker.
10109 Invoker,
10110}
10111
10112impl Display for CreateViewSecurity {
10113 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10114 match self {
10115 CreateViewSecurity::Definer => write!(f, "DEFINER"),
10116 CreateViewSecurity::Invoker => write!(f, "INVOKER"),
10117 }
10118 }
10119}
10120
10121/// [MySQL] `CREATE VIEW` additional parameters
10122///
10123/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/create-view.html
10124#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10125#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10126#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10127pub struct CreateViewParams {
10128 /// Optional view algorithm (e.g., MERGE, TEMPTABLE).
10129 pub algorithm: Option<CreateViewAlgorithm>,
10130 /// Optional definer (the security principal that will own the view).
10131 pub definer: Option<GranteeName>,
10132 /// Optional SQL SECURITY setting for the view.
10133 pub security: Option<CreateViewSecurity>,
10134}
10135
10136impl Display for CreateViewParams {
10137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10138 let CreateViewParams {
10139 algorithm,
10140 definer,
10141 security,
10142 } = self;
10143 if let Some(algorithm) = algorithm {
10144 write!(f, "ALGORITHM = {algorithm} ")?;
10145 }
10146 if let Some(definers) = definer {
10147 write!(f, "DEFINER = {definers} ")?;
10148 }
10149 if let Some(security) = security {
10150 write!(f, "SQL SECURITY {security} ")?;
10151 }
10152 Ok(())
10153 }
10154}
10155
10156#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10157#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10158#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10159/// Key/Value, where the value is a (optionally named) list of identifiers
10160///
10161/// ```sql
10162/// UNION = (tbl_name[,tbl_name]...)
10163/// ENGINE = ReplicatedMergeTree('/table_name','{replica}', ver)
10164/// ENGINE = SummingMergeTree([columns])
10165/// ```
10166pub struct NamedParenthesizedList {
10167 /// The option key (identifier) for this named list.
10168 pub key: Ident,
10169 /// Optional secondary name associated with the key.
10170 pub name: Option<Ident>,
10171 /// The list of identifier values for the key.
10172 pub values: Vec<Ident>,
10173}
10174
10175/// Snowflake `WITH ROW ACCESS POLICY policy_name ON (identifier, ...)`
10176///
10177/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10178/// <https://docs.snowflake.com/en/user-guide/security-row-intro>
10179#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10181#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10182pub struct RowAccessPolicy {
10183 /// The fully-qualified policy object name.
10184 pub policy: ObjectName,
10185 /// Identifiers for the columns or objects the policy applies to.
10186 pub on: Vec<Ident>,
10187}
10188
10189impl RowAccessPolicy {
10190 /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers.
10191 pub fn new(policy: ObjectName, on: Vec<Ident>) -> Self {
10192 Self { policy, on }
10193 }
10194}
10195
10196impl Display for RowAccessPolicy {
10197 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10198 write!(
10199 f,
10200 "WITH ROW ACCESS POLICY {} ON ({})",
10201 self.policy,
10202 display_comma_separated(self.on.as_slice())
10203 )
10204 }
10205}
10206
10207/// Snowflake `WITH TAG ( tag_name = '<tag_value>', ...)`
10208///
10209/// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
10210#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10211#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10212#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10213pub struct Tag {
10214 /// The tag key (can be qualified).
10215 pub key: ObjectName,
10216 /// The tag value as a string.
10217 pub value: String,
10218}
10219
10220impl Tag {
10221 /// Create a new `Tag` with the given key and value.
10222 pub fn new(key: ObjectName, value: String) -> Self {
10223 Self { key, value }
10224 }
10225}
10226
10227impl Display for Tag {
10228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10229 write!(f, "{}='{}'", self.key, self.value)
10230 }
10231}
10232
10233/// Snowflake `WITH CONTACT ( purpose = contact [ , purpose = contact ...] )`
10234///
10235/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10236#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10237#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10238#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10239pub struct ContactEntry {
10240 /// The purpose label for the contact entry.
10241 pub purpose: String,
10242 /// The contact information associated with the purpose.
10243 pub contact: String,
10244}
10245
10246impl Display for ContactEntry {
10247 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10248 write!(f, "{} = {}", self.purpose, self.contact)
10249 }
10250}
10251
10252/// Helper to indicate if a comment includes the `=` in the display form
10253#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10254#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10255#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10256pub enum CommentDef {
10257 /// Includes `=` when printing the comment, as `COMMENT = 'comment'`
10258 /// Does not include `=` when printing the comment, as `COMMENT 'comment'`
10259 WithEq(String),
10260 /// Comment variant that omits the `=` when displayed.
10261 WithoutEq(String),
10262}
10263
10264impl Display for CommentDef {
10265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10266 match self {
10267 CommentDef::WithEq(comment) | CommentDef::WithoutEq(comment) => write!(f, "{comment}"),
10268 }
10269 }
10270}
10271
10272/// Helper to indicate if a collection should be wrapped by a symbol in the display form
10273///
10274/// [`Display`] is implemented for every [`Vec<T>`] where `T: Display`.
10275/// The string output is a comma separated list for the vec items
10276///
10277/// # Examples
10278/// ```
10279/// # use sqlparser::ast::WrappedCollection;
10280/// let items = WrappedCollection::Parentheses(vec!["one", "two", "three"]);
10281/// assert_eq!("(one, two, three)", items.to_string());
10282///
10283/// let items = WrappedCollection::NoWrapping(vec!["one", "two", "three"]);
10284/// assert_eq!("one, two, three", items.to_string());
10285/// ```
10286#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10287#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10288#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10289pub enum WrappedCollection<T> {
10290 /// Print the collection without wrapping symbols, as `item, item, item`
10291 NoWrapping(T),
10292 /// Wraps the collection in Parentheses, as `(item, item, item)`
10293 Parentheses(T),
10294}
10295
10296impl<T> Display for WrappedCollection<Vec<T>>
10297where
10298 T: Display,
10299{
10300 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10301 match self {
10302 WrappedCollection::NoWrapping(inner) => {
10303 write!(f, "{}", display_comma_separated(inner.as_slice()))
10304 }
10305 WrappedCollection::Parentheses(inner) => {
10306 write!(f, "({})", display_comma_separated(inner.as_slice()))
10307 }
10308 }
10309 }
10310}
10311
10312/// Represents a single PostgreSQL utility option.
10313///
10314/// A utility option is a key-value pair where the key is an identifier (IDENT) and the value
10315/// can be one of the following:
10316/// - A number with an optional sign (`+` or `-`). Example: `+10`, `-10.2`, `3`
10317/// - A non-keyword string. Example: `option1`, `'option2'`, `"option3"`
10318/// - keyword: `TRUE`, `FALSE`, `ON` (`off` is also accept).
10319/// - Empty. Example: `ANALYZE` (identifier only)
10320///
10321/// Utility options are used in various PostgreSQL DDL statements, including statements such as
10322/// `CLUSTER`, `EXPLAIN`, `VACUUM`, and `REINDEX`. These statements format options as `( option [, ...] )`.
10323///
10324/// [CLUSTER](https://www.postgresql.org/docs/current/sql-cluster.html)
10325/// [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html)
10326/// [VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)
10327/// [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)
10328///
10329/// For example, the `EXPLAIN` AND `VACUUM` statements with options might look like this:
10330/// ```sql
10331/// EXPLAIN (ANALYZE, VERBOSE TRUE, FORMAT TEXT) SELECT * FROM my_table;
10332///
10333/// VACUUM (VERBOSE, ANALYZE ON, PARALLEL 10) my_table;
10334/// ```
10335#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10336#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10337#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10338pub struct UtilityOption {
10339 /// The option name (identifier).
10340 pub name: Ident,
10341 /// Optional argument for the option (number, string, keyword, etc.).
10342 pub arg: Option<Expr>,
10343}
10344
10345impl Display for UtilityOption {
10346 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10347 if let Some(ref arg) = self.arg {
10348 write!(f, "{} {}", self.name, arg)
10349 } else {
10350 write!(f, "{}", self.name)
10351 }
10352 }
10353}
10354
10355/// Represents the different options available for `SHOW`
10356/// statements to filter the results. Example from Snowflake:
10357/// <https://docs.snowflake.com/en/sql-reference/sql/show-tables>
10358#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10359#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10360#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10361pub struct ShowStatementOptions {
10362 /// Optional scope to show in (for example: TABLE, SCHEMA).
10363 pub show_in: Option<ShowStatementIn>,
10364 /// Optional `STARTS WITH` filter value.
10365 pub starts_with: Option<Value>,
10366 /// Optional `LIMIT` expression.
10367 pub limit: Option<Expr>,
10368 /// Optional `FROM` value used with `LIMIT`.
10369 pub limit_from: Option<Value>,
10370 /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`.
10371 pub filter_position: Option<ShowStatementFilterPosition>,
10372}
10373
10374impl Display for ShowStatementOptions {
10375 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10376 let (like_in_infix, like_in_suffix) = match &self.filter_position {
10377 Some(ShowStatementFilterPosition::Infix(filter)) => {
10378 (format!(" {filter}"), "".to_string())
10379 }
10380 Some(ShowStatementFilterPosition::Suffix(filter)) => {
10381 ("".to_string(), format!(" {filter}"))
10382 }
10383 None => ("".to_string(), "".to_string()),
10384 };
10385 write!(
10386 f,
10387 "{like_in_infix}{show_in}{starts_with}{limit}{from}{like_in_suffix}",
10388 show_in = match &self.show_in {
10389 Some(i) => format!(" {i}"),
10390 None => String::new(),
10391 },
10392 starts_with = match &self.starts_with {
10393 Some(s) => format!(" STARTS WITH {s}"),
10394 None => String::new(),
10395 },
10396 limit = match &self.limit {
10397 Some(l) => format!(" LIMIT {l}"),
10398 None => String::new(),
10399 },
10400 from = match &self.limit_from {
10401 Some(f) => format!(" FROM {f}"),
10402 None => String::new(),
10403 }
10404 )?;
10405 Ok(())
10406 }
10407}
10408
10409#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10410#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10411#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10412/// Where a `SHOW` filter appears relative to the main clause.
10413pub enum ShowStatementFilterPosition {
10414 /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`).
10415 Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl
10416 /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`).
10417 Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%'
10418}
10419
10420#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10421#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10422#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10423/// Parent object types usable with `SHOW ... IN <parent>` clauses.
10424pub enum ShowStatementInParentType {
10425 /// ACCOUNT parent type for SHOW statements.
10426 Account,
10427 /// DATABASE parent type for SHOW statements.
10428 Database,
10429 /// SCHEMA parent type for SHOW statements.
10430 Schema,
10431 /// TABLE parent type for SHOW statements.
10432 Table,
10433 /// VIEW parent type for SHOW statements.
10434 View,
10435}
10436
10437impl fmt::Display for ShowStatementInParentType {
10438 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10439 match self {
10440 ShowStatementInParentType::Account => write!(f, "ACCOUNT"),
10441 ShowStatementInParentType::Database => write!(f, "DATABASE"),
10442 ShowStatementInParentType::Schema => write!(f, "SCHEMA"),
10443 ShowStatementInParentType::Table => write!(f, "TABLE"),
10444 ShowStatementInParentType::View => write!(f, "VIEW"),
10445 }
10446 }
10447}
10448
10449#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10450#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10451#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10452/// Represents a `SHOW ... IN` clause with optional parent qualifier and name.
10453pub struct ShowStatementIn {
10454 /// The clause that specifies what to show (e.g. COLUMNS, TABLES).
10455 pub clause: ShowStatementInClause,
10456 /// Optional parent type qualifier (ACCOUNT/DATABASE/...).
10457 pub parent_type: Option<ShowStatementInParentType>,
10458 /// Optional parent object name for the SHOW clause.
10459 #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
10460 pub parent_name: Option<ObjectName>,
10461}
10462
10463impl fmt::Display for ShowStatementIn {
10464 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10465 write!(f, "{}", self.clause)?;
10466 if let Some(parent_type) = &self.parent_type {
10467 write!(f, " {parent_type}")?;
10468 }
10469 if let Some(parent_name) = &self.parent_name {
10470 write!(f, " {parent_name}")?;
10471 }
10472 Ok(())
10473 }
10474}
10475
10476/// A Show Charset statement
10477#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10478#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10479#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10480pub struct ShowCharset {
10481 /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET`
10482 /// true means CHARSET was used and false means CHARACTER SET was used
10483 pub is_shorthand: bool,
10484 /// Optional `LIKE`/`WHERE`-style filter for the statement.
10485 pub filter: Option<ShowStatementFilter>,
10486}
10487
10488impl fmt::Display for ShowCharset {
10489 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10490 write!(f, "SHOW")?;
10491 if self.is_shorthand {
10492 write!(f, " CHARSET")?;
10493 } else {
10494 write!(f, " CHARACTER SET")?;
10495 }
10496 if let Some(filter) = &self.filter {
10497 write!(f, " {filter}")?;
10498 }
10499 Ok(())
10500 }
10501}
10502
10503#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10504#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10505#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10506/// Options for a `SHOW OBJECTS` statement.
10507pub struct ShowObjects {
10508 /// Whether to show terse output.
10509 pub terse: bool,
10510 /// Additional options controlling the SHOW output.
10511 pub show_options: ShowStatementOptions,
10512}
10513
10514/// MSSQL's json null clause
10515///
10516/// ```plaintext
10517/// <json_null_clause> ::=
10518/// NULL ON NULL
10519/// | ABSENT ON NULL
10520/// ```
10521///
10522/// <https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=sql-server-ver16#json_null_clause>
10523#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10524#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10525#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10526pub enum JsonNullClause {
10527 /// `NULL ON NULL` behavior for JSON functions.
10528 NullOnNull,
10529 /// `ABSENT ON NULL` behavior for JSON functions.
10530 AbsentOnNull,
10531}
10532
10533impl Display for JsonNullClause {
10534 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10535 match self {
10536 JsonNullClause::NullOnNull => write!(f, "NULL ON NULL"),
10537 JsonNullClause::AbsentOnNull => write!(f, "ABSENT ON NULL"),
10538 }
10539 }
10540}
10541
10542/// PostgreSQL JSON function RETURNING clause
10543///
10544/// Example:
10545/// ```sql
10546/// JSON_OBJECT('a': 1 RETURNING jsonb)
10547/// ```
10548#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10549#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10550#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10551pub struct JsonReturningClause {
10552 /// The data type to return from the JSON function (e.g. JSON/JSONB).
10553 pub data_type: DataType,
10554}
10555
10556impl Display for JsonReturningClause {
10557 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10558 write!(f, "RETURNING {}", self.data_type)
10559 }
10560}
10561
10562/// rename object definition
10563#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10564#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10565#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10566pub struct RenameTable {
10567 /// The current name of the object to rename.
10568 pub old_name: ObjectName,
10569 /// The new name for the object.
10570 pub new_name: ObjectName,
10571}
10572
10573impl fmt::Display for RenameTable {
10574 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10575 write!(f, "{} TO {}", self.old_name, self.new_name)?;
10576 Ok(())
10577 }
10578}
10579
10580/// Represents the referenced table in an `INSERT INTO` statement
10581#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10582#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10583#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10584pub enum TableObject {
10585 /// Table specified by name.
10586 /// Example:
10587 /// ```sql
10588 /// INSERT INTO my_table
10589 /// ```
10590 TableName(#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName),
10591
10592 /// Table specified as a function.
10593 /// Example:
10594 /// ```sql
10595 /// INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
10596 /// ```
10597 /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/table-functions)
10598 TableFunction(Function),
10599}
10600
10601impl fmt::Display for TableObject {
10602 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10603 match self {
10604 Self::TableName(table_name) => write!(f, "{table_name}"),
10605 Self::TableFunction(func) => write!(f, "FUNCTION {func}"),
10606 }
10607 }
10608}
10609
10610/// Represents a SET SESSION AUTHORIZATION statement
10611#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10612#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10613#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10614pub struct SetSessionAuthorizationParam {
10615 /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION).
10616 pub scope: ContextModifier,
10617 /// The specific authorization parameter kind.
10618 pub kind: SetSessionAuthorizationParamKind,
10619}
10620
10621impl fmt::Display for SetSessionAuthorizationParam {
10622 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10623 write!(f, "{}", self.kind)
10624 }
10625}
10626
10627/// Represents the parameter kind for SET SESSION AUTHORIZATION
10628#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10629#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10630#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10631pub enum SetSessionAuthorizationParamKind {
10632 /// Default authorization
10633 Default,
10634
10635 /// User name
10636 User(Ident),
10637}
10638
10639impl fmt::Display for SetSessionAuthorizationParamKind {
10640 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10641 match self {
10642 SetSessionAuthorizationParamKind::Default => write!(f, "DEFAULT"),
10643 SetSessionAuthorizationParamKind::User(name) => write!(f, "{}", name),
10644 }
10645 }
10646}
10647
10648#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10649#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10650#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10651/// Kind of session parameter being set by `SET SESSION`.
10652pub enum SetSessionParamKind {
10653 /// Generic session parameter (name/value pair).
10654 Generic(SetSessionParamGeneric),
10655 /// Identity insert related parameter.
10656 IdentityInsert(SetSessionParamIdentityInsert),
10657 /// Offsets-related parameter.
10658 Offsets(SetSessionParamOffsets),
10659 /// Statistics-related parameter.
10660 Statistics(SetSessionParamStatistics),
10661}
10662
10663impl fmt::Display for SetSessionParamKind {
10664 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10665 match self {
10666 SetSessionParamKind::Generic(x) => write!(f, "{x}"),
10667 SetSessionParamKind::IdentityInsert(x) => write!(f, "{x}"),
10668 SetSessionParamKind::Offsets(x) => write!(f, "{x}"),
10669 SetSessionParamKind::Statistics(x) => write!(f, "{x}"),
10670 }
10671 }
10672}
10673
10674#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10675#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10676#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10677/// Generic `SET SESSION` parameter represented as name(s) and value.
10678pub struct SetSessionParamGeneric {
10679 /// Names of the session parameters being set.
10680 pub names: Vec<String>,
10681 /// The value to assign to the parameter(s).
10682 pub value: String,
10683}
10684
10685impl fmt::Display for SetSessionParamGeneric {
10686 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10687 write!(f, "{} {}", display_comma_separated(&self.names), self.value)
10688 }
10689}
10690
10691#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10692#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10693#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10694/// `IDENTITY_INSERT` session parameter for a specific object.
10695pub struct SetSessionParamIdentityInsert {
10696 /// Object name targeted by `IDENTITY_INSERT`.
10697 pub obj: ObjectName,
10698 /// Value (ON/OFF) for the identity insert setting.
10699 pub value: SessionParamValue,
10700}
10701
10702impl fmt::Display for SetSessionParamIdentityInsert {
10703 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10704 write!(f, "IDENTITY_INSERT {} {}", self.obj, self.value)
10705 }
10706}
10707
10708#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10709#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10710#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10711/// Offsets-related session parameter with keywords and a value.
10712pub struct SetSessionParamOffsets {
10713 /// Keywords specifying which offsets to modify.
10714 pub keywords: Vec<String>,
10715 /// Value (ON/OFF) for the offsets setting.
10716 pub value: SessionParamValue,
10717}
10718
10719impl fmt::Display for SetSessionParamOffsets {
10720 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10721 write!(
10722 f,
10723 "OFFSETS {} {}",
10724 display_comma_separated(&self.keywords),
10725 self.value
10726 )
10727 }
10728}
10729
10730#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10731#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10732#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10733/// Statistics-related session parameter specifying topic and value.
10734pub struct SetSessionParamStatistics {
10735 /// Statistics topic to set (IO/PROFILE/TIME/XML).
10736 pub topic: SessionParamStatsTopic,
10737 /// Value (ON/OFF) for the statistics topic.
10738 pub value: SessionParamValue,
10739}
10740
10741impl fmt::Display for SetSessionParamStatistics {
10742 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10743 write!(f, "STATISTICS {} {}", self.topic, self.value)
10744 }
10745}
10746
10747#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10748#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10749#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10750/// Topics available for session statistics configuration.
10751pub enum SessionParamStatsTopic {
10752 /// Input/output statistics.
10753 IO,
10754 /// Profile statistics.
10755 Profile,
10756 /// Time statistics.
10757 Time,
10758 /// XML-related statistics.
10759 Xml,
10760}
10761
10762impl fmt::Display for SessionParamStatsTopic {
10763 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10764 match self {
10765 SessionParamStatsTopic::IO => write!(f, "IO"),
10766 SessionParamStatsTopic::Profile => write!(f, "PROFILE"),
10767 SessionParamStatsTopic::Time => write!(f, "TIME"),
10768 SessionParamStatsTopic::Xml => write!(f, "XML"),
10769 }
10770 }
10771}
10772
10773#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10774#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10775#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10776/// Value for a session boolean-like parameter (ON/OFF).
10777pub enum SessionParamValue {
10778 /// Session parameter enabled.
10779 On,
10780 /// Session parameter disabled.
10781 Off,
10782}
10783
10784impl fmt::Display for SessionParamValue {
10785 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10786 match self {
10787 SessionParamValue::On => write!(f, "ON"),
10788 SessionParamValue::Off => write!(f, "OFF"),
10789 }
10790 }
10791}
10792
10793/// Snowflake StorageSerializationPolicy for Iceberg Tables
10794/// ```sql
10795/// [ STORAGE_SERIALIZATION_POLICY = { COMPATIBLE | OPTIMIZED } ]
10796/// ```
10797///
10798/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
10799#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10800#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10801#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10802pub enum StorageSerializationPolicy {
10803 /// Use compatible serialization mode.
10804 Compatible,
10805 /// Use optimized serialization mode.
10806 Optimized,
10807}
10808
10809impl Display for StorageSerializationPolicy {
10810 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10811 match self {
10812 StorageSerializationPolicy::Compatible => write!(f, "COMPATIBLE"),
10813 StorageSerializationPolicy::Optimized => write!(f, "OPTIMIZED"),
10814 }
10815 }
10816}
10817
10818/// Snowflake CatalogSyncNamespaceMode
10819/// ```sql
10820/// [ CATALOG_SYNC_NAMESPACE_MODE = { NEST | FLATTEN } ]
10821/// ```
10822///
10823/// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
10824#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10825#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10826#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10827pub enum CatalogSyncNamespaceMode {
10828 /// Nest namespaces when syncing catalog.
10829 Nest,
10830 /// Flatten namespaces when syncing catalog.
10831 Flatten,
10832}
10833
10834impl Display for CatalogSyncNamespaceMode {
10835 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10836 match self {
10837 CatalogSyncNamespaceMode::Nest => write!(f, "NEST"),
10838 CatalogSyncNamespaceMode::Flatten => write!(f, "FLATTEN"),
10839 }
10840 }
10841}
10842
10843/// Variants of the Snowflake `COPY INTO` statement
10844#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10845#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10846#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10847pub enum CopyIntoSnowflakeKind {
10848 /// Loads data from files to a table
10849 /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
10850 Table,
10851 /// Unloads data from a table or query to external files
10852 /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
10853 Location,
10854}
10855
10856#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10857#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10858#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10859/// `PRINT` statement for producing debug/output messages.
10860pub struct PrintStatement {
10861 /// The expression producing the message to print.
10862 pub message: Box<Expr>,
10863}
10864
10865impl fmt::Display for PrintStatement {
10866 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10867 write!(f, "PRINT {}", self.message)
10868 }
10869}
10870
10871/// Represents a `Return` statement.
10872///
10873/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
10874/// [MsSql functions](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql)
10875#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10876#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10877#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10878pub struct ReturnStatement {
10879 /// Optional return value expression.
10880 pub value: Option<ReturnStatementValue>,
10881}
10882
10883impl fmt::Display for ReturnStatement {
10884 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10885 match &self.value {
10886 Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {expr}"),
10887 None => write!(f, "RETURN"),
10888 }
10889 }
10890}
10891
10892/// Variants of a `RETURN` statement
10893#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10894#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10895#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10896pub enum ReturnStatementValue {
10897 /// Return an expression from a function or trigger.
10898 Expr(Expr),
10899}
10900
10901/// Represents an `OPEN` statement.
10902#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10903#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10904#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10905pub struct OpenStatement {
10906 /// Cursor name
10907 pub cursor_name: Ident,
10908}
10909
10910impl fmt::Display for OpenStatement {
10911 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10912 write!(f, "OPEN {}", self.cursor_name)
10913 }
10914}
10915
10916/// Specifies Include / Exclude NULL within UNPIVOT command.
10917/// For example
10918/// `UNPIVOT (column1 FOR new_column IN (col3, col4, col5, col6))`
10919#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10920#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10921#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10922pub enum NullInclusion {
10923 /// Include NULL values in the UNPIVOT output.
10924 IncludeNulls,
10925 /// Exclude NULL values from the UNPIVOT output.
10926 ExcludeNulls,
10927}
10928
10929impl fmt::Display for NullInclusion {
10930 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10931 match self {
10932 NullInclusion::IncludeNulls => write!(f, "INCLUDE NULLS"),
10933 NullInclusion::ExcludeNulls => write!(f, "EXCLUDE NULLS"),
10934 }
10935 }
10936}
10937
10938/// Checks membership of a value in a JSON array
10939///
10940/// Syntax:
10941/// ```sql
10942/// <value> MEMBER OF(<array>)
10943/// ```
10944/// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html#operator_member-of)
10945#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10946#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10947#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10948pub struct MemberOf {
10949 /// The value to check for membership.
10950 pub value: Box<Expr>,
10951 /// The JSON array expression to check against.
10952 pub array: Box<Expr>,
10953}
10954
10955impl fmt::Display for MemberOf {
10956 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10957 write!(f, "{} MEMBER OF({})", self.value, self.array)
10958 }
10959}
10960
10961#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10962#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10963#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10964/// Represents an `EXPORT DATA` statement.
10965pub struct ExportData {
10966 /// Options for the export operation.
10967 pub options: Vec<SqlOption>,
10968 /// The query producing the data to export.
10969 pub query: Box<Query>,
10970 /// Optional named connection to use for export.
10971 pub connection: Option<ObjectName>,
10972}
10973
10974impl fmt::Display for ExportData {
10975 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10976 if let Some(connection) = &self.connection {
10977 write!(
10978 f,
10979 "EXPORT DATA WITH CONNECTION {connection} OPTIONS({}) AS {}",
10980 display_comma_separated(&self.options),
10981 self.query
10982 )
10983 } else {
10984 write!(
10985 f,
10986 "EXPORT DATA OPTIONS({}) AS {}",
10987 display_comma_separated(&self.options),
10988 self.query
10989 )
10990 }
10991 }
10992}
10993/// Creates a user
10994///
10995/// Syntax:
10996/// ```sql
10997/// CREATE [OR REPLACE] USER [IF NOT EXISTS] <name> [OPTIONS]
10998/// ```
10999///
11000/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-user)
11001#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11002#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11003#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11004pub struct CreateUser {
11005 /// Replace existing user if present.
11006 pub or_replace: bool,
11007 /// Only create the user if it does not already exist.
11008 pub if_not_exists: bool,
11009 /// The name of the user to create.
11010 pub name: Ident,
11011 /// Key/value options for user creation.
11012 pub options: KeyValueOptions,
11013 /// Whether tags are specified using `WITH TAG`.
11014 pub with_tags: bool,
11015 /// Tags for the user.
11016 pub tags: KeyValueOptions,
11017}
11018
11019impl fmt::Display for CreateUser {
11020 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11021 write!(f, "CREATE")?;
11022 if self.or_replace {
11023 write!(f, " OR REPLACE")?;
11024 }
11025 write!(f, " USER")?;
11026 if self.if_not_exists {
11027 write!(f, " IF NOT EXISTS")?;
11028 }
11029 write!(f, " {}", self.name)?;
11030 if !self.options.options.is_empty() {
11031 write!(f, " {}", self.options)?;
11032 }
11033 if !self.tags.options.is_empty() {
11034 if self.with_tags {
11035 write!(f, " WITH")?;
11036 }
11037 write!(f, " TAG ({})", self.tags)?;
11038 }
11039 Ok(())
11040 }
11041}
11042
11043/// Modifies the properties of a user
11044///
11045/// [Snowflake Syntax:](https://docs.snowflake.com/en/sql-reference/sql/alter-user)
11046/// ```sql
11047/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
11048/// ```
11049///
11050/// [PostgreSQL Syntax:](https://www.postgresql.org/docs/current/sql-alteruser.html)
11051/// ```sql
11052/// ALTER USER <role_specification> [ WITH ] option [ ... ]
11053/// ```
11054#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11055#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11056#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11057pub struct AlterUser {
11058 /// Whether to only alter the user if it exists.
11059 pub if_exists: bool,
11060 /// The name of the user to alter.
11061 pub name: Ident,
11062 /// Optional new name for the user (Snowflake-specific).
11063 /// See: <https://docs.snowflake.com/en/sql-reference/sql/alter-user#syntax>
11064 pub rename_to: Option<Ident>,
11065 /// Reset the user's password.
11066 pub reset_password: bool,
11067 /// Abort all running queries for the user.
11068 pub abort_all_queries: bool,
11069 /// Optionally add a delegated role authorization.
11070 pub add_role_delegation: Option<AlterUserAddRoleDelegation>,
11071 /// Optionally remove a delegated role authorization.
11072 pub remove_role_delegation: Option<AlterUserRemoveRoleDelegation>,
11073 /// Enroll the user in MFA.
11074 pub enroll_mfa: bool,
11075 /// Set the default MFA method for the user.
11076 pub set_default_mfa_method: Option<MfaMethodKind>,
11077 /// Remove the user's default MFA method.
11078 pub remove_mfa_method: Option<MfaMethodKind>,
11079 /// Modify an MFA method for the user.
11080 pub modify_mfa_method: Option<AlterUserModifyMfaMethod>,
11081 /// Add an MFA OTP method with optional count.
11082 pub add_mfa_method_otp: Option<AlterUserAddMfaMethodOtp>,
11083 /// Set a user policy.
11084 pub set_policy: Option<AlterUserSetPolicy>,
11085 /// Unset a user policy.
11086 pub unset_policy: Option<UserPolicyKind>,
11087 /// Key/value tag options to set on the user.
11088 pub set_tag: KeyValueOptions,
11089 /// Tags to unset on the user.
11090 pub unset_tag: Vec<String>,
11091 /// Key/value properties to set on the user.
11092 pub set_props: KeyValueOptions,
11093 /// Properties to unset on the user.
11094 pub unset_props: Vec<String>,
11095 /// The following options are PostgreSQL-specific: <https://www.postgresql.org/docs/current/sql-alteruser.html>
11096 pub password: Option<AlterUserPassword>,
11097}
11098
11099/// ```sql
11100/// ALTER USER [ IF EXISTS ] [ <name> ] ADD DELEGATED AUTHORIZATION OF ROLE <role_name> TO SECURITY INTEGRATION <integration_name>
11101/// ```
11102#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11103#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11104#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11105pub struct AlterUserAddRoleDelegation {
11106 /// Role name to delegate.
11107 pub role: Ident,
11108 /// Security integration receiving the delegation.
11109 pub integration: Ident,
11110}
11111
11112/// ```sql
11113/// ALTER USER [ IF EXISTS ] [ <name> ] REMOVE DELEGATED { AUTHORIZATION OF ROLE <role_name> | AUTHORIZATIONS } FROM SECURITY INTEGRATION <integration_name>
11114/// ```
11115#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11116#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11117#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11118pub struct AlterUserRemoveRoleDelegation {
11119 /// Optional role name to remove delegation for.
11120 pub role: Option<Ident>,
11121 /// Security integration from which to remove delegation.
11122 pub integration: Ident,
11123}
11124
11125/// ```sql
11126/// ADD MFA METHOD OTP [ COUNT = number ]
11127/// ```
11128#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11129#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11130#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11131pub struct AlterUserAddMfaMethodOtp {
11132 /// Optional OTP count parameter.
11133 pub count: Option<Value>,
11134}
11135
11136/// ```sql
11137/// ALTER USER [ IF EXISTS ] [ <name> ] MODIFY MFA METHOD <mfa_method> SET COMMENT = '<string>'
11138/// ```
11139#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11141#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11142pub struct AlterUserModifyMfaMethod {
11143 /// The MFA method being modified.
11144 pub method: MfaMethodKind,
11145 /// The new comment for the MFA method.
11146 pub comment: String,
11147}
11148
11149/// Types of MFA methods
11150#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11151#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11152#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11153pub enum MfaMethodKind {
11154 /// PassKey (hardware or platform passkey) MFA method.
11155 PassKey,
11156 /// Time-based One-Time Password (TOTP) MFA method.
11157 Totp,
11158 /// Duo Security MFA method.
11159 Duo,
11160}
11161
11162impl fmt::Display for MfaMethodKind {
11163 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11164 match self {
11165 MfaMethodKind::PassKey => write!(f, "PASSKEY"),
11166 MfaMethodKind::Totp => write!(f, "TOTP"),
11167 MfaMethodKind::Duo => write!(f, "DUO"),
11168 }
11169 }
11170}
11171
11172/// ```sql
11173/// ALTER USER [ IF EXISTS ] [ <name> ] SET { AUTHENTICATION | PASSWORD | SESSION } POLICY <policy_name>
11174/// ```
11175#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11176#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11177#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11178pub struct AlterUserSetPolicy {
11179 /// The kind of user policy being set (authentication/password/session).
11180 pub policy_kind: UserPolicyKind,
11181 /// The identifier of the policy to apply.
11182 pub policy: Ident,
11183}
11184
11185/// Types of user-based policies
11186#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11187#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11188#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11189pub enum UserPolicyKind {
11190 /// Authentication policy.
11191 Authentication,
11192 /// Password policy.
11193 Password,
11194 /// Session policy.
11195 Session,
11196}
11197
11198impl fmt::Display for UserPolicyKind {
11199 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11200 match self {
11201 UserPolicyKind::Authentication => write!(f, "AUTHENTICATION"),
11202 UserPolicyKind::Password => write!(f, "PASSWORD"),
11203 UserPolicyKind::Session => write!(f, "SESSION"),
11204 }
11205 }
11206}
11207
11208impl fmt::Display for AlterUser {
11209 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11210 write!(f, "ALTER")?;
11211 write!(f, " USER")?;
11212 if self.if_exists {
11213 write!(f, " IF EXISTS")?;
11214 }
11215 write!(f, " {}", self.name)?;
11216 if let Some(new_name) = &self.rename_to {
11217 write!(f, " RENAME TO {new_name}")?;
11218 }
11219 if self.reset_password {
11220 write!(f, " RESET PASSWORD")?;
11221 }
11222 if self.abort_all_queries {
11223 write!(f, " ABORT ALL QUERIES")?;
11224 }
11225 if let Some(role_delegation) = &self.add_role_delegation {
11226 let role = &role_delegation.role;
11227 let integration = &role_delegation.integration;
11228 write!(
11229 f,
11230 " ADD DELEGATED AUTHORIZATION OF ROLE {role} TO SECURITY INTEGRATION {integration}"
11231 )?;
11232 }
11233 if let Some(role_delegation) = &self.remove_role_delegation {
11234 write!(f, " REMOVE DELEGATED")?;
11235 match &role_delegation.role {
11236 Some(role) => write!(f, " AUTHORIZATION OF ROLE {role}")?,
11237 None => write!(f, " AUTHORIZATIONS")?,
11238 }
11239 let integration = &role_delegation.integration;
11240 write!(f, " FROM SECURITY INTEGRATION {integration}")?;
11241 }
11242 if self.enroll_mfa {
11243 write!(f, " ENROLL MFA")?;
11244 }
11245 if let Some(method) = &self.set_default_mfa_method {
11246 write!(f, " SET DEFAULT_MFA_METHOD {method}")?
11247 }
11248 if let Some(method) = &self.remove_mfa_method {
11249 write!(f, " REMOVE MFA METHOD {method}")?;
11250 }
11251 if let Some(modify) = &self.modify_mfa_method {
11252 let method = &modify.method;
11253 let comment = &modify.comment;
11254 write!(
11255 f,
11256 " MODIFY MFA METHOD {method} SET COMMENT '{}'",
11257 value::escape_single_quote_string(comment)
11258 )?;
11259 }
11260 if let Some(add_mfa_method_otp) = &self.add_mfa_method_otp {
11261 write!(f, " ADD MFA METHOD OTP")?;
11262 if let Some(count) = &add_mfa_method_otp.count {
11263 write!(f, " COUNT = {count}")?;
11264 }
11265 }
11266 if let Some(policy) = &self.set_policy {
11267 let policy_kind = &policy.policy_kind;
11268 let name = &policy.policy;
11269 write!(f, " SET {policy_kind} POLICY {name}")?;
11270 }
11271 if let Some(policy_kind) = &self.unset_policy {
11272 write!(f, " UNSET {policy_kind} POLICY")?;
11273 }
11274 if !self.set_tag.options.is_empty() {
11275 write!(f, " SET TAG {}", self.set_tag)?;
11276 }
11277 if !self.unset_tag.is_empty() {
11278 write!(f, " UNSET TAG {}", display_comma_separated(&self.unset_tag))?;
11279 }
11280 let has_props = !self.set_props.options.is_empty();
11281 if has_props {
11282 write!(f, " SET")?;
11283 write!(f, " {}", &self.set_props)?;
11284 }
11285 if !self.unset_props.is_empty() {
11286 write!(f, " UNSET {}", display_comma_separated(&self.unset_props))?;
11287 }
11288 if let Some(password) = &self.password {
11289 write!(f, " {}", password)?;
11290 }
11291 Ok(())
11292 }
11293}
11294
11295/// ```sql
11296/// ALTER USER <role_specification> [ WITH ] PASSWORD { 'password' | NULL }``
11297/// ```
11298#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11299#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11300#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11301pub struct AlterUserPassword {
11302 /// Whether the password is encrypted.
11303 pub encrypted: bool,
11304 /// The password string, or `None` for `NULL`.
11305 pub password: Option<String>,
11306}
11307
11308impl Display for AlterUserPassword {
11309 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11310 if self.encrypted {
11311 write!(f, "ENCRYPTED ")?;
11312 }
11313 write!(f, "PASSWORD")?;
11314 match &self.password {
11315 None => write!(f, " NULL")?,
11316 Some(password) => write!(f, " '{}'", value::escape_single_quote_string(password))?,
11317 }
11318 Ok(())
11319 }
11320}
11321
11322/// Specifies how to create a new table based on an existing table's schema.
11323/// '''sql
11324/// CREATE TABLE new LIKE old ...
11325/// '''
11326#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11327#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11328#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11329pub enum CreateTableLikeKind {
11330 /// '''sql
11331 /// CREATE TABLE new (LIKE old ...)
11332 /// '''
11333 /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html)
11334 Parenthesized(CreateTableLike),
11335 /// '''sql
11336 /// CREATE TABLE new LIKE old ...
11337 /// '''
11338 /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-table#label-create-table-like)
11339 /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_like)
11340 Plain(CreateTableLike),
11341}
11342
11343#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11344#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11345#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11346/// Controls whether defaults are included when creating a table FROM/LILE another.
11347pub enum CreateTableLikeDefaults {
11348 /// Include default values from the source table.
11349 Including,
11350 /// Exclude default values from the source table.
11351 Excluding,
11352}
11353
11354impl fmt::Display for CreateTableLikeDefaults {
11355 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11356 match self {
11357 CreateTableLikeDefaults::Including => write!(f, "INCLUDING DEFAULTS"),
11358 CreateTableLikeDefaults::Excluding => write!(f, "EXCLUDING DEFAULTS"),
11359 }
11360 }
11361}
11362
11363#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11364#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11365#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11366/// Represents the `LIKE` clause of a `CREATE TABLE` statement.
11367pub struct CreateTableLike {
11368 /// The source table name to copy the schema from.
11369 pub name: ObjectName,
11370 /// Optional behavior controlling whether defaults are copied.
11371 pub defaults: Option<CreateTableLikeDefaults>,
11372}
11373
11374impl fmt::Display for CreateTableLike {
11375 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11376 write!(f, "LIKE {}", self.name)?;
11377 if let Some(defaults) = &self.defaults {
11378 write!(f, " {defaults}")?;
11379 }
11380 Ok(())
11381 }
11382}
11383
11384/// Specifies the refresh mode for the dynamic table.
11385///
11386/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11387#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11388#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11389#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11390pub enum RefreshModeKind {
11391 /// Automatic refresh mode (`AUTO`).
11392 Auto,
11393 /// Full refresh mode (`FULL`).
11394 Full,
11395 /// Incremental refresh mode (`INCREMENTAL`).
11396 Incremental,
11397}
11398
11399impl fmt::Display for RefreshModeKind {
11400 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11401 match self {
11402 RefreshModeKind::Auto => write!(f, "AUTO"),
11403 RefreshModeKind::Full => write!(f, "FULL"),
11404 RefreshModeKind::Incremental => write!(f, "INCREMENTAL"),
11405 }
11406 }
11407}
11408
11409/// Specifies the behavior of the initial refresh of the dynamic table.
11410///
11411/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-dynamic-table)
11412#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11413#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11414#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11415pub enum InitializeKind {
11416 /// Initialize on creation (`ON CREATE`).
11417 OnCreate,
11418 /// Initialize on schedule (`ON SCHEDULE`).
11419 OnSchedule,
11420}
11421
11422impl fmt::Display for InitializeKind {
11423 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11424 match self {
11425 InitializeKind::OnCreate => write!(f, "ON_CREATE"),
11426 InitializeKind::OnSchedule => write!(f, "ON_SCHEDULE"),
11427 }
11428 }
11429}
11430
11431/// Re-sorts rows and reclaims space in either a specified table or all tables in the current database
11432///
11433/// '''sql
11434/// VACUUM [ FULL | SORT ONLY | DELETE ONLY | REINDEX | RECLUSTER ] [ \[ table_name \] [ TO threshold PERCENT ] \[ BOOST \] ]
11435/// '''
11436/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
11437#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11438#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11439#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11440pub struct VacuumStatement {
11441 /// Whether `FULL` was specified.
11442 pub full: bool,
11443 /// Whether `SORT ONLY` was specified.
11444 pub sort_only: bool,
11445 /// Whether `DELETE ONLY` was specified.
11446 pub delete_only: bool,
11447 /// Whether `REINDEX` was specified.
11448 pub reindex: bool,
11449 /// Whether `RECLUSTER` was specified.
11450 pub recluster: bool,
11451 /// Optional table to run `VACUUM` on.
11452 pub table_name: Option<ObjectName>,
11453 /// Optional threshold value (percent) for `TO threshold PERCENT`.
11454 pub threshold: Option<Value>,
11455 /// Whether `BOOST` was specified.
11456 pub boost: bool,
11457}
11458
11459impl fmt::Display for VacuumStatement {
11460 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11461 write!(
11462 f,
11463 "VACUUM{}{}{}{}{}",
11464 if self.full { " FULL" } else { "" },
11465 if self.sort_only { " SORT ONLY" } else { "" },
11466 if self.delete_only { " DELETE ONLY" } else { "" },
11467 if self.reindex { " REINDEX" } else { "" },
11468 if self.recluster { " RECLUSTER" } else { "" },
11469 )?;
11470 if let Some(table_name) = &self.table_name {
11471 write!(f, " {table_name}")?;
11472 }
11473 if let Some(threshold) = &self.threshold {
11474 write!(f, " TO {threshold} PERCENT")?;
11475 }
11476 if self.boost {
11477 write!(f, " BOOST")?;
11478 }
11479 Ok(())
11480 }
11481}
11482
11483/// Variants of the RESET statement
11484#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11485#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11486#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11487pub enum Reset {
11488 /// Resets all session parameters to their default values.
11489 ALL,
11490
11491 /// Resets a specific session parameter to its default value.
11492 ConfigurationParameter(ObjectName),
11493}
11494
11495/// Resets a session parameter to its default value.
11496/// ```sql
11497/// RESET { ALL | <configuration_parameter> }
11498/// ```
11499#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11500#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11501#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11502pub struct ResetStatement {
11503 /// The reset action to perform (either `ALL` or a specific configuration parameter).
11504 pub reset: Reset,
11505}
11506
11507/// Query optimizer hints are optionally supported comments after the
11508/// `SELECT`, `INSERT`, `UPDATE`, `REPLACE`, `MERGE`, and `DELETE` keywords in
11509/// the corresponding statements.
11510///
11511/// See [Select::optimizer_hint]
11512#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11513#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11514#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11515pub struct OptimizerHint {
11516 /// the raw test of the optimizer hint without its markers
11517 pub text: String,
11518 /// the style of the comment which `text` was extracted from,
11519 /// e.g. `/*+...*/` or `--+...`
11520 ///
11521 /// Not all dialects support all styles, though.
11522 pub style: OptimizerHintStyle,
11523}
11524
11525/// The commentary style of an [optimizer hint](OptimizerHint)
11526#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
11527#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11528#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11529pub enum OptimizerHintStyle {
11530 /// A hint corresponding to a single line comment,
11531 /// e.g. `--+ LEADING(v.e v.d t)`
11532 SingleLine {
11533 /// the comment prefix, e.g. `--`
11534 prefix: String,
11535 },
11536 /// A hint corresponding to a multi line comment,
11537 /// e.g. `/*+ LEADING(v.e v.d t) */`
11538 MultiLine,
11539}
11540
11541impl fmt::Display for OptimizerHint {
11542 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11543 match &self.style {
11544 OptimizerHintStyle::SingleLine { prefix } => {
11545 f.write_str(prefix)?;
11546 f.write_str("+")?;
11547 f.write_str(&self.text)
11548 }
11549 OptimizerHintStyle::MultiLine => {
11550 f.write_str("/*+")?;
11551 f.write_str(&self.text)?;
11552 f.write_str("*/")
11553 }
11554 }
11555 }
11556}
11557
11558impl fmt::Display for ResetStatement {
11559 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11560 match &self.reset {
11561 Reset::ALL => write!(f, "RESET ALL"),
11562 Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
11563 }
11564 }
11565}
11566
11567impl From<Set> for Statement {
11568 fn from(s: Set) -> Self {
11569 Self::Set(s)
11570 }
11571}
11572
11573impl From<Query> for Statement {
11574 fn from(q: Query) -> Self {
11575 Box::new(q).into()
11576 }
11577}
11578
11579impl From<Box<Query>> for Statement {
11580 fn from(q: Box<Query>) -> Self {
11581 Self::Query(q)
11582 }
11583}
11584
11585impl From<Insert> for Statement {
11586 fn from(i: Insert) -> Self {
11587 Self::Insert(i)
11588 }
11589}
11590
11591impl From<Update> for Statement {
11592 fn from(u: Update) -> Self {
11593 Self::Update(u)
11594 }
11595}
11596
11597impl From<CreateView> for Statement {
11598 fn from(cv: CreateView) -> Self {
11599 Self::CreateView(cv)
11600 }
11601}
11602
11603impl From<CreateRole> for Statement {
11604 fn from(cr: CreateRole) -> Self {
11605 Self::CreateRole(cr)
11606 }
11607}
11608
11609impl From<AlterTable> for Statement {
11610 fn from(at: AlterTable) -> Self {
11611 Self::AlterTable(at)
11612 }
11613}
11614
11615impl From<DropFunction> for Statement {
11616 fn from(df: DropFunction) -> Self {
11617 Self::DropFunction(df)
11618 }
11619}
11620
11621impl From<CreateExtension> for Statement {
11622 fn from(ce: CreateExtension) -> Self {
11623 Self::CreateExtension(ce)
11624 }
11625}
11626
11627impl From<DropExtension> for Statement {
11628 fn from(de: DropExtension) -> Self {
11629 Self::DropExtension(de)
11630 }
11631}
11632
11633impl From<CaseStatement> for Statement {
11634 fn from(c: CaseStatement) -> Self {
11635 Self::Case(c)
11636 }
11637}
11638
11639impl From<IfStatement> for Statement {
11640 fn from(i: IfStatement) -> Self {
11641 Self::If(i)
11642 }
11643}
11644
11645impl From<WhileStatement> for Statement {
11646 fn from(w: WhileStatement) -> Self {
11647 Self::While(w)
11648 }
11649}
11650
11651impl From<RaiseStatement> for Statement {
11652 fn from(r: RaiseStatement) -> Self {
11653 Self::Raise(r)
11654 }
11655}
11656
11657impl From<Function> for Statement {
11658 fn from(f: Function) -> Self {
11659 Self::Call(f)
11660 }
11661}
11662
11663impl From<OpenStatement> for Statement {
11664 fn from(o: OpenStatement) -> Self {
11665 Self::Open(o)
11666 }
11667}
11668
11669impl From<Delete> for Statement {
11670 fn from(d: Delete) -> Self {
11671 Self::Delete(d)
11672 }
11673}
11674
11675impl From<CreateTable> for Statement {
11676 fn from(c: CreateTable) -> Self {
11677 Self::CreateTable(c)
11678 }
11679}
11680
11681impl From<CreateIndex> for Statement {
11682 fn from(c: CreateIndex) -> Self {
11683 Self::CreateIndex(c)
11684 }
11685}
11686
11687impl From<CreateServerStatement> for Statement {
11688 fn from(c: CreateServerStatement) -> Self {
11689 Self::CreateServer(c)
11690 }
11691}
11692
11693impl From<CreateConnector> for Statement {
11694 fn from(c: CreateConnector) -> Self {
11695 Self::CreateConnector(c)
11696 }
11697}
11698
11699impl From<CreateOperator> for Statement {
11700 fn from(c: CreateOperator) -> Self {
11701 Self::CreateOperator(c)
11702 }
11703}
11704
11705impl From<CreateOperatorFamily> for Statement {
11706 fn from(c: CreateOperatorFamily) -> Self {
11707 Self::CreateOperatorFamily(c)
11708 }
11709}
11710
11711impl From<CreateOperatorClass> for Statement {
11712 fn from(c: CreateOperatorClass) -> Self {
11713 Self::CreateOperatorClass(c)
11714 }
11715}
11716
11717impl From<AlterSchema> for Statement {
11718 fn from(a: AlterSchema) -> Self {
11719 Self::AlterSchema(a)
11720 }
11721}
11722
11723impl From<AlterType> for Statement {
11724 fn from(a: AlterType) -> Self {
11725 Self::AlterType(a)
11726 }
11727}
11728
11729impl From<AlterOperator> for Statement {
11730 fn from(a: AlterOperator) -> Self {
11731 Self::AlterOperator(a)
11732 }
11733}
11734
11735impl From<AlterOperatorFamily> for Statement {
11736 fn from(a: AlterOperatorFamily) -> Self {
11737 Self::AlterOperatorFamily(a)
11738 }
11739}
11740
11741impl From<AlterOperatorClass> for Statement {
11742 fn from(a: AlterOperatorClass) -> Self {
11743 Self::AlterOperatorClass(a)
11744 }
11745}
11746
11747impl From<Merge> for Statement {
11748 fn from(m: Merge) -> Self {
11749 Self::Merge(m)
11750 }
11751}
11752
11753impl From<AlterUser> for Statement {
11754 fn from(a: AlterUser) -> Self {
11755 Self::AlterUser(a)
11756 }
11757}
11758
11759impl From<DropDomain> for Statement {
11760 fn from(d: DropDomain) -> Self {
11761 Self::DropDomain(d)
11762 }
11763}
11764
11765impl From<ShowCharset> for Statement {
11766 fn from(s: ShowCharset) -> Self {
11767 Self::ShowCharset(s)
11768 }
11769}
11770
11771impl From<ShowObjects> for Statement {
11772 fn from(s: ShowObjects) -> Self {
11773 Self::ShowObjects(s)
11774 }
11775}
11776
11777impl From<Use> for Statement {
11778 fn from(u: Use) -> Self {
11779 Self::Use(u)
11780 }
11781}
11782
11783impl From<CreateFunction> for Statement {
11784 fn from(c: CreateFunction) -> Self {
11785 Self::CreateFunction(c)
11786 }
11787}
11788
11789impl From<CreateTrigger> for Statement {
11790 fn from(c: CreateTrigger) -> Self {
11791 Self::CreateTrigger(c)
11792 }
11793}
11794
11795impl From<DropTrigger> for Statement {
11796 fn from(d: DropTrigger) -> Self {
11797 Self::DropTrigger(d)
11798 }
11799}
11800
11801impl From<DropOperator> for Statement {
11802 fn from(d: DropOperator) -> Self {
11803 Self::DropOperator(d)
11804 }
11805}
11806
11807impl From<DropOperatorFamily> for Statement {
11808 fn from(d: DropOperatorFamily) -> Self {
11809 Self::DropOperatorFamily(d)
11810 }
11811}
11812
11813impl From<DropOperatorClass> for Statement {
11814 fn from(d: DropOperatorClass) -> Self {
11815 Self::DropOperatorClass(d)
11816 }
11817}
11818
11819impl From<DenyStatement> for Statement {
11820 fn from(d: DenyStatement) -> Self {
11821 Self::Deny(d)
11822 }
11823}
11824
11825impl From<CreateDomain> for Statement {
11826 fn from(c: CreateDomain) -> Self {
11827 Self::CreateDomain(c)
11828 }
11829}
11830
11831impl From<RenameTable> for Statement {
11832 fn from(r: RenameTable) -> Self {
11833 vec![r].into()
11834 }
11835}
11836
11837impl From<Vec<RenameTable>> for Statement {
11838 fn from(r: Vec<RenameTable>) -> Self {
11839 Self::RenameTable(r)
11840 }
11841}
11842
11843impl From<PrintStatement> for Statement {
11844 fn from(p: PrintStatement) -> Self {
11845 Self::Print(p)
11846 }
11847}
11848
11849impl From<ReturnStatement> for Statement {
11850 fn from(r: ReturnStatement) -> Self {
11851 Self::Return(r)
11852 }
11853}
11854
11855impl From<ExportData> for Statement {
11856 fn from(e: ExportData) -> Self {
11857 Self::ExportData(e)
11858 }
11859}
11860
11861impl From<CreateUser> for Statement {
11862 fn from(c: CreateUser) -> Self {
11863 Self::CreateUser(c)
11864 }
11865}
11866
11867impl From<VacuumStatement> for Statement {
11868 fn from(v: VacuumStatement) -> Self {
11869 Self::Vacuum(v)
11870 }
11871}
11872
11873impl From<ResetStatement> for Statement {
11874 fn from(r: ResetStatement) -> Self {
11875 Self::Reset(r)
11876 }
11877}
11878
11879#[cfg(test)]
11880mod tests {
11881 use crate::tokenizer::Location;
11882
11883 use super::*;
11884
11885 #[test]
11886 fn test_window_frame_default() {
11887 let window_frame = WindowFrame::default();
11888 assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
11889 }
11890
11891 #[test]
11892 fn test_grouping_sets_display() {
11893 // a and b in different group
11894 let grouping_sets = Expr::GroupingSets(vec![
11895 vec![Expr::Identifier(Ident::new("a"))],
11896 vec![Expr::Identifier(Ident::new("b"))],
11897 ]);
11898 assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}"));
11899
11900 // a and b in the same group
11901 let grouping_sets = Expr::GroupingSets(vec![vec![
11902 Expr::Identifier(Ident::new("a")),
11903 Expr::Identifier(Ident::new("b")),
11904 ]]);
11905 assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}"));
11906
11907 // (a, b) and (c, d) in different group
11908 let grouping_sets = Expr::GroupingSets(vec![
11909 vec![
11910 Expr::Identifier(Ident::new("a")),
11911 Expr::Identifier(Ident::new("b")),
11912 ],
11913 vec![
11914 Expr::Identifier(Ident::new("c")),
11915 Expr::Identifier(Ident::new("d")),
11916 ],
11917 ]);
11918 assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}"));
11919 }
11920
11921 #[test]
11922 fn test_rollup_display() {
11923 let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
11924 assert_eq!("ROLLUP (a)", format!("{rollup}"));
11925
11926 let rollup = Expr::Rollup(vec![vec![
11927 Expr::Identifier(Ident::new("a")),
11928 Expr::Identifier(Ident::new("b")),
11929 ]]);
11930 assert_eq!("ROLLUP ((a, b))", format!("{rollup}"));
11931
11932 let rollup = Expr::Rollup(vec![
11933 vec![Expr::Identifier(Ident::new("a"))],
11934 vec![Expr::Identifier(Ident::new("b"))],
11935 ]);
11936 assert_eq!("ROLLUP (a, b)", format!("{rollup}"));
11937
11938 let rollup = Expr::Rollup(vec![
11939 vec![Expr::Identifier(Ident::new("a"))],
11940 vec![
11941 Expr::Identifier(Ident::new("b")),
11942 Expr::Identifier(Ident::new("c")),
11943 ],
11944 vec![Expr::Identifier(Ident::new("d"))],
11945 ]);
11946 assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}"));
11947 }
11948
11949 #[test]
11950 fn test_cube_display() {
11951 let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
11952 assert_eq!("CUBE (a)", format!("{cube}"));
11953
11954 let cube = Expr::Cube(vec![vec![
11955 Expr::Identifier(Ident::new("a")),
11956 Expr::Identifier(Ident::new("b")),
11957 ]]);
11958 assert_eq!("CUBE ((a, b))", format!("{cube}"));
11959
11960 let cube = Expr::Cube(vec![
11961 vec![Expr::Identifier(Ident::new("a"))],
11962 vec![Expr::Identifier(Ident::new("b"))],
11963 ]);
11964 assert_eq!("CUBE (a, b)", format!("{cube}"));
11965
11966 let cube = Expr::Cube(vec![
11967 vec![Expr::Identifier(Ident::new("a"))],
11968 vec![
11969 Expr::Identifier(Ident::new("b")),
11970 Expr::Identifier(Ident::new("c")),
11971 ],
11972 vec![Expr::Identifier(Ident::new("d"))],
11973 ]);
11974 assert_eq!("CUBE (a, (b, c), d)", format!("{cube}"));
11975 }
11976
11977 #[test]
11978 fn test_interval_display() {
11979 let interval = Expr::Interval(Interval {
11980 value: Box::new(Expr::Value(
11981 Value::SingleQuotedString(String::from("123:45.67")).with_empty_span(),
11982 )),
11983 leading_field: Some(DateTimeField::Minute),
11984 leading_precision: Some(10),
11985 last_field: Some(DateTimeField::Second),
11986 fractional_seconds_precision: Some(9),
11987 });
11988 assert_eq!(
11989 "INTERVAL '123:45.67' MINUTE (10) TO SECOND (9)",
11990 format!("{interval}"),
11991 );
11992
11993 let interval = Expr::Interval(Interval {
11994 value: Box::new(Expr::Value(
11995 Value::SingleQuotedString(String::from("5")).with_empty_span(),
11996 )),
11997 leading_field: Some(DateTimeField::Second),
11998 leading_precision: Some(1),
11999 last_field: None,
12000 fractional_seconds_precision: Some(3),
12001 });
12002 assert_eq!("INTERVAL '5' SECOND (1, 3)", format!("{interval}"));
12003 }
12004
12005 #[test]
12006 fn test_one_or_many_with_parens_deref() {
12007 use core::ops::Index;
12008
12009 let one = OneOrManyWithParens::One("a");
12010
12011 assert_eq!(one.deref(), &["a"]);
12012 assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&one), &["a"]);
12013
12014 assert_eq!(one[0], "a");
12015 assert_eq!(one.index(0), &"a");
12016 assert_eq!(
12017 <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&one, 0),
12018 &"a"
12019 );
12020
12021 assert_eq!(one.len(), 1);
12022 assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&one), 1);
12023
12024 let many1 = OneOrManyWithParens::Many(vec!["b"]);
12025
12026 assert_eq!(many1.deref(), &["b"]);
12027 assert_eq!(<OneOrManyWithParens<_> as Deref>::deref(&many1), &["b"]);
12028
12029 assert_eq!(many1[0], "b");
12030 assert_eq!(many1.index(0), &"b");
12031 assert_eq!(
12032 <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many1, 0),
12033 &"b"
12034 );
12035
12036 assert_eq!(many1.len(), 1);
12037 assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many1), 1);
12038
12039 let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12040
12041 assert_eq!(many2.deref(), &["c", "d"]);
12042 assert_eq!(
12043 <OneOrManyWithParens<_> as Deref>::deref(&many2),
12044 &["c", "d"]
12045 );
12046
12047 assert_eq!(many2[0], "c");
12048 assert_eq!(many2.index(0), &"c");
12049 assert_eq!(
12050 <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 0),
12051 &"c"
12052 );
12053
12054 assert_eq!(many2[1], "d");
12055 assert_eq!(many2.index(1), &"d");
12056 assert_eq!(
12057 <<OneOrManyWithParens<_> as Deref>::Target as Index<usize>>::index(&many2, 1),
12058 &"d"
12059 );
12060
12061 assert_eq!(many2.len(), 2);
12062 assert_eq!(<OneOrManyWithParens<_> as Deref>::Target::len(&many2), 2);
12063 }
12064
12065 #[test]
12066 fn test_one_or_many_with_parens_as_ref() {
12067 let one = OneOrManyWithParens::One("a");
12068
12069 assert_eq!(one.as_ref(), &["a"]);
12070 assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&one), &["a"]);
12071
12072 let many1 = OneOrManyWithParens::Many(vec!["b"]);
12073
12074 assert_eq!(many1.as_ref(), &["b"]);
12075 assert_eq!(<OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many1), &["b"]);
12076
12077 let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12078
12079 assert_eq!(many2.as_ref(), &["c", "d"]);
12080 assert_eq!(
12081 <OneOrManyWithParens<_> as AsRef<_>>::as_ref(&many2),
12082 &["c", "d"]
12083 );
12084 }
12085
12086 #[test]
12087 fn test_one_or_many_with_parens_ref_into_iter() {
12088 let one = OneOrManyWithParens::One("a");
12089
12090 assert_eq!(Vec::from_iter(&one), vec![&"a"]);
12091
12092 let many1 = OneOrManyWithParens::Many(vec!["b"]);
12093
12094 assert_eq!(Vec::from_iter(&many1), vec![&"b"]);
12095
12096 let many2 = OneOrManyWithParens::Many(vec!["c", "d"]);
12097
12098 assert_eq!(Vec::from_iter(&many2), vec![&"c", &"d"]);
12099 }
12100
12101 #[test]
12102 fn test_one_or_many_with_parens_value_into_iter() {
12103 use core::iter::once;
12104
12105 //tests that our iterator implemented methods behaves exactly as it's inner iterator, at every step up to n calls to next/next_back
12106 fn test_steps<I>(ours: OneOrManyWithParens<usize>, inner: I, n: usize)
12107 where
12108 I: IntoIterator<Item = usize, IntoIter: DoubleEndedIterator + Clone> + Clone,
12109 {
12110 fn checks<I>(ours: OneOrManyWithParensIntoIter<usize>, inner: I)
12111 where
12112 I: Iterator<Item = usize> + Clone + DoubleEndedIterator,
12113 {
12114 assert_eq!(ours.size_hint(), inner.size_hint());
12115 assert_eq!(ours.clone().count(), inner.clone().count());
12116
12117 assert_eq!(
12118 ours.clone().fold(1, |a, v| a + v),
12119 inner.clone().fold(1, |a, v| a + v)
12120 );
12121
12122 assert_eq!(Vec::from_iter(ours.clone()), Vec::from_iter(inner.clone()));
12123 assert_eq!(
12124 Vec::from_iter(ours.clone().rev()),
12125 Vec::from_iter(inner.clone().rev())
12126 );
12127 }
12128
12129 let mut ours_next = ours.clone().into_iter();
12130 let mut inner_next = inner.clone().into_iter();
12131
12132 for _ in 0..n {
12133 checks(ours_next.clone(), inner_next.clone());
12134
12135 assert_eq!(ours_next.next(), inner_next.next());
12136 }
12137
12138 let mut ours_next_back = ours.clone().into_iter();
12139 let mut inner_next_back = inner.clone().into_iter();
12140
12141 for _ in 0..n {
12142 checks(ours_next_back.clone(), inner_next_back.clone());
12143
12144 assert_eq!(ours_next_back.next_back(), inner_next_back.next_back());
12145 }
12146
12147 let mut ours_mixed = ours.clone().into_iter();
12148 let mut inner_mixed = inner.clone().into_iter();
12149
12150 for i in 0..n {
12151 checks(ours_mixed.clone(), inner_mixed.clone());
12152
12153 if i % 2 == 0 {
12154 assert_eq!(ours_mixed.next_back(), inner_mixed.next_back());
12155 } else {
12156 assert_eq!(ours_mixed.next(), inner_mixed.next());
12157 }
12158 }
12159
12160 let mut ours_mixed2 = ours.into_iter();
12161 let mut inner_mixed2 = inner.into_iter();
12162
12163 for i in 0..n {
12164 checks(ours_mixed2.clone(), inner_mixed2.clone());
12165
12166 if i % 2 == 0 {
12167 assert_eq!(ours_mixed2.next(), inner_mixed2.next());
12168 } else {
12169 assert_eq!(ours_mixed2.next_back(), inner_mixed2.next_back());
12170 }
12171 }
12172 }
12173
12174 test_steps(OneOrManyWithParens::One(1), once(1), 3);
12175 test_steps(OneOrManyWithParens::Many(vec![2]), vec![2], 3);
12176 test_steps(OneOrManyWithParens::Many(vec![3, 4]), vec![3, 4], 4);
12177 }
12178
12179 // Tests that the position in the code of an `Ident` does not affect its
12180 // ordering.
12181 #[test]
12182 fn test_ident_ord() {
12183 let mut a = Ident::with_span(Span::new(Location::new(1, 1), Location::new(1, 1)), "a");
12184 let mut b = Ident::with_span(Span::new(Location::new(2, 2), Location::new(2, 2)), "b");
12185
12186 assert!(a < b);
12187 std::mem::swap(&mut a.span, &mut b.span);
12188 assert!(a < b);
12189 }
12190}