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, Top, Var, WindowFrame, WindowFrameBound,
167 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};
184use crate::parser::Parser;
185#[cfg(feature = "transpile")]
186use crate::tokens::TokenType;
187use crate::tokens::{Token, Tokenizer, TokenizerConfig};
188#[cfg(feature = "transpile")]
189use crate::traversal::ExpressionWalk;
190use serde::{Deserialize, Serialize};
191use std::collections::HashMap;
192use std::sync::{Arc, LazyLock, RwLock};
193
194#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
203#[serde(rename_all = "lowercase")]
204pub enum DialectType {
205 Generic,
207 PostgreSQL,
209 MySQL,
211 BigQuery,
213 Snowflake,
215 DuckDB,
217 SQLite,
219 Hive,
221 Spark,
223 Trino,
225 Presto,
227 Redshift,
229 TSQL,
231 Oracle,
233 ClickHouse,
235 Databricks,
237 Athena,
239 Teradata,
241 Doris,
243 StarRocks,
245 Materialize,
247 RisingWave,
249 SingleStore,
251 CockroachDB,
253 TiDB,
255 Druid,
257 Solr,
259 Tableau,
261 Dune,
263 Fabric,
265 Drill,
267 Dremio,
269 Exasol,
271 DataFusion,
273}
274
275impl Default for DialectType {
276 fn default() -> Self {
277 DialectType::Generic
278 }
279}
280
281impl std::fmt::Display for DialectType {
282 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
283 match self {
284 DialectType::Generic => write!(f, "generic"),
285 DialectType::PostgreSQL => write!(f, "postgresql"),
286 DialectType::MySQL => write!(f, "mysql"),
287 DialectType::BigQuery => write!(f, "bigquery"),
288 DialectType::Snowflake => write!(f, "snowflake"),
289 DialectType::DuckDB => write!(f, "duckdb"),
290 DialectType::SQLite => write!(f, "sqlite"),
291 DialectType::Hive => write!(f, "hive"),
292 DialectType::Spark => write!(f, "spark"),
293 DialectType::Trino => write!(f, "trino"),
294 DialectType::Presto => write!(f, "presto"),
295 DialectType::Redshift => write!(f, "redshift"),
296 DialectType::TSQL => write!(f, "tsql"),
297 DialectType::Oracle => write!(f, "oracle"),
298 DialectType::ClickHouse => write!(f, "clickhouse"),
299 DialectType::Databricks => write!(f, "databricks"),
300 DialectType::Athena => write!(f, "athena"),
301 DialectType::Teradata => write!(f, "teradata"),
302 DialectType::Doris => write!(f, "doris"),
303 DialectType::StarRocks => write!(f, "starrocks"),
304 DialectType::Materialize => write!(f, "materialize"),
305 DialectType::RisingWave => write!(f, "risingwave"),
306 DialectType::SingleStore => write!(f, "singlestore"),
307 DialectType::CockroachDB => write!(f, "cockroachdb"),
308 DialectType::TiDB => write!(f, "tidb"),
309 DialectType::Druid => write!(f, "druid"),
310 DialectType::Solr => write!(f, "solr"),
311 DialectType::Tableau => write!(f, "tableau"),
312 DialectType::Dune => write!(f, "dune"),
313 DialectType::Fabric => write!(f, "fabric"),
314 DialectType::Drill => write!(f, "drill"),
315 DialectType::Dremio => write!(f, "dremio"),
316 DialectType::Exasol => write!(f, "exasol"),
317 DialectType::DataFusion => write!(f, "datafusion"),
318 }
319 }
320}
321
322impl std::str::FromStr for DialectType {
323 type Err = crate::error::Error;
324
325 fn from_str(s: &str) -> Result<Self> {
326 match s.to_ascii_lowercase().as_str() {
327 "generic" | "" => Ok(DialectType::Generic),
328 "postgres" | "postgresql" => Ok(DialectType::PostgreSQL),
329 "mysql" => Ok(DialectType::MySQL),
330 "bigquery" => Ok(DialectType::BigQuery),
331 "snowflake" => Ok(DialectType::Snowflake),
332 "duckdb" => Ok(DialectType::DuckDB),
333 "sqlite" => Ok(DialectType::SQLite),
334 "hive" => Ok(DialectType::Hive),
335 "spark" | "spark2" => Ok(DialectType::Spark),
336 "trino" => Ok(DialectType::Trino),
337 "presto" => Ok(DialectType::Presto),
338 "redshift" => Ok(DialectType::Redshift),
339 "tsql" | "mssql" | "sqlserver" => Ok(DialectType::TSQL),
340 "oracle" => Ok(DialectType::Oracle),
341 "clickhouse" => Ok(DialectType::ClickHouse),
342 "databricks" => Ok(DialectType::Databricks),
343 "athena" => Ok(DialectType::Athena),
344 "teradata" => Ok(DialectType::Teradata),
345 "doris" => Ok(DialectType::Doris),
346 "starrocks" => Ok(DialectType::StarRocks),
347 "materialize" => Ok(DialectType::Materialize),
348 "risingwave" => Ok(DialectType::RisingWave),
349 "singlestore" | "memsql" => Ok(DialectType::SingleStore),
350 "cockroachdb" | "cockroach" => Ok(DialectType::CockroachDB),
351 "tidb" => Ok(DialectType::TiDB),
352 "druid" => Ok(DialectType::Druid),
353 "solr" => Ok(DialectType::Solr),
354 "tableau" => Ok(DialectType::Tableau),
355 "dune" => Ok(DialectType::Dune),
356 "fabric" => Ok(DialectType::Fabric),
357 "drill" => Ok(DialectType::Drill),
358 "dremio" => Ok(DialectType::Dremio),
359 "exasol" => Ok(DialectType::Exasol),
360 "datafusion" | "arrow-datafusion" | "arrow_datafusion" => Ok(DialectType::DataFusion),
361 _ => Err(crate::error::Error::parse(
362 format!("Unknown dialect: {}", s),
363 0,
364 0,
365 0,
366 0,
367 )),
368 }
369 }
370}
371
372pub trait DialectImpl {
388 fn dialect_type(&self) -> DialectType;
390
391 fn tokenizer_config(&self) -> TokenizerConfig {
396 TokenizerConfig::default()
397 }
398
399 #[cfg(feature = "generate")]
404 fn generator_config(&self) -> GeneratorConfig {
405 GeneratorConfig::default()
406 }
407
408 #[cfg(feature = "generate")]
414 fn generator_config_for_expr(&self, _expr: &Expression) -> GeneratorConfig {
415 self.generator_config()
416 }
417
418 #[cfg(feature = "transpile")]
424 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
425 Ok(expr)
426 }
427
428 #[cfg(feature = "transpile")]
434 fn preprocess(&self, expr: Expression) -> Result<Expression> {
435 Ok(expr)
436 }
437}
438
439#[cfg(any(
446 feature = "transpile",
447 feature = "ast-tools",
448 feature = "generate",
449 feature = "semantic"
450))]
451fn transform_data_type_recursive<F>(
452 dt: crate::expressions::DataType,
453 transform_fn: &F,
454) -> Result<crate::expressions::DataType>
455where
456 F: Fn(Expression) -> Result<Expression>,
457{
458 use crate::expressions::DataType;
459 let dt_expr = transform_fn(Expression::DataType(dt))?;
461 let dt = match dt_expr {
462 Expression::DataType(d) => d,
463 _ => {
464 return Ok(match dt_expr {
465 _ => DataType::Custom {
466 name: "UNKNOWN".to_string(),
467 },
468 })
469 }
470 };
471 match dt {
473 DataType::Array {
474 element_type,
475 dimension,
476 } => {
477 let inner = transform_data_type_recursive(*element_type, transform_fn)?;
478 Ok(DataType::Array {
479 element_type: Box::new(inner),
480 dimension,
481 })
482 }
483 DataType::List { element_type } => {
484 let inner = transform_data_type_recursive(*element_type, transform_fn)?;
485 Ok(DataType::List {
486 element_type: Box::new(inner),
487 })
488 }
489 DataType::Struct { fields, nested } => {
490 let mut new_fields = Vec::new();
491 for mut field in fields {
492 field.data_type = transform_data_type_recursive(field.data_type, transform_fn)?;
493 new_fields.push(field);
494 }
495 Ok(DataType::Struct {
496 fields: new_fields,
497 nested,
498 })
499 }
500 DataType::Map {
501 key_type,
502 value_type,
503 } => {
504 let k = transform_data_type_recursive(*key_type, transform_fn)?;
505 let v = transform_data_type_recursive(*value_type, transform_fn)?;
506 Ok(DataType::Map {
507 key_type: Box::new(k),
508 value_type: Box::new(v),
509 })
510 }
511 other => Ok(other),
512 }
513}
514
515#[cfg(feature = "transpile")]
518fn duckdb_to_presto_format(fmt: &str) -> String {
519 let mut result = fmt.to_string();
521 result = result.replace("%-m", "\x01NOPADM\x01");
523 result = result.replace("%-d", "\x01NOPADD\x01");
524 result = result.replace("%-I", "\x01NOPADI\x01");
525 result = result.replace("%-H", "\x01NOPADH\x01");
526 result = result.replace("%H:%M:%S", "\x01HMS\x01");
527 result = result.replace("%Y-%m-%d", "\x01YMD\x01");
528 result = result.replace("%M", "%i");
530 result = result.replace("%S", "%s");
531 result = result.replace("\x01NOPADM\x01", "%c");
533 result = result.replace("\x01NOPADD\x01", "%e");
534 result = result.replace("\x01NOPADI\x01", "%l");
535 result = result.replace("\x01NOPADH\x01", "%k");
536 result = result.replace("\x01HMS\x01", "%T");
537 result = result.replace("\x01YMD\x01", "%Y-%m-%d");
538 result
539}
540
541#[cfg(feature = "transpile")]
544fn duckdb_to_bigquery_format(fmt: &str) -> String {
545 let mut result = fmt.to_string();
546 result = result.replace("%-d", "%e");
548 result = result.replace("%Y-%m-%d %H:%M:%S", "%F %T");
549 result = result.replace("%Y-%m-%d", "%F");
550 result = result.replace("%H:%M:%S", "%T");
551 result
552}
553
554#[cfg(feature = "transpile")]
555fn presto_to_java_format(fmt: &str) -> String {
556 fmt.replace("%Y", "yyyy")
557 .replace("%m", "MM")
558 .replace("%d", "dd")
559 .replace("%H", "HH")
560 .replace("%i", "mm")
561 .replace("%S", "ss")
562 .replace("%s", "ss")
563 .replace("%y", "yy")
564 .replace("%T", "HH:mm:ss")
565 .replace("%F", "yyyy-MM-dd")
566 .replace("%M", "MMMM")
567}
568
569#[cfg(feature = "transpile")]
570fn normalize_presto_format(fmt: &str) -> String {
571 fmt.replace("%H:%i:%S", "%T").replace("%H:%i:%s", "%T")
572}
573
574#[cfg(feature = "transpile")]
575fn presto_to_duckdb_format(fmt: &str) -> String {
576 fmt.replace("%i", "%M")
577 .replace("%s", "%S")
578 .replace("%T", "%H:%M:%S")
579}
580
581#[cfg(feature = "transpile")]
582fn presto_to_bigquery_format(fmt: &str) -> String {
583 fmt.replace("%Y-%m-%d", "%F")
584 .replace("%H:%i:%S", "%T")
585 .replace("%H:%i:%s", "%T")
586 .replace("%i", "%M")
587 .replace("%s", "%S")
588}
589
590#[cfg(feature = "transpile")]
591fn is_default_presto_timestamp_format(fmt: &str) -> bool {
592 let normalized = normalize_presto_format(fmt);
593 normalized == "%Y-%m-%d %T"
594 || normalized == "%Y-%m-%d %H:%i:%S"
595 || fmt == "%Y-%m-%d %H:%i:%S"
596 || fmt == "%Y-%m-%d %T"
597}
598
599#[cfg(feature = "transpile")]
600fn is_default_presto_date_format(fmt: &str) -> bool {
601 fmt == "%Y-%m-%d" || fmt == "%F"
602}
603
604#[cfg(any(
612 feature = "transpile",
613 feature = "ast-tools",
614 feature = "generate",
615 feature = "semantic"
616))]
617pub fn transform_recursive<F>(expr: Expression, transform_fn: &F) -> Result<Expression>
618where
619 F: Fn(Expression) -> Result<Expression>,
620{
621 #[cfg(feature = "stacker")]
622 {
623 let red_zone = if cfg!(debug_assertions) {
624 4 * 1024 * 1024
625 } else {
626 1024 * 1024
627 };
628 stacker::maybe_grow(red_zone, 8 * 1024 * 1024, move || {
629 transform_recursive_inner(expr, transform_fn)
630 })
631 }
632 #[cfg(not(feature = "stacker"))]
633 {
634 transform_recursive_inner(expr, transform_fn)
635 }
636}
637
638#[cfg(any(
639 feature = "transpile",
640 feature = "ast-tools",
641 feature = "generate",
642 feature = "semantic"
643))]
644fn transform_recursive_inner<F>(expr: Expression, transform_fn: &F) -> Result<Expression>
645where
646 F: Fn(Expression) -> Result<Expression>,
647{
648 enum Task {
649 Visit(Expression),
650 Finish {
651 shell: Expression,
652 child_count: usize,
653 },
654 }
655
656 fn uses_generated_dispatch(expression: &Expression) -> bool {
660 match expression {
661 Expression::Select(select) => {
662 select.joins.is_empty()
663 && select.with.is_none()
664 && select.order_by.is_none()
665 && select.windows.is_none()
666 && select.settings.is_none()
667 }
668 Expression::Union(set_op) => set_op.with.is_none() && set_op.order_by.is_none(),
669 Expression::Intersect(set_op) => set_op.with.is_none() && set_op.order_by.is_none(),
670 Expression::Except(set_op) => set_op.with.is_none() && set_op.order_by.is_none(),
671 Expression::Literal(_)
672 | Expression::Boolean(_)
673 | Expression::Null(_)
674 | Expression::Identifier(_)
675 | Expression::Star(_)
676 | Expression::Parameter(_)
677 | Expression::Placeholder(_)
678 | Expression::SessionParameter(_)
679 | Expression::Alias(_)
680 | Expression::Paren(_)
681 | Expression::Not(_)
682 | Expression::Neg(_)
683 | Expression::IsNull(_)
684 | Expression::IsTrue(_)
685 | Expression::IsFalse(_)
686 | Expression::Subquery(_)
687 | Expression::Exists(_)
688 | Expression::TableArgument(_)
689 | Expression::And(_)
690 | Expression::Or(_)
691 | Expression::Add(_)
692 | Expression::Sub(_)
693 | Expression::Mul(_)
694 | Expression::Div(_)
695 | Expression::Eq(_)
696 | Expression::Lt(_)
697 | Expression::Gt(_)
698 | Expression::Neq(_)
699 | Expression::Lte(_)
700 | Expression::Gte(_)
701 | Expression::Mod(_)
702 | Expression::Concat(_)
703 | Expression::BitwiseAnd(_)
704 | Expression::BitwiseOr(_)
705 | Expression::BitwiseXor(_)
706 | Expression::Is(_)
707 | Expression::MemberOf(_)
708 | Expression::ArrayContainsAll(_)
709 | Expression::ArrayContainedBy(_)
710 | Expression::ArrayOverlaps(_)
711 | Expression::TsMatch(_)
712 | Expression::Adjacent(_)
713 | Expression::Like(_)
714 | Expression::ILike(_)
715 | Expression::Function(_)
716 | Expression::Lead(_)
717 | Expression::Lag(_)
718 | Expression::Array(_)
719 | Expression::Tuple(_)
720 | Expression::ArrayFunc(_)
721 | Expression::Coalesce(_)
722 | Expression::Greatest(_)
723 | Expression::Least(_)
724 | Expression::ArrayConcat(_)
725 | Expression::ArrayIntersect(_)
726 | Expression::ArrayZip(_)
727 | Expression::MapConcat(_)
728 | Expression::JsonArray(_)
729 | Expression::From(_) => true,
730 _ => false,
731 }
732 }
733
734 let mut tasks = vec![Task::Visit(expr)];
735 let mut results = Vec::new();
736
737 while let Some(task) = tasks.pop() {
738 match task {
739 Task::Visit(mut expression) => {
740 if !uses_generated_dispatch(&expression) {
741 results.push(transform_recursive_reference(expression, transform_fn)?);
742 continue;
743 }
744
745 let mut children = Vec::new();
746 crate::ast_children::for_each_child_mut(&mut expression, |child| {
747 children.push(std::mem::replace(child, Expression::Null(Null)));
748 });
749 let child_count = children.len();
750 tasks.push(Task::Finish {
751 shell: expression,
752 child_count,
753 });
754 for child in children.into_iter().rev() {
755 tasks.push(Task::Visit(child));
756 }
757 }
758 Task::Finish {
759 mut shell,
760 child_count,
761 } => {
762 if results.len() < child_count {
763 return Err(crate::error::Error::Internal(
764 "transform result stack underflow".to_string(),
765 ));
766 }
767 let transformed_children = results.split_off(results.len() - child_count);
768 let mut transformed_children = transformed_children.into_iter();
769 crate::ast_children::for_each_child_mut(&mut shell, |child| {
770 *child = transformed_children
771 .next()
772 .expect("validated transform child count");
773 });
774 if transformed_children.next().is_some() {
775 return Err(crate::error::Error::Internal(
776 "transform child restoration mismatch".to_string(),
777 ));
778 }
779 results.push(transform_fn(shell)?);
780 }
781 }
782 }
783
784 match results.len() {
785 1 => Ok(results.pop().expect("single transform result")),
786 _ => Err(crate::error::Error::Internal(
787 "unexpected transform result stack size".to_string(),
788 )),
789 }
790}
791
792#[cfg(any(
793 feature = "transpile",
794 feature = "ast-tools",
795 feature = "generate",
796 feature = "semantic"
797))]
798fn transform_table_ref_recursive<F>(table: TableRef, transform_fn: &F) -> Result<TableRef>
799where
800 F: Fn(Expression) -> Result<Expression>,
801{
802 match transform_recursive(Expression::Table(Box::new(table)), transform_fn)? {
803 Expression::Table(table) => Ok(*table),
804 _ => Err(crate::error::Error::parse(
805 "TableRef transformation returned non-table expression",
806 0,
807 0,
808 0,
809 0,
810 )),
811 }
812}
813
814#[cfg(any(
815 feature = "transpile",
816 feature = "ast-tools",
817 feature = "generate",
818 feature = "semantic"
819))]
820fn transform_from_recursive<F>(from: From, transform_fn: &F) -> Result<From>
821where
822 F: Fn(Expression) -> Result<Expression>,
823{
824 match transform_recursive(Expression::From(Box::new(from)), transform_fn)? {
825 Expression::From(from) => Ok(*from),
826 _ => Err(crate::error::Error::parse(
827 "FROM transformation returned non-FROM expression",
828 0,
829 0,
830 0,
831 0,
832 )),
833 }
834}
835
836#[cfg(any(
837 feature = "transpile",
838 feature = "ast-tools",
839 feature = "generate",
840 feature = "semantic"
841))]
842fn transform_join_recursive<F>(mut join: Join, transform_fn: &F) -> Result<Join>
843where
844 F: Fn(Expression) -> Result<Expression>,
845{
846 join.this = transform_recursive(join.this, transform_fn)?;
847 if let Some(on) = join.on.take() {
848 join.on = Some(transform_recursive(on, transform_fn)?);
849 }
850 if let Some(match_condition) = join.match_condition.take() {
851 join.match_condition = Some(transform_recursive(match_condition, transform_fn)?);
852 }
853 join.pivots = join
854 .pivots
855 .into_iter()
856 .map(|pivot| transform_recursive(pivot, transform_fn))
857 .collect::<Result<Vec<_>>>()?;
858
859 match transform_fn(Expression::Join(Box::new(join)))? {
860 Expression::Join(join) => Ok(*join),
861 _ => Err(crate::error::Error::parse(
862 "Join transformation returned non-join expression",
863 0,
864 0,
865 0,
866 0,
867 )),
868 }
869}
870
871#[cfg(any(
872 feature = "transpile",
873 feature = "ast-tools",
874 feature = "generate",
875 feature = "semantic"
876))]
877fn transform_output_clause_recursive<F>(
878 mut output: OutputClause,
879 transform_fn: &F,
880) -> Result<OutputClause>
881where
882 F: Fn(Expression) -> Result<Expression>,
883{
884 output.columns = output
885 .columns
886 .into_iter()
887 .map(|column| transform_recursive(column, transform_fn))
888 .collect::<Result<Vec<_>>>()?;
889 if let Some(into_table) = output.into_table.take() {
890 output.into_table = Some(transform_recursive(into_table, transform_fn)?);
891 }
892 Ok(output)
893}
894
895#[cfg(any(
896 feature = "transpile",
897 feature = "ast-tools",
898 feature = "generate",
899 feature = "semantic"
900))]
901fn transform_with_recursive<F>(mut with: With, transform_fn: &F) -> Result<With>
902where
903 F: Fn(Expression) -> Result<Expression>,
904{
905 with.ctes = with
906 .ctes
907 .into_iter()
908 .map(|mut cte| {
909 cte.this = transform_recursive(cte.this, transform_fn)?;
910 Ok(cte)
911 })
912 .collect::<Result<Vec<_>>>()?;
913 if let Some(search) = with.search.take() {
914 with.search = Some(Box::new(transform_recursive(*search, transform_fn)?));
915 }
916 Ok(with)
917}
918
919#[cfg(any(
920 feature = "transpile",
921 feature = "ast-tools",
922 feature = "generate",
923 feature = "semantic"
924))]
925fn transform_order_by_recursive<F>(mut order: OrderBy, transform_fn: &F) -> Result<OrderBy>
926where
927 F: Fn(Expression) -> Result<Expression>,
928{
929 order.expressions = order
930 .expressions
931 .into_iter()
932 .map(|mut ordered| {
933 let original = ordered.this.clone();
934 ordered.this = transform_recursive(ordered.this, transform_fn).unwrap_or(original);
935 match transform_fn(Expression::Ordered(Box::new(ordered.clone()))) {
936 Ok(Expression::Ordered(transformed)) => Ok(*transformed),
937 Ok(_) | Err(_) => Ok(ordered),
938 }
939 })
940 .collect::<Result<Vec<_>>>()?;
941 Ok(order)
942}
943
944#[cfg(any(
945 feature = "transpile",
946 feature = "ast-tools",
947 feature = "generate",
948 feature = "semantic"
949))]
950fn transform_recursive_reference<F>(expr: Expression, transform_fn: &F) -> Result<Expression>
951where
952 F: Fn(Expression) -> Result<Expression>,
953{
954 use crate::expressions::BinaryOp;
955
956 macro_rules! recurse_agg {
958 ($variant:ident, $f:expr) => {{
959 let mut f = $f;
960 f.this = transform_recursive(f.this, transform_fn)?;
961 if let Some(filter) = f.filter.take() {
962 f.filter = Some(transform_recursive(filter, transform_fn)?);
963 }
964 for ord in &mut f.order_by {
965 ord.this = transform_recursive(
966 std::mem::replace(&mut ord.this, Expression::Null(crate::expressions::Null)),
967 transform_fn,
968 )?;
969 }
970 if let Some((ref mut expr, _)) = f.having_max {
971 *expr = Box::new(transform_recursive(
972 std::mem::replace(expr.as_mut(), Expression::Null(crate::expressions::Null)),
973 transform_fn,
974 )?);
975 }
976 if let Some(limit) = f.limit.take() {
977 f.limit = Some(Box::new(transform_recursive(*limit, transform_fn)?));
978 }
979 Expression::$variant(f)
980 }};
981 }
982
983 macro_rules! transform_binary {
985 ($variant:ident, $op:expr) => {{
986 let left = transform_recursive($op.left, transform_fn)?;
987 let right = transform_recursive($op.right, transform_fn)?;
988 Expression::$variant(Box::new(BinaryOp {
989 left,
990 right,
991 left_comments: $op.left_comments,
992 operator_comments: $op.operator_comments,
993 trailing_comments: $op.trailing_comments,
994 inferred_type: $op.inferred_type,
995 }))
996 }};
997 }
998
999 if matches!(
1001 &expr,
1002 Expression::Literal(_)
1003 | Expression::Boolean(_)
1004 | Expression::Null(_)
1005 | Expression::Identifier(_)
1006 | Expression::Star(_)
1007 | Expression::Parameter(_)
1008 | Expression::Placeholder(_)
1009 | Expression::SessionParameter(_)
1010 ) {
1011 return transform_fn(expr);
1012 }
1013
1014 let expr = match expr {
1016 Expression::Select(mut select) => {
1017 select.expressions = select
1018 .expressions
1019 .into_iter()
1020 .map(|e| transform_recursive(e, transform_fn))
1021 .collect::<Result<Vec<_>>>()?;
1022
1023 if let Some(mut from) = select.from.take() {
1025 from.expressions = from
1026 .expressions
1027 .into_iter()
1028 .map(|e| transform_recursive(e, transform_fn))
1029 .collect::<Result<Vec<_>>>()?;
1030 select.from = Some(from);
1031 }
1032
1033 select.joins = select
1035 .joins
1036 .into_iter()
1037 .map(|mut join| {
1038 join.this = transform_recursive(join.this, transform_fn)?;
1039 if let Some(on) = join.on.take() {
1040 join.on = Some(transform_recursive(on, transform_fn)?);
1041 }
1042 match transform_fn(Expression::Join(Box::new(join)))? {
1044 Expression::Join(j) => Ok(*j),
1045 _ => Err(crate::error::Error::parse(
1046 "Join transformation returned non-join expression",
1047 0,
1048 0,
1049 0,
1050 0,
1051 )),
1052 }
1053 })
1054 .collect::<Result<Vec<_>>>()?;
1055
1056 select.lateral_views = select
1058 .lateral_views
1059 .into_iter()
1060 .map(|mut lv| {
1061 lv.this = transform_recursive(lv.this, transform_fn)?;
1062 Ok(lv)
1063 })
1064 .collect::<Result<Vec<_>>>()?;
1065
1066 if let Some(mut where_clause) = select.where_clause.take() {
1068 where_clause.this = transform_recursive(where_clause.this, transform_fn)?;
1069 select.where_clause = Some(where_clause);
1070 }
1071
1072 if let Some(mut group_by) = select.group_by.take() {
1074 group_by.expressions = group_by
1075 .expressions
1076 .into_iter()
1077 .map(|e| transform_recursive(e, transform_fn))
1078 .collect::<Result<Vec<_>>>()?;
1079 select.group_by = Some(group_by);
1080 }
1081
1082 if let Some(mut having) = select.having.take() {
1084 having.this = transform_recursive(having.this, transform_fn)?;
1085 select.having = Some(having);
1086 }
1087
1088 if let Some(mut with) = select.with.take() {
1090 with.ctes = with
1091 .ctes
1092 .into_iter()
1093 .map(|mut cte| {
1094 let original = cte.this.clone();
1095 cte.this = transform_recursive(cte.this, transform_fn).unwrap_or(original);
1096 cte
1097 })
1098 .collect();
1099 select.with = Some(with);
1100 }
1101
1102 if let Some(mut order) = select.order_by.take() {
1104 order.expressions = order
1105 .expressions
1106 .into_iter()
1107 .map(|o| {
1108 let mut o = o;
1109 let original = o.this.clone();
1110 o.this = transform_recursive(o.this, transform_fn).unwrap_or(original);
1111 match transform_fn(Expression::Ordered(Box::new(o.clone()))) {
1113 Ok(Expression::Ordered(transformed)) => *transformed,
1114 Ok(_) | Err(_) => o,
1115 }
1116 })
1117 .collect();
1118 select.order_by = Some(order);
1119 }
1120
1121 if let Some(ref mut windows) = select.windows {
1123 for nw in windows.iter_mut() {
1124 nw.spec.order_by = std::mem::take(&mut nw.spec.order_by)
1125 .into_iter()
1126 .map(|o| {
1127 let mut o = o;
1128 let original = o.this.clone();
1129 o.this = transform_recursive(o.this, transform_fn).unwrap_or(original);
1130 match transform_fn(Expression::Ordered(Box::new(o.clone()))) {
1131 Ok(Expression::Ordered(transformed)) => *transformed,
1132 Ok(_) | Err(_) => o,
1133 }
1134 })
1135 .collect();
1136 }
1137 }
1138
1139 if let Some(mut qual) = select.qualify.take() {
1141 qual.this = transform_recursive(qual.this, transform_fn)?;
1142 select.qualify = Some(qual);
1143 }
1144
1145 Expression::Select(select)
1146 }
1147 Expression::Function(mut f) => {
1148 f.args = f
1149 .args
1150 .into_iter()
1151 .map(|e| transform_recursive(e, transform_fn))
1152 .collect::<Result<Vec<_>>>()?;
1153 Expression::Function(f)
1154 }
1155 Expression::AggregateFunction(mut f) => {
1156 f.args = f
1157 .args
1158 .into_iter()
1159 .map(|e| transform_recursive(e, transform_fn))
1160 .collect::<Result<Vec<_>>>()?;
1161 if let Some(filter) = f.filter {
1162 f.filter = Some(transform_recursive(filter, transform_fn)?);
1163 }
1164 Expression::AggregateFunction(f)
1165 }
1166 Expression::WindowFunction(mut wf) => {
1167 wf.this = transform_recursive(wf.this, transform_fn)?;
1168 wf.over.partition_by = wf
1169 .over
1170 .partition_by
1171 .into_iter()
1172 .map(|e| transform_recursive(e, transform_fn))
1173 .collect::<Result<Vec<_>>>()?;
1174 wf.over.order_by = wf
1176 .over
1177 .order_by
1178 .into_iter()
1179 .map(|o| {
1180 let mut o = o;
1181 o.this = transform_recursive(o.this, transform_fn)?;
1182 match transform_fn(Expression::Ordered(Box::new(o)))? {
1183 Expression::Ordered(transformed) => Ok(*transformed),
1184 _ => Err(crate::error::Error::parse(
1185 "Ordered transformation returned non-Ordered expression",
1186 0,
1187 0,
1188 0,
1189 0,
1190 )),
1191 }
1192 })
1193 .collect::<Result<Vec<_>>>()?;
1194 Expression::WindowFunction(wf)
1195 }
1196 Expression::Alias(mut a) => {
1197 a.this = transform_recursive(a.this, transform_fn)?;
1198 Expression::Alias(a)
1199 }
1200 Expression::Cast(mut c) => {
1201 c.this = transform_recursive(c.this, transform_fn)?;
1202 c.to = transform_data_type_recursive(c.to, transform_fn)?;
1204 Expression::Cast(c)
1205 }
1206 Expression::And(op) => transform_binary!(And, *op),
1207 Expression::Or(op) => transform_binary!(Or, *op),
1208 Expression::Add(op) => transform_binary!(Add, *op),
1209 Expression::Sub(op) => transform_binary!(Sub, *op),
1210 Expression::Mul(op) => transform_binary!(Mul, *op),
1211 Expression::Div(op) => transform_binary!(Div, *op),
1212 Expression::Eq(op) => transform_binary!(Eq, *op),
1213 Expression::Lt(op) => transform_binary!(Lt, *op),
1214 Expression::Gt(op) => transform_binary!(Gt, *op),
1215 Expression::Paren(mut p) => {
1216 p.this = transform_recursive(p.this, transform_fn)?;
1217 Expression::Paren(p)
1218 }
1219 Expression::Coalesce(mut f) => {
1220 f.expressions = f
1221 .expressions
1222 .into_iter()
1223 .map(|e| transform_recursive(e, transform_fn))
1224 .collect::<Result<Vec<_>>>()?;
1225 Expression::Coalesce(f)
1226 }
1227 Expression::IfNull(mut f) => {
1228 f.this = transform_recursive(f.this, transform_fn)?;
1229 f.expression = transform_recursive(f.expression, transform_fn)?;
1230 Expression::IfNull(f)
1231 }
1232 Expression::Nvl(mut f) => {
1233 f.this = transform_recursive(f.this, transform_fn)?;
1234 f.expression = transform_recursive(f.expression, transform_fn)?;
1235 Expression::Nvl(f)
1236 }
1237 Expression::In(mut i) => {
1238 i.this = transform_recursive(i.this, transform_fn)?;
1239 i.expressions = i
1240 .expressions
1241 .into_iter()
1242 .map(|e| transform_recursive(e, transform_fn))
1243 .collect::<Result<Vec<_>>>()?;
1244 if let Some(query) = i.query {
1245 i.query = Some(transform_recursive(query, transform_fn)?);
1246 }
1247 Expression::In(i)
1248 }
1249 Expression::Not(mut n) => {
1250 n.this = transform_recursive(n.this, transform_fn)?;
1251 Expression::Not(n)
1252 }
1253 Expression::ArraySlice(mut s) => {
1254 s.this = transform_recursive(s.this, transform_fn)?;
1255 if let Some(start) = s.start {
1256 s.start = Some(transform_recursive(start, transform_fn)?);
1257 }
1258 if let Some(end) = s.end {
1259 s.end = Some(transform_recursive(end, transform_fn)?);
1260 }
1261 Expression::ArraySlice(s)
1262 }
1263 Expression::Subscript(mut s) => {
1264 s.this = transform_recursive(s.this, transform_fn)?;
1265 s.index = transform_recursive(s.index, transform_fn)?;
1266 Expression::Subscript(s)
1267 }
1268 Expression::Array(mut a) => {
1269 a.expressions = a
1270 .expressions
1271 .into_iter()
1272 .map(|e| transform_recursive(e, transform_fn))
1273 .collect::<Result<Vec<_>>>()?;
1274 Expression::Array(a)
1275 }
1276 Expression::Struct(mut s) => {
1277 let mut new_fields = Vec::new();
1278 for (name, expr) in s.fields {
1279 let transformed = transform_recursive(expr, transform_fn)?;
1280 new_fields.push((name, transformed));
1281 }
1282 s.fields = new_fields;
1283 Expression::Struct(s)
1284 }
1285 Expression::NamedArgument(mut na) => {
1286 na.value = transform_recursive(na.value, transform_fn)?;
1287 Expression::NamedArgument(na)
1288 }
1289 Expression::MapFunc(mut m) => {
1290 m.keys = m
1291 .keys
1292 .into_iter()
1293 .map(|e| transform_recursive(e, transform_fn))
1294 .collect::<Result<Vec<_>>>()?;
1295 m.values = m
1296 .values
1297 .into_iter()
1298 .map(|e| transform_recursive(e, transform_fn))
1299 .collect::<Result<Vec<_>>>()?;
1300 Expression::MapFunc(m)
1301 }
1302 Expression::ArrayFunc(mut a) => {
1303 a.expressions = a
1304 .expressions
1305 .into_iter()
1306 .map(|e| transform_recursive(e, transform_fn))
1307 .collect::<Result<Vec<_>>>()?;
1308 Expression::ArrayFunc(a)
1309 }
1310 Expression::Lambda(mut l) => {
1311 l.body = transform_recursive(l.body, transform_fn)?;
1312 Expression::Lambda(l)
1313 }
1314 Expression::JsonExtract(mut f) => {
1315 f.this = transform_recursive(f.this, transform_fn)?;
1316 f.path = transform_recursive(f.path, transform_fn)?;
1317 Expression::JsonExtract(f)
1318 }
1319 Expression::JsonExtractScalar(mut f) => {
1320 f.this = transform_recursive(f.this, transform_fn)?;
1321 f.path = transform_recursive(f.path, transform_fn)?;
1322 Expression::JsonExtractScalar(f)
1323 }
1324
1325 Expression::Length(mut f) => {
1328 f.this = transform_recursive(f.this, transform_fn)?;
1329 Expression::Length(f)
1330 }
1331 Expression::Upper(mut f) => {
1332 f.this = transform_recursive(f.this, transform_fn)?;
1333 Expression::Upper(f)
1334 }
1335 Expression::Lower(mut f) => {
1336 f.this = transform_recursive(f.this, transform_fn)?;
1337 Expression::Lower(f)
1338 }
1339 Expression::LTrim(mut f) => {
1340 f.this = transform_recursive(f.this, transform_fn)?;
1341 Expression::LTrim(f)
1342 }
1343 Expression::RTrim(mut f) => {
1344 f.this = transform_recursive(f.this, transform_fn)?;
1345 Expression::RTrim(f)
1346 }
1347 Expression::Reverse(mut f) => {
1348 f.this = transform_recursive(f.this, transform_fn)?;
1349 Expression::Reverse(f)
1350 }
1351 Expression::Abs(mut f) => {
1352 f.this = transform_recursive(f.this, transform_fn)?;
1353 Expression::Abs(f)
1354 }
1355 Expression::Ceil(mut f) => {
1356 f.this = transform_recursive(f.this, transform_fn)?;
1357 Expression::Ceil(f)
1358 }
1359 Expression::Floor(mut f) => {
1360 f.this = transform_recursive(f.this, transform_fn)?;
1361 Expression::Floor(f)
1362 }
1363 Expression::Sign(mut f) => {
1364 f.this = transform_recursive(f.this, transform_fn)?;
1365 Expression::Sign(f)
1366 }
1367 Expression::Sqrt(mut f) => {
1368 f.this = transform_recursive(f.this, transform_fn)?;
1369 Expression::Sqrt(f)
1370 }
1371 Expression::Cbrt(mut f) => {
1372 f.this = transform_recursive(f.this, transform_fn)?;
1373 Expression::Cbrt(f)
1374 }
1375 Expression::Ln(mut f) => {
1376 f.this = transform_recursive(f.this, transform_fn)?;
1377 Expression::Ln(f)
1378 }
1379 Expression::Log(mut f) => {
1380 f.this = transform_recursive(f.this, transform_fn)?;
1381 if let Some(base) = f.base {
1382 f.base = Some(transform_recursive(base, transform_fn)?);
1383 }
1384 Expression::Log(f)
1385 }
1386 Expression::Exp(mut f) => {
1387 f.this = transform_recursive(f.this, transform_fn)?;
1388 Expression::Exp(f)
1389 }
1390 Expression::Date(mut f) => {
1391 f.this = transform_recursive(f.this, transform_fn)?;
1392 Expression::Date(f)
1393 }
1394 Expression::Stddev(f) => recurse_agg!(Stddev, f),
1395 Expression::StddevSamp(f) => recurse_agg!(StddevSamp, f),
1396 Expression::Variance(f) => recurse_agg!(Variance, f),
1397
1398 Expression::ModFunc(mut f) => {
1400 f.this = transform_recursive(f.this, transform_fn)?;
1401 f.expression = transform_recursive(f.expression, transform_fn)?;
1402 Expression::ModFunc(f)
1403 }
1404 Expression::Power(mut f) => {
1405 f.this = transform_recursive(f.this, transform_fn)?;
1406 f.expression = transform_recursive(f.expression, transform_fn)?;
1407 Expression::Power(f)
1408 }
1409 Expression::MapFromArrays(mut f) => {
1410 f.this = transform_recursive(f.this, transform_fn)?;
1411 f.expression = transform_recursive(f.expression, transform_fn)?;
1412 Expression::MapFromArrays(f)
1413 }
1414 Expression::ElementAt(mut f) => {
1415 f.this = transform_recursive(f.this, transform_fn)?;
1416 f.expression = transform_recursive(f.expression, transform_fn)?;
1417 Expression::ElementAt(f)
1418 }
1419 Expression::MapContainsKey(mut f) => {
1420 f.this = transform_recursive(f.this, transform_fn)?;
1421 f.expression = transform_recursive(f.expression, transform_fn)?;
1422 Expression::MapContainsKey(f)
1423 }
1424 Expression::Left(mut f) => {
1425 f.this = transform_recursive(f.this, transform_fn)?;
1426 f.length = transform_recursive(f.length, transform_fn)?;
1427 Expression::Left(f)
1428 }
1429 Expression::Right(mut f) => {
1430 f.this = transform_recursive(f.this, transform_fn)?;
1431 f.length = transform_recursive(f.length, transform_fn)?;
1432 Expression::Right(f)
1433 }
1434 Expression::Repeat(mut f) => {
1435 f.this = transform_recursive(f.this, transform_fn)?;
1436 f.times = transform_recursive(f.times, transform_fn)?;
1437 Expression::Repeat(f)
1438 }
1439
1440 Expression::Substring(mut f) => {
1442 f.this = transform_recursive(f.this, transform_fn)?;
1443 f.start = transform_recursive(f.start, transform_fn)?;
1444 if let Some(len) = f.length {
1445 f.length = Some(transform_recursive(len, transform_fn)?);
1446 }
1447 Expression::Substring(f)
1448 }
1449 Expression::Replace(mut f) => {
1450 f.this = transform_recursive(f.this, transform_fn)?;
1451 f.old = transform_recursive(f.old, transform_fn)?;
1452 f.new = transform_recursive(f.new, transform_fn)?;
1453 Expression::Replace(f)
1454 }
1455 Expression::ConcatWs(mut f) => {
1456 f.separator = transform_recursive(f.separator, transform_fn)?;
1457 f.expressions = f
1458 .expressions
1459 .into_iter()
1460 .map(|e| transform_recursive(e, transform_fn))
1461 .collect::<Result<Vec<_>>>()?;
1462 Expression::ConcatWs(f)
1463 }
1464 Expression::Trim(mut f) => {
1465 f.this = transform_recursive(f.this, transform_fn)?;
1466 if let Some(chars) = f.characters {
1467 f.characters = Some(transform_recursive(chars, transform_fn)?);
1468 }
1469 Expression::Trim(f)
1470 }
1471 Expression::Split(mut f) => {
1472 f.this = transform_recursive(f.this, transform_fn)?;
1473 f.delimiter = transform_recursive(f.delimiter, transform_fn)?;
1474 Expression::Split(f)
1475 }
1476 Expression::Lpad(mut f) => {
1477 f.this = transform_recursive(f.this, transform_fn)?;
1478 f.length = transform_recursive(f.length, transform_fn)?;
1479 if let Some(fill) = f.fill {
1480 f.fill = Some(transform_recursive(fill, transform_fn)?);
1481 }
1482 Expression::Lpad(f)
1483 }
1484 Expression::Rpad(mut f) => {
1485 f.this = transform_recursive(f.this, transform_fn)?;
1486 f.length = transform_recursive(f.length, transform_fn)?;
1487 if let Some(fill) = f.fill {
1488 f.fill = Some(transform_recursive(fill, transform_fn)?);
1489 }
1490 Expression::Rpad(f)
1491 }
1492
1493 Expression::Case(mut c) => {
1495 if let Some(operand) = c.operand {
1496 c.operand = Some(transform_recursive(operand, transform_fn)?);
1497 }
1498 c.whens = c
1499 .whens
1500 .into_iter()
1501 .map(|(cond, then)| {
1502 let new_cond = transform_recursive(cond.clone(), transform_fn).unwrap_or(cond);
1503 let new_then = transform_recursive(then.clone(), transform_fn).unwrap_or(then);
1504 (new_cond, new_then)
1505 })
1506 .collect();
1507 if let Some(else_expr) = c.else_ {
1508 c.else_ = Some(transform_recursive(else_expr, transform_fn)?);
1509 }
1510 Expression::Case(c)
1511 }
1512 Expression::IfFunc(mut f) => {
1513 f.condition = transform_recursive(f.condition, transform_fn)?;
1514 f.true_value = transform_recursive(f.true_value, transform_fn)?;
1515 if let Some(false_val) = f.false_value {
1516 f.false_value = Some(transform_recursive(false_val, transform_fn)?);
1517 }
1518 Expression::IfFunc(f)
1519 }
1520
1521 Expression::DateAdd(mut f) => {
1523 f.this = transform_recursive(f.this, transform_fn)?;
1524 f.interval = transform_recursive(f.interval, transform_fn)?;
1525 Expression::DateAdd(f)
1526 }
1527 Expression::DateSub(mut f) => {
1528 f.this = transform_recursive(f.this, transform_fn)?;
1529 f.interval = transform_recursive(f.interval, transform_fn)?;
1530 Expression::DateSub(f)
1531 }
1532 Expression::DateDiff(mut f) => {
1533 f.this = transform_recursive(f.this, transform_fn)?;
1534 f.expression = transform_recursive(f.expression, transform_fn)?;
1535 Expression::DateDiff(f)
1536 }
1537 Expression::DateTrunc(mut f) => {
1538 f.this = transform_recursive(f.this, transform_fn)?;
1539 Expression::DateTrunc(f)
1540 }
1541 Expression::Extract(mut f) => {
1542 f.this = transform_recursive(f.this, transform_fn)?;
1543 Expression::Extract(f)
1544 }
1545
1546 Expression::JsonObject(mut f) => {
1548 f.pairs = f
1549 .pairs
1550 .into_iter()
1551 .map(|(k, v)| {
1552 let new_k = transform_recursive(k, transform_fn)?;
1553 let new_v = transform_recursive(v, transform_fn)?;
1554 Ok((new_k, new_v))
1555 })
1556 .collect::<Result<Vec<_>>>()?;
1557 Expression::JsonObject(f)
1558 }
1559
1560 Expression::Subquery(mut s) => {
1562 s.this = transform_recursive(s.this, transform_fn)?;
1563 Expression::Subquery(s)
1564 }
1565 Expression::Exists(mut e) => {
1566 e.this = transform_recursive(e.this, transform_fn)?;
1567 Expression::Exists(e)
1568 }
1569 Expression::Describe(mut d) => {
1570 d.target = transform_recursive(d.target, transform_fn)?;
1571 Expression::Describe(d)
1572 }
1573
1574 Expression::Union(mut u) => {
1576 let left = std::mem::replace(&mut u.left, Expression::Null(Null));
1577 u.left = transform_recursive(left, transform_fn)?;
1578 let right = std::mem::replace(&mut u.right, Expression::Null(Null));
1579 u.right = transform_recursive(right, transform_fn)?;
1580 if let Some(mut order) = u.order_by.take() {
1581 order.expressions = order
1582 .expressions
1583 .into_iter()
1584 .map(|o| {
1585 let mut o = o;
1586 let original = o.this.clone();
1587 o.this = transform_recursive(o.this, transform_fn).unwrap_or(original);
1588 match transform_fn(Expression::Ordered(Box::new(o.clone()))) {
1589 Ok(Expression::Ordered(transformed)) => *transformed,
1590 Ok(_) | Err(_) => o,
1591 }
1592 })
1593 .collect();
1594 u.order_by = Some(order);
1595 }
1596 if let Some(mut with) = u.with.take() {
1597 with.ctes = with
1598 .ctes
1599 .into_iter()
1600 .map(|mut cte| {
1601 let original = cte.this.clone();
1602 cte.this = transform_recursive(cte.this, transform_fn).unwrap_or(original);
1603 cte
1604 })
1605 .collect();
1606 u.with = Some(with);
1607 }
1608 Expression::Union(u)
1609 }
1610 Expression::Intersect(mut i) => {
1611 let left = std::mem::replace(&mut i.left, Expression::Null(Null));
1612 i.left = transform_recursive(left, transform_fn)?;
1613 let right = std::mem::replace(&mut i.right, Expression::Null(Null));
1614 i.right = transform_recursive(right, transform_fn)?;
1615 if let Some(mut order) = i.order_by.take() {
1616 order.expressions = order
1617 .expressions
1618 .into_iter()
1619 .map(|o| {
1620 let mut o = o;
1621 let original = o.this.clone();
1622 o.this = transform_recursive(o.this, transform_fn).unwrap_or(original);
1623 match transform_fn(Expression::Ordered(Box::new(o.clone()))) {
1624 Ok(Expression::Ordered(transformed)) => *transformed,
1625 Ok(_) | Err(_) => o,
1626 }
1627 })
1628 .collect();
1629 i.order_by = Some(order);
1630 }
1631 if let Some(mut with) = i.with.take() {
1632 with.ctes = with
1633 .ctes
1634 .into_iter()
1635 .map(|mut cte| {
1636 let original = cte.this.clone();
1637 cte.this = transform_recursive(cte.this, transform_fn).unwrap_or(original);
1638 cte
1639 })
1640 .collect();
1641 i.with = Some(with);
1642 }
1643 Expression::Intersect(i)
1644 }
1645 Expression::Except(mut e) => {
1646 let left = std::mem::replace(&mut e.left, Expression::Null(Null));
1647 e.left = transform_recursive(left, transform_fn)?;
1648 let right = std::mem::replace(&mut e.right, Expression::Null(Null));
1649 e.right = transform_recursive(right, transform_fn)?;
1650 if let Some(mut order) = e.order_by.take() {
1651 order.expressions = order
1652 .expressions
1653 .into_iter()
1654 .map(|o| {
1655 let mut o = o;
1656 let original = o.this.clone();
1657 o.this = transform_recursive(o.this, transform_fn).unwrap_or(original);
1658 match transform_fn(Expression::Ordered(Box::new(o.clone()))) {
1659 Ok(Expression::Ordered(transformed)) => *transformed,
1660 Ok(_) | Err(_) => o,
1661 }
1662 })
1663 .collect();
1664 e.order_by = Some(order);
1665 }
1666 if let Some(mut with) = e.with.take() {
1667 with.ctes = with
1668 .ctes
1669 .into_iter()
1670 .map(|mut cte| {
1671 let original = cte.this.clone();
1672 cte.this = transform_recursive(cte.this, transform_fn).unwrap_or(original);
1673 cte
1674 })
1675 .collect();
1676 e.with = Some(with);
1677 }
1678 Expression::Except(e)
1679 }
1680
1681 Expression::Insert(mut ins) => {
1683 let mut new_values = Vec::new();
1685 for row in ins.values {
1686 let mut new_row = Vec::new();
1687 for e in row {
1688 new_row.push(transform_recursive(e, transform_fn)?);
1689 }
1690 new_values.push(new_row);
1691 }
1692 ins.values = new_values;
1693
1694 if let Some(query) = ins.query {
1696 ins.query = Some(transform_recursive(query, transform_fn)?);
1697 }
1698
1699 let mut new_returning = Vec::new();
1701 for e in ins.returning {
1702 new_returning.push(transform_recursive(e, transform_fn)?);
1703 }
1704 ins.returning = new_returning;
1705
1706 if let Some(on_conflict) = ins.on_conflict {
1708 ins.on_conflict = Some(Box::new(transform_recursive(*on_conflict, transform_fn)?));
1709 }
1710
1711 Expression::Insert(ins)
1712 }
1713 Expression::Update(mut upd) => {
1714 upd.table = transform_table_ref_recursive(upd.table, transform_fn)?;
1715 upd.extra_tables = upd
1716 .extra_tables
1717 .into_iter()
1718 .map(|table| transform_table_ref_recursive(table, transform_fn))
1719 .collect::<Result<Vec<_>>>()?;
1720 upd.table_joins = upd
1721 .table_joins
1722 .into_iter()
1723 .map(|join| transform_join_recursive(join, transform_fn))
1724 .collect::<Result<Vec<_>>>()?;
1725 upd.set = upd
1726 .set
1727 .into_iter()
1728 .map(|(id, val)| {
1729 let new_val = transform_recursive(val.clone(), transform_fn).unwrap_or(val);
1730 (id, new_val)
1731 })
1732 .collect();
1733 if let Some(from_clause) = upd.from_clause.take() {
1734 upd.from_clause = Some(transform_from_recursive(from_clause, transform_fn)?);
1735 }
1736 upd.from_joins = upd
1737 .from_joins
1738 .into_iter()
1739 .map(|join| transform_join_recursive(join, transform_fn))
1740 .collect::<Result<Vec<_>>>()?;
1741 if let Some(mut where_clause) = upd.where_clause.take() {
1742 where_clause.this = transform_recursive(where_clause.this, transform_fn)?;
1743 upd.where_clause = Some(where_clause);
1744 }
1745 upd.returning = upd
1746 .returning
1747 .into_iter()
1748 .map(|expr| transform_recursive(expr, transform_fn))
1749 .collect::<Result<Vec<_>>>()?;
1750 if let Some(output) = upd.output.take() {
1751 upd.output = Some(transform_output_clause_recursive(output, transform_fn)?);
1752 }
1753 if let Some(with) = upd.with.take() {
1754 upd.with = Some(transform_with_recursive(with, transform_fn)?);
1755 }
1756 if let Some(limit) = upd.limit.take() {
1757 upd.limit = Some(transform_recursive(limit, transform_fn)?);
1758 }
1759 if let Some(order_by) = upd.order_by.take() {
1760 upd.order_by = Some(transform_order_by_recursive(order_by, transform_fn)?);
1761 }
1762 Expression::Update(upd)
1763 }
1764 Expression::Delete(mut del) => {
1765 del.table = transform_table_ref_recursive(del.table, transform_fn)?;
1766 del.using = del
1767 .using
1768 .into_iter()
1769 .map(|table| transform_table_ref_recursive(table, transform_fn))
1770 .collect::<Result<Vec<_>>>()?;
1771 if let Some(mut where_clause) = del.where_clause.take() {
1772 where_clause.this = transform_recursive(where_clause.this, transform_fn)?;
1773 del.where_clause = Some(where_clause);
1774 }
1775 if let Some(output) = del.output.take() {
1776 del.output = Some(transform_output_clause_recursive(output, transform_fn)?);
1777 }
1778 if let Some(with) = del.with.take() {
1779 del.with = Some(transform_with_recursive(with, transform_fn)?);
1780 }
1781 if let Some(limit) = del.limit.take() {
1782 del.limit = Some(transform_recursive(limit, transform_fn)?);
1783 }
1784 if let Some(order_by) = del.order_by.take() {
1785 del.order_by = Some(transform_order_by_recursive(order_by, transform_fn)?);
1786 }
1787 del.returning = del
1788 .returning
1789 .into_iter()
1790 .map(|expr| transform_recursive(expr, transform_fn))
1791 .collect::<Result<Vec<_>>>()?;
1792 del.tables = del
1793 .tables
1794 .into_iter()
1795 .map(|table| transform_table_ref_recursive(table, transform_fn))
1796 .collect::<Result<Vec<_>>>()?;
1797 del.joins = del
1798 .joins
1799 .into_iter()
1800 .map(|join| transform_join_recursive(join, transform_fn))
1801 .collect::<Result<Vec<_>>>()?;
1802 Expression::Delete(del)
1803 }
1804
1805 Expression::With(mut w) => {
1807 w.ctes = w
1808 .ctes
1809 .into_iter()
1810 .map(|mut cte| {
1811 let original = cte.this.clone();
1812 cte.this = transform_recursive(cte.this, transform_fn).unwrap_or(original);
1813 cte
1814 })
1815 .collect();
1816 Expression::With(w)
1817 }
1818 Expression::Cte(mut c) => {
1819 c.this = transform_recursive(c.this, transform_fn)?;
1820 Expression::Cte(c)
1821 }
1822
1823 Expression::Ordered(mut o) => {
1825 o.this = transform_recursive(o.this, transform_fn)?;
1826 Expression::Ordered(o)
1827 }
1828
1829 Expression::Neg(mut n) => {
1831 n.this = transform_recursive(n.this, transform_fn)?;
1832 Expression::Neg(n)
1833 }
1834
1835 Expression::Between(mut b) => {
1837 b.this = transform_recursive(b.this, transform_fn)?;
1838 b.low = transform_recursive(b.low, transform_fn)?;
1839 b.high = transform_recursive(b.high, transform_fn)?;
1840 Expression::Between(b)
1841 }
1842 Expression::IsNull(mut i) => {
1843 i.this = transform_recursive(i.this, transform_fn)?;
1844 Expression::IsNull(i)
1845 }
1846 Expression::IsTrue(mut i) => {
1847 i.this = transform_recursive(i.this, transform_fn)?;
1848 Expression::IsTrue(i)
1849 }
1850 Expression::IsFalse(mut i) => {
1851 i.this = transform_recursive(i.this, transform_fn)?;
1852 Expression::IsFalse(i)
1853 }
1854
1855 Expression::Like(mut l) => {
1857 l.left = transform_recursive(l.left, transform_fn)?;
1858 l.right = transform_recursive(l.right, transform_fn)?;
1859 Expression::Like(l)
1860 }
1861 Expression::ILike(mut l) => {
1862 l.left = transform_recursive(l.left, transform_fn)?;
1863 l.right = transform_recursive(l.right, transform_fn)?;
1864 Expression::ILike(l)
1865 }
1866
1867 Expression::Neq(op) => transform_binary!(Neq, *op),
1869 Expression::Lte(op) => transform_binary!(Lte, *op),
1870 Expression::Gte(op) => transform_binary!(Gte, *op),
1871 Expression::Mod(op) => transform_binary!(Mod, *op),
1872 Expression::Concat(op) => transform_binary!(Concat, *op),
1873 Expression::BitwiseAnd(op) => transform_binary!(BitwiseAnd, *op),
1874 Expression::BitwiseOr(op) => transform_binary!(BitwiseOr, *op),
1875 Expression::BitwiseXor(op) => transform_binary!(BitwiseXor, *op),
1876 Expression::Is(op) => transform_binary!(Is, *op),
1877
1878 Expression::TryCast(mut c) => {
1880 c.this = transform_recursive(c.this, transform_fn)?;
1881 c.to = transform_data_type_recursive(c.to, transform_fn)?;
1882 Expression::TryCast(c)
1883 }
1884 Expression::SafeCast(mut c) => {
1885 c.this = transform_recursive(c.this, transform_fn)?;
1886 c.to = transform_data_type_recursive(c.to, transform_fn)?;
1887 Expression::SafeCast(c)
1888 }
1889
1890 Expression::Unnest(mut f) => {
1892 f.this = transform_recursive(f.this, transform_fn)?;
1893 f.expressions = f
1894 .expressions
1895 .into_iter()
1896 .map(|e| transform_recursive(e, transform_fn))
1897 .collect::<Result<Vec<_>>>()?;
1898 Expression::Unnest(f)
1899 }
1900 Expression::Explode(mut f) => {
1901 f.this = transform_recursive(f.this, transform_fn)?;
1902 Expression::Explode(f)
1903 }
1904 Expression::GroupConcat(mut f) => {
1905 f.this = transform_recursive(f.this, transform_fn)?;
1906 Expression::GroupConcat(f)
1907 }
1908 Expression::StringAgg(mut f) => {
1909 f.this = transform_recursive(f.this, transform_fn)?;
1910 if let Some(order_by) = f.order_by.take() {
1911 f.order_by = Some(
1912 order_by
1913 .into_iter()
1914 .map(|mut ordered| {
1915 let original = ordered.this.clone();
1916 ordered.this =
1917 transform_recursive(ordered.this, transform_fn).unwrap_or(original);
1918 match transform_fn(Expression::Ordered(Box::new(ordered.clone()))) {
1919 Ok(Expression::Ordered(transformed)) => Ok(*transformed),
1920 Ok(_) | Err(_) => Ok(ordered),
1921 }
1922 })
1923 .collect::<Result<Vec<_>>>()?,
1924 );
1925 }
1926 Expression::StringAgg(f)
1927 }
1928 Expression::ListAgg(mut f) => {
1929 f.this = transform_recursive(f.this, transform_fn)?;
1930 Expression::ListAgg(f)
1931 }
1932 Expression::ArrayAgg(mut f) => {
1933 f.this = transform_recursive(f.this, transform_fn)?;
1934 Expression::ArrayAgg(f)
1935 }
1936 Expression::ParseJson(mut f) => {
1937 f.this = transform_recursive(f.this, transform_fn)?;
1938 Expression::ParseJson(f)
1939 }
1940 Expression::ToJson(mut f) => {
1941 f.this = transform_recursive(f.this, transform_fn)?;
1942 Expression::ToJson(f)
1943 }
1944 Expression::JSONExtract(mut e) => {
1945 e.this = Box::new(transform_recursive(*e.this, transform_fn)?);
1946 e.expression = Box::new(transform_recursive(*e.expression, transform_fn)?);
1947 Expression::JSONExtract(e)
1948 }
1949 Expression::JSONExtractScalar(mut e) => {
1950 e.this = Box::new(transform_recursive(*e.this, transform_fn)?);
1951 e.expression = Box::new(transform_recursive(*e.expression, transform_fn)?);
1952 Expression::JSONExtractScalar(e)
1953 }
1954
1955 Expression::StrToTime(mut e) => {
1957 e.this = Box::new(transform_recursive(*e.this, transform_fn)?);
1958 Expression::StrToTime(e)
1959 }
1960
1961 Expression::UnixToTime(mut e) => {
1963 e.this = Box::new(transform_recursive(*e.this, transform_fn)?);
1964 Expression::UnixToTime(e)
1965 }
1966
1967 Expression::CreateTable(mut ct) => {
1969 for col in &mut ct.columns {
1970 if let Some(default_expr) = col.default.take() {
1971 col.default = Some(transform_recursive(default_expr, transform_fn)?);
1972 }
1973 if let Some(on_update_expr) = col.on_update.take() {
1974 col.on_update = Some(transform_recursive(on_update_expr, transform_fn)?);
1975 }
1976 }
1981 if let Some(as_select) = ct.as_select.take() {
1982 ct.as_select = Some(transform_recursive(as_select, transform_fn)?);
1983 }
1984 Expression::CreateTable(ct)
1985 }
1986
1987 Expression::CreateView(mut cv) => {
1989 cv.query = transform_recursive(cv.query, transform_fn)?;
1990 Expression::CreateView(cv)
1991 }
1992
1993 Expression::CreateTask(mut ct) => {
1995 ct.body = transform_recursive(ct.body, transform_fn)?;
1996 Expression::CreateTask(ct)
1997 }
1998
1999 Expression::Prepare(mut prepare) => {
2001 prepare.statement = transform_recursive(prepare.statement, transform_fn)?;
2002 Expression::Prepare(prepare)
2003 }
2004
2005 Expression::Execute(mut execute) => {
2007 execute.this = transform_recursive(execute.this, transform_fn)?;
2008 execute.arguments = execute
2009 .arguments
2010 .into_iter()
2011 .map(|argument| transform_recursive(argument, transform_fn))
2012 .collect::<Result<Vec<_>>>()?;
2013 execute.parameters = execute
2014 .parameters
2015 .into_iter()
2016 .map(|mut parameter| {
2017 parameter.value = transform_recursive(parameter.value, transform_fn)?;
2018 Ok(parameter)
2019 })
2020 .collect::<Result<Vec<_>>>()?;
2021 Expression::Execute(execute)
2022 }
2023
2024 Expression::CreateProcedure(mut cp) => {
2026 if let Some(body) = cp.body.take() {
2027 cp.body = Some(match body {
2028 FunctionBody::Expression(expr) => {
2029 FunctionBody::Expression(transform_recursive(expr, transform_fn)?)
2030 }
2031 FunctionBody::Return(expr) => {
2032 FunctionBody::Return(transform_recursive(expr, transform_fn)?)
2033 }
2034 FunctionBody::Statements(stmts) => {
2035 let transformed_stmts = stmts
2036 .into_iter()
2037 .map(|s| transform_recursive(s, transform_fn))
2038 .collect::<Result<Vec<_>>>()?;
2039 FunctionBody::Statements(transformed_stmts)
2040 }
2041 other => other,
2042 });
2043 }
2044 Expression::CreateProcedure(cp)
2045 }
2046
2047 Expression::CreateFunction(mut cf) => {
2049 if let Some(body) = cf.body.take() {
2050 cf.body = Some(match body {
2051 FunctionBody::Expression(expr) => {
2052 FunctionBody::Expression(transform_recursive(expr, transform_fn)?)
2053 }
2054 FunctionBody::Return(expr) => {
2055 FunctionBody::Return(transform_recursive(expr, transform_fn)?)
2056 }
2057 FunctionBody::Statements(stmts) => {
2058 let transformed_stmts = stmts
2059 .into_iter()
2060 .map(|s| transform_recursive(s, transform_fn))
2061 .collect::<Result<Vec<_>>>()?;
2062 FunctionBody::Statements(transformed_stmts)
2063 }
2064 other => other,
2065 });
2066 }
2067 Expression::CreateFunction(cf)
2068 }
2069
2070 Expression::MemberOf(op) => transform_binary!(MemberOf, *op),
2072 Expression::ArrayContainsAll(op) => transform_binary!(ArrayContainsAll, *op),
2074 Expression::ArrayContainedBy(op) => transform_binary!(ArrayContainedBy, *op),
2076 Expression::ArrayOverlaps(op) => transform_binary!(ArrayOverlaps, *op),
2078 Expression::TsMatch(op) => transform_binary!(TsMatch, *op),
2080 Expression::Adjacent(op) => transform_binary!(Adjacent, *op),
2082
2083 Expression::Table(mut t) => {
2085 if let Some(when) = t.when.take() {
2086 let transformed =
2087 transform_recursive(Expression::HistoricalData(when), transform_fn)?;
2088 if let Expression::HistoricalData(hd) = transformed {
2089 t.when = Some(hd);
2090 }
2091 }
2092 if let Some(changes) = t.changes.take() {
2093 let transformed = transform_recursive(Expression::Changes(changes), transform_fn)?;
2094 if let Expression::Changes(c) = transformed {
2095 t.changes = Some(c);
2096 }
2097 }
2098 Expression::Table(t)
2099 }
2100
2101 Expression::HistoricalData(mut hd) => {
2103 *hd.expression = transform_recursive(*hd.expression, transform_fn)?;
2104 Expression::HistoricalData(hd)
2105 }
2106
2107 Expression::Changes(mut c) => {
2109 if let Some(at_before) = c.at_before.take() {
2110 c.at_before = Some(Box::new(transform_recursive(*at_before, transform_fn)?));
2111 }
2112 if let Some(end) = c.end.take() {
2113 c.end = Some(Box::new(transform_recursive(*end, transform_fn)?));
2114 }
2115 Expression::Changes(c)
2116 }
2117
2118 Expression::TableArgument(mut ta) => {
2120 ta.this = transform_recursive(ta.this, transform_fn)?;
2121 Expression::TableArgument(ta)
2122 }
2123
2124 Expression::JoinedTable(mut jt) => {
2126 jt.left = transform_recursive(jt.left, transform_fn)?;
2127 jt.joins = jt
2128 .joins
2129 .into_iter()
2130 .map(|mut join| {
2131 join.this = transform_recursive(join.this, transform_fn)?;
2132 if let Some(on) = join.on.take() {
2133 join.on = Some(transform_recursive(on, transform_fn)?);
2134 }
2135 match transform_fn(Expression::Join(Box::new(join)))? {
2136 Expression::Join(j) => Ok(*j),
2137 _ => Err(crate::error::Error::parse(
2138 "Join transformation returned non-join expression",
2139 0,
2140 0,
2141 0,
2142 0,
2143 )),
2144 }
2145 })
2146 .collect::<Result<Vec<_>>>()?;
2147 jt.lateral_views = jt
2148 .lateral_views
2149 .into_iter()
2150 .map(|mut lv| {
2151 lv.this = transform_recursive(lv.this, transform_fn)?;
2152 Ok(lv)
2153 })
2154 .collect::<Result<Vec<_>>>()?;
2155 Expression::JoinedTable(jt)
2156 }
2157
2158 Expression::Lateral(mut lat) => {
2160 *lat.this = transform_recursive(*lat.this, transform_fn)?;
2161 Expression::Lateral(lat)
2162 }
2163
2164 Expression::WithinGroup(mut wg) => {
2168 wg.order_by = wg
2169 .order_by
2170 .into_iter()
2171 .map(|mut o| {
2172 let original = o.this.clone();
2173 o.this = transform_recursive(o.this, transform_fn).unwrap_or(original);
2174 match transform_fn(Expression::Ordered(Box::new(o.clone()))) {
2175 Ok(Expression::Ordered(transformed)) => *transformed,
2176 Ok(_) | Err(_) => o,
2177 }
2178 })
2179 .collect();
2180 Expression::WithinGroup(wg)
2181 }
2182
2183 Expression::Filter(mut f) => {
2185 f.this = Box::new(transform_recursive(*f.this, transform_fn)?);
2186 f.expression = Box::new(transform_recursive(*f.expression, transform_fn)?);
2187 Expression::Filter(f)
2188 }
2189
2190 Expression::Sum(f) => recurse_agg!(Sum, f),
2194 Expression::Avg(f) => recurse_agg!(Avg, f),
2195 Expression::Min(f) => recurse_agg!(Min, f),
2196 Expression::Max(f) => recurse_agg!(Max, f),
2197 Expression::CountIf(f) => recurse_agg!(CountIf, f),
2198 Expression::StddevPop(f) => recurse_agg!(StddevPop, f),
2199 Expression::VarPop(f) => recurse_agg!(VarPop, f),
2200 Expression::VarSamp(f) => recurse_agg!(VarSamp, f),
2201 Expression::Median(f) => recurse_agg!(Median, f),
2202 Expression::Mode(f) => recurse_agg!(Mode, f),
2203 Expression::First(f) => recurse_agg!(First, f),
2204 Expression::Last(f) => recurse_agg!(Last, f),
2205 Expression::AnyValue(f) => recurse_agg!(AnyValue, f),
2206 Expression::ApproxDistinct(f) => recurse_agg!(ApproxDistinct, f),
2207 Expression::ApproxCountDistinct(f) => recurse_agg!(ApproxCountDistinct, f),
2208 Expression::LogicalAnd(f) => recurse_agg!(LogicalAnd, f),
2209 Expression::LogicalOr(f) => recurse_agg!(LogicalOr, f),
2210 Expression::Skewness(f) => recurse_agg!(Skewness, f),
2211 Expression::ArrayConcatAgg(f) => recurse_agg!(ArrayConcatAgg, f),
2212 Expression::ArrayUniqueAgg(f) => recurse_agg!(ArrayUniqueAgg, f),
2213 Expression::BoolXorAgg(f) => recurse_agg!(BoolXorAgg, f),
2214 Expression::BitwiseOrAgg(f) => recurse_agg!(BitwiseOrAgg, f),
2215 Expression::BitwiseAndAgg(f) => recurse_agg!(BitwiseAndAgg, f),
2216 Expression::BitwiseXorAgg(f) => recurse_agg!(BitwiseXorAgg, f),
2217
2218 Expression::Count(mut c) => {
2220 if let Some(this) = c.this.take() {
2221 c.this = Some(transform_recursive(this, transform_fn)?);
2222 }
2223 if let Some(filter) = c.filter.take() {
2224 c.filter = Some(transform_recursive(filter, transform_fn)?);
2225 }
2226 Expression::Count(c)
2227 }
2228
2229 Expression::PipeOperator(mut pipe) => {
2230 pipe.this = transform_recursive(pipe.this, transform_fn)?;
2231 pipe.expression = transform_recursive(pipe.expression, transform_fn)?;
2232 Expression::PipeOperator(pipe)
2233 }
2234
2235 Expression::ArrayExcept(mut f) => {
2237 f.this = transform_recursive(f.this, transform_fn)?;
2238 f.expression = transform_recursive(f.expression, transform_fn)?;
2239 Expression::ArrayExcept(f)
2240 }
2241 Expression::ArrayContains(mut f) => {
2242 f.this = transform_recursive(f.this, transform_fn)?;
2243 f.expression = transform_recursive(f.expression, transform_fn)?;
2244 Expression::ArrayContains(f)
2245 }
2246 Expression::ArrayDistinct(mut f) => {
2247 f.this = transform_recursive(f.this, transform_fn)?;
2248 Expression::ArrayDistinct(f)
2249 }
2250 Expression::ArrayPosition(mut f) => {
2251 f.this = transform_recursive(f.this, transform_fn)?;
2252 f.expression = transform_recursive(f.expression, transform_fn)?;
2253 Expression::ArrayPosition(f)
2254 }
2255
2256 other => other,
2258 };
2259
2260 transform_fn(expr)
2262}
2263
2264struct CachedDialectConfig {
2274 tokenizer_config: Arc<TokenizerConfig>,
2275 #[cfg(feature = "generate")]
2276 generator_config: Arc<GeneratorConfig>,
2277}
2278
2279struct DialectConfigs {
2280 tokenizer_config: Arc<TokenizerConfig>,
2281 #[cfg(feature = "generate")]
2282 generator_config: Arc<GeneratorConfig>,
2283 #[cfg(feature = "transpile")]
2284 transformer: Box<dyn Fn(Expression) -> Result<Expression> + Send + Sync>,
2285}
2286
2287macro_rules! cached_dialect {
2289 ($static_name:ident, $dialect_struct:expr, $feature:literal) => {
2290 #[cfg(feature = $feature)]
2291 static $static_name: LazyLock<CachedDialectConfig> = LazyLock::new(|| {
2292 let d = $dialect_struct;
2293 CachedDialectConfig {
2294 tokenizer_config: Arc::new(d.tokenizer_config()),
2295 #[cfg(feature = "generate")]
2296 generator_config: Arc::new(d.generator_config()),
2297 }
2298 });
2299 };
2300}
2301
2302static CACHED_GENERIC: LazyLock<CachedDialectConfig> = LazyLock::new(|| {
2303 let d = GenericDialect;
2304 CachedDialectConfig {
2305 tokenizer_config: Arc::new(d.tokenizer_config()),
2306 #[cfg(feature = "generate")]
2307 generator_config: Arc::new(d.generator_config()),
2308 }
2309});
2310
2311cached_dialect!(CACHED_POSTGRESQL, PostgresDialect, "dialect-postgresql");
2312cached_dialect!(CACHED_MYSQL, MySQLDialect, "dialect-mysql");
2313cached_dialect!(CACHED_BIGQUERY, BigQueryDialect, "dialect-bigquery");
2314cached_dialect!(CACHED_SNOWFLAKE, SnowflakeDialect, "dialect-snowflake");
2315cached_dialect!(CACHED_DUCKDB, DuckDBDialect, "dialect-duckdb");
2316cached_dialect!(CACHED_TSQL, TSQLDialect, "dialect-tsql");
2317cached_dialect!(CACHED_ORACLE, OracleDialect, "dialect-oracle");
2318cached_dialect!(CACHED_HIVE, HiveDialect, "dialect-hive");
2319cached_dialect!(CACHED_SPARK, SparkDialect, "dialect-spark");
2320cached_dialect!(CACHED_SQLITE, SQLiteDialect, "dialect-sqlite");
2321cached_dialect!(CACHED_PRESTO, PrestoDialect, "dialect-presto");
2322cached_dialect!(CACHED_TRINO, TrinoDialect, "dialect-trino");
2323cached_dialect!(CACHED_REDSHIFT, RedshiftDialect, "dialect-redshift");
2324cached_dialect!(CACHED_CLICKHOUSE, ClickHouseDialect, "dialect-clickhouse");
2325cached_dialect!(CACHED_DATABRICKS, DatabricksDialect, "dialect-databricks");
2326cached_dialect!(CACHED_ATHENA, AthenaDialect, "dialect-athena");
2327cached_dialect!(CACHED_TERADATA, TeradataDialect, "dialect-teradata");
2328cached_dialect!(CACHED_DORIS, DorisDialect, "dialect-doris");
2329cached_dialect!(CACHED_STARROCKS, StarRocksDialect, "dialect-starrocks");
2330cached_dialect!(
2331 CACHED_MATERIALIZE,
2332 MaterializeDialect,
2333 "dialect-materialize"
2334);
2335cached_dialect!(CACHED_RISINGWAVE, RisingWaveDialect, "dialect-risingwave");
2336cached_dialect!(
2337 CACHED_SINGLESTORE,
2338 SingleStoreDialect,
2339 "dialect-singlestore"
2340);
2341cached_dialect!(
2342 CACHED_COCKROACHDB,
2343 CockroachDBDialect,
2344 "dialect-cockroachdb"
2345);
2346cached_dialect!(CACHED_TIDB, TiDBDialect, "dialect-tidb");
2347cached_dialect!(CACHED_DRUID, DruidDialect, "dialect-druid");
2348cached_dialect!(CACHED_SOLR, SolrDialect, "dialect-solr");
2349cached_dialect!(CACHED_TABLEAU, TableauDialect, "dialect-tableau");
2350cached_dialect!(CACHED_DUNE, DuneDialect, "dialect-dune");
2351cached_dialect!(CACHED_FABRIC, FabricDialect, "dialect-fabric");
2352cached_dialect!(CACHED_DRILL, DrillDialect, "dialect-drill");
2353cached_dialect!(CACHED_DREMIO, DremioDialect, "dialect-dremio");
2354cached_dialect!(CACHED_EXASOL, ExasolDialect, "dialect-exasol");
2355cached_dialect!(CACHED_DATAFUSION, DataFusionDialect, "dialect-datafusion");
2356
2357fn configs_for_dialect_type(dt: DialectType) -> DialectConfigs {
2358 macro_rules! from_cache {
2360 ($cache:expr, $dialect_struct:expr) => {{
2361 let c = &*$cache;
2362 DialectConfigs {
2363 tokenizer_config: c.tokenizer_config.clone(),
2364 #[cfg(feature = "generate")]
2365 generator_config: c.generator_config.clone(),
2366 #[cfg(feature = "transpile")]
2367 transformer: Box::new(move |e| $dialect_struct.transform_expr(e)),
2368 }
2369 }};
2370 }
2371 match dt {
2372 #[cfg(feature = "dialect-postgresql")]
2373 DialectType::PostgreSQL => from_cache!(CACHED_POSTGRESQL, PostgresDialect),
2374 #[cfg(feature = "dialect-mysql")]
2375 DialectType::MySQL => from_cache!(CACHED_MYSQL, MySQLDialect),
2376 #[cfg(feature = "dialect-bigquery")]
2377 DialectType::BigQuery => from_cache!(CACHED_BIGQUERY, BigQueryDialect),
2378 #[cfg(feature = "dialect-snowflake")]
2379 DialectType::Snowflake => from_cache!(CACHED_SNOWFLAKE, SnowflakeDialect),
2380 #[cfg(feature = "dialect-duckdb")]
2381 DialectType::DuckDB => from_cache!(CACHED_DUCKDB, DuckDBDialect),
2382 #[cfg(feature = "dialect-tsql")]
2383 DialectType::TSQL => from_cache!(CACHED_TSQL, TSQLDialect),
2384 #[cfg(feature = "dialect-oracle")]
2385 DialectType::Oracle => from_cache!(CACHED_ORACLE, OracleDialect),
2386 #[cfg(feature = "dialect-hive")]
2387 DialectType::Hive => from_cache!(CACHED_HIVE, HiveDialect),
2388 #[cfg(feature = "dialect-spark")]
2389 DialectType::Spark => from_cache!(CACHED_SPARK, SparkDialect),
2390 #[cfg(feature = "dialect-sqlite")]
2391 DialectType::SQLite => from_cache!(CACHED_SQLITE, SQLiteDialect),
2392 #[cfg(feature = "dialect-presto")]
2393 DialectType::Presto => from_cache!(CACHED_PRESTO, PrestoDialect),
2394 #[cfg(feature = "dialect-trino")]
2395 DialectType::Trino => from_cache!(CACHED_TRINO, TrinoDialect),
2396 #[cfg(feature = "dialect-redshift")]
2397 DialectType::Redshift => from_cache!(CACHED_REDSHIFT, RedshiftDialect),
2398 #[cfg(feature = "dialect-clickhouse")]
2399 DialectType::ClickHouse => from_cache!(CACHED_CLICKHOUSE, ClickHouseDialect),
2400 #[cfg(feature = "dialect-databricks")]
2401 DialectType::Databricks => from_cache!(CACHED_DATABRICKS, DatabricksDialect),
2402 #[cfg(feature = "dialect-athena")]
2403 DialectType::Athena => from_cache!(CACHED_ATHENA, AthenaDialect),
2404 #[cfg(feature = "dialect-teradata")]
2405 DialectType::Teradata => from_cache!(CACHED_TERADATA, TeradataDialect),
2406 #[cfg(feature = "dialect-doris")]
2407 DialectType::Doris => from_cache!(CACHED_DORIS, DorisDialect),
2408 #[cfg(feature = "dialect-starrocks")]
2409 DialectType::StarRocks => from_cache!(CACHED_STARROCKS, StarRocksDialect),
2410 #[cfg(feature = "dialect-materialize")]
2411 DialectType::Materialize => from_cache!(CACHED_MATERIALIZE, MaterializeDialect),
2412 #[cfg(feature = "dialect-risingwave")]
2413 DialectType::RisingWave => from_cache!(CACHED_RISINGWAVE, RisingWaveDialect),
2414 #[cfg(feature = "dialect-singlestore")]
2415 DialectType::SingleStore => from_cache!(CACHED_SINGLESTORE, SingleStoreDialect),
2416 #[cfg(feature = "dialect-cockroachdb")]
2417 DialectType::CockroachDB => from_cache!(CACHED_COCKROACHDB, CockroachDBDialect),
2418 #[cfg(feature = "dialect-tidb")]
2419 DialectType::TiDB => from_cache!(CACHED_TIDB, TiDBDialect),
2420 #[cfg(feature = "dialect-druid")]
2421 DialectType::Druid => from_cache!(CACHED_DRUID, DruidDialect),
2422 #[cfg(feature = "dialect-solr")]
2423 DialectType::Solr => from_cache!(CACHED_SOLR, SolrDialect),
2424 #[cfg(feature = "dialect-tableau")]
2425 DialectType::Tableau => from_cache!(CACHED_TABLEAU, TableauDialect),
2426 #[cfg(feature = "dialect-dune")]
2427 DialectType::Dune => from_cache!(CACHED_DUNE, DuneDialect),
2428 #[cfg(feature = "dialect-fabric")]
2429 DialectType::Fabric => from_cache!(CACHED_FABRIC, FabricDialect),
2430 #[cfg(feature = "dialect-drill")]
2431 DialectType::Drill => from_cache!(CACHED_DRILL, DrillDialect),
2432 #[cfg(feature = "dialect-dremio")]
2433 DialectType::Dremio => from_cache!(CACHED_DREMIO, DremioDialect),
2434 #[cfg(feature = "dialect-exasol")]
2435 DialectType::Exasol => from_cache!(CACHED_EXASOL, ExasolDialect),
2436 #[cfg(feature = "dialect-datafusion")]
2437 DialectType::DataFusion => from_cache!(CACHED_DATAFUSION, DataFusionDialect),
2438 _ => from_cache!(CACHED_GENERIC, GenericDialect),
2439 }
2440}
2441
2442static CUSTOM_DIALECT_REGISTRY: LazyLock<RwLock<HashMap<String, Arc<CustomDialectConfig>>>> =
2447 LazyLock::new(|| RwLock::new(HashMap::new()));
2448
2449struct CustomDialectConfig {
2450 name: String,
2451 base_dialect: DialectType,
2452 tokenizer_config: Arc<TokenizerConfig>,
2453 #[cfg(feature = "generate")]
2454 generator_config: GeneratorConfig,
2455 #[cfg(feature = "transpile")]
2456 transform: Option<Arc<dyn Fn(Expression) -> Result<Expression> + Send + Sync>>,
2457 #[cfg(feature = "transpile")]
2458 preprocess: Option<Arc<dyn Fn(Expression) -> Result<Expression> + Send + Sync>>,
2459}
2460
2461pub struct CustomDialectBuilder {
2489 name: String,
2490 base_dialect: DialectType,
2491 tokenizer_modifier: Option<Box<dyn FnOnce(&mut TokenizerConfig)>>,
2492 #[cfg(feature = "generate")]
2493 generator_modifier: Option<Box<dyn FnOnce(&mut GeneratorConfig)>>,
2494 #[cfg(feature = "transpile")]
2495 transform: Option<Arc<dyn Fn(Expression) -> Result<Expression> + Send + Sync>>,
2496 #[cfg(feature = "transpile")]
2497 preprocess: Option<Arc<dyn Fn(Expression) -> Result<Expression> + Send + Sync>>,
2498}
2499
2500impl CustomDialectBuilder {
2501 pub fn new(name: impl Into<String>) -> Self {
2503 Self {
2504 name: name.into(),
2505 base_dialect: DialectType::Generic,
2506 tokenizer_modifier: None,
2507 #[cfg(feature = "generate")]
2508 generator_modifier: None,
2509 #[cfg(feature = "transpile")]
2510 transform: None,
2511 #[cfg(feature = "transpile")]
2512 preprocess: None,
2513 }
2514 }
2515
2516 pub fn based_on(mut self, dialect: DialectType) -> Self {
2518 self.base_dialect = dialect;
2519 self
2520 }
2521
2522 pub fn tokenizer_config_modifier<F>(mut self, f: F) -> Self
2524 where
2525 F: FnOnce(&mut TokenizerConfig) + 'static,
2526 {
2527 self.tokenizer_modifier = Some(Box::new(f));
2528 self
2529 }
2530
2531 #[cfg(feature = "generate")]
2533 pub fn generator_config_modifier<F>(mut self, f: F) -> Self
2534 where
2535 F: FnOnce(&mut GeneratorConfig) + 'static,
2536 {
2537 self.generator_modifier = Some(Box::new(f));
2538 self
2539 }
2540
2541 #[cfg(feature = "transpile")]
2546 pub fn transform_fn<F>(mut self, f: F) -> Self
2547 where
2548 F: Fn(Expression) -> Result<Expression> + Send + Sync + 'static,
2549 {
2550 self.transform = Some(Arc::new(f));
2551 self
2552 }
2553
2554 #[cfg(feature = "transpile")]
2559 pub fn preprocess_fn<F>(mut self, f: F) -> Self
2560 where
2561 F: Fn(Expression) -> Result<Expression> + Send + Sync + 'static,
2562 {
2563 self.preprocess = Some(Arc::new(f));
2564 self
2565 }
2566
2567 pub fn register(self) -> Result<()> {
2573 if DialectType::from_str(&self.name).is_ok() {
2575 return Err(crate::error::Error::parse(
2576 format!(
2577 "Cannot register custom dialect '{}': name collides with built-in dialect",
2578 self.name
2579 ),
2580 0,
2581 0,
2582 0,
2583 0,
2584 ));
2585 }
2586
2587 let base_configs = configs_for_dialect_type(self.base_dialect);
2589 let mut tok_config = (*base_configs.tokenizer_config).clone();
2590 #[cfg(feature = "generate")]
2591 let mut gen_config = (*base_configs.generator_config).clone();
2592
2593 if let Some(tok_mod) = self.tokenizer_modifier {
2595 tok_mod(&mut tok_config);
2596 }
2597 #[cfg(feature = "generate")]
2598 if let Some(gen_mod) = self.generator_modifier {
2599 gen_mod(&mut gen_config);
2600 }
2601
2602 let config = CustomDialectConfig {
2603 name: self.name.clone(),
2604 base_dialect: self.base_dialect,
2605 tokenizer_config: Arc::new(tok_config),
2606 #[cfg(feature = "generate")]
2607 generator_config: gen_config,
2608 #[cfg(feature = "transpile")]
2609 transform: self.transform,
2610 #[cfg(feature = "transpile")]
2611 preprocess: self.preprocess,
2612 };
2613
2614 register_custom_dialect(config)
2615 }
2616}
2617
2618use std::str::FromStr;
2619
2620fn register_custom_dialect(config: CustomDialectConfig) -> Result<()> {
2621 let mut registry = CUSTOM_DIALECT_REGISTRY.write().map_err(|e| {
2622 crate::error::Error::parse(format!("Registry lock poisoned: {}", e), 0, 0, 0, 0)
2623 })?;
2624
2625 if registry.contains_key(&config.name) {
2626 return Err(crate::error::Error::parse(
2627 format!("Custom dialect '{}' is already registered", config.name),
2628 0,
2629 0,
2630 0,
2631 0,
2632 ));
2633 }
2634
2635 registry.insert(config.name.clone(), Arc::new(config));
2636 Ok(())
2637}
2638
2639pub fn unregister_custom_dialect(name: &str) -> bool {
2644 if let Ok(mut registry) = CUSTOM_DIALECT_REGISTRY.write() {
2645 registry.remove(name).is_some()
2646 } else {
2647 false
2648 }
2649}
2650
2651fn get_custom_dialect_config(name: &str) -> Option<Arc<CustomDialectConfig>> {
2652 CUSTOM_DIALECT_REGISTRY
2653 .read()
2654 .ok()
2655 .and_then(|registry| registry.get(name).cloned())
2656}
2657
2658pub struct Dialect {
2681 dialect_type: DialectType,
2682 tokenizer: Tokenizer,
2683 #[cfg(feature = "generate")]
2684 generator_config: Arc<GeneratorConfig>,
2685 #[cfg(feature = "transpile")]
2686 transformer: Box<dyn Fn(Expression) -> Result<Expression> + Send + Sync>,
2687 #[cfg(feature = "generate")]
2689 generator_config_for_expr: Option<Box<dyn Fn(&Expression) -> GeneratorConfig + Send + Sync>>,
2690 #[cfg(feature = "transpile")]
2692 custom_preprocess: Option<Box<dyn Fn(Expression) -> Result<Expression> + Send + Sync>>,
2693}
2694
2695#[cfg(feature = "transpile")]
2704#[derive(Debug, Clone, Serialize, Deserialize)]
2705#[serde(rename_all = "camelCase", default)]
2706#[non_exhaustive]
2707pub struct TranspileOptions {
2708 pub pretty: bool,
2710 pub unsupported_level: UnsupportedLevel,
2715 pub max_unsupported: usize,
2717 pub complexity_guard: ComplexityGuardOptions,
2719}
2720
2721#[cfg(feature = "transpile")]
2722impl Default for TranspileOptions {
2723 fn default() -> Self {
2724 Self {
2725 pretty: false,
2726 unsupported_level: UnsupportedLevel::Warn,
2727 max_unsupported: 3,
2728 complexity_guard: ComplexityGuardOptions::default(),
2729 }
2730 }
2731}
2732
2733#[cfg(feature = "transpile")]
2734impl TranspileOptions {
2735 pub fn pretty() -> Self {
2737 Self {
2738 pretty: true,
2739 ..Default::default()
2740 }
2741 }
2742
2743 pub fn strict() -> Self {
2745 Self {
2746 unsupported_level: UnsupportedLevel::Raise,
2747 ..Default::default()
2748 }
2749 }
2750
2751 pub fn with_unsupported_level(mut self, level: UnsupportedLevel) -> Self {
2753 self.unsupported_level = level;
2754 self
2755 }
2756
2757 pub fn with_max_unsupported(mut self, max: usize) -> Self {
2759 self.max_unsupported = max;
2760 self
2761 }
2762
2763 pub fn with_complexity_guard(mut self, guard: ComplexityGuardOptions) -> Self {
2765 self.complexity_guard = guard;
2766 self
2767 }
2768}
2769
2770#[cfg(feature = "transpile")]
2777pub trait TranspileTarget {
2778 fn with_dialect<R>(self, f: impl FnOnce(&Dialect) -> R) -> R;
2780}
2781
2782#[cfg(feature = "transpile")]
2783impl TranspileTarget for DialectType {
2784 fn with_dialect<R>(self, f: impl FnOnce(&Dialect) -> R) -> R {
2785 f(&Dialect::get(self))
2786 }
2787}
2788
2789#[cfg(feature = "transpile")]
2790impl TranspileTarget for &Dialect {
2791 fn with_dialect<R>(self, f: impl FnOnce(&Dialect) -> R) -> R {
2792 f(self)
2793 }
2794}
2795
2796impl Dialect {
2797 pub fn get(dialect_type: DialectType) -> Self {
2804 let configs = configs_for_dialect_type(dialect_type);
2805 let tokenizer_config = configs.tokenizer_config;
2806 #[cfg(feature = "generate")]
2807 let generator_config = configs.generator_config;
2808 #[cfg(feature = "transpile")]
2809 let transformer = configs.transformer;
2810
2811 #[cfg(feature = "generate")]
2813 let generator_config_for_expr: Option<
2814 Box<dyn Fn(&Expression) -> GeneratorConfig + Send + Sync>,
2815 > = match dialect_type {
2816 #[cfg(feature = "dialect-athena")]
2817 DialectType::Athena => Some(Box::new(|expr| {
2818 AthenaDialect.generator_config_for_expr(expr)
2819 })),
2820 _ => None,
2821 };
2822
2823 Self {
2824 dialect_type,
2825 tokenizer: Tokenizer::from_shared_config(tokenizer_config),
2826 #[cfg(feature = "generate")]
2827 generator_config,
2828 #[cfg(feature = "transpile")]
2829 transformer,
2830 #[cfg(feature = "generate")]
2831 generator_config_for_expr,
2832 #[cfg(feature = "transpile")]
2833 custom_preprocess: None,
2834 }
2835 }
2836
2837 pub fn get_by_name(name: &str) -> Option<Self> {
2843 if let Ok(dt) = DialectType::from_str(name) {
2845 return Some(Self::get(dt));
2846 }
2847
2848 let config = get_custom_dialect_config(name)?;
2850 Some(Self::from_custom_config(&config))
2851 }
2852
2853 fn from_custom_config(config: &CustomDialectConfig) -> Self {
2855 #[cfg(feature = "transpile")]
2857 let transformer: Box<dyn Fn(Expression) -> Result<Expression> + Send + Sync> =
2858 if let Some(ref custom_transform) = config.transform {
2859 let t = Arc::clone(custom_transform);
2860 Box::new(move |e| t(e))
2861 } else {
2862 configs_for_dialect_type(config.base_dialect).transformer
2863 };
2864
2865 #[cfg(feature = "transpile")]
2867 let custom_preprocess: Option<
2868 Box<dyn Fn(Expression) -> Result<Expression> + Send + Sync>,
2869 > = config.preprocess.as_ref().map(|p| {
2870 let p = Arc::clone(p);
2871 Box::new(move |e: Expression| p(e))
2872 as Box<dyn Fn(Expression) -> Result<Expression> + Send + Sync>
2873 });
2874
2875 Self {
2876 dialect_type: config.base_dialect,
2877 tokenizer: Tokenizer::from_shared_config(config.tokenizer_config.clone()),
2878 #[cfg(feature = "generate")]
2879 generator_config: Arc::new(config.generator_config.clone()),
2880 #[cfg(feature = "transpile")]
2881 transformer,
2882 #[cfg(feature = "generate")]
2883 generator_config_for_expr: None,
2884 #[cfg(feature = "transpile")]
2885 custom_preprocess,
2886 }
2887 }
2888
2889 pub fn dialect_type(&self) -> DialectType {
2891 self.dialect_type
2892 }
2893
2894 #[cfg(feature = "generate")]
2896 pub fn generator_config(&self) -> &GeneratorConfig {
2897 &self.generator_config
2898 }
2899
2900 pub fn parse(&self, sql: &str) -> Result<Vec<Expression>> {
2906 self.parse_with_guard(sql, self.default_complexity_guard())
2907 }
2908
2909 fn parse_with_guard(
2910 &self,
2911 sql: &str,
2912 complexity_guard: ComplexityGuardOptions,
2913 ) -> Result<Vec<Expression>> {
2914 enforce_input(sql, &complexity_guard)?;
2915 let source: Arc<str> = Arc::from(sql);
2916 let (tokens, token_guard_stats) = self.tokenizer.tokenize_for_parser(&source)?;
2917 let config = crate::parser::ParserConfig {
2918 dialect: Some(self.dialect_type),
2919 complexity_guard,
2920 ..Default::default()
2921 };
2922 let mut parser = Parser::with_parser_tokens(tokens, token_guard_stats, config, source);
2923 parser.parse()
2924 }
2925
2926 fn default_complexity_guard(&self) -> ComplexityGuardOptions {
2927 let mut guard = ComplexityGuardOptions::default();
2928 if matches!(self.dialect_type, DialectType::ClickHouse) {
2929 guard.max_ast_depth = Some(4_096);
2930 guard.max_function_call_depth = Some(512);
2931 }
2932 guard
2933 }
2934
2935 #[cfg(feature = "transpile")]
2936 fn default_transpile_complexity_guard(
2937 &self,
2938 target_dialect: &Dialect,
2939 guard: ComplexityGuardOptions,
2940 ) -> ComplexityGuardOptions {
2941 if guard != ComplexityGuardOptions::default() {
2942 return guard;
2943 }
2944
2945 if matches!(self.dialect_type, DialectType::ClickHouse)
2946 || matches!(target_dialect.dialect_type, DialectType::ClickHouse)
2947 {
2948 let mut guard = guard;
2949 guard.max_ast_depth = Some(4_096);
2950 guard.max_function_call_depth = Some(512);
2951 guard
2952 } else {
2953 guard
2954 }
2955 }
2956
2957 pub fn parse_data_type(&self, sql: &str) -> Result<DataType> {
2962 let complexity_guard = self.default_complexity_guard();
2963 enforce_input(sql, &complexity_guard)?;
2964 let source: Arc<str> = Arc::from(sql);
2965 let (tokens, token_guard_stats) = self.tokenizer.tokenize_for_parser(&source)?;
2966 let config = crate::parser::ParserConfig {
2967 dialect: Some(self.dialect_type),
2968 complexity_guard,
2969 ..Default::default()
2970 };
2971 let mut parser = Parser::with_parser_tokens(tokens, token_guard_stats, config, source);
2972 parser.parse_standalone_data_type()
2973 }
2974
2975 pub fn tokenize(&self, sql: &str) -> Result<Vec<Token>> {
2977 self.tokenizer.tokenize(sql)
2978 }
2979
2980 #[cfg(feature = "generate")]
2983 fn get_config_for_expr(&self, expr: &Expression) -> GeneratorConfig {
2984 if let Some(ref config_fn) = self.generator_config_for_expr {
2985 config_fn(expr)
2986 } else {
2987 (*self.generator_config).clone()
2988 }
2989 }
2990
2991 #[cfg(feature = "generate")]
2997 pub fn generate(&self, expr: &Expression) -> Result<String> {
2998 if self.generator_config_for_expr.is_none() {
3000 let mut generator = Generator::with_arc_config(self.generator_config.clone());
3001 return generator.generate(expr);
3002 }
3003 let config = self.get_config_for_expr(expr);
3004 let mut generator = Generator::with_config(config);
3005 generator.generate(expr)
3006 }
3007
3008 #[cfg(feature = "generate")]
3010 pub fn generate_pretty(&self, expr: &Expression) -> Result<String> {
3011 let mut config = self.get_config_for_expr(expr);
3012 config.pretty = true;
3013 let mut generator = Generator::with_config(config);
3014 generator.generate(expr)
3015 }
3016
3017 #[cfg(feature = "generate")]
3019 pub fn generate_with_source(&self, expr: &Expression, source: DialectType) -> Result<String> {
3020 let mut config = self.get_config_for_expr(expr);
3021 config.source_dialect = Some(source);
3022 let mut generator = Generator::with_config(config);
3023 generator.generate(expr)
3024 }
3025
3026 #[cfg(feature = "generate")]
3028 pub fn generate_pretty_with_source(
3029 &self,
3030 expr: &Expression,
3031 source: DialectType,
3032 ) -> Result<String> {
3033 let mut config = self.get_config_for_expr(expr);
3034 config.pretty = true;
3035 config.source_dialect = Some(source);
3036 let mut generator = Generator::with_config(config);
3037 generator.generate(expr)
3038 }
3039
3040 #[cfg(all(feature = "generate", feature = "transpile"))]
3042 fn generate_with_transpile_options(
3043 &self,
3044 expr: &Expression,
3045 source: DialectType,
3046 opts: &TranspileOptions,
3047 ) -> Result<String> {
3048 let mut config = self.get_config_for_expr(expr);
3049 config.source_dialect = Some(source);
3050 config.pretty = opts.pretty;
3051 config.unsupported_level = opts.unsupported_level;
3052 config.max_unsupported = opts.max_unsupported.max(1);
3053 config.complexity_guard = opts.complexity_guard;
3054 let mut generator = Generator::with_config(config);
3055 generator.generate(expr)
3056 }
3057
3058 #[cfg(feature = "generate")]
3060 pub fn generate_with_identify(&self, expr: &Expression) -> Result<String> {
3061 let mut config = self.get_config_for_expr(expr);
3062 config.always_quote_identifiers = true;
3063 let mut generator = Generator::with_config(config);
3064 generator.generate(expr)
3065 }
3066
3067 #[cfg(feature = "generate")]
3069 pub fn generate_pretty_with_identify(&self, expr: &Expression) -> Result<String> {
3070 let mut config = (*self.generator_config).clone();
3071 config.pretty = true;
3072 config.always_quote_identifiers = true;
3073 let mut generator = Generator::with_config(config);
3074 generator.generate(expr)
3075 }
3076
3077 #[cfg(feature = "generate")]
3079 pub fn generate_with_overrides(
3080 &self,
3081 expr: &Expression,
3082 overrides: impl FnOnce(&mut GeneratorConfig),
3083 ) -> Result<String> {
3084 let mut config = self.get_config_for_expr(expr);
3085 overrides(&mut config);
3086 let mut generator = Generator::with_config(config);
3087 generator.generate(expr)
3088 }
3089
3090 #[cfg(feature = "transpile")]
3101 pub fn transform(&self, expr: Expression) -> Result<Expression> {
3102 self.transform_with_guard(expr, self.default_complexity_guard())
3103 }
3104
3105 #[cfg(feature = "transpile")]
3106 fn transform_with_guard(
3107 &self,
3108 expr: Expression,
3109 complexity_guard: ComplexityGuardOptions,
3110 ) -> Result<Expression> {
3111 enforce_generate_ast(&expr, &complexity_guard)?;
3112 let preprocessed = self.preprocess(expr)?;
3114 transform_recursive(preprocessed, &self.transformer)
3116 }
3117
3118 #[cfg(feature = "transpile")]
3120 fn preprocess(&self, expr: Expression) -> Result<Expression> {
3121 if let Some(ref custom_preprocess) = self.custom_preprocess {
3123 return custom_preprocess(expr);
3124 }
3125
3126 #[cfg(any(
3127 feature = "dialect-mysql",
3128 feature = "dialect-postgresql",
3129 feature = "dialect-bigquery",
3130 feature = "dialect-snowflake",
3131 feature = "dialect-tsql",
3132 feature = "dialect-spark",
3133 feature = "dialect-databricks",
3134 feature = "dialect-hive",
3135 feature = "dialect-sqlite",
3136 feature = "dialect-trino",
3137 feature = "dialect-presto",
3138 feature = "dialect-duckdb",
3139 feature = "dialect-redshift",
3140 feature = "dialect-starrocks",
3141 feature = "dialect-oracle",
3142 feature = "dialect-clickhouse",
3143 feature = "dialect-fabric",
3144 ))]
3145 use crate::transforms;
3146
3147 match self.dialect_type {
3148 #[cfg(feature = "dialect-mysql")]
3151 DialectType::MySQL => {
3152 let expr = transforms::eliminate_qualify(expr)?;
3153 let expr = transforms::eliminate_full_outer_join(expr)?;
3154 let expr = transforms::eliminate_semi_and_anti_joins(expr)?;
3155 let expr = transforms::unnest_generate_date_array_using_recursive_cte(expr)?;
3156 Ok(expr)
3157 }
3158 #[cfg(feature = "dialect-postgresql")]
3162 DialectType::PostgreSQL => {
3163 let expr = transforms::eliminate_qualify(expr)?;
3164 let expr = transforms::eliminate_semi_and_anti_joins(expr)?;
3165 let expr = transforms::unwrap_unnest_generate_series_for_postgres(expr)?;
3166 let expr = if let Expression::CreateFunction(mut cf) = expr {
3171 if cf.body.is_none() {
3172 for opt in &mut cf.set_options {
3173 if let crate::expressions::FunctionSetValue::Value { use_to, .. } =
3174 &mut opt.value
3175 {
3176 *use_to = false;
3177 }
3178 }
3179 }
3180 Expression::CreateFunction(cf)
3181 } else {
3182 expr
3183 };
3184 Ok(expr)
3185 }
3186 #[cfg(feature = "dialect-bigquery")]
3188 DialectType::BigQuery => {
3189 let expr = transforms::eliminate_semi_and_anti_joins(expr)?;
3190 let expr = transforms::pushdown_cte_column_names(expr)?;
3191 let expr = transforms::explode_projection_to_unnest(expr, DialectType::BigQuery)?;
3192 Ok(expr)
3193 }
3194 #[cfg(feature = "dialect-snowflake")]
3196 DialectType::Snowflake => {
3197 let expr = transforms::eliminate_semi_and_anti_joins(expr)?;
3198 let expr = transforms::eliminate_window_clause(expr)?;
3199 let expr = transforms::snowflake_flatten_projection_to_unnest(expr)?;
3200 Ok(expr)
3201 }
3202 #[cfg(feature = "dialect-tsql")]
3208 DialectType::TSQL => {
3209 let expr = transforms::eliminate_qualify(expr)?;
3210 let expr = transforms::eliminate_semi_and_anti_joins(expr)?;
3211 let expr =
3212 transforms::expand_distinct_grouping_sets_for_tsql(expr, DialectType::TSQL)?;
3213 let expr = transforms::ensure_bools(expr)?;
3214 let expr = transforms::unnest_generate_date_array_using_recursive_cte(expr)?;
3215 let expr = transforms::strip_cte_materialization(expr)?;
3216 let expr = transforms::move_ctes_to_top_level(expr)?;
3217 let expr = transforms::qualify_derived_table_outputs(expr)?;
3218 Ok(expr)
3219 }
3220 #[cfg(feature = "dialect-fabric")]
3223 DialectType::Fabric => {
3224 let expr =
3225 transforms::expand_distinct_grouping_sets_for_tsql(expr, DialectType::Fabric)?;
3226 let expr = transforms::ensure_bools(expr)?;
3227 let expr = transforms::strip_cte_materialization(expr)?;
3228 let expr = transforms::move_ctes_to_top_level(expr)?;
3229 Ok(expr)
3230 }
3231 #[cfg(feature = "dialect-spark")]
3234 DialectType::Spark => {
3235 let expr = transforms::eliminate_qualify(expr)?;
3236 let expr = transforms::add_auto_table_alias(expr)?;
3237 let expr = transforms::simplify_nested_paren_values(expr)?;
3238 let expr = transforms::move_ctes_to_top_level(expr)?;
3239 Ok(expr)
3240 }
3241 #[cfg(feature = "dialect-databricks")]
3244 DialectType::Databricks => {
3245 let expr = transforms::add_auto_table_alias(expr)?;
3246 let expr = transforms::simplify_nested_paren_values(expr)?;
3247 let expr = transforms::move_ctes_to_top_level(expr)?;
3248 Ok(expr)
3249 }
3250 #[cfg(feature = "dialect-hive")]
3252 DialectType::Hive => {
3253 let expr = transforms::eliminate_qualify(expr)?;
3254 let expr = transforms::move_ctes_to_top_level(expr)?;
3255 Ok(expr)
3256 }
3257 #[cfg(feature = "dialect-sqlite")]
3259 DialectType::SQLite => {
3260 let expr = transforms::eliminate_qualify(expr)?;
3261 Ok(expr)
3262 }
3263 #[cfg(feature = "dialect-trino")]
3265 DialectType::Trino => {
3266 let expr = transforms::eliminate_qualify(expr)?;
3267 let expr = transforms::explode_projection_to_unnest(expr, DialectType::Trino)?;
3268 Ok(expr)
3269 }
3270 #[cfg(feature = "dialect-presto")]
3272 DialectType::Presto => {
3273 let expr = transforms::eliminate_qualify(expr)?;
3274 let expr = transforms::eliminate_window_clause(expr)?;
3275 let expr = transforms::explode_projection_to_unnest(expr, DialectType::Presto)?;
3276 Ok(expr)
3277 }
3278 #[cfg(feature = "dialect-duckdb")]
3282 DialectType::DuckDB => {
3283 let expr = transforms::expand_posexplode_duckdb(expr)?;
3284 let expr = transforms::expand_like_any(expr)?;
3285 Ok(expr)
3286 }
3287 #[cfg(feature = "dialect-redshift")]
3289 DialectType::Redshift => {
3290 let expr = transforms::eliminate_qualify(expr)?;
3291 let expr = transforms::eliminate_window_clause(expr)?;
3292 let expr = transforms::unnest_generate_date_array_using_recursive_cte(expr)?;
3293 Ok(expr)
3294 }
3295 #[cfg(feature = "dialect-starrocks")]
3297 DialectType::StarRocks => {
3298 let expr = transforms::eliminate_qualify(expr)?;
3299 let expr = transforms::expand_between_in_delete(expr)?;
3300 let expr = transforms::eliminate_distinct_on_for_dialect(
3301 expr,
3302 Some(DialectType::StarRocks),
3303 Some(DialectType::StarRocks),
3304 )?;
3305 let expr = transforms::unnest_generate_date_array_using_recursive_cte(expr)?;
3306 Ok(expr)
3307 }
3308 #[cfg(feature = "dialect-datafusion")]
3310 DialectType::DataFusion => Ok(expr),
3311 #[cfg(feature = "dialect-oracle")]
3313 DialectType::Oracle => {
3314 let expr = transforms::eliminate_qualify(expr)?;
3315 Ok(expr)
3316 }
3317 #[cfg(feature = "dialect-drill")]
3319 DialectType::Drill => Ok(expr),
3320 #[cfg(feature = "dialect-teradata")]
3322 DialectType::Teradata => Ok(expr),
3323 #[cfg(feature = "dialect-clickhouse")]
3325 DialectType::ClickHouse => {
3326 let expr = transforms::no_limit_order_by_union(expr)?;
3327 Ok(expr)
3328 }
3329 _ => Ok(expr),
3331 }
3332 }
3333
3334 #[cfg(feature = "transpile")]
3347 pub fn transpile<T: TranspileTarget>(&self, sql: &str, target: T) -> Result<Vec<String>> {
3348 self.transpile_with(sql, target, TranspileOptions::default())
3349 }
3350
3351 #[cfg(feature = "transpile")]
3353 pub fn transpile_with<T: TranspileTarget>(
3354 &self,
3355 sql: &str,
3356 target: T,
3357 opts: TranspileOptions,
3358 ) -> Result<Vec<String>> {
3359 target.with_dialect(|td| self.transpile_inner(sql, td, &opts))
3360 }
3361
3362 #[cfg(feature = "transpile")]
3363 fn transpile_inner(
3364 &self,
3365 sql: &str,
3366 target_dialect: &Dialect,
3367 opts: &TranspileOptions,
3368 ) -> Result<Vec<String>> {
3369 let mut effective_opts = opts.clone();
3370 effective_opts.complexity_guard =
3371 self.default_transpile_complexity_guard(target_dialect, opts.complexity_guard);
3372 let opts = &effective_opts;
3373 let target = target_dialect.dialect_type;
3374 if matches!(self.dialect_type, DialectType::PostgreSQL)
3375 && matches!(target, DialectType::SQLite)
3376 {
3377 self.reject_pgvector_distance_operators_for_sqlite(sql)?;
3378 }
3379 let expressions = self.parse_with_guard(sql, opts.complexity_guard)?;
3380 let generic_identity =
3381 self.dialect_type == DialectType::Generic && target == DialectType::Generic;
3382
3383 if generic_identity {
3384 return expressions
3385 .into_iter()
3386 .map(|expr| {
3387 Self::reject_strict_unsupported(&expr, self.dialect_type, target, opts)?;
3388 target_dialect.generate_with_transpile_options(&expr, self.dialect_type, opts)
3389 })
3390 .collect();
3391 }
3392
3393 expressions
3394 .into_iter()
3395 .map(|expr| {
3396 let expr = if matches!(self.dialect_type, DialectType::DuckDB) {
3400 use crate::expressions::DataType as DT;
3401 transform_recursive(expr, &|e| match e {
3402 Expression::DataType(DT::VarChar { .. }) => {
3403 Ok(Expression::DataType(DT::Text))
3404 }
3405 Expression::DataType(DT::Char { .. }) => Ok(Expression::DataType(DT::Text)),
3406 _ => Ok(e),
3407 })?
3408 } else {
3409 expr
3410 };
3411
3412 Self::reject_postgres_tsql_strict_regex_predicates(
3413 &expr,
3414 self.dialect_type,
3415 target,
3416 opts,
3417 )?;
3418
3419 let normalized =
3423 if self.dialect_type != target && self.dialect_type != DialectType::Generic {
3424 self.transform_with_guard(expr, opts.complexity_guard)?
3425 } else {
3426 expr
3427 };
3428
3429 let normalized =
3434 if matches!(self.dialect_type, DialectType::TSQL | DialectType::Fabric)
3435 && !matches!(target, DialectType::TSQL | DialectType::Fabric)
3436 {
3437 transform_recursive(normalized, &|e| {
3438 if let Expression::Function(ref f) = e {
3439 if f.name.eq_ignore_ascii_case("ISNULL") && f.args.len() == 2 {
3440 if let (
3442 Expression::Function(ref jq),
3443 Expression::Function(ref jv),
3444 ) = (&f.args[0], &f.args[1])
3445 {
3446 if jq.name.eq_ignore_ascii_case("JSON_QUERY")
3447 && jv.name.eq_ignore_ascii_case("JSON_VALUE")
3448 {
3449 return Ok(f.args[0].clone());
3451 }
3452 }
3453 }
3454 }
3455 Ok(e)
3456 })?
3457 } else {
3458 normalized
3459 };
3460
3461 let normalized = if matches!(self.dialect_type, DialectType::Snowflake)
3465 && !matches!(target, DialectType::Snowflake)
3466 {
3467 transform_recursive(normalized, &|e| {
3468 if let Expression::Function(ref f) = e {
3469 if f.name.eq_ignore_ascii_case("CURRENT_TIME") {
3470 return Ok(Expression::Localtime(Box::new(
3471 crate::expressions::Localtime { this: None },
3472 )));
3473 }
3474 }
3475 Ok(e)
3476 })?
3477 } else {
3478 normalized
3479 };
3480
3481 let normalized = if matches!(self.dialect_type, DialectType::Snowflake)
3485 && matches!(target, DialectType::DuckDB)
3486 {
3487 transform_recursive(normalized, &|e| {
3488 if let Expression::Function(ref f) = e {
3489 if f.name.eq_ignore_ascii_case("REPEAT") && f.args.len() == 2 {
3490 if let Expression::Literal(ref lit) = f.args[0] {
3492 if let crate::expressions::Literal::String(ref s) = lit.as_ref()
3493 {
3494 if s == " " {
3495 if !matches!(f.args[1], Expression::Cast(_)) {
3497 let mut new_args = f.args.clone();
3498 new_args[1] = Expression::Cast(Box::new(
3499 crate::expressions::Cast {
3500 this: new_args[1].clone(),
3501 to: crate::expressions::DataType::BigInt {
3502 length: None,
3503 },
3504 trailing_comments: Vec::new(),
3505 double_colon_syntax: false,
3506 format: None,
3507 default: None,
3508 inferred_type: None,
3509 },
3510 ));
3511 return Ok(Expression::Function(Box::new(
3512 crate::expressions::Function {
3513 name: f.name.clone(),
3514 args: new_args,
3515 distinct: f.distinct,
3516 trailing_comments: f
3517 .trailing_comments
3518 .clone(),
3519 use_bracket_syntax: f.use_bracket_syntax,
3520 no_parens: f.no_parens,
3521 quoted: f.quoted,
3522 span: None,
3523 inferred_type: None,
3524 },
3525 )));
3526 }
3527 }
3528 }
3529 }
3530 }
3531 }
3532 Ok(e)
3533 })?
3534 } else {
3535 normalized
3536 };
3537
3538 let normalized = if matches!(self.dialect_type, DialectType::BigQuery)
3541 && !matches!(target, DialectType::BigQuery)
3542 {
3543 crate::transforms::propagate_struct_field_names(normalized)?
3544 } else {
3545 normalized
3546 };
3547
3548 let normalized = if matches!(self.dialect_type, DialectType::Snowflake)
3553 && matches!(target, DialectType::DuckDB)
3554 {
3555 fn make_scaled_random() -> Expression {
3556 let lower =
3557 Expression::Literal(Box::new(crate::expressions::Literal::Number(
3558 "-9.223372036854776E+18".to_string(),
3559 )));
3560 let upper =
3561 Expression::Literal(Box::new(crate::expressions::Literal::Number(
3562 "9.223372036854776e+18".to_string(),
3563 )));
3564 let random_call = Expression::Random(crate::expressions::Random);
3565 let range_size = Expression::Paren(Box::new(crate::expressions::Paren {
3566 this: Expression::Sub(Box::new(crate::expressions::BinaryOp {
3567 left: upper,
3568 right: lower.clone(),
3569 left_comments: vec![],
3570 operator_comments: vec![],
3571 trailing_comments: vec![],
3572 inferred_type: None,
3573 })),
3574 trailing_comments: vec![],
3575 }));
3576 let scaled = Expression::Mul(Box::new(crate::expressions::BinaryOp {
3577 left: random_call,
3578 right: range_size,
3579 left_comments: vec![],
3580 operator_comments: vec![],
3581 trailing_comments: vec![],
3582 inferred_type: None,
3583 }));
3584 let shifted = Expression::Add(Box::new(crate::expressions::BinaryOp {
3585 left: lower,
3586 right: scaled,
3587 left_comments: vec![],
3588 operator_comments: vec![],
3589 trailing_comments: vec![],
3590 inferred_type: None,
3591 }));
3592 Expression::Cast(Box::new(crate::expressions::Cast {
3593 this: shifted,
3594 to: crate::expressions::DataType::BigInt { length: None },
3595 trailing_comments: vec![],
3596 double_colon_syntax: false,
3597 format: None,
3598 default: None,
3599 inferred_type: None,
3600 }))
3601 }
3602
3603 let normalized = transform_recursive(normalized, &|e| {
3610 if let Expression::Function(ref f) = e {
3611 let n = f.name.to_ascii_uppercase();
3612 if n == "UNIFORM" || n == "NORMAL" || n == "ZIPF" || n == "RANDSTR" {
3613 if let Expression::Function(mut f) = e {
3614 for arg in f.args.iter_mut() {
3615 if let Expression::Rand(ref r) = arg {
3616 if r.lower.is_none() && r.upper.is_none() {
3617 if let Some(ref seed) = r.seed {
3618 *arg = Expression::Function(Box::new(
3621 crate::expressions::Function::new(
3622 "RANDOM".to_string(),
3623 vec![*seed.clone()],
3624 ),
3625 ));
3626 }
3627 }
3628 }
3629 }
3630 return Ok(Expression::Function(f));
3631 }
3632 }
3633 }
3634 Ok(e)
3635 })?;
3636
3637 transform_recursive(normalized, &|e| {
3645 if let Expression::Function(ref f) = e {
3646 let n = f.name.to_ascii_uppercase();
3647 if n == "UNIFORM" || n == "NORMAL" || n == "ZIPF" {
3648 if let Expression::Function(mut f) = e {
3649 for arg in f.args.iter_mut() {
3650 if let Expression::Cast(ref cast) = arg {
3652 if matches!(
3653 cast.to,
3654 crate::expressions::DataType::BigInt { .. }
3655 ) {
3656 if let Expression::Add(ref add) = cast.this {
3657 if let Expression::Literal(ref lit) = add.left {
3658 if let crate::expressions::Literal::Number(
3659 ref num,
3660 ) = lit.as_ref()
3661 {
3662 if num == "-9.223372036854776E+18" {
3663 *arg = Expression::Random(
3664 crate::expressions::Random,
3665 );
3666 }
3667 }
3668 }
3669 }
3670 }
3671 }
3672 }
3673 return Ok(Expression::Function(f));
3674 }
3675 return Ok(e);
3676 }
3677 }
3678 match e {
3679 Expression::Random(_) => Ok(make_scaled_random()),
3680 Expression::Rand(ref r) if r.lower.is_none() && r.upper.is_none() => {
3683 Ok(make_scaled_random())
3684 }
3685 _ => Ok(e),
3686 }
3687 })?
3688 } else {
3689 normalized
3690 };
3691
3692 let normalized = normalization::normalize(normalized, self.dialect_type, target)?;
3694
3695 let normalized = if matches!(target, DialectType::TSQL | DialectType::Fabric) {
3696 Self::normalize_tsql_fetch_overlaps_date_bin(normalized)?
3697 } else {
3698 normalized
3699 };
3700
3701 let normalized =
3702 if matches!(
3703 self.dialect_type,
3704 DialectType::PostgreSQL | DialectType::CockroachDB
3705 ) && !matches!(target, DialectType::PostgreSQL | DialectType::CockroachDB)
3706 {
3707 Self::normalize_postgres_type_function_casts(normalized)?
3708 } else {
3709 normalized
3710 };
3711
3712 let normalized = if matches!(self.dialect_type, DialectType::SQLite)
3713 && !matches!(target, DialectType::SQLite)
3714 {
3715 Self::normalize_sqlite_double_quoted_defaults(normalized)?
3716 } else {
3717 normalized
3718 };
3719
3720 let normalized = if matches!(self.dialect_type, DialectType::PostgreSQL)
3721 && matches!(target, DialectType::SQLite)
3722 {
3723 Self::normalize_postgres_to_sqlite_types(normalized)?
3724 } else {
3725 normalized
3726 };
3727
3728 let normalized = if matches!(self.dialect_type, DialectType::PostgreSQL)
3729 && matches!(target, DialectType::Fabric)
3730 {
3731 Self::normalize_postgres_to_fabric_types(normalized)?
3732 } else {
3733 normalized
3734 };
3735
3736 let normalized = if matches!(self.dialect_type, DialectType::BigQuery)
3740 && matches!(target, DialectType::DuckDB)
3741 {
3742 crate::transforms::wrap_duckdb_unnest_struct(normalized)?
3743 } else {
3744 normalized
3745 };
3746
3747 let normalized = if matches!(self.dialect_type, DialectType::BigQuery)
3750 && matches!(
3751 target,
3752 DialectType::DuckDB
3753 | DialectType::Presto
3754 | DialectType::Trino
3755 | DialectType::Athena
3756 | DialectType::Spark
3757 | DialectType::Databricks
3758 ) {
3759 crate::transforms::unnest_alias_to_column_alias(normalized)?
3760 } else if matches!(self.dialect_type, DialectType::BigQuery)
3761 && matches!(target, DialectType::BigQuery | DialectType::Redshift)
3762 {
3763 let result = crate::transforms::unnest_from_to_cross_join(normalized)?;
3766 if matches!(target, DialectType::Redshift) {
3768 crate::transforms::strip_unnest_column_refs(result)?
3769 } else {
3770 result
3771 }
3772 } else {
3773 normalized
3774 };
3775
3776 let normalized = if matches!(
3779 self.dialect_type,
3780 DialectType::PostgreSQL | DialectType::Redshift
3781 ) && matches!(
3782 target,
3783 DialectType::Presto | DialectType::Trino | DialectType::Athena
3784 ) {
3785 crate::transforms::wrap_unnest_join_aliases(normalized)?
3786 } else {
3787 normalized
3788 };
3789
3790 let normalized = crate::transforms::eliminate_distinct_on_for_dialect(
3794 normalized,
3795 Some(target),
3796 Some(self.dialect_type),
3797 )?;
3798
3799 let normalized = if matches!(target, DialectType::Snowflake) {
3801 Self::transform_generate_date_array_snowflake(normalized)?
3802 } else {
3803 normalized
3804 };
3805
3806 let normalized = if matches!(
3808 target,
3809 DialectType::Spark | DialectType::Databricks | DialectType::Hive
3810 ) {
3811 crate::transforms::unnest_to_explode_select(normalized)?
3812 } else {
3813 normalized
3814 };
3815
3816 let normalized = if matches!(target, DialectType::ClickHouse | DialectType::TSQL) {
3818 crate::transforms::no_limit_order_by_union(normalized)?
3819 } else {
3820 normalized
3821 };
3822
3823 let normalized = if matches!(target, DialectType::TSQL | DialectType::Fabric)
3827 && !matches!(self.dialect_type, DialectType::TSQL | DialectType::Fabric)
3828 {
3829 transform_recursive(normalized, &|e| {
3830 if let Expression::Count(ref c) = e {
3831 let args = if c.star {
3833 vec![Expression::Star(crate::expressions::Star {
3834 table: None,
3835 except: None,
3836 replace: None,
3837 rename: None,
3838 trailing_comments: Vec::new(),
3839 span: None,
3840 })]
3841 } else if let Some(ref this) = c.this {
3842 vec![this.clone()]
3843 } else {
3844 vec![]
3845 };
3846 Ok(Expression::AggregateFunction(Box::new(
3847 crate::expressions::AggregateFunction {
3848 name: "COUNT_BIG".to_string(),
3849 args,
3850 distinct: c.distinct,
3851 filter: c.filter.clone(),
3852 order_by: Vec::new(),
3853 limit: None,
3854 ignore_nulls: None,
3855 inferred_type: None,
3856 },
3857 )))
3858 } else {
3859 Ok(e)
3860 }
3861 })?
3862 } else {
3863 normalized
3864 };
3865
3866 let normalized = if matches!(target, DialectType::TSQL | DialectType::Fabric)
3870 && !matches!(self.dialect_type, DialectType::TSQL | DialectType::Fabric)
3871 {
3872 Self::rewrite_boolean_values_for_tsql(normalized)?
3873 } else {
3874 normalized
3875 };
3876
3877 let normalized = if matches!(
3878 self.dialect_type,
3879 DialectType::PostgreSQL | DialectType::CockroachDB
3880 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
3881 {
3882 Self::rewrite_postgres_format_for_tsql(normalized, target)?
3883 } else {
3884 normalized
3885 };
3886
3887 let normalized = if self.dialect_type == DialectType::PostgreSQL
3888 && matches!(target, DialectType::TSQL | DialectType::Fabric)
3889 {
3890 Self::normalize_postgres_only_for_tsql(normalized)?
3891 } else {
3892 normalized
3893 };
3894
3895 let transformed =
3896 target_dialect.transform_with_guard(normalized, opts.complexity_guard)?;
3897
3898 let transformed = if matches!(target, DialectType::TSQL | DialectType::Fabric) {
3902 Self::rewrite_aggregate_filters_for_tsql(transformed)?
3903 } else {
3904 transformed
3905 };
3906
3907 let transformed = if matches!(
3908 self.dialect_type,
3909 DialectType::PostgreSQL | DialectType::CockroachDB
3910 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
3911 {
3912 crate::transforms::grouped_percentiles_to_tsql_windows(transformed)?
3913 } else {
3914 transformed
3915 };
3916
3917 let transformed = if matches!(
3918 self.dialect_type,
3919 DialectType::PostgreSQL | DialectType::CockroachDB
3920 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
3921 {
3922 Self::normalize_postgres_trim_for_tsql(transformed)?
3923 } else {
3924 transformed
3925 };
3926
3927 let transformed = if matches!(
3928 self.dialect_type,
3929 DialectType::PostgreSQL | DialectType::CockroachDB
3930 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
3931 {
3932 Self::rewrite_postgres_json_array_elements_select_for_tsql(transformed)?
3933 } else {
3934 transformed
3935 };
3936
3937 let transformed = if matches!(target, DialectType::DuckDB) {
3939 Self::seq_rownum_to_range(transformed)?
3940 } else {
3941 transformed
3942 };
3943
3944 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
3945 Self::reject_tsql_interval_casts(&transformed, target, opts)?;
3946 }
3947
3948 let transformed = if matches!(target, DialectType::TSQL | DialectType::Fabric) {
3949 Self::rewrite_tsql_interval_casts_to_varchar(transformed)?
3950 } else {
3951 transformed
3952 };
3953
3954 let transformed = if matches!(target, DialectType::TSQL | DialectType::Fabric) {
3955 Self::legalize_tsql_nested_order_by(transformed)?
3956 } else {
3957 transformed
3958 };
3959
3960 Self::reject_strict_unsupported(&transformed, self.dialect_type, target, opts)?;
3961
3962 let mut sql = target_dialect.generate_with_transpile_options(
3963 &transformed,
3964 self.dialect_type,
3965 opts,
3966 )?;
3967
3968 if opts.pretty && target == DialectType::Snowflake {
3970 sql = Self::normalize_snowflake_pretty(sql);
3971 }
3972
3973 Ok(sql)
3974 })
3975 .collect()
3976 }
3977}
3978
3979#[cfg(feature = "transpile")]
3981impl Dialect {
3982 fn legalize_tsql_nested_order_by(expr: Expression) -> Result<Expression> {
3983 let preserve_root_order = matches!(&expr, Expression::Select(select) if Self::tsql_select_needs_order_offset(select));
3984
3985 let mut transformed = transform_recursive(expr, &|node| match node {
3986 Expression::Select(mut select) => {
3987 Self::legalize_tsql_select_offset(&mut select);
3988 if Self::tsql_select_needs_order_offset(&select) {
3989 select.offset = Some(Offset {
3990 this: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
3991 rows: Some(true),
3992 });
3993 }
3994 Ok(Expression::Select(select))
3995 }
3996 Expression::Subquery(mut subquery) => {
3997 Self::legalize_tsql_offset(&mut subquery.order_by, &mut subquery.offset, false);
3998 Ok(Expression::Subquery(subquery))
3999 }
4000 Expression::Union(mut union) => {
4001 Self::legalize_tsql_set_offset(&mut union.order_by, &mut union.offset);
4002 Ok(Expression::Union(union))
4003 }
4004 Expression::Intersect(mut intersect) => {
4005 Self::legalize_tsql_set_offset(&mut intersect.order_by, &mut intersect.offset);
4006 Ok(Expression::Intersect(intersect))
4007 }
4008 Expression::Except(mut except) => {
4009 Self::legalize_tsql_set_offset(&mut except.order_by, &mut except.offset);
4010 Ok(Expression::Except(except))
4011 }
4012 other => Ok(other),
4013 })?;
4014
4015 if preserve_root_order {
4016 if let Expression::Select(select) = &mut transformed {
4017 select.offset = None;
4018 }
4019 }
4020
4021 Ok(transformed)
4022 }
4023
4024 fn legalize_tsql_select_offset(select: &mut crate::expressions::Select) {
4025 let has_fetch = select.fetch.is_some();
4026 Self::legalize_tsql_offset(&mut select.order_by, &mut select.offset, has_fetch);
4027 }
4028
4029 fn legalize_tsql_offset(
4030 order_by: &mut Option<OrderBy>,
4031 offset: &mut Option<Offset>,
4032 retain_inert_offset: bool,
4033 ) {
4034 if order_by.is_some() {
4035 return;
4036 }
4037
4038 if offset
4039 .as_ref()
4040 .is_some_and(|offset| Self::tsql_offset_is_inert(&offset.this))
4041 && !retain_inert_offset
4042 {
4043 *offset = None;
4044 } else if offset.is_some() {
4045 *order_by = Some(Generator::dummy_tsql_order_by());
4046 }
4047 }
4048
4049 fn legalize_tsql_set_offset(
4050 order_by: &mut Option<OrderBy>,
4051 offset: &mut Option<Box<Expression>>,
4052 ) {
4053 if order_by.is_some() {
4054 return;
4055 }
4056
4057 if offset.as_deref().is_some_and(Self::tsql_offset_is_inert) {
4058 *offset = None;
4059 } else if offset.is_some() {
4060 *order_by = Some(Generator::dummy_tsql_order_by());
4061 }
4062 }
4063
4064 fn tsql_offset_is_inert(expr: &Expression) -> bool {
4065 match expr {
4066 Expression::Null(_) => true,
4067 Expression::Literal(literal) => match literal.as_ref() {
4068 Literal::Number(value) => value.parse::<i128>().is_ok_and(|value| value == 0),
4069 _ => false,
4070 },
4071 _ => false,
4072 }
4073 }
4074
4075 fn tsql_select_needs_order_offset(select: &crate::expressions::Select) -> bool {
4076 select.order_by.is_some()
4077 && select.top.is_none()
4078 && select.limit.is_none()
4079 && select.offset.is_none()
4080 && select.fetch.is_none()
4081 && select.for_xml.is_empty()
4082 && select.for_json.is_empty()
4083 }
4084
4085 fn reject_strict_unsupported(
4086 expr: &Expression,
4087 source: DialectType,
4088 target: DialectType,
4089 opts: &TranspileOptions,
4090 ) -> Result<()> {
4091 if !matches!(
4092 opts.unsupported_level,
4093 UnsupportedLevel::Raise | UnsupportedLevel::Immediate
4094 ) {
4095 return Ok(());
4096 }
4097
4098 let mut diagnostics = Vec::new();
4099
4100 for node in expr.dfs() {
4101 if matches!(target, DialectType::Fabric | DialectType::Hive)
4102 && Self::node_has_recursive_with(node)
4103 {
4104 Self::push_unsupported_diagnostic(&mut diagnostics, "recursive CTEs");
4105 }
4106
4107 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4108 && Self::node_has_lateral(node)
4109 {
4110 Self::push_unsupported_diagnostic(&mut diagnostics, "LATERAL joins and subqueries");
4111 }
4112
4113 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4114 if Self::node_has_join_using(node) {
4115 Self::push_unsupported_diagnostic(&mut diagnostics, "JOIN USING clauses");
4116 }
4117 if Self::node_has_natural_join(node) {
4118 Self::push_unsupported_diagnostic(&mut diagnostics, "NATURAL JOIN");
4119 }
4120 if Self::node_has_unsupported_relation_column_aliases(node) {
4121 Self::push_unsupported_diagnostic(
4122 &mut diagnostics,
4123 "column alias lists on base or joined table references",
4124 );
4125 }
4126 if Self::node_has_qualified_whole_row_aggregate_argument(node) {
4127 Self::push_unsupported_diagnostic(
4128 &mut diagnostics,
4129 "qualified whole-row aggregate arguments",
4130 );
4131 }
4132 }
4133
4134 if !Self::target_supports_distinct_on(target) && Self::node_has_distinct_on(node) {
4135 Self::push_unsupported_diagnostic(&mut diagnostics, "DISTINCT ON");
4136 }
4137
4138 if !Self::target_supports_remaining_unnest(target) && Self::node_is_unnest(node) {
4139 Self::push_unsupported_diagnostic(&mut diagnostics, "UNNEST");
4140 }
4141
4142 if !Self::target_supports_remaining_explode(target) && Self::node_is_explode(node) {
4143 Self::push_unsupported_diagnostic(&mut diagnostics, "EXPLODE");
4144 }
4145
4146 if Self::target_lacks_array_agg(target) && Self::node_is_array_agg(node) {
4147 Self::push_unsupported_diagnostic(&mut diagnostics, "ARRAY_AGG");
4148 }
4149
4150 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4151 && Self::node_is_distinct_string_agg(node)
4152 {
4153 Self::push_unsupported_diagnostic(&mut diagnostics, "STRING_AGG with DISTINCT");
4154 }
4155
4156 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4157 && matches!(node, Expression::NthValue(_))
4158 {
4159 Self::push_unsupported_diagnostic(&mut diagnostics, "NTH_VALUE");
4160 }
4161
4162 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4163 if let Some(frame) = Self::node_window_frame(node) {
4164 if matches!(frame.kind, WindowFrameKind::Groups) {
4165 Self::push_unsupported_diagnostic(&mut diagnostics, "GROUPS window frames");
4166 }
4167 if matches!(frame.kind, WindowFrameKind::Range)
4168 && (Self::window_frame_bound_has_value_offset(&frame.start)
4169 || frame
4170 .end
4171 .as_ref()
4172 .is_some_and(Self::window_frame_bound_has_value_offset))
4173 {
4174 Self::push_unsupported_diagnostic(
4175 &mut diagnostics,
4176 "value-offset RANGE window frames",
4177 );
4178 }
4179 if frame.exclude.is_some() {
4180 Self::push_unsupported_diagnostic(
4181 &mut diagnostics,
4182 "window frame EXCLUDE clauses",
4183 );
4184 }
4185 }
4186 }
4187
4188 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4189 && Self::node_is_regex_predicate(node)
4190 {
4191 Self::push_unsupported_diagnostic(
4192 &mut diagnostics,
4193 "regular expression predicates",
4194 );
4195 }
4196
4197 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4198 && Self::node_is_non_subquery_any(node)
4199 {
4200 Self::push_unsupported_diagnostic(
4201 &mut diagnostics,
4202 "ANY over non-subquery expressions",
4203 );
4204 }
4205
4206 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4207 && Self::node_is_row_value_subquery_comparison(node)
4208 {
4209 Self::push_unsupported_diagnostic(
4210 &mut diagnostics,
4211 "row-value subquery comparisons",
4212 );
4213 }
4214
4215 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4216 && Self::node_is_row_value_values_membership(node)
4217 {
4218 Self::push_unsupported_diagnostic(
4219 &mut diagnostics,
4220 "row-value VALUES membership comparisons",
4221 );
4222 }
4223
4224 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4225 && Self::node_has_fetch_with_ties(node)
4226 {
4227 Self::push_unsupported_diagnostic(&mut diagnostics, "FETCH WITH TIES without TOP");
4228 }
4229
4230 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4231 && Self::node_is_overlaps(node)
4232 {
4233 Self::push_unsupported_diagnostic(&mut diagnostics, "OVERLAPS");
4234 }
4235
4236 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4237 && Self::node_is_date_bin(node)
4238 {
4239 Self::push_unsupported_diagnostic(&mut diagnostics, "DATE_BIN");
4240 }
4241
4242 if source == DialectType::PostgreSQL
4243 && matches!(target, DialectType::TSQL | DialectType::Fabric)
4244 && Self::node_is_unresolved_postgres_date_subtraction(node)
4245 {
4246 Self::push_unsupported_diagnostic(
4247 &mut diagnostics,
4248 "PostgreSQL date subtraction with an unresolved column type",
4249 );
4250 }
4251
4252 if matches!(source, DialectType::PostgreSQL | DialectType::CockroachDB)
4253 && !matches!(target, DialectType::PostgreSQL | DialectType::CockroachDB)
4254 {
4255 if Self::node_is_postgres_json_build_object(node)
4256 && !(matches!(target, DialectType::TSQL | DialectType::Fabric)
4257 && Self::postgres_json_build_object_can_lower_to_json_object(node))
4258 {
4259 Self::push_unsupported_diagnostic(
4260 &mut diagnostics,
4261 "PostgreSQL JSON_BUILD_OBJECT",
4262 );
4263 }
4264 if Self::node_is_function_named(node, "TO_TSVECTOR") {
4265 Self::push_unsupported_diagnostic(&mut diagnostics, "PostgreSQL TO_TSVECTOR");
4266 }
4267 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4268 if let Some(collation_name) =
4269 Self::postgres_tsql_unsupported_collation_name(node)
4270 {
4271 Self::push_unsupported_diagnostic(
4272 &mut diagnostics,
4273 &format!("PostgreSQL collation \"{collation_name}\""),
4274 );
4275 }
4276 if let Some(array_semantics) =
4277 Self::postgres_tsql_unsupported_array_semantics(node)
4278 {
4279 Self::push_unsupported_diagnostic(
4280 &mut diagnostics,
4281 &format!("PostgreSQL {array_semantics}"),
4282 );
4283 }
4284 if let Some(function_name) = Self::postgres_tsql_unsupported_function_name(node)
4285 {
4286 Self::push_unsupported_diagnostic(
4287 &mut diagnostics,
4288 &format!("PostgreSQL {function_name}"),
4289 );
4290 }
4291 }
4292 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4293 && Self::node_is_postgres_type_function_cast(node)
4294 {
4295 Self::push_unsupported_diagnostic(
4296 &mut diagnostics,
4297 "PostgreSQL type-name function casts",
4298 );
4299 }
4300 }
4301
4302 if opts.unsupported_level == UnsupportedLevel::Immediate && !diagnostics.is_empty() {
4303 break;
4304 }
4305 }
4306
4307 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4308 Self::collect_tsql_unsupported_ordered_sets(expr, &mut diagnostics);
4309 Self::collect_tsql_windows_missing_order(expr, &HashMap::new(), &mut diagnostics);
4310 }
4311
4312 if diagnostics.is_empty() {
4313 return Ok(());
4314 }
4315
4316 let limit = if opts.unsupported_level == UnsupportedLevel::Immediate {
4317 1
4318 } else {
4319 opts.max_unsupported.max(1)
4320 };
4321 let mut messages = diagnostics.iter().take(limit).cloned().collect::<Vec<_>>();
4322 if diagnostics.len() > limit {
4323 messages.push(format!("... and {} more", diagnostics.len() - limit));
4324 }
4325
4326 Err(crate::error::Error::unsupported(
4327 messages.join("; "),
4328 target.to_string(),
4329 ))
4330 }
4331
4332 fn reject_postgres_tsql_strict_regex_predicates(
4333 expr: &Expression,
4334 source: DialectType,
4335 target: DialectType,
4336 opts: &TranspileOptions,
4337 ) -> Result<()> {
4338 if !matches!(
4339 opts.unsupported_level,
4340 UnsupportedLevel::Raise | UnsupportedLevel::Immediate
4341 ) || !matches!(source, DialectType::PostgreSQL | DialectType::CockroachDB)
4342 || !matches!(target, DialectType::TSQL | DialectType::Fabric)
4343 {
4344 return Ok(());
4345 }
4346
4347 if expr.dfs().any(Self::node_is_regex_predicate) {
4348 return Err(crate::error::Error::unsupported(
4349 "regular expression predicates",
4350 target.to_string(),
4351 ));
4352 }
4353
4354 Ok(())
4355 }
4356
4357 fn push_unsupported_diagnostic(diagnostics: &mut Vec<String>, message: &str) {
4358 if !diagnostics.iter().any(|existing| existing == message) {
4359 diagnostics.push(message.to_string());
4360 }
4361 }
4362
4363 fn node_is_unresolved_postgres_date_subtraction(expr: &Expression) -> bool {
4364 let Expression::Sub(op) = expr else {
4365 return false;
4366 };
4367
4368 (Self::is_explicit_date_expr(&op.left) && Self::is_column_expr(&op.right))
4369 || (Self::is_column_expr(&op.left) && Self::is_explicit_date_expr(&op.right))
4370 }
4371
4372 fn is_column_expr(expr: &Expression) -> bool {
4373 match expr {
4374 Expression::Column(_) => true,
4375 Expression::Paren(paren) => Self::is_column_expr(&paren.this),
4376 _ => false,
4377 }
4378 }
4379
4380 fn node_window_frame(expr: &Expression) -> Option<&WindowFrame> {
4381 match expr {
4382 Expression::WindowFunction(window) => window.over.frame.as_ref(),
4383 Expression::Window(window) | Expression::WindowSpec(window) => window.frame.as_ref(),
4384 _ => None,
4385 }
4386 }
4387
4388 fn window_frame_bound_has_value_offset(bound: &WindowFrameBound) -> bool {
4389 matches!(
4390 bound,
4391 WindowFrameBound::Preceding(_)
4392 | WindowFrameBound::Following(_)
4393 | WindowFrameBound::Value(_)
4394 | WindowFrameBound::BarePreceding
4395 | WindowFrameBound::BareFollowing
4396 )
4397 }
4398
4399 fn collect_tsql_windows_missing_order(
4400 expr: &Expression,
4401 active_windows: &HashMap<String, Over>,
4402 diagnostics: &mut Vec<String>,
4403 ) {
4404 if let Expression::Select(select) = expr {
4405 let local_windows = select
4406 .windows
4407 .as_ref()
4408 .map(|windows| {
4409 windows
4410 .iter()
4411 .map(|window| (window.name.name.to_ascii_lowercase(), window.spec.clone()))
4412 .collect()
4413 })
4414 .unwrap_or_default();
4415
4416 for child in expr.children() {
4417 Self::collect_tsql_windows_missing_order(child, &local_windows, diagnostics);
4418 }
4419 return;
4420 }
4421
4422 if let Expression::WindowFunction(window) = expr {
4423 let (has_order, has_frame) = Self::effective_window_order_and_frame(
4424 &window.over,
4425 active_windows,
4426 &mut Vec::new(),
4427 );
4428
4429 if !has_order {
4430 if has_frame {
4431 Self::push_unsupported_diagnostic(
4432 diagnostics,
4433 "window frames without ORDER BY",
4434 );
4435 }
4436 if let Some(function_name) =
4437 Self::tsql_window_function_requiring_order(&window.this)
4438 {
4439 Self::push_unsupported_diagnostic(
4440 diagnostics,
4441 &format!("{function_name} without ORDER BY"),
4442 );
4443 }
4444 }
4445 }
4446
4447 for child in expr.children() {
4448 Self::collect_tsql_windows_missing_order(child, active_windows, diagnostics);
4449 }
4450 }
4451
4452 fn effective_window_order_and_frame(
4453 over: &Over,
4454 active_windows: &HashMap<String, Over>,
4455 seen: &mut Vec<String>,
4456 ) -> (bool, bool) {
4457 let inherited = over
4458 .window_name
4459 .as_ref()
4460 .and_then(|name| {
4461 let key = name.name.to_ascii_lowercase();
4462 if seen.iter().any(|seen_name| seen_name == &key) {
4463 return None;
4464 }
4465 let named = active_windows.get(&key)?;
4466 seen.push(key);
4467 let properties =
4468 Self::effective_window_order_and_frame(named, active_windows, seen);
4469 seen.pop();
4470 Some(properties)
4471 })
4472 .unwrap_or((false, false));
4473
4474 (
4475 !over.order_by.is_empty() || inherited.0,
4476 over.frame.is_some() || inherited.1,
4477 )
4478 }
4479
4480 fn tsql_window_function_requiring_order(expr: &Expression) -> Option<&'static str> {
4481 match expr {
4482 Expression::FirstValue(_) => Some("FIRST_VALUE"),
4483 Expression::LastValue(_) => Some("LAST_VALUE"),
4484 Expression::Function(function) if function.name.eq_ignore_ascii_case("FIRST_VALUE") => {
4485 Some("FIRST_VALUE")
4486 }
4487 Expression::Function(function) if function.name.eq_ignore_ascii_case("LAST_VALUE") => {
4488 Some("LAST_VALUE")
4489 }
4490 _ => None,
4491 }
4492 }
4493
4494 fn collect_tsql_unsupported_ordered_sets(expr: &Expression, diagnostics: &mut Vec<String>) {
4495 match expr {
4496 Expression::WindowFunction(window) => {
4497 if let Expression::WithinGroup(within_group) = &window.this {
4498 if Self::within_group_is_hypothetical_set(within_group) {
4499 Self::push_unsupported_diagnostic(
4500 diagnostics,
4501 "RANK/DENSE_RANK/CUME_DIST/PERCENT_RANK hypothetical-set aggregates",
4502 );
4503 return;
4504 }
4505
4506 if Self::within_group_is_mode(within_group) {
4507 Self::push_unsupported_diagnostic(
4508 diagnostics,
4509 "MODE ordered-set aggregates",
4510 );
4511 return;
4512 }
4513
4514 if Self::within_group_is_percentile(within_group) {
4515 if !window.over.order_by.is_empty() || window.over.frame.is_some() {
4516 Self::push_unsupported_diagnostic(
4517 diagnostics,
4518 "PERCENTILE_CONT/PERCENTILE_DISC window ORDER BY or frame clauses",
4519 );
4520 }
4521 return;
4522 }
4523 }
4524 }
4525 Expression::WithinGroup(within_group) => {
4526 if Self::within_group_is_hypothetical_set(within_group) {
4527 Self::push_unsupported_diagnostic(
4528 diagnostics,
4529 "RANK/DENSE_RANK/CUME_DIST/PERCENT_RANK hypothetical-set aggregates",
4530 );
4531 return;
4532 }
4533
4534 if Self::within_group_is_mode(within_group) {
4535 Self::push_unsupported_diagnostic(diagnostics, "MODE ordered-set aggregates");
4536 return;
4537 }
4538
4539 if Self::within_group_is_percentile(within_group) {
4540 Self::push_unsupported_diagnostic(
4541 diagnostics,
4542 "PERCENTILE_CONT/PERCENTILE_DISC ordered-set aggregates without OVER",
4543 );
4544 return;
4545 }
4546 }
4547 _ => {}
4548 }
4549
4550 for child in expr.children() {
4551 Self::collect_tsql_unsupported_ordered_sets(child, diagnostics);
4552 }
4553 }
4554
4555 fn within_group_is_hypothetical_set(within_group: &crate::expressions::WithinGroup) -> bool {
4556 match &within_group.this {
4557 Expression::Function(function) => Self::is_hypothetical_set_name(&function.name),
4558 Expression::AggregateFunction(function) => {
4559 Self::is_hypothetical_set_name(&function.name)
4560 }
4561 Expression::Rank(_)
4562 | Expression::DenseRank(_)
4563 | Expression::CumeDist(_)
4564 | Expression::PercentRank(_) => true,
4565 _ => false,
4566 }
4567 }
4568
4569 fn within_group_is_percentile(within_group: &crate::expressions::WithinGroup) -> bool {
4570 match &within_group.this {
4571 Expression::Function(function) => Self::is_percentile_ordered_set_name(&function.name),
4572 Expression::AggregateFunction(function) => {
4573 Self::is_percentile_ordered_set_name(&function.name)
4574 }
4575 Expression::PercentileCont(_) | Expression::PercentileDisc(_) => true,
4576 _ => false,
4577 }
4578 }
4579
4580 fn within_group_is_mode(within_group: &crate::expressions::WithinGroup) -> bool {
4581 match &within_group.this {
4582 Expression::Function(function) => function.name.eq_ignore_ascii_case("MODE"),
4583 Expression::AggregateFunction(function) => function.name.eq_ignore_ascii_case("MODE"),
4584 Expression::Mode(_) => true,
4585 _ => false,
4586 }
4587 }
4588
4589 fn is_percentile_ordered_set_name(name: &str) -> bool {
4590 name.eq_ignore_ascii_case("PERCENTILE_CONT") || name.eq_ignore_ascii_case("PERCENTILE_DISC")
4591 }
4592
4593 fn is_hypothetical_set_name(name: &str) -> bool {
4594 name.eq_ignore_ascii_case("RANK")
4595 || name.eq_ignore_ascii_case("DENSE_RANK")
4596 || name.eq_ignore_ascii_case("CUME_DIST")
4597 || name.eq_ignore_ascii_case("PERCENT_RANK")
4598 }
4599
4600 fn target_supports_distinct_on(target: DialectType) -> bool {
4601 matches!(target, DialectType::PostgreSQL | DialectType::DuckDB)
4602 }
4603
4604 fn node_has_distinct_on(expr: &Expression) -> bool {
4605 matches!(
4606 expr,
4607 Expression::Select(select)
4608 if select
4609 .distinct_on
4610 .as_ref()
4611 .is_some_and(|distinct_on| !distinct_on.is_empty())
4612 )
4613 }
4614
4615 fn node_has_recursive_with(expr: &Expression) -> bool {
4616 fn recursive(with: &Option<With>) -> bool {
4617 with.as_ref().is_some_and(|with| with.recursive)
4618 }
4619
4620 match expr {
4621 Expression::With(with) => with.recursive,
4622 Expression::Select(select) => recursive(&select.with),
4623 Expression::Union(union) => recursive(&union.with),
4624 Expression::Intersect(intersect) => recursive(&intersect.with),
4625 Expression::Except(except) => recursive(&except.with),
4626 Expression::Pivot(pivot) => recursive(&pivot.with),
4627 Expression::Insert(insert) => recursive(&insert.with),
4628 Expression::Update(update) => recursive(&update.with),
4629 Expression::Delete(delete) => recursive(&delete.with),
4630 _ => false,
4631 }
4632 }
4633
4634 fn node_has_lateral(expr: &Expression) -> bool {
4635 fn join_has_lateral(join: &Join) -> bool {
4636 matches!(
4637 join.kind,
4638 crate::expressions::JoinKind::Lateral | crate::expressions::JoinKind::LeftLateral
4639 ) || Dialect::node_has_lateral(&join.this)
4640 || join.on.as_ref().is_some_and(Dialect::node_has_lateral)
4641 || join
4642 .match_condition
4643 .as_ref()
4644 .is_some_and(Dialect::node_has_lateral)
4645 || join.pivots.iter().any(Dialect::node_has_lateral)
4646 }
4647
4648 fn joins_have_lateral(joins: &[Join]) -> bool {
4649 joins.iter().any(join_has_lateral)
4650 }
4651
4652 match expr {
4653 Expression::Subquery(subquery) => {
4654 subquery.lateral || Dialect::node_has_lateral(&subquery.this)
4655 }
4656 Expression::Lateral(_) | Expression::LateralView(_) => true,
4657 Expression::Join(join) => join_has_lateral(join),
4658 Expression::Select(select) => {
4659 !select.lateral_views.is_empty()
4660 || joins_have_lateral(&select.joins)
4661 || select
4662 .from
4663 .as_ref()
4664 .is_some_and(|from| from.expressions.iter().any(Dialect::node_has_lateral))
4665 }
4666 Expression::JoinedTable(joined) => {
4667 !joined.lateral_views.is_empty()
4668 || Dialect::node_has_lateral(&joined.left)
4669 || joins_have_lateral(&joined.joins)
4670 }
4671 Expression::Update(update) => {
4672 joins_have_lateral(&update.table_joins) || joins_have_lateral(&update.from_joins)
4673 }
4674 _ => false,
4675 }
4676 }
4677
4678 fn node_has_join_using(expr: &Expression) -> bool {
4679 fn has_using(joins: &[Join]) -> bool {
4680 joins.iter().any(|join| !join.using.is_empty())
4681 }
4682
4683 match expr {
4684 Expression::Join(join) => !join.using.is_empty(),
4685 Expression::Select(select) => has_using(&select.joins),
4686 Expression::JoinedTable(joined) => has_using(&joined.joins),
4687 Expression::Update(update) => {
4688 has_using(&update.table_joins) || has_using(&update.from_joins)
4689 }
4690 Expression::Delete(delete) => has_using(&delete.joins),
4691 _ => false,
4692 }
4693 }
4694
4695 fn node_has_natural_join(expr: &Expression) -> bool {
4696 fn is_natural(join: &Join) -> bool {
4697 matches!(
4698 join.kind,
4699 crate::expressions::JoinKind::Natural
4700 | crate::expressions::JoinKind::NaturalLeft
4701 | crate::expressions::JoinKind::NaturalRight
4702 | crate::expressions::JoinKind::NaturalFull
4703 )
4704 }
4705
4706 fn has_natural(joins: &[Join]) -> bool {
4707 joins.iter().any(is_natural)
4708 }
4709
4710 match expr {
4711 Expression::Join(join) => is_natural(join),
4712 Expression::Select(select) => has_natural(&select.joins),
4713 Expression::JoinedTable(joined) => has_natural(&joined.joins),
4714 Expression::Update(update) => {
4715 has_natural(&update.table_joins) || has_natural(&update.from_joins)
4716 }
4717 Expression::Delete(delete) => has_natural(&delete.joins),
4718 _ => false,
4719 }
4720 }
4721
4722 fn node_has_unsupported_relation_column_aliases(expr: &Expression) -> bool {
4723 match expr {
4724 Expression::Table(table) => !table.column_aliases.is_empty(),
4725 Expression::Alias(alias) => {
4726 !alias.column_aliases.is_empty()
4727 && matches!(
4728 alias.this,
4729 Expression::Table(_) | Expression::JoinedTable(_)
4730 )
4731 }
4732 _ => false,
4733 }
4734 }
4735
4736 fn node_has_qualified_whole_row_aggregate_argument(expr: &Expression) -> bool {
4737 fn contains_qualified_star(expr: &Expression) -> bool {
4738 match expr {
4739 Expression::Star(star) => star.table.is_some(),
4740 Expression::Select(_)
4743 | Expression::Subquery(_)
4744 | Expression::Union(_)
4745 | Expression::Intersect(_)
4746 | Expression::Except(_) => false,
4747 _ => expr.children().into_iter().any(contains_qualified_star),
4748 }
4749 }
4750
4751 let is_aggregate = matches!(
4752 expr,
4753 Expression::AggregateFunction(_)
4754 | Expression::Count(_)
4755 | Expression::Sum(_)
4756 | Expression::Avg(_)
4757 | Expression::Min(_)
4758 | Expression::Max(_)
4759 | Expression::GroupConcat(_)
4760 | Expression::StringAgg(_)
4761 | Expression::ListAgg(_)
4762 | Expression::ArrayAgg(_)
4763 | Expression::CountIf(_)
4764 | Expression::SumIf(_)
4765 | Expression::Stddev(_)
4766 | Expression::StddevPop(_)
4767 | Expression::StddevSamp(_)
4768 | Expression::Variance(_)
4769 | Expression::VarPop(_)
4770 | Expression::VarSamp(_)
4771 | Expression::Median(_)
4772 | Expression::Mode(_)
4773 | Expression::First(_)
4774 | Expression::Last(_)
4775 | Expression::AnyValue(_)
4776 | Expression::ApproxDistinct(_)
4777 | Expression::ApproxCountDistinct(_)
4778 | Expression::ApproxPercentile(_)
4779 | Expression::Percentile(_)
4780 | Expression::LogicalAnd(_)
4781 | Expression::LogicalOr(_)
4782 | Expression::Skewness(_)
4783 | Expression::BitwiseCount(_)
4784 | Expression::BitwiseAndAgg(_)
4785 | Expression::BitwiseOrAgg(_)
4786 | Expression::BitwiseXorAgg(_)
4787 | Expression::ArrayConcatAgg(_)
4788 | Expression::ArrayUniqueAgg(_)
4789 | Expression::BoolXorAgg(_)
4790 | Expression::JsonArrayAgg(_)
4791 | Expression::JsonObjectAgg(_)
4792 | Expression::ParameterizedAgg(_)
4793 | Expression::ArgMax(_)
4794 | Expression::ArgMin(_)
4795 | Expression::ApproxTopK(_)
4796 | Expression::ApproxTopKAccumulate(_)
4797 | Expression::ApproxTopKCombine(_)
4798 | Expression::ApproxTopKEstimate(_)
4799 | Expression::ApproxTopSum(_)
4800 | Expression::ApproxQuantiles(_)
4801 | Expression::AnonymousAggFunc(_)
4802 | Expression::CombinedAggFunc(_)
4803 | Expression::CombinedParameterizedAgg(_)
4804 | Expression::HashAgg(_)
4805 | Expression::ObjectAgg(_)
4806 | Expression::AIAgg(_)
4807 );
4808
4809 is_aggregate && expr.children().into_iter().any(contains_qualified_star)
4810 }
4811
4812 fn target_supports_remaining_unnest(target: DialectType) -> bool {
4813 matches!(
4814 target,
4815 DialectType::PostgreSQL
4816 | DialectType::BigQuery
4817 | DialectType::DuckDB
4818 | DialectType::Presto
4819 | DialectType::Trino
4820 | DialectType::Athena
4821 )
4822 }
4823
4824 fn target_supports_remaining_explode(target: DialectType) -> bool {
4825 matches!(
4826 target,
4827 DialectType::Spark | DialectType::Databricks | DialectType::Hive
4828 )
4829 }
4830
4831 fn target_lacks_array_agg(target: DialectType) -> bool {
4832 matches!(
4833 target,
4834 DialectType::Fabric
4835 | DialectType::TSQL
4836 | DialectType::MySQL
4837 | DialectType::SQLite
4838 | DialectType::Oracle
4839 )
4840 }
4841
4842 fn node_is_unnest(expr: &Expression) -> bool {
4843 matches!(expr, Expression::Unnest(_)) || Self::node_is_function_named(expr, "UNNEST")
4844 }
4845
4846 fn node_is_explode(expr: &Expression) -> bool {
4847 matches!(expr, Expression::Explode(_) | Expression::ExplodeOuter(_))
4848 || Self::node_is_function_named(expr, "EXPLODE")
4849 || Self::node_is_function_named(expr, "EXPLODE_OUTER")
4850 }
4851
4852 fn node_is_array_agg(expr: &Expression) -> bool {
4853 matches!(expr, Expression::ArrayAgg(_)) || Self::node_is_function_named(expr, "ARRAY_AGG")
4854 }
4855
4856 fn node_is_distinct_string_agg(expr: &Expression) -> bool {
4857 match expr {
4858 Expression::StringAgg(agg) => agg.distinct,
4859 Expression::Function(function) => {
4860 function.distinct && function.name.eq_ignore_ascii_case("STRING_AGG")
4861 }
4862 Expression::AggregateFunction(function) => {
4863 function.distinct && function.name.eq_ignore_ascii_case("STRING_AGG")
4864 }
4865 _ => false,
4866 }
4867 }
4868
4869 fn postgres_tsql_unsupported_collation_name(expr: &Expression) -> Option<&'static str> {
4870 let Expression::Collation(collation) = expr else {
4871 return None;
4872 };
4873
4874 if collation.collation.eq_ignore_ascii_case("C") {
4875 Some("C")
4876 } else if collation.collation.eq_ignore_ascii_case("POSIX") {
4877 Some("POSIX")
4878 } else {
4879 None
4880 }
4881 }
4882
4883 fn postgres_tsql_unsupported_array_semantics(expr: &Expression) -> Option<&'static str> {
4884 match expr {
4885 Expression::Array(_) | Expression::ArrayFunc(_) => Some("array literals"),
4886 Expression::Subscript(_) => Some("array subscripts"),
4887 Expression::ArraySlice(_) => Some("array slices"),
4888 Expression::DataType(DataType::Array { .. }) => Some("array data types"),
4889 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast)
4890 if matches!(&cast.to, DataType::Array { .. }) =>
4891 {
4892 Some("array data types")
4893 }
4894 Expression::ArrayLength(_) | Expression::ArraySize(_) => Some("ARRAY_LENGTH"),
4895 Expression::Cardinality(_) => Some("CARDINALITY"),
4896 Expression::ArrayToString(_) | Expression::ArrayJoin(_) => Some("ARRAY_TO_STRING"),
4897 Expression::StringToArray(_) => Some("STRING_TO_ARRAY"),
4898 Expression::ArrayContains(_)
4899 | Expression::ArrayPosition(_)
4900 | Expression::ArrayAppend(_)
4901 | Expression::ArrayPrepend(_)
4902 | Expression::ArrayConcat(_)
4903 | Expression::ArraySort(_)
4904 | Expression::ArrayReverse(_)
4905 | Expression::ArrayDistinct(_)
4906 | Expression::ArrayFilter(_)
4907 | Expression::ArrayTransform(_)
4908 | Expression::ArrayFlatten(_)
4909 | Expression::ArrayCompact(_)
4910 | Expression::ArrayIntersect(_)
4911 | Expression::ArrayUnion(_)
4912 | Expression::ArrayExcept(_)
4913 | Expression::ArrayRemove(_)
4914 | Expression::ArrayZip(_)
4915 | Expression::ArrayAll(_)
4916 | Expression::ArrayAny(_)
4917 | Expression::ArrayConstructCompact(_)
4918 | Expression::ArraySum(_) => Some("array functions"),
4919 Expression::ArrayContainsAll(_)
4920 | Expression::ArrayContainedBy(_)
4921 | Expression::ArrayOverlaps(_) => Some("array operators"),
4922 Expression::Function(function) => {
4923 Self::postgres_tsql_unsupported_array_function_name_str(&function.name)
4924 }
4925 Expression::AggregateFunction(function) => {
4926 Self::postgres_tsql_unsupported_array_function_name_str(&function.name)
4927 }
4928 _ => None,
4929 }
4930 }
4931
4932 fn postgres_tsql_unsupported_array_function_name_str(name: &str) -> Option<&'static str> {
4933 if name.eq_ignore_ascii_case("ARRAY") {
4934 Some("array literals")
4935 } else if name.eq_ignore_ascii_case("ARRAY_LENGTH")
4936 || name.eq_ignore_ascii_case("ARRAY_SIZE")
4937 {
4938 Some("ARRAY_LENGTH")
4939 } else if name.eq_ignore_ascii_case("CARDINALITY") {
4940 Some("CARDINALITY")
4941 } else if name.eq_ignore_ascii_case("ARRAY_TO_STRING")
4942 || name.eq_ignore_ascii_case("ARRAY_JOIN")
4943 {
4944 Some("ARRAY_TO_STRING")
4945 } else if name.eq_ignore_ascii_case("STRING_TO_ARRAY") {
4946 Some("STRING_TO_ARRAY")
4947 } else {
4948 None
4949 }
4950 }
4951
4952 fn node_is_regex_predicate(expr: &Expression) -> bool {
4953 matches!(
4954 expr,
4955 Expression::SimilarTo(_) | Expression::RegexpLike(_) | Expression::RegexpILike(_)
4956 ) || Self::node_is_function_named(expr, "REGEXP_LIKE")
4957 || Self::node_is_function_named(expr, "REGEXP_I_LIKE")
4958 || Self::node_is_function_named(expr, "REGEXP_ILIKE")
4959 }
4960
4961 fn node_is_non_subquery_any(expr: &Expression) -> bool {
4962 matches!(
4963 expr,
4964 Expression::Any(q) if !Self::quantified_rhs_is_subquery(&q.subquery)
4965 )
4966 }
4967
4968 fn quantified_rhs_is_subquery(expr: &Expression) -> bool {
4969 match expr {
4970 Expression::Select(_) | Expression::Subquery(_) => true,
4971 Expression::Paren(paren) => Self::quantified_rhs_is_subquery(&paren.this),
4972 _ => false,
4973 }
4974 }
4975
4976 fn node_is_row_value_subquery_comparison(expr: &Expression) -> bool {
4977 match expr {
4978 Expression::In(in_expr) => {
4979 Self::in_rhs_is_subquery_like(in_expr) && Self::expr_is_row_value(&in_expr.this)
4980 }
4981 Expression::Eq(op) | Expression::Neq(op) => {
4982 (Self::expr_is_row_value(&op.left) && Self::expr_is_subquery_like(&op.right))
4983 || (Self::expr_is_row_value(&op.right) && Self::expr_is_subquery_like(&op.left))
4984 }
4985 _ => false,
4986 }
4987 }
4988
4989 fn node_is_row_value_values_membership(expr: &Expression) -> bool {
4990 matches!(
4991 expr,
4992 Expression::In(in_expr)
4993 if Self::expr_is_row_value(&in_expr.this)
4994 && Self::in_rhs_is_values_like(in_expr)
4995 )
4996 }
4997
4998 fn expr_is_row_value(expr: &Expression) -> bool {
4999 match expr {
5000 Expression::Tuple(tuple) => tuple.expressions.len() > 1,
5001 Expression::Function(function) if function.name.eq_ignore_ascii_case("ROW") => {
5002 function.args.len() > 1
5003 }
5004 Expression::Paren(paren) => Self::expr_is_row_value(&paren.this),
5005 _ => false,
5006 }
5007 }
5008
5009 fn expr_is_subquery_like(expr: &Expression) -> bool {
5010 match expr {
5011 Expression::Select(_) | Expression::Subquery(_) => true,
5012 Expression::Paren(paren) => Self::expr_is_subquery_like(&paren.this),
5013 _ => false,
5014 }
5015 }
5016
5017 fn in_rhs_is_subquery_like(in_expr: &crate::expressions::In) -> bool {
5018 if in_expr
5019 .query
5020 .as_ref()
5021 .is_some_and(Self::expr_is_subquery_like)
5022 {
5023 return true;
5024 }
5025
5026 in_expr.expressions.len() == 1 && Self::expr_is_subquery_like(&in_expr.expressions[0])
5027 }
5028
5029 fn in_rhs_is_values_like(in_expr: &crate::expressions::In) -> bool {
5030 if in_expr
5031 .query
5032 .as_ref()
5033 .is_some_and(Self::expr_is_values_like)
5034 {
5035 return true;
5036 }
5037
5038 (in_expr.expressions.len() == 1
5039 && Self::expr_is_values_like(&in_expr.expressions[0]))
5040 || in_expr.expressions.first().is_some_and(|expr| {
5041 matches!(expr, Expression::Function(function) if function.name.eq_ignore_ascii_case("VALUES"))
5042 })
5043 }
5044
5045 fn expr_is_values_like(expr: &Expression) -> bool {
5046 match expr {
5047 Expression::Values(_) => true,
5048 Expression::Paren(paren) => Self::expr_is_values_like(&paren.this),
5049 Expression::Subquery(subquery) => Self::expr_is_values_like(&subquery.this),
5050 _ => false,
5051 }
5052 }
5053
5054 fn normalize_tsql_fetch_overlaps_date_bin(expr: Expression) -> Result<Expression> {
5055 transform_recursive(expr, &|e| match e {
5056 Expression::Select(mut select) => {
5057 if select.top.is_none() && select.offset.is_none() {
5058 if let Some(fetch) = select.fetch.take() {
5059 if let Some(top) = Self::fetch_with_ties_to_top(fetch.clone()) {
5060 select.top = Some(top);
5061 } else {
5062 select.fetch = Some(fetch);
5063 }
5064 }
5065 }
5066 Self::rewrite_tsql_overlaps_in_select_predicates(&mut select)?;
5067 Ok(Expression::Select(select))
5068 }
5069 Expression::DateBin(date_bin) => {
5070 let date_bin = *date_bin;
5071 if let Some(rewritten) = Self::date_bin_to_date_bucket(date_bin.clone()) {
5072 Ok(rewritten)
5073 } else {
5074 Ok(Expression::DateBin(Box::new(date_bin)))
5075 }
5076 }
5077 Expression::Function(function) => {
5078 let function = *function;
5079 if function.name.eq_ignore_ascii_case("DATE_BIN") {
5080 if let Some(rewritten) = Self::date_bin_function_to_date_bucket(&function) {
5081 Ok(rewritten)
5082 } else {
5083 Ok(Expression::Function(Box::new(function)))
5084 }
5085 } else {
5086 Ok(Expression::Function(Box::new(function)))
5087 }
5088 }
5089 _ => Ok(e),
5090 })
5091 }
5092
5093 fn rewrite_tsql_overlaps_in_select_predicates(
5094 select: &mut crate::expressions::Select,
5095 ) -> Result<()> {
5096 if let Some(where_clause) = &mut select.where_clause {
5097 where_clause.this = Self::rewrite_tsql_overlaps_predicate(where_clause.this.clone())?;
5098 }
5099 if let Some(having) = &mut select.having {
5100 having.this = Self::rewrite_tsql_overlaps_predicate(having.this.clone())?;
5101 }
5102 if let Some(qualify) = &mut select.qualify {
5103 qualify.this = Self::rewrite_tsql_overlaps_predicate(qualify.this.clone())?;
5104 }
5105 for join in &mut select.joins {
5106 if let Some(on) = join.on.take() {
5107 join.on = Some(Self::rewrite_tsql_overlaps_predicate(on)?);
5108 }
5109 if let Some(match_condition) = join.match_condition.take() {
5110 join.match_condition =
5111 Some(Self::rewrite_tsql_overlaps_predicate(match_condition)?);
5112 }
5113 }
5114 Ok(())
5115 }
5116
5117 fn rewrite_tsql_overlaps_predicate(expr: Expression) -> Result<Expression> {
5118 transform_recursive(expr, &|e| match e {
5119 Expression::Overlaps(overlaps) => {
5120 let overlaps = *overlaps;
5121 if let Some(rewritten) = Self::rewrite_full_overlaps_for_tsql(&overlaps) {
5122 Ok(rewritten)
5123 } else {
5124 Ok(Expression::Overlaps(Box::new(overlaps)))
5125 }
5126 }
5127 _ => Ok(e),
5128 })
5129 }
5130
5131 fn fetch_with_ties_to_top(fetch: Fetch) -> Option<Top> {
5132 if !fetch.with_ties {
5133 return None;
5134 }
5135
5136 fetch.count.map(|count| Top {
5137 this: count,
5138 percent: fetch.percent,
5139 with_ties: true,
5140 parenthesized: true,
5141 })
5142 }
5143
5144 fn rewrite_full_overlaps_for_tsql(
5145 overlaps: &crate::expressions::OverlapsExpr,
5146 ) -> Option<Expression> {
5147 let (left_start, left_end, right_start, right_end) =
5148 if let (Some(left_start), Some(left_end), Some(right_start), Some(right_end)) = (
5149 overlaps.left_start.as_ref(),
5150 overlaps.left_end.as_ref(),
5151 overlaps.right_start.as_ref(),
5152 overlaps.right_end.as_ref(),
5153 ) {
5154 (left_start, left_end, right_start, right_end)
5155 } else if let (
5156 Some(Expression::Tuple(left_tuple)),
5157 Some(Expression::Tuple(right_tuple)),
5158 ) = (&overlaps.this, &overlaps.expression)
5159 {
5160 if left_tuple.expressions.len() != 2 || right_tuple.expressions.len() != 2 {
5161 return None;
5162 }
5163 (
5164 &left_tuple.expressions[0],
5165 &left_tuple.expressions[1],
5166 &right_tuple.expressions[0],
5167 &right_tuple.expressions[1],
5168 )
5169 } else {
5170 return None;
5171 };
5172
5173 let left_min = Self::case_min(left_start.clone(), left_end.clone());
5174 let left_max = Self::case_max(left_start.clone(), left_end.clone());
5175 let right_min = Self::case_min(right_start.clone(), right_end.clone());
5176 let right_max = Self::case_max(right_start.clone(), right_end.clone());
5177
5178 Some(Expression::And(Box::new(BinaryOp::new(
5179 Expression::Lte(Box::new(BinaryOp::new(left_min, right_max))),
5180 Expression::Lte(Box::new(BinaryOp::new(right_min, left_max))),
5181 ))))
5182 }
5183
5184 fn case_min(left: Expression, right: Expression) -> Expression {
5185 Expression::Case(Box::new(Case {
5186 operand: None,
5187 whens: vec![(
5188 Expression::Lte(Box::new(BinaryOp::new(left.clone(), right.clone()))),
5189 left,
5190 )],
5191 else_: Some(right),
5192 comments: Vec::new(),
5193 inferred_type: None,
5194 }))
5195 }
5196
5197 fn case_max(left: Expression, right: Expression) -> Expression {
5198 Expression::Case(Box::new(Case {
5199 operand: None,
5200 whens: vec![(
5201 Expression::Gte(Box::new(BinaryOp::new(left.clone(), right.clone()))),
5202 left,
5203 )],
5204 else_: Some(right),
5205 comments: Vec::new(),
5206 inferred_type: None,
5207 }))
5208 }
5209
5210 fn date_bin_to_date_bucket(date_bin: DateBin) -> Option<Expression> {
5211 if date_bin.unit.is_some() || date_bin.zone.is_some() {
5212 return None;
5213 }
5214
5215 let (datepart, number) = Self::date_bucket_parts(&date_bin.this)?;
5216 let mut args = vec![
5217 Self::date_bucket_datepart(datepart),
5218 number,
5219 *date_bin.expression,
5220 ];
5221 if let Some(origin) = date_bin.origin {
5222 args.push(*origin);
5223 }
5224
5225 Some(Expression::Function(Box::new(Function::new(
5226 "DATE_BUCKET".to_string(),
5227 args,
5228 ))))
5229 }
5230
5231 fn date_bin_function_to_date_bucket(function: &Function) -> Option<Expression> {
5232 if !(2..=3).contains(&function.args.len()) {
5233 return None;
5234 }
5235
5236 let (datepart, number) = Self::date_bucket_parts(&function.args[0])?;
5237 let mut args = vec![
5238 Self::date_bucket_datepart(datepart),
5239 number,
5240 function.args[1].clone(),
5241 ];
5242 if let Some(origin) = function.args.get(2) {
5243 args.push(origin.clone());
5244 }
5245
5246 Some(Expression::Function(Box::new(Function::new(
5247 "DATE_BUCKET".to_string(),
5248 args,
5249 ))))
5250 }
5251
5252 fn date_bucket_parts(stride: &Expression) -> Option<(&'static str, Expression)> {
5253 match stride {
5254 Expression::Literal(lit) => match lit.as_ref() {
5255 Literal::String(value) => Self::date_bucket_parts_from_string(value),
5256 _ => None,
5257 },
5258 Expression::Interval(interval) => Self::date_bucket_parts_from_interval(interval),
5259 _ => None,
5260 }
5261 }
5262
5263 fn date_bucket_parts_from_interval(interval: &Interval) -> Option<(&'static str, Expression)> {
5264 match &interval.unit {
5265 Some(IntervalUnitSpec::Simple { unit, .. }) => {
5266 let datepart = Self::date_bucket_datepart_from_unit(*unit)?;
5267 let amount = interval
5268 .this
5269 .as_ref()
5270 .and_then(Self::date_bucket_amount_expr)?;
5271 Some((datepart, amount))
5272 }
5273 None => interval.this.as_ref().and_then(|expr| match expr {
5274 Expression::Literal(lit) => match lit.as_ref() {
5275 Literal::String(value) => Self::date_bucket_parts_from_string(value),
5276 _ => None,
5277 },
5278 _ => None,
5279 }),
5280 _ => None,
5281 }
5282 }
5283
5284 fn date_bucket_parts_from_string(value: &str) -> Option<(&'static str, Expression)> {
5285 let mut parts = value.split_whitespace();
5286 let amount = parts.next()?;
5287 let unit = parts.next()?;
5288 if parts.next().is_some() {
5289 return None;
5290 }
5291
5292 Some((
5293 Self::date_bucket_datepart_from_name(unit)?,
5294 Self::positive_integer_expr(amount)?,
5295 ))
5296 }
5297
5298 fn date_bucket_amount_expr(expr: &Expression) -> Option<Expression> {
5299 match expr {
5300 Expression::Literal(lit) => match lit.as_ref() {
5301 Literal::Number(value) => Self::positive_integer_expr(value),
5302 Literal::String(value) => Self::positive_integer_expr(value),
5303 _ => None,
5304 },
5305 _ => Some(expr.clone()),
5306 }
5307 }
5308
5309 fn positive_integer_expr(value: &str) -> Option<Expression> {
5310 let parsed = value.trim().parse::<i64>().ok()?;
5311 (parsed > 0).then(|| Expression::number(parsed))
5312 }
5313
5314 fn date_bucket_datepart(datepart: &str) -> Expression {
5315 Expression::Var(Box::new(Var {
5316 this: datepart.to_string(),
5317 }))
5318 }
5319
5320 fn date_bucket_datepart_from_unit(unit: IntervalUnit) -> Option<&'static str> {
5321 match unit {
5322 IntervalUnit::Week => Some("WEEK"),
5323 IntervalUnit::Day => Some("DAY"),
5324 IntervalUnit::Hour => Some("HOUR"),
5325 IntervalUnit::Minute => Some("MINUTE"),
5326 IntervalUnit::Second => Some("SECOND"),
5327 IntervalUnit::Millisecond => Some("MILLISECOND"),
5328 _ => None,
5329 }
5330 }
5331
5332 fn date_bucket_datepart_from_name(unit: &str) -> Option<&'static str> {
5333 match unit.trim().to_ascii_uppercase().as_str() {
5334 "WEEK" | "WEEKS" | "W" | "WK" | "WKS" | "WW" => Some("WEEK"),
5335 "DAY" | "DAYS" | "D" | "DD" => Some("DAY"),
5336 "HOUR" | "HOURS" | "H" | "HH" | "HR" | "HRS" => Some("HOUR"),
5337 "MINUTE" | "MINUTES" | "MI" | "MIN" | "MINS" | "N" => Some("MINUTE"),
5338 "SECOND" | "SECONDS" | "S" | "SEC" | "SECS" | "SS" => Some("SECOND"),
5339 "MILLISECOND" | "MILLISECONDS" | "MS" | "MSEC" | "MSECS" | "MILLISEC" | "MILLISECS" => {
5340 Some("MILLISECOND")
5341 }
5342 _ => None,
5343 }
5344 }
5345
5346 fn node_has_fetch_with_ties(expr: &Expression) -> bool {
5347 matches!(
5348 expr,
5349 Expression::Select(select)
5350 if select
5351 .fetch
5352 .as_ref()
5353 .is_some_and(|fetch| fetch.with_ties)
5354 )
5355 }
5356
5357 fn node_is_overlaps(expr: &Expression) -> bool {
5358 matches!(expr, Expression::Overlaps(_))
5359 }
5360
5361 fn node_is_date_bin(expr: &Expression) -> bool {
5362 matches!(expr, Expression::DateBin(_)) || Self::node_is_function_named(expr, "DATE_BIN")
5363 }
5364
5365 fn node_is_function_named(expr: &Expression, name: &str) -> bool {
5366 match expr {
5367 Expression::Function(function) => function.name.eq_ignore_ascii_case(name),
5368 Expression::AggregateFunction(function) => function.name.eq_ignore_ascii_case(name),
5369 _ => false,
5370 }
5371 }
5372
5373 fn node_is_postgres_json_build_object(expr: &Expression) -> bool {
5374 match expr {
5375 Expression::Function(function) => {
5376 function.name.eq_ignore_ascii_case("JSON_BUILD_OBJECT")
5377 || function.name.eq_ignore_ascii_case("JSONB_BUILD_OBJECT")
5378 }
5379 _ => false,
5380 }
5381 }
5382
5383 fn postgres_json_build_object_can_lower_to_json_object(expr: &Expression) -> bool {
5384 matches!(
5385 expr,
5386 Expression::Function(function)
5387 if (function.name.eq_ignore_ascii_case("JSON_BUILD_OBJECT")
5388 || function.name.eq_ignore_ascii_case("JSONB_BUILD_OBJECT"))
5389 && !function.distinct
5390 && function.args.len() % 2 == 0
5391 )
5392 }
5393
5394 fn node_is_postgres_json_array_elements(expr: &Expression) -> bool {
5395 matches!(
5396 expr,
5397 Expression::Function(function)
5398 if function.name.eq_ignore_ascii_case("JSON_ARRAY_ELEMENTS")
5399 || function.name.eq_ignore_ascii_case("JSONB_ARRAY_ELEMENTS")
5400 || function.name.eq_ignore_ascii_case("JSON_ARRAY_ELEMENTS_TEXT")
5401 || function.name.eq_ignore_ascii_case("JSONB_ARRAY_ELEMENTS_TEXT")
5402 )
5403 }
5404
5405 fn postgres_tsql_unsupported_function_name(expr: &Expression) -> Option<&'static str> {
5406 match expr {
5407 Expression::Lpad(_) => Some("LPAD"),
5408 Expression::Rpad(_) => Some("RPAD"),
5409 Expression::SplitPart(_) => Some("SPLIT_PART"),
5410 Expression::Initcap(_) => Some("INITCAP"),
5411 Expression::ToJson(_) => Some("TO_JSON"),
5412 Expression::JSONBObjectAgg(_) => Some("JSONB_OBJECT_AGG"),
5413 Expression::ToNumber(_) => Some("TO_NUMBER"),
5414 Expression::WidthBucket(_) => Some("WIDTH_BUCKET"),
5415 Expression::BitwiseAndAgg(_) => Some("BIT_AND"),
5416 Expression::BitwiseOrAgg(_) => Some("BIT_OR"),
5417 Expression::BitwiseXorAgg(_) => Some("BIT_XOR"),
5418 Expression::Corr(_) => Some("CORR"),
5419 Expression::CovarPop(_) => Some("COVAR_POP"),
5420 Expression::CovarSamp(_) => Some("COVAR_SAMP"),
5421 Expression::RegrAvgx(_) => Some("REGR_AVGX"),
5422 Expression::RegrAvgy(_) => Some("REGR_AVGY"),
5423 Expression::RegrCount(_) => Some("REGR_COUNT"),
5424 Expression::RegrIntercept(_) => Some("REGR_INTERCEPT"),
5425 Expression::RegrR2(_) => Some("REGR_R2"),
5426 Expression::RegrSlope(_) => Some("REGR_SLOPE"),
5427 Expression::RegrSxx(_) => Some("REGR_SXX"),
5428 Expression::RegrSxy(_) => Some("REGR_SXY"),
5429 Expression::RegrSyy(_) => Some("REGR_SYY"),
5430 Expression::Function(function) => {
5431 Self::postgres_tsql_unsupported_function_name_str(&function.name)
5432 }
5433 Expression::AggregateFunction(function) => {
5434 Self::postgres_tsql_unsupported_function_name_str(&function.name)
5435 }
5436 _ => None,
5437 }
5438 }
5439
5440 fn postgres_tsql_unsupported_function_name_str(name: &str) -> Option<&'static str> {
5441 if name.eq_ignore_ascii_case("LPAD") {
5442 Some("LPAD")
5443 } else if name.eq_ignore_ascii_case("RPAD") {
5444 Some("RPAD")
5445 } else if name.eq_ignore_ascii_case("SPLIT_PART") {
5446 Some("SPLIT_PART")
5447 } else if name.eq_ignore_ascii_case("INITCAP") {
5448 Some("INITCAP")
5449 } else if name.eq_ignore_ascii_case("TO_JSON") {
5450 Some("TO_JSON")
5451 } else if name.eq_ignore_ascii_case("TO_JSONB") {
5452 Some("TO_JSONB")
5453 } else if name.eq_ignore_ascii_case("JSONB_OBJECT_AGG") {
5454 Some("JSONB_OBJECT_AGG")
5455 } else if name.eq_ignore_ascii_case("ROW_TO_JSON") {
5456 Some("ROW_TO_JSON")
5457 } else if name.eq_ignore_ascii_case("JSON_ARRAY_ELEMENTS") {
5458 Some("JSON_ARRAY_ELEMENTS")
5459 } else if name.eq_ignore_ascii_case("JSONB_ARRAY_ELEMENTS") {
5460 Some("JSONB_ARRAY_ELEMENTS")
5461 } else if name.eq_ignore_ascii_case("JSON_ARRAY_ELEMENTS_TEXT") {
5462 Some("JSON_ARRAY_ELEMENTS_TEXT")
5463 } else if name.eq_ignore_ascii_case("JSONB_ARRAY_ELEMENTS_TEXT") {
5464 Some("JSONB_ARRAY_ELEMENTS_TEXT")
5465 } else if name.eq_ignore_ascii_case("ENCODE") {
5466 Some("ENCODE")
5467 } else if name.eq_ignore_ascii_case("AGE") {
5468 Some("AGE")
5469 } else if name.eq_ignore_ascii_case("ERF") {
5470 Some("ERF")
5471 } else if name.eq_ignore_ascii_case("GCD") {
5472 Some("GCD")
5473 } else if name.eq_ignore_ascii_case("LCM") {
5474 Some("LCM")
5475 } else if name.eq_ignore_ascii_case("QUOTE_LITERAL") {
5476 Some("QUOTE_LITERAL")
5477 } else if name.eq_ignore_ascii_case("WIDTH_BUCKET") {
5478 Some("WIDTH_BUCKET")
5479 } else if name.eq_ignore_ascii_case("SCALE") {
5480 Some("SCALE")
5481 } else if name.eq_ignore_ascii_case("TRIM_SCALE") {
5482 Some("TRIM_SCALE")
5483 } else if name.eq_ignore_ascii_case("MIN_SCALE") {
5484 Some("MIN_SCALE")
5485 } else if name.eq_ignore_ascii_case("FACTORIAL") {
5486 Some("FACTORIAL")
5487 } else if name.eq_ignore_ascii_case("PG_LSN") {
5488 Some("PG_LSN")
5489 } else if name.eq_ignore_ascii_case("TO_CHAR") {
5490 Some("TO_CHAR")
5491 } else if name.eq_ignore_ascii_case("PG_TYPEOF") {
5492 Some("PG_TYPEOF")
5493 } else if name.eq_ignore_ascii_case("BIT_AND") {
5494 Some("BIT_AND")
5495 } else if name.eq_ignore_ascii_case("BIT_OR") {
5496 Some("BIT_OR")
5497 } else if name.eq_ignore_ascii_case("BIT_XOR") {
5498 Some("BIT_XOR")
5499 } else if name.eq_ignore_ascii_case("CORR") {
5500 Some("CORR")
5501 } else if name.eq_ignore_ascii_case("COVAR_POP") {
5502 Some("COVAR_POP")
5503 } else if name.eq_ignore_ascii_case("COVAR_SAMP") {
5504 Some("COVAR_SAMP")
5505 } else if name.eq_ignore_ascii_case("REGR_AVGX") {
5506 Some("REGR_AVGX")
5507 } else if name.eq_ignore_ascii_case("REGR_AVGY") {
5508 Some("REGR_AVGY")
5509 } else if name.eq_ignore_ascii_case("REGR_COUNT") {
5510 Some("REGR_COUNT")
5511 } else if name.eq_ignore_ascii_case("REGR_INTERCEPT") {
5512 Some("REGR_INTERCEPT")
5513 } else if name.eq_ignore_ascii_case("REGR_R2") {
5514 Some("REGR_R2")
5515 } else if name.eq_ignore_ascii_case("REGR_SLOPE") {
5516 Some("REGR_SLOPE")
5517 } else if name.eq_ignore_ascii_case("REGR_SXX") {
5518 Some("REGR_SXX")
5519 } else if name.eq_ignore_ascii_case("REGR_SXY") {
5520 Some("REGR_SXY")
5521 } else if name.eq_ignore_ascii_case("REGR_SYY") {
5522 Some("REGR_SYY")
5523 } else if name.eq_ignore_ascii_case("FLOAT8_ACCUM") {
5524 Some("FLOAT8_ACCUM")
5525 } else if name.eq_ignore_ascii_case("FLOAT8_REGR_ACCUM") {
5526 Some("FLOAT8_REGR_ACCUM")
5527 } else if name.eq_ignore_ascii_case("FLOAT8_COMBINE") {
5528 Some("FLOAT8_COMBINE")
5529 } else if name.eq_ignore_ascii_case("FLOAT8_REGR_COMBINE") {
5530 Some("FLOAT8_REGR_COMBINE")
5531 } else if name.eq_ignore_ascii_case("BOOLAND_STATEFUNC") {
5532 Some("BOOLAND_STATEFUNC")
5533 } else if name.eq_ignore_ascii_case("BOOLOR_STATEFUNC") {
5534 Some("BOOLOR_STATEFUNC")
5535 } else {
5536 None
5537 }
5538 }
5539
5540 fn normalize_postgres_trim_for_tsql(expr: Expression) -> Result<Expression> {
5541 transform_recursive(expr, &|e| match e {
5542 Expression::Trim(trim) => {
5543 let mut trim = *trim;
5544 match trim.position {
5545 crate::expressions::TrimPosition::Both
5546 if trim.position_explicit && trim.characters.is_some() =>
5547 {
5548 trim.position_explicit = false;
5549 trim.sql_standard_syntax = true;
5550 Ok(Expression::Trim(Box::new(trim)))
5551 }
5552 crate::expressions::TrimPosition::Leading if trim.characters.is_some() => {
5553 let characters = trim.characters.take().expect("checked above");
5554 Ok(Expression::Function(Box::new(Function::new(
5555 "LTRIM",
5556 vec![trim.this, characters],
5557 ))))
5558 }
5559 crate::expressions::TrimPosition::Trailing if trim.characters.is_some() => {
5560 let characters = trim.characters.take().expect("checked above");
5561 Ok(Expression::Function(Box::new(Function::new(
5562 "RTRIM",
5563 vec![trim.this, characters],
5564 ))))
5565 }
5566 _ => Ok(Expression::Trim(Box::new(trim))),
5567 }
5568 }
5569 other => Ok(other),
5570 })
5571 }
5572
5573 fn normalize_postgres_only_for_tsql(expr: Expression) -> Result<Expression> {
5574 transform_recursive(expr, &|e| match e {
5575 Expression::Table(mut table) if table.only => {
5576 table.only = false;
5577 Ok(Expression::Table(table))
5578 }
5579 other => Ok(other),
5580 })
5581 }
5582
5583 fn rewrite_postgres_json_array_elements_select_for_tsql(
5584 expr: Expression,
5585 ) -> Result<Expression> {
5586 let Expression::Select(select) = expr else {
5587 return Ok(expr);
5588 };
5589 let mut select = *select;
5590 if !Self::is_plain_single_projection_select(&select) {
5591 return Ok(Expression::Select(Box::new(select)));
5592 }
5593
5594 let Some(json_arg) =
5595 Self::postgres_json_array_elements_projection_arg(&select.expressions[0])
5596 else {
5597 return Ok(Expression::Select(Box::new(select)));
5598 };
5599
5600 select.expressions = vec![Expression::column("value")];
5601 select.from = Some(From {
5602 expressions: vec![Expression::OpenJSON(Box::new(
5603 crate::expressions::OpenJSON {
5604 this: Box::new(json_arg),
5605 path: None,
5606 expressions: Vec::new(),
5607 },
5608 ))],
5609 });
5610
5611 Ok(Expression::Select(Box::new(select)))
5612 }
5613
5614 fn is_plain_single_projection_select(select: &crate::expressions::Select) -> bool {
5615 select.expressions.len() == 1
5616 && select.from.is_none()
5617 && select.joins.is_empty()
5618 && select.lateral_views.is_empty()
5619 && select.prewhere.is_none()
5620 && select.where_clause.is_none()
5621 && select.group_by.is_none()
5622 && select.having.is_none()
5623 && select.qualify.is_none()
5624 && select.order_by.is_none()
5625 && select.distribute_by.is_none()
5626 && select.cluster_by.is_none()
5627 && select.sort_by.is_none()
5628 && select.limit.is_none()
5629 && select.offset.is_none()
5630 && select.limit_by.is_none()
5631 && select.fetch.is_none()
5632 && !select.distinct
5633 && select.distinct_on.is_none()
5634 && select.top.is_none()
5635 && select.with.is_none()
5636 && select.sample.is_none()
5637 && select.into.is_none()
5638 && select.locks.is_empty()
5639 && select.for_xml.is_empty()
5640 && select.for_json.is_empty()
5641 && select.exclude.is_none()
5642 }
5643
5644 fn postgres_json_array_elements_projection_arg(expr: &Expression) -> Option<Expression> {
5645 match expr {
5646 Expression::Function(function)
5647 if Self::node_is_postgres_json_array_elements(expr) && function.args.len() == 1 =>
5648 {
5649 Some(function.args[0].clone())
5650 }
5651 Expression::Alias(alias) => {
5652 Self::postgres_json_array_elements_projection_arg(&alias.this)
5653 }
5654 _ => None,
5655 }
5656 }
5657
5658 fn normalize_postgres_type_function_casts(expr: Expression) -> Result<Expression> {
5659 transform_recursive(expr, &|e| match e {
5660 Expression::Function(function) => {
5661 let mut function = *function;
5662 if function.args.len() == 1
5663 && !function.distinct
5664 && !function.quoted
5665 && !function.use_bracket_syntax
5666 && !function.name.contains('.')
5667 {
5668 if let Some(to) = Self::postgres_type_function_data_type(&function.name) {
5669 let this = function.args.remove(0);
5670 return Ok(Expression::Cast(Box::new(Cast {
5671 this,
5672 to,
5673 trailing_comments: function.trailing_comments,
5674 double_colon_syntax: false,
5675 format: None,
5676 default: None,
5677 inferred_type: function.inferred_type,
5678 })));
5679 }
5680 }
5681 Ok(Expression::Function(Box::new(function)))
5682 }
5683 _ => Ok(e),
5684 })
5685 }
5686
5687 fn node_is_postgres_type_function_cast(expr: &Expression) -> bool {
5688 matches!(
5689 expr,
5690 Expression::Function(function)
5691 if !function.quoted
5692 && !function.use_bracket_syntax
5693 && !function.name.contains('.')
5694 && Self::postgres_type_function_data_type(&function.name).is_some()
5695 )
5696 }
5697
5698 fn postgres_type_function_data_type(name: &str) -> Option<DataType> {
5699 match name.to_ascii_uppercase().as_str() {
5700 "NUMERIC" | "DECIMAL" | "DEC" => Some(DataType::Decimal {
5701 precision: None,
5702 scale: None,
5703 }),
5704 "INT2" | "SMALLINT" => Some(DataType::SmallInt { length: None }),
5705 "INT4" | "INT" => Some(DataType::Int {
5706 length: None,
5707 integer_spelling: false,
5708 }),
5709 "INTEGER" => Some(DataType::Int {
5710 length: None,
5711 integer_spelling: true,
5712 }),
5713 "INT8" | "BIGINT" => Some(DataType::BigInt { length: None }),
5714 "FLOAT4" | "REAL" => Some(DataType::Float {
5715 precision: None,
5716 scale: None,
5717 real_spelling: true,
5718 }),
5719 "FLOAT8" => Some(DataType::Double {
5720 precision: None,
5721 scale: None,
5722 }),
5723 "BOOL" | "BOOLEAN" => Some(DataType::Boolean),
5724 "TEXT" => Some(DataType::Text),
5725 "VARCHAR" => Some(DataType::VarChar {
5726 length: None,
5727 parenthesized_length: false,
5728 }),
5729 "UUID" => Some(DataType::Uuid),
5730 _ => None,
5731 }
5732 }
5733
5734 fn rewrite_boolean_values_for_tsql(expr: Expression) -> Result<Expression> {
5735 match expr {
5736 Expression::Select(select) => Self::rewrite_boolean_values_in_tsql_select(select),
5737 Expression::Subquery(mut subquery) => {
5738 subquery.this = Self::rewrite_boolean_values_for_tsql(subquery.this)?;
5739 Ok(Expression::Subquery(subquery))
5740 }
5741 Expression::Union(mut union) => {
5742 let left = std::mem::replace(&mut union.left, Expression::null());
5743 let right = std::mem::replace(&mut union.right, Expression::null());
5744 union.left = Self::rewrite_boolean_values_for_tsql(left)?;
5745 union.right = Self::rewrite_boolean_values_for_tsql(right)?;
5746 if let Some(mut with) = union.with.take() {
5747 with.ctes = with
5748 .ctes
5749 .into_iter()
5750 .map(|mut cte| {
5751 cte.this = Self::rewrite_boolean_values_for_tsql(cte.this)?;
5752 Ok(cte)
5753 })
5754 .collect::<Result<Vec<_>>>()?;
5755 union.with = Some(with);
5756 }
5757 Ok(Expression::Union(union))
5758 }
5759 Expression::Intersect(mut intersect) => {
5760 let left = std::mem::replace(&mut intersect.left, Expression::null());
5761 let right = std::mem::replace(&mut intersect.right, Expression::null());
5762 intersect.left = Self::rewrite_boolean_values_for_tsql(left)?;
5763 intersect.right = Self::rewrite_boolean_values_for_tsql(right)?;
5764 Ok(Expression::Intersect(intersect))
5765 }
5766 Expression::Except(mut except) => {
5767 let left = std::mem::replace(&mut except.left, Expression::null());
5768 let right = std::mem::replace(&mut except.right, Expression::null());
5769 except.left = Self::rewrite_boolean_values_for_tsql(left)?;
5770 except.right = Self::rewrite_boolean_values_for_tsql(right)?;
5771 Ok(Expression::Except(except))
5772 }
5773 other => Self::rewrite_tsql_boolean_embedded_queries(other),
5774 }
5775 }
5776
5777 fn rewrite_postgres_format_for_tsql(
5778 expr: Expression,
5779 target: DialectType,
5780 ) -> Result<Expression> {
5781 transform_recursive(expr, &|e| match e {
5782 Expression::Function(f) if f.name.eq_ignore_ascii_case("FORMAT") => {
5783 Self::postgres_format_function_to_tsql(*f, target)
5784 }
5785 other => Ok(other),
5786 })
5787 }
5788
5789 fn postgres_format_function_to_tsql(f: Function, target: DialectType) -> Result<Expression> {
5790 let Some(format_expr) = f.args.first() else {
5791 return Err(Self::unsupported_postgres_format_for_tsql(
5792 target,
5793 "missing format string",
5794 ));
5795 };
5796
5797 let format = match format_expr {
5798 Expression::Literal(lit) if lit.is_string() => lit.value_str(),
5799 _ => {
5800 return Err(Self::unsupported_postgres_format_for_tsql(
5801 target,
5802 "dynamic format strings",
5803 ))
5804 }
5805 };
5806
5807 let value_args = &f.args[1..];
5808 let mut arg_index = 0usize;
5809 let mut literal = String::new();
5810 let mut segments = Vec::new();
5811 let mut chars = format.chars();
5812
5813 while let Some(ch) = chars.next() {
5814 if ch != '%' {
5815 literal.push(ch);
5816 continue;
5817 }
5818
5819 let Some(specifier) = chars.next() else {
5820 return Err(Self::unsupported_postgres_format_for_tsql(
5821 target,
5822 "unterminated format specifier",
5823 ));
5824 };
5825
5826 match specifier {
5827 '%' => literal.push('%'),
5828 's' => {
5829 if !literal.is_empty() {
5830 segments.push(Expression::string(std::mem::take(&mut literal)));
5831 }
5832 let Some(arg) = value_args.get(arg_index) else {
5833 return Err(Self::unsupported_postgres_format_for_tsql(
5834 target,
5835 "not enough arguments",
5836 ));
5837 };
5838 segments.push(arg.clone());
5839 arg_index += 1;
5840 }
5841 other => {
5842 return Err(Self::unsupported_postgres_format_for_tsql(
5843 target,
5844 format!("unsupported format specifier %{other}"),
5845 ))
5846 }
5847 }
5848 }
5849
5850 if !literal.is_empty() {
5851 segments.push(Expression::string(literal));
5852 }
5853
5854 if arg_index != value_args.len() {
5855 return Err(Self::unsupported_postgres_format_for_tsql(
5856 target,
5857 "unused format arguments",
5858 ));
5859 }
5860
5861 Ok(Self::postgres_format_segments_to_tsql_concat(segments))
5862 }
5863
5864 fn postgres_format_segments_to_tsql_concat(mut segments: Vec<Expression>) -> Expression {
5865 if segments.is_empty() {
5866 return Expression::string("");
5867 }
5868
5869 if segments.len() == 1 {
5870 let only = segments.pop().expect("one segment");
5871 if matches!(&only, Expression::Literal(lit) if lit.is_string()) {
5872 return only;
5873 }
5874
5875 return Expression::Function(Box::new(Function::new(
5876 "CONCAT".to_string(),
5877 vec![only, Expression::string("")],
5878 )));
5879 }
5880
5881 Expression::Function(Box::new(Function::new("CONCAT".to_string(), segments)))
5882 }
5883
5884 fn unsupported_postgres_format_for_tsql(
5885 target: DialectType,
5886 reason: impl Into<String>,
5887 ) -> crate::error::Error {
5888 crate::error::Error::unsupported(
5889 format!("PostgreSQL format() ({})", reason.into()),
5890 target.to_string(),
5891 )
5892 }
5893
5894 fn rewrite_boolean_values_in_tsql_select(
5895 mut select: Box<crate::expressions::Select>,
5896 ) -> Result<Expression> {
5897 if let Some(mut with) = select.with.take() {
5898 with.ctes = with
5899 .ctes
5900 .into_iter()
5901 .map(|mut cte| {
5902 cte.this = Self::rewrite_boolean_values_for_tsql(cte.this)?;
5903 Ok(cte)
5904 })
5905 .collect::<Result<Vec<_>>>()?;
5906 select.with = Some(with);
5907 }
5908
5909 select.expressions = select
5910 .expressions
5911 .into_iter()
5912 .map(Self::rewrite_tsql_boolean_scalar_value)
5913 .collect::<Result<Vec<_>>>()?;
5914
5915 if let Some(mut from) = select.from.take() {
5916 from.expressions = from
5917 .expressions
5918 .into_iter()
5919 .map(Self::rewrite_tsql_boolean_embedded_queries)
5920 .collect::<Result<Vec<_>>>()?;
5921 select.from = Some(from);
5922 }
5923
5924 select.joins = select
5925 .joins
5926 .into_iter()
5927 .map(|mut join| {
5928 join.this = Self::rewrite_tsql_boolean_embedded_queries(join.this)?;
5929 if let Some(on) = join.on.take() {
5930 join.on = Some(Self::rewrite_tsql_boolean_predicate_context(on)?);
5931 }
5932 if let Some(match_condition) = join.match_condition.take() {
5933 join.match_condition = Some(Self::rewrite_tsql_boolean_predicate_context(
5934 match_condition,
5935 )?);
5936 }
5937 join.pivots = join
5938 .pivots
5939 .into_iter()
5940 .map(Self::rewrite_tsql_boolean_embedded_queries)
5941 .collect::<Result<Vec<_>>>()?;
5942 Ok(join)
5943 })
5944 .collect::<Result<Vec<_>>>()?;
5945
5946 select.lateral_views = select
5947 .lateral_views
5948 .into_iter()
5949 .map(|mut lateral_view| {
5950 lateral_view.this = Self::rewrite_tsql_boolean_embedded_queries(lateral_view.this)?;
5951 Ok(lateral_view)
5952 })
5953 .collect::<Result<Vec<_>>>()?;
5954
5955 if let Some(prewhere) = select.prewhere.take() {
5956 select.prewhere = Some(Self::rewrite_tsql_boolean_predicate_context(prewhere)?);
5957 }
5958
5959 if let Some(mut where_clause) = select.where_clause.take() {
5960 where_clause.this = Self::rewrite_tsql_boolean_predicate_context(where_clause.this)?;
5961 select.where_clause = Some(where_clause);
5962 }
5963
5964 if let Some(mut group_by) = select.group_by.take() {
5965 group_by.expressions = group_by
5966 .expressions
5967 .into_iter()
5968 .map(Self::rewrite_tsql_boolean_scalar_value)
5969 .collect::<Result<Vec<_>>>()?;
5970 select.group_by = Some(group_by);
5971 }
5972
5973 if let Some(mut having) = select.having.take() {
5974 having.this = Self::rewrite_tsql_boolean_predicate_context(having.this)?;
5975 select.having = Some(having);
5976 }
5977
5978 if let Some(mut qualify) = select.qualify.take() {
5979 qualify.this = Self::rewrite_tsql_boolean_predicate_context(qualify.this)?;
5980 select.qualify = Some(qualify);
5981 }
5982
5983 if let Some(mut order_by) = select.order_by.take() {
5984 order_by.expressions = Self::rewrite_tsql_boolean_ordered_values(order_by.expressions)?;
5985 select.order_by = Some(order_by);
5986 }
5987
5988 if let Some(mut distribute_by) = select.distribute_by.take() {
5989 distribute_by.expressions = distribute_by
5990 .expressions
5991 .into_iter()
5992 .map(Self::rewrite_tsql_boolean_scalar_value)
5993 .collect::<Result<Vec<_>>>()?;
5994 select.distribute_by = Some(distribute_by);
5995 }
5996
5997 if let Some(mut cluster_by) = select.cluster_by.take() {
5998 cluster_by.expressions =
5999 Self::rewrite_tsql_boolean_ordered_values(cluster_by.expressions)?;
6000 select.cluster_by = Some(cluster_by);
6001 }
6002
6003 if let Some(mut sort_by) = select.sort_by.take() {
6004 sort_by.expressions = Self::rewrite_tsql_boolean_ordered_values(sort_by.expressions)?;
6005 select.sort_by = Some(sort_by);
6006 }
6007
6008 if let Some(limit_by) = select.limit_by.take() {
6009 select.limit_by = Some(
6010 limit_by
6011 .into_iter()
6012 .map(Self::rewrite_tsql_boolean_scalar_value)
6013 .collect::<Result<Vec<_>>>()?,
6014 );
6015 }
6016
6017 if let Some(distinct_on) = select.distinct_on.take() {
6018 select.distinct_on = Some(
6019 distinct_on
6020 .into_iter()
6021 .map(Self::rewrite_tsql_boolean_scalar_value)
6022 .collect::<Result<Vec<_>>>()?,
6023 );
6024 }
6025
6026 if let Some(mut sample) = select.sample.take() {
6027 sample.size = Self::rewrite_tsql_boolean_embedded_queries(sample.size)?;
6028 if let Some(offset) = sample.offset.take() {
6029 sample.offset = Some(Self::rewrite_tsql_boolean_embedded_queries(offset)?);
6030 }
6031 if let Some(bucket_numerator) = sample.bucket_numerator.take() {
6032 sample.bucket_numerator = Some(Box::new(
6033 Self::rewrite_tsql_boolean_embedded_queries(*bucket_numerator)?,
6034 ));
6035 }
6036 if let Some(bucket_denominator) = sample.bucket_denominator.take() {
6037 sample.bucket_denominator = Some(Box::new(
6038 Self::rewrite_tsql_boolean_embedded_queries(*bucket_denominator)?,
6039 ));
6040 }
6041 if let Some(bucket_field) = sample.bucket_field.take() {
6042 sample.bucket_field = Some(Box::new(Self::rewrite_tsql_boolean_embedded_queries(
6043 *bucket_field,
6044 )?));
6045 }
6046 select.sample = Some(sample);
6047 }
6048
6049 if let Some(settings) = select.settings.take() {
6050 select.settings = Some(
6051 settings
6052 .into_iter()
6053 .map(Self::rewrite_tsql_boolean_embedded_queries)
6054 .collect::<Result<Vec<_>>>()?,
6055 );
6056 }
6057
6058 if let Some(format) = select.format.take() {
6059 select.format = Some(Self::rewrite_tsql_boolean_embedded_queries(format)?);
6060 }
6061
6062 if let Some(mut windows) = select.windows.take() {
6063 for window in windows.iter_mut() {
6064 Self::rewrite_tsql_boolean_over_values(&mut window.spec)?;
6065 }
6066 select.windows = Some(windows);
6067 }
6068
6069 Ok(Expression::Select(select))
6070 }
6071
6072 fn rewrite_tsql_boolean_scalar_value(expr: Expression) -> Result<Expression> {
6073 if Self::is_tsql_boolean_value_expression(&expr) {
6074 let predicate = Self::rewrite_tsql_boolean_predicate_context(expr)?;
6075 return Ok(Self::tsql_boolean_value_case(predicate));
6076 }
6077
6078 match expr {
6079 Expression::Alias(mut alias) => {
6080 alias.this = Self::rewrite_tsql_boolean_scalar_value(alias.this)?;
6081 Ok(Expression::Alias(alias))
6082 }
6083 Expression::Paren(mut paren) => {
6084 paren.this = Self::rewrite_tsql_boolean_scalar_value(paren.this)?;
6085 Ok(Expression::Paren(paren))
6086 }
6087 Expression::Cast(mut cast) => {
6088 cast.this = Self::rewrite_tsql_boolean_scalar_value(cast.this)?;
6089 if let Some(format) = cast.format.take() {
6090 cast.format = Some(Box::new(Self::rewrite_tsql_boolean_embedded_queries(
6091 *format,
6092 )?));
6093 }
6094 if let Some(default) = cast.default.take() {
6095 cast.default =
6096 Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*default)?));
6097 }
6098 Ok(Expression::Cast(cast))
6099 }
6100 Expression::TryCast(mut cast) => {
6101 cast.this = Self::rewrite_tsql_boolean_scalar_value(cast.this)?;
6102 if let Some(format) = cast.format.take() {
6103 cast.format = Some(Box::new(Self::rewrite_tsql_boolean_embedded_queries(
6104 *format,
6105 )?));
6106 }
6107 if let Some(default) = cast.default.take() {
6108 cast.default =
6109 Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*default)?));
6110 }
6111 Ok(Expression::TryCast(cast))
6112 }
6113 Expression::SafeCast(mut cast) => {
6114 cast.this = Self::rewrite_tsql_boolean_scalar_value(cast.this)?;
6115 if let Some(format) = cast.format.take() {
6116 cast.format = Some(Box::new(Self::rewrite_tsql_boolean_embedded_queries(
6117 *format,
6118 )?));
6119 }
6120 if let Some(default) = cast.default.take() {
6121 cast.default =
6122 Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*default)?));
6123 }
6124 Ok(Expression::SafeCast(cast))
6125 }
6126 Expression::Case(mut case) => {
6127 if let Some(operand) = case.operand.take() {
6128 case.operand = Some(Self::rewrite_tsql_boolean_scalar_value(operand)?);
6129 }
6130 case.whens = case
6131 .whens
6132 .into_iter()
6133 .map(|(condition, result)| {
6134 Ok((
6135 Self::rewrite_tsql_boolean_predicate_context(condition)?,
6136 Self::rewrite_tsql_boolean_scalar_value(result)?,
6137 ))
6138 })
6139 .collect::<Result<Vec<_>>>()?;
6140 if let Some(else_) = case.else_.take() {
6141 case.else_ = Some(Self::rewrite_tsql_boolean_scalar_value(else_)?);
6142 }
6143 Ok(Expression::Case(case))
6144 }
6145 Expression::IfFunc(mut if_func) => {
6146 if_func.condition =
6147 Self::rewrite_tsql_boolean_predicate_context(if_func.condition)?;
6148 if_func.true_value = Self::rewrite_tsql_boolean_scalar_value(if_func.true_value)?;
6149 if let Some(false_value) = if_func.false_value.take() {
6150 if_func.false_value =
6151 Some(Self::rewrite_tsql_boolean_scalar_value(false_value)?);
6152 }
6153 Ok(Expression::IfFunc(if_func))
6154 }
6155 Expression::WindowFunction(mut window_function) => {
6156 window_function.this =
6157 Self::rewrite_tsql_boolean_embedded_queries(window_function.this)?;
6158 Self::rewrite_tsql_boolean_over_values(&mut window_function.over)?;
6159 if let Some(mut keep) = window_function.keep.take() {
6160 keep.order_by = Self::rewrite_tsql_boolean_ordered_values(keep.order_by)?;
6161 window_function.keep = Some(keep);
6162 }
6163 Ok(Expression::WindowFunction(window_function))
6164 }
6165 Expression::WithinGroup(mut within_group) => {
6166 within_group.this = Self::rewrite_tsql_boolean_embedded_queries(within_group.this)?;
6167 within_group.order_by =
6168 Self::rewrite_tsql_boolean_ordered_values(within_group.order_by)?;
6169 Ok(Expression::WithinGroup(within_group))
6170 }
6171 Expression::Subquery(mut subquery) => {
6172 subquery.this = Self::rewrite_boolean_values_for_tsql(subquery.this)?;
6173 Ok(Expression::Subquery(subquery))
6174 }
6175 Expression::Select(select) => Self::rewrite_boolean_values_in_tsql_select(select),
6176 other => Self::rewrite_tsql_boolean_embedded_queries(other),
6177 }
6178 }
6179
6180 fn rewrite_tsql_boolean_predicate_context(expr: Expression) -> Result<Expression> {
6181 let expr = Self::rewrite_tsql_boolean_embedded_queries(expr)?;
6182 Ok(crate::transforms::ensure_bool_condition(expr))
6183 }
6184
6185 fn rewrite_tsql_boolean_embedded_queries(expr: Expression) -> Result<Expression> {
6186 transform_recursive(expr, &|e| match e {
6187 Expression::Select(select) => Self::rewrite_boolean_values_in_tsql_select(select),
6188 Expression::Subquery(mut subquery) => {
6189 subquery.this = Self::rewrite_boolean_values_for_tsql(subquery.this)?;
6190 Ok(Expression::Subquery(subquery))
6191 }
6192 Expression::Union(_) | Expression::Intersect(_) | Expression::Except(_) => {
6193 Self::rewrite_boolean_values_for_tsql(e)
6194 }
6195 other => Ok(other),
6196 })
6197 }
6198
6199 fn rewrite_tsql_boolean_ordered_values(
6200 ordered: Vec<crate::expressions::Ordered>,
6201 ) -> Result<Vec<crate::expressions::Ordered>> {
6202 ordered
6203 .into_iter()
6204 .map(|mut ordered| {
6205 ordered.this = Self::rewrite_tsql_boolean_scalar_value(ordered.this)?;
6206 if let Some(with_fill) = ordered.with_fill.take() {
6207 ordered.with_fill = Some(Box::new(
6208 Self::rewrite_tsql_boolean_with_fill_values(*with_fill)?,
6209 ));
6210 }
6211 Ok(ordered)
6212 })
6213 .collect()
6214 }
6215
6216 fn rewrite_tsql_boolean_with_fill_values(
6217 mut with_fill: crate::expressions::WithFill,
6218 ) -> Result<crate::expressions::WithFill> {
6219 if let Some(from) = with_fill.from_.take() {
6220 with_fill.from_ = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*from)?));
6221 }
6222 if let Some(to) = with_fill.to.take() {
6223 with_fill.to = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*to)?));
6224 }
6225 if let Some(step) = with_fill.step.take() {
6226 with_fill.step = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*step)?));
6227 }
6228 if let Some(staleness) = with_fill.staleness.take() {
6229 with_fill.staleness = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(
6230 *staleness,
6231 )?));
6232 }
6233 if let Some(interpolate) = with_fill.interpolate.take() {
6234 with_fill.interpolate = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(
6235 *interpolate,
6236 )?));
6237 }
6238 Ok(with_fill)
6239 }
6240
6241 fn rewrite_tsql_boolean_over_values(over: &mut crate::expressions::Over) -> Result<()> {
6242 over.partition_by = std::mem::take(&mut over.partition_by)
6243 .into_iter()
6244 .map(Self::rewrite_tsql_boolean_scalar_value)
6245 .collect::<Result<Vec<_>>>()?;
6246 over.order_by =
6247 Self::rewrite_tsql_boolean_ordered_values(std::mem::take(&mut over.order_by))?;
6248 Ok(())
6249 }
6250
6251 fn is_tsql_boolean_value_expression(expr: &Expression) -> bool {
6252 match expr {
6253 Expression::Paren(paren) => Self::is_tsql_boolean_value_expression(&paren.this),
6254 Expression::Eq(_)
6255 | Expression::Neq(_)
6256 | Expression::Lt(_)
6257 | Expression::Lte(_)
6258 | Expression::Gt(_)
6259 | Expression::Gte(_)
6260 | Expression::Is(_)
6261 | Expression::IsNull(_)
6262 | Expression::IsTrue(_)
6263 | Expression::IsFalse(_)
6264 | Expression::Like(_)
6265 | Expression::ILike(_)
6266 | Expression::StartsWith(_)
6267 | Expression::SimilarTo(_)
6268 | Expression::Glob(_)
6269 | Expression::RegexpLike(_)
6270 | Expression::In(_)
6271 | Expression::Between(_)
6272 | Expression::Exists(_)
6273 | Expression::And(_)
6274 | Expression::Or(_)
6275 | Expression::Not(_)
6276 | Expression::Any(_)
6277 | Expression::All(_)
6278 | Expression::NullSafeEq(_)
6279 | Expression::NullSafeNeq(_)
6280 | Expression::EqualNull(_) => true,
6281 _ => false,
6282 }
6283 }
6284
6285 fn tsql_boolean_value_case(predicate: Expression) -> Expression {
6286 let case = Expression::Case(Box::new(crate::expressions::Case {
6287 operand: None,
6288 whens: vec![(predicate, Expression::number(1))],
6289 else_: Some(Expression::number(0)),
6290 comments: Vec::new(),
6291 inferred_type: None,
6292 }));
6293
6294 Expression::Cast(Box::new(Cast {
6295 this: case,
6296 to: DataType::Boolean,
6297 trailing_comments: Vec::new(),
6298 double_colon_syntax: false,
6299 format: None,
6300 default: None,
6301 inferred_type: None,
6302 }))
6303 }
6304
6305 fn rewrite_aggregate_filters_for_tsql(expr: Expression) -> Result<Expression> {
6306 transform_recursive(expr, &|e| Self::rewrite_aggregate_filter_for_tsql(e))
6307 }
6308
6309 fn rewrite_aggregate_filter_for_tsql(expr: Expression) -> Result<Expression> {
6310 macro_rules! rewrite_agg_filter {
6311 ($variant:ident, $agg:expr) => {{
6312 let mut agg = $agg;
6313 if let Some(filter) = agg.filter.take() {
6314 let this = std::mem::replace(&mut agg.this, Expression::null());
6315 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6316 }
6317 Ok(Expression::$variant(agg))
6318 }};
6319 }
6320
6321 match expr {
6322 Expression::Filter(filter) => {
6323 let condition = match *filter.expression {
6324 Expression::Where(where_) => where_.this,
6325 other => other,
6326 };
6327 Ok(Self::push_filter_into_tsql_aggregate(
6328 *filter.this,
6329 condition,
6330 ))
6331 }
6332 Expression::AggregateFunction(mut agg) => {
6333 if let Some(filter) = agg.filter.take() {
6334 Self::rewrite_generic_aggregate_filter_for_tsql(&mut agg, filter);
6335 }
6336 Ok(Expression::AggregateFunction(agg))
6337 }
6338 Expression::Count(mut count) => {
6339 if let Some(filter) = count.filter.take() {
6340 let value = if count.star {
6341 Expression::number(1)
6342 } else {
6343 count.this.take().unwrap_or_else(|| Expression::number(1))
6344 };
6345 count.star = false;
6346 count.this = Some(Self::conditional_aggregate_value_for_tsql(filter, value));
6347 }
6348 Ok(Expression::Count(count))
6349 }
6350 Expression::Sum(agg) => rewrite_agg_filter!(Sum, agg),
6351 Expression::Avg(agg) => rewrite_agg_filter!(Avg, agg),
6352 Expression::Min(agg) => rewrite_agg_filter!(Min, agg),
6353 Expression::Max(agg) => rewrite_agg_filter!(Max, agg),
6354 Expression::ArrayAgg(agg) => rewrite_agg_filter!(ArrayAgg, agg),
6355 Expression::CountIf(agg) => Ok(Expression::CountIf(agg)),
6356 Expression::Stddev(agg) => rewrite_agg_filter!(Stddev, agg),
6357 Expression::StddevPop(agg) => rewrite_agg_filter!(StddevPop, agg),
6358 Expression::StddevSamp(agg) => rewrite_agg_filter!(StddevSamp, agg),
6359 Expression::Variance(agg) => rewrite_agg_filter!(Variance, agg),
6360 Expression::VarPop(agg) => rewrite_agg_filter!(VarPop, agg),
6361 Expression::VarSamp(agg) => rewrite_agg_filter!(VarSamp, agg),
6362 Expression::Median(agg) => rewrite_agg_filter!(Median, agg),
6363 Expression::Mode(agg) => rewrite_agg_filter!(Mode, agg),
6364 Expression::First(agg) => rewrite_agg_filter!(First, agg),
6365 Expression::Last(agg) => rewrite_agg_filter!(Last, agg),
6366 Expression::AnyValue(agg) => rewrite_agg_filter!(AnyValue, agg),
6367 Expression::ApproxDistinct(agg) => rewrite_agg_filter!(ApproxDistinct, agg),
6368 Expression::ApproxCountDistinct(agg) => {
6369 rewrite_agg_filter!(ApproxCountDistinct, agg)
6370 }
6371 Expression::LogicalAnd(agg) => rewrite_agg_filter!(LogicalAnd, agg),
6372 Expression::LogicalOr(agg) => rewrite_agg_filter!(LogicalOr, agg),
6373 Expression::Skewness(agg) => rewrite_agg_filter!(Skewness, agg),
6374 Expression::ArrayConcatAgg(agg) => rewrite_agg_filter!(ArrayConcatAgg, agg),
6375 Expression::ArrayUniqueAgg(agg) => rewrite_agg_filter!(ArrayUniqueAgg, agg),
6376 Expression::BoolXorAgg(agg) => rewrite_agg_filter!(BoolXorAgg, agg),
6377 Expression::BitwiseAndAgg(agg) => rewrite_agg_filter!(BitwiseAndAgg, agg),
6378 Expression::BitwiseOrAgg(agg) => rewrite_agg_filter!(BitwiseOrAgg, agg),
6379 Expression::BitwiseXorAgg(agg) => rewrite_agg_filter!(BitwiseXorAgg, agg),
6380 Expression::StringAgg(mut agg) => {
6381 if let Some(filter) = agg.filter.take() {
6382 let this = std::mem::replace(&mut agg.this, Expression::null());
6383 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6384 }
6385 Ok(Expression::StringAgg(agg))
6386 }
6387 Expression::GroupConcat(mut agg) => {
6388 if let Some(filter) = agg.filter.take() {
6389 let this = std::mem::replace(&mut agg.this, Expression::null());
6390 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6391 }
6392 Ok(Expression::GroupConcat(agg))
6393 }
6394 Expression::ListAgg(mut agg) => {
6395 if let Some(filter) = agg.filter.take() {
6396 let this = std::mem::replace(&mut agg.this, Expression::null());
6397 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6398 }
6399 Ok(Expression::ListAgg(agg))
6400 }
6401 Expression::WithinGroup(mut within_group) => {
6402 within_group.this = Self::rewrite_aggregate_filters_for_tsql(within_group.this)?;
6403 Ok(Expression::WithinGroup(within_group))
6404 }
6405 other => Ok(other),
6406 }
6407 }
6408
6409 fn push_filter_into_tsql_aggregate(expr: Expression, filter: Expression) -> Expression {
6410 macro_rules! push_agg_filter {
6411 ($variant:ident, $agg:expr) => {{
6412 let mut agg = $agg;
6413 let this = std::mem::replace(&mut agg.this, Expression::null());
6414 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6415 agg.filter = None;
6416 Expression::$variant(agg)
6417 }};
6418 }
6419
6420 match expr {
6421 Expression::AggregateFunction(mut agg) => {
6422 Self::rewrite_generic_aggregate_filter_for_tsql(&mut agg, filter);
6423 Expression::AggregateFunction(agg)
6424 }
6425 Expression::Count(mut count) => {
6426 let value = if count.star {
6427 Expression::number(1)
6428 } else {
6429 count.this.take().unwrap_or_else(|| Expression::number(1))
6430 };
6431 count.star = false;
6432 count.filter = None;
6433 count.this = Some(Self::conditional_aggregate_value_for_tsql(filter, value));
6434 Expression::Count(count)
6435 }
6436 Expression::Sum(agg) => push_agg_filter!(Sum, agg),
6437 Expression::Avg(agg) => push_agg_filter!(Avg, agg),
6438 Expression::Min(agg) => push_agg_filter!(Min, agg),
6439 Expression::Max(agg) => push_agg_filter!(Max, agg),
6440 Expression::ArrayAgg(agg) => push_agg_filter!(ArrayAgg, agg),
6441 Expression::CountIf(mut agg) => {
6442 agg.filter = Some(filter);
6443 Expression::CountIf(agg)
6444 }
6445 Expression::Stddev(agg) => push_agg_filter!(Stddev, agg),
6446 Expression::StddevPop(agg) => push_agg_filter!(StddevPop, agg),
6447 Expression::StddevSamp(agg) => push_agg_filter!(StddevSamp, agg),
6448 Expression::Variance(agg) => push_agg_filter!(Variance, agg),
6449 Expression::VarPop(agg) => push_agg_filter!(VarPop, agg),
6450 Expression::VarSamp(agg) => push_agg_filter!(VarSamp, agg),
6451 Expression::Median(agg) => push_agg_filter!(Median, agg),
6452 Expression::Mode(agg) => push_agg_filter!(Mode, agg),
6453 Expression::First(agg) => push_agg_filter!(First, agg),
6454 Expression::Last(agg) => push_agg_filter!(Last, agg),
6455 Expression::AnyValue(agg) => push_agg_filter!(AnyValue, agg),
6456 Expression::ApproxDistinct(agg) => push_agg_filter!(ApproxDistinct, agg),
6457 Expression::ApproxCountDistinct(agg) => {
6458 push_agg_filter!(ApproxCountDistinct, agg)
6459 }
6460 Expression::LogicalAnd(agg) => push_agg_filter!(LogicalAnd, agg),
6461 Expression::LogicalOr(agg) => push_agg_filter!(LogicalOr, agg),
6462 Expression::Skewness(agg) => push_agg_filter!(Skewness, agg),
6463 Expression::ArrayConcatAgg(agg) => push_agg_filter!(ArrayConcatAgg, agg),
6464 Expression::ArrayUniqueAgg(agg) => push_agg_filter!(ArrayUniqueAgg, agg),
6465 Expression::BoolXorAgg(agg) => push_agg_filter!(BoolXorAgg, agg),
6466 Expression::BitwiseAndAgg(agg) => push_agg_filter!(BitwiseAndAgg, agg),
6467 Expression::BitwiseOrAgg(agg) => push_agg_filter!(BitwiseOrAgg, agg),
6468 Expression::BitwiseXorAgg(agg) => push_agg_filter!(BitwiseXorAgg, agg),
6469 Expression::StringAgg(mut agg) => {
6470 let this = std::mem::replace(&mut agg.this, Expression::null());
6471 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6472 agg.filter = None;
6473 Expression::StringAgg(agg)
6474 }
6475 Expression::GroupConcat(mut agg) => {
6476 let this = std::mem::replace(&mut agg.this, Expression::null());
6477 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6478 agg.filter = None;
6479 Expression::GroupConcat(agg)
6480 }
6481 Expression::ListAgg(mut agg) => {
6482 let this = std::mem::replace(&mut agg.this, Expression::null());
6483 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6484 agg.filter = None;
6485 Expression::ListAgg(agg)
6486 }
6487 Expression::WithinGroup(mut within_group) => {
6488 within_group.this =
6489 Self::push_filter_into_tsql_aggregate(within_group.this, filter);
6490 Expression::WithinGroup(within_group)
6491 }
6492 other => Expression::Filter(Box::new(crate::expressions::Filter {
6493 this: Box::new(other),
6494 expression: Box::new(filter),
6495 })),
6496 }
6497 }
6498
6499 fn rewrite_generic_aggregate_filter_for_tsql(
6500 agg: &mut crate::expressions::AggregateFunction,
6501 filter: Expression,
6502 ) {
6503 let is_count =
6504 agg.name.eq_ignore_ascii_case("COUNT") || agg.name.eq_ignore_ascii_case("COUNT_BIG");
6505 let is_count_star = is_count
6506 && (agg.args.is_empty()
6507 || (agg.args.len() == 1 && matches!(agg.args[0], Expression::Star(_))));
6508
6509 if is_count_star {
6510 agg.args = vec![Self::conditional_aggregate_value_for_tsql(
6511 filter,
6512 Expression::number(1),
6513 )];
6514 } else if !agg.args.is_empty() {
6515 agg.args = agg
6516 .args
6517 .drain(..)
6518 .map(|arg| Self::conditional_aggregate_value_for_tsql(filter.clone(), arg))
6519 .collect();
6520 } else {
6521 agg.filter = Some(filter);
6522 }
6523 }
6524
6525 fn conditional_aggregate_value_for_tsql(filter: Expression, value: Expression) -> Expression {
6526 Expression::Case(Box::new(crate::expressions::Case {
6527 operand: None,
6528 whens: vec![(filter, value)],
6529 else_: None,
6530 comments: Vec::new(),
6531 inferred_type: None,
6532 }))
6533 }
6534
6535 fn reject_pgvector_distance_operators_for_sqlite(&self, sql: &str) -> Result<()> {
6536 let tokens = self.tokenize(sql)?;
6537 for (i, token) in tokens.iter().enumerate() {
6538 if token.token_type == TokenType::NullsafeEq {
6539 return Err(crate::error::Error::unsupported(
6540 "PostgreSQL pgvector cosine distance operator <=>",
6541 "SQLite",
6542 ));
6543 }
6544 if token.token_type == TokenType::Lt
6545 && tokens
6546 .get(i + 1)
6547 .is_some_and(|token| token.token_type == TokenType::Tilde)
6548 && tokens
6549 .get(i + 2)
6550 .is_some_and(|token| token.token_type == TokenType::Gt)
6551 {
6552 return Err(crate::error::Error::unsupported(
6553 "PostgreSQL pgvector Hamming distance operator <~>",
6554 "SQLite",
6555 ));
6556 }
6557 }
6558 Ok(())
6559 }
6560
6561 fn normalize_sqlite_double_quoted_defaults(expr: Expression) -> Result<Expression> {
6562 fn normalize_default_expr(expr: Expression) -> Result<Expression> {
6563 transform_recursive(expr, &|e| match e {
6564 Expression::Column(col)
6565 if col.table.is_none() && col.name.quoted && !col.join_mark =>
6566 {
6567 Ok(Expression::Literal(Box::new(Literal::String(
6568 col.name.name,
6569 ))))
6570 }
6571 Expression::Identifier(id) if id.quoted => {
6572 Ok(Expression::Literal(Box::new(Literal::String(id.name))))
6573 }
6574 _ => Ok(e),
6575 })
6576 }
6577
6578 fn normalize_column_default(col: &mut crate::expressions::ColumnDef) -> Result<()> {
6579 if let Some(default) = col.default.take() {
6580 col.default = Some(normalize_default_expr(default)?);
6581 }
6582
6583 for constraint in &mut col.constraints {
6584 if let ColumnConstraint::Default(default) = constraint {
6585 *default = normalize_default_expr(default.clone())?;
6586 }
6587 }
6588
6589 Ok(())
6590 }
6591
6592 transform_recursive(expr, &|e| match e {
6593 Expression::CreateTable(mut ct) => {
6594 for column in &mut ct.columns {
6595 normalize_column_default(column)?;
6596 }
6597 Ok(Expression::CreateTable(ct))
6598 }
6599 Expression::ColumnDef(mut col) => {
6600 normalize_column_default(&mut col)?;
6601 Ok(Expression::ColumnDef(col))
6602 }
6603 _ => Ok(e),
6604 })
6605 }
6606
6607 fn normalize_postgres_to_sqlite_types(expr: Expression) -> Result<Expression> {
6608 fn sqlite_type(dt: crate::expressions::DataType) -> crate::expressions::DataType {
6609 use crate::expressions::DataType;
6610
6611 match dt {
6612 DataType::Bit { .. } => DataType::Int {
6613 length: None,
6614 integer_spelling: true,
6615 },
6616 DataType::TextWithLength { .. } => DataType::Text,
6617 DataType::VarChar { .. } => DataType::Text,
6618 DataType::Char { .. } => DataType::Text,
6619 DataType::Timestamp { timezone: true, .. } => DataType::Text,
6620 DataType::Custom { name } => {
6621 let base = name
6622 .split_once('(')
6623 .map_or(name.as_str(), |(base, _)| base)
6624 .trim();
6625 if base.eq_ignore_ascii_case("TSVECTOR")
6626 || base.eq_ignore_ascii_case("TIMESTAMPTZ")
6627 || base.eq_ignore_ascii_case("TIMESTAMP WITH TIME ZONE")
6628 || base.eq_ignore_ascii_case("NVARCHAR")
6629 || base.eq_ignore_ascii_case("NCHAR")
6630 {
6631 DataType::Text
6632 } else {
6633 DataType::Custom { name }
6634 }
6635 }
6636 _ => dt,
6637 }
6638 }
6639
6640 transform_recursive(expr, &|e| match e {
6641 Expression::DataType(dt) => Ok(Expression::DataType(sqlite_type(dt))),
6642 Expression::CreateTable(mut ct) => {
6643 for column in &mut ct.columns {
6644 column.data_type = sqlite_type(column.data_type.clone());
6645 }
6646 Ok(Expression::CreateTable(ct))
6647 }
6648 _ => Ok(e),
6649 })
6650 }
6651
6652 fn normalize_postgres_to_fabric_types(expr: Expression) -> Result<Expression> {
6653 fn fabric_type(dt: crate::expressions::DataType) -> crate::expressions::DataType {
6654 use crate::expressions::DataType;
6655
6656 match dt {
6657 DataType::Decimal {
6658 precision: None,
6659 scale: None,
6660 } => DataType::Decimal {
6661 precision: Some(38),
6662 scale: Some(10),
6663 },
6664 DataType::Json | DataType::JsonB => DataType::Custom {
6665 name: "VARCHAR(MAX)".to_string(),
6666 },
6667 _ => dt,
6668 }
6669 }
6670
6671 transform_recursive(expr, &|e| match e {
6672 Expression::DataType(dt) => Ok(Expression::DataType(fabric_type(dt))),
6673 Expression::CreateTable(mut ct) => {
6674 for column in &mut ct.columns {
6675 column.data_type = fabric_type(column.data_type.clone());
6676 }
6677 Ok(Expression::CreateTable(ct))
6678 }
6679 Expression::ColumnDef(mut col) => {
6680 col.data_type = fabric_type(col.data_type);
6681 Ok(Expression::ColumnDef(col))
6682 }
6683 _ => Ok(e),
6684 })
6685 }
6686
6687 fn seq_rownum_to_range(expr: Expression) -> Result<Expression> {
6691 if let Expression::Select(mut select) = expr {
6692 let has_range_from = if let Some(ref from) = select.from {
6694 from.expressions.iter().any(|e| {
6695 match e {
6697 Expression::Function(f) => f.name.eq_ignore_ascii_case("RANGE"),
6698 Expression::Alias(a) => {
6699 matches!(&a.this, Expression::Function(f) if f.name.eq_ignore_ascii_case("RANGE"))
6700 }
6701 _ => false,
6702 }
6703 })
6704 } else {
6705 false
6706 };
6707
6708 if has_range_from {
6709 select.expressions = select
6711 .expressions
6712 .into_iter()
6713 .map(|e| Self::replace_rownum_with_range(e))
6714 .collect();
6715 }
6716
6717 Ok(Expression::Select(select))
6718 } else {
6719 Ok(expr)
6720 }
6721 }
6722
6723 fn replace_rownum_with_range(expr: Expression) -> Expression {
6725 match expr {
6726 Expression::Mod(op) => {
6728 let new_left = Self::try_replace_rownum_paren(&op.left);
6729 Expression::Mod(Box::new(crate::expressions::BinaryOp {
6730 left: new_left,
6731 right: op.right,
6732 left_comments: op.left_comments,
6733 operator_comments: op.operator_comments,
6734 trailing_comments: op.trailing_comments,
6735 inferred_type: op.inferred_type,
6736 }))
6737 }
6738 Expression::Paren(p) => {
6740 let inner = Self::replace_rownum_with_range(p.this);
6741 Expression::Paren(Box::new(crate::expressions::Paren {
6742 this: inner,
6743 trailing_comments: p.trailing_comments,
6744 }))
6745 }
6746 Expression::Case(mut c) => {
6747 c.whens = c
6749 .whens
6750 .into_iter()
6751 .map(|(cond, then)| {
6752 (
6753 Self::replace_rownum_with_range(cond),
6754 Self::replace_rownum_with_range(then),
6755 )
6756 })
6757 .collect();
6758 if let Some(else_) = c.else_ {
6759 c.else_ = Some(Self::replace_rownum_with_range(else_));
6760 }
6761 Expression::Case(c)
6762 }
6763 Expression::Gte(op) => Expression::Gte(Box::new(crate::expressions::BinaryOp {
6764 left: Self::replace_rownum_with_range(op.left),
6765 right: op.right,
6766 left_comments: op.left_comments,
6767 operator_comments: op.operator_comments,
6768 trailing_comments: op.trailing_comments,
6769 inferred_type: op.inferred_type,
6770 })),
6771 Expression::Sub(op) => Expression::Sub(Box::new(crate::expressions::BinaryOp {
6772 left: Self::replace_rownum_with_range(op.left),
6773 right: op.right,
6774 left_comments: op.left_comments,
6775 operator_comments: op.operator_comments,
6776 trailing_comments: op.trailing_comments,
6777 inferred_type: op.inferred_type,
6778 })),
6779 Expression::Alias(mut a) => {
6780 a.this = Self::replace_rownum_with_range(a.this);
6781 Expression::Alias(a)
6782 }
6783 other => other,
6784 }
6785 }
6786
6787 fn try_replace_rownum_paren(expr: &Expression) -> Expression {
6789 if let Expression::Paren(ref p) = expr {
6790 if let Expression::Sub(ref sub) = p.this {
6791 if let Expression::WindowFunction(ref wf) = sub.left {
6792 if let Expression::Function(ref f) = wf.this {
6793 if f.name.eq_ignore_ascii_case("ROW_NUMBER") {
6794 if let Expression::Literal(ref lit) = sub.right {
6795 if let crate::expressions::Literal::Number(ref n) = lit.as_ref() {
6796 if n == "1" {
6797 return Expression::column("range");
6798 }
6799 }
6800 }
6801 }
6802 }
6803 }
6804 }
6805 }
6806 expr.clone()
6807 }
6808
6809 fn transform_generate_date_array_snowflake(expr: Expression) -> Result<Expression> {
6816 use crate::expressions::*;
6817 transform_recursive(expr, &|e| {
6818 if let Expression::ArraySize(ref af) = e {
6820 if let Expression::Function(ref f) = af.this {
6821 if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") && f.args.len() >= 2 {
6822 let result = Self::convert_array_size_gda_snowflake(f)?;
6823 return Ok(result);
6824 }
6825 }
6826 }
6827
6828 let Expression::Select(mut sel) = e else {
6829 return Ok(e);
6830 };
6831
6832 let mut gda_info: Option<(String, Expression, Expression, String)> = None; let mut gda_join_idx: Option<usize> = None;
6835
6836 for (idx, join) in sel.joins.iter().enumerate() {
6837 let (unnest_ref, alias_name) = match &join.this {
6841 Expression::Unnest(ref unnest) => {
6842 let alias = unnest.alias.as_ref().map(|id| id.name.clone());
6843 (Some(unnest.as_ref()), alias)
6844 }
6845 Expression::Alias(ref a) => {
6846 if let Expression::Unnest(ref unnest) = a.this {
6847 (Some(unnest.as_ref()), Some(a.alias.name.clone()))
6848 } else {
6849 (None, None)
6850 }
6851 }
6852 _ => (None, None),
6853 };
6854
6855 if let (Some(unnest), Some(alias)) = (unnest_ref, alias_name) {
6856 if let Expression::Function(ref f) = unnest.this {
6858 if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") && f.args.len() >= 2 {
6859 let start_expr = f.args[0].clone();
6860 let end_expr = f.args[1].clone();
6861 let step = f.args.get(2).cloned();
6862
6863 let unit = if let Some(Expression::Interval(ref iv)) = step {
6865 if let Some(IntervalUnitSpec::Simple { ref unit, .. }) = iv.unit {
6866 Some(format!("{:?}", unit).to_ascii_uppercase())
6867 } else if let Some(ref this) = iv.this {
6868 if let Expression::Literal(lit) = this {
6870 if let Literal::String(ref s) = lit.as_ref() {
6871 let parts: Vec<&str> = s.split_whitespace().collect();
6872 if parts.len() == 2 {
6873 Some(parts[1].to_ascii_uppercase())
6874 } else if parts.len() == 1 {
6875 let upper = parts[0].to_ascii_uppercase();
6877 if matches!(
6878 upper.as_str(),
6879 "YEAR"
6880 | "QUARTER"
6881 | "MONTH"
6882 | "WEEK"
6883 | "DAY"
6884 | "HOUR"
6885 | "MINUTE"
6886 | "SECOND"
6887 ) {
6888 Some(upper)
6889 } else {
6890 None
6891 }
6892 } else {
6893 None
6894 }
6895 } else {
6896 None
6897 }
6898 } else {
6899 None
6900 }
6901 } else {
6902 None
6903 }
6904 } else {
6905 None
6906 };
6907
6908 if let Some(unit_str) = unit {
6909 gda_info = Some((alias, start_expr, end_expr, unit_str));
6910 gda_join_idx = Some(idx);
6911 }
6912 }
6913 }
6914 }
6915 if gda_info.is_some() {
6916 break;
6917 }
6918 }
6919
6920 let Some((alias_name, start_expr, end_expr, unit_str)) = gda_info else {
6921 let result = Self::try_transform_from_gda_snowflake(sel);
6924 return result;
6925 };
6926 let join_idx = gda_join_idx.unwrap();
6927
6928 let datediff = Expression::Function(Box::new(Function::new(
6932 "DATEDIFF".to_string(),
6933 vec![
6934 Expression::boxed_column(Column {
6935 name: Identifier::new(&unit_str),
6936 table: None,
6937 join_mark: false,
6938 trailing_comments: vec![],
6939 span: None,
6940 inferred_type: None,
6941 }),
6942 start_expr.clone(),
6943 end_expr.clone(),
6944 ],
6945 )));
6946 let datediff_plus_one = Expression::Add(Box::new(BinaryOp {
6947 left: datediff,
6948 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
6949 left_comments: vec![],
6950 operator_comments: vec![],
6951 trailing_comments: vec![],
6952 inferred_type: None,
6953 }));
6954
6955 let array_gen_range = Expression::Function(Box::new(Function::new(
6956 "ARRAY_GENERATE_RANGE".to_string(),
6957 vec![
6958 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
6959 datediff_plus_one,
6960 ],
6961 )));
6962
6963 let flatten_input = Expression::NamedArgument(Box::new(NamedArgument {
6965 name: Identifier::new("INPUT"),
6966 value: array_gen_range,
6967 separator: crate::expressions::NamedArgSeparator::DArrow,
6968 }));
6969 let flatten = Expression::Function(Box::new(Function::new(
6970 "FLATTEN".to_string(),
6971 vec![flatten_input],
6972 )));
6973
6974 let alias_table = Alias {
6976 this: flatten,
6977 alias: Identifier::new("_t0"),
6978 column_aliases: vec![
6979 Identifier::new("seq"),
6980 Identifier::new("key"),
6981 Identifier::new("path"),
6982 Identifier::new("index"),
6983 Identifier::new(&alias_name),
6984 Identifier::new("this"),
6985 ],
6986 alias_explicit_as: false,
6987 alias_keyword: None,
6988 pre_alias_comments: vec![],
6989 trailing_comments: vec![],
6990 inferred_type: None,
6991 };
6992 let lateral_expr = Expression::Lateral(Box::new(Lateral {
6993 this: Box::new(Expression::Alias(Box::new(alias_table))),
6994 view: None,
6995 outer: None,
6996 alias: None,
6997 alias_quoted: false,
6998 cross_apply: None,
6999 ordinality: None,
7000 column_aliases: vec![],
7001 }));
7002
7003 sel.joins.remove(join_idx);
7005 if let Some(ref mut from) = sel.from {
7006 from.expressions.push(lateral_expr);
7007 }
7008
7009 let dateadd_expr = Expression::Function(Box::new(Function::new(
7011 "DATEADD".to_string(),
7012 vec![
7013 Expression::boxed_column(Column {
7014 name: Identifier::new(&unit_str),
7015 table: None,
7016 join_mark: false,
7017 trailing_comments: vec![],
7018 span: None,
7019 inferred_type: None,
7020 }),
7021 Expression::Cast(Box::new(Cast {
7022 this: Expression::boxed_column(Column {
7023 name: Identifier::new(&alias_name),
7024 table: None,
7025 join_mark: false,
7026 trailing_comments: vec![],
7027 span: None,
7028 inferred_type: None,
7029 }),
7030 to: DataType::Int {
7031 length: None,
7032 integer_spelling: false,
7033 },
7034 trailing_comments: vec![],
7035 double_colon_syntax: false,
7036 format: None,
7037 default: None,
7038 inferred_type: None,
7039 })),
7040 Expression::Cast(Box::new(Cast {
7041 this: start_expr.clone(),
7042 to: DataType::Date,
7043 trailing_comments: vec![],
7044 double_colon_syntax: false,
7045 format: None,
7046 default: None,
7047 inferred_type: None,
7048 })),
7049 ],
7050 )));
7051
7052 let new_exprs: Vec<Expression> = sel
7054 .expressions
7055 .iter()
7056 .map(|expr| Self::replace_column_ref_with_dateadd(expr, &alias_name, &dateadd_expr))
7057 .collect();
7058 sel.expressions = new_exprs;
7059
7060 Ok(Expression::Select(sel))
7061 })
7062 }
7063
7064 fn replace_column_ref_with_dateadd(
7066 expr: &Expression,
7067 alias_name: &str,
7068 dateadd: &Expression,
7069 ) -> Expression {
7070 use crate::expressions::*;
7071 match expr {
7072 Expression::Column(c) if c.name.name == alias_name && c.table.is_none() => {
7073 Expression::Alias(Box::new(Alias {
7075 this: dateadd.clone(),
7076 alias: Identifier::new(alias_name),
7077 column_aliases: vec![],
7078 alias_explicit_as: false,
7079 alias_keyword: None,
7080 pre_alias_comments: vec![],
7081 trailing_comments: vec![],
7082 inferred_type: None,
7083 }))
7084 }
7085 Expression::Alias(a) => {
7086 let new_this = Self::replace_column_ref_inner(&a.this, alias_name, dateadd);
7088 Expression::Alias(Box::new(Alias {
7089 this: new_this,
7090 alias: a.alias.clone(),
7091 column_aliases: a.column_aliases.clone(),
7092 alias_explicit_as: false,
7093 alias_keyword: None,
7094 pre_alias_comments: a.pre_alias_comments.clone(),
7095 trailing_comments: a.trailing_comments.clone(),
7096 inferred_type: None,
7097 }))
7098 }
7099 _ => expr.clone(),
7100 }
7101 }
7102
7103 fn replace_column_ref_inner(
7105 expr: &Expression,
7106 alias_name: &str,
7107 dateadd: &Expression,
7108 ) -> Expression {
7109 use crate::expressions::*;
7110 match expr {
7111 Expression::Column(c) if c.name.name == alias_name && c.table.is_none() => {
7112 dateadd.clone()
7113 }
7114 Expression::Add(op) => {
7115 let left = Self::replace_column_ref_inner(&op.left, alias_name, dateadd);
7116 let right = Self::replace_column_ref_inner(&op.right, alias_name, dateadd);
7117 Expression::Add(Box::new(BinaryOp {
7118 left,
7119 right,
7120 left_comments: op.left_comments.clone(),
7121 operator_comments: op.operator_comments.clone(),
7122 trailing_comments: op.trailing_comments.clone(),
7123 inferred_type: None,
7124 }))
7125 }
7126 Expression::Sub(op) => {
7127 let left = Self::replace_column_ref_inner(&op.left, alias_name, dateadd);
7128 let right = Self::replace_column_ref_inner(&op.right, alias_name, dateadd);
7129 Expression::Sub(Box::new(BinaryOp {
7130 left,
7131 right,
7132 left_comments: op.left_comments.clone(),
7133 operator_comments: op.operator_comments.clone(),
7134 trailing_comments: op.trailing_comments.clone(),
7135 inferred_type: None,
7136 }))
7137 }
7138 Expression::Mul(op) => {
7139 let left = Self::replace_column_ref_inner(&op.left, alias_name, dateadd);
7140 let right = Self::replace_column_ref_inner(&op.right, alias_name, dateadd);
7141 Expression::Mul(Box::new(BinaryOp {
7142 left,
7143 right,
7144 left_comments: op.left_comments.clone(),
7145 operator_comments: op.operator_comments.clone(),
7146 trailing_comments: op.trailing_comments.clone(),
7147 inferred_type: None,
7148 }))
7149 }
7150 _ => expr.clone(),
7151 }
7152 }
7153
7154 fn try_transform_from_gda_snowflake(
7157 mut sel: Box<crate::expressions::Select>,
7158 ) -> Result<Expression> {
7159 use crate::expressions::*;
7160
7161 let mut gda_info: Option<(
7163 usize,
7164 String,
7165 Expression,
7166 Expression,
7167 String,
7168 Option<(String, Vec<Identifier>)>,
7169 )> = None; if let Some(ref from) = sel.from {
7172 for (idx, table_expr) in from.expressions.iter().enumerate() {
7173 let (unnest_opt, outer_alias_info) = match table_expr {
7176 Expression::Unnest(ref unnest) => (Some(unnest.as_ref()), None),
7177 Expression::Alias(ref a) => {
7178 if let Expression::Unnest(ref unnest) = a.this {
7179 let alias_info = (a.alias.name.clone(), a.column_aliases.clone());
7180 (Some(unnest.as_ref()), Some(alias_info))
7181 } else {
7182 (None, None)
7183 }
7184 }
7185 _ => (None, None),
7186 };
7187
7188 if let Some(unnest) = unnest_opt {
7189 let func_opt = match &unnest.this {
7191 Expression::Function(ref f)
7192 if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY")
7193 && f.args.len() >= 2 =>
7194 {
7195 Some(f)
7196 }
7197 _ => None,
7199 };
7200
7201 if let Some(f) = func_opt {
7202 let start_expr = f.args[0].clone();
7203 let end_expr = f.args[1].clone();
7204 let step = f.args.get(2).cloned();
7205
7206 let unit = Self::extract_interval_unit_str(&step);
7208 let col_name = outer_alias_info
7209 .as_ref()
7210 .and_then(|(_, cols)| cols.first().map(|id| id.name.clone()))
7211 .unwrap_or_else(|| "value".to_string());
7212
7213 if let Some(unit_str) = unit {
7214 gda_info = Some((
7215 idx,
7216 col_name,
7217 start_expr,
7218 end_expr,
7219 unit_str,
7220 outer_alias_info,
7221 ));
7222 break;
7223 }
7224 }
7225 }
7226 }
7227 }
7228
7229 let Some((from_idx, col_name, start_expr, end_expr, unit_str, outer_alias_info)) = gda_info
7230 else {
7231 return Ok(Expression::Select(sel));
7232 };
7233
7234 let datediff = Expression::Function(Box::new(Function::new(
7240 "DATEDIFF".to_string(),
7241 vec![
7242 Expression::boxed_column(Column {
7243 name: Identifier::new(&unit_str),
7244 table: None,
7245 join_mark: false,
7246 trailing_comments: vec![],
7247 span: None,
7248 inferred_type: None,
7249 }),
7250 start_expr.clone(),
7251 end_expr.clone(),
7252 ],
7253 )));
7254 let datediff_plus_one = Expression::Add(Box::new(BinaryOp {
7256 left: datediff,
7257 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
7258 left_comments: vec![],
7259 operator_comments: vec![],
7260 trailing_comments: vec![],
7261 inferred_type: None,
7262 }));
7263
7264 let array_gen_range = Expression::Function(Box::new(Function::new(
7265 "ARRAY_GENERATE_RANGE".to_string(),
7266 vec![
7267 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
7268 datediff_plus_one,
7269 ],
7270 )));
7271
7272 let flatten_input = Expression::NamedArgument(Box::new(NamedArgument {
7274 name: Identifier::new("INPUT"),
7275 value: array_gen_range,
7276 separator: crate::expressions::NamedArgSeparator::DArrow,
7277 }));
7278 let flatten = Expression::Function(Box::new(Function::new(
7279 "FLATTEN".to_string(),
7280 vec![flatten_input],
7281 )));
7282
7283 let table_alias_name = outer_alias_info
7285 .as_ref()
7286 .map(|(name, _)| name.clone())
7287 .unwrap_or_else(|| "_t0".to_string());
7288
7289 let table_func =
7291 Expression::Function(Box::new(Function::new("TABLE".to_string(), vec![flatten])));
7292 let flatten_aliased = Expression::Alias(Box::new(Alias {
7293 this: table_func,
7294 alias: Identifier::new(&table_alias_name),
7295 column_aliases: vec![
7296 Identifier::new("seq"),
7297 Identifier::new("key"),
7298 Identifier::new("path"),
7299 Identifier::new("index"),
7300 Identifier::new(&col_name),
7301 Identifier::new("this"),
7302 ],
7303 alias_explicit_as: false,
7304 alias_keyword: None,
7305 pre_alias_comments: vec![],
7306 trailing_comments: vec![],
7307 inferred_type: None,
7308 }));
7309
7310 let dateadd_expr = Expression::Function(Box::new(Function::new(
7312 "DATEADD".to_string(),
7313 vec![
7314 Expression::boxed_column(Column {
7315 name: Identifier::new(&unit_str),
7316 table: None,
7317 join_mark: false,
7318 trailing_comments: vec![],
7319 span: None,
7320 inferred_type: None,
7321 }),
7322 Expression::Cast(Box::new(Cast {
7323 this: Expression::boxed_column(Column {
7324 name: Identifier::new(&col_name),
7325 table: None,
7326 join_mark: false,
7327 trailing_comments: vec![],
7328 span: None,
7329 inferred_type: None,
7330 }),
7331 to: DataType::Int {
7332 length: None,
7333 integer_spelling: false,
7334 },
7335 trailing_comments: vec![],
7336 double_colon_syntax: false,
7337 format: None,
7338 default: None,
7339 inferred_type: None,
7340 })),
7341 start_expr.clone(),
7343 ],
7344 )));
7345 let dateadd_aliased = Expression::Alias(Box::new(Alias {
7346 this: dateadd_expr,
7347 alias: Identifier::new(&col_name),
7348 column_aliases: vec![],
7349 alias_explicit_as: false,
7350 alias_keyword: None,
7351 pre_alias_comments: vec![],
7352 trailing_comments: vec![],
7353 inferred_type: None,
7354 }));
7355
7356 let mut inner_select = Select::new();
7358 inner_select.expressions = vec![dateadd_aliased];
7359 inner_select.from = Some(From {
7360 expressions: vec![flatten_aliased],
7361 });
7362
7363 let inner_select_expr = Expression::Select(Box::new(inner_select));
7364 let subquery = Expression::Subquery(Box::new(Subquery {
7365 this: inner_select_expr,
7366 alias: None,
7367 column_aliases: vec![],
7368 alias_explicit_as: false,
7369 alias_keyword: None,
7370 order_by: None,
7371 limit: None,
7372 offset: None,
7373 distribute_by: None,
7374 sort_by: None,
7375 cluster_by: None,
7376 lateral: false,
7377 modifiers_inside: false,
7378 trailing_comments: vec![],
7379 inferred_type: None,
7380 }));
7381
7382 let replacement = if let Some((alias_name, col_aliases)) = outer_alias_info {
7384 Expression::Alias(Box::new(Alias {
7385 this: subquery,
7386 alias: Identifier::new(&alias_name),
7387 column_aliases: col_aliases,
7388 alias_explicit_as: false,
7389 alias_keyword: None,
7390 pre_alias_comments: vec![],
7391 trailing_comments: vec![],
7392 inferred_type: None,
7393 }))
7394 } else {
7395 subquery
7396 };
7397
7398 if let Some(ref mut from) = sel.from {
7400 from.expressions[from_idx] = replacement;
7401 }
7402
7403 Ok(Expression::Select(sel))
7404 }
7405
7406 fn convert_array_size_gda_snowflake(f: &crate::expressions::Function) -> Result<Expression> {
7410 use crate::expressions::*;
7411
7412 let start_expr = f.args[0].clone();
7413 let end_expr = f.args[1].clone();
7414 let step = f.args.get(2).cloned();
7415 let unit_str = Self::extract_interval_unit_str(&step).unwrap_or_else(|| "DAY".to_string());
7416 let col_name = "value";
7417
7418 let datediff = Expression::Function(Box::new(Function::new(
7420 "DATEDIFF".to_string(),
7421 vec![
7422 Expression::boxed_column(Column {
7423 name: Identifier::new(&unit_str),
7424 table: None,
7425 join_mark: false,
7426 trailing_comments: vec![],
7427 span: None,
7428 inferred_type: None,
7429 }),
7430 start_expr.clone(),
7431 end_expr.clone(),
7432 ],
7433 )));
7434 let datediff_plus_one = Expression::Add(Box::new(BinaryOp {
7436 left: datediff,
7437 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
7438 left_comments: vec![],
7439 operator_comments: vec![],
7440 trailing_comments: vec![],
7441 inferred_type: None,
7442 }));
7443
7444 let array_gen_range = Expression::Function(Box::new(Function::new(
7445 "ARRAY_GENERATE_RANGE".to_string(),
7446 vec![
7447 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
7448 datediff_plus_one,
7449 ],
7450 )));
7451
7452 let flatten_input = Expression::NamedArgument(Box::new(NamedArgument {
7453 name: Identifier::new("INPUT"),
7454 value: array_gen_range,
7455 separator: crate::expressions::NamedArgSeparator::DArrow,
7456 }));
7457 let flatten = Expression::Function(Box::new(Function::new(
7458 "FLATTEN".to_string(),
7459 vec![flatten_input],
7460 )));
7461
7462 let table_func =
7463 Expression::Function(Box::new(Function::new("TABLE".to_string(), vec![flatten])));
7464 let flatten_aliased = Expression::Alias(Box::new(Alias {
7465 this: table_func,
7466 alias: Identifier::new("_t0"),
7467 column_aliases: vec![
7468 Identifier::new("seq"),
7469 Identifier::new("key"),
7470 Identifier::new("path"),
7471 Identifier::new("index"),
7472 Identifier::new(col_name),
7473 Identifier::new("this"),
7474 ],
7475 alias_explicit_as: false,
7476 alias_keyword: None,
7477 pre_alias_comments: vec![],
7478 trailing_comments: vec![],
7479 inferred_type: None,
7480 }));
7481
7482 let dateadd_expr = Expression::Function(Box::new(Function::new(
7483 "DATEADD".to_string(),
7484 vec![
7485 Expression::boxed_column(Column {
7486 name: Identifier::new(&unit_str),
7487 table: None,
7488 join_mark: false,
7489 trailing_comments: vec![],
7490 span: None,
7491 inferred_type: None,
7492 }),
7493 Expression::Cast(Box::new(Cast {
7494 this: Expression::boxed_column(Column {
7495 name: Identifier::new(col_name),
7496 table: None,
7497 join_mark: false,
7498 trailing_comments: vec![],
7499 span: None,
7500 inferred_type: None,
7501 }),
7502 to: DataType::Int {
7503 length: None,
7504 integer_spelling: false,
7505 },
7506 trailing_comments: vec![],
7507 double_colon_syntax: false,
7508 format: None,
7509 default: None,
7510 inferred_type: None,
7511 })),
7512 start_expr.clone(),
7513 ],
7514 )));
7515 let dateadd_aliased = Expression::Alias(Box::new(Alias {
7516 this: dateadd_expr,
7517 alias: Identifier::new(col_name),
7518 column_aliases: vec![],
7519 alias_explicit_as: false,
7520 alias_keyword: None,
7521 pre_alias_comments: vec![],
7522 trailing_comments: vec![],
7523 inferred_type: None,
7524 }));
7525
7526 let mut inner_select = Select::new();
7528 inner_select.expressions = vec![dateadd_aliased];
7529 inner_select.from = Some(From {
7530 expressions: vec![flatten_aliased],
7531 });
7532
7533 let inner_subquery = Expression::Subquery(Box::new(Subquery {
7535 this: Expression::Select(Box::new(inner_select)),
7536 alias: None,
7537 column_aliases: vec![],
7538 alias_explicit_as: false,
7539 alias_keyword: None,
7540 order_by: None,
7541 limit: None,
7542 offset: None,
7543 distribute_by: None,
7544 sort_by: None,
7545 cluster_by: None,
7546 lateral: false,
7547 modifiers_inside: false,
7548 trailing_comments: vec![],
7549 inferred_type: None,
7550 }));
7551
7552 let star = Expression::Star(Star {
7554 table: None,
7555 except: None,
7556 replace: None,
7557 rename: None,
7558 trailing_comments: vec![],
7559 span: None,
7560 });
7561 let array_agg = Expression::ArrayAgg(Box::new(AggFunc {
7562 this: star,
7563 distinct: false,
7564 filter: None,
7565 order_by: vec![],
7566 name: Some("ARRAY_AGG".to_string()),
7567 ignore_nulls: None,
7568 having_max: None,
7569 limit: None,
7570 inferred_type: None,
7571 }));
7572
7573 let mut outer_select = Select::new();
7574 outer_select.expressions = vec![array_agg];
7575 outer_select.from = Some(From {
7576 expressions: vec![inner_subquery],
7577 });
7578
7579 let outer_subquery = Expression::Subquery(Box::new(Subquery {
7581 this: Expression::Select(Box::new(outer_select)),
7582 alias: None,
7583 column_aliases: vec![],
7584 alias_explicit_as: false,
7585 alias_keyword: None,
7586 order_by: None,
7587 limit: None,
7588 offset: None,
7589 distribute_by: None,
7590 sort_by: None,
7591 cluster_by: None,
7592 lateral: false,
7593 modifiers_inside: false,
7594 trailing_comments: vec![],
7595 inferred_type: None,
7596 }));
7597
7598 Ok(Expression::ArraySize(Box::new(UnaryFunc::new(
7600 outer_subquery,
7601 ))))
7602 }
7603
7604 fn extract_interval_unit_str(step: &Option<Expression>) -> Option<String> {
7606 use crate::expressions::*;
7607 if let Some(Expression::Interval(ref iv)) = step {
7608 if let Some(IntervalUnitSpec::Simple { ref unit, .. }) = iv.unit {
7609 return Some(format!("{:?}", unit).to_ascii_uppercase());
7610 }
7611 if let Some(ref this) = iv.this {
7612 if let Expression::Literal(lit) = this {
7613 if let Literal::String(ref s) = lit.as_ref() {
7614 let parts: Vec<&str> = s.split_whitespace().collect();
7615 if parts.len() == 2 {
7616 return Some(parts[1].to_ascii_uppercase());
7617 } else if parts.len() == 1 {
7618 let upper = parts[0].to_ascii_uppercase();
7619 if matches!(
7620 upper.as_str(),
7621 "YEAR"
7622 | "QUARTER"
7623 | "MONTH"
7624 | "WEEK"
7625 | "DAY"
7626 | "HOUR"
7627 | "MINUTE"
7628 | "SECOND"
7629 ) {
7630 return Some(upper);
7631 }
7632 }
7633 }
7634 }
7635 }
7636 }
7637 if step.is_none() {
7639 return Some("DAY".to_string());
7640 }
7641 None
7642 }
7643
7644 fn normalize_snowflake_pretty(mut sql: String) -> String {
7645 if sql.contains("LATERAL IFF(_u.pos = _u_2.pos_2, _u_2.entity, NULL) AS datasource(SEQ, KEY, PATH, INDEX, VALUE, THIS)")
7646 && sql.contains("ARRAY_GENERATE_RANGE(0, (GREATEST(ARRAY_SIZE(INPUT => PARSE_JSON(flags))) - 1) + 1)")
7647 {
7648 sql = sql.replace(
7649 "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')",
7650 "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 )",
7651 );
7652
7653 sql = sql.replace(
7654 "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)",
7655 "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)",
7656 );
7657
7658 sql = sql.replace(
7659 "OR (_u.pos > (ARRAY_SIZE(INPUT => PARSE_JSON(flags)) - 1)\n AND _u_2.pos_2 = (ARRAY_SIZE(INPUT => PARSE_JSON(flags)) - 1))",
7660 "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 )",
7661 );
7662 }
7663
7664 sql
7665 }
7666
7667 #[cfg(feature = "transpile")]
7668 fn wrap_tsql_top_level_values(expr: Expression) -> Expression {
7669 match expr {
7670 Expression::Values(values) => Self::tsql_values_as_select(*values),
7671 Expression::Union(mut union) => {
7672 let left = std::mem::replace(&mut union.left, Expression::Null(Null));
7673 let right = std::mem::replace(&mut union.right, Expression::Null(Null));
7674 union.left = Self::wrap_tsql_values_set_operand(left);
7675 union.right = Self::wrap_tsql_values_set_operand(right);
7676 Expression::Union(union)
7677 }
7678 Expression::Intersect(mut intersect) => {
7679 let left = std::mem::replace(&mut intersect.left, Expression::Null(Null));
7680 let right = std::mem::replace(&mut intersect.right, Expression::Null(Null));
7681 intersect.left = Self::wrap_tsql_values_set_operand(left);
7682 intersect.right = Self::wrap_tsql_values_set_operand(right);
7683 Expression::Intersect(intersect)
7684 }
7685 Expression::Except(mut except) => {
7686 let left = std::mem::replace(&mut except.left, Expression::Null(Null));
7687 let right = std::mem::replace(&mut except.right, Expression::Null(Null));
7688 except.left = Self::wrap_tsql_values_set_operand(left);
7689 except.right = Self::wrap_tsql_values_set_operand(right);
7690 Expression::Except(except)
7691 }
7692 other => other,
7693 }
7694 }
7695
7696 #[cfg(feature = "transpile")]
7697 fn wrap_tsql_values_set_operand(expr: Expression) -> Expression {
7698 match expr {
7699 Expression::Values(values) => Self::tsql_values_as_select(*values),
7700 Expression::Union(mut union) => {
7701 let left = std::mem::replace(&mut union.left, Expression::Null(Null));
7702 let right = std::mem::replace(&mut union.right, Expression::Null(Null));
7703 union.left = Self::wrap_tsql_values_set_operand(left);
7704 union.right = Self::wrap_tsql_values_set_operand(right);
7705 Expression::Union(union)
7706 }
7707 Expression::Intersect(mut intersect) => {
7708 let left = std::mem::replace(&mut intersect.left, Expression::Null(Null));
7709 let right = std::mem::replace(&mut intersect.right, Expression::Null(Null));
7710 intersect.left = Self::wrap_tsql_values_set_operand(left);
7711 intersect.right = Self::wrap_tsql_values_set_operand(right);
7712 Expression::Intersect(intersect)
7713 }
7714 Expression::Except(mut except) => {
7715 let left = std::mem::replace(&mut except.left, Expression::Null(Null));
7716 let right = std::mem::replace(&mut except.right, Expression::Null(Null));
7717 except.left = Self::wrap_tsql_values_set_operand(left);
7718 except.right = Self::wrap_tsql_values_set_operand(right);
7719 Expression::Except(except)
7720 }
7721 other => other,
7722 }
7723 }
7724
7725 #[cfg(feature = "transpile")]
7726 fn tsql_values_as_select(mut values: crate::expressions::Values) -> Expression {
7727 let column_aliases = if values.column_aliases.is_empty() {
7728 let column_count = values
7729 .expressions
7730 .first()
7731 .map(|row| row.expressions.len())
7732 .unwrap_or(0);
7733 (1..=column_count)
7734 .map(|index| Identifier::new(format!("column{index}")))
7735 .collect()
7736 } else {
7737 std::mem::take(&mut values.column_aliases)
7738 };
7739
7740 values.alias = None;
7741
7742 let values_subquery = Expression::Subquery(Box::new(crate::expressions::Subquery {
7743 this: Expression::Values(Box::new(values)),
7744 alias: Some(Identifier::new("_v")),
7745 column_aliases,
7746 alias_explicit_as: false,
7747 alias_keyword: None,
7748 order_by: None,
7749 limit: None,
7750 offset: None,
7751 distribute_by: None,
7752 sort_by: None,
7753 cluster_by: None,
7754 lateral: false,
7755 modifiers_inside: false,
7756 trailing_comments: Vec::new(),
7757 inferred_type: None,
7758 }));
7759
7760 let mut select = crate::expressions::Select::new();
7761 select.expressions = vec![Expression::star()];
7762 select.from = Some(From {
7763 expressions: vec![values_subquery],
7764 });
7765
7766 Expression::Select(Box::new(select))
7767 }
7768
7769 fn extract_interval_parts(
7770 interval_expr: &Expression,
7771 ) -> Option<(Expression, crate::expressions::IntervalUnit)> {
7772 use crate::expressions::{DataType, IntervalUnit, IntervalUnitSpec, Literal};
7773
7774 fn unit_from_str(unit: &str) -> Option<IntervalUnit> {
7775 match unit.trim().to_ascii_uppercase().as_str() {
7776 "YEAR" | "YEARS" | "Y" | "YR" | "YRS" | "YY" | "YYYY" => Some(IntervalUnit::Year),
7777 "QUARTER" | "QUARTERS" | "Q" | "QTR" | "QTRS" | "QQ" => Some(IntervalUnit::Quarter),
7778 "MONTH" | "MONTHS" | "MON" | "MONS" | "MM" => Some(IntervalUnit::Month),
7779 "WEEK" | "WEEKS" | "W" | "WK" | "WKS" | "WW" | "ISOWEEK" => {
7780 Some(IntervalUnit::Week)
7781 }
7782 "DAY" | "DAYS" | "D" | "DD" => Some(IntervalUnit::Day),
7783 "HOUR" | "HOURS" | "H" | "HH" | "HR" | "HRS" => Some(IntervalUnit::Hour),
7784 "MINUTE" | "MINUTES" | "MI" | "MIN" | "MINS" | "N" => Some(IntervalUnit::Minute),
7785 "SECOND" | "SECONDS" | "S" | "SEC" | "SECS" | "SS" => Some(IntervalUnit::Second),
7786 "MILLISECOND" | "MILLISECONDS" | "MS" | "MSEC" | "MSECS" | "MSECOND"
7787 | "MSECONDS" | "MILLISEC" | "MILLISECS" | "MILLISECON" => {
7788 Some(IntervalUnit::Millisecond)
7789 }
7790 "MICROSECOND" | "MICROSECONDS" | "US" | "USEC" | "USECS" | "USECOND"
7791 | "USECONDS" | "MICROSEC" | "MICROSECS" | "MCS" => Some(IntervalUnit::Microsecond),
7792 "NANOSECOND" | "NANOSECONDS" | "NS" | "NSEC" | "NSECS" | "NSECOND" | "NSECONDS"
7793 | "NANOSEC" | "NANOSECS" => Some(IntervalUnit::Nanosecond),
7794 _ => None,
7795 }
7796 }
7797
7798 fn parts_from_literal_string(s: &str) -> Option<(Expression, IntervalUnit)> {
7799 let mut parts = s.split_whitespace();
7800 let value = parts.next()?;
7801 let unit = unit_from_str(parts.next()?)?;
7802 Some((
7803 Expression::Literal(Box::new(Literal::String(value.to_string()))),
7804 unit,
7805 ))
7806 }
7807
7808 fn unit_from_spec(unit: &IntervalUnitSpec) -> Option<IntervalUnit> {
7809 match unit {
7810 IntervalUnitSpec::Simple { unit, .. } => Some(*unit),
7811 IntervalUnitSpec::Expr(expr) => match expr.as_ref() {
7812 Expression::Day(_) => Some(IntervalUnit::Day),
7813 Expression::Month(_) => Some(IntervalUnit::Month),
7814 Expression::Year(_) => Some(IntervalUnit::Year),
7815 Expression::Identifier(id) => unit_from_str(&id.name),
7816 Expression::Var(v) => unit_from_str(&v.this),
7817 Expression::Column(col) => unit_from_str(&col.name.name),
7818 _ => None,
7819 },
7820 _ => None,
7821 }
7822 }
7823
7824 match interval_expr {
7825 Expression::Interval(iv) => {
7826 let val = iv.this.clone().unwrap_or(Expression::number(0));
7827 if let Expression::Literal(lit) = &val {
7828 if let Literal::String(s) = lit.as_ref() {
7829 if let Some(parts) = parts_from_literal_string(s) {
7830 return Some(parts);
7831 }
7832 }
7833 }
7834 let unit = iv
7835 .unit
7836 .as_ref()
7837 .and_then(unit_from_spec)
7838 .unwrap_or(IntervalUnit::Day);
7839 Some((val, unit))
7840 }
7841 Expression::Cast(cast) if matches!(cast.to, DataType::Interval { .. }) => {
7842 if let Expression::Literal(lit) = &cast.this {
7843 if let Literal::String(s) = lit.as_ref() {
7844 if let Some(parts) = parts_from_literal_string(s) {
7845 return Some(parts);
7846 }
7847 }
7848 }
7849 let unit = match &cast.to {
7850 DataType::Interval {
7851 unit: Some(unit), ..
7852 } => unit_from_str(unit).unwrap_or(IntervalUnit::Day),
7853 _ => IntervalUnit::Day,
7854 };
7855 Some((cast.this.clone(), unit))
7856 }
7857 _ => None,
7858 }
7859 }
7860
7861 fn data_type_is_interval(dt: &DataType) -> bool {
7862 match dt {
7863 DataType::Interval { .. } => true,
7864 DataType::Custom { name } => name.trim().eq_ignore_ascii_case("INTERVAL"),
7865 _ => false,
7866 }
7867 }
7868
7869 fn node_is_interval_cast(node: &Expression) -> bool {
7870 match node {
7871 Expression::Cast(c) | Expression::TryCast(c) | Expression::SafeCast(c) => {
7872 Self::data_type_is_interval(&c.to)
7873 }
7874 _ => false,
7875 }
7876 }
7877
7878 fn reject_tsql_interval_casts(
7879 expr: &Expression,
7880 target: DialectType,
7881 opts: &TranspileOptions,
7882 ) -> Result<()> {
7883 if !matches!(
7884 opts.unsupported_level,
7885 UnsupportedLevel::Raise | UnsupportedLevel::Immediate
7886 ) {
7887 return Ok(());
7888 }
7889
7890 if expr.dfs().any(Self::node_is_interval_cast) {
7891 return Err(crate::error::Error::unsupported(
7892 "INTERVAL casts",
7893 target.to_string(),
7894 ));
7895 }
7896
7897 Ok(())
7898 }
7899
7900 fn tsql_varchar_max_type() -> DataType {
7901 DataType::Custom {
7902 name: "VARCHAR(MAX)".to_string(),
7903 }
7904 }
7905
7906 fn rewrite_tsql_interval_casts_to_varchar(expr: Expression) -> Result<Expression> {
7907 transform_recursive(expr, &|e| match e {
7908 Expression::Cast(mut cast) if Self::data_type_is_interval(&cast.to) => {
7909 cast.to = Self::tsql_varchar_max_type();
7910 cast.double_colon_syntax = false;
7911 Ok(Expression::Cast(cast))
7912 }
7913 Expression::TryCast(mut cast) if Self::data_type_is_interval(&cast.to) => {
7914 cast.to = Self::tsql_varchar_max_type();
7915 cast.double_colon_syntax = false;
7916 Ok(Expression::TryCast(cast))
7917 }
7918 Expression::SafeCast(mut cast) if Self::data_type_is_interval(&cast.to) => {
7919 cast.to = Self::tsql_varchar_max_type();
7920 cast.double_colon_syntax = false;
7921 Ok(Expression::SafeCast(cast))
7922 }
7923 _ => Ok(e),
7924 })
7925 }
7926
7927 fn rewrite_tsql_interval_arithmetic(
7928 expr: &Expression,
7929 source: DialectType,
7930 ) -> Option<Expression> {
7931 match expr {
7932 Expression::Add(op) => {
7933 if Self::extract_interval_parts(&op.right).is_some() {
7934 return Some(Self::build_tsql_dateadd_from_interval(
7935 op.left.clone(),
7936 &op.right,
7937 false,
7938 ));
7939 }
7940
7941 if Self::is_postgres_family_source(source) {
7942 if Self::is_explicit_date_expr(&op.left)
7943 && Self::is_integer_day_offset_expr(&op.right)
7944 {
7945 return Some(Self::build_tsql_dateadd_days(
7946 op.left.clone(),
7947 op.right.clone(),
7948 false,
7949 ));
7950 }
7951
7952 if Self::is_integer_day_offset_expr(&op.left)
7953 && Self::is_explicit_date_expr(&op.right)
7954 {
7955 return Some(Self::build_tsql_dateadd_days(
7956 op.right.clone(),
7957 op.left.clone(),
7958 false,
7959 ));
7960 }
7961 }
7962
7963 None
7964 }
7965 Expression::Sub(op) => {
7966 if Self::extract_interval_parts(&op.right).is_some() {
7967 return Some(Self::build_tsql_dateadd_from_interval(
7968 op.left.clone(),
7969 &op.right,
7970 true,
7971 ));
7972 }
7973
7974 if Self::is_postgres_family_source(source) {
7975 if Self::is_explicit_date_expr(&op.left)
7976 && Self::is_explicit_date_expr(&op.right)
7977 {
7978 return Some(Self::build_tsql_datediff_days(
7979 op.right.clone(),
7980 op.left.clone(),
7981 ));
7982 }
7983
7984 if Self::is_explicit_date_expr(&op.left)
7985 && Self::is_integer_day_offset_expr(&op.right)
7986 {
7987 return Some(Self::build_tsql_dateadd_days(
7988 op.left.clone(),
7989 op.right.clone(),
7990 true,
7991 ));
7992 }
7993 }
7994
7995 None
7996 }
7997 _ => None,
7998 }
7999 }
8000
8001 fn is_postgres_family_source(source: DialectType) -> bool {
8002 matches!(
8003 source,
8004 DialectType::PostgreSQL
8005 | DialectType::Redshift
8006 | DialectType::Materialize
8007 | DialectType::RisingWave
8008 | DialectType::CockroachDB
8009 )
8010 }
8011
8012 fn is_explicit_date_expr(expr: &Expression) -> bool {
8013 use crate::expressions::Literal;
8014
8015 match expr {
8016 Expression::Literal(lit) => matches!(lit.as_ref(), Literal::Date(_)),
8017 Expression::Cast(c) | Expression::TryCast(c) | Expression::SafeCast(c) => {
8018 matches!(c.to, crate::expressions::DataType::Date)
8019 }
8020 Expression::Paren(p) => Self::is_explicit_date_expr(&p.this),
8021 Expression::CurrentDate(_)
8022 | Expression::Date(_)
8023 | Expression::MakeDate(_)
8024 | Expression::ToDate(_)
8025 | Expression::DateStrToDate(_) => true,
8026 _ => false,
8027 }
8028 }
8029
8030 fn is_integer_day_offset_expr(expr: &Expression) -> bool {
8031 use crate::expressions::Literal;
8032
8033 match expr {
8034 Expression::Literal(lit) => match lit.as_ref() {
8035 Literal::Number(n) => n.parse::<i64>().is_ok(),
8036 _ => false,
8037 },
8038 Expression::Parameter(_) | Expression::Placeholder(_) => true,
8039 Expression::Neg(op) => Self::is_integer_day_offset_expr(&op.this),
8040 Expression::Paren(p) => Self::is_integer_day_offset_expr(&p.this),
8041 _ => false,
8042 }
8043 }
8044
8045 fn build_tsql_datediff_days(start: Expression, end: Expression) -> Expression {
8046 Expression::Function(Box::new(Function::new(
8047 "DATEDIFF".to_string(),
8048 vec![Expression::Identifier(Identifier::new("DAY")), start, end],
8049 )))
8050 }
8051
8052 fn build_tsql_dateadd_days(date: Expression, amount: Expression, subtract: bool) -> Expression {
8053 Expression::Function(Box::new(Function::new(
8054 "DATEADD".to_string(),
8055 vec![
8056 Expression::Identifier(Identifier::new("DAY")),
8057 Self::tsql_dateadd_amount(amount, subtract),
8058 date,
8059 ],
8060 )))
8061 }
8062
8063 fn build_tsql_dateadd_from_interval(
8064 date: Expression,
8065 interval: &Expression,
8066 subtract: bool,
8067 ) -> Expression {
8068 let (value, unit) = Self::extract_interval_parts(interval)
8069 .unwrap_or_else(|| (interval.clone(), crate::expressions::IntervalUnit::Day));
8070 let unit = normalization::temporal::interval_unit_to_string(&unit);
8071 let amount = Self::tsql_dateadd_amount(value, subtract);
8072
8073 Expression::Function(Box::new(Function::new(
8074 "DATEADD".to_string(),
8075 vec![Expression::Identifier(Identifier::new(unit)), amount, date],
8076 )))
8077 }
8078
8079 fn tsql_dateadd_amount(value: Expression, negate: bool) -> Expression {
8080 use crate::expressions::{Parameter, ParameterStyle, UnaryOp};
8081
8082 fn numeric_literal_value(value: &Expression) -> Option<&str> {
8083 match value {
8084 Expression::Literal(lit) => match lit.as_ref() {
8085 crate::expressions::Literal::Number(n)
8086 | crate::expressions::Literal::String(n) => Some(n.as_str()),
8087 _ => None,
8088 },
8089 _ => None,
8090 }
8091 }
8092
8093 fn colon_parameter(value: &Expression) -> Option<Expression> {
8094 let Expression::Literal(lit) = value else {
8095 return None;
8096 };
8097 let crate::expressions::Literal::String(s) = lit.as_ref() else {
8098 return None;
8099 };
8100 let name = s.strip_prefix(':')?;
8101 if name.is_empty()
8102 || !name
8103 .chars()
8104 .all(|ch| ch.is_ascii_alphanumeric() || ch == '_')
8105 {
8106 return None;
8107 }
8108
8109 Some(Expression::Parameter(Box::new(Parameter {
8110 name: if name.chars().all(|ch| ch.is_ascii_digit()) {
8111 None
8112 } else {
8113 Some(name.to_string())
8114 },
8115 index: name.parse::<u32>().ok(),
8116 style: ParameterStyle::Colon,
8117 quoted: false,
8118 string_quoted: false,
8119 expression: None,
8120 })))
8121 }
8122
8123 let value = colon_parameter(&value).unwrap_or(value);
8124
8125 if let Some(n) = numeric_literal_value(&value) {
8126 if let Ok(parsed) = n.parse::<f64>() {
8127 let normalized = if negate { -parsed } else { parsed };
8128 let rendered = if normalized.fract() == 0.0 {
8129 format!("{}", normalized as i64)
8130 } else {
8131 normalized.to_string()
8132 };
8133 return Expression::Literal(Box::new(crate::expressions::Literal::Number(
8134 rendered,
8135 )));
8136 }
8137 }
8138
8139 if !negate {
8140 return value;
8141 }
8142
8143 match value {
8144 Expression::Neg(op) => op.this,
8145 other => Expression::Neg(Box::new(UnaryOp {
8146 this: other,
8147 inferred_type: None,
8148 })),
8149 }
8150 }
8151
8152 const PRESERVED_TO_DATE: &'static str = "_POLYGLOT_TO_DATE";
8156}
8157
8158#[cfg(test)]
8159mod tests {
8160 use super::*;
8161
8162 #[test]
8163 fn built_in_dialect_instances_share_tokenizer_config() {
8164 let first = Dialect::get(DialectType::PostgreSQL);
8165 let second = Dialect::get(DialectType::PostgreSQL);
8166
8167 assert!(first.tokenizer.shares_config_with(&second.tokenizer));
8168 }
8169
8170 #[test]
8171 fn test_dialect_type_from_str() {
8172 assert_eq!(
8173 "postgres".parse::<DialectType>().unwrap(),
8174 DialectType::PostgreSQL
8175 );
8176 assert_eq!(
8177 "postgresql".parse::<DialectType>().unwrap(),
8178 DialectType::PostgreSQL
8179 );
8180 assert_eq!("mysql".parse::<DialectType>().unwrap(), DialectType::MySQL);
8181 assert_eq!(
8182 "bigquery".parse::<DialectType>().unwrap(),
8183 DialectType::BigQuery
8184 );
8185 }
8186
8187 #[test]
8188 fn test_basic_transpile() {
8189 let dialect = Dialect::get(DialectType::Generic);
8190 let result = dialect
8191 .transpile("SELECT 1", DialectType::PostgreSQL)
8192 .unwrap();
8193 assert_eq!(result.len(), 1);
8194 assert_eq!(result[0], "SELECT 1");
8195 }
8196
8197 #[test]
8198 fn test_sqlite_double_quoted_column_defaults_to_postgres_strings() {
8199 let sqlite = Dialect::get(DialectType::SQLite);
8200 let result = sqlite
8201 .transpile(
8202 r#"CREATE TABLE "_collections" (
8203 "type" TEXT DEFAULT "base" NOT NULL,
8204 "fields" JSON DEFAULT "[]" NOT NULL,
8205 "options" JSON DEFAULT "{}" NOT NULL
8206 )"#,
8207 DialectType::PostgreSQL,
8208 )
8209 .unwrap();
8210
8211 assert!(result[0].contains(r#""type" TEXT DEFAULT 'base' NOT NULL"#));
8212 assert!(result[0].contains(r#""fields" JSON DEFAULT '[]' NOT NULL"#));
8213 assert!(result[0].contains(r#""options" JSON DEFAULT '{}' NOT NULL"#));
8214 }
8215
8216 #[test]
8217 fn test_sqlite_identity_preserves_double_quoted_column_defaults() {
8218 let sqlite = Dialect::get(DialectType::SQLite);
8219 let result = sqlite
8220 .transpile(
8221 r#"CREATE TABLE "_collections" ("type" TEXT DEFAULT "base" NOT NULL)"#,
8222 DialectType::SQLite,
8223 )
8224 .unwrap();
8225
8226 assert_eq!(
8227 result[0],
8228 r#"CREATE TABLE "_collections" ("type" TEXT DEFAULT "base" NOT NULL)"#
8229 );
8230 }
8231
8232 #[test]
8233 fn test_function_transformation_mysql() {
8234 let dialect = Dialect::get(DialectType::Generic);
8236 let result = dialect
8237 .transpile("SELECT NVL(a, b)", DialectType::MySQL)
8238 .unwrap();
8239 assert_eq!(result[0], "SELECT IFNULL(a, b)");
8240 }
8241
8242 #[test]
8243 fn test_get_path_duckdb() {
8244 let snowflake = Dialect::get(DialectType::Snowflake);
8246
8247 let result_sf_sf = snowflake
8249 .transpile(
8250 "SELECT PARSE_JSON('{\"fruit\":\"banana\"}'):fruit",
8251 DialectType::Snowflake,
8252 )
8253 .unwrap();
8254 eprintln!("Snowflake->Snowflake colon: {}", result_sf_sf[0]);
8255
8256 let result_sf_dk = snowflake
8258 .transpile(
8259 "SELECT PARSE_JSON('{\"fruit\":\"banana\"}'):fruit",
8260 DialectType::DuckDB,
8261 )
8262 .unwrap();
8263 eprintln!("Snowflake->DuckDB colon: {}", result_sf_dk[0]);
8264
8265 let result_gp = snowflake
8267 .transpile(
8268 "SELECT GET_PATH(PARSE_JSON('{\"fruit\":\"banana\"}'), 'fruit')",
8269 DialectType::DuckDB,
8270 )
8271 .unwrap();
8272 eprintln!("Snowflake->DuckDB explicit GET_PATH: {}", result_gp[0]);
8273 }
8274
8275 #[test]
8276 fn test_function_transformation_postgres() {
8277 let dialect = Dialect::get(DialectType::Generic);
8279 let result = dialect
8280 .transpile("SELECT IFNULL(a, b)", DialectType::PostgreSQL)
8281 .unwrap();
8282 assert_eq!(result[0], "SELECT COALESCE(a, b)");
8283
8284 let result = dialect
8286 .transpile("SELECT NVL(a, b)", DialectType::PostgreSQL)
8287 .unwrap();
8288 assert_eq!(result[0], "SELECT COALESCE(a, b)");
8289 }
8290
8291 #[test]
8292 fn test_hive_cast_to_trycast() {
8293 let hive = Dialect::get(DialectType::Hive);
8295 let result = hive
8296 .transpile("CAST(1 AS INT)", DialectType::DuckDB)
8297 .unwrap();
8298 assert_eq!(result[0], "TRY_CAST(1 AS INT)");
8299
8300 let result = hive
8301 .transpile("CAST(1 AS INT)", DialectType::Presto)
8302 .unwrap();
8303 assert_eq!(result[0], "TRY_CAST(1 AS INTEGER)");
8304 }
8305
8306 #[test]
8307 fn test_hive_array_identity() {
8308 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')";
8310 let hive = Dialect::get(DialectType::Hive);
8311
8312 let result = hive.transpile(sql, DialectType::Hive).unwrap();
8314 eprintln!("Hive ARRAY via transpile: {}", result[0]);
8315 assert!(
8316 result[0].contains("ARRAY<DATE>"),
8317 "transpile: Expected ARRAY<DATE>, got: {}",
8318 result[0]
8319 );
8320
8321 let ast = hive.parse(sql).unwrap();
8323 let transformed = hive.transform(ast[0].clone()).unwrap();
8324 let output = hive.generate(&transformed).unwrap();
8325 eprintln!("Hive ARRAY via identity path: {}", output);
8326 assert!(
8327 output.contains("ARRAY<DATE>"),
8328 "identity path: Expected ARRAY<DATE>, got: {}",
8329 output
8330 );
8331 }
8332
8333 #[test]
8334 fn test_starrocks_delete_between_expansion() {
8335 let dialect = Dialect::get(DialectType::Generic);
8337
8338 let result = dialect
8340 .transpile(
8341 "DELETE FROM t WHERE a BETWEEN b AND c",
8342 DialectType::StarRocks,
8343 )
8344 .unwrap();
8345 assert_eq!(result[0], "DELETE FROM t WHERE a >= b AND a <= c");
8346
8347 let result = dialect
8349 .transpile(
8350 "DELETE FROM t WHERE a NOT BETWEEN b AND c",
8351 DialectType::StarRocks,
8352 )
8353 .unwrap();
8354 assert_eq!(result[0], "DELETE FROM t WHERE a < b OR a > c");
8355
8356 let result = dialect
8358 .transpile(
8359 "SELECT * FROM t WHERE a BETWEEN b AND c",
8360 DialectType::StarRocks,
8361 )
8362 .unwrap();
8363 assert!(
8364 result[0].contains("BETWEEN"),
8365 "BETWEEN should be preserved in SELECT"
8366 );
8367 }
8368
8369 #[test]
8370 fn test_snowflake_ltrim_rtrim_parse() {
8371 let sf = Dialect::get(DialectType::Snowflake);
8372 let sql = "SELECT LTRIM(RTRIM(col)) FROM t1";
8373 let result = sf.transpile(sql, DialectType::DuckDB);
8374 match &result {
8375 Ok(r) => eprintln!("LTRIM/RTRIM result: {}", r[0]),
8376 Err(e) => eprintln!("LTRIM/RTRIM error: {}", e),
8377 }
8378 assert!(
8379 result.is_ok(),
8380 "Expected successful parse of LTRIM(RTRIM(col)), got error: {:?}",
8381 result.err()
8382 );
8383 }
8384
8385 #[test]
8386 fn test_duckdb_count_if_parse() {
8387 let duck = Dialect::get(DialectType::DuckDB);
8388 let sql = "COUNT_IF(x)";
8389 let result = duck.transpile(sql, DialectType::DuckDB);
8390 match &result {
8391 Ok(r) => eprintln!("COUNT_IF result: {}", r[0]),
8392 Err(e) => eprintln!("COUNT_IF error: {}", e),
8393 }
8394 assert!(
8395 result.is_ok(),
8396 "Expected successful parse of COUNT_IF(x), got error: {:?}",
8397 result.err()
8398 );
8399 }
8400
8401 #[test]
8402 fn test_tsql_cast_tinyint_parse() {
8403 let tsql = Dialect::get(DialectType::TSQL);
8404 let sql = "CAST(X AS TINYINT)";
8405 let result = tsql.transpile(sql, DialectType::DuckDB);
8406 match &result {
8407 Ok(r) => eprintln!("TSQL CAST TINYINT result: {}", r[0]),
8408 Err(e) => eprintln!("TSQL CAST TINYINT error: {}", e),
8409 }
8410 assert!(
8411 result.is_ok(),
8412 "Expected successful transpile, got error: {:?}",
8413 result.err()
8414 );
8415 }
8416
8417 #[test]
8418 fn test_pg_hash_bitwise_xor() {
8419 let dialect = Dialect::get(DialectType::PostgreSQL);
8420 let result = dialect.transpile("x # y", DialectType::PostgreSQL).unwrap();
8421 assert_eq!(result[0], "x # y");
8422 }
8423
8424 #[test]
8425 fn test_pg_array_to_duckdb() {
8426 let dialect = Dialect::get(DialectType::PostgreSQL);
8427 let result = dialect
8428 .transpile("SELECT ARRAY[1, 2, 3] @> ARRAY[1, 2]", DialectType::DuckDB)
8429 .unwrap();
8430 assert_eq!(result[0], "SELECT [1, 2, 3] @> [1, 2]");
8431 }
8432
8433 #[test]
8434 fn test_array_remove_bigquery() {
8435 let dialect = Dialect::get(DialectType::Generic);
8436 let result = dialect
8437 .transpile("ARRAY_REMOVE(the_array, target)", DialectType::BigQuery)
8438 .unwrap();
8439 assert_eq!(
8440 result[0],
8441 "ARRAY(SELECT _u FROM UNNEST(the_array) AS _u WHERE _u <> target)"
8442 );
8443 }
8444
8445 #[test]
8446 fn test_map_clickhouse_case() {
8447 let dialect = Dialect::get(DialectType::Generic);
8448 let parsed = dialect
8449 .parse("CAST(MAP('a', '1') AS MAP(TEXT, TEXT))")
8450 .unwrap();
8451 eprintln!("MAP parsed: {:?}", parsed);
8452 let result = dialect
8453 .transpile(
8454 "CAST(MAP('a', '1') AS MAP(TEXT, TEXT))",
8455 DialectType::ClickHouse,
8456 )
8457 .unwrap();
8458 eprintln!("MAP result: {}", result[0]);
8459 }
8460
8461 #[test]
8462 fn test_generate_date_array_presto() {
8463 let dialect = Dialect::get(DialectType::Generic);
8464 let result = dialect.transpile(
8465 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8466 DialectType::Presto,
8467 ).unwrap();
8468 eprintln!("GDA -> Presto: {}", result[0]);
8469 assert_eq!(result[0], "SELECT * FROM UNNEST(SEQUENCE(CAST('2020-01-01' AS DATE), CAST('2020-02-01' AS DATE), (1 * INTERVAL '7' DAY)))");
8470 }
8471
8472 #[test]
8473 fn test_generate_date_array_postgres() {
8474 let dialect = Dialect::get(DialectType::Generic);
8475 let result = dialect.transpile(
8476 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8477 DialectType::PostgreSQL,
8478 ).unwrap();
8479 eprintln!("GDA -> PostgreSQL: {}", result[0]);
8480 }
8481
8482 #[test]
8483 fn test_generate_date_array_snowflake() {
8484 let dialect = Dialect::get(DialectType::Generic);
8485 let result = dialect
8486 .transpile(
8487 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8488 DialectType::Snowflake,
8489 )
8490 .unwrap();
8491 eprintln!("GDA -> Snowflake: {}", result[0]);
8492 }
8493
8494 #[test]
8495 fn test_array_length_generate_date_array_snowflake() {
8496 let dialect = Dialect::get(DialectType::Generic);
8497 let result = dialect.transpile(
8498 "SELECT ARRAY_LENGTH(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8499 DialectType::Snowflake,
8500 ).unwrap();
8501 eprintln!("ARRAY_LENGTH(GDA) -> Snowflake: {}", result[0]);
8502 }
8503
8504 #[test]
8505 fn test_generate_date_array_mysql() {
8506 let dialect = Dialect::get(DialectType::Generic);
8507 let result = dialect.transpile(
8508 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8509 DialectType::MySQL,
8510 ).unwrap();
8511 eprintln!("GDA -> MySQL: {}", result[0]);
8512 }
8513
8514 #[test]
8515 fn test_generate_date_array_redshift() {
8516 let dialect = Dialect::get(DialectType::Generic);
8517 let result = dialect.transpile(
8518 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8519 DialectType::Redshift,
8520 ).unwrap();
8521 eprintln!("GDA -> Redshift: {}", result[0]);
8522 }
8523
8524 #[test]
8525 fn test_generate_date_array_tsql() {
8526 let dialect = Dialect::get(DialectType::Generic);
8527 let result = dialect.transpile(
8528 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8529 DialectType::TSQL,
8530 ).unwrap();
8531 eprintln!("GDA -> TSQL: {}", result[0]);
8532 }
8533
8534 #[test]
8535 fn test_struct_colon_syntax() {
8536 let dialect = Dialect::get(DialectType::Generic);
8537 let result = dialect.transpile(
8539 "CAST((1, 2, 3, 4) AS STRUCT<a TINYINT, b SMALLINT, c INT, d BIGINT>)",
8540 DialectType::ClickHouse,
8541 );
8542 match result {
8543 Ok(r) => eprintln!("STRUCT no colon -> ClickHouse: {}", r[0]),
8544 Err(e) => eprintln!("STRUCT no colon error: {}", e),
8545 }
8546 let result = dialect.transpile(
8548 "CAST((1, 2, 3, 4) AS STRUCT<a: TINYINT, b: SMALLINT, c: INT, d: BIGINT>)",
8549 DialectType::ClickHouse,
8550 );
8551 match result {
8552 Ok(r) => eprintln!("STRUCT colon -> ClickHouse: {}", r[0]),
8553 Err(e) => eprintln!("STRUCT colon error: {}", e),
8554 }
8555 }
8556
8557 #[test]
8558 fn test_generate_date_array_cte_wrapped_mysql() {
8559 let dialect = Dialect::get(DialectType::Generic);
8560 let result = dialect.transpile(
8561 "WITH dates AS (SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))) SELECT * FROM dates",
8562 DialectType::MySQL,
8563 ).unwrap();
8564 eprintln!("GDA CTE -> MySQL: {}", result[0]);
8565 }
8566
8567 #[test]
8568 fn test_generate_date_array_cte_wrapped_tsql() {
8569 let dialect = Dialect::get(DialectType::Generic);
8570 let result = dialect.transpile(
8571 "WITH dates AS (SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))) SELECT * FROM dates",
8572 DialectType::TSQL,
8573 ).unwrap();
8574 eprintln!("GDA CTE -> TSQL: {}", result[0]);
8575 }
8576
8577 #[test]
8578 fn test_decode_literal_no_null_check() {
8579 let dialect = Dialect::get(DialectType::Oracle);
8581 let result = dialect
8582 .transpile("SELECT decode(1,2,3,4)", DialectType::DuckDB)
8583 .unwrap();
8584 assert_eq!(
8585 result[0], "SELECT CASE WHEN 1 = 2 THEN 3 ELSE 4 END",
8586 "Literal DECODE should not have IS NULL checks"
8587 );
8588 }
8589
8590 #[test]
8591 fn test_decode_column_vs_literal_no_null_check() {
8592 let dialect = Dialect::get(DialectType::Oracle);
8594 let result = dialect
8595 .transpile("SELECT decode(col, 2, 3, 4) FROM t", DialectType::DuckDB)
8596 .unwrap();
8597 assert_eq!(
8598 result[0], "SELECT CASE WHEN col = 2 THEN 3 ELSE 4 END FROM t",
8599 "Column vs literal DECODE should not have IS NULL checks"
8600 );
8601 }
8602
8603 #[test]
8604 fn test_decode_column_vs_column_keeps_null_check() {
8605 let dialect = Dialect::get(DialectType::Oracle);
8607 let result = dialect
8608 .transpile("SELECT decode(col, col2, 3, 4) FROM t", DialectType::DuckDB)
8609 .unwrap();
8610 assert!(
8611 result[0].contains("IS NULL"),
8612 "Column vs column DECODE should have IS NULL checks, got: {}",
8613 result[0]
8614 );
8615 }
8616
8617 #[test]
8618 fn test_decode_null_search() {
8619 let dialect = Dialect::get(DialectType::Oracle);
8621 let result = dialect
8622 .transpile("SELECT decode(col, NULL, 3, 4) FROM t", DialectType::DuckDB)
8623 .unwrap();
8624 assert_eq!(
8625 result[0],
8626 "SELECT CASE WHEN col IS NULL THEN 3 ELSE 4 END FROM t",
8627 );
8628 }
8629
8630 #[test]
8635 fn test_regexp_substr_snowflake_to_duckdb_2arg() {
8636 let dialect = Dialect::get(DialectType::Snowflake);
8637 let result = dialect
8638 .transpile("SELECT REGEXP_SUBSTR(s, 'pattern')", DialectType::DuckDB)
8639 .unwrap();
8640 assert_eq!(result[0], "SELECT REGEXP_EXTRACT(s, 'pattern')");
8641 }
8642
8643 #[test]
8644 fn test_regexp_substr_snowflake_to_duckdb_3arg_pos1() {
8645 let dialect = Dialect::get(DialectType::Snowflake);
8646 let result = dialect
8647 .transpile("SELECT REGEXP_SUBSTR(s, 'pattern', 1)", DialectType::DuckDB)
8648 .unwrap();
8649 assert_eq!(result[0], "SELECT REGEXP_EXTRACT(s, 'pattern')");
8650 }
8651
8652 #[test]
8653 fn test_regexp_substr_snowflake_to_duckdb_3arg_pos_gt1() {
8654 let dialect = Dialect::get(DialectType::Snowflake);
8655 let result = dialect
8656 .transpile("SELECT REGEXP_SUBSTR(s, 'pattern', 3)", DialectType::DuckDB)
8657 .unwrap();
8658 assert_eq!(
8659 result[0],
8660 "SELECT REGEXP_EXTRACT(NULLIF(SUBSTRING(s, 3), ''), 'pattern')"
8661 );
8662 }
8663
8664 #[test]
8665 fn test_regexp_substr_snowflake_to_duckdb_4arg_occ_gt1() {
8666 let dialect = Dialect::get(DialectType::Snowflake);
8667 let result = dialect
8668 .transpile(
8669 "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 3)",
8670 DialectType::DuckDB,
8671 )
8672 .unwrap();
8673 assert_eq!(
8674 result[0],
8675 "SELECT ARRAY_EXTRACT(REGEXP_EXTRACT_ALL(s, 'pattern'), 3)"
8676 );
8677 }
8678
8679 #[test]
8680 fn test_regexp_substr_snowflake_to_duckdb_5arg_e_flag() {
8681 let dialect = Dialect::get(DialectType::Snowflake);
8682 let result = dialect
8683 .transpile(
8684 "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 1, 'e')",
8685 DialectType::DuckDB,
8686 )
8687 .unwrap();
8688 assert_eq!(result[0], "SELECT REGEXP_EXTRACT(s, 'pattern')");
8689 }
8690
8691 #[test]
8692 fn test_regexp_substr_snowflake_to_duckdb_6arg_group0() {
8693 let dialect = Dialect::get(DialectType::Snowflake);
8694 let result = dialect
8695 .transpile(
8696 "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 1, 'e', 0)",
8697 DialectType::DuckDB,
8698 )
8699 .unwrap();
8700 assert_eq!(result[0], "SELECT REGEXP_EXTRACT(s, 'pattern')");
8701 }
8702
8703 #[test]
8704 fn test_regexp_substr_snowflake_identity_strip_group0() {
8705 let dialect = Dialect::get(DialectType::Snowflake);
8706 let result = dialect
8707 .transpile(
8708 "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 1, 'e', 0)",
8709 DialectType::Snowflake,
8710 )
8711 .unwrap();
8712 assert_eq!(result[0], "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 1, 'e')");
8713 }
8714
8715 #[test]
8716 fn test_regexp_substr_all_snowflake_to_duckdb_2arg() {
8717 let dialect = Dialect::get(DialectType::Snowflake);
8718 let result = dialect
8719 .transpile(
8720 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern')",
8721 DialectType::DuckDB,
8722 )
8723 .unwrap();
8724 assert_eq!(result[0], "SELECT REGEXP_EXTRACT_ALL(s, 'pattern')");
8725 }
8726
8727 #[test]
8728 fn test_regexp_substr_all_snowflake_to_duckdb_3arg_pos_gt1() {
8729 let dialect = Dialect::get(DialectType::Snowflake);
8730 let result = dialect
8731 .transpile(
8732 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 3)",
8733 DialectType::DuckDB,
8734 )
8735 .unwrap();
8736 assert_eq!(
8737 result[0],
8738 "SELECT REGEXP_EXTRACT_ALL(SUBSTRING(s, 3), 'pattern')"
8739 );
8740 }
8741
8742 #[test]
8743 fn test_regexp_substr_all_snowflake_to_duckdb_5arg_e_flag() {
8744 let dialect = Dialect::get(DialectType::Snowflake);
8745 let result = dialect
8746 .transpile(
8747 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 1, 1, 'e')",
8748 DialectType::DuckDB,
8749 )
8750 .unwrap();
8751 assert_eq!(result[0], "SELECT REGEXP_EXTRACT_ALL(s, 'pattern')");
8752 }
8753
8754 #[test]
8755 fn test_regexp_substr_all_snowflake_to_duckdb_6arg_group0() {
8756 let dialect = Dialect::get(DialectType::Snowflake);
8757 let result = dialect
8758 .transpile(
8759 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 1, 1, 'e', 0)",
8760 DialectType::DuckDB,
8761 )
8762 .unwrap();
8763 assert_eq!(result[0], "SELECT REGEXP_EXTRACT_ALL(s, 'pattern')");
8764 }
8765
8766 #[test]
8767 fn test_regexp_substr_all_snowflake_identity_strip_group0() {
8768 let dialect = Dialect::get(DialectType::Snowflake);
8769 let result = dialect
8770 .transpile(
8771 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 1, 1, 'e', 0)",
8772 DialectType::Snowflake,
8773 )
8774 .unwrap();
8775 assert_eq!(
8776 result[0],
8777 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 1, 1, 'e')"
8778 );
8779 }
8780
8781 #[test]
8782 fn test_regexp_count_snowflake_to_duckdb_2arg() {
8783 let dialect = Dialect::get(DialectType::Snowflake);
8784 let result = dialect
8785 .transpile("SELECT REGEXP_COUNT(s, 'pattern')", DialectType::DuckDB)
8786 .unwrap();
8787 assert_eq!(
8788 result[0],
8789 "SELECT CASE WHEN 'pattern' = '' THEN 0 ELSE LENGTH(REGEXP_EXTRACT_ALL(s, 'pattern')) END"
8790 );
8791 }
8792
8793 #[test]
8794 fn test_regexp_count_snowflake_to_duckdb_3arg() {
8795 let dialect = Dialect::get(DialectType::Snowflake);
8796 let result = dialect
8797 .transpile("SELECT REGEXP_COUNT(s, 'pattern', 3)", DialectType::DuckDB)
8798 .unwrap();
8799 assert_eq!(
8800 result[0],
8801 "SELECT CASE WHEN 'pattern' = '' THEN 0 ELSE LENGTH(REGEXP_EXTRACT_ALL(SUBSTRING(s, 3), 'pattern')) END"
8802 );
8803 }
8804
8805 #[test]
8806 fn test_regexp_count_snowflake_to_duckdb_4arg_flags() {
8807 let dialect = Dialect::get(DialectType::Snowflake);
8808 let result = dialect
8809 .transpile(
8810 "SELECT REGEXP_COUNT(s, 'pattern', 1, 'i')",
8811 DialectType::DuckDB,
8812 )
8813 .unwrap();
8814 assert_eq!(
8815 result[0],
8816 "SELECT CASE WHEN '(?i)' || 'pattern' = '' THEN 0 ELSE LENGTH(REGEXP_EXTRACT_ALL(SUBSTRING(s, 1), '(?i)' || 'pattern')) END"
8817 );
8818 }
8819
8820 #[test]
8821 fn test_regexp_count_snowflake_to_duckdb_4arg_flags_literal_string() {
8822 let dialect = Dialect::get(DialectType::Snowflake);
8823 let result = dialect
8824 .transpile(
8825 "SELECT REGEXP_COUNT('Hello World', 'L', 1, 'im')",
8826 DialectType::DuckDB,
8827 )
8828 .unwrap();
8829 assert_eq!(
8830 result[0],
8831 "SELECT CASE WHEN '(?im)' || 'L' = '' THEN 0 ELSE LENGTH(REGEXP_EXTRACT_ALL(SUBSTRING('Hello World', 1), '(?im)' || 'L')) END"
8832 );
8833 }
8834
8835 #[test]
8836 fn test_regexp_replace_snowflake_to_duckdb_5arg_pos1_occ1() {
8837 let dialect = Dialect::get(DialectType::Snowflake);
8838 let result = dialect
8839 .transpile(
8840 "SELECT REGEXP_REPLACE(s, 'pattern', 'repl', 1, 1)",
8841 DialectType::DuckDB,
8842 )
8843 .unwrap();
8844 assert_eq!(result[0], "SELECT REGEXP_REPLACE(s, 'pattern', 'repl')");
8845 }
8846
8847 #[test]
8848 fn test_regexp_replace_snowflake_to_duckdb_5arg_pos_gt1_occ0() {
8849 let dialect = Dialect::get(DialectType::Snowflake);
8850 let result = dialect
8851 .transpile(
8852 "SELECT REGEXP_REPLACE(s, 'pattern', 'repl', 3, 0)",
8853 DialectType::DuckDB,
8854 )
8855 .unwrap();
8856 assert_eq!(
8857 result[0],
8858 "SELECT SUBSTRING(s, 1, 2) || REGEXP_REPLACE(SUBSTRING(s, 3), 'pattern', 'repl', 'g')"
8859 );
8860 }
8861
8862 #[test]
8863 fn test_regexp_replace_snowflake_to_duckdb_5arg_pos_gt1_occ1() {
8864 let dialect = Dialect::get(DialectType::Snowflake);
8865 let result = dialect
8866 .transpile(
8867 "SELECT REGEXP_REPLACE(s, 'pattern', 'repl', 3, 1)",
8868 DialectType::DuckDB,
8869 )
8870 .unwrap();
8871 assert_eq!(
8872 result[0],
8873 "SELECT SUBSTRING(s, 1, 2) || REGEXP_REPLACE(SUBSTRING(s, 3), 'pattern', 'repl')"
8874 );
8875 }
8876
8877 #[test]
8878 fn test_rlike_snowflake_to_duckdb_2arg() {
8879 let dialect = Dialect::get(DialectType::Snowflake);
8880 let result = dialect
8881 .transpile("SELECT RLIKE(a, b)", DialectType::DuckDB)
8882 .unwrap();
8883 assert_eq!(result[0], "SELECT REGEXP_FULL_MATCH(a, b)");
8884 }
8885
8886 #[test]
8887 fn test_rlike_snowflake_to_duckdb_3arg_flags() {
8888 let dialect = Dialect::get(DialectType::Snowflake);
8889 let result = dialect
8890 .transpile("SELECT RLIKE(a, b, 'i')", DialectType::DuckDB)
8891 .unwrap();
8892 assert_eq!(result[0], "SELECT REGEXP_FULL_MATCH(a, b, 'i')");
8893 }
8894
8895 #[test]
8896 fn test_regexp_extract_all_bigquery_to_snowflake_no_capture() {
8897 let dialect = Dialect::get(DialectType::BigQuery);
8898 let result = dialect
8899 .transpile(
8900 "SELECT REGEXP_EXTRACT_ALL(s, 'pattern')",
8901 DialectType::Snowflake,
8902 )
8903 .unwrap();
8904 assert_eq!(result[0], "SELECT REGEXP_SUBSTR_ALL(s, 'pattern')");
8905 }
8906
8907 #[test]
8908 fn test_regexp_extract_all_bigquery_to_snowflake_with_capture() {
8909 let dialect = Dialect::get(DialectType::BigQuery);
8910 let result = dialect
8911 .transpile(
8912 "SELECT REGEXP_EXTRACT_ALL(s, '(a)[0-9]')",
8913 DialectType::Snowflake,
8914 )
8915 .unwrap();
8916 assert_eq!(
8917 result[0],
8918 "SELECT REGEXP_SUBSTR_ALL(s, '(a)[0-9]', 1, 1, 'c', 1)"
8919 );
8920 }
8921
8922 #[test]
8923 fn test_regexp_instr_snowflake_to_duckdb_2arg() {
8924 let dialect = Dialect::get(DialectType::Snowflake);
8925 let result = dialect
8926 .transpile("SELECT REGEXP_INSTR(s, 'pattern')", DialectType::DuckDB)
8927 .unwrap();
8928 assert!(
8929 result[0].contains("CASE WHEN"),
8930 "Expected CASE WHEN in result: {}",
8931 result[0]
8932 );
8933 assert!(
8934 result[0].contains("LIST_SUM"),
8935 "Expected LIST_SUM in result: {}",
8936 result[0]
8937 );
8938 }
8939
8940 #[test]
8941 fn test_array_except_generic_to_duckdb() {
8942 let dialect = Dialect::get(DialectType::Generic);
8943 let result = dialect
8944 .transpile(
8945 "SELECT ARRAY_EXCEPT(ARRAY(1, 2, 3), ARRAY(2))",
8946 DialectType::DuckDB,
8947 )
8948 .unwrap();
8949 eprintln!("ARRAY_EXCEPT Generic->DuckDB: {}", result[0]);
8950 assert!(
8951 result[0].contains("CASE WHEN"),
8952 "Expected CASE WHEN: {}",
8953 result[0]
8954 );
8955 assert!(
8956 result[0].contains("LIST_FILTER"),
8957 "Expected LIST_FILTER: {}",
8958 result[0]
8959 );
8960 assert!(
8961 result[0].contains("LIST_DISTINCT"),
8962 "Expected LIST_DISTINCT: {}",
8963 result[0]
8964 );
8965 assert!(
8966 result[0].contains("IS NOT DISTINCT FROM"),
8967 "Expected IS NOT DISTINCT FROM: {}",
8968 result[0]
8969 );
8970 assert!(
8971 result[0].contains("= 0"),
8972 "Expected = 0 filter: {}",
8973 result[0]
8974 );
8975 }
8976
8977 #[test]
8978 fn test_array_except_generic_to_snowflake() {
8979 let dialect = Dialect::get(DialectType::Generic);
8980 let result = dialect
8981 .transpile(
8982 "SELECT ARRAY_EXCEPT(ARRAY(1, 2, 3), ARRAY(2))",
8983 DialectType::Snowflake,
8984 )
8985 .unwrap();
8986 eprintln!("ARRAY_EXCEPT Generic->Snowflake: {}", result[0]);
8987 assert_eq!(result[0], "SELECT ARRAY_EXCEPT([1, 2, 3], [2])");
8988 }
8989
8990 #[test]
8991 fn test_array_except_generic_to_presto() {
8992 let dialect = Dialect::get(DialectType::Generic);
8993 let result = dialect
8994 .transpile(
8995 "SELECT ARRAY_EXCEPT(ARRAY(1, 2, 3), ARRAY(2))",
8996 DialectType::Presto,
8997 )
8998 .unwrap();
8999 eprintln!("ARRAY_EXCEPT Generic->Presto: {}", result[0]);
9000 assert_eq!(result[0], "SELECT ARRAY_EXCEPT(ARRAY[1, 2, 3], ARRAY[2])");
9001 }
9002
9003 #[test]
9004 fn test_array_except_snowflake_to_duckdb() {
9005 let dialect = Dialect::get(DialectType::Snowflake);
9006 let result = dialect
9007 .transpile("SELECT ARRAY_EXCEPT([1, 2, 3], [2])", DialectType::DuckDB)
9008 .unwrap();
9009 eprintln!("ARRAY_EXCEPT Snowflake->DuckDB: {}", result[0]);
9010 assert!(
9011 result[0].contains("CASE WHEN"),
9012 "Expected CASE WHEN: {}",
9013 result[0]
9014 );
9015 assert!(
9016 result[0].contains("LIST_TRANSFORM"),
9017 "Expected LIST_TRANSFORM: {}",
9018 result[0]
9019 );
9020 }
9021
9022 #[test]
9023 fn test_array_contains_snowflake_to_snowflake() {
9024 let dialect = Dialect::get(DialectType::Snowflake);
9025 let result = dialect
9026 .transpile(
9027 "SELECT ARRAY_CONTAINS(x, [1, NULL, 3])",
9028 DialectType::Snowflake,
9029 )
9030 .unwrap();
9031 eprintln!("ARRAY_CONTAINS Snowflake->Snowflake: {}", result[0]);
9032 assert_eq!(result[0], "SELECT ARRAY_CONTAINS(x, [1, NULL, 3])");
9033 }
9034
9035 #[test]
9036 fn test_array_contains_snowflake_to_duckdb() {
9037 let dialect = Dialect::get(DialectType::Snowflake);
9038 let result = dialect
9039 .transpile(
9040 "SELECT ARRAY_CONTAINS(x, [1, NULL, 3])",
9041 DialectType::DuckDB,
9042 )
9043 .unwrap();
9044 eprintln!("ARRAY_CONTAINS Snowflake->DuckDB: {}", result[0]);
9045 assert!(
9046 result[0].contains("CASE WHEN"),
9047 "Expected CASE WHEN: {}",
9048 result[0]
9049 );
9050 assert!(
9051 result[0].contains("NULLIF"),
9052 "Expected NULLIF: {}",
9053 result[0]
9054 );
9055 assert!(
9056 result[0].contains("ARRAY_CONTAINS"),
9057 "Expected ARRAY_CONTAINS: {}",
9058 result[0]
9059 );
9060 }
9061
9062 #[test]
9063 fn test_array_distinct_snowflake_to_duckdb() {
9064 let dialect = Dialect::get(DialectType::Snowflake);
9065 let result = dialect
9066 .transpile(
9067 "SELECT ARRAY_DISTINCT([1, 2, 2, 3, 1])",
9068 DialectType::DuckDB,
9069 )
9070 .unwrap();
9071 eprintln!("ARRAY_DISTINCT Snowflake->DuckDB: {}", result[0]);
9072 assert!(
9073 result[0].contains("CASE WHEN"),
9074 "Expected CASE WHEN: {}",
9075 result[0]
9076 );
9077 assert!(
9078 result[0].contains("LIST_DISTINCT"),
9079 "Expected LIST_DISTINCT: {}",
9080 result[0]
9081 );
9082 assert!(
9083 result[0].contains("LIST_APPEND"),
9084 "Expected LIST_APPEND: {}",
9085 result[0]
9086 );
9087 assert!(
9088 result[0].contains("LIST_FILTER"),
9089 "Expected LIST_FILTER: {}",
9090 result[0]
9091 );
9092 }
9093}