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