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