1mod generic; #[cfg(feature = "transpile")]
24mod normalization;
25
26#[cfg(feature = "dialect-athena")]
27mod athena;
28#[cfg(feature = "dialect-bigquery")]
29mod bigquery;
30#[cfg(feature = "dialect-clickhouse")]
31mod clickhouse;
32#[cfg(feature = "dialect-cockroachdb")]
33mod cockroachdb;
34#[cfg(feature = "dialect-databricks")]
35mod databricks;
36#[cfg(feature = "dialect-datafusion")]
37mod datafusion;
38#[cfg(feature = "dialect-doris")]
39mod doris;
40#[cfg(feature = "dialect-dremio")]
41mod dremio;
42#[cfg(feature = "dialect-drill")]
43mod drill;
44#[cfg(feature = "dialect-druid")]
45mod druid;
46#[cfg(feature = "dialect-duckdb")]
47mod duckdb;
48#[cfg(feature = "dialect-dune")]
49mod dune;
50#[cfg(feature = "dialect-exasol")]
51mod exasol;
52#[cfg(feature = "dialect-fabric")]
53mod fabric;
54#[cfg(feature = "dialect-hive")]
55mod hive;
56#[cfg(feature = "dialect-materialize")]
57mod materialize;
58#[cfg(feature = "dialect-mysql")]
59mod mysql;
60#[cfg(feature = "dialect-oracle")]
61mod oracle;
62#[cfg(feature = "dialect-postgresql")]
63mod postgres;
64#[cfg(feature = "dialect-presto")]
65mod presto;
66#[cfg(feature = "dialect-redshift")]
67mod redshift;
68#[cfg(feature = "dialect-risingwave")]
69mod risingwave;
70#[cfg(feature = "dialect-singlestore")]
71mod singlestore;
72#[cfg(feature = "dialect-snowflake")]
73mod snowflake;
74#[cfg(feature = "dialect-solr")]
75mod solr;
76#[cfg(feature = "dialect-spark")]
77mod spark;
78#[cfg(feature = "dialect-sqlite")]
79mod sqlite;
80#[cfg(feature = "dialect-starrocks")]
81mod starrocks;
82#[cfg(feature = "dialect-tableau")]
83mod tableau;
84#[cfg(feature = "dialect-teradata")]
85mod teradata;
86#[cfg(feature = "dialect-tidb")]
87mod tidb;
88#[cfg(feature = "dialect-trino")]
89mod trino;
90#[cfg(feature = "dialect-tsql")]
91mod tsql;
92
93pub use generic::GenericDialect; #[cfg(feature = "dialect-athena")]
96pub use athena::AthenaDialect;
97#[cfg(feature = "dialect-bigquery")]
98pub use bigquery::BigQueryDialect;
99#[cfg(feature = "dialect-clickhouse")]
100pub use clickhouse::ClickHouseDialect;
101#[cfg(feature = "dialect-cockroachdb")]
102pub use cockroachdb::CockroachDBDialect;
103#[cfg(feature = "dialect-databricks")]
104pub use databricks::DatabricksDialect;
105#[cfg(feature = "dialect-datafusion")]
106pub use datafusion::DataFusionDialect;
107#[cfg(feature = "dialect-doris")]
108pub use doris::DorisDialect;
109#[cfg(feature = "dialect-dremio")]
110pub use dremio::DremioDialect;
111#[cfg(feature = "dialect-drill")]
112pub use drill::DrillDialect;
113#[cfg(feature = "dialect-druid")]
114pub use druid::DruidDialect;
115#[cfg(feature = "dialect-duckdb")]
116pub use duckdb::DuckDBDialect;
117#[cfg(feature = "dialect-dune")]
118pub use dune::DuneDialect;
119#[cfg(feature = "dialect-exasol")]
120pub use exasol::ExasolDialect;
121#[cfg(feature = "dialect-fabric")]
122pub use fabric::FabricDialect;
123#[cfg(feature = "dialect-hive")]
124pub use hive::HiveDialect;
125#[cfg(feature = "dialect-materialize")]
126pub use materialize::MaterializeDialect;
127#[cfg(feature = "dialect-mysql")]
128pub use mysql::MySQLDialect;
129#[cfg(feature = "dialect-oracle")]
130pub use oracle::OracleDialect;
131#[cfg(feature = "dialect-postgresql")]
132pub use postgres::PostgresDialect;
133#[cfg(feature = "dialect-presto")]
134pub use presto::PrestoDialect;
135#[cfg(feature = "dialect-redshift")]
136pub use redshift::RedshiftDialect;
137#[cfg(feature = "dialect-risingwave")]
138pub use risingwave::RisingWaveDialect;
139#[cfg(feature = "dialect-singlestore")]
140pub use singlestore::SingleStoreDialect;
141#[cfg(feature = "dialect-snowflake")]
142pub use snowflake::SnowflakeDialect;
143#[cfg(feature = "dialect-solr")]
144pub use solr::SolrDialect;
145#[cfg(feature = "dialect-spark")]
146pub use spark::SparkDialect;
147#[cfg(feature = "dialect-sqlite")]
148pub use sqlite::SQLiteDialect;
149#[cfg(feature = "dialect-starrocks")]
150pub use starrocks::StarRocksDialect;
151#[cfg(feature = "dialect-tableau")]
152pub use tableau::TableauDialect;
153#[cfg(feature = "dialect-teradata")]
154pub use teradata::TeradataDialect;
155#[cfg(feature = "dialect-tidb")]
156pub use tidb::TiDBDialect;
157#[cfg(feature = "dialect-trino")]
158pub use trino::TrinoDialect;
159#[cfg(feature = "dialect-tsql")]
160pub use tsql::TSQLDialect;
161
162use crate::error::Result;
163#[cfg(feature = "transpile")]
164use crate::expressions::{
165 BinaryOp, Case, Cast, ColumnConstraint, DateBin, Fetch, Function, Identifier, Interval,
166 IntervalUnit, IntervalUnitSpec, Literal, Offset, Over, Select, Subquery, Top, Var, WindowFrame,
167 WindowFrameBound, WindowFrameKind,
168};
169use crate::expressions::{DataType, Expression};
170#[cfg(any(
171 feature = "transpile",
172 feature = "ast-tools",
173 feature = "generate",
174 feature = "semantic"
175))]
176use crate::expressions::{From, FunctionBody, Join, Null, OrderBy, OutputClause, TableRef, With};
177#[cfg(feature = "transpile")]
178use crate::generator::UnsupportedLevel;
179#[cfg(feature = "generate")]
180use crate::generator::{Generator, GeneratorConfig};
181#[cfg(feature = "transpile")]
182use crate::guard::enforce_generate_ast;
183use crate::guard::{enforce_input, ComplexityGuardOptions};
184#[cfg(feature = "transpile")]
185use crate::helper::find_new_name;
186use crate::parser::Parser;
187#[cfg(feature = "transpile")]
188use crate::tokens::TokenType;
189use crate::tokens::{Token, Tokenizer, TokenizerConfig};
190#[cfg(feature = "transpile")]
191use crate::traversal::ExpressionWalk;
192use serde::{Deserialize, Serialize};
193use std::collections::HashMap;
194#[cfg(feature = "transpile")]
195use std::collections::HashSet;
196use std::sync::{Arc, LazyLock, RwLock};
197
198#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
207#[serde(rename_all = "lowercase")]
208pub enum DialectType {
209 Generic,
211 PostgreSQL,
213 MySQL,
215 BigQuery,
217 Snowflake,
219 DuckDB,
221 SQLite,
223 Hive,
225 Spark,
227 Trino,
229 Presto,
231 Redshift,
233 TSQL,
235 Oracle,
237 ClickHouse,
239 Databricks,
241 Athena,
243 Teradata,
245 Doris,
247 StarRocks,
249 Materialize,
251 RisingWave,
253 SingleStore,
255 CockroachDB,
257 TiDB,
259 Druid,
261 Solr,
263 Tableau,
265 Dune,
267 Fabric,
269 Drill,
271 Dremio,
273 Exasol,
275 DataFusion,
277}
278
279impl DialectType {
280 pub(crate) const fn supports_string_aliases(self) -> bool {
282 matches!(
283 self,
284 DialectType::TSQL | DialectType::Fabric | DialectType::MySQL | DialectType::SQLite
285 )
286 }
287}
288
289impl Default for DialectType {
290 fn default() -> Self {
291 DialectType::Generic
292 }
293}
294
295impl std::fmt::Display for DialectType {
296 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
297 match self {
298 DialectType::Generic => write!(f, "generic"),
299 DialectType::PostgreSQL => write!(f, "postgresql"),
300 DialectType::MySQL => write!(f, "mysql"),
301 DialectType::BigQuery => write!(f, "bigquery"),
302 DialectType::Snowflake => write!(f, "snowflake"),
303 DialectType::DuckDB => write!(f, "duckdb"),
304 DialectType::SQLite => write!(f, "sqlite"),
305 DialectType::Hive => write!(f, "hive"),
306 DialectType::Spark => write!(f, "spark"),
307 DialectType::Trino => write!(f, "trino"),
308 DialectType::Presto => write!(f, "presto"),
309 DialectType::Redshift => write!(f, "redshift"),
310 DialectType::TSQL => write!(f, "tsql"),
311 DialectType::Oracle => write!(f, "oracle"),
312 DialectType::ClickHouse => write!(f, "clickhouse"),
313 DialectType::Databricks => write!(f, "databricks"),
314 DialectType::Athena => write!(f, "athena"),
315 DialectType::Teradata => write!(f, "teradata"),
316 DialectType::Doris => write!(f, "doris"),
317 DialectType::StarRocks => write!(f, "starrocks"),
318 DialectType::Materialize => write!(f, "materialize"),
319 DialectType::RisingWave => write!(f, "risingwave"),
320 DialectType::SingleStore => write!(f, "singlestore"),
321 DialectType::CockroachDB => write!(f, "cockroachdb"),
322 DialectType::TiDB => write!(f, "tidb"),
323 DialectType::Druid => write!(f, "druid"),
324 DialectType::Solr => write!(f, "solr"),
325 DialectType::Tableau => write!(f, "tableau"),
326 DialectType::Dune => write!(f, "dune"),
327 DialectType::Fabric => write!(f, "fabric"),
328 DialectType::Drill => write!(f, "drill"),
329 DialectType::Dremio => write!(f, "dremio"),
330 DialectType::Exasol => write!(f, "exasol"),
331 DialectType::DataFusion => write!(f, "datafusion"),
332 }
333 }
334}
335
336impl std::str::FromStr for DialectType {
337 type Err = crate::error::Error;
338
339 fn from_str(s: &str) -> Result<Self> {
340 match s.to_ascii_lowercase().as_str() {
341 "generic" | "" => Ok(DialectType::Generic),
342 "postgres" | "postgresql" => Ok(DialectType::PostgreSQL),
343 "mysql" => Ok(DialectType::MySQL),
344 "bigquery" => Ok(DialectType::BigQuery),
345 "snowflake" => Ok(DialectType::Snowflake),
346 "duckdb" => Ok(DialectType::DuckDB),
347 "sqlite" => Ok(DialectType::SQLite),
348 "hive" => Ok(DialectType::Hive),
349 "spark" | "spark2" => Ok(DialectType::Spark),
350 "trino" => Ok(DialectType::Trino),
351 "presto" => Ok(DialectType::Presto),
352 "redshift" => Ok(DialectType::Redshift),
353 "tsql" | "mssql" | "sqlserver" => Ok(DialectType::TSQL),
354 "oracle" => Ok(DialectType::Oracle),
355 "clickhouse" => Ok(DialectType::ClickHouse),
356 "databricks" => Ok(DialectType::Databricks),
357 "athena" => Ok(DialectType::Athena),
358 "teradata" => Ok(DialectType::Teradata),
359 "doris" => Ok(DialectType::Doris),
360 "starrocks" => Ok(DialectType::StarRocks),
361 "materialize" => Ok(DialectType::Materialize),
362 "risingwave" => Ok(DialectType::RisingWave),
363 "singlestore" | "memsql" => Ok(DialectType::SingleStore),
364 "cockroachdb" | "cockroach" => Ok(DialectType::CockroachDB),
365 "tidb" => Ok(DialectType::TiDB),
366 "druid" => Ok(DialectType::Druid),
367 "solr" => Ok(DialectType::Solr),
368 "tableau" => Ok(DialectType::Tableau),
369 "dune" => Ok(DialectType::Dune),
370 "fabric" => Ok(DialectType::Fabric),
371 "drill" => Ok(DialectType::Drill),
372 "dremio" => Ok(DialectType::Dremio),
373 "exasol" => Ok(DialectType::Exasol),
374 "datafusion" | "arrow-datafusion" | "arrow_datafusion" => Ok(DialectType::DataFusion),
375 _ => Err(crate::error::Error::parse(
376 format!("Unknown dialect: {}", s),
377 0,
378 0,
379 0,
380 0,
381 )),
382 }
383 }
384}
385
386pub trait DialectImpl {
402 fn dialect_type(&self) -> DialectType;
404
405 fn tokenizer_config(&self) -> TokenizerConfig {
410 TokenizerConfig::default()
411 }
412
413 #[cfg(feature = "generate")]
418 fn generator_config(&self) -> GeneratorConfig {
419 GeneratorConfig::default()
420 }
421
422 #[cfg(feature = "generate")]
428 fn generator_config_for_expr(&self, _expr: &Expression) -> GeneratorConfig {
429 self.generator_config()
430 }
431
432 #[cfg(feature = "transpile")]
438 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
439 Ok(expr)
440 }
441
442 #[cfg(feature = "transpile")]
448 fn preprocess(&self, expr: Expression) -> Result<Expression> {
449 Ok(expr)
450 }
451}
452
453#[cfg(any(
460 feature = "transpile",
461 feature = "ast-tools",
462 feature = "generate",
463 feature = "semantic"
464))]
465fn transform_data_type_recursive<F>(
466 dt: crate::expressions::DataType,
467 transform_fn: &F,
468) -> Result<crate::expressions::DataType>
469where
470 F: Fn(Expression) -> Result<Expression>,
471{
472 use crate::expressions::DataType;
473 let dt_expr = transform_fn(Expression::DataType(dt))?;
475 let dt = match dt_expr {
476 Expression::DataType(d) => d,
477 _ => {
478 return Ok(match dt_expr {
479 _ => DataType::Custom {
480 name: "UNKNOWN".to_string(),
481 },
482 })
483 }
484 };
485 match dt {
487 DataType::Array {
488 element_type,
489 dimension,
490 } => {
491 let inner = transform_data_type_recursive(*element_type, transform_fn)?;
492 Ok(DataType::Array {
493 element_type: Box::new(inner),
494 dimension,
495 })
496 }
497 DataType::List { element_type } => {
498 let inner = transform_data_type_recursive(*element_type, transform_fn)?;
499 Ok(DataType::List {
500 element_type: Box::new(inner),
501 })
502 }
503 DataType::Struct { fields, nested } => {
504 let mut new_fields = Vec::new();
505 for mut field in fields {
506 field.data_type = transform_data_type_recursive(field.data_type, transform_fn)?;
507 new_fields.push(field);
508 }
509 Ok(DataType::Struct {
510 fields: new_fields,
511 nested,
512 })
513 }
514 DataType::Map {
515 key_type,
516 value_type,
517 } => {
518 let k = transform_data_type_recursive(*key_type, transform_fn)?;
519 let v = transform_data_type_recursive(*value_type, transform_fn)?;
520 Ok(DataType::Map {
521 key_type: Box::new(k),
522 value_type: Box::new(v),
523 })
524 }
525 other => Ok(other),
526 }
527}
528
529#[cfg(feature = "transpile")]
532fn duckdb_to_presto_format(fmt: &str) -> String {
533 let mut result = fmt.to_string();
535 result = result.replace("%-m", "\x01NOPADM\x01");
537 result = result.replace("%-d", "\x01NOPADD\x01");
538 result = result.replace("%-I", "\x01NOPADI\x01");
539 result = result.replace("%-H", "\x01NOPADH\x01");
540 result = result.replace("%H:%M:%S", "\x01HMS\x01");
541 result = result.replace("%Y-%m-%d", "\x01YMD\x01");
542 result = result.replace("%M", "%i");
544 result = result.replace("%S", "%s");
545 result = result.replace("\x01NOPADM\x01", "%c");
547 result = result.replace("\x01NOPADD\x01", "%e");
548 result = result.replace("\x01NOPADI\x01", "%l");
549 result = result.replace("\x01NOPADH\x01", "%k");
550 result = result.replace("\x01HMS\x01", "%T");
551 result = result.replace("\x01YMD\x01", "%Y-%m-%d");
552 result
553}
554
555#[cfg(feature = "transpile")]
558fn duckdb_to_bigquery_format(fmt: &str) -> String {
559 let mut result = fmt.to_string();
560 result = result.replace("%-d", "%e");
562 result = result.replace("%Y-%m-%d %H:%M:%S", "%F %T");
563 result = result.replace("%Y-%m-%d", "%F");
564 result = result.replace("%H:%M:%S", "%T");
565 result
566}
567
568#[cfg(feature = "transpile")]
569fn presto_to_java_format(fmt: &str) -> String {
570 fmt.replace("%Y", "yyyy")
571 .replace("%m", "MM")
572 .replace("%d", "dd")
573 .replace("%H", "HH")
574 .replace("%i", "mm")
575 .replace("%S", "ss")
576 .replace("%s", "ss")
577 .replace("%y", "yy")
578 .replace("%T", "HH:mm:ss")
579 .replace("%F", "yyyy-MM-dd")
580 .replace("%M", "MMMM")
581}
582
583#[cfg(feature = "transpile")]
584fn presto_to_java_parse_format(fmt: &str) -> String {
585 fmt.replace("%Y", "yyyy")
586 .replace("%m", "M")
587 .replace("%d", "d")
588 .replace("%H", "H")
589 .replace("%i", "m")
590 .replace("%S", "s")
591 .replace("%s", "s")
592 .replace("%y", "yy")
593 .replace("%T", "H:m:s")
594 .replace("%F", "yyyy-M-d")
595 .replace("%M", "MMMM")
596}
597
598#[cfg(feature = "transpile")]
599fn normalize_presto_format(fmt: &str) -> String {
600 fmt.replace("%H:%i:%S", "%T").replace("%H:%i:%s", "%T")
601}
602
603#[cfg(feature = "transpile")]
604fn presto_to_duckdb_format(fmt: &str) -> String {
605 fmt.replace("%i", "%M")
606 .replace("%s", "%S")
607 .replace("%T", "%H:%M:%S")
608}
609
610#[cfg(feature = "transpile")]
611fn presto_to_bigquery_format(fmt: &str) -> String {
612 fmt.replace("%Y-%m-%d", "%F")
613 .replace("%H:%i:%S", "%T")
614 .replace("%H:%i:%s", "%T")
615 .replace("%i", "%M")
616 .replace("%s", "%S")
617}
618
619#[cfg(feature = "transpile")]
620fn is_default_presto_timestamp_format(fmt: &str) -> bool {
621 let normalized = normalize_presto_format(fmt);
622 normalized == "%Y-%m-%d %T"
623 || normalized == "%Y-%m-%d %H:%i:%S"
624 || fmt == "%Y-%m-%d %H:%i:%S"
625 || fmt == "%Y-%m-%d %T"
626}
627
628#[cfg(feature = "transpile")]
629fn is_default_presto_date_format(fmt: &str) -> bool {
630 fmt == "%Y-%m-%d" || fmt == "%F"
631}
632
633#[cfg(any(
641 feature = "transpile",
642 feature = "ast-tools",
643 feature = "generate",
644 feature = "semantic"
645))]
646pub fn transform_recursive<F>(expr: Expression, transform_fn: &F) -> Result<Expression>
647where
648 F: Fn(Expression) -> Result<Expression>,
649{
650 #[cfg(feature = "stacker")]
651 {
652 let red_zone = if cfg!(debug_assertions) {
653 4 * 1024 * 1024
654 } else {
655 1024 * 1024
656 };
657 stacker::maybe_grow(red_zone, 8 * 1024 * 1024, move || {
658 transform_recursive_inner(expr, transform_fn)
659 })
660 }
661 #[cfg(not(feature = "stacker"))]
662 {
663 transform_recursive_inner(expr, transform_fn)
664 }
665}
666
667#[cfg(any(
668 feature = "transpile",
669 feature = "ast-tools",
670 feature = "generate",
671 feature = "semantic"
672))]
673fn transform_recursive_inner<F>(expr: Expression, transform_fn: &F) -> Result<Expression>
674where
675 F: Fn(Expression) -> Result<Expression>,
676{
677 enum Task {
678 Visit(Expression),
679 Finish {
680 shell: Expression,
681 child_count: usize,
682 },
683 }
684
685 fn uses_generated_dispatch(expression: &Expression) -> bool {
689 match expression {
690 Expression::Select(select) => {
691 select.joins.is_empty()
692 && select.with.is_none()
693 && select.order_by.is_none()
694 && select.windows.is_none()
695 && select.settings.is_none()
696 }
697 Expression::Union(set_op) => set_op.with.is_none() && set_op.order_by.is_none(),
698 Expression::Intersect(set_op) => set_op.with.is_none() && set_op.order_by.is_none(),
699 Expression::Except(set_op) => set_op.with.is_none() && set_op.order_by.is_none(),
700 Expression::Literal(_)
701 | Expression::Boolean(_)
702 | Expression::Null(_)
703 | Expression::Identifier(_)
704 | Expression::Star(_)
705 | Expression::Parameter(_)
706 | Expression::Placeholder(_)
707 | Expression::SessionParameter(_)
708 | Expression::Alias(_)
709 | Expression::Paren(_)
710 | Expression::Not(_)
711 | Expression::Neg(_)
712 | Expression::IsNull(_)
713 | Expression::IsTrue(_)
714 | Expression::IsFalse(_)
715 | Expression::Subquery(_)
716 | Expression::Exists(_)
717 | Expression::Any(_)
718 | Expression::All(_)
719 | Expression::TableArgument(_)
720 | Expression::And(_)
721 | Expression::Or(_)
722 | Expression::Add(_)
723 | Expression::Sub(_)
724 | Expression::Mul(_)
725 | Expression::Div(_)
726 | Expression::Eq(_)
727 | Expression::NullSafeEq(_)
728 | Expression::NullSafeNeq(_)
729 | Expression::Lt(_)
730 | Expression::Gt(_)
731 | Expression::Neq(_)
732 | Expression::Lte(_)
733 | Expression::Gte(_)
734 | Expression::Mod(_)
735 | Expression::Concat(_)
736 | Expression::BitwiseAnd(_)
737 | Expression::BitwiseOr(_)
738 | Expression::BitwiseXor(_)
739 | Expression::Is(_)
740 | Expression::MemberOf(_)
741 | Expression::ArrayContainsAll(_)
742 | Expression::ArrayContainedBy(_)
743 | Expression::ArrayOverlaps(_)
744 | Expression::TsMatch(_)
745 | Expression::Adjacent(_)
746 | Expression::Like(_)
747 | Expression::ILike(_)
748 | Expression::Function(_)
749 | Expression::Lead(_)
750 | Expression::Lag(_)
751 | Expression::Array(_)
752 | Expression::Tuple(_)
753 | Expression::ArrayFunc(_)
754 | Expression::Coalesce(_)
755 | Expression::Greatest(_)
756 | Expression::Least(_)
757 | Expression::ArrayConcat(_)
758 | Expression::ArrayIntersect(_)
759 | Expression::ArrayZip(_)
760 | Expression::MapConcat(_)
761 | Expression::JsonArray(_)
762 | Expression::From(_) => true,
763 _ => false,
764 }
765 }
766
767 let mut tasks = vec![Task::Visit(expr)];
768 let mut results = Vec::new();
769
770 while let Some(task) = tasks.pop() {
771 match task {
772 Task::Visit(mut expression) => {
773 if !uses_generated_dispatch(&expression) {
774 results.push(transform_recursive_reference(expression, transform_fn)?);
775 continue;
776 }
777
778 let mut children = Vec::new();
779 crate::ast_children::for_each_child_mut(&mut expression, |child| {
780 children.push(std::mem::replace(child, Expression::Null(Null)));
781 });
782 let child_count = children.len();
783 tasks.push(Task::Finish {
784 shell: expression,
785 child_count,
786 });
787 for child in children.into_iter().rev() {
788 tasks.push(Task::Visit(child));
789 }
790 }
791 Task::Finish {
792 mut shell,
793 child_count,
794 } => {
795 if results.len() < child_count {
796 return Err(crate::error::Error::Internal(
797 "transform result stack underflow".to_string(),
798 ));
799 }
800 let transformed_children = results.split_off(results.len() - child_count);
801 let mut transformed_children = transformed_children.into_iter();
802 crate::ast_children::for_each_child_mut(&mut shell, |child| {
803 *child = transformed_children
804 .next()
805 .expect("validated transform child count");
806 });
807 if transformed_children.next().is_some() {
808 return Err(crate::error::Error::Internal(
809 "transform child restoration mismatch".to_string(),
810 ));
811 }
812 results.push(transform_fn(shell)?);
813 }
814 }
815 }
816
817 match results.len() {
818 1 => Ok(results.pop().expect("single transform result")),
819 _ => Err(crate::error::Error::Internal(
820 "unexpected transform result stack size".to_string(),
821 )),
822 }
823}
824
825#[cfg(any(
826 feature = "transpile",
827 feature = "ast-tools",
828 feature = "generate",
829 feature = "semantic"
830))]
831fn transform_table_ref_recursive<F>(table: TableRef, transform_fn: &F) -> Result<TableRef>
832where
833 F: Fn(Expression) -> Result<Expression>,
834{
835 match transform_recursive(Expression::Table(Box::new(table)), transform_fn)? {
836 Expression::Table(table) => Ok(*table),
837 _ => Err(crate::error::Error::parse(
838 "TableRef transformation returned non-table expression",
839 0,
840 0,
841 0,
842 0,
843 )),
844 }
845}
846
847#[cfg(any(
848 feature = "transpile",
849 feature = "ast-tools",
850 feature = "generate",
851 feature = "semantic"
852))]
853fn transform_from_recursive<F>(from: From, transform_fn: &F) -> Result<From>
854where
855 F: Fn(Expression) -> Result<Expression>,
856{
857 match transform_recursive(Expression::From(Box::new(from)), transform_fn)? {
858 Expression::From(from) => Ok(*from),
859 _ => Err(crate::error::Error::parse(
860 "FROM transformation returned non-FROM expression",
861 0,
862 0,
863 0,
864 0,
865 )),
866 }
867}
868
869#[cfg(any(
870 feature = "transpile",
871 feature = "ast-tools",
872 feature = "generate",
873 feature = "semantic"
874))]
875fn transform_join_recursive<F>(mut join: Join, transform_fn: &F) -> Result<Join>
876where
877 F: Fn(Expression) -> Result<Expression>,
878{
879 join.this = transform_recursive(join.this, transform_fn)?;
880 if let Some(on) = join.on.take() {
881 join.on = Some(transform_recursive(on, transform_fn)?);
882 }
883 if let Some(match_condition) = join.match_condition.take() {
884 join.match_condition = Some(transform_recursive(match_condition, transform_fn)?);
885 }
886 join.pivots = join
887 .pivots
888 .into_iter()
889 .map(|pivot| transform_recursive(pivot, transform_fn))
890 .collect::<Result<Vec<_>>>()?;
891
892 match transform_fn(Expression::Join(Box::new(join)))? {
893 Expression::Join(join) => Ok(*join),
894 _ => Err(crate::error::Error::parse(
895 "Join transformation returned non-join expression",
896 0,
897 0,
898 0,
899 0,
900 )),
901 }
902}
903
904#[cfg(any(
905 feature = "transpile",
906 feature = "ast-tools",
907 feature = "generate",
908 feature = "semantic"
909))]
910fn transform_output_clause_recursive<F>(
911 mut output: OutputClause,
912 transform_fn: &F,
913) -> Result<OutputClause>
914where
915 F: Fn(Expression) -> Result<Expression>,
916{
917 output.columns = output
918 .columns
919 .into_iter()
920 .map(|column| transform_recursive(column, transform_fn))
921 .collect::<Result<Vec<_>>>()?;
922 if let Some(into_table) = output.into_table.take() {
923 output.into_table = Some(transform_recursive(into_table, transform_fn)?);
924 }
925 Ok(output)
926}
927
928#[cfg(any(
929 feature = "transpile",
930 feature = "ast-tools",
931 feature = "generate",
932 feature = "semantic"
933))]
934fn transform_with_recursive<F>(mut with: With, transform_fn: &F) -> Result<With>
935where
936 F: Fn(Expression) -> Result<Expression>,
937{
938 with.ctes = with
939 .ctes
940 .into_iter()
941 .map(|mut cte| {
942 cte.this = transform_recursive(cte.this, transform_fn)?;
943 Ok(cte)
944 })
945 .collect::<Result<Vec<_>>>()?;
946 if let Some(search) = with.search.take() {
947 with.search = Some(Box::new(transform_recursive(*search, transform_fn)?));
948 }
949 Ok(with)
950}
951
952#[cfg(any(
953 feature = "transpile",
954 feature = "ast-tools",
955 feature = "generate",
956 feature = "semantic"
957))]
958fn transform_order_by_recursive<F>(mut order: OrderBy, transform_fn: &F) -> Result<OrderBy>
959where
960 F: Fn(Expression) -> Result<Expression>,
961{
962 order.expressions = order
963 .expressions
964 .into_iter()
965 .map(|mut ordered| {
966 let original = ordered.this.clone();
967 ordered.this = transform_recursive(ordered.this, transform_fn).unwrap_or(original);
968 match transform_fn(Expression::Ordered(Box::new(ordered.clone()))) {
969 Ok(Expression::Ordered(transformed)) => Ok(*transformed),
970 Ok(_) | Err(_) => Ok(ordered),
971 }
972 })
973 .collect::<Result<Vec<_>>>()?;
974 Ok(order)
975}
976
977#[cfg(any(
978 feature = "transpile",
979 feature = "ast-tools",
980 feature = "generate",
981 feature = "semantic"
982))]
983fn transform_recursive_reference<F>(expr: Expression, transform_fn: &F) -> Result<Expression>
984where
985 F: Fn(Expression) -> Result<Expression>,
986{
987 use crate::expressions::BinaryOp;
988
989 macro_rules! recurse_agg {
991 ($variant:ident, $f:expr) => {{
992 let mut f = $f;
993 f.this = transform_recursive(f.this, transform_fn)?;
994 if let Some(filter) = f.filter.take() {
995 f.filter = Some(transform_recursive(filter, transform_fn)?);
996 }
997 for ord in &mut f.order_by {
998 ord.this = transform_recursive(
999 std::mem::replace(&mut ord.this, Expression::Null(crate::expressions::Null)),
1000 transform_fn,
1001 )?;
1002 }
1003 if let Some((ref mut expr, _)) = f.having_max {
1004 *expr = Box::new(transform_recursive(
1005 std::mem::replace(expr.as_mut(), Expression::Null(crate::expressions::Null)),
1006 transform_fn,
1007 )?);
1008 }
1009 if let Some(limit) = f.limit.take() {
1010 f.limit = Some(Box::new(transform_recursive(*limit, transform_fn)?));
1011 }
1012 Expression::$variant(f)
1013 }};
1014 }
1015
1016 macro_rules! transform_binary {
1018 ($variant:ident, $op:expr) => {{
1019 let left = transform_recursive($op.left, transform_fn)?;
1020 let right = transform_recursive($op.right, transform_fn)?;
1021 Expression::$variant(Box::new(BinaryOp {
1022 left,
1023 right,
1024 left_comments: $op.left_comments,
1025 operator_comments: $op.operator_comments,
1026 trailing_comments: $op.trailing_comments,
1027 inferred_type: $op.inferred_type,
1028 }))
1029 }};
1030 }
1031
1032 if matches!(
1034 &expr,
1035 Expression::Literal(_)
1036 | Expression::Boolean(_)
1037 | Expression::Null(_)
1038 | Expression::Identifier(_)
1039 | Expression::Star(_)
1040 | Expression::Parameter(_)
1041 | Expression::Placeholder(_)
1042 | Expression::SessionParameter(_)
1043 ) {
1044 return transform_fn(expr);
1045 }
1046
1047 let expr = match expr {
1049 Expression::Select(mut select) => {
1050 select.expressions = select
1051 .expressions
1052 .into_iter()
1053 .map(|e| transform_recursive(e, transform_fn))
1054 .collect::<Result<Vec<_>>>()?;
1055
1056 if let Some(mut from) = select.from.take() {
1058 from.expressions = from
1059 .expressions
1060 .into_iter()
1061 .map(|e| transform_recursive(e, transform_fn))
1062 .collect::<Result<Vec<_>>>()?;
1063 select.from = Some(from);
1064 }
1065
1066 select.joins = select
1068 .joins
1069 .into_iter()
1070 .map(|mut join| {
1071 join.this = transform_recursive(join.this, transform_fn)?;
1072 if let Some(on) = join.on.take() {
1073 join.on = Some(transform_recursive(on, transform_fn)?);
1074 }
1075 match transform_fn(Expression::Join(Box::new(join)))? {
1077 Expression::Join(j) => Ok(*j),
1078 _ => Err(crate::error::Error::parse(
1079 "Join transformation returned non-join expression",
1080 0,
1081 0,
1082 0,
1083 0,
1084 )),
1085 }
1086 })
1087 .collect::<Result<Vec<_>>>()?;
1088
1089 select.lateral_views = select
1091 .lateral_views
1092 .into_iter()
1093 .map(|mut lv| {
1094 lv.this = transform_recursive(lv.this, transform_fn)?;
1095 Ok(lv)
1096 })
1097 .collect::<Result<Vec<_>>>()?;
1098
1099 if let Some(mut where_clause) = select.where_clause.take() {
1101 where_clause.this = transform_recursive(where_clause.this, transform_fn)?;
1102 select.where_clause = Some(where_clause);
1103 }
1104
1105 if let Some(mut group_by) = select.group_by.take() {
1107 group_by.expressions = group_by
1108 .expressions
1109 .into_iter()
1110 .map(|e| transform_recursive(e, transform_fn))
1111 .collect::<Result<Vec<_>>>()?;
1112 select.group_by = Some(group_by);
1113 }
1114
1115 if let Some(mut having) = select.having.take() {
1117 having.this = transform_recursive(having.this, transform_fn)?;
1118 select.having = Some(having);
1119 }
1120
1121 if let Some(mut with) = select.with.take() {
1123 with.ctes = with
1124 .ctes
1125 .into_iter()
1126 .map(|mut cte| {
1127 let original = cte.this.clone();
1128 cte.this = transform_recursive(cte.this, transform_fn).unwrap_or(original);
1129 cte
1130 })
1131 .collect();
1132 select.with = Some(with);
1133 }
1134
1135 if let Some(mut order) = select.order_by.take() {
1137 order.expressions = order
1138 .expressions
1139 .into_iter()
1140 .map(|o| {
1141 let mut o = o;
1142 let original = o.this.clone();
1143 o.this = transform_recursive(o.this, transform_fn).unwrap_or(original);
1144 match transform_fn(Expression::Ordered(Box::new(o.clone()))) {
1146 Ok(Expression::Ordered(transformed)) => *transformed,
1147 Ok(_) | Err(_) => o,
1148 }
1149 })
1150 .collect();
1151 select.order_by = Some(order);
1152 }
1153
1154 if let Some(ref mut windows) = select.windows {
1156 for nw in windows.iter_mut() {
1157 nw.spec.order_by = std::mem::take(&mut nw.spec.order_by)
1158 .into_iter()
1159 .map(|o| {
1160 let mut o = o;
1161 let original = o.this.clone();
1162 o.this = transform_recursive(o.this, transform_fn).unwrap_or(original);
1163 match transform_fn(Expression::Ordered(Box::new(o.clone()))) {
1164 Ok(Expression::Ordered(transformed)) => *transformed,
1165 Ok(_) | Err(_) => o,
1166 }
1167 })
1168 .collect();
1169 }
1170 }
1171
1172 if let Some(mut qual) = select.qualify.take() {
1174 qual.this = transform_recursive(qual.this, transform_fn)?;
1175 select.qualify = Some(qual);
1176 }
1177
1178 Expression::Select(select)
1179 }
1180 Expression::Function(mut f) => {
1181 f.args = f
1182 .args
1183 .into_iter()
1184 .map(|e| transform_recursive(e, transform_fn))
1185 .collect::<Result<Vec<_>>>()?;
1186 Expression::Function(f)
1187 }
1188 Expression::AggregateFunction(mut f) => {
1189 f.args = f
1190 .args
1191 .into_iter()
1192 .map(|e| transform_recursive(e, transform_fn))
1193 .collect::<Result<Vec<_>>>()?;
1194 if let Some(filter) = f.filter {
1195 f.filter = Some(transform_recursive(filter, transform_fn)?);
1196 }
1197 Expression::AggregateFunction(f)
1198 }
1199 Expression::WindowFunction(mut wf) => {
1200 wf.this = transform_recursive(wf.this, transform_fn)?;
1201 wf.over.partition_by = wf
1202 .over
1203 .partition_by
1204 .into_iter()
1205 .map(|e| transform_recursive(e, transform_fn))
1206 .collect::<Result<Vec<_>>>()?;
1207 wf.over.order_by = wf
1209 .over
1210 .order_by
1211 .into_iter()
1212 .map(|o| {
1213 let mut o = o;
1214 o.this = transform_recursive(o.this, transform_fn)?;
1215 match transform_fn(Expression::Ordered(Box::new(o)))? {
1216 Expression::Ordered(transformed) => Ok(*transformed),
1217 _ => Err(crate::error::Error::parse(
1218 "Ordered transformation returned non-Ordered expression",
1219 0,
1220 0,
1221 0,
1222 0,
1223 )),
1224 }
1225 })
1226 .collect::<Result<Vec<_>>>()?;
1227 Expression::WindowFunction(wf)
1228 }
1229 Expression::Alias(mut a) => {
1230 a.this = transform_recursive(a.this, transform_fn)?;
1231 Expression::Alias(a)
1232 }
1233 Expression::Cast(mut c) => {
1234 c.this = transform_recursive(c.this, transform_fn)?;
1235 c.to = transform_data_type_recursive(c.to, transform_fn)?;
1237 Expression::Cast(c)
1238 }
1239 Expression::And(op) => transform_binary!(And, *op),
1240 Expression::Or(op) => transform_binary!(Or, *op),
1241 Expression::Add(op) => transform_binary!(Add, *op),
1242 Expression::Sub(op) => transform_binary!(Sub, *op),
1243 Expression::Mul(op) => transform_binary!(Mul, *op),
1244 Expression::Div(op) => transform_binary!(Div, *op),
1245 Expression::Eq(op) => transform_binary!(Eq, *op),
1246 Expression::Lt(op) => transform_binary!(Lt, *op),
1247 Expression::Gt(op) => transform_binary!(Gt, *op),
1248 Expression::Paren(mut p) => {
1249 p.this = transform_recursive(p.this, transform_fn)?;
1250 Expression::Paren(p)
1251 }
1252 Expression::Coalesce(mut f) => {
1253 f.expressions = f
1254 .expressions
1255 .into_iter()
1256 .map(|e| transform_recursive(e, transform_fn))
1257 .collect::<Result<Vec<_>>>()?;
1258 Expression::Coalesce(f)
1259 }
1260 Expression::IfNull(mut f) => {
1261 f.this = transform_recursive(f.this, transform_fn)?;
1262 f.expression = transform_recursive(f.expression, transform_fn)?;
1263 Expression::IfNull(f)
1264 }
1265 Expression::Nvl(mut f) => {
1266 f.this = transform_recursive(f.this, transform_fn)?;
1267 f.expression = transform_recursive(f.expression, transform_fn)?;
1268 Expression::Nvl(f)
1269 }
1270 Expression::In(mut i) => {
1271 i.this = transform_recursive(i.this, transform_fn)?;
1272 i.expressions = i
1273 .expressions
1274 .into_iter()
1275 .map(|e| transform_recursive(e, transform_fn))
1276 .collect::<Result<Vec<_>>>()?;
1277 if let Some(query) = i.query {
1278 i.query = Some(transform_recursive(query, transform_fn)?);
1279 }
1280 Expression::In(i)
1281 }
1282 Expression::Not(mut n) => {
1283 n.this = transform_recursive(n.this, transform_fn)?;
1284 Expression::Not(n)
1285 }
1286 Expression::ArraySlice(mut s) => {
1287 s.this = transform_recursive(s.this, transform_fn)?;
1288 if let Some(start) = s.start {
1289 s.start = Some(transform_recursive(start, transform_fn)?);
1290 }
1291 if let Some(end) = s.end {
1292 s.end = Some(transform_recursive(end, transform_fn)?);
1293 }
1294 Expression::ArraySlice(s)
1295 }
1296 Expression::Subscript(mut s) => {
1297 s.this = transform_recursive(s.this, transform_fn)?;
1298 s.index = transform_recursive(s.index, transform_fn)?;
1299 Expression::Subscript(s)
1300 }
1301 Expression::Array(mut a) => {
1302 a.expressions = a
1303 .expressions
1304 .into_iter()
1305 .map(|e| transform_recursive(e, transform_fn))
1306 .collect::<Result<Vec<_>>>()?;
1307 Expression::Array(a)
1308 }
1309 Expression::Struct(mut s) => {
1310 let mut new_fields = Vec::new();
1311 for (name, expr) in s.fields {
1312 let transformed = transform_recursive(expr, transform_fn)?;
1313 new_fields.push((name, transformed));
1314 }
1315 s.fields = new_fields;
1316 Expression::Struct(s)
1317 }
1318 Expression::NamedArgument(mut na) => {
1319 na.value = transform_recursive(na.value, transform_fn)?;
1320 Expression::NamedArgument(na)
1321 }
1322 Expression::MapFunc(mut m) => {
1323 m.keys = m
1324 .keys
1325 .into_iter()
1326 .map(|e| transform_recursive(e, transform_fn))
1327 .collect::<Result<Vec<_>>>()?;
1328 m.values = m
1329 .values
1330 .into_iter()
1331 .map(|e| transform_recursive(e, transform_fn))
1332 .collect::<Result<Vec<_>>>()?;
1333 Expression::MapFunc(m)
1334 }
1335 Expression::ArrayFunc(mut a) => {
1336 a.expressions = a
1337 .expressions
1338 .into_iter()
1339 .map(|e| transform_recursive(e, transform_fn))
1340 .collect::<Result<Vec<_>>>()?;
1341 Expression::ArrayFunc(a)
1342 }
1343 Expression::Lambda(mut l) => {
1344 l.body = transform_recursive(l.body, transform_fn)?;
1345 Expression::Lambda(l)
1346 }
1347 Expression::JsonExtract(mut f) => {
1348 f.this = transform_recursive(f.this, transform_fn)?;
1349 f.path = transform_recursive(f.path, transform_fn)?;
1350 Expression::JsonExtract(f)
1351 }
1352 Expression::JsonExtractScalar(mut f) => {
1353 f.this = transform_recursive(f.this, transform_fn)?;
1354 f.path = transform_recursive(f.path, transform_fn)?;
1355 Expression::JsonExtractScalar(f)
1356 }
1357
1358 Expression::Length(mut f) => {
1361 f.this = transform_recursive(f.this, transform_fn)?;
1362 Expression::Length(f)
1363 }
1364 Expression::Upper(mut f) => {
1365 f.this = transform_recursive(f.this, transform_fn)?;
1366 Expression::Upper(f)
1367 }
1368 Expression::Lower(mut f) => {
1369 f.this = transform_recursive(f.this, transform_fn)?;
1370 Expression::Lower(f)
1371 }
1372 Expression::LTrim(mut f) => {
1373 f.this = transform_recursive(f.this, transform_fn)?;
1374 Expression::LTrim(f)
1375 }
1376 Expression::RTrim(mut f) => {
1377 f.this = transform_recursive(f.this, transform_fn)?;
1378 Expression::RTrim(f)
1379 }
1380 Expression::Reverse(mut f) => {
1381 f.this = transform_recursive(f.this, transform_fn)?;
1382 Expression::Reverse(f)
1383 }
1384 Expression::Abs(mut f) => {
1385 f.this = transform_recursive(f.this, transform_fn)?;
1386 Expression::Abs(f)
1387 }
1388 Expression::Ceil(mut f) => {
1389 f.this = transform_recursive(f.this, transform_fn)?;
1390 Expression::Ceil(f)
1391 }
1392 Expression::Floor(mut f) => {
1393 f.this = transform_recursive(f.this, transform_fn)?;
1394 Expression::Floor(f)
1395 }
1396 Expression::Sign(mut f) => {
1397 f.this = transform_recursive(f.this, transform_fn)?;
1398 Expression::Sign(f)
1399 }
1400 Expression::Sqrt(mut f) => {
1401 f.this = transform_recursive(f.this, transform_fn)?;
1402 Expression::Sqrt(f)
1403 }
1404 Expression::Cbrt(mut f) => {
1405 f.this = transform_recursive(f.this, transform_fn)?;
1406 Expression::Cbrt(f)
1407 }
1408 Expression::Ln(mut f) => {
1409 f.this = transform_recursive(f.this, transform_fn)?;
1410 Expression::Ln(f)
1411 }
1412 Expression::Log(mut f) => {
1413 f.this = transform_recursive(f.this, transform_fn)?;
1414 if let Some(base) = f.base {
1415 f.base = Some(transform_recursive(base, transform_fn)?);
1416 }
1417 Expression::Log(f)
1418 }
1419 Expression::Exp(mut f) => {
1420 f.this = transform_recursive(f.this, transform_fn)?;
1421 Expression::Exp(f)
1422 }
1423 Expression::Date(mut f) => {
1424 f.this = transform_recursive(f.this, transform_fn)?;
1425 Expression::Date(f)
1426 }
1427 Expression::Stddev(f) => recurse_agg!(Stddev, f),
1428 Expression::StddevSamp(f) => recurse_agg!(StddevSamp, f),
1429 Expression::Variance(f) => recurse_agg!(Variance, f),
1430
1431 Expression::ModFunc(mut f) => {
1433 f.this = transform_recursive(f.this, transform_fn)?;
1434 f.expression = transform_recursive(f.expression, transform_fn)?;
1435 Expression::ModFunc(f)
1436 }
1437 Expression::Power(mut f) => {
1438 f.this = transform_recursive(f.this, transform_fn)?;
1439 f.expression = transform_recursive(f.expression, transform_fn)?;
1440 Expression::Power(f)
1441 }
1442 Expression::MapFromArrays(mut f) => {
1443 f.this = transform_recursive(f.this, transform_fn)?;
1444 f.expression = transform_recursive(f.expression, transform_fn)?;
1445 Expression::MapFromArrays(f)
1446 }
1447 Expression::ElementAt(mut f) => {
1448 f.this = transform_recursive(f.this, transform_fn)?;
1449 f.expression = transform_recursive(f.expression, transform_fn)?;
1450 Expression::ElementAt(f)
1451 }
1452 Expression::MapContainsKey(mut f) => {
1453 f.this = transform_recursive(f.this, transform_fn)?;
1454 f.expression = transform_recursive(f.expression, transform_fn)?;
1455 Expression::MapContainsKey(f)
1456 }
1457 Expression::Left(mut f) => {
1458 f.this = transform_recursive(f.this, transform_fn)?;
1459 f.length = transform_recursive(f.length, transform_fn)?;
1460 Expression::Left(f)
1461 }
1462 Expression::Right(mut f) => {
1463 f.this = transform_recursive(f.this, transform_fn)?;
1464 f.length = transform_recursive(f.length, transform_fn)?;
1465 Expression::Right(f)
1466 }
1467 Expression::Repeat(mut f) => {
1468 f.this = transform_recursive(f.this, transform_fn)?;
1469 f.times = transform_recursive(f.times, transform_fn)?;
1470 Expression::Repeat(f)
1471 }
1472
1473 Expression::Substring(mut f) => {
1475 f.this = transform_recursive(f.this, transform_fn)?;
1476 f.start = transform_recursive(f.start, transform_fn)?;
1477 if let Some(len) = f.length {
1478 f.length = Some(transform_recursive(len, transform_fn)?);
1479 }
1480 Expression::Substring(f)
1481 }
1482 Expression::Replace(mut f) => {
1483 f.this = transform_recursive(f.this, transform_fn)?;
1484 f.old = transform_recursive(f.old, transform_fn)?;
1485 f.new = transform_recursive(f.new, transform_fn)?;
1486 Expression::Replace(f)
1487 }
1488 Expression::ConcatWs(mut f) => {
1489 f.separator = transform_recursive(f.separator, transform_fn)?;
1490 f.expressions = f
1491 .expressions
1492 .into_iter()
1493 .map(|e| transform_recursive(e, transform_fn))
1494 .collect::<Result<Vec<_>>>()?;
1495 Expression::ConcatWs(f)
1496 }
1497 Expression::Trim(mut f) => {
1498 f.this = transform_recursive(f.this, transform_fn)?;
1499 if let Some(chars) = f.characters {
1500 f.characters = Some(transform_recursive(chars, transform_fn)?);
1501 }
1502 Expression::Trim(f)
1503 }
1504 Expression::Split(mut f) => {
1505 f.this = transform_recursive(f.this, transform_fn)?;
1506 f.delimiter = transform_recursive(f.delimiter, transform_fn)?;
1507 Expression::Split(f)
1508 }
1509 Expression::Lpad(mut f) => {
1510 f.this = transform_recursive(f.this, transform_fn)?;
1511 f.length = transform_recursive(f.length, transform_fn)?;
1512 if let Some(fill) = f.fill {
1513 f.fill = Some(transform_recursive(fill, transform_fn)?);
1514 }
1515 Expression::Lpad(f)
1516 }
1517 Expression::Rpad(mut f) => {
1518 f.this = transform_recursive(f.this, transform_fn)?;
1519 f.length = transform_recursive(f.length, transform_fn)?;
1520 if let Some(fill) = f.fill {
1521 f.fill = Some(transform_recursive(fill, transform_fn)?);
1522 }
1523 Expression::Rpad(f)
1524 }
1525
1526 Expression::Case(mut c) => {
1528 if let Some(operand) = c.operand {
1529 c.operand = Some(transform_recursive(operand, transform_fn)?);
1530 }
1531 c.whens = c
1532 .whens
1533 .into_iter()
1534 .map(|(cond, then)| {
1535 let new_cond = transform_recursive(cond.clone(), transform_fn).unwrap_or(cond);
1536 let new_then = transform_recursive(then.clone(), transform_fn).unwrap_or(then);
1537 (new_cond, new_then)
1538 })
1539 .collect();
1540 if let Some(else_expr) = c.else_ {
1541 c.else_ = Some(transform_recursive(else_expr, transform_fn)?);
1542 }
1543 Expression::Case(c)
1544 }
1545 Expression::IfFunc(mut f) => {
1546 f.condition = transform_recursive(f.condition, transform_fn)?;
1547 f.true_value = transform_recursive(f.true_value, transform_fn)?;
1548 if let Some(false_val) = f.false_value {
1549 f.false_value = Some(transform_recursive(false_val, transform_fn)?);
1550 }
1551 Expression::IfFunc(f)
1552 }
1553
1554 Expression::DateAdd(mut f) => {
1556 f.this = transform_recursive(f.this, transform_fn)?;
1557 f.interval = transform_recursive(f.interval, transform_fn)?;
1558 Expression::DateAdd(f)
1559 }
1560 Expression::DateSub(mut f) => {
1561 f.this = transform_recursive(f.this, transform_fn)?;
1562 f.interval = transform_recursive(f.interval, transform_fn)?;
1563 Expression::DateSub(f)
1564 }
1565 Expression::DateDiff(mut f) => {
1566 f.this = transform_recursive(f.this, transform_fn)?;
1567 f.expression = transform_recursive(f.expression, transform_fn)?;
1568 Expression::DateDiff(f)
1569 }
1570 Expression::DateTrunc(mut f) => {
1571 f.this = transform_recursive(f.this, transform_fn)?;
1572 Expression::DateTrunc(f)
1573 }
1574 Expression::Extract(mut f) => {
1575 f.this = transform_recursive(f.this, transform_fn)?;
1576 Expression::Extract(f)
1577 }
1578
1579 Expression::JsonObject(mut f) => {
1581 f.pairs = f
1582 .pairs
1583 .into_iter()
1584 .map(|(k, v)| {
1585 let new_k = transform_recursive(k, transform_fn)?;
1586 let new_v = transform_recursive(v, transform_fn)?;
1587 Ok((new_k, new_v))
1588 })
1589 .collect::<Result<Vec<_>>>()?;
1590 Expression::JsonObject(f)
1591 }
1592
1593 Expression::Subquery(mut s) => {
1595 s.this = transform_recursive(s.this, transform_fn)?;
1596 Expression::Subquery(s)
1597 }
1598 Expression::Exists(mut e) => {
1599 e.this = transform_recursive(e.this, transform_fn)?;
1600 Expression::Exists(e)
1601 }
1602 Expression::Describe(mut d) => {
1603 d.target = transform_recursive(d.target, transform_fn)?;
1604 Expression::Describe(d)
1605 }
1606
1607 Expression::Union(mut u) => {
1609 let left = std::mem::replace(&mut u.left, Expression::Null(Null));
1610 u.left = transform_recursive(left, transform_fn)?;
1611 let right = std::mem::replace(&mut u.right, Expression::Null(Null));
1612 u.right = transform_recursive(right, transform_fn)?;
1613 if let Some(mut order) = u.order_by.take() {
1614 order.expressions = order
1615 .expressions
1616 .into_iter()
1617 .map(|o| {
1618 let mut o = o;
1619 let original = o.this.clone();
1620 o.this = transform_recursive(o.this, transform_fn).unwrap_or(original);
1621 match transform_fn(Expression::Ordered(Box::new(o.clone()))) {
1622 Ok(Expression::Ordered(transformed)) => *transformed,
1623 Ok(_) | Err(_) => o,
1624 }
1625 })
1626 .collect();
1627 u.order_by = Some(order);
1628 }
1629 if let Some(mut with) = u.with.take() {
1630 with.ctes = with
1631 .ctes
1632 .into_iter()
1633 .map(|mut cte| {
1634 let original = cte.this.clone();
1635 cte.this = transform_recursive(cte.this, transform_fn).unwrap_or(original);
1636 cte
1637 })
1638 .collect();
1639 u.with = Some(with);
1640 }
1641 Expression::Union(u)
1642 }
1643 Expression::Intersect(mut i) => {
1644 let left = std::mem::replace(&mut i.left, Expression::Null(Null));
1645 i.left = transform_recursive(left, transform_fn)?;
1646 let right = std::mem::replace(&mut i.right, Expression::Null(Null));
1647 i.right = transform_recursive(right, transform_fn)?;
1648 if let Some(mut order) = i.order_by.take() {
1649 order.expressions = order
1650 .expressions
1651 .into_iter()
1652 .map(|o| {
1653 let mut o = o;
1654 let original = o.this.clone();
1655 o.this = transform_recursive(o.this, transform_fn).unwrap_or(original);
1656 match transform_fn(Expression::Ordered(Box::new(o.clone()))) {
1657 Ok(Expression::Ordered(transformed)) => *transformed,
1658 Ok(_) | Err(_) => o,
1659 }
1660 })
1661 .collect();
1662 i.order_by = Some(order);
1663 }
1664 if let Some(mut with) = i.with.take() {
1665 with.ctes = with
1666 .ctes
1667 .into_iter()
1668 .map(|mut cte| {
1669 let original = cte.this.clone();
1670 cte.this = transform_recursive(cte.this, transform_fn).unwrap_or(original);
1671 cte
1672 })
1673 .collect();
1674 i.with = Some(with);
1675 }
1676 Expression::Intersect(i)
1677 }
1678 Expression::Except(mut e) => {
1679 let left = std::mem::replace(&mut e.left, Expression::Null(Null));
1680 e.left = transform_recursive(left, transform_fn)?;
1681 let right = std::mem::replace(&mut e.right, Expression::Null(Null));
1682 e.right = transform_recursive(right, transform_fn)?;
1683 if let Some(mut order) = e.order_by.take() {
1684 order.expressions = order
1685 .expressions
1686 .into_iter()
1687 .map(|o| {
1688 let mut o = o;
1689 let original = o.this.clone();
1690 o.this = transform_recursive(o.this, transform_fn).unwrap_or(original);
1691 match transform_fn(Expression::Ordered(Box::new(o.clone()))) {
1692 Ok(Expression::Ordered(transformed)) => *transformed,
1693 Ok(_) | Err(_) => o,
1694 }
1695 })
1696 .collect();
1697 e.order_by = Some(order);
1698 }
1699 if let Some(mut with) = e.with.take() {
1700 with.ctes = with
1701 .ctes
1702 .into_iter()
1703 .map(|mut cte| {
1704 let original = cte.this.clone();
1705 cte.this = transform_recursive(cte.this, transform_fn).unwrap_or(original);
1706 cte
1707 })
1708 .collect();
1709 e.with = Some(with);
1710 }
1711 Expression::Except(e)
1712 }
1713
1714 Expression::Insert(mut ins) => {
1716 let mut new_values = Vec::new();
1718 for row in ins.values {
1719 let mut new_row = Vec::new();
1720 for e in row {
1721 new_row.push(transform_recursive(e, transform_fn)?);
1722 }
1723 new_values.push(new_row);
1724 }
1725 ins.values = new_values;
1726
1727 if let Some(query) = ins.query {
1729 ins.query = Some(transform_recursive(query, transform_fn)?);
1730 }
1731
1732 let mut new_returning = Vec::new();
1734 for e in ins.returning {
1735 new_returning.push(transform_recursive(e, transform_fn)?);
1736 }
1737 ins.returning = new_returning;
1738
1739 if let Some(on_conflict) = ins.on_conflict {
1741 ins.on_conflict = Some(Box::new(transform_recursive(*on_conflict, transform_fn)?));
1742 }
1743
1744 Expression::Insert(ins)
1745 }
1746 Expression::Update(mut upd) => {
1747 upd.table = transform_table_ref_recursive(upd.table, transform_fn)?;
1748 upd.extra_tables = upd
1749 .extra_tables
1750 .into_iter()
1751 .map(|table| transform_table_ref_recursive(table, transform_fn))
1752 .collect::<Result<Vec<_>>>()?;
1753 upd.table_joins = upd
1754 .table_joins
1755 .into_iter()
1756 .map(|join| transform_join_recursive(join, transform_fn))
1757 .collect::<Result<Vec<_>>>()?;
1758 upd.set = upd
1759 .set
1760 .into_iter()
1761 .map(|(id, val)| {
1762 let new_val = transform_recursive(val.clone(), transform_fn).unwrap_or(val);
1763 (id, new_val)
1764 })
1765 .collect();
1766 if let Some(from_clause) = upd.from_clause.take() {
1767 upd.from_clause = Some(transform_from_recursive(from_clause, transform_fn)?);
1768 }
1769 upd.from_joins = upd
1770 .from_joins
1771 .into_iter()
1772 .map(|join| transform_join_recursive(join, transform_fn))
1773 .collect::<Result<Vec<_>>>()?;
1774 if let Some(mut where_clause) = upd.where_clause.take() {
1775 where_clause.this = transform_recursive(where_clause.this, transform_fn)?;
1776 upd.where_clause = Some(where_clause);
1777 }
1778 upd.returning = upd
1779 .returning
1780 .into_iter()
1781 .map(|expr| transform_recursive(expr, transform_fn))
1782 .collect::<Result<Vec<_>>>()?;
1783 if let Some(output) = upd.output.take() {
1784 upd.output = Some(transform_output_clause_recursive(output, transform_fn)?);
1785 }
1786 if let Some(with) = upd.with.take() {
1787 upd.with = Some(transform_with_recursive(with, transform_fn)?);
1788 }
1789 if let Some(limit) = upd.limit.take() {
1790 upd.limit = Some(transform_recursive(limit, transform_fn)?);
1791 }
1792 if let Some(order_by) = upd.order_by.take() {
1793 upd.order_by = Some(transform_order_by_recursive(order_by, transform_fn)?);
1794 }
1795 Expression::Update(upd)
1796 }
1797 Expression::Delete(mut del) => {
1798 del.table = transform_table_ref_recursive(del.table, transform_fn)?;
1799 del.using = del
1800 .using
1801 .into_iter()
1802 .map(|table| transform_table_ref_recursive(table, transform_fn))
1803 .collect::<Result<Vec<_>>>()?;
1804 if let Some(mut where_clause) = del.where_clause.take() {
1805 where_clause.this = transform_recursive(where_clause.this, transform_fn)?;
1806 del.where_clause = Some(where_clause);
1807 }
1808 if let Some(output) = del.output.take() {
1809 del.output = Some(transform_output_clause_recursive(output, transform_fn)?);
1810 }
1811 if let Some(with) = del.with.take() {
1812 del.with = Some(transform_with_recursive(with, transform_fn)?);
1813 }
1814 if let Some(limit) = del.limit.take() {
1815 del.limit = Some(transform_recursive(limit, transform_fn)?);
1816 }
1817 if let Some(order_by) = del.order_by.take() {
1818 del.order_by = Some(transform_order_by_recursive(order_by, transform_fn)?);
1819 }
1820 del.returning = del
1821 .returning
1822 .into_iter()
1823 .map(|expr| transform_recursive(expr, transform_fn))
1824 .collect::<Result<Vec<_>>>()?;
1825 del.tables = del
1826 .tables
1827 .into_iter()
1828 .map(|table| transform_table_ref_recursive(table, transform_fn))
1829 .collect::<Result<Vec<_>>>()?;
1830 del.joins = del
1831 .joins
1832 .into_iter()
1833 .map(|join| transform_join_recursive(join, transform_fn))
1834 .collect::<Result<Vec<_>>>()?;
1835 Expression::Delete(del)
1836 }
1837
1838 Expression::With(mut w) => {
1840 w.ctes = w
1841 .ctes
1842 .into_iter()
1843 .map(|mut cte| {
1844 let original = cte.this.clone();
1845 cte.this = transform_recursive(cte.this, transform_fn).unwrap_or(original);
1846 cte
1847 })
1848 .collect();
1849 Expression::With(w)
1850 }
1851 Expression::Cte(mut c) => {
1852 c.this = transform_recursive(c.this, transform_fn)?;
1853 Expression::Cte(c)
1854 }
1855
1856 Expression::Ordered(mut o) => {
1858 o.this = transform_recursive(o.this, transform_fn)?;
1859 Expression::Ordered(o)
1860 }
1861
1862 Expression::Neg(mut n) => {
1864 n.this = transform_recursive(n.this, transform_fn)?;
1865 Expression::Neg(n)
1866 }
1867
1868 Expression::Between(mut b) => {
1870 b.this = transform_recursive(b.this, transform_fn)?;
1871 b.low = transform_recursive(b.low, transform_fn)?;
1872 b.high = transform_recursive(b.high, transform_fn)?;
1873 Expression::Between(b)
1874 }
1875 Expression::IsNull(mut i) => {
1876 i.this = transform_recursive(i.this, transform_fn)?;
1877 Expression::IsNull(i)
1878 }
1879 Expression::IsTrue(mut i) => {
1880 i.this = transform_recursive(i.this, transform_fn)?;
1881 Expression::IsTrue(i)
1882 }
1883 Expression::IsFalse(mut i) => {
1884 i.this = transform_recursive(i.this, transform_fn)?;
1885 Expression::IsFalse(i)
1886 }
1887
1888 Expression::Like(mut l) => {
1890 l.left = transform_recursive(l.left, transform_fn)?;
1891 l.right = transform_recursive(l.right, transform_fn)?;
1892 Expression::Like(l)
1893 }
1894 Expression::ILike(mut l) => {
1895 l.left = transform_recursive(l.left, transform_fn)?;
1896 l.right = transform_recursive(l.right, transform_fn)?;
1897 Expression::ILike(l)
1898 }
1899
1900 Expression::Neq(op) => transform_binary!(Neq, *op),
1902 Expression::Lte(op) => transform_binary!(Lte, *op),
1903 Expression::Gte(op) => transform_binary!(Gte, *op),
1904 Expression::Mod(op) => transform_binary!(Mod, *op),
1905 Expression::Concat(op) => transform_binary!(Concat, *op),
1906 Expression::BitwiseAnd(op) => transform_binary!(BitwiseAnd, *op),
1907 Expression::BitwiseOr(op) => transform_binary!(BitwiseOr, *op),
1908 Expression::BitwiseXor(op) => transform_binary!(BitwiseXor, *op),
1909 Expression::Is(op) => transform_binary!(Is, *op),
1910
1911 Expression::TryCast(mut c) => {
1913 c.this = transform_recursive(c.this, transform_fn)?;
1914 c.to = transform_data_type_recursive(c.to, transform_fn)?;
1915 Expression::TryCast(c)
1916 }
1917 Expression::SafeCast(mut c) => {
1918 c.this = transform_recursive(c.this, transform_fn)?;
1919 c.to = transform_data_type_recursive(c.to, transform_fn)?;
1920 Expression::SafeCast(c)
1921 }
1922
1923 Expression::Unnest(mut f) => {
1925 f.this = transform_recursive(f.this, transform_fn)?;
1926 f.expressions = f
1927 .expressions
1928 .into_iter()
1929 .map(|e| transform_recursive(e, transform_fn))
1930 .collect::<Result<Vec<_>>>()?;
1931 Expression::Unnest(f)
1932 }
1933 Expression::Explode(mut f) => {
1934 f.this = transform_recursive(f.this, transform_fn)?;
1935 Expression::Explode(f)
1936 }
1937 Expression::GroupConcat(mut f) => {
1938 f.this = transform_recursive(f.this, transform_fn)?;
1939 Expression::GroupConcat(f)
1940 }
1941 Expression::StringAgg(mut f) => {
1942 f.this = transform_recursive(f.this, transform_fn)?;
1943 if let Some(order_by) = f.order_by.take() {
1944 f.order_by = Some(
1945 order_by
1946 .into_iter()
1947 .map(|mut ordered| {
1948 let original = ordered.this.clone();
1949 ordered.this =
1950 transform_recursive(ordered.this, transform_fn).unwrap_or(original);
1951 match transform_fn(Expression::Ordered(Box::new(ordered.clone()))) {
1952 Ok(Expression::Ordered(transformed)) => Ok(*transformed),
1953 Ok(_) | Err(_) => Ok(ordered),
1954 }
1955 })
1956 .collect::<Result<Vec<_>>>()?,
1957 );
1958 }
1959 Expression::StringAgg(f)
1960 }
1961 Expression::ListAgg(mut f) => {
1962 f.this = transform_recursive(f.this, transform_fn)?;
1963 Expression::ListAgg(f)
1964 }
1965 Expression::ArrayAgg(mut f) => {
1966 f.this = transform_recursive(f.this, transform_fn)?;
1967 Expression::ArrayAgg(f)
1968 }
1969 Expression::ParseJson(mut f) => {
1970 f.this = transform_recursive(f.this, transform_fn)?;
1971 Expression::ParseJson(f)
1972 }
1973 Expression::ToJson(mut f) => {
1974 f.this = transform_recursive(f.this, transform_fn)?;
1975 Expression::ToJson(f)
1976 }
1977 Expression::JSONExtract(mut e) => {
1978 e.this = Box::new(transform_recursive(*e.this, transform_fn)?);
1979 e.expression = Box::new(transform_recursive(*e.expression, transform_fn)?);
1980 Expression::JSONExtract(e)
1981 }
1982 Expression::JSONExtractScalar(mut e) => {
1983 e.this = Box::new(transform_recursive(*e.this, transform_fn)?);
1984 e.expression = Box::new(transform_recursive(*e.expression, transform_fn)?);
1985 Expression::JSONExtractScalar(e)
1986 }
1987
1988 Expression::StrToTime(mut e) => {
1990 e.this = Box::new(transform_recursive(*e.this, transform_fn)?);
1991 Expression::StrToTime(e)
1992 }
1993
1994 Expression::UnixToTime(mut e) => {
1996 e.this = Box::new(transform_recursive(*e.this, transform_fn)?);
1997 Expression::UnixToTime(e)
1998 }
1999
2000 Expression::CreateTable(mut ct) => {
2002 for col in &mut ct.columns {
2003 if let Some(default_expr) = col.default.take() {
2004 col.default = Some(transform_recursive(default_expr, transform_fn)?);
2005 }
2006 if let Some(on_update_expr) = col.on_update.take() {
2007 col.on_update = Some(transform_recursive(on_update_expr, transform_fn)?);
2008 }
2009 }
2014 if let Some(as_select) = ct.as_select.take() {
2015 ct.as_select = Some(transform_recursive(as_select, transform_fn)?);
2016 }
2017 Expression::CreateTable(ct)
2018 }
2019
2020 Expression::CreateView(mut cv) => {
2022 cv.query = transform_recursive(cv.query, transform_fn)?;
2023 Expression::CreateView(cv)
2024 }
2025
2026 Expression::CreateTask(mut ct) => {
2028 ct.body = transform_recursive(ct.body, transform_fn)?;
2029 Expression::CreateTask(ct)
2030 }
2031
2032 Expression::Prepare(mut prepare) => {
2034 prepare.statement = transform_recursive(prepare.statement, transform_fn)?;
2035 Expression::Prepare(prepare)
2036 }
2037
2038 Expression::Execute(mut execute) => {
2040 execute.this = transform_recursive(execute.this, transform_fn)?;
2041 execute.arguments = execute
2042 .arguments
2043 .into_iter()
2044 .map(|argument| transform_recursive(argument, transform_fn))
2045 .collect::<Result<Vec<_>>>()?;
2046 execute.parameters = execute
2047 .parameters
2048 .into_iter()
2049 .map(|mut parameter| {
2050 parameter.value = transform_recursive(parameter.value, transform_fn)?;
2051 Ok(parameter)
2052 })
2053 .collect::<Result<Vec<_>>>()?;
2054 Expression::Execute(execute)
2055 }
2056
2057 Expression::CreateProcedure(mut cp) => {
2059 if let Some(body) = cp.body.take() {
2060 cp.body = Some(match body {
2061 FunctionBody::Expression(expr) => {
2062 FunctionBody::Expression(transform_recursive(expr, transform_fn)?)
2063 }
2064 FunctionBody::Return(expr) => {
2065 FunctionBody::Return(transform_recursive(expr, transform_fn)?)
2066 }
2067 FunctionBody::Statements(stmts) => {
2068 let transformed_stmts = stmts
2069 .into_iter()
2070 .map(|s| transform_recursive(s, transform_fn))
2071 .collect::<Result<Vec<_>>>()?;
2072 FunctionBody::Statements(transformed_stmts)
2073 }
2074 other => other,
2075 });
2076 }
2077 Expression::CreateProcedure(cp)
2078 }
2079
2080 Expression::CreateFunction(mut cf) => {
2082 if let Some(body) = cf.body.take() {
2083 cf.body = Some(match body {
2084 FunctionBody::Expression(expr) => {
2085 FunctionBody::Expression(transform_recursive(expr, transform_fn)?)
2086 }
2087 FunctionBody::Return(expr) => {
2088 FunctionBody::Return(transform_recursive(expr, transform_fn)?)
2089 }
2090 FunctionBody::Statements(stmts) => {
2091 let transformed_stmts = stmts
2092 .into_iter()
2093 .map(|s| transform_recursive(s, transform_fn))
2094 .collect::<Result<Vec<_>>>()?;
2095 FunctionBody::Statements(transformed_stmts)
2096 }
2097 other => other,
2098 });
2099 }
2100 Expression::CreateFunction(cf)
2101 }
2102
2103 Expression::MemberOf(op) => transform_binary!(MemberOf, *op),
2105 Expression::ArrayContainsAll(op) => transform_binary!(ArrayContainsAll, *op),
2107 Expression::ArrayContainedBy(op) => transform_binary!(ArrayContainedBy, *op),
2109 Expression::ArrayOverlaps(op) => transform_binary!(ArrayOverlaps, *op),
2111 Expression::TsMatch(op) => transform_binary!(TsMatch, *op),
2113 Expression::Adjacent(op) => transform_binary!(Adjacent, *op),
2115
2116 Expression::Table(mut t) => {
2118 if let Some(when) = t.when.take() {
2119 let transformed =
2120 transform_recursive(Expression::HistoricalData(when), transform_fn)?;
2121 if let Expression::HistoricalData(hd) = transformed {
2122 t.when = Some(hd);
2123 }
2124 }
2125 if let Some(changes) = t.changes.take() {
2126 let transformed = transform_recursive(Expression::Changes(changes), transform_fn)?;
2127 if let Expression::Changes(c) = transformed {
2128 t.changes = Some(c);
2129 }
2130 }
2131 Expression::Table(t)
2132 }
2133
2134 Expression::HistoricalData(mut hd) => {
2136 *hd.expression = transform_recursive(*hd.expression, transform_fn)?;
2137 Expression::HistoricalData(hd)
2138 }
2139
2140 Expression::Changes(mut c) => {
2142 if let Some(at_before) = c.at_before.take() {
2143 c.at_before = Some(Box::new(transform_recursive(*at_before, transform_fn)?));
2144 }
2145 if let Some(end) = c.end.take() {
2146 c.end = Some(Box::new(transform_recursive(*end, transform_fn)?));
2147 }
2148 Expression::Changes(c)
2149 }
2150
2151 Expression::TableArgument(mut ta) => {
2153 ta.this = transform_recursive(ta.this, transform_fn)?;
2154 Expression::TableArgument(ta)
2155 }
2156
2157 Expression::JoinedTable(mut jt) => {
2159 jt.left = transform_recursive(jt.left, transform_fn)?;
2160 jt.joins = jt
2161 .joins
2162 .into_iter()
2163 .map(|mut join| {
2164 join.this = transform_recursive(join.this, transform_fn)?;
2165 if let Some(on) = join.on.take() {
2166 join.on = Some(transform_recursive(on, transform_fn)?);
2167 }
2168 match transform_fn(Expression::Join(Box::new(join)))? {
2169 Expression::Join(j) => Ok(*j),
2170 _ => Err(crate::error::Error::parse(
2171 "Join transformation returned non-join expression",
2172 0,
2173 0,
2174 0,
2175 0,
2176 )),
2177 }
2178 })
2179 .collect::<Result<Vec<_>>>()?;
2180 jt.lateral_views = jt
2181 .lateral_views
2182 .into_iter()
2183 .map(|mut lv| {
2184 lv.this = transform_recursive(lv.this, transform_fn)?;
2185 Ok(lv)
2186 })
2187 .collect::<Result<Vec<_>>>()?;
2188 Expression::JoinedTable(jt)
2189 }
2190
2191 Expression::Lateral(mut lat) => {
2193 *lat.this = transform_recursive(*lat.this, transform_fn)?;
2194 Expression::Lateral(lat)
2195 }
2196
2197 Expression::WithinGroup(mut wg) => {
2201 wg.order_by = wg
2202 .order_by
2203 .into_iter()
2204 .map(|mut o| {
2205 let original = o.this.clone();
2206 o.this = transform_recursive(o.this, transform_fn).unwrap_or(original);
2207 match transform_fn(Expression::Ordered(Box::new(o.clone()))) {
2208 Ok(Expression::Ordered(transformed)) => *transformed,
2209 Ok(_) | Err(_) => o,
2210 }
2211 })
2212 .collect();
2213 Expression::WithinGroup(wg)
2214 }
2215
2216 Expression::Filter(mut f) => {
2218 f.this = Box::new(transform_recursive(*f.this, transform_fn)?);
2219 f.expression = Box::new(transform_recursive(*f.expression, transform_fn)?);
2220 Expression::Filter(f)
2221 }
2222
2223 Expression::Sum(f) => recurse_agg!(Sum, f),
2227 Expression::Avg(f) => recurse_agg!(Avg, f),
2228 Expression::Min(f) => recurse_agg!(Min, f),
2229 Expression::Max(f) => recurse_agg!(Max, f),
2230 Expression::CountIf(f) => recurse_agg!(CountIf, f),
2231 Expression::StddevPop(f) => recurse_agg!(StddevPop, f),
2232 Expression::VarPop(f) => recurse_agg!(VarPop, f),
2233 Expression::VarSamp(f) => recurse_agg!(VarSamp, f),
2234 Expression::Median(f) => recurse_agg!(Median, f),
2235 Expression::Mode(f) => recurse_agg!(Mode, f),
2236 Expression::First(f) => recurse_agg!(First, f),
2237 Expression::Last(f) => recurse_agg!(Last, f),
2238 Expression::AnyValue(f) => recurse_agg!(AnyValue, f),
2239 Expression::ApproxDistinct(f) => recurse_agg!(ApproxDistinct, f),
2240 Expression::ApproxCountDistinct(f) => recurse_agg!(ApproxCountDistinct, f),
2241 Expression::LogicalAnd(f) => recurse_agg!(LogicalAnd, f),
2242 Expression::LogicalOr(f) => recurse_agg!(LogicalOr, f),
2243 Expression::Skewness(f) => recurse_agg!(Skewness, f),
2244 Expression::ArrayConcatAgg(f) => recurse_agg!(ArrayConcatAgg, f),
2245 Expression::ArrayUniqueAgg(f) => recurse_agg!(ArrayUniqueAgg, f),
2246 Expression::BoolXorAgg(f) => recurse_agg!(BoolXorAgg, f),
2247 Expression::BitwiseOrAgg(f) => recurse_agg!(BitwiseOrAgg, f),
2248 Expression::BitwiseAndAgg(f) => recurse_agg!(BitwiseAndAgg, f),
2249 Expression::BitwiseXorAgg(f) => recurse_agg!(BitwiseXorAgg, f),
2250
2251 Expression::Count(mut c) => {
2253 if let Some(this) = c.this.take() {
2254 c.this = Some(transform_recursive(this, transform_fn)?);
2255 }
2256 if let Some(filter) = c.filter.take() {
2257 c.filter = Some(transform_recursive(filter, transform_fn)?);
2258 }
2259 Expression::Count(c)
2260 }
2261
2262 Expression::PipeOperator(mut pipe) => {
2263 pipe.this = transform_recursive(pipe.this, transform_fn)?;
2264 pipe.expression = transform_recursive(pipe.expression, transform_fn)?;
2265 Expression::PipeOperator(pipe)
2266 }
2267
2268 Expression::ArrayExcept(mut f) => {
2270 f.this = transform_recursive(f.this, transform_fn)?;
2271 f.expression = transform_recursive(f.expression, transform_fn)?;
2272 Expression::ArrayExcept(f)
2273 }
2274 Expression::ArrayContains(mut f) => {
2275 f.this = transform_recursive(f.this, transform_fn)?;
2276 f.expression = transform_recursive(f.expression, transform_fn)?;
2277 Expression::ArrayContains(f)
2278 }
2279 Expression::ArrayDistinct(mut f) => {
2280 f.this = transform_recursive(f.this, transform_fn)?;
2281 Expression::ArrayDistinct(f)
2282 }
2283 Expression::ArrayPosition(mut f) => {
2284 f.this = transform_recursive(f.this, transform_fn)?;
2285 f.expression = transform_recursive(f.expression, transform_fn)?;
2286 Expression::ArrayPosition(f)
2287 }
2288
2289 other => other,
2291 };
2292
2293 transform_fn(expr)
2295}
2296
2297struct CachedDialectConfig {
2307 tokenizer_config: Arc<TokenizerConfig>,
2308 #[cfg(feature = "generate")]
2309 generator_config: Arc<GeneratorConfig>,
2310}
2311
2312struct DialectConfigs {
2313 tokenizer_config: Arc<TokenizerConfig>,
2314 #[cfg(feature = "generate")]
2315 generator_config: Arc<GeneratorConfig>,
2316 #[cfg(feature = "transpile")]
2317 transformer: Box<dyn Fn(Expression) -> Result<Expression> + Send + Sync>,
2318}
2319
2320macro_rules! cached_dialect {
2322 ($static_name:ident, $dialect_struct:expr, $feature:literal) => {
2323 #[cfg(feature = $feature)]
2324 static $static_name: LazyLock<CachedDialectConfig> = LazyLock::new(|| {
2325 let d = $dialect_struct;
2326 CachedDialectConfig {
2327 tokenizer_config: Arc::new(d.tokenizer_config()),
2328 #[cfg(feature = "generate")]
2329 generator_config: Arc::new(d.generator_config()),
2330 }
2331 });
2332 };
2333}
2334
2335static CACHED_GENERIC: LazyLock<CachedDialectConfig> = LazyLock::new(|| {
2336 let d = GenericDialect;
2337 CachedDialectConfig {
2338 tokenizer_config: Arc::new(d.tokenizer_config()),
2339 #[cfg(feature = "generate")]
2340 generator_config: Arc::new(d.generator_config()),
2341 }
2342});
2343
2344cached_dialect!(CACHED_POSTGRESQL, PostgresDialect, "dialect-postgresql");
2345cached_dialect!(CACHED_MYSQL, MySQLDialect, "dialect-mysql");
2346cached_dialect!(CACHED_BIGQUERY, BigQueryDialect, "dialect-bigquery");
2347cached_dialect!(CACHED_SNOWFLAKE, SnowflakeDialect, "dialect-snowflake");
2348cached_dialect!(CACHED_DUCKDB, DuckDBDialect, "dialect-duckdb");
2349cached_dialect!(CACHED_TSQL, TSQLDialect, "dialect-tsql");
2350cached_dialect!(CACHED_ORACLE, OracleDialect, "dialect-oracle");
2351cached_dialect!(CACHED_HIVE, HiveDialect, "dialect-hive");
2352cached_dialect!(CACHED_SPARK, SparkDialect, "dialect-spark");
2353cached_dialect!(CACHED_SQLITE, SQLiteDialect, "dialect-sqlite");
2354cached_dialect!(CACHED_PRESTO, PrestoDialect, "dialect-presto");
2355cached_dialect!(CACHED_TRINO, TrinoDialect, "dialect-trino");
2356cached_dialect!(CACHED_REDSHIFT, RedshiftDialect, "dialect-redshift");
2357cached_dialect!(CACHED_CLICKHOUSE, ClickHouseDialect, "dialect-clickhouse");
2358cached_dialect!(CACHED_DATABRICKS, DatabricksDialect, "dialect-databricks");
2359cached_dialect!(CACHED_ATHENA, AthenaDialect, "dialect-athena");
2360cached_dialect!(CACHED_TERADATA, TeradataDialect, "dialect-teradata");
2361cached_dialect!(CACHED_DORIS, DorisDialect, "dialect-doris");
2362cached_dialect!(CACHED_STARROCKS, StarRocksDialect, "dialect-starrocks");
2363cached_dialect!(
2364 CACHED_MATERIALIZE,
2365 MaterializeDialect,
2366 "dialect-materialize"
2367);
2368cached_dialect!(CACHED_RISINGWAVE, RisingWaveDialect, "dialect-risingwave");
2369cached_dialect!(
2370 CACHED_SINGLESTORE,
2371 SingleStoreDialect,
2372 "dialect-singlestore"
2373);
2374cached_dialect!(
2375 CACHED_COCKROACHDB,
2376 CockroachDBDialect,
2377 "dialect-cockroachdb"
2378);
2379cached_dialect!(CACHED_TIDB, TiDBDialect, "dialect-tidb");
2380cached_dialect!(CACHED_DRUID, DruidDialect, "dialect-druid");
2381cached_dialect!(CACHED_SOLR, SolrDialect, "dialect-solr");
2382cached_dialect!(CACHED_TABLEAU, TableauDialect, "dialect-tableau");
2383cached_dialect!(CACHED_DUNE, DuneDialect, "dialect-dune");
2384cached_dialect!(CACHED_FABRIC, FabricDialect, "dialect-fabric");
2385cached_dialect!(CACHED_DRILL, DrillDialect, "dialect-drill");
2386cached_dialect!(CACHED_DREMIO, DremioDialect, "dialect-dremio");
2387cached_dialect!(CACHED_EXASOL, ExasolDialect, "dialect-exasol");
2388cached_dialect!(CACHED_DATAFUSION, DataFusionDialect, "dialect-datafusion");
2389
2390fn configs_for_dialect_type(dt: DialectType) -> DialectConfigs {
2391 macro_rules! from_cache {
2393 ($cache:expr, $dialect_struct:expr) => {{
2394 let c = &*$cache;
2395 DialectConfigs {
2396 tokenizer_config: c.tokenizer_config.clone(),
2397 #[cfg(feature = "generate")]
2398 generator_config: c.generator_config.clone(),
2399 #[cfg(feature = "transpile")]
2400 transformer: Box::new(move |e| $dialect_struct.transform_expr(e)),
2401 }
2402 }};
2403 }
2404 match dt {
2405 #[cfg(feature = "dialect-postgresql")]
2406 DialectType::PostgreSQL => from_cache!(CACHED_POSTGRESQL, PostgresDialect),
2407 #[cfg(feature = "dialect-mysql")]
2408 DialectType::MySQL => from_cache!(CACHED_MYSQL, MySQLDialect),
2409 #[cfg(feature = "dialect-bigquery")]
2410 DialectType::BigQuery => from_cache!(CACHED_BIGQUERY, BigQueryDialect),
2411 #[cfg(feature = "dialect-snowflake")]
2412 DialectType::Snowflake => from_cache!(CACHED_SNOWFLAKE, SnowflakeDialect),
2413 #[cfg(feature = "dialect-duckdb")]
2414 DialectType::DuckDB => from_cache!(CACHED_DUCKDB, DuckDBDialect),
2415 #[cfg(feature = "dialect-tsql")]
2416 DialectType::TSQL => from_cache!(CACHED_TSQL, TSQLDialect),
2417 #[cfg(feature = "dialect-oracle")]
2418 DialectType::Oracle => from_cache!(CACHED_ORACLE, OracleDialect),
2419 #[cfg(feature = "dialect-hive")]
2420 DialectType::Hive => from_cache!(CACHED_HIVE, HiveDialect),
2421 #[cfg(feature = "dialect-spark")]
2422 DialectType::Spark => from_cache!(CACHED_SPARK, SparkDialect),
2423 #[cfg(feature = "dialect-sqlite")]
2424 DialectType::SQLite => from_cache!(CACHED_SQLITE, SQLiteDialect),
2425 #[cfg(feature = "dialect-presto")]
2426 DialectType::Presto => from_cache!(CACHED_PRESTO, PrestoDialect),
2427 #[cfg(feature = "dialect-trino")]
2428 DialectType::Trino => from_cache!(CACHED_TRINO, TrinoDialect),
2429 #[cfg(feature = "dialect-redshift")]
2430 DialectType::Redshift => from_cache!(CACHED_REDSHIFT, RedshiftDialect),
2431 #[cfg(feature = "dialect-clickhouse")]
2432 DialectType::ClickHouse => from_cache!(CACHED_CLICKHOUSE, ClickHouseDialect),
2433 #[cfg(feature = "dialect-databricks")]
2434 DialectType::Databricks => from_cache!(CACHED_DATABRICKS, DatabricksDialect),
2435 #[cfg(feature = "dialect-athena")]
2436 DialectType::Athena => from_cache!(CACHED_ATHENA, AthenaDialect),
2437 #[cfg(feature = "dialect-teradata")]
2438 DialectType::Teradata => from_cache!(CACHED_TERADATA, TeradataDialect),
2439 #[cfg(feature = "dialect-doris")]
2440 DialectType::Doris => from_cache!(CACHED_DORIS, DorisDialect),
2441 #[cfg(feature = "dialect-starrocks")]
2442 DialectType::StarRocks => from_cache!(CACHED_STARROCKS, StarRocksDialect),
2443 #[cfg(feature = "dialect-materialize")]
2444 DialectType::Materialize => from_cache!(CACHED_MATERIALIZE, MaterializeDialect),
2445 #[cfg(feature = "dialect-risingwave")]
2446 DialectType::RisingWave => from_cache!(CACHED_RISINGWAVE, RisingWaveDialect),
2447 #[cfg(feature = "dialect-singlestore")]
2448 DialectType::SingleStore => from_cache!(CACHED_SINGLESTORE, SingleStoreDialect),
2449 #[cfg(feature = "dialect-cockroachdb")]
2450 DialectType::CockroachDB => from_cache!(CACHED_COCKROACHDB, CockroachDBDialect),
2451 #[cfg(feature = "dialect-tidb")]
2452 DialectType::TiDB => from_cache!(CACHED_TIDB, TiDBDialect),
2453 #[cfg(feature = "dialect-druid")]
2454 DialectType::Druid => from_cache!(CACHED_DRUID, DruidDialect),
2455 #[cfg(feature = "dialect-solr")]
2456 DialectType::Solr => from_cache!(CACHED_SOLR, SolrDialect),
2457 #[cfg(feature = "dialect-tableau")]
2458 DialectType::Tableau => from_cache!(CACHED_TABLEAU, TableauDialect),
2459 #[cfg(feature = "dialect-dune")]
2460 DialectType::Dune => from_cache!(CACHED_DUNE, DuneDialect),
2461 #[cfg(feature = "dialect-fabric")]
2462 DialectType::Fabric => from_cache!(CACHED_FABRIC, FabricDialect),
2463 #[cfg(feature = "dialect-drill")]
2464 DialectType::Drill => from_cache!(CACHED_DRILL, DrillDialect),
2465 #[cfg(feature = "dialect-dremio")]
2466 DialectType::Dremio => from_cache!(CACHED_DREMIO, DremioDialect),
2467 #[cfg(feature = "dialect-exasol")]
2468 DialectType::Exasol => from_cache!(CACHED_EXASOL, ExasolDialect),
2469 #[cfg(feature = "dialect-datafusion")]
2470 DialectType::DataFusion => from_cache!(CACHED_DATAFUSION, DataFusionDialect),
2471 _ => from_cache!(CACHED_GENERIC, GenericDialect),
2472 }
2473}
2474
2475static CUSTOM_DIALECT_REGISTRY: LazyLock<RwLock<HashMap<String, Arc<CustomDialectConfig>>>> =
2480 LazyLock::new(|| RwLock::new(HashMap::new()));
2481
2482struct CustomDialectConfig {
2483 name: String,
2484 base_dialect: DialectType,
2485 tokenizer_config: Arc<TokenizerConfig>,
2486 #[cfg(feature = "generate")]
2487 generator_config: GeneratorConfig,
2488 #[cfg(feature = "transpile")]
2489 transform: Option<Arc<dyn Fn(Expression) -> Result<Expression> + Send + Sync>>,
2490 #[cfg(feature = "transpile")]
2491 preprocess: Option<Arc<dyn Fn(Expression) -> Result<Expression> + Send + Sync>>,
2492}
2493
2494pub struct CustomDialectBuilder {
2522 name: String,
2523 base_dialect: DialectType,
2524 tokenizer_modifier: Option<Box<dyn FnOnce(&mut TokenizerConfig)>>,
2525 #[cfg(feature = "generate")]
2526 generator_modifier: Option<Box<dyn FnOnce(&mut GeneratorConfig)>>,
2527 #[cfg(feature = "transpile")]
2528 transform: Option<Arc<dyn Fn(Expression) -> Result<Expression> + Send + Sync>>,
2529 #[cfg(feature = "transpile")]
2530 preprocess: Option<Arc<dyn Fn(Expression) -> Result<Expression> + Send + Sync>>,
2531}
2532
2533impl CustomDialectBuilder {
2534 pub fn new(name: impl Into<String>) -> Self {
2536 Self {
2537 name: name.into(),
2538 base_dialect: DialectType::Generic,
2539 tokenizer_modifier: None,
2540 #[cfg(feature = "generate")]
2541 generator_modifier: None,
2542 #[cfg(feature = "transpile")]
2543 transform: None,
2544 #[cfg(feature = "transpile")]
2545 preprocess: None,
2546 }
2547 }
2548
2549 pub fn based_on(mut self, dialect: DialectType) -> Self {
2551 self.base_dialect = dialect;
2552 self
2553 }
2554
2555 pub fn tokenizer_config_modifier<F>(mut self, f: F) -> Self
2557 where
2558 F: FnOnce(&mut TokenizerConfig) + 'static,
2559 {
2560 self.tokenizer_modifier = Some(Box::new(f));
2561 self
2562 }
2563
2564 #[cfg(feature = "generate")]
2566 pub fn generator_config_modifier<F>(mut self, f: F) -> Self
2567 where
2568 F: FnOnce(&mut GeneratorConfig) + 'static,
2569 {
2570 self.generator_modifier = Some(Box::new(f));
2571 self
2572 }
2573
2574 #[cfg(feature = "transpile")]
2579 pub fn transform_fn<F>(mut self, f: F) -> Self
2580 where
2581 F: Fn(Expression) -> Result<Expression> + Send + Sync + 'static,
2582 {
2583 self.transform = Some(Arc::new(f));
2584 self
2585 }
2586
2587 #[cfg(feature = "transpile")]
2592 pub fn preprocess_fn<F>(mut self, f: F) -> Self
2593 where
2594 F: Fn(Expression) -> Result<Expression> + Send + Sync + 'static,
2595 {
2596 self.preprocess = Some(Arc::new(f));
2597 self
2598 }
2599
2600 pub fn register(self) -> Result<()> {
2606 if DialectType::from_str(&self.name).is_ok() {
2608 return Err(crate::error::Error::parse(
2609 format!(
2610 "Cannot register custom dialect '{}': name collides with built-in dialect",
2611 self.name
2612 ),
2613 0,
2614 0,
2615 0,
2616 0,
2617 ));
2618 }
2619
2620 let base_configs = configs_for_dialect_type(self.base_dialect);
2622 let mut tok_config = (*base_configs.tokenizer_config).clone();
2623 #[cfg(feature = "generate")]
2624 let mut gen_config = (*base_configs.generator_config).clone();
2625
2626 if let Some(tok_mod) = self.tokenizer_modifier {
2628 tok_mod(&mut tok_config);
2629 }
2630 #[cfg(feature = "generate")]
2631 if let Some(gen_mod) = self.generator_modifier {
2632 gen_mod(&mut gen_config);
2633 }
2634
2635 let config = CustomDialectConfig {
2636 name: self.name.clone(),
2637 base_dialect: self.base_dialect,
2638 tokenizer_config: Arc::new(tok_config),
2639 #[cfg(feature = "generate")]
2640 generator_config: gen_config,
2641 #[cfg(feature = "transpile")]
2642 transform: self.transform,
2643 #[cfg(feature = "transpile")]
2644 preprocess: self.preprocess,
2645 };
2646
2647 register_custom_dialect(config)
2648 }
2649}
2650
2651use std::str::FromStr;
2652
2653fn register_custom_dialect(config: CustomDialectConfig) -> Result<()> {
2654 let mut registry = CUSTOM_DIALECT_REGISTRY.write().map_err(|e| {
2655 crate::error::Error::parse(format!("Registry lock poisoned: {}", e), 0, 0, 0, 0)
2656 })?;
2657
2658 if registry.contains_key(&config.name) {
2659 return Err(crate::error::Error::parse(
2660 format!("Custom dialect '{}' is already registered", config.name),
2661 0,
2662 0,
2663 0,
2664 0,
2665 ));
2666 }
2667
2668 registry.insert(config.name.clone(), Arc::new(config));
2669 Ok(())
2670}
2671
2672pub fn unregister_custom_dialect(name: &str) -> bool {
2677 if let Ok(mut registry) = CUSTOM_DIALECT_REGISTRY.write() {
2678 registry.remove(name).is_some()
2679 } else {
2680 false
2681 }
2682}
2683
2684fn get_custom_dialect_config(name: &str) -> Option<Arc<CustomDialectConfig>> {
2685 CUSTOM_DIALECT_REGISTRY
2686 .read()
2687 .ok()
2688 .and_then(|registry| registry.get(name).cloned())
2689}
2690
2691pub struct Dialect {
2714 dialect_type: DialectType,
2715 tokenizer: Tokenizer,
2716 #[cfg(feature = "generate")]
2717 generator_config: Arc<GeneratorConfig>,
2718 #[cfg(feature = "transpile")]
2719 transformer: Box<dyn Fn(Expression) -> Result<Expression> + Send + Sync>,
2720 #[cfg(feature = "generate")]
2722 generator_config_for_expr: Option<Box<dyn Fn(&Expression) -> GeneratorConfig + Send + Sync>>,
2723 #[cfg(feature = "transpile")]
2725 custom_preprocess: Option<Box<dyn Fn(Expression) -> Result<Expression> + Send + Sync>>,
2726}
2727
2728#[cfg(feature = "transpile")]
2737#[derive(Debug, Clone, Serialize, Deserialize)]
2738#[serde(rename_all = "camelCase", default)]
2739#[non_exhaustive]
2740pub struct TranspileOptions {
2741 pub pretty: bool,
2743 pub unsupported_level: UnsupportedLevel,
2748 pub max_unsupported: usize,
2750 pub complexity_guard: ComplexityGuardOptions,
2752}
2753
2754#[cfg(feature = "transpile")]
2755impl Default for TranspileOptions {
2756 fn default() -> Self {
2757 Self {
2758 pretty: false,
2759 unsupported_level: UnsupportedLevel::Warn,
2760 max_unsupported: 3,
2761 complexity_guard: ComplexityGuardOptions::default(),
2762 }
2763 }
2764}
2765
2766#[cfg(feature = "transpile")]
2767impl TranspileOptions {
2768 pub fn pretty() -> Self {
2770 Self {
2771 pretty: true,
2772 ..Default::default()
2773 }
2774 }
2775
2776 pub fn strict() -> Self {
2778 Self {
2779 unsupported_level: UnsupportedLevel::Raise,
2780 ..Default::default()
2781 }
2782 }
2783
2784 pub fn with_unsupported_level(mut self, level: UnsupportedLevel) -> Self {
2786 self.unsupported_level = level;
2787 self
2788 }
2789
2790 pub fn with_max_unsupported(mut self, max: usize) -> Self {
2792 self.max_unsupported = max;
2793 self
2794 }
2795
2796 pub fn with_complexity_guard(mut self, guard: ComplexityGuardOptions) -> Self {
2798 self.complexity_guard = guard;
2799 self
2800 }
2801}
2802
2803#[cfg(feature = "transpile")]
2810pub trait TranspileTarget {
2811 fn with_dialect<R>(self, f: impl FnOnce(&Dialect) -> R) -> R;
2813}
2814
2815#[cfg(feature = "transpile")]
2816impl TranspileTarget for DialectType {
2817 fn with_dialect<R>(self, f: impl FnOnce(&Dialect) -> R) -> R {
2818 f(&Dialect::get(self))
2819 }
2820}
2821
2822#[cfg(feature = "transpile")]
2823impl TranspileTarget for &Dialect {
2824 fn with_dialect<R>(self, f: impl FnOnce(&Dialect) -> R) -> R {
2825 f(self)
2826 }
2827}
2828
2829impl Dialect {
2830 pub fn get(dialect_type: DialectType) -> Self {
2837 let configs = configs_for_dialect_type(dialect_type);
2838 let tokenizer_config = configs.tokenizer_config;
2839 #[cfg(feature = "generate")]
2840 let generator_config = configs.generator_config;
2841 #[cfg(feature = "transpile")]
2842 let transformer = configs.transformer;
2843
2844 #[cfg(feature = "generate")]
2846 let generator_config_for_expr: Option<
2847 Box<dyn Fn(&Expression) -> GeneratorConfig + Send + Sync>,
2848 > = match dialect_type {
2849 #[cfg(feature = "dialect-athena")]
2850 DialectType::Athena => Some(Box::new(|expr| {
2851 AthenaDialect.generator_config_for_expr(expr)
2852 })),
2853 _ => None,
2854 };
2855
2856 Self {
2857 dialect_type,
2858 tokenizer: Tokenizer::from_shared_config(tokenizer_config),
2859 #[cfg(feature = "generate")]
2860 generator_config,
2861 #[cfg(feature = "transpile")]
2862 transformer,
2863 #[cfg(feature = "generate")]
2864 generator_config_for_expr,
2865 #[cfg(feature = "transpile")]
2866 custom_preprocess: None,
2867 }
2868 }
2869
2870 pub fn get_by_name(name: &str) -> Option<Self> {
2876 if let Ok(dt) = DialectType::from_str(name) {
2878 return Some(Self::get(dt));
2879 }
2880
2881 let config = get_custom_dialect_config(name)?;
2883 Some(Self::from_custom_config(&config))
2884 }
2885
2886 fn from_custom_config(config: &CustomDialectConfig) -> Self {
2888 #[cfg(feature = "transpile")]
2890 let transformer: Box<dyn Fn(Expression) -> Result<Expression> + Send + Sync> =
2891 if let Some(ref custom_transform) = config.transform {
2892 let t = Arc::clone(custom_transform);
2893 Box::new(move |e| t(e))
2894 } else {
2895 configs_for_dialect_type(config.base_dialect).transformer
2896 };
2897
2898 #[cfg(feature = "transpile")]
2900 let custom_preprocess: Option<
2901 Box<dyn Fn(Expression) -> Result<Expression> + Send + Sync>,
2902 > = config.preprocess.as_ref().map(|p| {
2903 let p = Arc::clone(p);
2904 Box::new(move |e: Expression| p(e))
2905 as Box<dyn Fn(Expression) -> Result<Expression> + Send + Sync>
2906 });
2907
2908 Self {
2909 dialect_type: config.base_dialect,
2910 tokenizer: Tokenizer::from_shared_config(config.tokenizer_config.clone()),
2911 #[cfg(feature = "generate")]
2912 generator_config: Arc::new(config.generator_config.clone()),
2913 #[cfg(feature = "transpile")]
2914 transformer,
2915 #[cfg(feature = "generate")]
2916 generator_config_for_expr: None,
2917 #[cfg(feature = "transpile")]
2918 custom_preprocess,
2919 }
2920 }
2921
2922 pub fn dialect_type(&self) -> DialectType {
2924 self.dialect_type
2925 }
2926
2927 #[cfg(feature = "generate")]
2929 pub fn generator_config(&self) -> &GeneratorConfig {
2930 &self.generator_config
2931 }
2932
2933 pub fn parse(&self, sql: &str) -> Result<Vec<Expression>> {
2939 self.parse_with_guard(sql, self.default_complexity_guard())
2940 }
2941
2942 fn parse_with_guard(
2943 &self,
2944 sql: &str,
2945 complexity_guard: ComplexityGuardOptions,
2946 ) -> Result<Vec<Expression>> {
2947 enforce_input(sql, &complexity_guard)?;
2948 let source: Arc<str> = Arc::from(sql);
2949 let (tokens, token_guard_stats) = self.tokenizer.tokenize_for_parser(&source)?;
2950 let config = crate::parser::ParserConfig {
2951 dialect: Some(self.dialect_type),
2952 complexity_guard,
2953 ..Default::default()
2954 };
2955 let mut parser = Parser::with_parser_tokens(tokens, token_guard_stats, config, source);
2956 parser.parse()
2957 }
2958
2959 fn default_complexity_guard(&self) -> ComplexityGuardOptions {
2960 let mut guard = ComplexityGuardOptions::default();
2961 if matches!(self.dialect_type, DialectType::ClickHouse) {
2962 guard.max_ast_depth = Some(4_096);
2963 guard.max_function_call_depth = Some(512);
2964 }
2965 guard
2966 }
2967
2968 #[cfg(feature = "transpile")]
2969 fn default_transpile_complexity_guard(
2970 &self,
2971 target_dialect: &Dialect,
2972 guard: ComplexityGuardOptions,
2973 ) -> ComplexityGuardOptions {
2974 if guard != ComplexityGuardOptions::default() {
2975 return guard;
2976 }
2977
2978 if matches!(self.dialect_type, DialectType::ClickHouse)
2979 || matches!(target_dialect.dialect_type, DialectType::ClickHouse)
2980 {
2981 let mut guard = guard;
2982 guard.max_ast_depth = Some(4_096);
2983 guard.max_function_call_depth = Some(512);
2984 guard
2985 } else {
2986 guard
2987 }
2988 }
2989
2990 pub fn parse_data_type(&self, sql: &str) -> Result<DataType> {
2995 let complexity_guard = self.default_complexity_guard();
2996 enforce_input(sql, &complexity_guard)?;
2997 let source: Arc<str> = Arc::from(sql);
2998 let (tokens, token_guard_stats) = self.tokenizer.tokenize_for_parser(&source)?;
2999 let config = crate::parser::ParserConfig {
3000 dialect: Some(self.dialect_type),
3001 complexity_guard,
3002 ..Default::default()
3003 };
3004 let mut parser = Parser::with_parser_tokens(tokens, token_guard_stats, config, source);
3005 parser.parse_standalone_data_type()
3006 }
3007
3008 pub fn tokenize(&self, sql: &str) -> Result<Vec<Token>> {
3010 self.tokenizer.tokenize(sql)
3011 }
3012
3013 #[cfg(feature = "generate")]
3016 fn get_config_for_expr(&self, expr: &Expression) -> GeneratorConfig {
3017 if let Some(ref config_fn) = self.generator_config_for_expr {
3018 config_fn(expr)
3019 } else {
3020 (*self.generator_config).clone()
3021 }
3022 }
3023
3024 #[cfg(feature = "generate")]
3030 pub fn generate(&self, expr: &Expression) -> Result<String> {
3031 if self.generator_config_for_expr.is_none() {
3033 let mut generator = Generator::with_arc_config(self.generator_config.clone());
3034 return generator.generate(expr);
3035 }
3036 let config = self.get_config_for_expr(expr);
3037 let mut generator = Generator::with_config(config);
3038 generator.generate(expr)
3039 }
3040
3041 #[cfg(feature = "generate")]
3043 pub fn generate_pretty(&self, expr: &Expression) -> Result<String> {
3044 let mut config = self.get_config_for_expr(expr);
3045 config.pretty = true;
3046 let mut generator = Generator::with_config(config);
3047 generator.generate(expr)
3048 }
3049
3050 #[cfg(feature = "generate")]
3052 pub fn generate_with_source(&self, expr: &Expression, source: DialectType) -> Result<String> {
3053 let mut config = self.get_config_for_expr(expr);
3054 config.source_dialect = Some(source);
3055 let mut generator = Generator::with_config(config);
3056 generator.generate(expr)
3057 }
3058
3059 #[cfg(feature = "generate")]
3061 pub fn generate_pretty_with_source(
3062 &self,
3063 expr: &Expression,
3064 source: DialectType,
3065 ) -> Result<String> {
3066 let mut config = self.get_config_for_expr(expr);
3067 config.pretty = true;
3068 config.source_dialect = Some(source);
3069 let mut generator = Generator::with_config(config);
3070 generator.generate(expr)
3071 }
3072
3073 #[cfg(all(feature = "generate", feature = "transpile"))]
3075 fn generate_with_transpile_options(
3076 &self,
3077 expr: &Expression,
3078 source: DialectType,
3079 opts: &TranspileOptions,
3080 ) -> Result<String> {
3081 let mut config = self.get_config_for_expr(expr);
3082 config.source_dialect = Some(source);
3083 config.pretty = opts.pretty;
3084 config.unsupported_level = opts.unsupported_level;
3085 config.max_unsupported = opts.max_unsupported.max(1);
3086 config.complexity_guard = opts.complexity_guard;
3087 let mut generator = Generator::with_config(config);
3088 generator.generate(expr)
3089 }
3090
3091 #[cfg(feature = "generate")]
3093 pub fn generate_with_identify(&self, expr: &Expression) -> Result<String> {
3094 let mut config = self.get_config_for_expr(expr);
3095 config.always_quote_identifiers = true;
3096 let mut generator = Generator::with_config(config);
3097 generator.generate(expr)
3098 }
3099
3100 #[cfg(feature = "generate")]
3102 pub fn generate_pretty_with_identify(&self, expr: &Expression) -> Result<String> {
3103 let mut config = (*self.generator_config).clone();
3104 config.pretty = true;
3105 config.always_quote_identifiers = true;
3106 let mut generator = Generator::with_config(config);
3107 generator.generate(expr)
3108 }
3109
3110 #[cfg(feature = "generate")]
3112 pub fn generate_with_overrides(
3113 &self,
3114 expr: &Expression,
3115 overrides: impl FnOnce(&mut GeneratorConfig),
3116 ) -> Result<String> {
3117 let mut config = self.get_config_for_expr(expr);
3118 overrides(&mut config);
3119 let mut generator = Generator::with_config(config);
3120 generator.generate(expr)
3121 }
3122
3123 #[cfg(feature = "transpile")]
3134 pub fn transform(&self, expr: Expression) -> Result<Expression> {
3135 self.transform_with_guard(expr, self.default_complexity_guard())
3136 }
3137
3138 #[cfg(feature = "transpile")]
3139 fn transform_with_guard(
3140 &self,
3141 expr: Expression,
3142 complexity_guard: ComplexityGuardOptions,
3143 ) -> Result<Expression> {
3144 enforce_generate_ast(&expr, &complexity_guard)?;
3145 let preprocessed = self.preprocess(expr)?;
3147 transform_recursive(preprocessed, &self.transformer)
3149 }
3150
3151 #[cfg(feature = "transpile")]
3153 fn preprocess(&self, expr: Expression) -> Result<Expression> {
3154 if let Some(ref custom_preprocess) = self.custom_preprocess {
3156 return custom_preprocess(expr);
3157 }
3158
3159 #[cfg(any(
3160 feature = "dialect-mysql",
3161 feature = "dialect-postgresql",
3162 feature = "dialect-bigquery",
3163 feature = "dialect-snowflake",
3164 feature = "dialect-tsql",
3165 feature = "dialect-spark",
3166 feature = "dialect-databricks",
3167 feature = "dialect-hive",
3168 feature = "dialect-sqlite",
3169 feature = "dialect-trino",
3170 feature = "dialect-presto",
3171 feature = "dialect-duckdb",
3172 feature = "dialect-redshift",
3173 feature = "dialect-starrocks",
3174 feature = "dialect-oracle",
3175 feature = "dialect-clickhouse",
3176 feature = "dialect-fabric",
3177 ))]
3178 use crate::transforms;
3179
3180 match self.dialect_type {
3181 #[cfg(feature = "dialect-mysql")]
3184 DialectType::MySQL => {
3185 let expr = transforms::eliminate_qualify(expr)?;
3186 let expr = transforms::eliminate_full_outer_join(expr)?;
3187 let expr = transforms::eliminate_semi_and_anti_joins(expr)?;
3188 let expr = transforms::unnest_generate_date_array_using_recursive_cte(expr)?;
3189 Ok(expr)
3190 }
3191 #[cfg(feature = "dialect-postgresql")]
3195 DialectType::PostgreSQL => {
3196 let expr = transforms::eliminate_qualify(expr)?;
3197 let expr = transforms::eliminate_semi_and_anti_joins(expr)?;
3198 let expr = transforms::unwrap_unnest_generate_series_for_postgres(expr)?;
3199 let expr = if let Expression::CreateFunction(mut cf) = expr {
3204 if cf.body.is_none() {
3205 for opt in &mut cf.set_options {
3206 if let crate::expressions::FunctionSetValue::Value { use_to, .. } =
3207 &mut opt.value
3208 {
3209 *use_to = false;
3210 }
3211 }
3212 }
3213 Expression::CreateFunction(cf)
3214 } else {
3215 expr
3216 };
3217 Ok(expr)
3218 }
3219 #[cfg(feature = "dialect-bigquery")]
3221 DialectType::BigQuery => {
3222 let expr = transforms::eliminate_semi_and_anti_joins(expr)?;
3223 let expr = transforms::pushdown_cte_column_names(expr)?;
3224 let expr = transforms::explode_projection_to_unnest(expr, DialectType::BigQuery)?;
3225 Ok(expr)
3226 }
3227 #[cfg(feature = "dialect-snowflake")]
3229 DialectType::Snowflake => {
3230 let expr = transforms::eliminate_semi_and_anti_joins(expr)?;
3231 let expr = transforms::eliminate_window_clause(expr)?;
3232 let expr = transforms::snowflake_flatten_projection_to_unnest(expr)?;
3233 Ok(expr)
3234 }
3235 #[cfg(feature = "dialect-tsql")]
3241 DialectType::TSQL => {
3242 let expr = transforms::eliminate_qualify(expr)?;
3243 let expr = transforms::eliminate_semi_and_anti_joins(expr)?;
3244 let expr = transforms::normalize_grouping_sets_for_tsql(expr)?;
3245 let expr =
3246 transforms::expand_distinct_grouping_sets_for_tsql(expr, DialectType::TSQL)?;
3247 let expr = transforms::ensure_bools(expr)?;
3248 let expr = transforms::unnest_generate_date_array_using_recursive_cte(expr)?;
3249 let expr = transforms::strip_cte_materialization(expr)?;
3250 let expr = transforms::move_ctes_to_top_level(expr)?;
3251 let expr = transforms::qualify_derived_table_outputs(expr)?;
3252 Ok(expr)
3253 }
3254 #[cfg(feature = "dialect-fabric")]
3257 DialectType::Fabric => {
3258 let expr = transforms::normalize_grouping_sets_for_tsql(expr)?;
3259 let expr =
3260 transforms::expand_distinct_grouping_sets_for_tsql(expr, DialectType::Fabric)?;
3261 let expr = transforms::ensure_bools(expr)?;
3262 let expr = transforms::strip_cte_materialization(expr)?;
3263 let expr = transforms::move_ctes_to_top_level(expr)?;
3264 Ok(expr)
3265 }
3266 #[cfg(feature = "dialect-spark")]
3269 DialectType::Spark => {
3270 let expr = transforms::eliminate_qualify(expr)?;
3271 let expr = transforms::add_auto_table_alias(expr)?;
3272 let expr = transforms::simplify_nested_paren_values(expr)?;
3273 let expr = transforms::move_ctes_to_top_level(expr)?;
3274 Ok(expr)
3275 }
3276 #[cfg(feature = "dialect-databricks")]
3279 DialectType::Databricks => {
3280 let expr = transforms::add_auto_table_alias(expr)?;
3281 let expr = transforms::simplify_nested_paren_values(expr)?;
3282 let expr = transforms::move_ctes_to_top_level(expr)?;
3283 Ok(expr)
3284 }
3285 #[cfg(feature = "dialect-hive")]
3287 DialectType::Hive => {
3288 let expr = transforms::eliminate_qualify(expr)?;
3289 let expr = transforms::move_ctes_to_top_level(expr)?;
3290 Ok(expr)
3291 }
3292 #[cfg(feature = "dialect-sqlite")]
3294 DialectType::SQLite => {
3295 let expr = transforms::eliminate_qualify(expr)?;
3296 Ok(expr)
3297 }
3298 #[cfg(feature = "dialect-trino")]
3300 DialectType::Trino => {
3301 let expr = transforms::eliminate_qualify(expr)?;
3302 let expr = transforms::explode_projection_to_unnest(expr, DialectType::Trino)?;
3303 Ok(expr)
3304 }
3305 #[cfg(feature = "dialect-presto")]
3307 DialectType::Presto => {
3308 let expr = transforms::eliminate_qualify(expr)?;
3309 let expr = transforms::eliminate_window_clause(expr)?;
3310 let expr = transforms::explode_projection_to_unnest(expr, DialectType::Presto)?;
3311 Ok(expr)
3312 }
3313 #[cfg(feature = "dialect-duckdb")]
3317 DialectType::DuckDB => {
3318 let expr = transforms::expand_posexplode_duckdb(expr)?;
3319 let expr = transforms::expand_like_any(expr)?;
3320 Ok(expr)
3321 }
3322 #[cfg(feature = "dialect-redshift")]
3324 DialectType::Redshift => {
3325 let expr = transforms::eliminate_qualify(expr)?;
3326 let expr = transforms::eliminate_window_clause(expr)?;
3327 let expr = transforms::unnest_generate_date_array_using_recursive_cte(expr)?;
3328 Ok(expr)
3329 }
3330 #[cfg(feature = "dialect-starrocks")]
3332 DialectType::StarRocks => {
3333 let expr = transforms::eliminate_qualify(expr)?;
3334 let expr = transforms::expand_between_in_delete(expr)?;
3335 let expr = transforms::eliminate_distinct_on_for_dialect(
3336 expr,
3337 Some(DialectType::StarRocks),
3338 Some(DialectType::StarRocks),
3339 )?;
3340 let expr = transforms::unnest_generate_date_array_using_recursive_cte(expr)?;
3341 Ok(expr)
3342 }
3343 #[cfg(feature = "dialect-datafusion")]
3345 DialectType::DataFusion => Ok(expr),
3346 #[cfg(feature = "dialect-oracle")]
3348 DialectType::Oracle => {
3349 let expr = transforms::eliminate_qualify(expr)?;
3350 Ok(expr)
3351 }
3352 #[cfg(feature = "dialect-drill")]
3354 DialectType::Drill => Ok(expr),
3355 #[cfg(feature = "dialect-teradata")]
3357 DialectType::Teradata => Ok(expr),
3358 #[cfg(feature = "dialect-clickhouse")]
3360 DialectType::ClickHouse => {
3361 let expr = transforms::no_limit_order_by_union(expr)?;
3362 Ok(expr)
3363 }
3364 _ => Ok(expr),
3366 }
3367 }
3368
3369 #[cfg(feature = "transpile")]
3382 pub fn transpile<T: TranspileTarget>(&self, sql: &str, target: T) -> Result<Vec<String>> {
3383 self.transpile_with(sql, target, TranspileOptions::default())
3384 }
3385
3386 #[cfg(feature = "transpile")]
3388 pub fn transpile_with<T: TranspileTarget>(
3389 &self,
3390 sql: &str,
3391 target: T,
3392 opts: TranspileOptions,
3393 ) -> Result<Vec<String>> {
3394 target.with_dialect(|td| self.transpile_inner(sql, td, &opts))
3395 }
3396
3397 #[cfg(feature = "transpile")]
3398 fn transpile_inner(
3399 &self,
3400 sql: &str,
3401 target_dialect: &Dialect,
3402 opts: &TranspileOptions,
3403 ) -> Result<Vec<String>> {
3404 let mut effective_opts = opts.clone();
3405 effective_opts.complexity_guard =
3406 self.default_transpile_complexity_guard(target_dialect, opts.complexity_guard);
3407 let opts = &effective_opts;
3408 let target = target_dialect.dialect_type;
3409 if matches!(self.dialect_type, DialectType::PostgreSQL)
3410 && matches!(target, DialectType::SQLite)
3411 {
3412 self.reject_pgvector_distance_operators_for_sqlite(sql)?;
3413 }
3414 let expressions = self.parse_with_guard(sql, opts.complexity_guard)?;
3415 let generic_identity =
3416 self.dialect_type == DialectType::Generic && target == DialectType::Generic;
3417
3418 if generic_identity {
3419 return expressions
3420 .into_iter()
3421 .map(|expr| {
3422 Self::reject_strict_unsupported(&expr, self.dialect_type, target, opts)?;
3423 target_dialect.generate_with_transpile_options(&expr, self.dialect_type, opts)
3424 })
3425 .collect();
3426 }
3427
3428 expressions
3429 .into_iter()
3430 .map(|expr| {
3431 let expr = if matches!(self.dialect_type, DialectType::DuckDB) {
3435 use crate::expressions::DataType as DT;
3436 transform_recursive(expr, &|e| match e {
3437 Expression::DataType(DT::VarChar { .. }) => {
3438 Ok(Expression::DataType(DT::Text))
3439 }
3440 Expression::DataType(DT::Char { .. }) => Ok(Expression::DataType(DT::Text)),
3441 _ => Ok(e),
3442 })?
3443 } else {
3444 expr
3445 };
3446
3447 Self::reject_postgres_tsql_strict_regex_predicates(
3448 &expr,
3449 self.dialect_type,
3450 target,
3451 opts,
3452 )?;
3453 Self::reject_tsql_strict_json_constructor_return_types(
3454 &expr,
3455 self.dialect_type,
3456 target,
3457 opts,
3458 )?;
3459 Self::reject_postgres_tsql_strict_json_aggregate_modifiers(
3460 &expr,
3461 self.dialect_type,
3462 target,
3463 opts,
3464 )?;
3465
3466 let normalized =
3470 if self.dialect_type != target && self.dialect_type != DialectType::Generic {
3471 self.transform_with_guard(expr, opts.complexity_guard)?
3472 } else {
3473 expr
3474 };
3475
3476 let normalized =
3481 if matches!(self.dialect_type, DialectType::TSQL | DialectType::Fabric)
3482 && !matches!(target, DialectType::TSQL | DialectType::Fabric)
3483 {
3484 transform_recursive(normalized, &|e| {
3485 if let Expression::Function(ref f) = e {
3486 if f.name.eq_ignore_ascii_case("ISNULL") && f.args.len() == 2 {
3487 if let (
3489 Expression::Function(ref jq),
3490 Expression::Function(ref jv),
3491 ) = (&f.args[0], &f.args[1])
3492 {
3493 if jq.name.eq_ignore_ascii_case("JSON_QUERY")
3494 && jv.name.eq_ignore_ascii_case("JSON_VALUE")
3495 {
3496 return Ok(f.args[0].clone());
3498 }
3499 }
3500 }
3501 }
3502 Ok(e)
3503 })?
3504 } else {
3505 normalized
3506 };
3507
3508 let normalized = if matches!(self.dialect_type, DialectType::Snowflake)
3512 && !matches!(target, DialectType::Snowflake)
3513 {
3514 transform_recursive(normalized, &|e| {
3515 if let Expression::Function(ref f) = e {
3516 if f.name.eq_ignore_ascii_case("CURRENT_TIME") {
3517 return Ok(Expression::Localtime(Box::new(
3518 crate::expressions::Localtime { this: None },
3519 )));
3520 }
3521 }
3522 Ok(e)
3523 })?
3524 } else {
3525 normalized
3526 };
3527
3528 let normalized = if matches!(self.dialect_type, DialectType::Snowflake)
3532 && matches!(target, DialectType::DuckDB)
3533 {
3534 transform_recursive(normalized, &|e| {
3535 if let Expression::Function(ref f) = e {
3536 if f.name.eq_ignore_ascii_case("REPEAT") && f.args.len() == 2 {
3537 if let Expression::Literal(ref lit) = f.args[0] {
3539 if let crate::expressions::Literal::String(ref s) = lit.as_ref()
3540 {
3541 if s == " " {
3542 if !matches!(f.args[1], Expression::Cast(_)) {
3544 let mut new_args = f.args.clone();
3545 new_args[1] = Expression::Cast(Box::new(
3546 crate::expressions::Cast {
3547 this: new_args[1].clone(),
3548 to: crate::expressions::DataType::BigInt {
3549 length: None,
3550 },
3551 trailing_comments: Vec::new(),
3552 double_colon_syntax: false,
3553 format: None,
3554 default: None,
3555 inferred_type: None,
3556 },
3557 ));
3558 return Ok(Expression::Function(Box::new(
3559 crate::expressions::Function {
3560 name: f.name.clone(),
3561 args: new_args,
3562 distinct: f.distinct,
3563 trailing_comments: f
3564 .trailing_comments
3565 .clone(),
3566 use_bracket_syntax: f.use_bracket_syntax,
3567 no_parens: f.no_parens,
3568 quoted: f.quoted,
3569 span: None,
3570 inferred_type: None,
3571 },
3572 )));
3573 }
3574 }
3575 }
3576 }
3577 }
3578 }
3579 Ok(e)
3580 })?
3581 } else {
3582 normalized
3583 };
3584
3585 let normalized = if matches!(self.dialect_type, DialectType::BigQuery)
3588 && !matches!(target, DialectType::BigQuery)
3589 {
3590 crate::transforms::propagate_struct_field_names(normalized)?
3591 } else {
3592 normalized
3593 };
3594
3595 let normalized = if matches!(self.dialect_type, DialectType::Snowflake)
3600 && matches!(target, DialectType::DuckDB)
3601 {
3602 fn make_scaled_random() -> Expression {
3603 let lower =
3604 Expression::Literal(Box::new(crate::expressions::Literal::Number(
3605 "-9.223372036854776E+18".to_string(),
3606 )));
3607 let upper =
3608 Expression::Literal(Box::new(crate::expressions::Literal::Number(
3609 "9.223372036854776e+18".to_string(),
3610 )));
3611 let random_call = Expression::Random(crate::expressions::Random);
3612 let range_size = Expression::Paren(Box::new(crate::expressions::Paren {
3613 this: Expression::Sub(Box::new(crate::expressions::BinaryOp {
3614 left: upper,
3615 right: lower.clone(),
3616 left_comments: vec![],
3617 operator_comments: vec![],
3618 trailing_comments: vec![],
3619 inferred_type: None,
3620 })),
3621 trailing_comments: vec![],
3622 }));
3623 let scaled = Expression::Mul(Box::new(crate::expressions::BinaryOp {
3624 left: random_call,
3625 right: range_size,
3626 left_comments: vec![],
3627 operator_comments: vec![],
3628 trailing_comments: vec![],
3629 inferred_type: None,
3630 }));
3631 let shifted = Expression::Add(Box::new(crate::expressions::BinaryOp {
3632 left: lower,
3633 right: scaled,
3634 left_comments: vec![],
3635 operator_comments: vec![],
3636 trailing_comments: vec![],
3637 inferred_type: None,
3638 }));
3639 Expression::Cast(Box::new(crate::expressions::Cast {
3640 this: shifted,
3641 to: crate::expressions::DataType::BigInt { length: None },
3642 trailing_comments: vec![],
3643 double_colon_syntax: false,
3644 format: None,
3645 default: None,
3646 inferred_type: None,
3647 }))
3648 }
3649
3650 let normalized = transform_recursive(normalized, &|e| {
3657 if let Expression::Function(ref f) = e {
3658 let n = f.name.to_ascii_uppercase();
3659 if n == "UNIFORM" || n == "NORMAL" || n == "ZIPF" || n == "RANDSTR" {
3660 if let Expression::Function(mut f) = e {
3661 for arg in f.args.iter_mut() {
3662 if let Expression::Rand(ref r) = arg {
3663 if r.lower.is_none() && r.upper.is_none() {
3664 if let Some(ref seed) = r.seed {
3665 *arg = Expression::Function(Box::new(
3668 crate::expressions::Function::new(
3669 "RANDOM".to_string(),
3670 vec![*seed.clone()],
3671 ),
3672 ));
3673 }
3674 }
3675 }
3676 }
3677 return Ok(Expression::Function(f));
3678 }
3679 }
3680 }
3681 Ok(e)
3682 })?;
3683
3684 transform_recursive(normalized, &|e| {
3692 if let Expression::Function(ref f) = e {
3693 let n = f.name.to_ascii_uppercase();
3694 if n == "UNIFORM" || n == "NORMAL" || n == "ZIPF" {
3695 if let Expression::Function(mut f) = e {
3696 for arg in f.args.iter_mut() {
3697 if let Expression::Cast(ref cast) = arg {
3699 if matches!(
3700 cast.to,
3701 crate::expressions::DataType::BigInt { .. }
3702 ) {
3703 if let Expression::Add(ref add) = cast.this {
3704 if let Expression::Literal(ref lit) = add.left {
3705 if let crate::expressions::Literal::Number(
3706 ref num,
3707 ) = lit.as_ref()
3708 {
3709 if num == "-9.223372036854776E+18" {
3710 *arg = Expression::Random(
3711 crate::expressions::Random,
3712 );
3713 }
3714 }
3715 }
3716 }
3717 }
3718 }
3719 }
3720 return Ok(Expression::Function(f));
3721 }
3722 return Ok(e);
3723 }
3724 }
3725 match e {
3726 Expression::Random(_) => Ok(make_scaled_random()),
3727 Expression::Rand(ref r) if r.lower.is_none() && r.upper.is_none() => {
3730 Ok(make_scaled_random())
3731 }
3732 _ => Ok(e),
3733 }
3734 })?
3735 } else {
3736 normalized
3737 };
3738
3739 let normalized = normalization::normalize(
3741 normalized,
3742 self.dialect_type,
3743 target,
3744 matches!(
3745 opts.unsupported_level,
3746 UnsupportedLevel::Raise | UnsupportedLevel::Immediate
3747 ),
3748 )?;
3749
3750 let normalized = if matches!(target, DialectType::TSQL | DialectType::Fabric) {
3751 Self::normalize_tsql_fetch_overlaps_date_bin(normalized)?
3752 } else {
3753 normalized
3754 };
3755
3756 let normalized =
3757 if matches!(
3758 self.dialect_type,
3759 DialectType::PostgreSQL | DialectType::CockroachDB
3760 ) && !matches!(target, DialectType::PostgreSQL | DialectType::CockroachDB)
3761 {
3762 Self::normalize_postgres_type_function_casts(normalized, target)?
3763 } else {
3764 normalized
3765 };
3766
3767 let normalized = if matches!(self.dialect_type, DialectType::SQLite)
3768 && !matches!(target, DialectType::SQLite)
3769 {
3770 Self::normalize_sqlite_double_quoted_defaults(normalized)?
3771 } else {
3772 normalized
3773 };
3774
3775 let normalized = if matches!(self.dialect_type, DialectType::PostgreSQL)
3776 && matches!(target, DialectType::SQLite)
3777 {
3778 Self::normalize_postgres_to_sqlite_types(normalized)?
3779 } else {
3780 normalized
3781 };
3782
3783 let normalized = if matches!(self.dialect_type, DialectType::PostgreSQL)
3784 && matches!(target, DialectType::Fabric)
3785 {
3786 Self::normalize_postgres_to_fabric_types(normalized)?
3787 } else {
3788 normalized
3789 };
3790
3791 let normalized = if matches!(self.dialect_type, DialectType::BigQuery)
3795 && matches!(target, DialectType::DuckDB)
3796 {
3797 crate::transforms::wrap_duckdb_unnest_struct(normalized)?
3798 } else {
3799 normalized
3800 };
3801
3802 let normalized = if matches!(self.dialect_type, DialectType::BigQuery)
3805 && matches!(
3806 target,
3807 DialectType::DuckDB
3808 | DialectType::Presto
3809 | DialectType::Trino
3810 | DialectType::Athena
3811 | DialectType::Spark
3812 | DialectType::Databricks
3813 ) {
3814 crate::transforms::unnest_alias_to_column_alias(normalized)?
3815 } else if matches!(self.dialect_type, DialectType::BigQuery)
3816 && matches!(target, DialectType::BigQuery | DialectType::Redshift)
3817 {
3818 let result = crate::transforms::unnest_from_to_cross_join(normalized)?;
3821 if matches!(target, DialectType::Redshift) {
3823 crate::transforms::strip_unnest_column_refs(result)?
3824 } else {
3825 result
3826 }
3827 } else {
3828 normalized
3829 };
3830
3831 let normalized = if matches!(
3834 self.dialect_type,
3835 DialectType::PostgreSQL | DialectType::Redshift
3836 ) && matches!(
3837 target,
3838 DialectType::Presto | DialectType::Trino | DialectType::Athena
3839 ) {
3840 crate::transforms::wrap_unnest_join_aliases(normalized)?
3841 } else {
3842 normalized
3843 };
3844
3845 let normalized = crate::transforms::eliminate_distinct_on_for_dialect(
3849 normalized,
3850 Some(target),
3851 Some(self.dialect_type),
3852 )?;
3853
3854 let normalized = if matches!(target, DialectType::Snowflake) {
3856 Self::transform_generate_date_array_snowflake(normalized)?
3857 } else {
3858 normalized
3859 };
3860
3861 let normalized = if matches!(
3863 target,
3864 DialectType::Spark | DialectType::Databricks | DialectType::Hive
3865 ) {
3866 crate::transforms::unnest_to_explode_select(normalized)?
3867 } else {
3868 normalized
3869 };
3870
3871 let normalized = if matches!(target, DialectType::ClickHouse | DialectType::TSQL) {
3873 crate::transforms::no_limit_order_by_union(normalized)?
3874 } else {
3875 normalized
3876 };
3877
3878 let normalized = if matches!(
3879 self.dialect_type,
3880 DialectType::PostgreSQL | DialectType::CockroachDB
3881 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
3882 {
3883 Self::normalize_postgres_boolean_semantics_for_tsql(normalized)?
3884 } else {
3885 normalized
3886 };
3887
3888 let normalized = if self.dialect_type == DialectType::PostgreSQL
3889 && matches!(target, DialectType::TSQL | DialectType::Fabric)
3890 {
3891 Self::normalize_postgres_bytea_literals_for_tsql(normalized)?
3892 } else {
3893 normalized
3894 };
3895
3896 let normalized = if matches!(
3897 self.dialect_type,
3898 DialectType::PostgreSQL | DialectType::CockroachDB
3899 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
3900 {
3901 Self::normalize_postgres_string_semantics_for_tsql(normalized)?
3902 } else {
3903 normalized
3904 };
3905
3906 let normalized = if matches!(target, DialectType::TSQL | DialectType::Fabric)
3910 && !matches!(self.dialect_type, DialectType::TSQL | DialectType::Fabric)
3911 {
3912 transform_recursive(normalized, &|e| {
3913 if let Expression::Count(ref c) = e {
3914 let args = if c.star {
3916 vec![Expression::Star(crate::expressions::Star {
3917 table: None,
3918 except: None,
3919 replace: None,
3920 rename: None,
3921 trailing_comments: Vec::new(),
3922 span: None,
3923 })]
3924 } else if let Some(ref this) = c.this {
3925 vec![this.clone()]
3926 } else {
3927 vec![]
3928 };
3929 Ok(Expression::AggregateFunction(Box::new(
3930 crate::expressions::AggregateFunction {
3931 name: "COUNT_BIG".to_string(),
3932 args,
3933 distinct: c.distinct,
3934 filter: c.filter.clone(),
3935 order_by: Vec::new(),
3936 limit: None,
3937 ignore_nulls: None,
3938 inferred_type: None,
3939 },
3940 )))
3941 } else {
3942 Ok(e)
3943 }
3944 })?
3945 } else {
3946 normalized
3947 };
3948
3949 let normalized = if matches!(target, DialectType::TSQL | DialectType::Fabric)
3953 && !matches!(self.dialect_type, DialectType::TSQL | DialectType::Fabric)
3954 {
3955 let normalized = if self.dialect_type == DialectType::PostgreSQL {
3956 Self::rewrite_postgres_row_value_equality_for_tsql(normalized)?
3957 } else {
3958 normalized
3959 };
3960 Self::rewrite_boolean_values_for_tsql(normalized)?
3961 } else {
3962 normalized
3963 };
3964
3965 let normalized = if matches!(
3966 self.dialect_type,
3967 DialectType::PostgreSQL | DialectType::CockroachDB
3968 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
3969 {
3970 Self::rewrite_postgres_format_for_tsql(normalized, target)?
3971 } else {
3972 normalized
3973 };
3974
3975 let normalized = if self.dialect_type == DialectType::PostgreSQL
3976 && matches!(target, DialectType::TSQL | DialectType::Fabric)
3977 {
3978 Self::normalize_postgres_only_for_tsql(normalized)?
3979 } else {
3980 normalized
3981 };
3982
3983 let transformed =
3984 target_dialect.transform_with_guard(normalized, opts.complexity_guard)?;
3985
3986 let transformed = if matches!(target, DialectType::TSQL | DialectType::Fabric) {
3990 Self::rewrite_aggregate_filters_for_tsql(transformed)?
3991 } else {
3992 transformed
3993 };
3994
3995 let transformed = if matches!(
3996 self.dialect_type,
3997 DialectType::PostgreSQL | DialectType::CockroachDB
3998 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
3999 {
4000 crate::transforms::grouped_percentiles_to_tsql_windows(transformed)?
4001 } else {
4002 transformed
4003 };
4004
4005 let transformed = if matches!(
4006 self.dialect_type,
4007 DialectType::PostgreSQL | DialectType::CockroachDB
4008 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
4009 {
4010 Self::normalize_postgres_trim_for_tsql(transformed)?
4011 } else {
4012 transformed
4013 };
4014
4015 let transformed = if matches!(
4016 self.dialect_type,
4017 DialectType::PostgreSQL | DialectType::CockroachDB
4018 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
4019 {
4020 Self::rewrite_postgres_json_array_elements_select_for_tsql(transformed)?
4021 } else {
4022 transformed
4023 };
4024
4025 let transformed = if matches!(target, DialectType::DuckDB) {
4027 Self::seq_rownum_to_range(transformed)?
4028 } else {
4029 transformed
4030 };
4031
4032 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4033 Self::reject_tsql_interval_casts(&transformed, target, opts)?;
4034 }
4035
4036 let transformed = if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4037 Self::rewrite_tsql_interval_casts_to_varchar(transformed)?
4038 } else {
4039 transformed
4040 };
4041
4042 let transformed = if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4043 Self::legalize_tsql_nested_order_by(transformed)?
4044 } else {
4045 transformed
4046 };
4047
4048 Self::reject_strict_unsupported(&transformed, self.dialect_type, target, opts)?;
4049
4050 let mut sql = target_dialect.generate_with_transpile_options(
4051 &transformed,
4052 self.dialect_type,
4053 opts,
4054 )?;
4055
4056 if opts.pretty && target == DialectType::Snowflake {
4058 sql = Self::normalize_snowflake_pretty(sql);
4059 }
4060
4061 Ok(sql)
4062 })
4063 .collect()
4064 }
4065}
4066
4067#[cfg(feature = "transpile")]
4069impl Dialect {
4070 fn legalize_tsql_nested_order_by(expr: Expression) -> Result<Expression> {
4071 let preserve_root_order = matches!(&expr, Expression::Select(select) if Self::tsql_select_needs_order_offset(select));
4072
4073 let mut transformed = transform_recursive(expr, &|node| match node {
4074 Expression::Select(mut select) => {
4075 Self::legalize_tsql_select_offset(&mut select);
4076 if Self::tsql_select_needs_order_offset(&select) {
4077 select.offset = Some(Offset {
4078 this: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
4079 rows: Some(true),
4080 });
4081 }
4082 Ok(Expression::Select(select))
4083 }
4084 Expression::Subquery(mut subquery) => {
4085 Self::legalize_tsql_offset(&mut subquery.order_by, &mut subquery.offset, false);
4086 Ok(Expression::Subquery(subquery))
4087 }
4088 Expression::Union(mut union) => {
4089 Self::legalize_tsql_set_offset(&mut union.order_by, &mut union.offset);
4090 Ok(Expression::Union(union))
4091 }
4092 Expression::Intersect(mut intersect) => {
4093 Self::legalize_tsql_set_offset(&mut intersect.order_by, &mut intersect.offset);
4094 Ok(Expression::Intersect(intersect))
4095 }
4096 Expression::Except(mut except) => {
4097 Self::legalize_tsql_set_offset(&mut except.order_by, &mut except.offset);
4098 Ok(Expression::Except(except))
4099 }
4100 other => Ok(other),
4101 })?;
4102
4103 if preserve_root_order {
4104 if let Expression::Select(select) = &mut transformed {
4105 select.offset = None;
4106 }
4107 }
4108
4109 Self::drop_tsql_unbounded_nested_set_order_by(transformed)
4110 }
4111
4112 fn drop_tsql_unbounded_nested_set_order_by(mut expr: Expression) -> Result<Expression> {
4113 let root_order_by = Self::take_tsql_root_set_order_by(&mut expr);
4114
4115 let mut transformed = transform_recursive(expr, &|node| match node {
4116 Expression::Union(mut union) => {
4117 if union.limit.is_none() && union.offset.is_none() {
4118 union.order_by = None;
4119 }
4120 Ok(Expression::Union(union))
4121 }
4122 Expression::Intersect(mut intersect) => {
4123 if intersect.limit.is_none() && intersect.offset.is_none() {
4124 intersect.order_by = None;
4125 }
4126 Ok(Expression::Intersect(intersect))
4127 }
4128 Expression::Except(mut except) => {
4129 if except.limit.is_none() && except.offset.is_none() {
4130 except.order_by = None;
4131 }
4132 Ok(Expression::Except(except))
4133 }
4134 other => Ok(other),
4135 })?;
4136
4137 if let Some(order_by) = root_order_by {
4138 Self::restore_tsql_root_set_order_by(&mut transformed, order_by);
4139 }
4140
4141 Ok(transformed)
4142 }
4143
4144 fn take_tsql_root_set_order_by(expr: &mut Expression) -> Option<OrderBy> {
4145 match expr {
4146 Expression::Union(union) => union.order_by.take(),
4147 Expression::Intersect(intersect) => intersect.order_by.take(),
4148 Expression::Except(except) => except.order_by.take(),
4149 Expression::Subquery(subquery) if subquery.alias.is_none() => {
4150 Self::take_tsql_root_set_order_by(&mut subquery.this)
4151 }
4152 Expression::Paren(paren) => Self::take_tsql_root_set_order_by(&mut paren.this),
4153 _ => None,
4154 }
4155 }
4156
4157 fn restore_tsql_root_set_order_by(expr: &mut Expression, order_by: OrderBy) {
4158 match expr {
4159 Expression::Union(union) => union.order_by = Some(order_by),
4160 Expression::Intersect(intersect) => intersect.order_by = Some(order_by),
4161 Expression::Except(except) => except.order_by = Some(order_by),
4162 Expression::Subquery(subquery) if subquery.alias.is_none() => {
4163 Self::restore_tsql_root_set_order_by(&mut subquery.this, order_by);
4164 }
4165 Expression::Paren(paren) => {
4166 Self::restore_tsql_root_set_order_by(&mut paren.this, order_by);
4167 }
4168 _ => {}
4169 }
4170 }
4171
4172 fn legalize_tsql_select_offset(select: &mut crate::expressions::Select) {
4173 let has_fetch = select.fetch.is_some();
4174 Self::legalize_tsql_offset(&mut select.order_by, &mut select.offset, has_fetch);
4175 }
4176
4177 fn legalize_tsql_offset(
4178 order_by: &mut Option<OrderBy>,
4179 offset: &mut Option<Offset>,
4180 retain_inert_offset: bool,
4181 ) {
4182 if order_by.is_some() {
4183 return;
4184 }
4185
4186 if offset
4187 .as_ref()
4188 .is_some_and(|offset| Self::tsql_offset_is_inert(&offset.this))
4189 && !retain_inert_offset
4190 {
4191 *offset = None;
4192 } else if offset.is_some() {
4193 *order_by = Some(Generator::dummy_tsql_order_by());
4194 }
4195 }
4196
4197 fn legalize_tsql_set_offset(
4198 order_by: &mut Option<OrderBy>,
4199 offset: &mut Option<Box<Expression>>,
4200 ) {
4201 if order_by.is_some() {
4202 return;
4203 }
4204
4205 if offset.as_deref().is_some_and(Self::tsql_offset_is_inert) {
4206 *offset = None;
4207 } else if offset.is_some() {
4208 *order_by = Some(Generator::dummy_tsql_order_by());
4209 }
4210 }
4211
4212 fn tsql_offset_is_inert(expr: &Expression) -> bool {
4213 match expr {
4214 Expression::Null(_) => true,
4215 Expression::Literal(literal) => match literal.as_ref() {
4216 Literal::Number(value) => value.parse::<i128>().is_ok_and(|value| value == 0),
4217 _ => false,
4218 },
4219 _ => false,
4220 }
4221 }
4222
4223 fn tsql_select_needs_order_offset(select: &crate::expressions::Select) -> bool {
4224 select.order_by.is_some()
4225 && select.top.is_none()
4226 && select.limit.is_none()
4227 && select.offset.is_none()
4228 && select.fetch.is_none()
4229 && select.for_xml.is_empty()
4230 && select.for_json.is_empty()
4231 }
4232
4233 fn reject_strict_unsupported(
4234 expr: &Expression,
4235 source: DialectType,
4236 target: DialectType,
4237 opts: &TranspileOptions,
4238 ) -> Result<()> {
4239 if !matches!(
4240 opts.unsupported_level,
4241 UnsupportedLevel::Raise | UnsupportedLevel::Immediate
4242 ) {
4243 return Ok(());
4244 }
4245
4246 let mut diagnostics = Vec::new();
4247 if matches!(source, DialectType::PostgreSQL | DialectType::CockroachDB)
4248 && matches!(target, DialectType::TSQL | DialectType::Fabric)
4249 && Self::tsql_apply_has_invalid_outer_aggregate(expr)
4250 {
4251 Self::push_unsupported_diagnostic(
4252 &mut diagnostics,
4253 "APPLY aggregate expressions that combine an outer reference with another column reference",
4254 );
4255 }
4256 let structural_grouping_tuples =
4257 if matches!(source, DialectType::PostgreSQL | DialectType::CockroachDB)
4258 && matches!(target, DialectType::TSQL | DialectType::Fabric)
4259 {
4260 Self::collect_tsql_grouping_tuple_nodes(expr)
4261 } else {
4262 HashSet::new()
4263 };
4264
4265 for node in expr.dfs() {
4266 if matches!(target, DialectType::Fabric | DialectType::Hive)
4267 && Self::node_has_recursive_with(node)
4268 {
4269 Self::push_unsupported_diagnostic(&mut diagnostics, "recursive CTEs");
4270 }
4271
4272 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4273 && Self::node_has_lateral(node)
4274 {
4275 Self::push_unsupported_diagnostic(&mut diagnostics, "LATERAL joins and subqueries");
4276 }
4277
4278 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4279 if Self::node_has_join_using(node) {
4280 Self::push_unsupported_diagnostic(&mut diagnostics, "JOIN USING clauses");
4281 }
4282 if Self::node_has_natural_join(node) {
4283 Self::push_unsupported_diagnostic(&mut diagnostics, "NATURAL JOIN");
4284 }
4285 if Self::node_has_unsupported_relation_column_aliases(node) {
4286 Self::push_unsupported_diagnostic(
4287 &mut diagnostics,
4288 "column alias lists on base or joined table references",
4289 );
4290 }
4291 if Self::node_has_qualified_whole_row_aggregate_argument(node) {
4292 Self::push_unsupported_diagnostic(
4293 &mut diagnostics,
4294 "qualified whole-row aggregate arguments",
4295 );
4296 }
4297 }
4298
4299 if !Self::target_supports_distinct_on(target) && Self::node_has_distinct_on(node) {
4300 Self::push_unsupported_diagnostic(&mut diagnostics, "DISTINCT ON");
4301 }
4302
4303 if !Self::target_supports_remaining_unnest(target) && Self::node_is_unnest(node) {
4304 Self::push_unsupported_diagnostic(&mut diagnostics, "UNNEST");
4305 }
4306
4307 if !Self::target_supports_remaining_explode(target) && Self::node_is_explode(node) {
4308 Self::push_unsupported_diagnostic(&mut diagnostics, "EXPLODE");
4309 }
4310
4311 if Self::target_lacks_array_agg(target) && Self::node_is_array_agg(node) {
4312 Self::push_unsupported_diagnostic(&mut diagnostics, "ARRAY_AGG");
4313 }
4314
4315 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4316 && Self::node_is_distinct_string_agg(node)
4317 {
4318 Self::push_unsupported_diagnostic(&mut diagnostics, "STRING_AGG with DISTINCT");
4319 }
4320
4321 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4322 && matches!(node, Expression::NthValue(_))
4323 {
4324 Self::push_unsupported_diagnostic(&mut diagnostics, "NTH_VALUE");
4325 }
4326
4327 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4328 if let Some(frame) = Self::node_window_frame(node) {
4329 if matches!(frame.kind, WindowFrameKind::Groups) {
4330 Self::push_unsupported_diagnostic(&mut diagnostics, "GROUPS window frames");
4331 }
4332 if matches!(frame.kind, WindowFrameKind::Range)
4333 && (Self::window_frame_bound_has_value_offset(&frame.start)
4334 || frame
4335 .end
4336 .as_ref()
4337 .is_some_and(Self::window_frame_bound_has_value_offset))
4338 {
4339 Self::push_unsupported_diagnostic(
4340 &mut diagnostics,
4341 "value-offset RANGE window frames",
4342 );
4343 }
4344 if frame.exclude.is_some() {
4345 Self::push_unsupported_diagnostic(
4346 &mut diagnostics,
4347 "window frame EXCLUDE clauses",
4348 );
4349 }
4350 }
4351 }
4352
4353 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4354 && Self::node_is_regex_predicate(node)
4355 {
4356 Self::push_unsupported_diagnostic(
4357 &mut diagnostics,
4358 "regular expression predicates",
4359 );
4360 }
4361
4362 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4363 && Self::node_is_non_subquery_any(node)
4364 {
4365 Self::push_unsupported_diagnostic(
4366 &mut diagnostics,
4367 "ANY over non-subquery expressions",
4368 );
4369 }
4370
4371 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4372 && Self::node_is_row_value_subquery_comparison(node)
4373 {
4374 Self::push_unsupported_diagnostic(
4375 &mut diagnostics,
4376 "row-value subquery comparisons",
4377 );
4378 }
4379
4380 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4381 && Self::node_is_row_value_values_membership(node)
4382 {
4383 Self::push_unsupported_diagnostic(
4384 &mut diagnostics,
4385 "row-value VALUES membership comparisons",
4386 );
4387 }
4388
4389 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4390 && Self::node_has_fetch_with_ties(node)
4391 {
4392 Self::push_unsupported_diagnostic(&mut diagnostics, "FETCH WITH TIES without TOP");
4393 }
4394
4395 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4396 && Self::node_is_overlaps(node)
4397 {
4398 Self::push_unsupported_diagnostic(&mut diagnostics, "OVERLAPS");
4399 }
4400
4401 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4402 && Self::node_is_date_bin(node)
4403 {
4404 Self::push_unsupported_diagnostic(&mut diagnostics, "DATE_BIN");
4405 }
4406
4407 if source == DialectType::PostgreSQL
4408 && matches!(target, DialectType::TSQL | DialectType::Fabric)
4409 && Self::node_is_unresolved_postgres_date_subtraction(node)
4410 {
4411 Self::push_unsupported_diagnostic(
4412 &mut diagnostics,
4413 "PostgreSQL date subtraction with an unresolved column type",
4414 );
4415 }
4416
4417 if matches!(source, DialectType::PostgreSQL | DialectType::CockroachDB)
4418 && !matches!(target, DialectType::PostgreSQL | DialectType::CockroachDB)
4419 {
4420 if Self::node_is_postgres_json_build_object(node)
4421 && !(matches!(target, DialectType::TSQL | DialectType::Fabric)
4422 && Self::postgres_json_build_object_can_lower_to_json_object(node))
4423 {
4424 Self::push_unsupported_diagnostic(
4425 &mut diagnostics,
4426 "PostgreSQL JSON_BUILD_OBJECT",
4427 );
4428 }
4429 if Self::node_is_function_named(node, "TO_TSVECTOR") {
4430 Self::push_unsupported_diagnostic(&mut diagnostics, "PostgreSQL TO_TSVECTOR");
4431 }
4432 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4433 if let Some(composite_semantics) =
4434 Self::postgres_tsql_unsupported_composite_semantics(
4435 node,
4436 structural_grouping_tuples.contains(&(node as *const Expression)),
4437 )
4438 {
4439 Self::push_unsupported_diagnostic(
4440 &mut diagnostics,
4441 &format!("PostgreSQL {composite_semantics}"),
4442 );
4443 }
4444 if Self::node_is_postgres_unknown_cast(node) {
4445 Self::push_unsupported_diagnostic(
4446 &mut diagnostics,
4447 "PostgreSQL unresolved UNKNOWN casts",
4448 );
4449 }
4450 if let Some(collation_name) =
4451 Self::postgres_tsql_unsupported_collation_name(node)
4452 {
4453 Self::push_unsupported_diagnostic(
4454 &mut diagnostics,
4455 &format!("PostgreSQL collation \"{collation_name}\""),
4456 );
4457 }
4458 if let Some(array_semantics) =
4459 Self::postgres_tsql_unsupported_array_semantics(node)
4460 {
4461 Self::push_unsupported_diagnostic(
4462 &mut diagnostics,
4463 &format!("PostgreSQL {array_semantics}"),
4464 );
4465 }
4466 if let Some(string_semantics) =
4467 Self::postgres_tsql_unsupported_string_semantics(node)
4468 {
4469 Self::push_unsupported_diagnostic(
4470 &mut diagnostics,
4471 &format!("PostgreSQL {string_semantics}"),
4472 );
4473 }
4474 if source == DialectType::PostgreSQL {
4475 if let Some(binary_semantics) =
4476 Self::postgres_tsql_unsupported_binary_semantics(node)
4477 {
4478 Self::push_unsupported_diagnostic(
4479 &mut diagnostics,
4480 &format!("PostgreSQL {binary_semantics}"),
4481 );
4482 }
4483 }
4484 if let Some(function_name) =
4485 Self::postgres_tsql_unsupported_function_name(node, target)
4486 {
4487 Self::push_unsupported_diagnostic(
4488 &mut diagnostics,
4489 &format!("PostgreSQL {function_name}"),
4490 );
4491 }
4492 }
4493 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4494 && Self::node_is_postgres_type_function_cast(node)
4495 {
4496 Self::push_unsupported_diagnostic(
4497 &mut diagnostics,
4498 "PostgreSQL type-name function casts",
4499 );
4500 }
4501 }
4502
4503 if opts.unsupported_level == UnsupportedLevel::Immediate && !diagnostics.is_empty() {
4504 break;
4505 }
4506 }
4507
4508 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4509 Self::collect_tsql_unsupported_ordered_sets(expr, &mut diagnostics);
4510 Self::collect_tsql_windows_missing_order(expr, &HashMap::new(), &mut diagnostics);
4511 }
4512
4513 if diagnostics.is_empty() {
4514 return Ok(());
4515 }
4516
4517 let limit = if opts.unsupported_level == UnsupportedLevel::Immediate {
4518 1
4519 } else {
4520 opts.max_unsupported.max(1)
4521 };
4522 let mut messages = diagnostics.iter().take(limit).cloned().collect::<Vec<_>>();
4523 if diagnostics.len() > limit {
4524 messages.push(format!("... and {} more", diagnostics.len() - limit));
4525 }
4526
4527 Err(crate::error::Error::unsupported(
4528 messages.join("; "),
4529 target.to_string(),
4530 ))
4531 }
4532
4533 fn reject_postgres_tsql_strict_regex_predicates(
4534 expr: &Expression,
4535 source: DialectType,
4536 target: DialectType,
4537 opts: &TranspileOptions,
4538 ) -> Result<()> {
4539 if !matches!(
4540 opts.unsupported_level,
4541 UnsupportedLevel::Raise | UnsupportedLevel::Immediate
4542 ) || !matches!(source, DialectType::PostgreSQL | DialectType::CockroachDB)
4543 || !matches!(target, DialectType::TSQL | DialectType::Fabric)
4544 {
4545 return Ok(());
4546 }
4547
4548 if expr.dfs().any(Self::node_is_regex_predicate) {
4549 return Err(crate::error::Error::unsupported(
4550 "regular expression predicates",
4551 target.to_string(),
4552 ));
4553 }
4554
4555 Ok(())
4556 }
4557
4558 fn reject_tsql_strict_json_constructor_return_types(
4559 expr: &Expression,
4560 source: DialectType,
4561 target: DialectType,
4562 opts: &TranspileOptions,
4563 ) -> Result<()> {
4564 if !matches!(
4565 opts.unsupported_level,
4566 UnsupportedLevel::Raise | UnsupportedLevel::Immediate
4567 ) || source == target
4568 || !matches!(target, DialectType::TSQL | DialectType::Fabric)
4569 {
4570 return Ok(());
4571 }
4572
4573 let mut diagnostics = Vec::new();
4574 for node in expr.dfs() {
4575 if let Some(return_type) =
4576 normalization::unsupported_tsql_json_constructor_return_type(node)
4577 {
4578 let message =
4579 format!("SQL/JSON constructor RETURNING {return_type} cannot be preserved");
4580 Self::push_unsupported_diagnostic(&mut diagnostics, &message);
4581 if opts.unsupported_level == UnsupportedLevel::Immediate {
4582 break;
4583 }
4584 }
4585 }
4586
4587 if diagnostics.is_empty() {
4588 return Ok(());
4589 }
4590
4591 let limit = if opts.unsupported_level == UnsupportedLevel::Immediate {
4592 1
4593 } else {
4594 opts.max_unsupported.max(1)
4595 };
4596 let mut messages = diagnostics.iter().take(limit).cloned().collect::<Vec<_>>();
4597 if diagnostics.len() > limit {
4598 messages.push(format!("... and {} more", diagnostics.len() - limit));
4599 }
4600
4601 Err(crate::error::Error::unsupported(
4602 messages.join("; "),
4603 target.to_string(),
4604 ))
4605 }
4606
4607 fn reject_postgres_tsql_strict_json_aggregate_modifiers(
4608 expr: &Expression,
4609 source: DialectType,
4610 target: DialectType,
4611 opts: &TranspileOptions,
4612 ) -> Result<()> {
4613 if !matches!(
4614 opts.unsupported_level,
4615 UnsupportedLevel::Raise | UnsupportedLevel::Immediate
4616 ) || !matches!(source, DialectType::PostgreSQL | DialectType::CockroachDB)
4617 || !matches!(target, DialectType::TSQL | DialectType::Fabric)
4618 {
4619 return Ok(());
4620 }
4621
4622 let mut diagnostics = Vec::new();
4623 for node in expr.dfs() {
4624 match node {
4625 Expression::Function(function)
4626 if !function.quoted
4627 && matches!(
4628 function.name.to_ascii_uppercase().as_str(),
4629 "JSON_AGG" | "JSONB_AGG"
4630 ) =>
4631 {
4632 let name = function.name.to_ascii_uppercase();
4633 if function.args.len() != 1 {
4634 Self::push_unsupported_diagnostic(
4635 &mut diagnostics,
4636 &format!("PostgreSQL {name} with invalid argument count"),
4637 );
4638 }
4639 if function.distinct {
4640 Self::push_unsupported_diagnostic(
4641 &mut diagnostics,
4642 &format!("PostgreSQL {name} with DISTINCT"),
4643 );
4644 }
4645 }
4646 Expression::AggregateFunction(function)
4647 if matches!(
4648 function.name.to_ascii_uppercase().as_str(),
4649 "JSON_AGG" | "JSONB_AGG"
4650 ) =>
4651 {
4652 let name = function.name.to_ascii_uppercase();
4653 if function.args.len() != 1 {
4654 Self::push_unsupported_diagnostic(
4655 &mut diagnostics,
4656 &format!("PostgreSQL {name} with invalid argument count"),
4657 );
4658 }
4659 if function.distinct {
4660 Self::push_unsupported_diagnostic(
4661 &mut diagnostics,
4662 &format!("PostgreSQL {name} with DISTINCT"),
4663 );
4664 }
4665 if function.filter.is_some() {
4666 Self::push_unsupported_diagnostic(
4667 &mut diagnostics,
4668 &format!("PostgreSQL {name} with FILTER"),
4669 );
4670 }
4671 if function.limit.is_some() || function.ignore_nulls.is_some() {
4672 Self::push_unsupported_diagnostic(
4673 &mut diagnostics,
4674 &format!("PostgreSQL {name} with unsupported aggregate modifiers"),
4675 );
4676 }
4677 }
4678 Expression::Filter(filter) => {
4679 if let Some(name) = Self::postgres_json_aggregate_name(&filter.this) {
4680 Self::push_unsupported_diagnostic(
4681 &mut diagnostics,
4682 &format!("PostgreSQL {name} with FILTER"),
4683 );
4684 }
4685 }
4686 _ => {}
4687 }
4688
4689 if opts.unsupported_level == UnsupportedLevel::Immediate && !diagnostics.is_empty() {
4690 break;
4691 }
4692 }
4693
4694 if diagnostics.is_empty() {
4695 return Ok(());
4696 }
4697
4698 let limit = if opts.unsupported_level == UnsupportedLevel::Immediate {
4699 1
4700 } else {
4701 opts.max_unsupported.max(1)
4702 };
4703 let mut messages = diagnostics.iter().take(limit).cloned().collect::<Vec<_>>();
4704 if diagnostics.len() > limit {
4705 messages.push(format!("... and {} more", diagnostics.len() - limit));
4706 }
4707
4708 Err(crate::error::Error::unsupported(
4709 messages.join("; "),
4710 target.to_string(),
4711 ))
4712 }
4713
4714 fn postgres_json_aggregate_name(expr: &Expression) -> Option<String> {
4715 let name = match expr {
4716 Expression::Function(function) if !function.quoted => &function.name,
4717 Expression::AggregateFunction(function) => &function.name,
4718 _ => return None,
4719 };
4720 let name = name.to_ascii_uppercase();
4721 matches!(name.as_str(), "JSON_AGG" | "JSONB_AGG").then_some(name)
4722 }
4723
4724 fn push_unsupported_diagnostic(diagnostics: &mut Vec<String>, message: &str) {
4725 if !diagnostics.iter().any(|existing| existing == message) {
4726 diagnostics.push(message.to_string());
4727 }
4728 }
4729
4730 fn node_is_unresolved_postgres_date_subtraction(expr: &Expression) -> bool {
4731 let Expression::Sub(op) = expr else {
4732 return false;
4733 };
4734
4735 (Self::is_explicit_date_expr(&op.left) && Self::is_column_expr(&op.right))
4736 || (Self::is_column_expr(&op.left) && Self::is_explicit_date_expr(&op.right))
4737 }
4738
4739 fn is_column_expr(expr: &Expression) -> bool {
4740 match expr {
4741 Expression::Column(_) => true,
4742 Expression::Paren(paren) => Self::is_column_expr(&paren.this),
4743 _ => false,
4744 }
4745 }
4746
4747 fn node_window_frame(expr: &Expression) -> Option<&WindowFrame> {
4748 match expr {
4749 Expression::WindowFunction(window) => window.over.frame.as_ref(),
4750 Expression::Window(window) | Expression::WindowSpec(window) => window.frame.as_ref(),
4751 _ => None,
4752 }
4753 }
4754
4755 fn window_frame_bound_has_value_offset(bound: &WindowFrameBound) -> bool {
4756 matches!(
4757 bound,
4758 WindowFrameBound::Preceding(_)
4759 | WindowFrameBound::Following(_)
4760 | WindowFrameBound::Value(_)
4761 | WindowFrameBound::BarePreceding
4762 | WindowFrameBound::BareFollowing
4763 )
4764 }
4765
4766 fn collect_tsql_windows_missing_order(
4767 expr: &Expression,
4768 active_windows: &HashMap<String, Over>,
4769 diagnostics: &mut Vec<String>,
4770 ) {
4771 if let Expression::Select(select) = expr {
4772 let local_windows = select
4773 .windows
4774 .as_ref()
4775 .map(|windows| {
4776 windows
4777 .iter()
4778 .map(|window| (window.name.name.to_ascii_lowercase(), window.spec.clone()))
4779 .collect()
4780 })
4781 .unwrap_or_default();
4782
4783 for child in expr.children() {
4784 Self::collect_tsql_windows_missing_order(child, &local_windows, diagnostics);
4785 }
4786 return;
4787 }
4788
4789 if let Expression::WindowFunction(window) = expr {
4790 let (has_order, has_frame) = Self::effective_window_order_and_frame(
4791 &window.over,
4792 active_windows,
4793 &mut Vec::new(),
4794 );
4795
4796 if !has_order {
4797 if has_frame {
4798 Self::push_unsupported_diagnostic(
4799 diagnostics,
4800 "window frames without ORDER BY",
4801 );
4802 }
4803 if let Some(function_name) =
4804 Self::tsql_window_function_requiring_order(&window.this)
4805 {
4806 Self::push_unsupported_diagnostic(
4807 diagnostics,
4808 &format!("{function_name} without ORDER BY"),
4809 );
4810 }
4811 }
4812 }
4813
4814 for child in expr.children() {
4815 Self::collect_tsql_windows_missing_order(child, active_windows, diagnostics);
4816 }
4817 }
4818
4819 fn effective_window_order_and_frame(
4820 over: &Over,
4821 active_windows: &HashMap<String, Over>,
4822 seen: &mut Vec<String>,
4823 ) -> (bool, bool) {
4824 let inherited = over
4825 .window_name
4826 .as_ref()
4827 .and_then(|name| {
4828 let key = name.name.to_ascii_lowercase();
4829 if seen.iter().any(|seen_name| seen_name == &key) {
4830 return None;
4831 }
4832 let named = active_windows.get(&key)?;
4833 seen.push(key);
4834 let properties =
4835 Self::effective_window_order_and_frame(named, active_windows, seen);
4836 seen.pop();
4837 Some(properties)
4838 })
4839 .unwrap_or((false, false));
4840
4841 (
4842 !over.order_by.is_empty() || inherited.0,
4843 over.frame.is_some() || inherited.1,
4844 )
4845 }
4846
4847 fn tsql_window_function_requiring_order(expr: &Expression) -> Option<&'static str> {
4848 match expr {
4849 Expression::FirstValue(_) => Some("FIRST_VALUE"),
4850 Expression::LastValue(_) => Some("LAST_VALUE"),
4851 Expression::Function(function) if function.name.eq_ignore_ascii_case("FIRST_VALUE") => {
4852 Some("FIRST_VALUE")
4853 }
4854 Expression::Function(function) if function.name.eq_ignore_ascii_case("LAST_VALUE") => {
4855 Some("LAST_VALUE")
4856 }
4857 _ => None,
4858 }
4859 }
4860
4861 fn collect_tsql_unsupported_ordered_sets(expr: &Expression, diagnostics: &mut Vec<String>) {
4862 match expr {
4863 Expression::WindowFunction(window) => {
4864 if let Expression::WithinGroup(within_group) = &window.this {
4865 if Self::within_group_is_hypothetical_set(within_group) {
4866 Self::push_unsupported_diagnostic(
4867 diagnostics,
4868 "RANK/DENSE_RANK/CUME_DIST/PERCENT_RANK hypothetical-set aggregates",
4869 );
4870 return;
4871 }
4872
4873 if Self::within_group_is_mode(within_group) {
4874 Self::push_unsupported_diagnostic(
4875 diagnostics,
4876 "MODE ordered-set aggregates",
4877 );
4878 return;
4879 }
4880
4881 if Self::within_group_is_percentile(within_group) {
4882 if !window.over.order_by.is_empty() || window.over.frame.is_some() {
4883 Self::push_unsupported_diagnostic(
4884 diagnostics,
4885 "PERCENTILE_CONT/PERCENTILE_DISC window ORDER BY or frame clauses",
4886 );
4887 }
4888 return;
4889 }
4890 }
4891 }
4892 Expression::WithinGroup(within_group) => {
4893 if Self::within_group_is_hypothetical_set(within_group) {
4894 Self::push_unsupported_diagnostic(
4895 diagnostics,
4896 "RANK/DENSE_RANK/CUME_DIST/PERCENT_RANK hypothetical-set aggregates",
4897 );
4898 return;
4899 }
4900
4901 if Self::within_group_is_mode(within_group) {
4902 Self::push_unsupported_diagnostic(diagnostics, "MODE ordered-set aggregates");
4903 return;
4904 }
4905
4906 if Self::within_group_is_percentile(within_group) {
4907 Self::push_unsupported_diagnostic(
4908 diagnostics,
4909 "PERCENTILE_CONT/PERCENTILE_DISC ordered-set aggregates without OVER",
4910 );
4911 return;
4912 }
4913 }
4914 _ => {}
4915 }
4916
4917 for child in expr.children() {
4918 Self::collect_tsql_unsupported_ordered_sets(child, diagnostics);
4919 }
4920 }
4921
4922 fn within_group_is_hypothetical_set(within_group: &crate::expressions::WithinGroup) -> bool {
4923 match &within_group.this {
4924 Expression::Function(function) => Self::is_hypothetical_set_name(&function.name),
4925 Expression::AggregateFunction(function) => {
4926 Self::is_hypothetical_set_name(&function.name)
4927 }
4928 Expression::Rank(_)
4929 | Expression::DenseRank(_)
4930 | Expression::CumeDist(_)
4931 | Expression::PercentRank(_) => true,
4932 _ => false,
4933 }
4934 }
4935
4936 fn within_group_is_percentile(within_group: &crate::expressions::WithinGroup) -> bool {
4937 match &within_group.this {
4938 Expression::Function(function) => Self::is_percentile_ordered_set_name(&function.name),
4939 Expression::AggregateFunction(function) => {
4940 Self::is_percentile_ordered_set_name(&function.name)
4941 }
4942 Expression::PercentileCont(_) | Expression::PercentileDisc(_) => true,
4943 _ => false,
4944 }
4945 }
4946
4947 fn within_group_is_mode(within_group: &crate::expressions::WithinGroup) -> bool {
4948 match &within_group.this {
4949 Expression::Function(function) => function.name.eq_ignore_ascii_case("MODE"),
4950 Expression::AggregateFunction(function) => function.name.eq_ignore_ascii_case("MODE"),
4951 Expression::Mode(_) => true,
4952 _ => false,
4953 }
4954 }
4955
4956 fn is_percentile_ordered_set_name(name: &str) -> bool {
4957 name.eq_ignore_ascii_case("PERCENTILE_CONT") || name.eq_ignore_ascii_case("PERCENTILE_DISC")
4958 }
4959
4960 fn is_hypothetical_set_name(name: &str) -> bool {
4961 name.eq_ignore_ascii_case("RANK")
4962 || name.eq_ignore_ascii_case("DENSE_RANK")
4963 || name.eq_ignore_ascii_case("CUME_DIST")
4964 || name.eq_ignore_ascii_case("PERCENT_RANK")
4965 }
4966
4967 fn target_supports_distinct_on(target: DialectType) -> bool {
4968 matches!(target, DialectType::PostgreSQL | DialectType::DuckDB)
4969 }
4970
4971 fn node_has_distinct_on(expr: &Expression) -> bool {
4972 matches!(
4973 expr,
4974 Expression::Select(select)
4975 if select
4976 .distinct_on
4977 .as_ref()
4978 .is_some_and(|distinct_on| !distinct_on.is_empty())
4979 )
4980 }
4981
4982 fn node_has_recursive_with(expr: &Expression) -> bool {
4983 fn recursive(with: &Option<With>) -> bool {
4984 with.as_ref().is_some_and(|with| with.recursive)
4985 }
4986
4987 match expr {
4988 Expression::With(with) => with.recursive,
4989 Expression::Select(select) => recursive(&select.with),
4990 Expression::Union(union) => recursive(&union.with),
4991 Expression::Intersect(intersect) => recursive(&intersect.with),
4992 Expression::Except(except) => recursive(&except.with),
4993 Expression::Pivot(pivot) => recursive(&pivot.with),
4994 Expression::Insert(insert) => recursive(&insert.with),
4995 Expression::Update(update) => recursive(&update.with),
4996 Expression::Delete(delete) => recursive(&delete.with),
4997 _ => false,
4998 }
4999 }
5000
5001 fn node_has_lateral(expr: &Expression) -> bool {
5002 fn join_has_lateral(join: &Join) -> bool {
5003 matches!(
5004 join.kind,
5005 crate::expressions::JoinKind::Lateral | crate::expressions::JoinKind::LeftLateral
5006 ) || Dialect::node_has_lateral(&join.this)
5007 || join.on.as_ref().is_some_and(Dialect::node_has_lateral)
5008 || join
5009 .match_condition
5010 .as_ref()
5011 .is_some_and(Dialect::node_has_lateral)
5012 || join.pivots.iter().any(Dialect::node_has_lateral)
5013 }
5014
5015 fn joins_have_lateral(joins: &[Join]) -> bool {
5016 joins.iter().any(join_has_lateral)
5017 }
5018
5019 match expr {
5020 Expression::Subquery(subquery) => {
5021 subquery.lateral || Dialect::node_has_lateral(&subquery.this)
5022 }
5023 Expression::Lateral(_) | Expression::LateralView(_) => true,
5024 Expression::Join(join) => join_has_lateral(join),
5025 Expression::Select(select) => {
5026 !select.lateral_views.is_empty()
5027 || joins_have_lateral(&select.joins)
5028 || select
5029 .from
5030 .as_ref()
5031 .is_some_and(|from| from.expressions.iter().any(Dialect::node_has_lateral))
5032 }
5033 Expression::JoinedTable(joined) => {
5034 !joined.lateral_views.is_empty()
5035 || Dialect::node_has_lateral(&joined.left)
5036 || joins_have_lateral(&joined.joins)
5037 }
5038 Expression::Update(update) => {
5039 joins_have_lateral(&update.table_joins) || joins_have_lateral(&update.from_joins)
5040 }
5041 _ => false,
5042 }
5043 }
5044
5045 fn node_has_join_using(expr: &Expression) -> bool {
5046 fn has_using(joins: &[Join]) -> bool {
5047 joins.iter().any(|join| !join.using.is_empty())
5048 }
5049
5050 match expr {
5051 Expression::Join(join) => !join.using.is_empty(),
5052 Expression::Select(select) => has_using(&select.joins),
5053 Expression::JoinedTable(joined) => has_using(&joined.joins),
5054 Expression::Update(update) => {
5055 has_using(&update.table_joins) || has_using(&update.from_joins)
5056 }
5057 Expression::Delete(delete) => has_using(&delete.joins),
5058 _ => false,
5059 }
5060 }
5061
5062 fn node_has_natural_join(expr: &Expression) -> bool {
5063 fn is_natural(join: &Join) -> bool {
5064 matches!(
5065 join.kind,
5066 crate::expressions::JoinKind::Natural
5067 | crate::expressions::JoinKind::NaturalLeft
5068 | crate::expressions::JoinKind::NaturalRight
5069 | crate::expressions::JoinKind::NaturalFull
5070 )
5071 }
5072
5073 fn has_natural(joins: &[Join]) -> bool {
5074 joins.iter().any(is_natural)
5075 }
5076
5077 match expr {
5078 Expression::Join(join) => is_natural(join),
5079 Expression::Select(select) => has_natural(&select.joins),
5080 Expression::JoinedTable(joined) => has_natural(&joined.joins),
5081 Expression::Update(update) => {
5082 has_natural(&update.table_joins) || has_natural(&update.from_joins)
5083 }
5084 Expression::Delete(delete) => has_natural(&delete.joins),
5085 _ => false,
5086 }
5087 }
5088
5089 fn node_has_unsupported_relation_column_aliases(expr: &Expression) -> bool {
5090 match expr {
5091 Expression::Table(table) => !table.column_aliases.is_empty(),
5092 Expression::Alias(alias) => {
5093 !alias.column_aliases.is_empty()
5094 && matches!(
5095 alias.this,
5096 Expression::Table(_) | Expression::JoinedTable(_)
5097 )
5098 }
5099 _ => false,
5100 }
5101 }
5102
5103 fn node_is_aggregate_function(expr: &Expression) -> bool {
5104 matches!(
5105 expr,
5106 Expression::AggregateFunction(_)
5107 | Expression::Count(_)
5108 | Expression::Sum(_)
5109 | Expression::Avg(_)
5110 | Expression::Min(_)
5111 | Expression::Max(_)
5112 | Expression::GroupConcat(_)
5113 | Expression::StringAgg(_)
5114 | Expression::ListAgg(_)
5115 | Expression::ArrayAgg(_)
5116 | Expression::CountIf(_)
5117 | Expression::SumIf(_)
5118 | Expression::Stddev(_)
5119 | Expression::StddevPop(_)
5120 | Expression::StddevSamp(_)
5121 | Expression::Variance(_)
5122 | Expression::VarPop(_)
5123 | Expression::VarSamp(_)
5124 | Expression::Median(_)
5125 | Expression::Mode(_)
5126 | Expression::First(_)
5127 | Expression::Last(_)
5128 | Expression::AnyValue(_)
5129 | Expression::ApproxDistinct(_)
5130 | Expression::ApproxCountDistinct(_)
5131 | Expression::ApproxPercentile(_)
5132 | Expression::Percentile(_)
5133 | Expression::LogicalAnd(_)
5134 | Expression::LogicalOr(_)
5135 | Expression::Skewness(_)
5136 | Expression::BitwiseCount(_)
5137 | Expression::BitwiseAndAgg(_)
5138 | Expression::BitwiseOrAgg(_)
5139 | Expression::BitwiseXorAgg(_)
5140 | Expression::ArrayConcatAgg(_)
5141 | Expression::ArrayUniqueAgg(_)
5142 | Expression::BoolXorAgg(_)
5143 | Expression::JsonArrayAgg(_)
5144 | Expression::JsonObjectAgg(_)
5145 | Expression::ParameterizedAgg(_)
5146 | Expression::ArgMax(_)
5147 | Expression::ArgMin(_)
5148 | Expression::ApproxTopK(_)
5149 | Expression::ApproxTopKAccumulate(_)
5150 | Expression::ApproxTopKCombine(_)
5151 | Expression::ApproxTopKEstimate(_)
5152 | Expression::ApproxTopSum(_)
5153 | Expression::ApproxQuantiles(_)
5154 | Expression::AnonymousAggFunc(_)
5155 | Expression::CombinedAggFunc(_)
5156 | Expression::CombinedParameterizedAgg(_)
5157 | Expression::HashAgg(_)
5158 | Expression::ObjectAgg(_)
5159 | Expression::AIAgg(_)
5160 )
5161 }
5162
5163 fn node_has_qualified_whole_row_aggregate_argument(expr: &Expression) -> bool {
5164 fn contains_qualified_star(expr: &Expression) -> bool {
5165 match expr {
5166 Expression::Star(star) => star.table.is_some(),
5167 Expression::Select(_)
5170 | Expression::Subquery(_)
5171 | Expression::Union(_)
5172 | Expression::Intersect(_)
5173 | Expression::Except(_) => false,
5174 _ => expr.children().into_iter().any(contains_qualified_star),
5175 }
5176 }
5177
5178 Self::node_is_aggregate_function(expr)
5179 && expr.children().into_iter().any(contains_qualified_star)
5180 }
5181
5182 fn tsql_apply_has_invalid_outer_aggregate(expr: &Expression) -> bool {
5183 fn collect_source_names(expr: &Expression, names: &mut HashSet<String>) {
5186 let mut insert = |name: &Identifier| {
5187 if !name.name.is_empty() {
5188 names.insert(name.name.to_ascii_lowercase());
5189 }
5190 };
5191
5192 match expr {
5193 Expression::Table(table) => {
5194 insert(table.alias.as_ref().unwrap_or(&table.name));
5195 }
5196 Expression::Subquery(subquery) => {
5197 if let Some(alias) = &subquery.alias {
5198 insert(alias);
5199 }
5200 }
5201 Expression::Alias(alias) => insert(&alias.alias),
5202 Expression::JoinedTable(joined) => {
5203 if let Some(alias) = &joined.alias {
5204 insert(alias);
5205 } else {
5206 collect_source_names(&joined.left, names);
5207 for join in &joined.joins {
5208 collect_source_names(&join.this, names);
5209 }
5210 }
5211 }
5212 Expression::Paren(paren) => collect_source_names(&paren.this, names),
5213 Expression::Pivot(pivot) => {
5214 if let Some(alias) = &pivot.alias {
5215 insert(alias);
5216 } else {
5217 collect_source_names(&pivot.this, names);
5218 }
5219 }
5220 Expression::Unpivot(unpivot) => {
5221 if let Some(alias) = &unpivot.alias {
5222 insert(alias);
5223 } else {
5224 collect_source_names(&unpivot.this, names);
5225 }
5226 }
5227 _ => {}
5228 }
5229 }
5230
5231 fn collect_columns<'a>(
5232 expr: &'a Expression,
5233 columns: &mut Vec<&'a crate::expressions::Column>,
5234 ) {
5235 match expr {
5236 Expression::Column(column) => columns.push(column),
5237 Expression::Select(_)
5240 | Expression::Subquery(_)
5241 | Expression::Union(_)
5242 | Expression::Intersect(_)
5243 | Expression::Except(_) => {}
5244 _ => {
5245 for child in expr.children() {
5246 collect_columns(child, columns);
5247 }
5248 }
5249 }
5250 }
5251
5252 fn same_column(
5253 left: &crate::expressions::Column,
5254 right: &crate::expressions::Column,
5255 ) -> bool {
5256 let same_identifier =
5257 |left: &Identifier, right: &Identifier| left.name.eq_ignore_ascii_case(&right.name);
5258
5259 same_identifier(&left.name, &right.name)
5260 && match (&left.table, &right.table) {
5261 (Some(left), Some(right)) => same_identifier(left, right),
5262 (None, None) => true,
5263 _ => false,
5264 }
5265 }
5266
5267 fn aggregate_is_invalid(expr: &Expression, local_sources: &HashSet<String>) -> bool {
5268 let mut columns = Vec::new();
5269 collect_columns(expr, &mut columns);
5270
5271 let outer_column = columns.iter().copied().find(|column| match &column.table {
5272 Some(table) => !local_sources.contains(&table.name.to_ascii_lowercase()),
5273 None => local_sources.is_empty(),
5276 });
5277
5278 outer_column
5279 .is_some_and(|outer| columns.iter().any(|column| !same_column(outer, column)))
5280 }
5281
5282 fn expression_has_invalid_aggregate(
5283 expr: &Expression,
5284 local_sources: &HashSet<String>,
5285 ) -> bool {
5286 if Dialect::node_is_aggregate_function(expr)
5287 && aggregate_is_invalid(expr, local_sources)
5288 {
5289 return true;
5290 }
5291
5292 match expr {
5293 Expression::Select(_)
5294 | Expression::Subquery(_)
5295 | Expression::Union(_)
5296 | Expression::Intersect(_)
5297 | Expression::Except(_) => false,
5298 _ => expr
5299 .children()
5300 .into_iter()
5301 .any(|child| expression_has_invalid_aggregate(child, local_sources)),
5302 }
5303 }
5304
5305 fn select_has_invalid_aggregate(select: &Select) -> bool {
5306 let mut local_sources = HashSet::new();
5307 if let Some(from) = &select.from {
5308 for source in &from.expressions {
5309 collect_source_names(source, &mut local_sources);
5310 }
5311 }
5312 for join in &select.joins {
5313 collect_source_names(&join.this, &mut local_sources);
5314 }
5315
5316 let invalid =
5317 |expr: &Expression| expression_has_invalid_aggregate(expr, &local_sources);
5318
5319 select.expressions.iter().any(invalid)
5320 || select.prewhere.as_ref().is_some_and(invalid)
5321 || select
5322 .where_clause
5323 .as_ref()
5324 .is_some_and(|where_clause| invalid(&where_clause.this))
5325 || select
5326 .group_by
5327 .as_ref()
5328 .is_some_and(|group_by| group_by.expressions.iter().any(invalid))
5329 || select
5330 .having
5331 .as_ref()
5332 .is_some_and(|having| invalid(&having.this))
5333 || select
5334 .qualify
5335 .as_ref()
5336 .is_some_and(|qualify| invalid(&qualify.this))
5337 || select.order_by.as_ref().is_some_and(|order_by| {
5338 order_by
5339 .expressions
5340 .iter()
5341 .any(|ordered| invalid(&ordered.this))
5342 })
5343 }
5344
5345 fn apply_rhs_is_invalid(rhs: &Expression) -> bool {
5346 rhs.dfs().any(|node| match node {
5347 Expression::Select(select) => select_has_invalid_aggregate(select),
5348 _ => false,
5349 })
5350 }
5351
5352 fn joins_have_invalid_aggregate(joins: &[Join]) -> bool {
5353 joins.iter().any(|join| {
5354 matches!(
5355 join.kind,
5356 crate::expressions::JoinKind::CrossApply
5357 | crate::expressions::JoinKind::OuterApply
5358 ) && apply_rhs_is_invalid(&join.this)
5359 })
5360 }
5361
5362 expr.dfs().any(|node| match node {
5363 Expression::Select(select) => joins_have_invalid_aggregate(&select.joins),
5364 Expression::JoinedTable(joined) => joins_have_invalid_aggregate(&joined.joins),
5365 Expression::Update(update) => {
5366 joins_have_invalid_aggregate(&update.table_joins)
5367 || joins_have_invalid_aggregate(&update.from_joins)
5368 }
5369 Expression::Delete(delete) => joins_have_invalid_aggregate(&delete.joins),
5370 _ => false,
5371 })
5372 }
5373
5374 fn target_supports_remaining_unnest(target: DialectType) -> bool {
5375 matches!(
5376 target,
5377 DialectType::PostgreSQL
5378 | DialectType::BigQuery
5379 | DialectType::DuckDB
5380 | DialectType::Presto
5381 | DialectType::Trino
5382 | DialectType::Athena
5383 )
5384 }
5385
5386 fn target_supports_remaining_explode(target: DialectType) -> bool {
5387 matches!(
5388 target,
5389 DialectType::Spark | DialectType::Databricks | DialectType::Hive
5390 )
5391 }
5392
5393 fn target_lacks_array_agg(target: DialectType) -> bool {
5394 matches!(
5395 target,
5396 DialectType::Fabric
5397 | DialectType::TSQL
5398 | DialectType::MySQL
5399 | DialectType::SQLite
5400 | DialectType::Oracle
5401 )
5402 }
5403
5404 fn node_is_unnest(expr: &Expression) -> bool {
5405 matches!(expr, Expression::Unnest(_)) || Self::node_is_function_named(expr, "UNNEST")
5406 }
5407
5408 fn node_is_explode(expr: &Expression) -> bool {
5409 matches!(expr, Expression::Explode(_) | Expression::ExplodeOuter(_))
5410 || Self::node_is_function_named(expr, "EXPLODE")
5411 || Self::node_is_function_named(expr, "EXPLODE_OUTER")
5412 }
5413
5414 fn node_is_array_agg(expr: &Expression) -> bool {
5415 matches!(expr, Expression::ArrayAgg(_)) || Self::node_is_function_named(expr, "ARRAY_AGG")
5416 }
5417
5418 fn node_is_distinct_string_agg(expr: &Expression) -> bool {
5419 match expr {
5420 Expression::StringAgg(agg) => agg.distinct,
5421 Expression::Function(function) => {
5422 function.distinct && function.name.eq_ignore_ascii_case("STRING_AGG")
5423 }
5424 Expression::AggregateFunction(function) => {
5425 function.distinct && function.name.eq_ignore_ascii_case("STRING_AGG")
5426 }
5427 _ => false,
5428 }
5429 }
5430
5431 fn postgres_tsql_unsupported_collation_name(expr: &Expression) -> Option<&'static str> {
5432 let Expression::Collation(collation) = expr else {
5433 return None;
5434 };
5435
5436 if collation.collation.eq_ignore_ascii_case("C") {
5437 Some("C")
5438 } else if collation.collation.eq_ignore_ascii_case("POSIX") {
5439 Some("POSIX")
5440 } else {
5441 None
5442 }
5443 }
5444
5445 fn collect_tsql_grouping_tuple_nodes(expr: &Expression) -> HashSet<*const Expression> {
5446 let mut tuples = HashSet::new();
5447
5448 for node in expr.dfs() {
5449 let Expression::Select(select) = node else {
5450 continue;
5451 };
5452 let Some(group_by) = &select.group_by else {
5453 continue;
5454 };
5455
5456 for expression in &group_by.expressions {
5457 Self::collect_tsql_grouping_element_tuples(expression, &mut tuples);
5458 }
5459 }
5460
5461 tuples
5462 }
5463
5464 fn collect_tsql_grouping_element_tuples(
5465 expr: &Expression,
5466 tuples: &mut HashSet<*const Expression>,
5467 ) {
5468 match expr {
5469 Expression::GroupingSets(grouping_sets) => {
5470 for expression in &grouping_sets.expressions {
5471 Self::collect_tsql_grouping_unit_tuples(expression, tuples);
5472 }
5473 }
5474 Expression::Rollup(rollup) => {
5475 for expression in &rollup.expressions {
5476 Self::collect_tsql_grouping_unit_tuples(expression, tuples);
5477 }
5478 }
5479 Expression::Cube(cube) => {
5480 for expression in &cube.expressions {
5481 Self::collect_tsql_grouping_unit_tuples(expression, tuples);
5482 }
5483 }
5484 Expression::Function(function)
5485 if !function.quoted
5486 && (function.name.eq_ignore_ascii_case("GROUPING SETS")
5487 || function.name.eq_ignore_ascii_case("ROLLUP")
5488 || function.name.eq_ignore_ascii_case("CUBE")) =>
5489 {
5490 for expression in &function.args {
5491 Self::collect_tsql_grouping_unit_tuples(expression, tuples);
5492 }
5493 }
5494 _ => {}
5495 }
5496 }
5497
5498 fn collect_tsql_grouping_unit_tuples(
5499 expr: &Expression,
5500 tuples: &mut HashSet<*const Expression>,
5501 ) {
5502 match expr {
5503 Expression::Tuple(tuple) => {
5504 tuples.insert(expr as *const Expression);
5505 for expression in &tuple.expressions {
5506 match expression {
5507 Expression::Tuple(_) | Expression::Paren(_) => {
5508 Self::collect_tsql_grouping_unit_tuples(expression, tuples);
5509 }
5510 Expression::GroupingSets(_)
5511 | Expression::Rollup(_)
5512 | Expression::Cube(_) => {
5513 Self::collect_tsql_grouping_element_tuples(expression, tuples);
5514 }
5515 Expression::Function(function)
5516 if !function.quoted
5517 && (function.name.eq_ignore_ascii_case("GROUPING SETS")
5518 || function.name.eq_ignore_ascii_case("ROLLUP")
5519 || function.name.eq_ignore_ascii_case("CUBE")) =>
5520 {
5521 Self::collect_tsql_grouping_element_tuples(expression, tuples);
5522 }
5523 _ => {}
5524 }
5525 }
5526 }
5527 Expression::Paren(paren) => {
5528 Self::collect_tsql_grouping_unit_tuples(&paren.this, tuples);
5529 }
5530 Expression::GroupingSets(_) | Expression::Rollup(_) | Expression::Cube(_) => {
5531 Self::collect_tsql_grouping_element_tuples(expr, tuples);
5532 }
5533 Expression::Function(function)
5534 if !function.quoted
5535 && (function.name.eq_ignore_ascii_case("GROUPING SETS")
5536 || function.name.eq_ignore_ascii_case("ROLLUP")
5537 || function.name.eq_ignore_ascii_case("CUBE")) =>
5538 {
5539 Self::collect_tsql_grouping_element_tuples(expr, tuples);
5540 }
5541 _ => {}
5542 }
5543 }
5544
5545 fn postgres_tsql_unsupported_composite_semantics(
5546 expr: &Expression,
5547 structural_grouping_tuple: bool,
5548 ) -> Option<&'static str> {
5549 match expr {
5550 Expression::Tuple(_) if !structural_grouping_tuple => Some("row/composite values"),
5551 Expression::Struct(_) | Expression::StructFunc(_) => Some("row/composite values"),
5552 Expression::Function(function)
5553 if !function.quoted && function.name.eq_ignore_ascii_case("ROW") =>
5554 {
5555 Some("row/composite values")
5556 }
5557 Expression::StructExtract(_) => Some("row/composite field access"),
5558 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) if matches!(&cast.this, Expression::Star(star) if star.table.is_some()) => {
5559 Some("qualified whole-row casts")
5560 }
5561 _ => None,
5562 }
5563 }
5564
5565 fn node_is_postgres_unknown_cast(expr: &Expression) -> bool {
5566 match expr {
5567 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) => {
5568 normalization::is_postgres_unknown_type(&cast.to)
5569 }
5570 _ => false,
5571 }
5572 }
5573
5574 fn postgres_tsql_unsupported_array_semantics(expr: &Expression) -> Option<&'static str> {
5575 match expr {
5576 Expression::Array(_) | Expression::ArrayFunc(_) => Some("array literals"),
5577 Expression::Subscript(_) => Some("array subscripts"),
5578 Expression::ArraySlice(_) => Some("array slices"),
5579 Expression::DataType(DataType::Array { .. }) => Some("array data types"),
5580 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast)
5581 if matches!(&cast.to, DataType::Array { .. }) =>
5582 {
5583 Some("array data types")
5584 }
5585 Expression::ArrayLength(_) | Expression::ArraySize(_) => Some("ARRAY_LENGTH"),
5586 Expression::Cardinality(_) => Some("CARDINALITY"),
5587 Expression::ArrayToString(_) | Expression::ArrayJoin(_) => Some("ARRAY_TO_STRING"),
5588 Expression::StringToArray(_) => Some("STRING_TO_ARRAY"),
5589 Expression::ArrayContains(_)
5590 | Expression::ArrayPosition(_)
5591 | Expression::ArrayAppend(_)
5592 | Expression::ArrayPrepend(_)
5593 | Expression::ArrayConcat(_)
5594 | Expression::ArraySort(_)
5595 | Expression::ArrayReverse(_)
5596 | Expression::ArrayDistinct(_)
5597 | Expression::ArrayFilter(_)
5598 | Expression::ArrayTransform(_)
5599 | Expression::ArrayFlatten(_)
5600 | Expression::ArrayCompact(_)
5601 | Expression::ArrayIntersect(_)
5602 | Expression::ArrayUnion(_)
5603 | Expression::ArrayExcept(_)
5604 | Expression::ArrayRemove(_)
5605 | Expression::ArrayZip(_)
5606 | Expression::ArrayAll(_)
5607 | Expression::ArrayAny(_)
5608 | Expression::ArrayConstructCompact(_)
5609 | Expression::ArraySum(_) => Some("array functions"),
5610 Expression::ArrayContainsAll(_)
5611 | Expression::ArrayContainedBy(_)
5612 | Expression::ArrayOverlaps(_) => Some("array operators"),
5613 Expression::Function(function) => {
5614 Self::postgres_tsql_unsupported_array_function_name_str(&function.name)
5615 }
5616 Expression::AggregateFunction(function) => {
5617 Self::postgres_tsql_unsupported_array_function_name_str(&function.name)
5618 }
5619 _ => None,
5620 }
5621 }
5622
5623 fn postgres_tsql_unsupported_array_function_name_str(name: &str) -> Option<&'static str> {
5624 if name.eq_ignore_ascii_case("ARRAY") {
5625 Some("array literals")
5626 } else if name.eq_ignore_ascii_case("ARRAY_LENGTH")
5627 || name.eq_ignore_ascii_case("ARRAY_SIZE")
5628 {
5629 Some("ARRAY_LENGTH")
5630 } else if name.eq_ignore_ascii_case("CARDINALITY") {
5631 Some("CARDINALITY")
5632 } else if name.eq_ignore_ascii_case("ARRAY_TO_STRING")
5633 || name.eq_ignore_ascii_case("ARRAY_JOIN")
5634 {
5635 Some("ARRAY_TO_STRING")
5636 } else if name.eq_ignore_ascii_case("STRING_TO_ARRAY") {
5637 Some("STRING_TO_ARRAY")
5638 } else {
5639 None
5640 }
5641 }
5642
5643 fn node_is_regex_predicate(expr: &Expression) -> bool {
5644 matches!(
5645 expr,
5646 Expression::SimilarTo(_) | Expression::RegexpLike(_) | Expression::RegexpILike(_)
5647 ) || Self::node_is_function_named(expr, "REGEXP_LIKE")
5648 || Self::node_is_function_named(expr, "REGEXP_I_LIKE")
5649 || Self::node_is_function_named(expr, "REGEXP_ILIKE")
5650 }
5651
5652 fn node_is_non_subquery_any(expr: &Expression) -> bool {
5653 matches!(
5654 expr,
5655 Expression::Any(q) if !Self::quantified_rhs_is_subquery(&q.subquery)
5656 )
5657 }
5658
5659 fn quantified_rhs_is_subquery(expr: &Expression) -> bool {
5660 match expr {
5661 Expression::Select(_) | Expression::Subquery(_) => true,
5662 Expression::Paren(paren) => Self::quantified_rhs_is_subquery(&paren.this),
5663 _ => false,
5664 }
5665 }
5666
5667 fn node_is_row_value_subquery_comparison(expr: &Expression) -> bool {
5668 match expr {
5669 Expression::In(in_expr) => {
5670 Self::in_rhs_is_subquery_like(in_expr) && Self::expr_is_row_value(&in_expr.this)
5671 }
5672 Expression::Eq(op) | Expression::Neq(op) => {
5673 (Self::expr_is_row_value(&op.left) && Self::expr_is_subquery_like(&op.right))
5674 || (Self::expr_is_row_value(&op.right) && Self::expr_is_subquery_like(&op.left))
5675 }
5676 _ => false,
5677 }
5678 }
5679
5680 fn node_is_row_value_values_membership(expr: &Expression) -> bool {
5681 matches!(
5682 expr,
5683 Expression::In(in_expr)
5684 if Self::expr_is_row_value(&in_expr.this)
5685 && Self::in_rhs_is_values_like(in_expr)
5686 )
5687 }
5688
5689 fn expr_is_row_value(expr: &Expression) -> bool {
5690 match expr {
5691 Expression::Tuple(tuple) => tuple.expressions.len() > 1,
5692 Expression::Function(function) if function.name.eq_ignore_ascii_case("ROW") => {
5693 function.args.len() > 1
5694 }
5695 Expression::Paren(paren) => Self::expr_is_row_value(&paren.this),
5696 _ => false,
5697 }
5698 }
5699
5700 fn expr_is_subquery_like(expr: &Expression) -> bool {
5701 match expr {
5702 Expression::Select(_) | Expression::Subquery(_) => true,
5703 Expression::Paren(paren) => Self::expr_is_subquery_like(&paren.this),
5704 _ => false,
5705 }
5706 }
5707
5708 fn in_rhs_is_subquery_like(in_expr: &crate::expressions::In) -> bool {
5709 if in_expr
5710 .query
5711 .as_ref()
5712 .is_some_and(Self::expr_is_subquery_like)
5713 {
5714 return true;
5715 }
5716
5717 in_expr.expressions.len() == 1 && Self::expr_is_subquery_like(&in_expr.expressions[0])
5718 }
5719
5720 fn in_rhs_is_values_like(in_expr: &crate::expressions::In) -> bool {
5721 if in_expr
5722 .query
5723 .as_ref()
5724 .is_some_and(Self::expr_is_values_like)
5725 {
5726 return true;
5727 }
5728
5729 (in_expr.expressions.len() == 1
5730 && Self::expr_is_values_like(&in_expr.expressions[0]))
5731 || in_expr.expressions.first().is_some_and(|expr| {
5732 matches!(expr, Expression::Function(function) if function.name.eq_ignore_ascii_case("VALUES"))
5733 })
5734 }
5735
5736 fn expr_is_values_like(expr: &Expression) -> bool {
5737 match expr {
5738 Expression::Values(_) => true,
5739 Expression::Paren(paren) => Self::expr_is_values_like(&paren.this),
5740 Expression::Subquery(subquery) => Self::expr_is_values_like(&subquery.this),
5741 _ => false,
5742 }
5743 }
5744
5745 fn normalize_tsql_fetch_overlaps_date_bin(expr: Expression) -> Result<Expression> {
5746 transform_recursive(expr, &|e| match e {
5747 Expression::Select(mut select) => {
5748 if select.top.is_none() && select.offset.is_none() {
5749 if let Some(fetch) = select.fetch.take() {
5750 if let Some(top) = Self::fetch_with_ties_to_top(fetch.clone()) {
5751 select.top = Some(top);
5752 } else {
5753 select.fetch = Some(fetch);
5754 }
5755 }
5756 }
5757 Self::rewrite_tsql_overlaps_in_select_predicates(&mut select)?;
5758 Ok(Expression::Select(select))
5759 }
5760 Expression::DateBin(date_bin) => {
5761 let date_bin = *date_bin;
5762 if let Some(rewritten) = Self::date_bin_to_date_bucket(date_bin.clone()) {
5763 Ok(rewritten)
5764 } else {
5765 Ok(Expression::DateBin(Box::new(date_bin)))
5766 }
5767 }
5768 Expression::Function(function) => {
5769 let function = *function;
5770 if function.name.eq_ignore_ascii_case("DATE_BIN") {
5771 if let Some(rewritten) = Self::date_bin_function_to_date_bucket(&function) {
5772 Ok(rewritten)
5773 } else {
5774 Ok(Expression::Function(Box::new(function)))
5775 }
5776 } else {
5777 Ok(Expression::Function(Box::new(function)))
5778 }
5779 }
5780 _ => Ok(e),
5781 })
5782 }
5783
5784 fn rewrite_tsql_overlaps_in_select_predicates(
5785 select: &mut crate::expressions::Select,
5786 ) -> Result<()> {
5787 if let Some(where_clause) = &mut select.where_clause {
5788 where_clause.this = Self::rewrite_tsql_overlaps_predicate(where_clause.this.clone())?;
5789 }
5790 if let Some(having) = &mut select.having {
5791 having.this = Self::rewrite_tsql_overlaps_predicate(having.this.clone())?;
5792 }
5793 if let Some(qualify) = &mut select.qualify {
5794 qualify.this = Self::rewrite_tsql_overlaps_predicate(qualify.this.clone())?;
5795 }
5796 for join in &mut select.joins {
5797 if let Some(on) = join.on.take() {
5798 join.on = Some(Self::rewrite_tsql_overlaps_predicate(on)?);
5799 }
5800 if let Some(match_condition) = join.match_condition.take() {
5801 join.match_condition =
5802 Some(Self::rewrite_tsql_overlaps_predicate(match_condition)?);
5803 }
5804 }
5805 Ok(())
5806 }
5807
5808 fn rewrite_tsql_overlaps_predicate(expr: Expression) -> Result<Expression> {
5809 transform_recursive(expr, &|e| match e {
5810 Expression::Overlaps(overlaps) => {
5811 let overlaps = *overlaps;
5812 if let Some(rewritten) = Self::rewrite_full_overlaps_for_tsql(&overlaps) {
5813 Ok(rewritten)
5814 } else {
5815 Ok(Expression::Overlaps(Box::new(overlaps)))
5816 }
5817 }
5818 _ => Ok(e),
5819 })
5820 }
5821
5822 fn fetch_with_ties_to_top(fetch: Fetch) -> Option<Top> {
5823 if !fetch.with_ties {
5824 return None;
5825 }
5826
5827 fetch.count.map(|count| Top {
5828 this: count,
5829 percent: fetch.percent,
5830 with_ties: true,
5831 parenthesized: true,
5832 })
5833 }
5834
5835 fn rewrite_full_overlaps_for_tsql(
5836 overlaps: &crate::expressions::OverlapsExpr,
5837 ) -> Option<Expression> {
5838 let (left_start, left_end, right_start, right_end) =
5839 if let (Some(left_start), Some(left_end), Some(right_start), Some(right_end)) = (
5840 overlaps.left_start.as_ref(),
5841 overlaps.left_end.as_ref(),
5842 overlaps.right_start.as_ref(),
5843 overlaps.right_end.as_ref(),
5844 ) {
5845 (left_start, left_end, right_start, right_end)
5846 } else if let (
5847 Some(Expression::Tuple(left_tuple)),
5848 Some(Expression::Tuple(right_tuple)),
5849 ) = (&overlaps.this, &overlaps.expression)
5850 {
5851 if left_tuple.expressions.len() != 2 || right_tuple.expressions.len() != 2 {
5852 return None;
5853 }
5854 (
5855 &left_tuple.expressions[0],
5856 &left_tuple.expressions[1],
5857 &right_tuple.expressions[0],
5858 &right_tuple.expressions[1],
5859 )
5860 } else {
5861 return None;
5862 };
5863
5864 let left_min = Self::case_min(left_start.clone(), left_end.clone());
5865 let left_max = Self::case_max(left_start.clone(), left_end.clone());
5866 let right_min = Self::case_min(right_start.clone(), right_end.clone());
5867 let right_max = Self::case_max(right_start.clone(), right_end.clone());
5868
5869 Some(Expression::And(Box::new(BinaryOp::new(
5870 Expression::Lte(Box::new(BinaryOp::new(left_min, right_max))),
5871 Expression::Lte(Box::new(BinaryOp::new(right_min, left_max))),
5872 ))))
5873 }
5874
5875 fn case_min(left: Expression, right: Expression) -> Expression {
5876 Expression::Case(Box::new(Case {
5877 operand: None,
5878 whens: vec![(
5879 Expression::Lte(Box::new(BinaryOp::new(left.clone(), right.clone()))),
5880 left,
5881 )],
5882 else_: Some(right),
5883 comments: Vec::new(),
5884 inferred_type: None,
5885 }))
5886 }
5887
5888 fn case_max(left: Expression, right: Expression) -> Expression {
5889 Expression::Case(Box::new(Case {
5890 operand: None,
5891 whens: vec![(
5892 Expression::Gte(Box::new(BinaryOp::new(left.clone(), right.clone()))),
5893 left,
5894 )],
5895 else_: Some(right),
5896 comments: Vec::new(),
5897 inferred_type: None,
5898 }))
5899 }
5900
5901 fn date_bin_to_date_bucket(date_bin: DateBin) -> Option<Expression> {
5902 if date_bin.unit.is_some() || date_bin.zone.is_some() {
5903 return None;
5904 }
5905
5906 let (datepart, number) = Self::date_bucket_parts(&date_bin.this)?;
5907 let mut args = vec![
5908 Self::date_bucket_datepart(datepart),
5909 number,
5910 *date_bin.expression,
5911 ];
5912 if let Some(origin) = date_bin.origin {
5913 args.push(*origin);
5914 }
5915
5916 Some(Expression::Function(Box::new(Function::new(
5917 "DATE_BUCKET".to_string(),
5918 args,
5919 ))))
5920 }
5921
5922 fn date_bin_function_to_date_bucket(function: &Function) -> Option<Expression> {
5923 if !(2..=3).contains(&function.args.len()) {
5924 return None;
5925 }
5926
5927 let (datepart, number) = Self::date_bucket_parts(&function.args[0])?;
5928 let mut args = vec![
5929 Self::date_bucket_datepart(datepart),
5930 number,
5931 function.args[1].clone(),
5932 ];
5933 if let Some(origin) = function.args.get(2) {
5934 args.push(origin.clone());
5935 }
5936
5937 Some(Expression::Function(Box::new(Function::new(
5938 "DATE_BUCKET".to_string(),
5939 args,
5940 ))))
5941 }
5942
5943 fn date_bucket_parts(stride: &Expression) -> Option<(&'static str, Expression)> {
5944 match stride {
5945 Expression::Literal(lit) => match lit.as_ref() {
5946 Literal::String(value) => Self::date_bucket_parts_from_string(value),
5947 _ => None,
5948 },
5949 Expression::Interval(interval) => Self::date_bucket_parts_from_interval(interval),
5950 _ => None,
5951 }
5952 }
5953
5954 fn date_bucket_parts_from_interval(interval: &Interval) -> Option<(&'static str, Expression)> {
5955 match &interval.unit {
5956 Some(IntervalUnitSpec::Simple { unit, .. }) => {
5957 let datepart = Self::date_bucket_datepart_from_unit(*unit)?;
5958 let amount = interval
5959 .this
5960 .as_ref()
5961 .and_then(Self::date_bucket_amount_expr)?;
5962 Some((datepart, amount))
5963 }
5964 None => interval.this.as_ref().and_then(|expr| match expr {
5965 Expression::Literal(lit) => match lit.as_ref() {
5966 Literal::String(value) => Self::date_bucket_parts_from_string(value),
5967 _ => None,
5968 },
5969 _ => None,
5970 }),
5971 _ => None,
5972 }
5973 }
5974
5975 fn date_bucket_parts_from_string(value: &str) -> Option<(&'static str, Expression)> {
5976 let mut parts = value.split_whitespace();
5977 let amount = parts.next()?;
5978 let unit = parts.next()?;
5979 if parts.next().is_some() {
5980 return None;
5981 }
5982
5983 Some((
5984 Self::date_bucket_datepart_from_name(unit)?,
5985 Self::positive_integer_expr(amount)?,
5986 ))
5987 }
5988
5989 fn date_bucket_amount_expr(expr: &Expression) -> Option<Expression> {
5990 match expr {
5991 Expression::Literal(lit) => match lit.as_ref() {
5992 Literal::Number(value) => Self::positive_integer_expr(value),
5993 Literal::String(value) => Self::positive_integer_expr(value),
5994 _ => None,
5995 },
5996 _ => Some(expr.clone()),
5997 }
5998 }
5999
6000 fn positive_integer_expr(value: &str) -> Option<Expression> {
6001 let parsed = value.trim().parse::<i64>().ok()?;
6002 (parsed > 0).then(|| Expression::number(parsed))
6003 }
6004
6005 fn date_bucket_datepart(datepart: &str) -> Expression {
6006 Expression::Var(Box::new(Var {
6007 this: datepart.to_string(),
6008 }))
6009 }
6010
6011 fn date_bucket_datepart_from_unit(unit: IntervalUnit) -> Option<&'static str> {
6012 match unit {
6013 IntervalUnit::Week => Some("WEEK"),
6014 IntervalUnit::Day => Some("DAY"),
6015 IntervalUnit::Hour => Some("HOUR"),
6016 IntervalUnit::Minute => Some("MINUTE"),
6017 IntervalUnit::Second => Some("SECOND"),
6018 IntervalUnit::Millisecond => Some("MILLISECOND"),
6019 _ => None,
6020 }
6021 }
6022
6023 fn date_bucket_datepart_from_name(unit: &str) -> Option<&'static str> {
6024 match unit.trim().to_ascii_uppercase().as_str() {
6025 "WEEK" | "WEEKS" | "W" | "WK" | "WKS" | "WW" => Some("WEEK"),
6026 "DAY" | "DAYS" | "D" | "DD" => Some("DAY"),
6027 "HOUR" | "HOURS" | "H" | "HH" | "HR" | "HRS" => Some("HOUR"),
6028 "MINUTE" | "MINUTES" | "MI" | "MIN" | "MINS" | "N" => Some("MINUTE"),
6029 "SECOND" | "SECONDS" | "S" | "SEC" | "SECS" | "SS" => Some("SECOND"),
6030 "MILLISECOND" | "MILLISECONDS" | "MS" | "MSEC" | "MSECS" | "MILLISEC" | "MILLISECS" => {
6031 Some("MILLISECOND")
6032 }
6033 _ => None,
6034 }
6035 }
6036
6037 fn node_has_fetch_with_ties(expr: &Expression) -> bool {
6038 matches!(
6039 expr,
6040 Expression::Select(select)
6041 if select
6042 .fetch
6043 .as_ref()
6044 .is_some_and(|fetch| fetch.with_ties)
6045 )
6046 }
6047
6048 fn node_is_overlaps(expr: &Expression) -> bool {
6049 matches!(expr, Expression::Overlaps(_))
6050 }
6051
6052 fn node_is_date_bin(expr: &Expression) -> bool {
6053 matches!(expr, Expression::DateBin(_)) || Self::node_is_function_named(expr, "DATE_BIN")
6054 }
6055
6056 fn node_is_function_named(expr: &Expression, name: &str) -> bool {
6057 match expr {
6058 Expression::Function(function) => function.name.eq_ignore_ascii_case(name),
6059 Expression::AggregateFunction(function) => function.name.eq_ignore_ascii_case(name),
6060 _ => false,
6061 }
6062 }
6063
6064 fn node_is_postgres_json_build_object(expr: &Expression) -> bool {
6065 match expr {
6066 Expression::Function(function) => {
6067 function.name.eq_ignore_ascii_case("JSON_BUILD_OBJECT")
6068 || function.name.eq_ignore_ascii_case("JSONB_BUILD_OBJECT")
6069 }
6070 _ => false,
6071 }
6072 }
6073
6074 fn postgres_json_build_object_can_lower_to_json_object(expr: &Expression) -> bool {
6075 matches!(
6076 expr,
6077 Expression::Function(function)
6078 if (function.name.eq_ignore_ascii_case("JSON_BUILD_OBJECT")
6079 || function.name.eq_ignore_ascii_case("JSONB_BUILD_OBJECT"))
6080 && !function.distinct
6081 && function.args.len() % 2 == 0
6082 )
6083 }
6084
6085 fn node_is_postgres_json_array_elements(expr: &Expression) -> bool {
6086 matches!(
6087 expr,
6088 Expression::Function(function)
6089 if function.name.eq_ignore_ascii_case("JSON_ARRAY_ELEMENTS")
6090 || function.name.eq_ignore_ascii_case("JSONB_ARRAY_ELEMENTS")
6091 || function.name.eq_ignore_ascii_case("JSON_ARRAY_ELEMENTS_TEXT")
6092 || function.name.eq_ignore_ascii_case("JSONB_ARRAY_ELEMENTS_TEXT")
6093 )
6094 }
6095
6096 fn postgres_tsql_unsupported_function_name(
6097 expr: &Expression,
6098 target: DialectType,
6099 ) -> Option<&'static str> {
6100 match expr {
6101 Expression::Lpad(_) => Some("LPAD"),
6102 Expression::Rpad(_) => Some("RPAD"),
6103 Expression::SplitPart(_) => Some("SPLIT_PART"),
6104 Expression::Initcap(_) => Some("INITCAP"),
6105 Expression::RegexpReplace(_) => Some("REGEXP_REPLACE"),
6106 Expression::RegexpInstr(_) => Some("REGEXP_INSTR"),
6107 Expression::RegexpCount(_) => Some("REGEXP_COUNT"),
6108 Expression::RegexpSplit(_) => Some("REGEXP_SPLIT"),
6109 Expression::DecodeCase(_) => Some("DECODE"),
6110 Expression::ToJson(_) => Some("TO_JSON"),
6111 Expression::JSONBObjectAgg(_) => Some("JSONB_OBJECT_AGG"),
6112 Expression::ToNumber(_) => Some("TO_NUMBER"),
6113 Expression::WidthBucket(_) => Some("WIDTH_BUCKET"),
6114 Expression::BitwiseAndAgg(_) => Some("BIT_AND"),
6115 Expression::BitwiseOrAgg(_) => Some("BIT_OR"),
6116 Expression::BitwiseXorAgg(_) => Some("BIT_XOR"),
6117 Expression::Corr(_) => Some("CORR"),
6118 Expression::CovarPop(_) => Some("COVAR_POP"),
6119 Expression::CovarSamp(_) => Some("COVAR_SAMP"),
6120 Expression::RegrAvgx(_) => Some("REGR_AVGX"),
6121 Expression::RegrAvgy(_) => Some("REGR_AVGY"),
6122 Expression::RegrCount(_) => Some("REGR_COUNT"),
6123 Expression::RegrIntercept(_) => Some("REGR_INTERCEPT"),
6124 Expression::RegrR2(_) => Some("REGR_R2"),
6125 Expression::RegrSlope(_) => Some("REGR_SLOPE"),
6126 Expression::RegrSxx(_) => Some("REGR_SXX"),
6127 Expression::RegrSxy(_) => Some("REGR_SXY"),
6128 Expression::RegrSyy(_) => Some("REGR_SYY"),
6129 Expression::Function(function) => {
6130 Self::postgres_tsql_unsupported_function_name_str(&function.name, target)
6131 }
6132 Expression::AggregateFunction(function) => {
6133 Self::postgres_tsql_unsupported_function_name_str(&function.name, target)
6134 }
6135 _ => None,
6136 }
6137 }
6138
6139 fn postgres_tsql_unsupported_function_name_str(
6140 name: &str,
6141 target: DialectType,
6142 ) -> Option<&'static str> {
6143 if name.eq_ignore_ascii_case("LPAD") {
6144 Some("LPAD")
6145 } else if name.eq_ignore_ascii_case("RPAD") {
6146 Some("RPAD")
6147 } else if name.eq_ignore_ascii_case("SPLIT_PART") {
6148 Some("SPLIT_PART")
6149 } else if name.eq_ignore_ascii_case("INITCAP") {
6150 Some("INITCAP")
6151 } else if name.eq_ignore_ascii_case("TO_JSON") {
6152 Some("TO_JSON")
6153 } else if name.eq_ignore_ascii_case("TO_JSONB") {
6154 Some("TO_JSONB")
6155 } else if name.eq_ignore_ascii_case("JSONB_OBJECT_AGG") {
6156 Some("JSONB_OBJECT_AGG")
6157 } else if name.eq_ignore_ascii_case("ROW_TO_JSON") {
6158 Some("ROW_TO_JSON")
6159 } else if name.eq_ignore_ascii_case("JSON_ARRAY_ELEMENTS") {
6160 Some("JSON_ARRAY_ELEMENTS")
6161 } else if name.eq_ignore_ascii_case("JSONB_ARRAY_ELEMENTS") {
6162 Some("JSONB_ARRAY_ELEMENTS")
6163 } else if name.eq_ignore_ascii_case("JSON_ARRAY_ELEMENTS_TEXT") {
6164 Some("JSON_ARRAY_ELEMENTS_TEXT")
6165 } else if name.eq_ignore_ascii_case("JSONB_ARRAY_ELEMENTS_TEXT") {
6166 Some("JSONB_ARRAY_ELEMENTS_TEXT")
6167 } else if name.eq_ignore_ascii_case("ENCODE") {
6168 Some("ENCODE")
6169 } else if name.eq_ignore_ascii_case("DECODE") {
6170 Some("DECODE")
6171 } else if name.eq_ignore_ascii_case("REGEXP_REPLACE") {
6172 Some("REGEXP_REPLACE")
6173 } else if name.eq_ignore_ascii_case("REGEXP_COUNT") {
6174 Some("REGEXP_COUNT")
6175 } else if name.eq_ignore_ascii_case("REGEXP_INSTR") {
6176 Some("REGEXP_INSTR")
6177 } else if name.eq_ignore_ascii_case("REGEXP_SUBSTR") {
6178 Some("REGEXP_SUBSTR")
6179 } else if name.eq_ignore_ascii_case("REGEXP_SPLIT") {
6180 Some("REGEXP_SPLIT")
6181 } else if name.eq_ignore_ascii_case("REGEXP_SPLIT_TO_ARRAY") {
6182 Some("REGEXP_SPLIT_TO_ARRAY")
6183 } else if name.eq_ignore_ascii_case("REGEXP_SPLIT_TO_TABLE") {
6184 Some("REGEXP_SPLIT_TO_TABLE")
6185 } else if name.eq_ignore_ascii_case("SHA224") {
6186 Some("SHA224")
6187 } else if name.eq_ignore_ascii_case("SHA384") {
6188 Some("SHA384")
6189 } else if name.eq_ignore_ascii_case("TO_BIN") {
6190 Some("TO_BIN")
6191 } else if name.eq_ignore_ascii_case("TO_OCT") {
6192 Some("TO_OCT")
6193 } else if target == DialectType::TSQL && name.eq_ignore_ascii_case("UNISTR") {
6194 Some("UNISTR")
6195 } else if name.eq_ignore_ascii_case("AGE") {
6196 Some("AGE")
6197 } else if name.eq_ignore_ascii_case("ERF") {
6198 Some("ERF")
6199 } else if name.eq_ignore_ascii_case("SINH") {
6200 Some("SINH")
6201 } else if name.eq_ignore_ascii_case("COSH") {
6202 Some("COSH")
6203 } else if name.eq_ignore_ascii_case("TANH") {
6204 Some("TANH")
6205 } else if name.eq_ignore_ascii_case("ASINH") {
6206 Some("ASINH")
6207 } else if name.eq_ignore_ascii_case("ACOSH") {
6208 Some("ACOSH")
6209 } else if name.eq_ignore_ascii_case("ATANH") {
6210 Some("ATANH")
6211 } else if name.eq_ignore_ascii_case("GCD") {
6212 Some("GCD")
6213 } else if name.eq_ignore_ascii_case("LCM") {
6214 Some("LCM")
6215 } else if name.eq_ignore_ascii_case("QUOTE_LITERAL") {
6216 Some("QUOTE_LITERAL")
6217 } else if name.eq_ignore_ascii_case("WIDTH_BUCKET") {
6218 Some("WIDTH_BUCKET")
6219 } else if name.eq_ignore_ascii_case("SCALE") {
6220 Some("SCALE")
6221 } else if name.eq_ignore_ascii_case("TRIM_SCALE") {
6222 Some("TRIM_SCALE")
6223 } else if name.eq_ignore_ascii_case("MIN_SCALE") {
6224 Some("MIN_SCALE")
6225 } else if name.eq_ignore_ascii_case("FACTORIAL") {
6226 Some("FACTORIAL")
6227 } else if name.eq_ignore_ascii_case("PG_LSN") {
6228 Some("PG_LSN")
6229 } else if name.eq_ignore_ascii_case("TO_CHAR") {
6230 Some("TO_CHAR")
6231 } else if name.eq_ignore_ascii_case("PG_TYPEOF") {
6232 Some("PG_TYPEOF")
6233 } else if name.eq_ignore_ascii_case("BIT_AND") {
6234 Some("BIT_AND")
6235 } else if name.eq_ignore_ascii_case("BIT_OR") {
6236 Some("BIT_OR")
6237 } else if name.eq_ignore_ascii_case("BIT_XOR") {
6238 Some("BIT_XOR")
6239 } else if name.eq_ignore_ascii_case("CORR") {
6240 Some("CORR")
6241 } else if name.eq_ignore_ascii_case("COVAR_POP") {
6242 Some("COVAR_POP")
6243 } else if name.eq_ignore_ascii_case("COVAR_SAMP") {
6244 Some("COVAR_SAMP")
6245 } else if name.eq_ignore_ascii_case("REGR_AVGX") {
6246 Some("REGR_AVGX")
6247 } else if name.eq_ignore_ascii_case("REGR_AVGY") {
6248 Some("REGR_AVGY")
6249 } else if name.eq_ignore_ascii_case("REGR_COUNT") {
6250 Some("REGR_COUNT")
6251 } else if name.eq_ignore_ascii_case("REGR_INTERCEPT") {
6252 Some("REGR_INTERCEPT")
6253 } else if name.eq_ignore_ascii_case("REGR_R2") {
6254 Some("REGR_R2")
6255 } else if name.eq_ignore_ascii_case("REGR_SLOPE") {
6256 Some("REGR_SLOPE")
6257 } else if name.eq_ignore_ascii_case("REGR_SXX") {
6258 Some("REGR_SXX")
6259 } else if name.eq_ignore_ascii_case("REGR_SXY") {
6260 Some("REGR_SXY")
6261 } else if name.eq_ignore_ascii_case("REGR_SYY") {
6262 Some("REGR_SYY")
6263 } else if name.eq_ignore_ascii_case("FLOAT8_ACCUM") {
6264 Some("FLOAT8_ACCUM")
6265 } else if name.eq_ignore_ascii_case("FLOAT8_REGR_ACCUM") {
6266 Some("FLOAT8_REGR_ACCUM")
6267 } else if name.eq_ignore_ascii_case("FLOAT8_COMBINE") {
6268 Some("FLOAT8_COMBINE")
6269 } else if name.eq_ignore_ascii_case("FLOAT8_REGR_COMBINE") {
6270 Some("FLOAT8_REGR_COMBINE")
6271 } else if name.eq_ignore_ascii_case("BOOLAND_STATEFUNC") {
6272 Some("BOOLAND_STATEFUNC")
6273 } else if name.eq_ignore_ascii_case("BOOLOR_STATEFUNC") {
6274 Some("BOOLOR_STATEFUNC")
6275 } else {
6276 None
6277 }
6278 }
6279
6280 fn normalize_postgres_trim_for_tsql(expr: Expression) -> Result<Expression> {
6281 transform_recursive(expr, &|e| match e {
6282 Expression::Trim(trim) => {
6283 let mut trim = *trim;
6284 trim.characters = trim.characters.map(Self::strip_postgres_text_literal_cast);
6285 match trim.position {
6286 crate::expressions::TrimPosition::Both
6287 if trim.position_explicit && trim.characters.is_some() =>
6288 {
6289 trim.position_explicit = false;
6290 trim.sql_standard_syntax = true;
6291 Ok(Expression::Trim(Box::new(trim)))
6292 }
6293 crate::expressions::TrimPosition::Leading if trim.characters.is_some() => {
6294 let characters = trim.characters.take().expect("checked above");
6295 Ok(Expression::Function(Box::new(Function::new(
6296 "LTRIM",
6297 vec![trim.this, characters],
6298 ))))
6299 }
6300 crate::expressions::TrimPosition::Trailing if trim.characters.is_some() => {
6301 let characters = trim.characters.take().expect("checked above");
6302 Ok(Expression::Function(Box::new(Function::new(
6303 "RTRIM",
6304 vec![trim.this, characters],
6305 ))))
6306 }
6307 _ => Ok(Expression::Trim(Box::new(trim))),
6308 }
6309 }
6310 other => Ok(other),
6311 })
6312 }
6313
6314 fn normalize_postgres_string_semantics_for_tsql(expr: Expression) -> Result<Expression> {
6315 transform_recursive(expr, &|e| match e {
6316 Expression::Like(mut op) => {
6317 Self::recover_postgres_like_escape(&mut op);
6318 Ok(Expression::Like(op))
6319 }
6320 Expression::ILike(mut op) => {
6321 Self::recover_postgres_like_escape(&mut op);
6322 Ok(Expression::ILike(op))
6323 }
6324 Expression::Substring(mut substring)
6325 if substring.length.is_none()
6326 && Self::is_explicitly_numeric_expression(&substring.start) =>
6327 {
6328 substring.length = Some(Expression::number(i32::MAX as i64));
6329 Ok(Expression::Substring(substring))
6330 }
6331 Expression::Trim(mut trim) => {
6332 trim.characters = trim.characters.map(Self::strip_postgres_text_literal_cast);
6333 Ok(Expression::Trim(trim))
6334 }
6335 Expression::Function(mut function)
6336 if !function.quoted
6337 && matches!(
6338 function.name.to_ascii_uppercase().as_str(),
6339 "BTRIM" | "LTRIM" | "RTRIM"
6340 )
6341 && function.args.len() == 2 =>
6342 {
6343 function.args[1] = Self::strip_postgres_text_literal_cast(function.args[1].clone());
6344 Ok(Expression::Function(function))
6345 }
6346 Expression::Translate(translate) => {
6347 Ok(Self::normalize_postgres_translate_for_tsql(*translate))
6348 }
6349 Expression::Function(function)
6350 if !function.quoted
6351 && function.name.eq_ignore_ascii_case("TRANSLATE")
6352 && function.args.len() == 3 =>
6353 {
6354 Ok(Self::normalize_postgres_translate_function_for_tsql(
6355 *function,
6356 ))
6357 }
6358 other => Ok(other),
6359 })
6360 }
6361
6362 fn normalize_postgres_bytea_literals_for_tsql(expr: Expression) -> Result<Expression> {
6363 transform_recursive(expr, &|e| match e {
6364 Expression::Cast(cast) if Self::is_postgres_bytea_data_type(&cast.to) => {
6365 let Some(value) = Self::postgres_plain_string_literal_value(&cast.this) else {
6366 return Ok(Expression::Cast(cast));
6367 };
6368 let Some(hex) = Self::postgres_bytea_hex_payload(value) else {
6369 return Ok(Expression::Cast(cast));
6370 };
6371
6372 Ok(Expression::Literal(Box::new(Literal::HexString(hex))))
6376 }
6377 other => Ok(other),
6378 })
6379 }
6380
6381 fn postgres_plain_string_literal_value(expr: &Expression) -> Option<&str> {
6382 match expr {
6383 Expression::Literal(literal) => match literal.as_ref() {
6384 Literal::String(value) => Some(value),
6385 _ => None,
6386 },
6387 Expression::Paren(paren) => Self::postgres_plain_string_literal_value(&paren.this),
6388 _ => None,
6389 }
6390 }
6391
6392 fn postgres_bytea_hex_payload(value: &str) -> Option<String> {
6393 let payload = value.strip_prefix("\\x")?;
6394 if payload.is_empty() {
6395 return Some(String::new());
6396 }
6397
6398 let mut chars = payload.chars().peekable();
6399 let mut hex = String::with_capacity(payload.len());
6400 loop {
6401 let high = chars.next()?;
6402 let low = chars.next()?;
6403 if !high.is_ascii_hexdigit() || !low.is_ascii_hexdigit() {
6404 return None;
6405 }
6406 hex.push(high);
6407 hex.push(low);
6408
6409 let Some(next) = chars.peek().copied() else {
6410 return Some(hex);
6411 };
6412 if next.is_ascii_whitespace() {
6413 while chars
6414 .peek()
6415 .is_some_and(|character| character.is_ascii_whitespace())
6416 {
6417 chars.next();
6418 }
6419 chars.peek()?;
6422 }
6423 }
6424 }
6425
6426 fn is_postgres_bytea_data_type(data_type: &DataType) -> bool {
6427 match data_type {
6428 DataType::VarBinary { length: None } => true,
6429 DataType::Custom { name } => name.trim().eq_ignore_ascii_case("BYTEA"),
6430 _ => false,
6431 }
6432 }
6433
6434 fn postgres_tsql_unsupported_binary_semantics(expr: &Expression) -> Option<&'static str> {
6435 let cast = match expr {
6436 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast)
6437 if Self::is_postgres_bytea_data_type(&cast.to) =>
6438 {
6439 cast
6440 }
6441 _ => return None,
6442 };
6443
6444 let literal = match &cast.this {
6445 Expression::Literal(literal) => literal.as_ref(),
6446 Expression::Paren(paren) => match &paren.this {
6447 Expression::Literal(literal) => literal.as_ref(),
6448 _ => return None,
6449 },
6450 _ => return None,
6451 };
6452 let value = match literal {
6453 Literal::String(value) | Literal::EscapeString(value) => value,
6454 _ => return None,
6455 };
6456
6457 if value.starts_with("\\x") {
6458 Some("bytea hex literals with invalid or unsupported formatting")
6459 } else if value.contains('\\') {
6460 Some("bytea escape-format literals")
6461 } else {
6462 None
6463 }
6464 }
6465
6466 fn recover_postgres_like_escape(op: &mut crate::expressions::LikeOp) {
6467 if op.escape.is_some() {
6468 return;
6469 }
6470
6471 let Expression::Function(function) = &op.right else {
6472 return;
6473 };
6474 if function.quoted
6475 || function.distinct
6476 || !function.name.eq_ignore_ascii_case("LIKE_ESCAPE")
6477 || function.args.len() != 2
6478 {
6479 return;
6480 }
6481
6482 let pattern = function.args[0].clone();
6483 let escape = function.args[1].clone();
6484 op.right = Self::strip_postgres_text_literal_cast(pattern);
6485 op.escape = Some(Self::strip_postgres_text_literal_cast(escape));
6486 }
6487
6488 fn normalize_postgres_translate_for_tsql(
6489 mut translate: crate::expressions::Translate,
6490 ) -> Expression {
6491 let (Some(from), Some(to)) = (&translate.from_, &translate.to) else {
6492 return Expression::Translate(Box::new(translate));
6493 };
6494
6495 let (Some(from_value), Some(to_value)) = (
6496 Self::postgres_text_literal_value(from),
6497 Self::postgres_text_literal_value(to),
6498 ) else {
6499 return Expression::Translate(Box::new(translate));
6500 };
6501 let from_value = from_value.to_string();
6502 let to_value = to_value.to_string();
6503
6504 if from_value.chars().count() > to_value.chars().count() {
6505 if let Some(input) = Self::postgres_text_literal_value(&translate.this) {
6506 return Expression::string(Self::translate_postgres_literal(
6507 input,
6508 &from_value,
6509 &to_value,
6510 ));
6511 }
6512 return Expression::Translate(Box::new(translate));
6513 }
6514
6515 translate.from_ = Some(Box::new(Self::strip_postgres_text_literal_cast(
6516 *translate.from_.expect("checked above"),
6517 )));
6518 let normalized_to = if from_value.chars().count() < to_value.chars().count() {
6519 Expression::string(
6520 to_value
6521 .chars()
6522 .take(from_value.chars().count())
6523 .collect::<String>(),
6524 )
6525 } else {
6526 Self::strip_postgres_text_literal_cast(*translate.to.expect("checked above"))
6527 };
6528 translate.to = Some(Box::new(normalized_to));
6529 Expression::Translate(Box::new(translate))
6530 }
6531
6532 fn normalize_postgres_translate_function_for_tsql(mut function: Function) -> Expression {
6533 let from = Self::postgres_text_literal_value(&function.args[1]);
6534 let to = Self::postgres_text_literal_value(&function.args[2]);
6535 let (Some(from), Some(to)) = (from, to) else {
6536 return Expression::Function(Box::new(function));
6537 };
6538 let from = from.to_string();
6539 let to = to.to_string();
6540
6541 if from.chars().count() > to.chars().count() {
6542 if let Some(input) = Self::postgres_text_literal_value(&function.args[0]) {
6543 return Expression::string(Self::translate_postgres_literal(input, &from, &to));
6544 }
6545 return Expression::Function(Box::new(function));
6546 }
6547
6548 function.args[1] = Self::strip_postgres_text_literal_cast(function.args[1].clone());
6549 function.args[2] = if from.chars().count() < to.chars().count() {
6550 Expression::string(to.chars().take(from.chars().count()).collect::<String>())
6551 } else {
6552 Self::strip_postgres_text_literal_cast(function.args[2].clone())
6553 };
6554 Expression::Function(Box::new(function))
6555 }
6556
6557 fn translate_postgres_literal(input: &str, from: &str, to: &str) -> String {
6558 let from = from.chars().collect::<Vec<_>>();
6559 let to = to.chars().collect::<Vec<_>>();
6560 let mut output = String::with_capacity(input.len());
6561
6562 for ch in input.chars() {
6563 match from.iter().position(|candidate| *candidate == ch) {
6564 Some(index) if index < to.len() => output.push(to[index]),
6565 Some(_) => {}
6566 None => output.push(ch),
6567 }
6568 }
6569
6570 output
6571 }
6572
6573 fn postgres_tsql_unsupported_string_semantics(expr: &Expression) -> Option<&'static str> {
6574 match expr {
6575 Expression::Substring(substring) if substring.length.is_none() => {
6576 if Self::postgres_text_literal_value(&substring.start).is_some() {
6577 Some("regular-expression SUBSTRING")
6578 } else {
6579 Some("SUBSTRING without a statically numeric start position")
6580 }
6581 }
6582 Expression::Translate(translate) => {
6583 let from = translate
6584 .from_
6585 .as_deref()
6586 .and_then(Self::postgres_text_literal_value);
6587 let to = translate
6588 .to
6589 .as_deref()
6590 .and_then(Self::postgres_text_literal_value);
6591 match (from, to) {
6592 (Some(from), Some(to)) if from.chars().count() == to.chars().count() => None,
6593 _ => Some("TRANSLATE with source and replacement lengths that differ or cannot be proven equal"),
6594 }
6595 }
6596 Expression::Function(function)
6597 if !function.quoted && function.name.eq_ignore_ascii_case("LIKE_ESCAPE") =>
6598 {
6599 Some("LIKE_ESCAPE helper outside a LIKE predicate")
6600 }
6601 Expression::Function(function)
6602 if !function.quoted
6603 && function.name.eq_ignore_ascii_case("TRANSLATE")
6604 && function.args.len() == 3 =>
6605 {
6606 let from = Self::postgres_text_literal_value(&function.args[1]);
6607 let to = Self::postgres_text_literal_value(&function.args[2]);
6608 match (from, to) {
6609 (Some(from), Some(to)) if from.chars().count() == to.chars().count() => None,
6610 _ => Some("TRANSLATE with source and replacement lengths that differ or cannot be proven equal"),
6611 }
6612 }
6613 Expression::Trim(trim)
6614 if trim
6615 .characters
6616 .as_ref()
6617 .is_some_and(Self::is_unbounded_text_cast) =>
6618 {
6619 Some("TRIM character set cast to an unbounded text type")
6620 }
6621 Expression::Function(function)
6622 if !function.quoted
6623 && matches!(
6624 function.name.to_ascii_uppercase().as_str(),
6625 "LTRIM" | "RTRIM"
6626 )
6627 && function.args.len() == 2
6628 && Self::is_unbounded_text_cast(&function.args[1]) =>
6629 {
6630 Some("TRIM character set cast to an unbounded text type")
6631 }
6632 _ => None,
6633 }
6634 }
6635
6636 fn strip_postgres_text_literal_cast(expr: Expression) -> Expression {
6637 match expr {
6638 Expression::Cast(cast)
6639 if Self::is_text_data_type(&cast.to)
6640 && Self::postgres_text_literal_value(&cast.this).is_some() =>
6641 {
6642 Self::strip_postgres_text_literal_cast(cast.this)
6643 }
6644 Expression::TryCast(cast)
6645 if Self::is_text_data_type(&cast.to)
6646 && Self::postgres_text_literal_value(&cast.this).is_some() =>
6647 {
6648 Self::strip_postgres_text_literal_cast(cast.this)
6649 }
6650 Expression::SafeCast(cast)
6651 if Self::is_text_data_type(&cast.to)
6652 && Self::postgres_text_literal_value(&cast.this).is_some() =>
6653 {
6654 Self::strip_postgres_text_literal_cast(cast.this)
6655 }
6656 Expression::Paren(mut paren)
6657 if Self::postgres_text_literal_value(&paren.this).is_some() =>
6658 {
6659 paren.this = Self::strip_postgres_text_literal_cast(paren.this);
6660 Expression::Paren(paren)
6661 }
6662 other => other,
6663 }
6664 }
6665
6666 fn postgres_text_literal_value(expr: &Expression) -> Option<&str> {
6667 match expr {
6668 Expression::Literal(literal) if literal.is_string() => Some(literal.value_str()),
6669 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast)
6670 if Self::is_text_data_type(&cast.to) =>
6671 {
6672 Self::postgres_text_literal_value(&cast.this)
6673 }
6674 Expression::Alias(alias) => Self::postgres_text_literal_value(&alias.this),
6675 Expression::Paren(paren) => Self::postgres_text_literal_value(&paren.this),
6676 _ => None,
6677 }
6678 }
6679
6680 fn is_text_data_type(data_type: &DataType) -> bool {
6681 match data_type {
6682 DataType::Char { .. }
6683 | DataType::VarChar { .. }
6684 | DataType::String { .. }
6685 | DataType::Text
6686 | DataType::TextWithLength { .. } => true,
6687 DataType::Custom { name } => {
6688 let base = name
6689 .split_once('(')
6690 .map_or(name.as_str(), |(base, _)| base)
6691 .trim();
6692 matches!(
6693 base.to_ascii_uppercase().as_str(),
6694 "CHAR"
6695 | "NCHAR"
6696 | "VARCHAR"
6697 | "NVARCHAR"
6698 | "TEXT"
6699 | "NTEXT"
6700 | "STRING"
6701 | "CHARACTER VARYING"
6702 )
6703 }
6704 _ => false,
6705 }
6706 }
6707
6708 fn is_unbounded_text_cast(expr: &Expression) -> bool {
6709 let data_type = match expr {
6710 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) => {
6711 &cast.to
6712 }
6713 Expression::Paren(paren) => return Self::is_unbounded_text_cast(&paren.this),
6714 _ => return false,
6715 };
6716
6717 match data_type {
6718 DataType::Text => true,
6719 DataType::VarChar { length: None, .. } | DataType::String { length: None } => true,
6720 DataType::Custom { name } => name.to_ascii_uppercase().contains("(MAX)"),
6721 _ => false,
6722 }
6723 }
6724
6725 fn is_explicitly_numeric_expression(expr: &Expression) -> bool {
6726 if expr.inferred_type().is_some_and(Self::is_numeric_data_type) {
6727 return true;
6728 }
6729
6730 match expr {
6731 Expression::Literal(literal) => literal.is_number(),
6732 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) => {
6733 Self::is_numeric_data_type(&cast.to)
6734 }
6735 Expression::Alias(alias) => Self::is_explicitly_numeric_expression(&alias.this),
6736 Expression::Paren(paren) => Self::is_explicitly_numeric_expression(&paren.this),
6737 Expression::Neg(unary) => Self::is_explicitly_numeric_expression(&unary.this),
6738 _ => false,
6739 }
6740 }
6741
6742 fn is_numeric_data_type(data_type: &DataType) -> bool {
6743 match data_type {
6744 DataType::TinyInt { .. }
6745 | DataType::SmallInt { .. }
6746 | DataType::Int { .. }
6747 | DataType::BigInt { .. }
6748 | DataType::Float { .. }
6749 | DataType::Double { .. }
6750 | DataType::Decimal { .. } => true,
6751 DataType::Custom { name } => {
6752 let base = name
6753 .split_once('(')
6754 .map_or(name.as_str(), |(base, _)| base)
6755 .trim();
6756 matches!(
6757 base.to_ascii_uppercase().as_str(),
6758 "TINYINT"
6759 | "SMALLINT"
6760 | "INT"
6761 | "INTEGER"
6762 | "BIGINT"
6763 | "DECIMAL"
6764 | "NUMERIC"
6765 | "REAL"
6766 | "FLOAT"
6767 | "MONEY"
6768 | "SMALLMONEY"
6769 )
6770 }
6771 _ => false,
6772 }
6773 }
6774
6775 fn normalize_postgres_only_for_tsql(expr: Expression) -> Result<Expression> {
6776 transform_recursive(expr, &|e| match e {
6777 Expression::Table(mut table) if table.only => {
6778 table.only = false;
6779 Ok(Expression::Table(table))
6780 }
6781 other => Ok(other),
6782 })
6783 }
6784
6785 fn rewrite_postgres_json_array_elements_select_for_tsql(
6786 expr: Expression,
6787 ) -> Result<Expression> {
6788 let Expression::Select(select) = expr else {
6789 return Ok(expr);
6790 };
6791 let mut select = *select;
6792 if !Self::is_plain_single_projection_select(&select) {
6793 return Ok(Expression::Select(Box::new(select)));
6794 }
6795
6796 let Some(json_arg) =
6797 Self::postgres_json_array_elements_projection_arg(&select.expressions[0])
6798 else {
6799 return Ok(Expression::Select(Box::new(select)));
6800 };
6801
6802 select.expressions = vec![Expression::column("value")];
6803 select.from = Some(From {
6804 expressions: vec![Expression::OpenJSON(Box::new(
6805 crate::expressions::OpenJSON {
6806 this: Box::new(json_arg),
6807 path: None,
6808 expressions: Vec::new(),
6809 },
6810 ))],
6811 });
6812
6813 Ok(Expression::Select(Box::new(select)))
6814 }
6815
6816 fn is_plain_single_projection_select(select: &crate::expressions::Select) -> bool {
6817 select.expressions.len() == 1
6818 && select.from.is_none()
6819 && select.joins.is_empty()
6820 && select.lateral_views.is_empty()
6821 && select.prewhere.is_none()
6822 && select.where_clause.is_none()
6823 && select.group_by.is_none()
6824 && select.having.is_none()
6825 && select.qualify.is_none()
6826 && select.order_by.is_none()
6827 && select.distribute_by.is_none()
6828 && select.cluster_by.is_none()
6829 && select.sort_by.is_none()
6830 && select.limit.is_none()
6831 && select.offset.is_none()
6832 && select.limit_by.is_none()
6833 && select.fetch.is_none()
6834 && !select.distinct
6835 && select.distinct_on.is_none()
6836 && select.top.is_none()
6837 && select.with.is_none()
6838 && select.sample.is_none()
6839 && select.into.is_none()
6840 && select.locks.is_empty()
6841 && select.for_xml.is_empty()
6842 && select.for_json.is_empty()
6843 && select.exclude.is_none()
6844 }
6845
6846 fn postgres_json_array_elements_projection_arg(expr: &Expression) -> Option<Expression> {
6847 match expr {
6848 Expression::Function(function)
6849 if Self::node_is_postgres_json_array_elements(expr) && function.args.len() == 1 =>
6850 {
6851 Some(function.args[0].clone())
6852 }
6853 Expression::Alias(alias) => {
6854 Self::postgres_json_array_elements_projection_arg(&alias.this)
6855 }
6856 _ => None,
6857 }
6858 }
6859
6860 fn normalize_postgres_type_function_casts(
6861 expr: Expression,
6862 target: DialectType,
6863 ) -> Result<Expression> {
6864 transform_recursive(expr, &|e| match e {
6865 Expression::Function(function) => {
6866 let mut function = *function;
6867 if function.args.len() == 1
6868 && !function.distinct
6869 && !function.quoted
6870 && !function.use_bracket_syntax
6871 && !function.name.contains('.')
6872 {
6873 if let Some(to) = Self::postgres_type_function_data_type(&function.name) {
6874 let this = function.args.remove(0);
6875 let cast = Cast {
6876 this,
6877 to,
6878 trailing_comments: function.trailing_comments,
6879 double_colon_syntax: false,
6880 format: None,
6881 default: None,
6882 inferred_type: function.inferred_type,
6883 };
6884 return Ok(
6885 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
6886 normalization::rewrite_postgres_float_to_integer_cast(cast)
6887 } else {
6888 Expression::Cast(Box::new(cast))
6889 },
6890 );
6891 }
6892 }
6893 Ok(Expression::Function(Box::new(function)))
6894 }
6895 _ => Ok(e),
6896 })
6897 }
6898
6899 fn node_is_postgres_type_function_cast(expr: &Expression) -> bool {
6900 matches!(
6901 expr,
6902 Expression::Function(function)
6903 if !function.quoted
6904 && !function.use_bracket_syntax
6905 && !function.name.contains('.')
6906 && Self::postgres_type_function_data_type(&function.name).is_some()
6907 )
6908 }
6909
6910 fn postgres_type_function_data_type(name: &str) -> Option<DataType> {
6911 match name.to_ascii_uppercase().as_str() {
6912 "NUMERIC" | "DECIMAL" | "DEC" => Some(DataType::Decimal {
6913 precision: None,
6914 scale: None,
6915 }),
6916 "INT2" | "SMALLINT" => Some(DataType::SmallInt { length: None }),
6917 "INT4" | "INT" => Some(DataType::Int {
6918 length: None,
6919 integer_spelling: false,
6920 }),
6921 "INTEGER" => Some(DataType::Int {
6922 length: None,
6923 integer_spelling: true,
6924 }),
6925 "INT8" | "BIGINT" => Some(DataType::BigInt { length: None }),
6926 "FLOAT4" | "REAL" => Some(DataType::Float {
6927 precision: None,
6928 scale: None,
6929 real_spelling: true,
6930 }),
6931 "FLOAT8" => Some(DataType::Double {
6932 precision: None,
6933 scale: None,
6934 }),
6935 "BOOL" | "BOOLEAN" => Some(DataType::Boolean),
6936 "TEXT" => Some(DataType::Text),
6937 "VARCHAR" => Some(DataType::VarChar {
6938 length: None,
6939 parenthesized_length: false,
6940 }),
6941 "UUID" => Some(DataType::Uuid),
6942 _ => None,
6943 }
6944 }
6945
6946 fn rewrite_boolean_values_for_tsql(expr: Expression) -> Result<Expression> {
6947 match expr {
6948 Expression::Select(select) => Self::rewrite_boolean_values_in_tsql_select(select),
6949 Expression::Subquery(mut subquery) => {
6950 subquery.this = Self::rewrite_boolean_values_for_tsql(subquery.this)?;
6951 Ok(Expression::Subquery(subquery))
6952 }
6953 Expression::Union(mut union) => {
6954 let left = std::mem::replace(&mut union.left, Expression::null());
6955 let right = std::mem::replace(&mut union.right, Expression::null());
6956 union.left = Self::rewrite_boolean_values_for_tsql(left)?;
6957 union.right = Self::rewrite_boolean_values_for_tsql(right)?;
6958 if let Some(mut with) = union.with.take() {
6959 with.ctes = with
6960 .ctes
6961 .into_iter()
6962 .map(|mut cte| {
6963 cte.this = Self::rewrite_boolean_values_for_tsql(cte.this)?;
6964 Ok(cte)
6965 })
6966 .collect::<Result<Vec<_>>>()?;
6967 union.with = Some(with);
6968 }
6969 Ok(Expression::Union(union))
6970 }
6971 Expression::Intersect(mut intersect) => {
6972 let left = std::mem::replace(&mut intersect.left, Expression::null());
6973 let right = std::mem::replace(&mut intersect.right, Expression::null());
6974 intersect.left = Self::rewrite_boolean_values_for_tsql(left)?;
6975 intersect.right = Self::rewrite_boolean_values_for_tsql(right)?;
6976 Ok(Expression::Intersect(intersect))
6977 }
6978 Expression::Except(mut except) => {
6979 let left = std::mem::replace(&mut except.left, Expression::null());
6980 let right = std::mem::replace(&mut except.right, Expression::null());
6981 except.left = Self::rewrite_boolean_values_for_tsql(left)?;
6982 except.right = Self::rewrite_boolean_values_for_tsql(right)?;
6983 Ok(Expression::Except(except))
6984 }
6985 other => Self::rewrite_tsql_boolean_nested_contexts(other),
6986 }
6987 }
6988
6989 fn rewrite_postgres_row_value_equality_for_tsql(expr: Expression) -> Result<Expression> {
6990 transform_recursive(expr, &|e| match e {
6991 Expression::Eq(op) => {
6992 let op = *op;
6993 Ok(Self::postgres_row_value_equality_to_tsql_scalar(&op)
6994 .unwrap_or_else(|| Expression::Eq(Box::new(op))))
6995 }
6996 other => Ok(other),
6997 })
6998 }
6999
7000 fn postgres_row_value_equality_to_tsql_scalar(op: &BinaryOp) -> Option<Expression> {
7001 let (row, query) =
7002 if Self::expr_is_row_value(&op.left) && Self::expr_is_subquery_like(&op.right) {
7003 (&op.left, &op.right)
7004 } else if Self::expr_is_row_value(&op.right) && Self::expr_is_subquery_like(&op.left) {
7005 (&op.right, &op.left)
7006 } else {
7007 return None;
7008 };
7009
7010 let row_values = Self::row_value_expressions(row)?;
7011 let projection_count = Self::subquery_projection_count(query)?;
7012 if row_values.is_empty() || row_values.len() != projection_count {
7013 return None;
7014 }
7015
7016 let mut taken_names = HashSet::new();
7021 Self::collect_generated_alias_conflicts(row, &mut taken_names);
7022 Self::collect_generated_alias_conflicts(query, &mut taken_names);
7023
7024 let source_alias = find_new_name(&taken_names, "_polyglot_row");
7025 taken_names.insert(source_alias.to_ascii_lowercase());
7026 let column_aliases = (1..=row_values.len())
7027 .map(|index| {
7028 let name = find_new_name(&taken_names, &format!("_polyglot_row_value_{index}"));
7029 taken_names.insert(name.to_ascii_lowercase());
7030 Identifier::new(name)
7031 })
7032 .collect::<Vec<_>>();
7033 let source = Self::subquery_as_derived_table(
7034 query,
7035 Identifier::new(&source_alias),
7036 column_aliases.clone(),
7037 )?;
7038
7039 let mut equal_components = Vec::with_capacity(row_values.len());
7040 let mut unequal_components = Vec::with_capacity(row_values.len());
7041 for (column, row_value) in column_aliases.into_iter().zip(row_values) {
7042 let projected = Expression::qualified_column(source_alias.clone(), column.name);
7043 equal_components.push(Expression::Eq(Box::new(BinaryOp::new(
7044 projected.clone(),
7045 row_value.clone(),
7046 ))));
7047 unequal_components.push(Expression::Neq(Box::new(BinaryOp::new(
7048 projected, row_value,
7049 ))));
7050 }
7051
7052 let all_equal = equal_components
7053 .into_iter()
7054 .reduce(|left, right| Expression::And(Box::new(BinaryOp::new(left, right))))?;
7055 let any_unequal = unequal_components
7056 .into_iter()
7057 .reduce(|left, right| Expression::Or(Box::new(BinaryOp::new(left, right))))?;
7058 let comparison = Expression::Case(Box::new(Case {
7059 operand: None,
7060 whens: vec![
7061 (all_equal, Expression::number(1)),
7062 (any_unequal, Expression::number(0)),
7063 ],
7064 else_: Some(Expression::null()),
7065 comments: Vec::new(),
7066 inferred_type: None,
7067 }));
7068
7069 let scalar_select = Select::new().column(comparison).from(source);
7070 let scalar_subquery = Expression::Subquery(Box::new(Subquery {
7071 this: Expression::Select(Box::new(scalar_select)),
7072 alias: None,
7073 column_aliases: Vec::new(),
7074 alias_explicit_as: false,
7075 alias_keyword: None,
7076 order_by: None,
7077 limit: None,
7078 offset: None,
7079 distribute_by: None,
7080 sort_by: None,
7081 cluster_by: None,
7082 lateral: false,
7083 modifiers_inside: false,
7084 trailing_comments: Vec::new(),
7085 inferred_type: Some(DataType::Boolean),
7086 }));
7087
7088 Some(Expression::Cast(Box::new(Cast {
7089 this: scalar_subquery,
7090 to: DataType::Boolean,
7091 trailing_comments: Vec::new(),
7092 double_colon_syntax: false,
7093 format: None,
7094 default: None,
7095 inferred_type: Some(DataType::Boolean),
7096 })))
7097 }
7098
7099 fn row_value_expressions(expr: &Expression) -> Option<Vec<Expression>> {
7100 match expr {
7101 Expression::Tuple(tuple) => Some(tuple.expressions.clone()),
7102 Expression::Function(function) if function.name.eq_ignore_ascii_case("ROW") => {
7103 Some(function.args.clone())
7104 }
7105 Expression::Paren(paren) => Self::row_value_expressions(&paren.this),
7106 _ => None,
7107 }
7108 }
7109
7110 fn subquery_projection_count(expr: &Expression) -> Option<usize> {
7111 match expr {
7112 Expression::Select(select) => Some(select.expressions.len()),
7113 Expression::Subquery(subquery) => Self::subquery_projection_count(&subquery.this),
7114 Expression::Paren(paren) => Self::subquery_projection_count(&paren.this),
7115 _ => None,
7116 }
7117 }
7118
7119 fn subquery_as_derived_table(
7120 expr: &Expression,
7121 alias: Identifier,
7122 column_aliases: Vec<Identifier>,
7123 ) -> Option<Expression> {
7124 match expr.clone() {
7125 Expression::Subquery(mut subquery) => {
7126 subquery.alias = Some(alias);
7127 subquery.column_aliases = column_aliases;
7128 subquery.alias_explicit_as = true;
7129 subquery.alias_keyword = None;
7130 Some(Expression::Subquery(subquery))
7131 }
7132 Expression::Select(_) | Expression::Paren(_) => {
7133 Some(Expression::Subquery(Box::new(Subquery {
7134 this: expr.clone(),
7135 alias: Some(alias),
7136 column_aliases,
7137 alias_explicit_as: true,
7138 alias_keyword: None,
7139 order_by: None,
7140 limit: None,
7141 offset: None,
7142 distribute_by: None,
7143 sort_by: None,
7144 cluster_by: None,
7145 lateral: false,
7146 modifiers_inside: false,
7147 trailing_comments: Vec::new(),
7148 inferred_type: None,
7149 })))
7150 }
7151 _ => None,
7152 }
7153 }
7154
7155 fn collect_generated_alias_conflicts(expr: &Expression, names: &mut HashSet<String>) {
7156 fn insert(names: &mut HashSet<String>, identifier: &Identifier) {
7157 if !identifier.name.is_empty() {
7158 names.insert(identifier.name.to_ascii_lowercase());
7159 }
7160 }
7161
7162 for node in expr.dfs() {
7163 match node {
7164 Expression::Identifier(identifier) => insert(names, identifier),
7165 Expression::Column(column) => {
7166 insert(names, &column.name);
7167 if let Some(table) = &column.table {
7168 insert(names, table);
7169 }
7170 }
7171 Expression::Table(table) => {
7172 insert(names, &table.name);
7173 if let Some(schema) = &table.schema {
7174 insert(names, schema);
7175 }
7176 if let Some(catalog) = &table.catalog {
7177 insert(names, catalog);
7178 }
7179 if let Some(alias) = &table.alias {
7180 insert(names, alias);
7181 }
7182 for alias in &table.column_aliases {
7183 insert(names, alias);
7184 }
7185 }
7186 Expression::Alias(alias) => {
7187 insert(names, &alias.alias);
7188 for column_alias in &alias.column_aliases {
7189 insert(names, column_alias);
7190 }
7191 }
7192 Expression::Subquery(subquery) => {
7193 if let Some(alias) = &subquery.alias {
7194 insert(names, alias);
7195 }
7196 for column_alias in &subquery.column_aliases {
7197 insert(names, column_alias);
7198 }
7199 }
7200 Expression::Cte(cte) => {
7201 insert(names, &cte.alias);
7202 for column in &cte.columns {
7203 insert(names, column);
7204 }
7205 for key in &cte.key_expressions {
7206 insert(names, key);
7207 }
7208 }
7209 Expression::Values(values) => {
7210 if let Some(alias) = &values.alias {
7211 insert(names, alias);
7212 }
7213 for column_alias in &values.column_aliases {
7214 insert(names, column_alias);
7215 }
7216 }
7217 Expression::Unnest(unnest) => {
7218 if let Some(alias) = &unnest.alias {
7219 insert(names, alias);
7220 }
7221 if let Some(offset_alias) = &unnest.offset_alias {
7222 insert(names, offset_alias);
7223 }
7224 }
7225 _ => {}
7226 }
7227 }
7228 }
7229
7230 fn rewrite_postgres_format_for_tsql(
7231 expr: Expression,
7232 target: DialectType,
7233 ) -> Result<Expression> {
7234 transform_recursive(expr, &|e| match e {
7235 Expression::Function(f) if f.name.eq_ignore_ascii_case("FORMAT") => {
7236 Self::postgres_format_function_to_tsql(*f, target)
7237 }
7238 other => Ok(other),
7239 })
7240 }
7241
7242 fn postgres_format_function_to_tsql(f: Function, target: DialectType) -> Result<Expression> {
7243 let Some(format_expr) = f.args.first() else {
7244 return Err(Self::unsupported_postgres_format_for_tsql(
7245 target,
7246 "missing format string",
7247 ));
7248 };
7249
7250 let format = match format_expr {
7251 Expression::Literal(lit) if lit.is_string() => lit.value_str(),
7252 _ => {
7253 return Err(Self::unsupported_postgres_format_for_tsql(
7254 target,
7255 "dynamic format strings",
7256 ))
7257 }
7258 };
7259
7260 let value_args = &f.args[1..];
7261 let mut arg_index = 0usize;
7262 let mut literal = String::new();
7263 let mut segments = Vec::new();
7264 let mut chars = format.chars();
7265
7266 while let Some(ch) = chars.next() {
7267 if ch != '%' {
7268 literal.push(ch);
7269 continue;
7270 }
7271
7272 let Some(specifier) = chars.next() else {
7273 return Err(Self::unsupported_postgres_format_for_tsql(
7274 target,
7275 "unterminated format specifier",
7276 ));
7277 };
7278
7279 match specifier {
7280 '%' => literal.push('%'),
7281 's' => {
7282 if !literal.is_empty() {
7283 segments.push(Expression::string(std::mem::take(&mut literal)));
7284 }
7285 let Some(arg) = value_args.get(arg_index) else {
7286 return Err(Self::unsupported_postgres_format_for_tsql(
7287 target,
7288 "not enough arguments",
7289 ));
7290 };
7291 segments.push(arg.clone());
7292 arg_index += 1;
7293 }
7294 other => {
7295 return Err(Self::unsupported_postgres_format_for_tsql(
7296 target,
7297 format!("unsupported format specifier %{other}"),
7298 ))
7299 }
7300 }
7301 }
7302
7303 if !literal.is_empty() {
7304 segments.push(Expression::string(literal));
7305 }
7306
7307 if arg_index != value_args.len() {
7308 return Err(Self::unsupported_postgres_format_for_tsql(
7309 target,
7310 "unused format arguments",
7311 ));
7312 }
7313
7314 Ok(Self::postgres_format_segments_to_tsql_concat(segments))
7315 }
7316
7317 fn postgres_format_segments_to_tsql_concat(mut segments: Vec<Expression>) -> Expression {
7318 if segments.is_empty() {
7319 return Expression::string("");
7320 }
7321
7322 if segments.len() == 1 {
7323 let only = segments.pop().expect("one segment");
7324 if matches!(&only, Expression::Literal(lit) if lit.is_string()) {
7325 return only;
7326 }
7327
7328 return Expression::Function(Box::new(Function::new(
7329 "CONCAT".to_string(),
7330 vec![only, Expression::string("")],
7331 )));
7332 }
7333
7334 Expression::Function(Box::new(Function::new("CONCAT".to_string(), segments)))
7335 }
7336
7337 fn unsupported_postgres_format_for_tsql(
7338 target: DialectType,
7339 reason: impl Into<String>,
7340 ) -> crate::error::Error {
7341 crate::error::Error::unsupported(
7342 format!("PostgreSQL format() ({})", reason.into()),
7343 target.to_string(),
7344 )
7345 }
7346
7347 fn rewrite_boolean_values_in_tsql_select(
7348 mut select: Box<crate::expressions::Select>,
7349 ) -> Result<Expression> {
7350 if let Some(mut with) = select.with.take() {
7351 with.ctes = with
7352 .ctes
7353 .into_iter()
7354 .map(|mut cte| {
7355 cte.this = Self::rewrite_boolean_values_for_tsql(cte.this)?;
7356 Ok(cte)
7357 })
7358 .collect::<Result<Vec<_>>>()?;
7359 select.with = Some(with);
7360 }
7361
7362 select.expressions = select
7363 .expressions
7364 .into_iter()
7365 .map(Self::rewrite_tsql_boolean_scalar_value)
7366 .collect::<Result<Vec<_>>>()?;
7367
7368 if let Some(mut from) = select.from.take() {
7369 from.expressions = from
7370 .expressions
7371 .into_iter()
7372 .map(Self::rewrite_tsql_boolean_nested_contexts)
7373 .collect::<Result<Vec<_>>>()?;
7374 select.from = Some(from);
7375 }
7376
7377 select.joins = select
7378 .joins
7379 .into_iter()
7380 .map(|mut join| {
7381 join.this = Self::rewrite_tsql_boolean_nested_contexts(join.this)?;
7382 if let Some(on) = join.on.take() {
7383 join.on = Some(Self::rewrite_tsql_boolean_predicate_context(on)?);
7384 }
7385 if let Some(match_condition) = join.match_condition.take() {
7386 join.match_condition = Some(Self::rewrite_tsql_boolean_predicate_context(
7387 match_condition,
7388 )?);
7389 }
7390 join.pivots = join
7391 .pivots
7392 .into_iter()
7393 .map(Self::rewrite_tsql_boolean_nested_contexts)
7394 .collect::<Result<Vec<_>>>()?;
7395 Ok(join)
7396 })
7397 .collect::<Result<Vec<_>>>()?;
7398
7399 select.lateral_views = select
7400 .lateral_views
7401 .into_iter()
7402 .map(|mut lateral_view| {
7403 lateral_view.this = Self::rewrite_tsql_boolean_nested_contexts(lateral_view.this)?;
7404 Ok(lateral_view)
7405 })
7406 .collect::<Result<Vec<_>>>()?;
7407
7408 if let Some(prewhere) = select.prewhere.take() {
7409 select.prewhere = Some(Self::rewrite_tsql_boolean_predicate_context(prewhere)?);
7410 }
7411
7412 if let Some(mut where_clause) = select.where_clause.take() {
7413 where_clause.this = Self::rewrite_tsql_boolean_predicate_context(where_clause.this)?;
7414 select.where_clause = Some(where_clause);
7415 }
7416
7417 if let Some(mut group_by) = select.group_by.take() {
7418 group_by.expressions = group_by
7419 .expressions
7420 .into_iter()
7421 .map(Self::rewrite_tsql_boolean_scalar_value)
7422 .collect::<Result<Vec<_>>>()?;
7423 select.group_by = Some(group_by);
7424 }
7425
7426 if let Some(mut having) = select.having.take() {
7427 having.this = Self::rewrite_tsql_boolean_predicate_context(having.this)?;
7428 select.having = Some(having);
7429 }
7430
7431 if let Some(mut qualify) = select.qualify.take() {
7432 qualify.this = Self::rewrite_tsql_boolean_predicate_context(qualify.this)?;
7433 select.qualify = Some(qualify);
7434 }
7435
7436 if let Some(mut order_by) = select.order_by.take() {
7437 order_by.expressions = Self::rewrite_tsql_boolean_ordered_values(order_by.expressions)?;
7438 select.order_by = Some(order_by);
7439 }
7440
7441 if let Some(mut distribute_by) = select.distribute_by.take() {
7442 distribute_by.expressions = distribute_by
7443 .expressions
7444 .into_iter()
7445 .map(Self::rewrite_tsql_boolean_scalar_value)
7446 .collect::<Result<Vec<_>>>()?;
7447 select.distribute_by = Some(distribute_by);
7448 }
7449
7450 if let Some(mut cluster_by) = select.cluster_by.take() {
7451 cluster_by.expressions =
7452 Self::rewrite_tsql_boolean_ordered_values(cluster_by.expressions)?;
7453 select.cluster_by = Some(cluster_by);
7454 }
7455
7456 if let Some(mut sort_by) = select.sort_by.take() {
7457 sort_by.expressions = Self::rewrite_tsql_boolean_ordered_values(sort_by.expressions)?;
7458 select.sort_by = Some(sort_by);
7459 }
7460
7461 if let Some(limit_by) = select.limit_by.take() {
7462 select.limit_by = Some(
7463 limit_by
7464 .into_iter()
7465 .map(Self::rewrite_tsql_boolean_scalar_value)
7466 .collect::<Result<Vec<_>>>()?,
7467 );
7468 }
7469
7470 if let Some(distinct_on) = select.distinct_on.take() {
7471 select.distinct_on = Some(
7472 distinct_on
7473 .into_iter()
7474 .map(Self::rewrite_tsql_boolean_scalar_value)
7475 .collect::<Result<Vec<_>>>()?,
7476 );
7477 }
7478
7479 if let Some(mut sample) = select.sample.take() {
7480 sample.size = Self::rewrite_tsql_boolean_nested_contexts(sample.size)?;
7481 if let Some(offset) = sample.offset.take() {
7482 sample.offset = Some(Self::rewrite_tsql_boolean_nested_contexts(offset)?);
7483 }
7484 if let Some(bucket_numerator) = sample.bucket_numerator.take() {
7485 sample.bucket_numerator = Some(Box::new(
7486 Self::rewrite_tsql_boolean_nested_contexts(*bucket_numerator)?,
7487 ));
7488 }
7489 if let Some(bucket_denominator) = sample.bucket_denominator.take() {
7490 sample.bucket_denominator = Some(Box::new(
7491 Self::rewrite_tsql_boolean_nested_contexts(*bucket_denominator)?,
7492 ));
7493 }
7494 if let Some(bucket_field) = sample.bucket_field.take() {
7495 sample.bucket_field = Some(Box::new(Self::rewrite_tsql_boolean_nested_contexts(
7496 *bucket_field,
7497 )?));
7498 }
7499 select.sample = Some(sample);
7500 }
7501
7502 if let Some(settings) = select.settings.take() {
7503 select.settings = Some(
7504 settings
7505 .into_iter()
7506 .map(Self::rewrite_tsql_boolean_nested_contexts)
7507 .collect::<Result<Vec<_>>>()?,
7508 );
7509 }
7510
7511 if let Some(format) = select.format.take() {
7512 select.format = Some(Self::rewrite_tsql_boolean_nested_contexts(format)?);
7513 }
7514
7515 if let Some(mut windows) = select.windows.take() {
7516 for window in windows.iter_mut() {
7517 Self::rewrite_tsql_boolean_over_values(&mut window.spec)?;
7518 }
7519 select.windows = Some(windows);
7520 }
7521
7522 Ok(Expression::Select(select))
7523 }
7524
7525 fn normalize_postgres_boolean_semantics_for_tsql(expr: Expression) -> Result<Expression> {
7526 transform_recursive(expr, &|e| match e {
7527 Expression::Function(function)
7528 if function.args.len() == 2
7529 && (function.name.eq_ignore_ascii_case("BOOLEQ")
7530 || function.name.eq_ignore_ascii_case("BOOLNE")) =>
7531 {
7532 let is_equal = function.name.eq_ignore_ascii_case("BOOLEQ");
7533 let mut args = function.args.into_iter();
7534 let op = BinaryOp {
7535 left: args.next().expect("checked boolean operator arity"),
7536 right: args.next().expect("checked boolean operator arity"),
7537 left_comments: Vec::new(),
7538 operator_comments: Vec::new(),
7539 trailing_comments: function.trailing_comments,
7540 inferred_type: None,
7541 };
7542 if is_equal {
7543 Ok(Expression::Eq(Box::new(op)))
7544 } else {
7545 Ok(Expression::Neq(Box::new(op)))
7546 }
7547 }
7548 Expression::Cast(cast)
7549 if matches!(cast.to, DataType::Text)
7550 && Self::is_known_postgres_boolean_expression(&cast.this) =>
7551 {
7552 Ok(Self::postgres_boolean_text_value(cast.this))
7553 }
7554 other => Ok(other),
7555 })
7556 }
7557
7558 fn is_known_postgres_boolean_expression(expr: &Expression) -> bool {
7559 match expr {
7560 Expression::Boolean(_) => true,
7561 Expression::Cast(cast) => matches!(cast.to, DataType::Boolean),
7562 Expression::Paren(paren) => Self::is_known_postgres_boolean_expression(&paren.this),
7563 other => Self::is_tsql_boolean_value_expression(other),
7564 }
7565 }
7566
7567 fn postgres_boolean_text_value(predicate: Expression) -> Expression {
7568 if let Expression::Boolean(boolean) = predicate {
7569 return Expression::string(if boolean.value { "true" } else { "false" });
7570 }
7571
7572 Self::three_valued_boolean_case(
7573 predicate,
7574 Expression::string("true"),
7575 Expression::string("false"),
7576 )
7577 }
7578
7579 fn rewrite_tsql_boolean_scalar_value(expr: Expression) -> Result<Expression> {
7580 if let Expression::Boolean(boolean) = expr {
7581 return Ok(Expression::Cast(Box::new(Cast {
7582 this: Expression::Boolean(boolean),
7583 to: DataType::Boolean,
7584 trailing_comments: Vec::new(),
7585 double_colon_syntax: false,
7586 format: None,
7587 default: None,
7588 inferred_type: None,
7589 })));
7590 }
7591
7592 if Self::is_tsql_boolean_value_expression(&expr) {
7593 let can_be_unknown = Self::tsql_boolean_expression_can_be_unknown(&expr)
7596 && !Self::node_is_row_value_subquery_comparison(&expr);
7597 let predicate = Self::rewrite_tsql_boolean_predicate_context(expr)?;
7598 return Ok(Self::tsql_boolean_value_case(predicate, can_be_unknown));
7599 }
7600
7601 match expr {
7602 Expression::Alias(mut alias) => {
7603 alias.this = Self::rewrite_tsql_boolean_scalar_value(alias.this)?;
7604 Ok(Expression::Alias(alias))
7605 }
7606 Expression::Paren(mut paren) => {
7607 paren.this = Self::rewrite_tsql_boolean_scalar_value(paren.this)?;
7608 Ok(Expression::Paren(paren))
7609 }
7610 Expression::Cast(mut cast) => {
7611 cast.this = Self::rewrite_tsql_boolean_scalar_value(cast.this)?;
7612 if let Some(format) = cast.format.take() {
7613 cast.format = Some(Box::new(Self::rewrite_tsql_boolean_nested_contexts(
7614 *format,
7615 )?));
7616 }
7617 if let Some(default) = cast.default.take() {
7618 cast.default =
7619 Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*default)?));
7620 }
7621 Ok(Expression::Cast(cast))
7622 }
7623 Expression::TryCast(mut cast) => {
7624 cast.this = Self::rewrite_tsql_boolean_scalar_value(cast.this)?;
7625 if let Some(format) = cast.format.take() {
7626 cast.format = Some(Box::new(Self::rewrite_tsql_boolean_nested_contexts(
7627 *format,
7628 )?));
7629 }
7630 if let Some(default) = cast.default.take() {
7631 cast.default =
7632 Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*default)?));
7633 }
7634 Ok(Expression::TryCast(cast))
7635 }
7636 Expression::SafeCast(mut cast) => {
7637 cast.this = Self::rewrite_tsql_boolean_scalar_value(cast.this)?;
7638 if let Some(format) = cast.format.take() {
7639 cast.format = Some(Box::new(Self::rewrite_tsql_boolean_nested_contexts(
7640 *format,
7641 )?));
7642 }
7643 if let Some(default) = cast.default.take() {
7644 cast.default =
7645 Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*default)?));
7646 }
7647 Ok(Expression::SafeCast(cast))
7648 }
7649 Expression::Case(mut case) => {
7650 let is_simple_case = case.operand.is_some();
7651 if let Some(operand) = case.operand.take() {
7652 case.operand = Some(Self::rewrite_tsql_boolean_scalar_value(operand)?);
7653 }
7654 case.whens = case
7655 .whens
7656 .into_iter()
7657 .map(|(condition, result)| {
7658 let condition = if is_simple_case {
7659 Self::rewrite_tsql_boolean_scalar_value(condition)?
7660 } else {
7661 Self::rewrite_tsql_boolean_predicate_context(condition)?
7662 };
7663 Ok((condition, Self::rewrite_tsql_boolean_scalar_value(result)?))
7664 })
7665 .collect::<Result<Vec<_>>>()?;
7666 if let Some(else_) = case.else_.take() {
7667 case.else_ = Some(Self::rewrite_tsql_boolean_scalar_value(else_)?);
7668 }
7669 Ok(Expression::Case(case))
7670 }
7671 Expression::IfFunc(mut if_func) => {
7672 if_func.condition =
7673 Self::rewrite_tsql_boolean_predicate_context(if_func.condition)?;
7674 if_func.true_value = Self::rewrite_tsql_boolean_scalar_value(if_func.true_value)?;
7675 if let Some(false_value) = if_func.false_value.take() {
7676 if_func.false_value =
7677 Some(Self::rewrite_tsql_boolean_scalar_value(false_value)?);
7678 }
7679 Ok(Expression::IfFunc(if_func))
7680 }
7681 Expression::WindowFunction(mut window_function) => {
7682 window_function.this =
7683 Self::rewrite_tsql_boolean_nested_contexts(window_function.this)?;
7684 Self::rewrite_tsql_boolean_over_values(&mut window_function.over)?;
7685 if let Some(mut keep) = window_function.keep.take() {
7686 keep.order_by = Self::rewrite_tsql_boolean_ordered_values(keep.order_by)?;
7687 window_function.keep = Some(keep);
7688 }
7689 Ok(Expression::WindowFunction(window_function))
7690 }
7691 Expression::WithinGroup(mut within_group) => {
7692 within_group.this = Self::rewrite_tsql_boolean_nested_contexts(within_group.this)?;
7693 within_group.order_by =
7694 Self::rewrite_tsql_boolean_ordered_values(within_group.order_by)?;
7695 Ok(Expression::WithinGroup(within_group))
7696 }
7697 Expression::Subquery(mut subquery) => {
7698 subquery.this = Self::rewrite_boolean_values_for_tsql(subquery.this)?;
7699 Ok(Expression::Subquery(subquery))
7700 }
7701 Expression::Select(select) => Self::rewrite_boolean_values_in_tsql_select(select),
7702 other => Self::rewrite_tsql_boolean_nested_contexts(other),
7703 }
7704 }
7705
7706 fn rewrite_tsql_boolean_predicate_context(expr: Expression) -> Result<Expression> {
7707 let expr = Self::rewrite_tsql_boolean_nested_contexts(expr)?;
7708 Ok(crate::transforms::ensure_bool_condition(expr))
7709 }
7710
7711 fn rewrite_tsql_boolean_nested_contexts(expr: Expression) -> Result<Expression> {
7712 transform_recursive(expr, &|e| match e {
7713 Expression::Select(select) => Self::rewrite_boolean_values_in_tsql_select(select),
7714 Expression::Subquery(mut subquery) => {
7715 subquery.this = Self::rewrite_boolean_values_for_tsql(subquery.this)?;
7716 Ok(Expression::Subquery(subquery))
7717 }
7718 Expression::Union(_) | Expression::Intersect(_) | Expression::Except(_) => {
7719 Self::rewrite_boolean_values_for_tsql(e)
7720 }
7721 other => Self::rewrite_tsql_boolean_cast_operand(other),
7722 })
7723 }
7724
7725 fn rewrite_tsql_boolean_cast_operand(expr: Expression) -> Result<Expression> {
7726 macro_rules! rewrite_cast_operand {
7727 ($variant:ident, $cast:expr) => {{
7728 let mut cast = $cast;
7729 if Self::is_tsql_boolean_value_expression(&cast.this) {
7730 cast.this = Self::rewrite_tsql_boolean_scalar_value(cast.this)?;
7731 }
7732 Ok(Expression::$variant(cast))
7733 }};
7734 }
7735
7736 match expr {
7737 Expression::Cast(cast) => rewrite_cast_operand!(Cast, cast),
7738 Expression::TryCast(cast) => rewrite_cast_operand!(TryCast, cast),
7739 Expression::SafeCast(cast) => rewrite_cast_operand!(SafeCast, cast),
7740 other => Ok(other),
7741 }
7742 }
7743
7744 fn rewrite_tsql_boolean_ordered_values(
7745 ordered: Vec<crate::expressions::Ordered>,
7746 ) -> Result<Vec<crate::expressions::Ordered>> {
7747 ordered
7748 .into_iter()
7749 .map(|mut ordered| {
7750 ordered.this = Self::rewrite_tsql_boolean_scalar_value(ordered.this)?;
7751 if let Some(with_fill) = ordered.with_fill.take() {
7752 ordered.with_fill = Some(Box::new(
7753 Self::rewrite_tsql_boolean_with_fill_values(*with_fill)?,
7754 ));
7755 }
7756 Ok(ordered)
7757 })
7758 .collect()
7759 }
7760
7761 fn rewrite_tsql_boolean_with_fill_values(
7762 mut with_fill: crate::expressions::WithFill,
7763 ) -> Result<crate::expressions::WithFill> {
7764 if let Some(from) = with_fill.from_.take() {
7765 with_fill.from_ = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*from)?));
7766 }
7767 if let Some(to) = with_fill.to.take() {
7768 with_fill.to = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*to)?));
7769 }
7770 if let Some(step) = with_fill.step.take() {
7771 with_fill.step = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*step)?));
7772 }
7773 if let Some(staleness) = with_fill.staleness.take() {
7774 with_fill.staleness = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(
7775 *staleness,
7776 )?));
7777 }
7778 if let Some(interpolate) = with_fill.interpolate.take() {
7779 with_fill.interpolate = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(
7780 *interpolate,
7781 )?));
7782 }
7783 Ok(with_fill)
7784 }
7785
7786 fn rewrite_tsql_boolean_over_values(over: &mut crate::expressions::Over) -> Result<()> {
7787 over.partition_by = std::mem::take(&mut over.partition_by)
7788 .into_iter()
7789 .map(Self::rewrite_tsql_boolean_scalar_value)
7790 .collect::<Result<Vec<_>>>()?;
7791 over.order_by =
7792 Self::rewrite_tsql_boolean_ordered_values(std::mem::take(&mut over.order_by))?;
7793 Ok(())
7794 }
7795
7796 fn is_tsql_boolean_value_expression(expr: &Expression) -> bool {
7797 match expr {
7798 Expression::Paren(paren) => Self::is_tsql_boolean_value_expression(&paren.this),
7799 Expression::Eq(_)
7800 | Expression::Neq(_)
7801 | Expression::Lt(_)
7802 | Expression::Lte(_)
7803 | Expression::Gt(_)
7804 | Expression::Gte(_)
7805 | Expression::Is(_)
7806 | Expression::IsNull(_)
7807 | Expression::IsTrue(_)
7808 | Expression::IsFalse(_)
7809 | Expression::Like(_)
7810 | Expression::ILike(_)
7811 | Expression::StartsWith(_)
7812 | Expression::SimilarTo(_)
7813 | Expression::Glob(_)
7814 | Expression::RegexpLike(_)
7815 | Expression::In(_)
7816 | Expression::Between(_)
7817 | Expression::Exists(_)
7818 | Expression::And(_)
7819 | Expression::Or(_)
7820 | Expression::Not(_)
7821 | Expression::Any(_)
7822 | Expression::All(_)
7823 | Expression::NullSafeEq(_)
7824 | Expression::NullSafeNeq(_)
7825 | Expression::EqualNull(_) => true,
7826 _ => false,
7827 }
7828 }
7829
7830 fn tsql_boolean_expression_can_be_unknown(expr: &Expression) -> bool {
7831 match expr {
7832 Expression::Boolean(_)
7833 | Expression::IsNull(_)
7834 | Expression::IsTrue(_)
7835 | Expression::IsFalse(_)
7836 | Expression::Exists(_)
7837 | Expression::NullSafeEq(_)
7838 | Expression::NullSafeNeq(_)
7839 | Expression::EqualNull(_) => false,
7840 Expression::Paren(paren) => Self::tsql_boolean_expression_can_be_unknown(&paren.this),
7841 Expression::Not(op) => Self::tsql_boolean_expression_can_be_unknown(&op.this),
7842 Expression::And(op) | Expression::Or(op) => {
7843 Self::tsql_boolean_expression_can_be_unknown(&op.left)
7844 || Self::tsql_boolean_expression_can_be_unknown(&op.right)
7845 }
7846 _ => true,
7847 }
7848 }
7849
7850 fn tsql_boolean_value_case(predicate: Expression, can_be_unknown: bool) -> Expression {
7851 let case = if can_be_unknown {
7852 Self::three_valued_boolean_case(predicate, Expression::number(1), Expression::number(0))
7853 } else {
7854 Expression::Case(Box::new(crate::expressions::Case {
7855 operand: None,
7856 whens: vec![(predicate, Expression::number(1))],
7857 else_: Some(Expression::number(0)),
7858 comments: Vec::new(),
7859 inferred_type: None,
7860 }))
7861 };
7862
7863 Expression::Cast(Box::new(Cast {
7864 this: case,
7865 to: DataType::Boolean,
7866 trailing_comments: Vec::new(),
7867 double_colon_syntax: false,
7868 format: None,
7869 default: None,
7870 inferred_type: None,
7871 }))
7872 }
7873
7874 fn three_valued_boolean_case(
7875 predicate: Expression,
7876 true_value: Expression,
7877 false_value: Expression,
7878 ) -> Expression {
7879 let false_operand = if matches!(predicate, Expression::And(_) | Expression::Or(_)) {
7880 Expression::Paren(Box::new(crate::expressions::Paren {
7881 this: predicate.clone(),
7882 trailing_comments: Vec::new(),
7883 }))
7884 } else {
7885 predicate.clone()
7886 };
7887 let false_predicate = Expression::Not(Box::new(crate::expressions::UnaryOp {
7888 this: false_operand,
7889 inferred_type: None,
7890 }));
7891
7892 Expression::Case(Box::new(crate::expressions::Case {
7893 operand: None,
7894 whens: vec![(predicate, true_value), (false_predicate, false_value)],
7895 else_: Some(Expression::null()),
7896 comments: Vec::new(),
7897 inferred_type: None,
7898 }))
7899 }
7900
7901 fn rewrite_aggregate_filters_for_tsql(expr: Expression) -> Result<Expression> {
7902 transform_recursive(expr, &|e| Self::rewrite_aggregate_filter_for_tsql(e))
7903 }
7904
7905 fn rewrite_aggregate_filter_for_tsql(expr: Expression) -> Result<Expression> {
7906 macro_rules! rewrite_agg_filter {
7907 ($variant:ident, $agg:expr) => {{
7908 let mut agg = $agg;
7909 if let Some(filter) = agg.filter.take() {
7910 let this = std::mem::replace(&mut agg.this, Expression::null());
7911 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
7912 }
7913 Ok(Expression::$variant(agg))
7914 }};
7915 }
7916
7917 match expr {
7918 Expression::Filter(filter) => {
7919 let condition = match *filter.expression {
7920 Expression::Where(where_) => where_.this,
7921 other => other,
7922 };
7923 Ok(Self::push_filter_into_tsql_aggregate(
7924 *filter.this,
7925 condition,
7926 ))
7927 }
7928 Expression::AggregateFunction(mut agg) => {
7929 if let Some(filter) = agg.filter.take() {
7930 Self::rewrite_generic_aggregate_filter_for_tsql(&mut agg, filter);
7931 }
7932 Ok(Expression::AggregateFunction(agg))
7933 }
7934 Expression::Count(mut count) => {
7935 if let Some(filter) = count.filter.take() {
7936 let value = if count.star {
7937 Expression::number(1)
7938 } else {
7939 count.this.take().unwrap_or_else(|| Expression::number(1))
7940 };
7941 count.star = false;
7942 count.this = Some(Self::conditional_aggregate_value_for_tsql(filter, value));
7943 }
7944 Ok(Expression::Count(count))
7945 }
7946 Expression::Sum(agg) => rewrite_agg_filter!(Sum, agg),
7947 Expression::Avg(agg) => rewrite_agg_filter!(Avg, agg),
7948 Expression::Min(agg) => rewrite_agg_filter!(Min, agg),
7949 Expression::Max(agg) => rewrite_agg_filter!(Max, agg),
7950 Expression::ArrayAgg(agg) => rewrite_agg_filter!(ArrayAgg, agg),
7951 Expression::CountIf(agg) => Ok(Expression::CountIf(agg)),
7952 Expression::Stddev(agg) => rewrite_agg_filter!(Stddev, agg),
7953 Expression::StddevPop(agg) => rewrite_agg_filter!(StddevPop, agg),
7954 Expression::StddevSamp(agg) => rewrite_agg_filter!(StddevSamp, agg),
7955 Expression::Variance(agg) => rewrite_agg_filter!(Variance, agg),
7956 Expression::VarPop(agg) => rewrite_agg_filter!(VarPop, agg),
7957 Expression::VarSamp(agg) => rewrite_agg_filter!(VarSamp, agg),
7958 Expression::Median(agg) => rewrite_agg_filter!(Median, agg),
7959 Expression::Mode(agg) => rewrite_agg_filter!(Mode, agg),
7960 Expression::First(agg) => rewrite_agg_filter!(First, agg),
7961 Expression::Last(agg) => rewrite_agg_filter!(Last, agg),
7962 Expression::AnyValue(agg) => rewrite_agg_filter!(AnyValue, agg),
7963 Expression::ApproxDistinct(agg) => rewrite_agg_filter!(ApproxDistinct, agg),
7964 Expression::ApproxCountDistinct(agg) => {
7965 rewrite_agg_filter!(ApproxCountDistinct, agg)
7966 }
7967 Expression::LogicalAnd(agg) => rewrite_agg_filter!(LogicalAnd, agg),
7968 Expression::LogicalOr(agg) => rewrite_agg_filter!(LogicalOr, agg),
7969 Expression::Skewness(agg) => rewrite_agg_filter!(Skewness, agg),
7970 Expression::ArrayConcatAgg(agg) => rewrite_agg_filter!(ArrayConcatAgg, agg),
7971 Expression::ArrayUniqueAgg(agg) => rewrite_agg_filter!(ArrayUniqueAgg, agg),
7972 Expression::BoolXorAgg(agg) => rewrite_agg_filter!(BoolXorAgg, agg),
7973 Expression::BitwiseAndAgg(agg) => rewrite_agg_filter!(BitwiseAndAgg, agg),
7974 Expression::BitwiseOrAgg(agg) => rewrite_agg_filter!(BitwiseOrAgg, agg),
7975 Expression::BitwiseXorAgg(agg) => rewrite_agg_filter!(BitwiseXorAgg, agg),
7976 Expression::StringAgg(mut agg) => {
7977 if let Some(filter) = agg.filter.take() {
7978 let this = std::mem::replace(&mut agg.this, Expression::null());
7979 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
7980 }
7981 Ok(Expression::StringAgg(agg))
7982 }
7983 Expression::GroupConcat(mut agg) => {
7984 if let Some(filter) = agg.filter.take() {
7985 let this = std::mem::replace(&mut agg.this, Expression::null());
7986 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
7987 }
7988 Ok(Expression::GroupConcat(agg))
7989 }
7990 Expression::ListAgg(mut agg) => {
7991 if let Some(filter) = agg.filter.take() {
7992 let this = std::mem::replace(&mut agg.this, Expression::null());
7993 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
7994 }
7995 Ok(Expression::ListAgg(agg))
7996 }
7997 Expression::WithinGroup(mut within_group) => {
7998 within_group.this = Self::rewrite_aggregate_filters_for_tsql(within_group.this)?;
7999 Ok(Expression::WithinGroup(within_group))
8000 }
8001 other => Ok(other),
8002 }
8003 }
8004
8005 fn push_filter_into_tsql_aggregate(expr: Expression, filter: Expression) -> Expression {
8006 macro_rules! push_agg_filter {
8007 ($variant:ident, $agg:expr) => {{
8008 let mut agg = $agg;
8009 let this = std::mem::replace(&mut agg.this, Expression::null());
8010 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
8011 agg.filter = None;
8012 Expression::$variant(agg)
8013 }};
8014 }
8015
8016 match expr {
8017 Expression::AggregateFunction(mut agg) => {
8018 Self::rewrite_generic_aggregate_filter_for_tsql(&mut agg, filter);
8019 Expression::AggregateFunction(agg)
8020 }
8021 Expression::Count(mut count) => {
8022 let value = if count.star {
8023 Expression::number(1)
8024 } else {
8025 count.this.take().unwrap_or_else(|| Expression::number(1))
8026 };
8027 count.star = false;
8028 count.filter = None;
8029 count.this = Some(Self::conditional_aggregate_value_for_tsql(filter, value));
8030 Expression::Count(count)
8031 }
8032 Expression::Sum(agg) => push_agg_filter!(Sum, agg),
8033 Expression::Avg(agg) => push_agg_filter!(Avg, agg),
8034 Expression::Min(agg) => push_agg_filter!(Min, agg),
8035 Expression::Max(agg) => push_agg_filter!(Max, agg),
8036 Expression::ArrayAgg(agg) => push_agg_filter!(ArrayAgg, agg),
8037 Expression::CountIf(mut agg) => {
8038 agg.filter = Some(filter);
8039 Expression::CountIf(agg)
8040 }
8041 Expression::Stddev(agg) => push_agg_filter!(Stddev, agg),
8042 Expression::StddevPop(agg) => push_agg_filter!(StddevPop, agg),
8043 Expression::StddevSamp(agg) => push_agg_filter!(StddevSamp, agg),
8044 Expression::Variance(agg) => push_agg_filter!(Variance, agg),
8045 Expression::VarPop(agg) => push_agg_filter!(VarPop, agg),
8046 Expression::VarSamp(agg) => push_agg_filter!(VarSamp, agg),
8047 Expression::Median(agg) => push_agg_filter!(Median, agg),
8048 Expression::Mode(agg) => push_agg_filter!(Mode, agg),
8049 Expression::First(agg) => push_agg_filter!(First, agg),
8050 Expression::Last(agg) => push_agg_filter!(Last, agg),
8051 Expression::AnyValue(agg) => push_agg_filter!(AnyValue, agg),
8052 Expression::ApproxDistinct(agg) => push_agg_filter!(ApproxDistinct, agg),
8053 Expression::ApproxCountDistinct(agg) => {
8054 push_agg_filter!(ApproxCountDistinct, agg)
8055 }
8056 Expression::LogicalAnd(agg) => push_agg_filter!(LogicalAnd, agg),
8057 Expression::LogicalOr(agg) => push_agg_filter!(LogicalOr, agg),
8058 Expression::Skewness(agg) => push_agg_filter!(Skewness, agg),
8059 Expression::ArrayConcatAgg(agg) => push_agg_filter!(ArrayConcatAgg, agg),
8060 Expression::ArrayUniqueAgg(agg) => push_agg_filter!(ArrayUniqueAgg, agg),
8061 Expression::BoolXorAgg(agg) => push_agg_filter!(BoolXorAgg, agg),
8062 Expression::BitwiseAndAgg(agg) => push_agg_filter!(BitwiseAndAgg, agg),
8063 Expression::BitwiseOrAgg(agg) => push_agg_filter!(BitwiseOrAgg, agg),
8064 Expression::BitwiseXorAgg(agg) => push_agg_filter!(BitwiseXorAgg, agg),
8065 Expression::StringAgg(mut agg) => {
8066 let this = std::mem::replace(&mut agg.this, Expression::null());
8067 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
8068 agg.filter = None;
8069 Expression::StringAgg(agg)
8070 }
8071 Expression::GroupConcat(mut agg) => {
8072 let this = std::mem::replace(&mut agg.this, Expression::null());
8073 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
8074 agg.filter = None;
8075 Expression::GroupConcat(agg)
8076 }
8077 Expression::ListAgg(mut agg) => {
8078 let this = std::mem::replace(&mut agg.this, Expression::null());
8079 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
8080 agg.filter = None;
8081 Expression::ListAgg(agg)
8082 }
8083 Expression::WithinGroup(mut within_group) => {
8084 within_group.this =
8085 Self::push_filter_into_tsql_aggregate(within_group.this, filter);
8086 Expression::WithinGroup(within_group)
8087 }
8088 other => Expression::Filter(Box::new(crate::expressions::Filter {
8089 this: Box::new(other),
8090 expression: Box::new(filter),
8091 })),
8092 }
8093 }
8094
8095 fn rewrite_generic_aggregate_filter_for_tsql(
8096 agg: &mut crate::expressions::AggregateFunction,
8097 filter: Expression,
8098 ) {
8099 let is_count =
8100 agg.name.eq_ignore_ascii_case("COUNT") || agg.name.eq_ignore_ascii_case("COUNT_BIG");
8101 let is_count_star = is_count
8102 && (agg.args.is_empty()
8103 || (agg.args.len() == 1 && matches!(agg.args[0], Expression::Star(_))));
8104
8105 if is_count_star {
8106 agg.args = vec![Self::conditional_aggregate_value_for_tsql(
8107 filter,
8108 Expression::number(1),
8109 )];
8110 } else if !agg.args.is_empty() {
8111 agg.args = agg
8112 .args
8113 .drain(..)
8114 .map(|arg| Self::conditional_aggregate_value_for_tsql(filter.clone(), arg))
8115 .collect();
8116 } else {
8117 agg.filter = Some(filter);
8118 }
8119 }
8120
8121 fn conditional_aggregate_value_for_tsql(filter: Expression, value: Expression) -> Expression {
8122 let filter = crate::transforms::ensure_bool_condition(filter);
8123 Expression::Case(Box::new(crate::expressions::Case {
8124 operand: None,
8125 whens: vec![(filter, value)],
8126 else_: None,
8127 comments: Vec::new(),
8128 inferred_type: None,
8129 }))
8130 }
8131
8132 fn reject_pgvector_distance_operators_for_sqlite(&self, sql: &str) -> Result<()> {
8133 let tokens = self.tokenize(sql)?;
8134 for (i, token) in tokens.iter().enumerate() {
8135 if token.token_type == TokenType::NullsafeEq {
8136 return Err(crate::error::Error::unsupported(
8137 "PostgreSQL pgvector cosine distance operator <=>",
8138 "SQLite",
8139 ));
8140 }
8141 if token.token_type == TokenType::Lt
8142 && tokens
8143 .get(i + 1)
8144 .is_some_and(|token| token.token_type == TokenType::Tilde)
8145 && tokens
8146 .get(i + 2)
8147 .is_some_and(|token| token.token_type == TokenType::Gt)
8148 {
8149 return Err(crate::error::Error::unsupported(
8150 "PostgreSQL pgvector Hamming distance operator <~>",
8151 "SQLite",
8152 ));
8153 }
8154 }
8155 Ok(())
8156 }
8157
8158 fn normalize_sqlite_double_quoted_defaults(expr: Expression) -> Result<Expression> {
8159 fn normalize_default_expr(expr: Expression) -> Result<Expression> {
8160 transform_recursive(expr, &|e| match e {
8161 Expression::Column(col)
8162 if col.table.is_none() && col.name.quoted && !col.join_mark =>
8163 {
8164 Ok(Expression::Literal(Box::new(Literal::String(
8165 col.name.name,
8166 ))))
8167 }
8168 Expression::Identifier(id) if id.quoted => {
8169 Ok(Expression::Literal(Box::new(Literal::String(id.name))))
8170 }
8171 _ => Ok(e),
8172 })
8173 }
8174
8175 fn normalize_column_default(col: &mut crate::expressions::ColumnDef) -> Result<()> {
8176 if let Some(default) = col.default.take() {
8177 col.default = Some(normalize_default_expr(default)?);
8178 }
8179
8180 for constraint in &mut col.constraints {
8181 if let ColumnConstraint::Default(default) = constraint {
8182 *default = normalize_default_expr(default.clone())?;
8183 }
8184 }
8185
8186 Ok(())
8187 }
8188
8189 transform_recursive(expr, &|e| match e {
8190 Expression::CreateTable(mut ct) => {
8191 for column in &mut ct.columns {
8192 normalize_column_default(column)?;
8193 }
8194 Ok(Expression::CreateTable(ct))
8195 }
8196 Expression::ColumnDef(mut col) => {
8197 normalize_column_default(&mut col)?;
8198 Ok(Expression::ColumnDef(col))
8199 }
8200 _ => Ok(e),
8201 })
8202 }
8203
8204 fn normalize_postgres_to_sqlite_types(expr: Expression) -> Result<Expression> {
8205 fn sqlite_type(dt: crate::expressions::DataType) -> crate::expressions::DataType {
8206 use crate::expressions::DataType;
8207
8208 match dt {
8209 DataType::Bit { .. } => DataType::Int {
8210 length: None,
8211 integer_spelling: true,
8212 },
8213 DataType::TextWithLength { .. } => DataType::Text,
8214 DataType::VarChar { .. } => DataType::Text,
8215 DataType::Char { .. } => DataType::Text,
8216 DataType::Timestamp { timezone: true, .. } => DataType::Text,
8217 DataType::Custom { name } => {
8218 let base = name
8219 .split_once('(')
8220 .map_or(name.as_str(), |(base, _)| base)
8221 .trim();
8222 if base.eq_ignore_ascii_case("TSVECTOR")
8223 || base.eq_ignore_ascii_case("TIMESTAMPTZ")
8224 || base.eq_ignore_ascii_case("TIMESTAMP WITH TIME ZONE")
8225 || base.eq_ignore_ascii_case("NVARCHAR")
8226 || base.eq_ignore_ascii_case("NCHAR")
8227 {
8228 DataType::Text
8229 } else {
8230 DataType::Custom { name }
8231 }
8232 }
8233 _ => dt,
8234 }
8235 }
8236
8237 transform_recursive(expr, &|e| match e {
8238 Expression::DataType(dt) => Ok(Expression::DataType(sqlite_type(dt))),
8239 Expression::CreateTable(mut ct) => {
8240 for column in &mut ct.columns {
8241 column.data_type = sqlite_type(column.data_type.clone());
8242 }
8243 Ok(Expression::CreateTable(ct))
8244 }
8245 _ => Ok(e),
8246 })
8247 }
8248
8249 fn normalize_postgres_to_fabric_types(expr: Expression) -> Result<Expression> {
8250 fn fabric_type(dt: crate::expressions::DataType) -> crate::expressions::DataType {
8251 use crate::expressions::DataType;
8252
8253 match dt {
8254 DataType::Decimal {
8255 precision: None,
8256 scale: None,
8257 } => DataType::Decimal {
8258 precision: Some(38),
8259 scale: Some(10),
8260 },
8261 DataType::Json | DataType::JsonB => DataType::Custom {
8262 name: "VARCHAR(MAX)".to_string(),
8263 },
8264 _ => dt,
8265 }
8266 }
8267
8268 transform_recursive(expr, &|e| match e {
8269 Expression::DataType(dt) => Ok(Expression::DataType(fabric_type(dt))),
8270 Expression::CreateTable(mut ct) => {
8271 for column in &mut ct.columns {
8272 column.data_type = fabric_type(column.data_type.clone());
8273 }
8274 Ok(Expression::CreateTable(ct))
8275 }
8276 Expression::ColumnDef(mut col) => {
8277 col.data_type = fabric_type(col.data_type);
8278 Ok(Expression::ColumnDef(col))
8279 }
8280 _ => Ok(e),
8281 })
8282 }
8283
8284 fn seq_rownum_to_range(expr: Expression) -> Result<Expression> {
8288 if let Expression::Select(mut select) = expr {
8289 let has_range_from = if let Some(ref from) = select.from {
8291 from.expressions.iter().any(|e| {
8292 match e {
8294 Expression::Function(f) => f.name.eq_ignore_ascii_case("RANGE"),
8295 Expression::Alias(a) => {
8296 matches!(&a.this, Expression::Function(f) if f.name.eq_ignore_ascii_case("RANGE"))
8297 }
8298 _ => false,
8299 }
8300 })
8301 } else {
8302 false
8303 };
8304
8305 if has_range_from {
8306 select.expressions = select
8308 .expressions
8309 .into_iter()
8310 .map(|e| Self::replace_rownum_with_range(e))
8311 .collect();
8312 }
8313
8314 Ok(Expression::Select(select))
8315 } else {
8316 Ok(expr)
8317 }
8318 }
8319
8320 fn replace_rownum_with_range(expr: Expression) -> Expression {
8322 match expr {
8323 Expression::Mod(op) => {
8325 let new_left = Self::try_replace_rownum_paren(&op.left);
8326 Expression::Mod(Box::new(crate::expressions::BinaryOp {
8327 left: new_left,
8328 right: op.right,
8329 left_comments: op.left_comments,
8330 operator_comments: op.operator_comments,
8331 trailing_comments: op.trailing_comments,
8332 inferred_type: op.inferred_type,
8333 }))
8334 }
8335 Expression::Paren(p) => {
8337 let inner = Self::replace_rownum_with_range(p.this);
8338 Expression::Paren(Box::new(crate::expressions::Paren {
8339 this: inner,
8340 trailing_comments: p.trailing_comments,
8341 }))
8342 }
8343 Expression::Case(mut c) => {
8344 c.whens = c
8346 .whens
8347 .into_iter()
8348 .map(|(cond, then)| {
8349 (
8350 Self::replace_rownum_with_range(cond),
8351 Self::replace_rownum_with_range(then),
8352 )
8353 })
8354 .collect();
8355 if let Some(else_) = c.else_ {
8356 c.else_ = Some(Self::replace_rownum_with_range(else_));
8357 }
8358 Expression::Case(c)
8359 }
8360 Expression::Gte(op) => Expression::Gte(Box::new(crate::expressions::BinaryOp {
8361 left: Self::replace_rownum_with_range(op.left),
8362 right: op.right,
8363 left_comments: op.left_comments,
8364 operator_comments: op.operator_comments,
8365 trailing_comments: op.trailing_comments,
8366 inferred_type: op.inferred_type,
8367 })),
8368 Expression::Sub(op) => Expression::Sub(Box::new(crate::expressions::BinaryOp {
8369 left: Self::replace_rownum_with_range(op.left),
8370 right: op.right,
8371 left_comments: op.left_comments,
8372 operator_comments: op.operator_comments,
8373 trailing_comments: op.trailing_comments,
8374 inferred_type: op.inferred_type,
8375 })),
8376 Expression::Alias(mut a) => {
8377 a.this = Self::replace_rownum_with_range(a.this);
8378 Expression::Alias(a)
8379 }
8380 other => other,
8381 }
8382 }
8383
8384 fn try_replace_rownum_paren(expr: &Expression) -> Expression {
8386 if let Expression::Paren(ref p) = expr {
8387 if let Expression::Sub(ref sub) = p.this {
8388 if let Expression::WindowFunction(ref wf) = sub.left {
8389 if let Expression::Function(ref f) = wf.this {
8390 if f.name.eq_ignore_ascii_case("ROW_NUMBER") {
8391 if let Expression::Literal(ref lit) = sub.right {
8392 if let crate::expressions::Literal::Number(ref n) = lit.as_ref() {
8393 if n == "1" {
8394 return Expression::column("range");
8395 }
8396 }
8397 }
8398 }
8399 }
8400 }
8401 }
8402 }
8403 expr.clone()
8404 }
8405
8406 fn transform_generate_date_array_snowflake(expr: Expression) -> Result<Expression> {
8413 use crate::expressions::*;
8414 transform_recursive(expr, &|e| {
8415 if let Expression::ArraySize(ref af) = e {
8417 if let Expression::Function(ref f) = af.this {
8418 if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") && f.args.len() >= 2 {
8419 let result = Self::convert_array_size_gda_snowflake(f)?;
8420 return Ok(result);
8421 }
8422 }
8423 }
8424
8425 let Expression::Select(mut sel) = e else {
8426 return Ok(e);
8427 };
8428
8429 let mut gda_info: Option<(String, Expression, Expression, String)> = None; let mut gda_join_idx: Option<usize> = None;
8432
8433 for (idx, join) in sel.joins.iter().enumerate() {
8434 let (unnest_ref, alias_name) = match &join.this {
8438 Expression::Unnest(ref unnest) => {
8439 let alias = unnest.alias.as_ref().map(|id| id.name.clone());
8440 (Some(unnest.as_ref()), alias)
8441 }
8442 Expression::Alias(ref a) => {
8443 if let Expression::Unnest(ref unnest) = a.this {
8444 (Some(unnest.as_ref()), Some(a.alias.name.clone()))
8445 } else {
8446 (None, None)
8447 }
8448 }
8449 _ => (None, None),
8450 };
8451
8452 if let (Some(unnest), Some(alias)) = (unnest_ref, alias_name) {
8453 if let Expression::Function(ref f) = unnest.this {
8455 if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") && f.args.len() >= 2 {
8456 let start_expr = f.args[0].clone();
8457 let end_expr = f.args[1].clone();
8458 let step = f.args.get(2).cloned();
8459
8460 let unit = if let Some(Expression::Interval(ref iv)) = step {
8462 if let Some(IntervalUnitSpec::Simple { ref unit, .. }) = iv.unit {
8463 Some(format!("{:?}", unit).to_ascii_uppercase())
8464 } else if let Some(ref this) = iv.this {
8465 if let Expression::Literal(lit) = this {
8467 if let Literal::String(ref s) = lit.as_ref() {
8468 let parts: Vec<&str> = s.split_whitespace().collect();
8469 if parts.len() == 2 {
8470 Some(parts[1].to_ascii_uppercase())
8471 } else if parts.len() == 1 {
8472 let upper = parts[0].to_ascii_uppercase();
8474 if matches!(
8475 upper.as_str(),
8476 "YEAR"
8477 | "QUARTER"
8478 | "MONTH"
8479 | "WEEK"
8480 | "DAY"
8481 | "HOUR"
8482 | "MINUTE"
8483 | "SECOND"
8484 ) {
8485 Some(upper)
8486 } else {
8487 None
8488 }
8489 } else {
8490 None
8491 }
8492 } else {
8493 None
8494 }
8495 } else {
8496 None
8497 }
8498 } else {
8499 None
8500 }
8501 } else {
8502 None
8503 };
8504
8505 if let Some(unit_str) = unit {
8506 gda_info = Some((alias, start_expr, end_expr, unit_str));
8507 gda_join_idx = Some(idx);
8508 }
8509 }
8510 }
8511 }
8512 if gda_info.is_some() {
8513 break;
8514 }
8515 }
8516
8517 let Some((alias_name, start_expr, end_expr, unit_str)) = gda_info else {
8518 let result = Self::try_transform_from_gda_snowflake(sel);
8521 return result;
8522 };
8523 let join_idx = gda_join_idx.unwrap();
8524
8525 let datediff = Expression::Function(Box::new(Function::new(
8529 "DATEDIFF".to_string(),
8530 vec![
8531 Expression::boxed_column(Column {
8532 name: Identifier::new(&unit_str),
8533 table: None,
8534 join_mark: false,
8535 trailing_comments: vec![],
8536 span: None,
8537 inferred_type: None,
8538 }),
8539 start_expr.clone(),
8540 end_expr.clone(),
8541 ],
8542 )));
8543 let datediff_plus_one = Expression::Add(Box::new(BinaryOp {
8544 left: datediff,
8545 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
8546 left_comments: vec![],
8547 operator_comments: vec![],
8548 trailing_comments: vec![],
8549 inferred_type: None,
8550 }));
8551
8552 let array_gen_range = Expression::Function(Box::new(Function::new(
8553 "ARRAY_GENERATE_RANGE".to_string(),
8554 vec![
8555 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
8556 datediff_plus_one,
8557 ],
8558 )));
8559
8560 let flatten_input = Expression::NamedArgument(Box::new(NamedArgument {
8562 name: Identifier::new("INPUT"),
8563 value: array_gen_range,
8564 separator: crate::expressions::NamedArgSeparator::DArrow,
8565 }));
8566 let flatten = Expression::Function(Box::new(Function::new(
8567 "FLATTEN".to_string(),
8568 vec![flatten_input],
8569 )));
8570
8571 let alias_table = Alias {
8573 this: flatten,
8574 alias: Identifier::new("_t0"),
8575 column_aliases: vec![
8576 Identifier::new("seq"),
8577 Identifier::new("key"),
8578 Identifier::new("path"),
8579 Identifier::new("index"),
8580 Identifier::new(&alias_name),
8581 Identifier::new("this"),
8582 ],
8583 alias_explicit_as: false,
8584 alias_keyword: None,
8585 pre_alias_comments: vec![],
8586 trailing_comments: vec![],
8587 inferred_type: None,
8588 };
8589 let lateral_expr = Expression::Lateral(Box::new(Lateral {
8590 this: Box::new(Expression::Alias(Box::new(alias_table))),
8591 view: None,
8592 outer: None,
8593 alias: None,
8594 alias_quoted: false,
8595 cross_apply: None,
8596 ordinality: None,
8597 column_aliases: vec![],
8598 }));
8599
8600 sel.joins.remove(join_idx);
8602 if let Some(ref mut from) = sel.from {
8603 from.expressions.push(lateral_expr);
8604 }
8605
8606 let dateadd_expr = Expression::Function(Box::new(Function::new(
8608 "DATEADD".to_string(),
8609 vec![
8610 Expression::boxed_column(Column {
8611 name: Identifier::new(&unit_str),
8612 table: None,
8613 join_mark: false,
8614 trailing_comments: vec![],
8615 span: None,
8616 inferred_type: None,
8617 }),
8618 Expression::Cast(Box::new(Cast {
8619 this: Expression::boxed_column(Column {
8620 name: Identifier::new(&alias_name),
8621 table: None,
8622 join_mark: false,
8623 trailing_comments: vec![],
8624 span: None,
8625 inferred_type: None,
8626 }),
8627 to: DataType::Int {
8628 length: None,
8629 integer_spelling: false,
8630 },
8631 trailing_comments: vec![],
8632 double_colon_syntax: false,
8633 format: None,
8634 default: None,
8635 inferred_type: None,
8636 })),
8637 Expression::Cast(Box::new(Cast {
8638 this: start_expr.clone(),
8639 to: DataType::Date,
8640 trailing_comments: vec![],
8641 double_colon_syntax: false,
8642 format: None,
8643 default: None,
8644 inferred_type: None,
8645 })),
8646 ],
8647 )));
8648
8649 let new_exprs: Vec<Expression> = sel
8651 .expressions
8652 .iter()
8653 .map(|expr| Self::replace_column_ref_with_dateadd(expr, &alias_name, &dateadd_expr))
8654 .collect();
8655 sel.expressions = new_exprs;
8656
8657 Ok(Expression::Select(sel))
8658 })
8659 }
8660
8661 fn replace_column_ref_with_dateadd(
8663 expr: &Expression,
8664 alias_name: &str,
8665 dateadd: &Expression,
8666 ) -> Expression {
8667 use crate::expressions::*;
8668 match expr {
8669 Expression::Column(c) if c.name.name == alias_name && c.table.is_none() => {
8670 Expression::Alias(Box::new(Alias {
8672 this: dateadd.clone(),
8673 alias: Identifier::new(alias_name),
8674 column_aliases: vec![],
8675 alias_explicit_as: false,
8676 alias_keyword: None,
8677 pre_alias_comments: vec![],
8678 trailing_comments: vec![],
8679 inferred_type: None,
8680 }))
8681 }
8682 Expression::Alias(a) => {
8683 let new_this = Self::replace_column_ref_inner(&a.this, alias_name, dateadd);
8685 Expression::Alias(Box::new(Alias {
8686 this: new_this,
8687 alias: a.alias.clone(),
8688 column_aliases: a.column_aliases.clone(),
8689 alias_explicit_as: false,
8690 alias_keyword: None,
8691 pre_alias_comments: a.pre_alias_comments.clone(),
8692 trailing_comments: a.trailing_comments.clone(),
8693 inferred_type: None,
8694 }))
8695 }
8696 _ => expr.clone(),
8697 }
8698 }
8699
8700 fn replace_column_ref_inner(
8702 expr: &Expression,
8703 alias_name: &str,
8704 dateadd: &Expression,
8705 ) -> Expression {
8706 use crate::expressions::*;
8707 match expr {
8708 Expression::Column(c) if c.name.name == alias_name && c.table.is_none() => {
8709 dateadd.clone()
8710 }
8711 Expression::Add(op) => {
8712 let left = Self::replace_column_ref_inner(&op.left, alias_name, dateadd);
8713 let right = Self::replace_column_ref_inner(&op.right, alias_name, dateadd);
8714 Expression::Add(Box::new(BinaryOp {
8715 left,
8716 right,
8717 left_comments: op.left_comments.clone(),
8718 operator_comments: op.operator_comments.clone(),
8719 trailing_comments: op.trailing_comments.clone(),
8720 inferred_type: None,
8721 }))
8722 }
8723 Expression::Sub(op) => {
8724 let left = Self::replace_column_ref_inner(&op.left, alias_name, dateadd);
8725 let right = Self::replace_column_ref_inner(&op.right, alias_name, dateadd);
8726 Expression::Sub(Box::new(BinaryOp {
8727 left,
8728 right,
8729 left_comments: op.left_comments.clone(),
8730 operator_comments: op.operator_comments.clone(),
8731 trailing_comments: op.trailing_comments.clone(),
8732 inferred_type: None,
8733 }))
8734 }
8735 Expression::Mul(op) => {
8736 let left = Self::replace_column_ref_inner(&op.left, alias_name, dateadd);
8737 let right = Self::replace_column_ref_inner(&op.right, alias_name, dateadd);
8738 Expression::Mul(Box::new(BinaryOp {
8739 left,
8740 right,
8741 left_comments: op.left_comments.clone(),
8742 operator_comments: op.operator_comments.clone(),
8743 trailing_comments: op.trailing_comments.clone(),
8744 inferred_type: None,
8745 }))
8746 }
8747 _ => expr.clone(),
8748 }
8749 }
8750
8751 fn try_transform_from_gda_snowflake(
8754 mut sel: Box<crate::expressions::Select>,
8755 ) -> Result<Expression> {
8756 use crate::expressions::*;
8757
8758 let mut gda_info: Option<(
8760 usize,
8761 String,
8762 Expression,
8763 Expression,
8764 String,
8765 Option<(String, Vec<Identifier>)>,
8766 )> = None; if let Some(ref from) = sel.from {
8769 for (idx, table_expr) in from.expressions.iter().enumerate() {
8770 let (unnest_opt, outer_alias_info) = match table_expr {
8773 Expression::Unnest(ref unnest) => (Some(unnest.as_ref()), None),
8774 Expression::Alias(ref a) => {
8775 if let Expression::Unnest(ref unnest) = a.this {
8776 let alias_info = (a.alias.name.clone(), a.column_aliases.clone());
8777 (Some(unnest.as_ref()), Some(alias_info))
8778 } else {
8779 (None, None)
8780 }
8781 }
8782 _ => (None, None),
8783 };
8784
8785 if let Some(unnest) = unnest_opt {
8786 let func_opt = match &unnest.this {
8788 Expression::Function(ref f)
8789 if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY")
8790 && f.args.len() >= 2 =>
8791 {
8792 Some(f)
8793 }
8794 _ => None,
8796 };
8797
8798 if let Some(f) = func_opt {
8799 let start_expr = f.args[0].clone();
8800 let end_expr = f.args[1].clone();
8801 let step = f.args.get(2).cloned();
8802
8803 let unit = Self::extract_interval_unit_str(&step);
8805 let col_name = outer_alias_info
8806 .as_ref()
8807 .and_then(|(_, cols)| cols.first().map(|id| id.name.clone()))
8808 .unwrap_or_else(|| "value".to_string());
8809
8810 if let Some(unit_str) = unit {
8811 gda_info = Some((
8812 idx,
8813 col_name,
8814 start_expr,
8815 end_expr,
8816 unit_str,
8817 outer_alias_info,
8818 ));
8819 break;
8820 }
8821 }
8822 }
8823 }
8824 }
8825
8826 let Some((from_idx, col_name, start_expr, end_expr, unit_str, outer_alias_info)) = gda_info
8827 else {
8828 return Ok(Expression::Select(sel));
8829 };
8830
8831 let datediff = Expression::Function(Box::new(Function::new(
8837 "DATEDIFF".to_string(),
8838 vec![
8839 Expression::boxed_column(Column {
8840 name: Identifier::new(&unit_str),
8841 table: None,
8842 join_mark: false,
8843 trailing_comments: vec![],
8844 span: None,
8845 inferred_type: None,
8846 }),
8847 start_expr.clone(),
8848 end_expr.clone(),
8849 ],
8850 )));
8851 let datediff_plus_one = Expression::Add(Box::new(BinaryOp {
8853 left: datediff,
8854 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
8855 left_comments: vec![],
8856 operator_comments: vec![],
8857 trailing_comments: vec![],
8858 inferred_type: None,
8859 }));
8860
8861 let array_gen_range = Expression::Function(Box::new(Function::new(
8862 "ARRAY_GENERATE_RANGE".to_string(),
8863 vec![
8864 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
8865 datediff_plus_one,
8866 ],
8867 )));
8868
8869 let flatten_input = Expression::NamedArgument(Box::new(NamedArgument {
8871 name: Identifier::new("INPUT"),
8872 value: array_gen_range,
8873 separator: crate::expressions::NamedArgSeparator::DArrow,
8874 }));
8875 let flatten = Expression::Function(Box::new(Function::new(
8876 "FLATTEN".to_string(),
8877 vec![flatten_input],
8878 )));
8879
8880 let table_alias_name = outer_alias_info
8882 .as_ref()
8883 .map(|(name, _)| name.clone())
8884 .unwrap_or_else(|| "_t0".to_string());
8885
8886 let table_func =
8888 Expression::Function(Box::new(Function::new("TABLE".to_string(), vec![flatten])));
8889 let flatten_aliased = Expression::Alias(Box::new(Alias {
8890 this: table_func,
8891 alias: Identifier::new(&table_alias_name),
8892 column_aliases: vec![
8893 Identifier::new("seq"),
8894 Identifier::new("key"),
8895 Identifier::new("path"),
8896 Identifier::new("index"),
8897 Identifier::new(&col_name),
8898 Identifier::new("this"),
8899 ],
8900 alias_explicit_as: false,
8901 alias_keyword: None,
8902 pre_alias_comments: vec![],
8903 trailing_comments: vec![],
8904 inferred_type: None,
8905 }));
8906
8907 let dateadd_expr = Expression::Function(Box::new(Function::new(
8909 "DATEADD".to_string(),
8910 vec![
8911 Expression::boxed_column(Column {
8912 name: Identifier::new(&unit_str),
8913 table: None,
8914 join_mark: false,
8915 trailing_comments: vec![],
8916 span: None,
8917 inferred_type: None,
8918 }),
8919 Expression::Cast(Box::new(Cast {
8920 this: Expression::boxed_column(Column {
8921 name: Identifier::new(&col_name),
8922 table: None,
8923 join_mark: false,
8924 trailing_comments: vec![],
8925 span: None,
8926 inferred_type: None,
8927 }),
8928 to: DataType::Int {
8929 length: None,
8930 integer_spelling: false,
8931 },
8932 trailing_comments: vec![],
8933 double_colon_syntax: false,
8934 format: None,
8935 default: None,
8936 inferred_type: None,
8937 })),
8938 start_expr.clone(),
8940 ],
8941 )));
8942 let dateadd_aliased = Expression::Alias(Box::new(Alias {
8943 this: dateadd_expr,
8944 alias: Identifier::new(&col_name),
8945 column_aliases: vec![],
8946 alias_explicit_as: false,
8947 alias_keyword: None,
8948 pre_alias_comments: vec![],
8949 trailing_comments: vec![],
8950 inferred_type: None,
8951 }));
8952
8953 let mut inner_select = Select::new();
8955 inner_select.expressions = vec![dateadd_aliased];
8956 inner_select.from = Some(From {
8957 expressions: vec![flatten_aliased],
8958 });
8959
8960 let inner_select_expr = Expression::Select(Box::new(inner_select));
8961 let subquery = Expression::Subquery(Box::new(Subquery {
8962 this: inner_select_expr,
8963 alias: None,
8964 column_aliases: vec![],
8965 alias_explicit_as: false,
8966 alias_keyword: None,
8967 order_by: None,
8968 limit: None,
8969 offset: None,
8970 distribute_by: None,
8971 sort_by: None,
8972 cluster_by: None,
8973 lateral: false,
8974 modifiers_inside: false,
8975 trailing_comments: vec![],
8976 inferred_type: None,
8977 }));
8978
8979 let replacement = if let Some((alias_name, col_aliases)) = outer_alias_info {
8981 Expression::Alias(Box::new(Alias {
8982 this: subquery,
8983 alias: Identifier::new(&alias_name),
8984 column_aliases: col_aliases,
8985 alias_explicit_as: false,
8986 alias_keyword: None,
8987 pre_alias_comments: vec![],
8988 trailing_comments: vec![],
8989 inferred_type: None,
8990 }))
8991 } else {
8992 subquery
8993 };
8994
8995 if let Some(ref mut from) = sel.from {
8997 from.expressions[from_idx] = replacement;
8998 }
8999
9000 Ok(Expression::Select(sel))
9001 }
9002
9003 fn convert_array_size_gda_snowflake(f: &crate::expressions::Function) -> Result<Expression> {
9007 use crate::expressions::*;
9008
9009 let start_expr = f.args[0].clone();
9010 let end_expr = f.args[1].clone();
9011 let step = f.args.get(2).cloned();
9012 let unit_str = Self::extract_interval_unit_str(&step).unwrap_or_else(|| "DAY".to_string());
9013 let col_name = "value";
9014
9015 let datediff = Expression::Function(Box::new(Function::new(
9017 "DATEDIFF".to_string(),
9018 vec![
9019 Expression::boxed_column(Column {
9020 name: Identifier::new(&unit_str),
9021 table: None,
9022 join_mark: false,
9023 trailing_comments: vec![],
9024 span: None,
9025 inferred_type: None,
9026 }),
9027 start_expr.clone(),
9028 end_expr.clone(),
9029 ],
9030 )));
9031 let datediff_plus_one = Expression::Add(Box::new(BinaryOp {
9033 left: datediff,
9034 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
9035 left_comments: vec![],
9036 operator_comments: vec![],
9037 trailing_comments: vec![],
9038 inferred_type: None,
9039 }));
9040
9041 let array_gen_range = Expression::Function(Box::new(Function::new(
9042 "ARRAY_GENERATE_RANGE".to_string(),
9043 vec![
9044 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
9045 datediff_plus_one,
9046 ],
9047 )));
9048
9049 let flatten_input = Expression::NamedArgument(Box::new(NamedArgument {
9050 name: Identifier::new("INPUT"),
9051 value: array_gen_range,
9052 separator: crate::expressions::NamedArgSeparator::DArrow,
9053 }));
9054 let flatten = Expression::Function(Box::new(Function::new(
9055 "FLATTEN".to_string(),
9056 vec![flatten_input],
9057 )));
9058
9059 let table_func =
9060 Expression::Function(Box::new(Function::new("TABLE".to_string(), vec![flatten])));
9061 let flatten_aliased = Expression::Alias(Box::new(Alias {
9062 this: table_func,
9063 alias: Identifier::new("_t0"),
9064 column_aliases: vec![
9065 Identifier::new("seq"),
9066 Identifier::new("key"),
9067 Identifier::new("path"),
9068 Identifier::new("index"),
9069 Identifier::new(col_name),
9070 Identifier::new("this"),
9071 ],
9072 alias_explicit_as: false,
9073 alias_keyword: None,
9074 pre_alias_comments: vec![],
9075 trailing_comments: vec![],
9076 inferred_type: None,
9077 }));
9078
9079 let dateadd_expr = Expression::Function(Box::new(Function::new(
9080 "DATEADD".to_string(),
9081 vec![
9082 Expression::boxed_column(Column {
9083 name: Identifier::new(&unit_str),
9084 table: None,
9085 join_mark: false,
9086 trailing_comments: vec![],
9087 span: None,
9088 inferred_type: None,
9089 }),
9090 Expression::Cast(Box::new(Cast {
9091 this: Expression::boxed_column(Column {
9092 name: Identifier::new(col_name),
9093 table: None,
9094 join_mark: false,
9095 trailing_comments: vec![],
9096 span: None,
9097 inferred_type: None,
9098 }),
9099 to: DataType::Int {
9100 length: None,
9101 integer_spelling: false,
9102 },
9103 trailing_comments: vec![],
9104 double_colon_syntax: false,
9105 format: None,
9106 default: None,
9107 inferred_type: None,
9108 })),
9109 start_expr.clone(),
9110 ],
9111 )));
9112 let dateadd_aliased = Expression::Alias(Box::new(Alias {
9113 this: dateadd_expr,
9114 alias: Identifier::new(col_name),
9115 column_aliases: vec![],
9116 alias_explicit_as: false,
9117 alias_keyword: None,
9118 pre_alias_comments: vec![],
9119 trailing_comments: vec![],
9120 inferred_type: None,
9121 }));
9122
9123 let mut inner_select = Select::new();
9125 inner_select.expressions = vec![dateadd_aliased];
9126 inner_select.from = Some(From {
9127 expressions: vec![flatten_aliased],
9128 });
9129
9130 let inner_subquery = Expression::Subquery(Box::new(Subquery {
9132 this: Expression::Select(Box::new(inner_select)),
9133 alias: None,
9134 column_aliases: vec![],
9135 alias_explicit_as: false,
9136 alias_keyword: None,
9137 order_by: None,
9138 limit: None,
9139 offset: None,
9140 distribute_by: None,
9141 sort_by: None,
9142 cluster_by: None,
9143 lateral: false,
9144 modifiers_inside: false,
9145 trailing_comments: vec![],
9146 inferred_type: None,
9147 }));
9148
9149 let star = Expression::Star(Star {
9151 table: None,
9152 except: None,
9153 replace: None,
9154 rename: None,
9155 trailing_comments: vec![],
9156 span: None,
9157 });
9158 let array_agg = Expression::ArrayAgg(Box::new(AggFunc {
9159 this: star,
9160 distinct: false,
9161 filter: None,
9162 order_by: vec![],
9163 name: Some("ARRAY_AGG".to_string()),
9164 ignore_nulls: None,
9165 having_max: None,
9166 limit: None,
9167 inferred_type: None,
9168 }));
9169
9170 let mut outer_select = Select::new();
9171 outer_select.expressions = vec![array_agg];
9172 outer_select.from = Some(From {
9173 expressions: vec![inner_subquery],
9174 });
9175
9176 let outer_subquery = Expression::Subquery(Box::new(Subquery {
9178 this: Expression::Select(Box::new(outer_select)),
9179 alias: None,
9180 column_aliases: vec![],
9181 alias_explicit_as: false,
9182 alias_keyword: None,
9183 order_by: None,
9184 limit: None,
9185 offset: None,
9186 distribute_by: None,
9187 sort_by: None,
9188 cluster_by: None,
9189 lateral: false,
9190 modifiers_inside: false,
9191 trailing_comments: vec![],
9192 inferred_type: None,
9193 }));
9194
9195 Ok(Expression::ArraySize(Box::new(UnaryFunc::new(
9197 outer_subquery,
9198 ))))
9199 }
9200
9201 fn extract_interval_unit_str(step: &Option<Expression>) -> Option<String> {
9203 use crate::expressions::*;
9204 if let Some(Expression::Interval(ref iv)) = step {
9205 if let Some(IntervalUnitSpec::Simple { ref unit, .. }) = iv.unit {
9206 return Some(format!("{:?}", unit).to_ascii_uppercase());
9207 }
9208 if let Some(ref this) = iv.this {
9209 if let Expression::Literal(lit) = this {
9210 if let Literal::String(ref s) = lit.as_ref() {
9211 let parts: Vec<&str> = s.split_whitespace().collect();
9212 if parts.len() == 2 {
9213 return Some(parts[1].to_ascii_uppercase());
9214 } else if parts.len() == 1 {
9215 let upper = parts[0].to_ascii_uppercase();
9216 if matches!(
9217 upper.as_str(),
9218 "YEAR"
9219 | "QUARTER"
9220 | "MONTH"
9221 | "WEEK"
9222 | "DAY"
9223 | "HOUR"
9224 | "MINUTE"
9225 | "SECOND"
9226 ) {
9227 return Some(upper);
9228 }
9229 }
9230 }
9231 }
9232 }
9233 }
9234 if step.is_none() {
9236 return Some("DAY".to_string());
9237 }
9238 None
9239 }
9240
9241 fn normalize_snowflake_pretty(mut sql: String) -> String {
9242 if sql.contains("LATERAL IFF(_u.pos = _u_2.pos_2, _u_2.entity, NULL) AS datasource(SEQ, KEY, PATH, INDEX, VALUE, THIS)")
9243 && sql.contains("ARRAY_GENERATE_RANGE(0, (GREATEST(ARRAY_SIZE(INPUT => PARSE_JSON(flags))) - 1) + 1)")
9244 {
9245 sql = sql.replace(
9246 "AND uc.user_id <> ALL (SELECT DISTINCT\n _id\n FROM users, LATERAL IFF(_u.pos = _u_2.pos_2, _u_2.entity, NULL) AS datasource(SEQ, KEY, PATH, INDEX, VALUE, THIS)\n WHERE\n GET_PATH(datasource.value, 'name') = 'something')",
9247 "AND uc.user_id <> ALL (\n SELECT DISTINCT\n _id\n FROM users, LATERAL IFF(_u.pos = _u_2.pos_2, _u_2.entity, NULL) AS datasource(SEQ, KEY, PATH, INDEX, VALUE, THIS)\n WHERE\n GET_PATH(datasource.value, 'name') = 'something'\n )",
9248 );
9249
9250 sql = sql.replace(
9251 "CROSS JOIN TABLE(FLATTEN(INPUT => ARRAY_GENERATE_RANGE(0, (GREATEST(ARRAY_SIZE(INPUT => PARSE_JSON(flags))) - 1) + 1))) AS _u(seq, key, path, index, pos, this)",
9252 "CROSS JOIN TABLE(FLATTEN(INPUT => ARRAY_GENERATE_RANGE(0, (\n GREATEST(ARRAY_SIZE(INPUT => PARSE_JSON(flags))) - 1\n) + 1))) AS _u(seq, key, path, index, pos, this)",
9253 );
9254
9255 sql = sql.replace(
9256 "OR (_u.pos > (ARRAY_SIZE(INPUT => PARSE_JSON(flags)) - 1)\n AND _u_2.pos_2 = (ARRAY_SIZE(INPUT => PARSE_JSON(flags)) - 1))",
9257 "OR (\n _u.pos > (\n ARRAY_SIZE(INPUT => PARSE_JSON(flags)) - 1\n )\n AND _u_2.pos_2 = (\n ARRAY_SIZE(INPUT => PARSE_JSON(flags)) - 1\n )\n )",
9258 );
9259 }
9260
9261 sql
9262 }
9263
9264 #[cfg(feature = "transpile")]
9265 fn wrap_tsql_top_level_values(expr: Expression) -> Expression {
9266 match expr {
9267 Expression::Values(values) => Self::tsql_values_as_select(*values),
9268 Expression::Union(mut union) => {
9269 let left = std::mem::replace(&mut union.left, Expression::Null(Null));
9270 let right = std::mem::replace(&mut union.right, Expression::Null(Null));
9271 union.left = Self::wrap_tsql_values_set_operand(left);
9272 union.right = Self::wrap_tsql_values_set_operand(right);
9273 Expression::Union(union)
9274 }
9275 Expression::Intersect(mut intersect) => {
9276 let left = std::mem::replace(&mut intersect.left, Expression::Null(Null));
9277 let right = std::mem::replace(&mut intersect.right, Expression::Null(Null));
9278 intersect.left = Self::wrap_tsql_values_set_operand(left);
9279 intersect.right = Self::wrap_tsql_values_set_operand(right);
9280 Expression::Intersect(intersect)
9281 }
9282 Expression::Except(mut except) => {
9283 let left = std::mem::replace(&mut except.left, Expression::Null(Null));
9284 let right = std::mem::replace(&mut except.right, Expression::Null(Null));
9285 except.left = Self::wrap_tsql_values_set_operand(left);
9286 except.right = Self::wrap_tsql_values_set_operand(right);
9287 Expression::Except(except)
9288 }
9289 other => other,
9290 }
9291 }
9292
9293 #[cfg(feature = "transpile")]
9294 fn wrap_tsql_values_set_operand(expr: Expression) -> Expression {
9295 match expr {
9296 Expression::Values(values) => Self::tsql_values_as_select(*values),
9297 Expression::Select(mut select)
9298 if Self::is_parser_wrapped_values_set_operand(&select) =>
9299 {
9300 let mut from = select.from.take().expect("checked as present");
9301 let Expression::Values(values) = from
9302 .expressions
9303 .pop()
9304 .expect("checked as a single VALUES source")
9305 else {
9306 unreachable!("checked as a VALUES source");
9307 };
9308 Self::tsql_values_as_select(*values)
9309 }
9310 Expression::Annotated(mut annotated) => {
9311 annotated.this = Self::wrap_tsql_values_set_operand(annotated.this);
9312 Expression::Annotated(annotated)
9313 }
9314 Expression::Union(mut union) => {
9315 let left = std::mem::replace(&mut union.left, Expression::Null(Null));
9316 let right = std::mem::replace(&mut union.right, Expression::Null(Null));
9317 union.left = Self::wrap_tsql_values_set_operand(left);
9318 union.right = Self::wrap_tsql_values_set_operand(right);
9319 Expression::Union(union)
9320 }
9321 Expression::Intersect(mut intersect) => {
9322 let left = std::mem::replace(&mut intersect.left, Expression::Null(Null));
9323 let right = std::mem::replace(&mut intersect.right, Expression::Null(Null));
9324 intersect.left = Self::wrap_tsql_values_set_operand(left);
9325 intersect.right = Self::wrap_tsql_values_set_operand(right);
9326 Expression::Intersect(intersect)
9327 }
9328 Expression::Except(mut except) => {
9329 let left = std::mem::replace(&mut except.left, Expression::Null(Null));
9330 let right = std::mem::replace(&mut except.right, Expression::Null(Null));
9331 except.left = Self::wrap_tsql_values_set_operand(left);
9332 except.right = Self::wrap_tsql_values_set_operand(right);
9333 Expression::Except(except)
9334 }
9335 other => other,
9336 }
9337 }
9338
9339 #[cfg(feature = "transpile")]
9340 fn is_parser_wrapped_values_set_operand(select: &Select) -> bool {
9341 let Some(from) = &select.from else {
9342 return false;
9343 };
9344 let [Expression::Values(values)] = from.expressions.as_slice() else {
9345 return false;
9346 };
9347 if !values
9348 .alias
9349 .as_ref()
9350 .is_some_and(|alias| alias.name == "_values")
9351 {
9352 return false;
9353 }
9354
9355 let mut parser_wrapper = Select::new();
9356 parser_wrapper.expressions = vec![Expression::star()];
9357 parser_wrapper.from = Some(from.clone());
9358 select == &parser_wrapper
9359 }
9360
9361 #[cfg(feature = "transpile")]
9362 fn tsql_values_as_select(mut values: crate::expressions::Values) -> Expression {
9363 let column_aliases = if values.column_aliases.is_empty() {
9364 let column_count = values
9365 .expressions
9366 .first()
9367 .map(|row| row.expressions.len())
9368 .unwrap_or(0);
9369 (1..=column_count)
9370 .map(|index| Identifier::new(format!("column{index}")))
9371 .collect()
9372 } else {
9373 std::mem::take(&mut values.column_aliases)
9374 };
9375
9376 values.alias = None;
9377
9378 let values_subquery = Expression::Subquery(Box::new(crate::expressions::Subquery {
9379 this: Expression::Values(Box::new(values)),
9380 alias: Some(Identifier::new("_v")),
9381 column_aliases,
9382 alias_explicit_as: false,
9383 alias_keyword: None,
9384 order_by: None,
9385 limit: None,
9386 offset: None,
9387 distribute_by: None,
9388 sort_by: None,
9389 cluster_by: None,
9390 lateral: false,
9391 modifiers_inside: false,
9392 trailing_comments: Vec::new(),
9393 inferred_type: None,
9394 }));
9395
9396 let mut select = crate::expressions::Select::new();
9397 select.expressions = vec![Expression::star()];
9398 select.from = Some(From {
9399 expressions: vec![values_subquery],
9400 });
9401
9402 Expression::Select(Box::new(select))
9403 }
9404
9405 fn extract_interval_parts(
9406 interval_expr: &Expression,
9407 ) -> Option<(Expression, crate::expressions::IntervalUnit)> {
9408 use crate::expressions::{DataType, IntervalUnit, IntervalUnitSpec, Literal};
9409
9410 fn unit_from_str(unit: &str) -> Option<IntervalUnit> {
9411 match unit.trim().to_ascii_uppercase().as_str() {
9412 "YEAR" | "YEARS" | "Y" | "YR" | "YRS" | "YY" | "YYYY" => Some(IntervalUnit::Year),
9413 "QUARTER" | "QUARTERS" | "Q" | "QTR" | "QTRS" | "QQ" => Some(IntervalUnit::Quarter),
9414 "MONTH" | "MONTHS" | "MON" | "MONS" | "MM" => Some(IntervalUnit::Month),
9415 "WEEK" | "WEEKS" | "W" | "WK" | "WKS" | "WW" | "ISOWEEK" => {
9416 Some(IntervalUnit::Week)
9417 }
9418 "DAY" | "DAYS" | "D" | "DD" => Some(IntervalUnit::Day),
9419 "HOUR" | "HOURS" | "H" | "HH" | "HR" | "HRS" => Some(IntervalUnit::Hour),
9420 "MINUTE" | "MINUTES" | "MI" | "MIN" | "MINS" | "N" => Some(IntervalUnit::Minute),
9421 "SECOND" | "SECONDS" | "S" | "SEC" | "SECS" | "SS" => Some(IntervalUnit::Second),
9422 "MILLISECOND" | "MILLISECONDS" | "MS" | "MSEC" | "MSECS" | "MSECOND"
9423 | "MSECONDS" | "MILLISEC" | "MILLISECS" | "MILLISECON" => {
9424 Some(IntervalUnit::Millisecond)
9425 }
9426 "MICROSECOND" | "MICROSECONDS" | "US" | "USEC" | "USECS" | "USECOND"
9427 | "USECONDS" | "MICROSEC" | "MICROSECS" | "MCS" => Some(IntervalUnit::Microsecond),
9428 "NANOSECOND" | "NANOSECONDS" | "NS" | "NSEC" | "NSECS" | "NSECOND" | "NSECONDS"
9429 | "NANOSEC" | "NANOSECS" => Some(IntervalUnit::Nanosecond),
9430 _ => None,
9431 }
9432 }
9433
9434 fn parts_from_literal_string(s: &str) -> Option<(Expression, IntervalUnit)> {
9435 let mut parts = s.split_whitespace();
9436 let value = parts.next()?;
9437 let unit = unit_from_str(parts.next()?)?;
9438 Some((
9439 Expression::Literal(Box::new(Literal::String(value.to_string()))),
9440 unit,
9441 ))
9442 }
9443
9444 fn unit_from_spec(unit: &IntervalUnitSpec) -> Option<IntervalUnit> {
9445 match unit {
9446 IntervalUnitSpec::Simple { unit, .. } => Some(*unit),
9447 IntervalUnitSpec::Expr(expr) => match expr.as_ref() {
9448 Expression::Day(_) => Some(IntervalUnit::Day),
9449 Expression::Month(_) => Some(IntervalUnit::Month),
9450 Expression::Year(_) => Some(IntervalUnit::Year),
9451 Expression::Identifier(id) => unit_from_str(&id.name),
9452 Expression::Var(v) => unit_from_str(&v.this),
9453 Expression::Column(col) => unit_from_str(&col.name.name),
9454 _ => None,
9455 },
9456 _ => None,
9457 }
9458 }
9459
9460 match interval_expr {
9461 Expression::Interval(iv) => {
9462 let val = iv.this.clone().unwrap_or(Expression::number(0));
9463 if let Expression::Literal(lit) = &val {
9464 if let Literal::String(s) = lit.as_ref() {
9465 if let Some(parts) = parts_from_literal_string(s) {
9466 return Some(parts);
9467 }
9468 }
9469 }
9470 let unit = iv
9471 .unit
9472 .as_ref()
9473 .and_then(unit_from_spec)
9474 .unwrap_or(IntervalUnit::Day);
9475 Some((val, unit))
9476 }
9477 Expression::Cast(cast) if matches!(cast.to, DataType::Interval { .. }) => {
9478 if let Expression::Literal(lit) = &cast.this {
9479 if let Literal::String(s) = lit.as_ref() {
9480 if let Some(parts) = parts_from_literal_string(s) {
9481 return Some(parts);
9482 }
9483 }
9484 }
9485 let unit = match &cast.to {
9486 DataType::Interval {
9487 unit: Some(unit), ..
9488 } => unit_from_str(unit).unwrap_or(IntervalUnit::Day),
9489 _ => IntervalUnit::Day,
9490 };
9491 Some((cast.this.clone(), unit))
9492 }
9493 _ => None,
9494 }
9495 }
9496
9497 fn data_type_is_interval(dt: &DataType) -> bool {
9498 match dt {
9499 DataType::Interval { .. } => true,
9500 DataType::Custom { name } => name.trim().eq_ignore_ascii_case("INTERVAL"),
9501 _ => false,
9502 }
9503 }
9504
9505 fn node_is_interval_cast(node: &Expression) -> bool {
9506 match node {
9507 Expression::Cast(c) | Expression::TryCast(c) | Expression::SafeCast(c) => {
9508 Self::data_type_is_interval(&c.to)
9509 }
9510 _ => false,
9511 }
9512 }
9513
9514 fn reject_tsql_interval_casts(
9515 expr: &Expression,
9516 target: DialectType,
9517 opts: &TranspileOptions,
9518 ) -> Result<()> {
9519 if !matches!(
9520 opts.unsupported_level,
9521 UnsupportedLevel::Raise | UnsupportedLevel::Immediate
9522 ) {
9523 return Ok(());
9524 }
9525
9526 if expr.dfs().any(Self::node_is_interval_cast) {
9527 return Err(crate::error::Error::unsupported(
9528 "INTERVAL casts",
9529 target.to_string(),
9530 ));
9531 }
9532
9533 Ok(())
9534 }
9535
9536 fn tsql_varchar_max_type() -> DataType {
9537 DataType::Custom {
9538 name: "VARCHAR(MAX)".to_string(),
9539 }
9540 }
9541
9542 fn rewrite_tsql_interval_casts_to_varchar(expr: Expression) -> Result<Expression> {
9543 transform_recursive(expr, &|e| match e {
9544 Expression::Cast(mut cast) if Self::data_type_is_interval(&cast.to) => {
9545 cast.to = Self::tsql_varchar_max_type();
9546 cast.double_colon_syntax = false;
9547 Ok(Expression::Cast(cast))
9548 }
9549 Expression::TryCast(mut cast) if Self::data_type_is_interval(&cast.to) => {
9550 cast.to = Self::tsql_varchar_max_type();
9551 cast.double_colon_syntax = false;
9552 Ok(Expression::TryCast(cast))
9553 }
9554 Expression::SafeCast(mut cast) if Self::data_type_is_interval(&cast.to) => {
9555 cast.to = Self::tsql_varchar_max_type();
9556 cast.double_colon_syntax = false;
9557 Ok(Expression::SafeCast(cast))
9558 }
9559 _ => Ok(e),
9560 })
9561 }
9562
9563 fn rewrite_tsql_interval_arithmetic_legacy(
9564 expr: &Expression,
9565 source: DialectType,
9566 ) -> Option<Expression> {
9567 match expr {
9568 Expression::Add(op) => {
9569 if Self::extract_interval_parts(&op.right).is_some() {
9570 return Some(Self::build_tsql_dateadd_from_interval(
9571 op.left.clone(),
9572 &op.right,
9573 false,
9574 ));
9575 }
9576
9577 if Self::is_postgres_family_source(source) {
9578 if Self::is_explicit_date_expr(&op.left)
9579 && Self::is_integer_day_offset_expr(&op.right)
9580 {
9581 return Some(Self::build_tsql_dateadd_days(
9582 op.left.clone(),
9583 op.right.clone(),
9584 false,
9585 ));
9586 }
9587
9588 if Self::is_integer_day_offset_expr(&op.left)
9589 && Self::is_explicit_date_expr(&op.right)
9590 {
9591 return Some(Self::build_tsql_dateadd_days(
9592 op.right.clone(),
9593 op.left.clone(),
9594 false,
9595 ));
9596 }
9597 }
9598
9599 None
9600 }
9601 Expression::Sub(op) => {
9602 if Self::extract_interval_parts(&op.right).is_some() {
9603 return Some(Self::build_tsql_dateadd_from_interval(
9604 op.left.clone(),
9605 &op.right,
9606 true,
9607 ));
9608 }
9609
9610 if Self::is_postgres_family_source(source) {
9611 if Self::is_explicit_date_expr(&op.left)
9612 && Self::is_explicit_date_expr(&op.right)
9613 {
9614 return Some(Self::build_tsql_datediff_days(
9615 op.right.clone(),
9616 op.left.clone(),
9617 ));
9618 }
9619
9620 if Self::is_explicit_date_expr(&op.left)
9621 && Self::is_integer_day_offset_expr(&op.right)
9622 {
9623 return Some(Self::build_tsql_dateadd_days(
9624 op.left.clone(),
9625 op.right.clone(),
9626 true,
9627 ));
9628 }
9629 }
9630
9631 None
9632 }
9633 _ => None,
9634 }
9635 }
9636
9637 fn is_postgres_family_source(source: DialectType) -> bool {
9638 matches!(
9639 source,
9640 DialectType::PostgreSQL
9641 | DialectType::Redshift
9642 | DialectType::Materialize
9643 | DialectType::RisingWave
9644 | DialectType::CockroachDB
9645 )
9646 }
9647
9648 fn is_explicit_date_expr(expr: &Expression) -> bool {
9649 use crate::expressions::Literal;
9650
9651 match expr {
9652 Expression::Literal(lit) => matches!(lit.as_ref(), Literal::Date(_)),
9653 Expression::Cast(c) | Expression::TryCast(c) | Expression::SafeCast(c) => {
9654 matches!(c.to, crate::expressions::DataType::Date)
9655 }
9656 Expression::Paren(p) => Self::is_explicit_date_expr(&p.this),
9657 Expression::CurrentDate(_)
9658 | Expression::Date(_)
9659 | Expression::MakeDate(_)
9660 | Expression::ToDate(_)
9661 | Expression::DateStrToDate(_) => true,
9662 _ => false,
9663 }
9664 }
9665
9666 fn is_integer_day_offset_expr(expr: &Expression) -> bool {
9667 use crate::expressions::Literal;
9668
9669 match expr {
9670 Expression::Literal(lit) => match lit.as_ref() {
9671 Literal::Number(n) => n.parse::<i64>().is_ok(),
9672 _ => false,
9673 },
9674 Expression::Parameter(_) | Expression::Placeholder(_) => true,
9675 Expression::Neg(op) => Self::is_integer_day_offset_expr(&op.this),
9676 Expression::Paren(p) => Self::is_integer_day_offset_expr(&p.this),
9677 _ => false,
9678 }
9679 }
9680
9681 fn build_tsql_datediff_days(start: Expression, end: Expression) -> Expression {
9682 Expression::Function(Box::new(Function::new(
9683 "DATEDIFF".to_string(),
9684 vec![Expression::Identifier(Identifier::new("DAY")), start, end],
9685 )))
9686 }
9687
9688 fn build_tsql_dateadd_days(date: Expression, amount: Expression, subtract: bool) -> Expression {
9689 Expression::Function(Box::new(Function::new(
9690 "DATEADD".to_string(),
9691 vec![
9692 Expression::Identifier(Identifier::new("DAY")),
9693 Self::tsql_dateadd_amount(amount, subtract),
9694 date,
9695 ],
9696 )))
9697 }
9698
9699 fn build_tsql_dateadd_from_interval(
9700 date: Expression,
9701 interval: &Expression,
9702 subtract: bool,
9703 ) -> Expression {
9704 let (value, unit) = Self::extract_interval_parts(interval)
9705 .unwrap_or_else(|| (interval.clone(), crate::expressions::IntervalUnit::Day));
9706 let unit = normalization::temporal::interval_unit_to_string(&unit);
9707 let amount = Self::tsql_dateadd_amount(value, subtract);
9708
9709 Expression::Function(Box::new(Function::new(
9710 "DATEADD".to_string(),
9711 vec![Expression::Identifier(Identifier::new(unit)), amount, date],
9712 )))
9713 }
9714
9715 fn tsql_dateadd_amount(value: Expression, negate: bool) -> Expression {
9716 use crate::expressions::{Parameter, ParameterStyle, UnaryOp};
9717
9718 fn numeric_literal_value(value: &Expression) -> Option<&str> {
9719 match value {
9720 Expression::Literal(lit) => match lit.as_ref() {
9721 crate::expressions::Literal::Number(n)
9722 | crate::expressions::Literal::String(n) => Some(n.as_str()),
9723 _ => None,
9724 },
9725 _ => None,
9726 }
9727 }
9728
9729 fn colon_parameter(value: &Expression) -> Option<Expression> {
9730 let Expression::Literal(lit) = value else {
9731 return None;
9732 };
9733 let crate::expressions::Literal::String(s) = lit.as_ref() else {
9734 return None;
9735 };
9736 let name = s.strip_prefix(':')?;
9737 if name.is_empty()
9738 || !name
9739 .chars()
9740 .all(|ch| ch.is_ascii_alphanumeric() || ch == '_')
9741 {
9742 return None;
9743 }
9744
9745 Some(Expression::Parameter(Box::new(Parameter {
9746 name: if name.chars().all(|ch| ch.is_ascii_digit()) {
9747 None
9748 } else {
9749 Some(name.to_string())
9750 },
9751 index: name.parse::<u32>().ok(),
9752 style: ParameterStyle::Colon,
9753 quoted: false,
9754 string_quoted: false,
9755 expression: None,
9756 })))
9757 }
9758
9759 let value = colon_parameter(&value).unwrap_or(value);
9760
9761 if let Some(n) = numeric_literal_value(&value) {
9762 if let Ok(parsed) = n.parse::<f64>() {
9763 let normalized = if negate { -parsed } else { parsed };
9764 let rendered = if normalized.fract() == 0.0 {
9765 format!("{}", normalized as i64)
9766 } else {
9767 normalized.to_string()
9768 };
9769 return Expression::Literal(Box::new(crate::expressions::Literal::Number(
9770 rendered,
9771 )));
9772 }
9773 }
9774
9775 if !negate {
9776 return value;
9777 }
9778
9779 match value {
9780 Expression::Neg(op) => op.this,
9781 other => Expression::Neg(Box::new(UnaryOp {
9782 this: other,
9783 inferred_type: None,
9784 })),
9785 }
9786 }
9787
9788 const PRESERVED_TO_DATE: &'static str = "_POLYGLOT_TO_DATE";
9792}
9793
9794#[cfg(test)]
9795mod tests {
9796 use super::*;
9797
9798 #[test]
9799 fn built_in_dialect_instances_share_tokenizer_config() {
9800 let first = Dialect::get(DialectType::PostgreSQL);
9801 let second = Dialect::get(DialectType::PostgreSQL);
9802
9803 assert!(first.tokenizer.shares_config_with(&second.tokenizer));
9804 }
9805
9806 #[test]
9807 fn test_dialect_type_from_str() {
9808 assert_eq!(
9809 "postgres".parse::<DialectType>().unwrap(),
9810 DialectType::PostgreSQL
9811 );
9812 assert_eq!(
9813 "postgresql".parse::<DialectType>().unwrap(),
9814 DialectType::PostgreSQL
9815 );
9816 assert_eq!("mysql".parse::<DialectType>().unwrap(), DialectType::MySQL);
9817 assert_eq!(
9818 "bigquery".parse::<DialectType>().unwrap(),
9819 DialectType::BigQuery
9820 );
9821 }
9822
9823 #[test]
9824 fn test_basic_transpile() {
9825 let dialect = Dialect::get(DialectType::Generic);
9826 let result = dialect
9827 .transpile("SELECT 1", DialectType::PostgreSQL)
9828 .unwrap();
9829 assert_eq!(result.len(), 1);
9830 assert_eq!(result[0], "SELECT 1");
9831 }
9832
9833 #[test]
9834 fn test_sqlite_double_quoted_column_defaults_to_postgres_strings() {
9835 let sqlite = Dialect::get(DialectType::SQLite);
9836 let result = sqlite
9837 .transpile(
9838 r#"CREATE TABLE "_collections" (
9839 "type" TEXT DEFAULT "base" NOT NULL,
9840 "fields" JSON DEFAULT "[]" NOT NULL,
9841 "options" JSON DEFAULT "{}" NOT NULL
9842 )"#,
9843 DialectType::PostgreSQL,
9844 )
9845 .unwrap();
9846
9847 assert!(result[0].contains(r#""type" TEXT DEFAULT 'base' NOT NULL"#));
9848 assert!(result[0].contains(r#""fields" JSON DEFAULT '[]' NOT NULL"#));
9849 assert!(result[0].contains(r#""options" JSON DEFAULT '{}' NOT NULL"#));
9850 }
9851
9852 #[test]
9853 fn test_sqlite_identity_preserves_double_quoted_column_defaults() {
9854 let sqlite = Dialect::get(DialectType::SQLite);
9855 let result = sqlite
9856 .transpile(
9857 r#"CREATE TABLE "_collections" ("type" TEXT DEFAULT "base" NOT NULL)"#,
9858 DialectType::SQLite,
9859 )
9860 .unwrap();
9861
9862 assert_eq!(
9863 result[0],
9864 r#"CREATE TABLE "_collections" ("type" TEXT DEFAULT "base" NOT NULL)"#
9865 );
9866 }
9867
9868 #[test]
9869 fn test_function_transformation_mysql() {
9870 let dialect = Dialect::get(DialectType::Generic);
9872 let result = dialect
9873 .transpile("SELECT NVL(a, b)", DialectType::MySQL)
9874 .unwrap();
9875 assert_eq!(result[0], "SELECT IFNULL(a, b)");
9876 }
9877
9878 #[test]
9879 fn test_get_path_duckdb() {
9880 let snowflake = Dialect::get(DialectType::Snowflake);
9882
9883 let result_sf_sf = snowflake
9885 .transpile(
9886 "SELECT PARSE_JSON('{\"fruit\":\"banana\"}'):fruit",
9887 DialectType::Snowflake,
9888 )
9889 .unwrap();
9890 eprintln!("Snowflake->Snowflake colon: {}", result_sf_sf[0]);
9891
9892 let result_sf_dk = snowflake
9894 .transpile(
9895 "SELECT PARSE_JSON('{\"fruit\":\"banana\"}'):fruit",
9896 DialectType::DuckDB,
9897 )
9898 .unwrap();
9899 eprintln!("Snowflake->DuckDB colon: {}", result_sf_dk[0]);
9900
9901 let result_gp = snowflake
9903 .transpile(
9904 "SELECT GET_PATH(PARSE_JSON('{\"fruit\":\"banana\"}'), 'fruit')",
9905 DialectType::DuckDB,
9906 )
9907 .unwrap();
9908 eprintln!("Snowflake->DuckDB explicit GET_PATH: {}", result_gp[0]);
9909 }
9910
9911 #[test]
9912 fn test_function_transformation_postgres() {
9913 let dialect = Dialect::get(DialectType::Generic);
9915 let result = dialect
9916 .transpile("SELECT IFNULL(a, b)", DialectType::PostgreSQL)
9917 .unwrap();
9918 assert_eq!(result[0], "SELECT COALESCE(a, b)");
9919
9920 let result = dialect
9922 .transpile("SELECT NVL(a, b)", DialectType::PostgreSQL)
9923 .unwrap();
9924 assert_eq!(result[0], "SELECT COALESCE(a, b)");
9925 }
9926
9927 #[test]
9928 fn test_hive_cast_to_trycast() {
9929 let hive = Dialect::get(DialectType::Hive);
9931 let result = hive
9932 .transpile("CAST(1 AS INT)", DialectType::DuckDB)
9933 .unwrap();
9934 assert_eq!(result[0], "TRY_CAST(1 AS INT)");
9935
9936 let result = hive
9937 .transpile("CAST(1 AS INT)", DialectType::Presto)
9938 .unwrap();
9939 assert_eq!(result[0], "TRY_CAST(1 AS INTEGER)");
9940 }
9941
9942 #[test]
9943 fn test_hive_array_identity() {
9944 let sql = "CREATE EXTERNAL TABLE `my_table` (`a7` ARRAY<DATE>) ROW FORMAT SERDE 'a' STORED AS INPUTFORMAT 'b' OUTPUTFORMAT 'c' LOCATION 'd' TBLPROPERTIES ('e'='f')";
9946 let hive = Dialect::get(DialectType::Hive);
9947
9948 let result = hive.transpile(sql, DialectType::Hive).unwrap();
9950 eprintln!("Hive ARRAY via transpile: {}", result[0]);
9951 assert!(
9952 result[0].contains("ARRAY<DATE>"),
9953 "transpile: Expected ARRAY<DATE>, got: {}",
9954 result[0]
9955 );
9956
9957 let ast = hive.parse(sql).unwrap();
9959 let transformed = hive.transform(ast[0].clone()).unwrap();
9960 let output = hive.generate(&transformed).unwrap();
9961 eprintln!("Hive ARRAY via identity path: {}", output);
9962 assert!(
9963 output.contains("ARRAY<DATE>"),
9964 "identity path: Expected ARRAY<DATE>, got: {}",
9965 output
9966 );
9967 }
9968
9969 #[test]
9970 fn test_starrocks_delete_between_expansion() {
9971 let dialect = Dialect::get(DialectType::Generic);
9973
9974 let result = dialect
9976 .transpile(
9977 "DELETE FROM t WHERE a BETWEEN b AND c",
9978 DialectType::StarRocks,
9979 )
9980 .unwrap();
9981 assert_eq!(result[0], "DELETE FROM t WHERE a >= b AND a <= c");
9982
9983 let result = dialect
9985 .transpile(
9986 "DELETE FROM t WHERE a NOT BETWEEN b AND c",
9987 DialectType::StarRocks,
9988 )
9989 .unwrap();
9990 assert_eq!(result[0], "DELETE FROM t WHERE a < b OR a > c");
9991
9992 let result = dialect
9994 .transpile(
9995 "SELECT * FROM t WHERE a BETWEEN b AND c",
9996 DialectType::StarRocks,
9997 )
9998 .unwrap();
9999 assert!(
10000 result[0].contains("BETWEEN"),
10001 "BETWEEN should be preserved in SELECT"
10002 );
10003 }
10004
10005 #[test]
10006 fn test_snowflake_ltrim_rtrim_parse() {
10007 let sf = Dialect::get(DialectType::Snowflake);
10008 let sql = "SELECT LTRIM(RTRIM(col)) FROM t1";
10009 let result = sf.transpile(sql, DialectType::DuckDB);
10010 match &result {
10011 Ok(r) => eprintln!("LTRIM/RTRIM result: {}", r[0]),
10012 Err(e) => eprintln!("LTRIM/RTRIM error: {}", e),
10013 }
10014 assert!(
10015 result.is_ok(),
10016 "Expected successful parse of LTRIM(RTRIM(col)), got error: {:?}",
10017 result.err()
10018 );
10019 }
10020
10021 #[test]
10022 fn test_duckdb_count_if_parse() {
10023 let duck = Dialect::get(DialectType::DuckDB);
10024 let sql = "COUNT_IF(x)";
10025 let result = duck.transpile(sql, DialectType::DuckDB);
10026 match &result {
10027 Ok(r) => eprintln!("COUNT_IF result: {}", r[0]),
10028 Err(e) => eprintln!("COUNT_IF error: {}", e),
10029 }
10030 assert!(
10031 result.is_ok(),
10032 "Expected successful parse of COUNT_IF(x), got error: {:?}",
10033 result.err()
10034 );
10035 }
10036
10037 #[test]
10038 fn test_tsql_cast_tinyint_parse() {
10039 let tsql = Dialect::get(DialectType::TSQL);
10040 let sql = "CAST(X AS TINYINT)";
10041 let result = tsql.transpile(sql, DialectType::DuckDB);
10042 match &result {
10043 Ok(r) => eprintln!("TSQL CAST TINYINT result: {}", r[0]),
10044 Err(e) => eprintln!("TSQL CAST TINYINT error: {}", e),
10045 }
10046 assert!(
10047 result.is_ok(),
10048 "Expected successful transpile, got error: {:?}",
10049 result.err()
10050 );
10051 }
10052
10053 #[test]
10054 fn test_pg_hash_bitwise_xor() {
10055 let dialect = Dialect::get(DialectType::PostgreSQL);
10056 let result = dialect.transpile("x # y", DialectType::PostgreSQL).unwrap();
10057 assert_eq!(result[0], "x # y");
10058 }
10059
10060 #[test]
10061 fn test_pg_array_to_duckdb() {
10062 let dialect = Dialect::get(DialectType::PostgreSQL);
10063 let result = dialect
10064 .transpile("SELECT ARRAY[1, 2, 3] @> ARRAY[1, 2]", DialectType::DuckDB)
10065 .unwrap();
10066 assert_eq!(result[0], "SELECT [1, 2, 3] @> [1, 2]");
10067 }
10068
10069 #[test]
10070 fn test_array_remove_bigquery() {
10071 let dialect = Dialect::get(DialectType::Generic);
10072 let result = dialect
10073 .transpile("ARRAY_REMOVE(the_array, target)", DialectType::BigQuery)
10074 .unwrap();
10075 assert_eq!(
10076 result[0],
10077 "ARRAY(SELECT _u FROM UNNEST(the_array) AS _u WHERE _u <> target)"
10078 );
10079 }
10080
10081 #[test]
10082 fn test_map_clickhouse_case() {
10083 let dialect = Dialect::get(DialectType::Generic);
10084 let parsed = dialect
10085 .parse("CAST(MAP('a', '1') AS MAP(TEXT, TEXT))")
10086 .unwrap();
10087 eprintln!("MAP parsed: {:?}", parsed);
10088 let result = dialect
10089 .transpile(
10090 "CAST(MAP('a', '1') AS MAP(TEXT, TEXT))",
10091 DialectType::ClickHouse,
10092 )
10093 .unwrap();
10094 eprintln!("MAP result: {}", result[0]);
10095 }
10096
10097 #[test]
10098 fn test_generate_date_array_presto() {
10099 let dialect = Dialect::get(DialectType::Generic);
10100 let result = dialect.transpile(
10101 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
10102 DialectType::Presto,
10103 ).unwrap();
10104 eprintln!("GDA -> Presto: {}", result[0]);
10105 assert_eq!(result[0], "SELECT * FROM UNNEST(SEQUENCE(CAST('2020-01-01' AS DATE), CAST('2020-02-01' AS DATE), (1 * INTERVAL '7' DAY)))");
10106 }
10107
10108 #[test]
10109 fn test_generate_date_array_postgres() {
10110 let dialect = Dialect::get(DialectType::Generic);
10111 let result = dialect.transpile(
10112 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
10113 DialectType::PostgreSQL,
10114 ).unwrap();
10115 eprintln!("GDA -> PostgreSQL: {}", result[0]);
10116 }
10117
10118 #[test]
10119 fn test_generate_date_array_snowflake() {
10120 let dialect = Dialect::get(DialectType::Generic);
10121 let result = dialect
10122 .transpile(
10123 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
10124 DialectType::Snowflake,
10125 )
10126 .unwrap();
10127 eprintln!("GDA -> Snowflake: {}", result[0]);
10128 }
10129
10130 #[test]
10131 fn test_array_length_generate_date_array_snowflake() {
10132 let dialect = Dialect::get(DialectType::Generic);
10133 let result = dialect.transpile(
10134 "SELECT ARRAY_LENGTH(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
10135 DialectType::Snowflake,
10136 ).unwrap();
10137 eprintln!("ARRAY_LENGTH(GDA) -> Snowflake: {}", result[0]);
10138 }
10139
10140 #[test]
10141 fn test_generate_date_array_mysql() {
10142 let dialect = Dialect::get(DialectType::Generic);
10143 let result = dialect.transpile(
10144 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
10145 DialectType::MySQL,
10146 ).unwrap();
10147 eprintln!("GDA -> MySQL: {}", result[0]);
10148 }
10149
10150 #[test]
10151 fn test_generate_date_array_redshift() {
10152 let dialect = Dialect::get(DialectType::Generic);
10153 let result = dialect.transpile(
10154 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
10155 DialectType::Redshift,
10156 ).unwrap();
10157 eprintln!("GDA -> Redshift: {}", result[0]);
10158 }
10159
10160 #[test]
10161 fn test_generate_date_array_tsql() {
10162 let dialect = Dialect::get(DialectType::Generic);
10163 let result = dialect.transpile(
10164 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
10165 DialectType::TSQL,
10166 ).unwrap();
10167 eprintln!("GDA -> TSQL: {}", result[0]);
10168 }
10169
10170 #[test]
10171 fn test_struct_colon_syntax() {
10172 let dialect = Dialect::get(DialectType::Generic);
10173 let result = dialect.transpile(
10175 "CAST((1, 2, 3, 4) AS STRUCT<a TINYINT, b SMALLINT, c INT, d BIGINT>)",
10176 DialectType::ClickHouse,
10177 );
10178 match result {
10179 Ok(r) => eprintln!("STRUCT no colon -> ClickHouse: {}", r[0]),
10180 Err(e) => eprintln!("STRUCT no colon error: {}", e),
10181 }
10182 let result = dialect.transpile(
10184 "CAST((1, 2, 3, 4) AS STRUCT<a: TINYINT, b: SMALLINT, c: INT, d: BIGINT>)",
10185 DialectType::ClickHouse,
10186 );
10187 match result {
10188 Ok(r) => eprintln!("STRUCT colon -> ClickHouse: {}", r[0]),
10189 Err(e) => eprintln!("STRUCT colon error: {}", e),
10190 }
10191 }
10192
10193 #[test]
10194 fn test_generate_date_array_cte_wrapped_mysql() {
10195 let dialect = Dialect::get(DialectType::Generic);
10196 let result = dialect.transpile(
10197 "WITH dates AS (SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))) SELECT * FROM dates",
10198 DialectType::MySQL,
10199 ).unwrap();
10200 eprintln!("GDA CTE -> MySQL: {}", result[0]);
10201 }
10202
10203 #[test]
10204 fn test_generate_date_array_cte_wrapped_tsql() {
10205 let dialect = Dialect::get(DialectType::Generic);
10206 let result = dialect.transpile(
10207 "WITH dates AS (SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))) SELECT * FROM dates",
10208 DialectType::TSQL,
10209 ).unwrap();
10210 eprintln!("GDA CTE -> TSQL: {}", result[0]);
10211 }
10212
10213 #[test]
10214 fn test_decode_literal_no_null_check() {
10215 let dialect = Dialect::get(DialectType::Oracle);
10217 let result = dialect
10218 .transpile("SELECT decode(1,2,3,4)", DialectType::DuckDB)
10219 .unwrap();
10220 assert_eq!(
10221 result[0], "SELECT CASE WHEN 1 = 2 THEN 3 ELSE 4 END",
10222 "Literal DECODE should not have IS NULL checks"
10223 );
10224 }
10225
10226 #[test]
10227 fn test_decode_column_vs_literal_no_null_check() {
10228 let dialect = Dialect::get(DialectType::Oracle);
10230 let result = dialect
10231 .transpile("SELECT decode(col, 2, 3, 4) FROM t", DialectType::DuckDB)
10232 .unwrap();
10233 assert_eq!(
10234 result[0], "SELECT CASE WHEN col = 2 THEN 3 ELSE 4 END FROM t",
10235 "Column vs literal DECODE should not have IS NULL checks"
10236 );
10237 }
10238
10239 #[test]
10240 fn test_decode_column_vs_column_keeps_null_check() {
10241 let dialect = Dialect::get(DialectType::Oracle);
10243 let result = dialect
10244 .transpile("SELECT decode(col, col2, 3, 4) FROM t", DialectType::DuckDB)
10245 .unwrap();
10246 assert!(
10247 result[0].contains("IS NULL"),
10248 "Column vs column DECODE should have IS NULL checks, got: {}",
10249 result[0]
10250 );
10251 }
10252
10253 #[test]
10254 fn test_decode_null_search() {
10255 let dialect = Dialect::get(DialectType::Oracle);
10257 let result = dialect
10258 .transpile("SELECT decode(col, NULL, 3, 4) FROM t", DialectType::DuckDB)
10259 .unwrap();
10260 assert_eq!(
10261 result[0],
10262 "SELECT CASE WHEN col IS NULL THEN 3 ELSE 4 END FROM t",
10263 );
10264 }
10265
10266 #[test]
10271 fn test_regexp_substr_snowflake_to_duckdb_2arg() {
10272 let dialect = Dialect::get(DialectType::Snowflake);
10273 let result = dialect
10274 .transpile("SELECT REGEXP_SUBSTR(s, 'pattern')", DialectType::DuckDB)
10275 .unwrap();
10276 assert_eq!(result[0], "SELECT REGEXP_EXTRACT(s, 'pattern')");
10277 }
10278
10279 #[test]
10280 fn test_regexp_substr_snowflake_to_duckdb_3arg_pos1() {
10281 let dialect = Dialect::get(DialectType::Snowflake);
10282 let result = dialect
10283 .transpile("SELECT REGEXP_SUBSTR(s, 'pattern', 1)", DialectType::DuckDB)
10284 .unwrap();
10285 assert_eq!(result[0], "SELECT REGEXP_EXTRACT(s, 'pattern')");
10286 }
10287
10288 #[test]
10289 fn test_regexp_substr_snowflake_to_duckdb_3arg_pos_gt1() {
10290 let dialect = Dialect::get(DialectType::Snowflake);
10291 let result = dialect
10292 .transpile("SELECT REGEXP_SUBSTR(s, 'pattern', 3)", DialectType::DuckDB)
10293 .unwrap();
10294 assert_eq!(
10295 result[0],
10296 "SELECT REGEXP_EXTRACT(NULLIF(SUBSTRING(s, 3), ''), 'pattern')"
10297 );
10298 }
10299
10300 #[test]
10301 fn test_regexp_substr_snowflake_to_duckdb_4arg_occ_gt1() {
10302 let dialect = Dialect::get(DialectType::Snowflake);
10303 let result = dialect
10304 .transpile(
10305 "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 3)",
10306 DialectType::DuckDB,
10307 )
10308 .unwrap();
10309 assert_eq!(
10310 result[0],
10311 "SELECT ARRAY_EXTRACT(REGEXP_EXTRACT_ALL(s, 'pattern'), 3)"
10312 );
10313 }
10314
10315 #[test]
10316 fn test_regexp_substr_snowflake_to_duckdb_5arg_e_flag() {
10317 let dialect = Dialect::get(DialectType::Snowflake);
10318 let result = dialect
10319 .transpile(
10320 "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 1, 'e')",
10321 DialectType::DuckDB,
10322 )
10323 .unwrap();
10324 assert_eq!(result[0], "SELECT REGEXP_EXTRACT(s, 'pattern')");
10325 }
10326
10327 #[test]
10328 fn test_regexp_substr_snowflake_to_duckdb_6arg_group0() {
10329 let dialect = Dialect::get(DialectType::Snowflake);
10330 let result = dialect
10331 .transpile(
10332 "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 1, 'e', 0)",
10333 DialectType::DuckDB,
10334 )
10335 .unwrap();
10336 assert_eq!(result[0], "SELECT REGEXP_EXTRACT(s, 'pattern')");
10337 }
10338
10339 #[test]
10340 fn test_regexp_substr_snowflake_identity_strip_group0() {
10341 let dialect = Dialect::get(DialectType::Snowflake);
10342 let result = dialect
10343 .transpile(
10344 "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 1, 'e', 0)",
10345 DialectType::Snowflake,
10346 )
10347 .unwrap();
10348 assert_eq!(result[0], "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 1, 'e')");
10349 }
10350
10351 #[test]
10352 fn test_regexp_substr_all_snowflake_to_duckdb_2arg() {
10353 let dialect = Dialect::get(DialectType::Snowflake);
10354 let result = dialect
10355 .transpile(
10356 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern')",
10357 DialectType::DuckDB,
10358 )
10359 .unwrap();
10360 assert_eq!(result[0], "SELECT REGEXP_EXTRACT_ALL(s, 'pattern')");
10361 }
10362
10363 #[test]
10364 fn test_regexp_substr_all_snowflake_to_duckdb_3arg_pos_gt1() {
10365 let dialect = Dialect::get(DialectType::Snowflake);
10366 let result = dialect
10367 .transpile(
10368 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 3)",
10369 DialectType::DuckDB,
10370 )
10371 .unwrap();
10372 assert_eq!(
10373 result[0],
10374 "SELECT REGEXP_EXTRACT_ALL(SUBSTRING(s, 3), 'pattern')"
10375 );
10376 }
10377
10378 #[test]
10379 fn test_regexp_substr_all_snowflake_to_duckdb_5arg_e_flag() {
10380 let dialect = Dialect::get(DialectType::Snowflake);
10381 let result = dialect
10382 .transpile(
10383 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 1, 1, 'e')",
10384 DialectType::DuckDB,
10385 )
10386 .unwrap();
10387 assert_eq!(result[0], "SELECT REGEXP_EXTRACT_ALL(s, 'pattern')");
10388 }
10389
10390 #[test]
10391 fn test_regexp_substr_all_snowflake_to_duckdb_6arg_group0() {
10392 let dialect = Dialect::get(DialectType::Snowflake);
10393 let result = dialect
10394 .transpile(
10395 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 1, 1, 'e', 0)",
10396 DialectType::DuckDB,
10397 )
10398 .unwrap();
10399 assert_eq!(result[0], "SELECT REGEXP_EXTRACT_ALL(s, 'pattern')");
10400 }
10401
10402 #[test]
10403 fn test_regexp_substr_all_snowflake_identity_strip_group0() {
10404 let dialect = Dialect::get(DialectType::Snowflake);
10405 let result = dialect
10406 .transpile(
10407 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 1, 1, 'e', 0)",
10408 DialectType::Snowflake,
10409 )
10410 .unwrap();
10411 assert_eq!(
10412 result[0],
10413 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 1, 1, 'e')"
10414 );
10415 }
10416
10417 #[test]
10418 fn test_regexp_count_snowflake_to_duckdb_2arg() {
10419 let dialect = Dialect::get(DialectType::Snowflake);
10420 let result = dialect
10421 .transpile("SELECT REGEXP_COUNT(s, 'pattern')", DialectType::DuckDB)
10422 .unwrap();
10423 assert_eq!(
10424 result[0],
10425 "SELECT CASE WHEN 'pattern' = '' THEN 0 ELSE LENGTH(REGEXP_EXTRACT_ALL(s, 'pattern')) END"
10426 );
10427 }
10428
10429 #[test]
10430 fn test_regexp_count_snowflake_to_duckdb_3arg() {
10431 let dialect = Dialect::get(DialectType::Snowflake);
10432 let result = dialect
10433 .transpile("SELECT REGEXP_COUNT(s, 'pattern', 3)", DialectType::DuckDB)
10434 .unwrap();
10435 assert_eq!(
10436 result[0],
10437 "SELECT CASE WHEN 'pattern' = '' THEN 0 ELSE LENGTH(REGEXP_EXTRACT_ALL(SUBSTRING(s, 3), 'pattern')) END"
10438 );
10439 }
10440
10441 #[test]
10442 fn test_regexp_count_snowflake_to_duckdb_4arg_flags() {
10443 let dialect = Dialect::get(DialectType::Snowflake);
10444 let result = dialect
10445 .transpile(
10446 "SELECT REGEXP_COUNT(s, 'pattern', 1, 'i')",
10447 DialectType::DuckDB,
10448 )
10449 .unwrap();
10450 assert_eq!(
10451 result[0],
10452 "SELECT CASE WHEN '(?i)' || 'pattern' = '' THEN 0 ELSE LENGTH(REGEXP_EXTRACT_ALL(SUBSTRING(s, 1), '(?i)' || 'pattern')) END"
10453 );
10454 }
10455
10456 #[test]
10457 fn test_regexp_count_snowflake_to_duckdb_4arg_flags_literal_string() {
10458 let dialect = Dialect::get(DialectType::Snowflake);
10459 let result = dialect
10460 .transpile(
10461 "SELECT REGEXP_COUNT('Hello World', 'L', 1, 'im')",
10462 DialectType::DuckDB,
10463 )
10464 .unwrap();
10465 assert_eq!(
10466 result[0],
10467 "SELECT CASE WHEN '(?im)' || 'L' = '' THEN 0 ELSE LENGTH(REGEXP_EXTRACT_ALL(SUBSTRING('Hello World', 1), '(?im)' || 'L')) END"
10468 );
10469 }
10470
10471 #[test]
10472 fn test_regexp_replace_snowflake_to_duckdb_5arg_pos1_occ1() {
10473 let dialect = Dialect::get(DialectType::Snowflake);
10474 let result = dialect
10475 .transpile(
10476 "SELECT REGEXP_REPLACE(s, 'pattern', 'repl', 1, 1)",
10477 DialectType::DuckDB,
10478 )
10479 .unwrap();
10480 assert_eq!(result[0], "SELECT REGEXP_REPLACE(s, 'pattern', 'repl')");
10481 }
10482
10483 #[test]
10484 fn test_regexp_replace_snowflake_to_duckdb_5arg_pos_gt1_occ0() {
10485 let dialect = Dialect::get(DialectType::Snowflake);
10486 let result = dialect
10487 .transpile(
10488 "SELECT REGEXP_REPLACE(s, 'pattern', 'repl', 3, 0)",
10489 DialectType::DuckDB,
10490 )
10491 .unwrap();
10492 assert_eq!(
10493 result[0],
10494 "SELECT SUBSTRING(s, 1, 2) || REGEXP_REPLACE(SUBSTRING(s, 3), 'pattern', 'repl', 'g')"
10495 );
10496 }
10497
10498 #[test]
10499 fn test_regexp_replace_snowflake_to_duckdb_5arg_pos_gt1_occ1() {
10500 let dialect = Dialect::get(DialectType::Snowflake);
10501 let result = dialect
10502 .transpile(
10503 "SELECT REGEXP_REPLACE(s, 'pattern', 'repl', 3, 1)",
10504 DialectType::DuckDB,
10505 )
10506 .unwrap();
10507 assert_eq!(
10508 result[0],
10509 "SELECT SUBSTRING(s, 1, 2) || REGEXP_REPLACE(SUBSTRING(s, 3), 'pattern', 'repl')"
10510 );
10511 }
10512
10513 #[test]
10514 fn test_rlike_snowflake_to_duckdb_2arg() {
10515 let dialect = Dialect::get(DialectType::Snowflake);
10516 let result = dialect
10517 .transpile("SELECT RLIKE(a, b)", DialectType::DuckDB)
10518 .unwrap();
10519 assert_eq!(result[0], "SELECT REGEXP_FULL_MATCH(a, b)");
10520 }
10521
10522 #[test]
10523 fn test_rlike_snowflake_to_duckdb_3arg_flags() {
10524 let dialect = Dialect::get(DialectType::Snowflake);
10525 let result = dialect
10526 .transpile("SELECT RLIKE(a, b, 'i')", DialectType::DuckDB)
10527 .unwrap();
10528 assert_eq!(result[0], "SELECT REGEXP_FULL_MATCH(a, b, 'i')");
10529 }
10530
10531 #[test]
10532 fn test_regexp_extract_all_bigquery_to_snowflake_no_capture() {
10533 let dialect = Dialect::get(DialectType::BigQuery);
10534 let result = dialect
10535 .transpile(
10536 "SELECT REGEXP_EXTRACT_ALL(s, 'pattern')",
10537 DialectType::Snowflake,
10538 )
10539 .unwrap();
10540 assert_eq!(result[0], "SELECT REGEXP_SUBSTR_ALL(s, 'pattern')");
10541 }
10542
10543 #[test]
10544 fn test_regexp_extract_all_bigquery_to_snowflake_with_capture() {
10545 let dialect = Dialect::get(DialectType::BigQuery);
10546 let result = dialect
10547 .transpile(
10548 "SELECT REGEXP_EXTRACT_ALL(s, '(a)[0-9]')",
10549 DialectType::Snowflake,
10550 )
10551 .unwrap();
10552 assert_eq!(
10553 result[0],
10554 "SELECT REGEXP_SUBSTR_ALL(s, '(a)[0-9]', 1, 1, 'c', 1)"
10555 );
10556 }
10557
10558 #[test]
10559 fn test_regexp_instr_snowflake_to_duckdb_2arg() {
10560 let dialect = Dialect::get(DialectType::Snowflake);
10561 let result = dialect
10562 .transpile("SELECT REGEXP_INSTR(s, 'pattern')", DialectType::DuckDB)
10563 .unwrap();
10564 assert!(
10565 result[0].contains("CASE WHEN"),
10566 "Expected CASE WHEN in result: {}",
10567 result[0]
10568 );
10569 assert!(
10570 result[0].contains("LIST_SUM"),
10571 "Expected LIST_SUM in result: {}",
10572 result[0]
10573 );
10574 }
10575
10576 #[test]
10577 fn test_array_except_generic_to_duckdb() {
10578 let dialect = Dialect::get(DialectType::Generic);
10579 let result = dialect
10580 .transpile(
10581 "SELECT ARRAY_EXCEPT(ARRAY(1, 2, 3), ARRAY(2))",
10582 DialectType::DuckDB,
10583 )
10584 .unwrap();
10585 eprintln!("ARRAY_EXCEPT Generic->DuckDB: {}", result[0]);
10586 assert!(
10587 result[0].contains("CASE WHEN"),
10588 "Expected CASE WHEN: {}",
10589 result[0]
10590 );
10591 assert!(
10592 result[0].contains("LIST_FILTER"),
10593 "Expected LIST_FILTER: {}",
10594 result[0]
10595 );
10596 assert!(
10597 result[0].contains("LIST_DISTINCT"),
10598 "Expected LIST_DISTINCT: {}",
10599 result[0]
10600 );
10601 assert!(
10602 result[0].contains("IS NOT DISTINCT FROM"),
10603 "Expected IS NOT DISTINCT FROM: {}",
10604 result[0]
10605 );
10606 assert!(
10607 result[0].contains("= 0"),
10608 "Expected = 0 filter: {}",
10609 result[0]
10610 );
10611 }
10612
10613 #[test]
10614 fn test_array_except_generic_to_snowflake() {
10615 let dialect = Dialect::get(DialectType::Generic);
10616 let result = dialect
10617 .transpile(
10618 "SELECT ARRAY_EXCEPT(ARRAY(1, 2, 3), ARRAY(2))",
10619 DialectType::Snowflake,
10620 )
10621 .unwrap();
10622 eprintln!("ARRAY_EXCEPT Generic->Snowflake: {}", result[0]);
10623 assert_eq!(result[0], "SELECT ARRAY_EXCEPT([1, 2, 3], [2])");
10624 }
10625
10626 #[test]
10627 fn test_array_except_generic_to_presto() {
10628 let dialect = Dialect::get(DialectType::Generic);
10629 let result = dialect
10630 .transpile(
10631 "SELECT ARRAY_EXCEPT(ARRAY(1, 2, 3), ARRAY(2))",
10632 DialectType::Presto,
10633 )
10634 .unwrap();
10635 eprintln!("ARRAY_EXCEPT Generic->Presto: {}", result[0]);
10636 assert_eq!(result[0], "SELECT ARRAY_EXCEPT(ARRAY[1, 2, 3], ARRAY[2])");
10637 }
10638
10639 #[test]
10640 fn test_array_except_snowflake_to_duckdb() {
10641 let dialect = Dialect::get(DialectType::Snowflake);
10642 let result = dialect
10643 .transpile("SELECT ARRAY_EXCEPT([1, 2, 3], [2])", DialectType::DuckDB)
10644 .unwrap();
10645 eprintln!("ARRAY_EXCEPT Snowflake->DuckDB: {}", result[0]);
10646 assert!(
10647 result[0].contains("CASE WHEN"),
10648 "Expected CASE WHEN: {}",
10649 result[0]
10650 );
10651 assert!(
10652 result[0].contains("LIST_TRANSFORM"),
10653 "Expected LIST_TRANSFORM: {}",
10654 result[0]
10655 );
10656 }
10657
10658 #[test]
10659 fn test_array_contains_snowflake_to_snowflake() {
10660 let dialect = Dialect::get(DialectType::Snowflake);
10661 let result = dialect
10662 .transpile(
10663 "SELECT ARRAY_CONTAINS(x, [1, NULL, 3])",
10664 DialectType::Snowflake,
10665 )
10666 .unwrap();
10667 eprintln!("ARRAY_CONTAINS Snowflake->Snowflake: {}", result[0]);
10668 assert_eq!(result[0], "SELECT ARRAY_CONTAINS(x, [1, NULL, 3])");
10669 }
10670
10671 #[test]
10672 fn test_array_contains_snowflake_to_duckdb() {
10673 let dialect = Dialect::get(DialectType::Snowflake);
10674 let result = dialect
10675 .transpile(
10676 "SELECT ARRAY_CONTAINS(x, [1, NULL, 3])",
10677 DialectType::DuckDB,
10678 )
10679 .unwrap();
10680 eprintln!("ARRAY_CONTAINS Snowflake->DuckDB: {}", result[0]);
10681 assert!(
10682 result[0].contains("CASE WHEN"),
10683 "Expected CASE WHEN: {}",
10684 result[0]
10685 );
10686 assert!(
10687 result[0].contains("NULLIF"),
10688 "Expected NULLIF: {}",
10689 result[0]
10690 );
10691 assert!(
10692 result[0].contains("ARRAY_CONTAINS"),
10693 "Expected ARRAY_CONTAINS: {}",
10694 result[0]
10695 );
10696 }
10697
10698 #[test]
10699 fn test_array_distinct_snowflake_to_duckdb() {
10700 let dialect = Dialect::get(DialectType::Snowflake);
10701 let result = dialect
10702 .transpile(
10703 "SELECT ARRAY_DISTINCT([1, 2, 2, 3, 1])",
10704 DialectType::DuckDB,
10705 )
10706 .unwrap();
10707 eprintln!("ARRAY_DISTINCT Snowflake->DuckDB: {}", result[0]);
10708 assert!(
10709 result[0].contains("CASE WHEN"),
10710 "Expected CASE WHEN: {}",
10711 result[0]
10712 );
10713 assert!(
10714 result[0].contains("LIST_DISTINCT"),
10715 "Expected LIST_DISTINCT: {}",
10716 result[0]
10717 );
10718 assert!(
10719 result[0].contains("LIST_APPEND"),
10720 "Expected LIST_APPEND: {}",
10721 result[0]
10722 );
10723 assert!(
10724 result[0].contains("LIST_FILTER"),
10725 "Expected LIST_FILTER: {}",
10726 result[0]
10727 );
10728 }
10729}