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 Self::reject_postgres_tsql_strict_unknown_text_casts(
3419 &expr,
3420 self.dialect_type,
3421 target,
3422 opts,
3423 )?;
3424
3425 let normalized =
3429 if self.dialect_type != target && self.dialect_type != DialectType::Generic {
3430 self.transform_with_guard(expr, opts.complexity_guard)?
3431 } else {
3432 expr
3433 };
3434
3435 let normalized =
3440 if matches!(self.dialect_type, DialectType::TSQL | DialectType::Fabric)
3441 && !matches!(target, DialectType::TSQL | DialectType::Fabric)
3442 {
3443 transform_recursive(normalized, &|e| {
3444 if let Expression::Function(ref f) = e {
3445 if f.name.eq_ignore_ascii_case("ISNULL") && f.args.len() == 2 {
3446 if let (
3448 Expression::Function(ref jq),
3449 Expression::Function(ref jv),
3450 ) = (&f.args[0], &f.args[1])
3451 {
3452 if jq.name.eq_ignore_ascii_case("JSON_QUERY")
3453 && jv.name.eq_ignore_ascii_case("JSON_VALUE")
3454 {
3455 return Ok(f.args[0].clone());
3457 }
3458 }
3459 }
3460 }
3461 Ok(e)
3462 })?
3463 } else {
3464 normalized
3465 };
3466
3467 let normalized = if matches!(self.dialect_type, DialectType::Snowflake)
3471 && !matches!(target, DialectType::Snowflake)
3472 {
3473 transform_recursive(normalized, &|e| {
3474 if let Expression::Function(ref f) = e {
3475 if f.name.eq_ignore_ascii_case("CURRENT_TIME") {
3476 return Ok(Expression::Localtime(Box::new(
3477 crate::expressions::Localtime { this: None },
3478 )));
3479 }
3480 }
3481 Ok(e)
3482 })?
3483 } else {
3484 normalized
3485 };
3486
3487 let normalized = if matches!(self.dialect_type, DialectType::Snowflake)
3491 && matches!(target, DialectType::DuckDB)
3492 {
3493 transform_recursive(normalized, &|e| {
3494 if let Expression::Function(ref f) = e {
3495 if f.name.eq_ignore_ascii_case("REPEAT") && f.args.len() == 2 {
3496 if let Expression::Literal(ref lit) = f.args[0] {
3498 if let crate::expressions::Literal::String(ref s) = lit.as_ref()
3499 {
3500 if s == " " {
3501 if !matches!(f.args[1], Expression::Cast(_)) {
3503 let mut new_args = f.args.clone();
3504 new_args[1] = Expression::Cast(Box::new(
3505 crate::expressions::Cast {
3506 this: new_args[1].clone(),
3507 to: crate::expressions::DataType::BigInt {
3508 length: None,
3509 },
3510 trailing_comments: Vec::new(),
3511 double_colon_syntax: false,
3512 format: None,
3513 default: None,
3514 inferred_type: None,
3515 },
3516 ));
3517 return Ok(Expression::Function(Box::new(
3518 crate::expressions::Function {
3519 name: f.name.clone(),
3520 args: new_args,
3521 distinct: f.distinct,
3522 trailing_comments: f
3523 .trailing_comments
3524 .clone(),
3525 use_bracket_syntax: f.use_bracket_syntax,
3526 no_parens: f.no_parens,
3527 quoted: f.quoted,
3528 span: None,
3529 inferred_type: None,
3530 },
3531 )));
3532 }
3533 }
3534 }
3535 }
3536 }
3537 }
3538 Ok(e)
3539 })?
3540 } else {
3541 normalized
3542 };
3543
3544 let normalized = if matches!(self.dialect_type, DialectType::BigQuery)
3547 && !matches!(target, DialectType::BigQuery)
3548 {
3549 crate::transforms::propagate_struct_field_names(normalized)?
3550 } else {
3551 normalized
3552 };
3553
3554 let normalized = if matches!(self.dialect_type, DialectType::Snowflake)
3559 && matches!(target, DialectType::DuckDB)
3560 {
3561 fn make_scaled_random() -> Expression {
3562 let lower =
3563 Expression::Literal(Box::new(crate::expressions::Literal::Number(
3564 "-9.223372036854776E+18".to_string(),
3565 )));
3566 let upper =
3567 Expression::Literal(Box::new(crate::expressions::Literal::Number(
3568 "9.223372036854776e+18".to_string(),
3569 )));
3570 let random_call = Expression::Random(crate::expressions::Random);
3571 let range_size = Expression::Paren(Box::new(crate::expressions::Paren {
3572 this: Expression::Sub(Box::new(crate::expressions::BinaryOp {
3573 left: upper,
3574 right: lower.clone(),
3575 left_comments: vec![],
3576 operator_comments: vec![],
3577 trailing_comments: vec![],
3578 inferred_type: None,
3579 })),
3580 trailing_comments: vec![],
3581 }));
3582 let scaled = Expression::Mul(Box::new(crate::expressions::BinaryOp {
3583 left: random_call,
3584 right: range_size,
3585 left_comments: vec![],
3586 operator_comments: vec![],
3587 trailing_comments: vec![],
3588 inferred_type: None,
3589 }));
3590 let shifted = Expression::Add(Box::new(crate::expressions::BinaryOp {
3591 left: lower,
3592 right: scaled,
3593 left_comments: vec![],
3594 operator_comments: vec![],
3595 trailing_comments: vec![],
3596 inferred_type: None,
3597 }));
3598 Expression::Cast(Box::new(crate::expressions::Cast {
3599 this: shifted,
3600 to: crate::expressions::DataType::BigInt { length: None },
3601 trailing_comments: vec![],
3602 double_colon_syntax: false,
3603 format: None,
3604 default: None,
3605 inferred_type: None,
3606 }))
3607 }
3608
3609 let normalized = transform_recursive(normalized, &|e| {
3616 if let Expression::Function(ref f) = e {
3617 let n = f.name.to_ascii_uppercase();
3618 if n == "UNIFORM" || n == "NORMAL" || n == "ZIPF" || n == "RANDSTR" {
3619 if let Expression::Function(mut f) = e {
3620 for arg in f.args.iter_mut() {
3621 if let Expression::Rand(ref r) = arg {
3622 if r.lower.is_none() && r.upper.is_none() {
3623 if let Some(ref seed) = r.seed {
3624 *arg = Expression::Function(Box::new(
3627 crate::expressions::Function::new(
3628 "RANDOM".to_string(),
3629 vec![*seed.clone()],
3630 ),
3631 ));
3632 }
3633 }
3634 }
3635 }
3636 return Ok(Expression::Function(f));
3637 }
3638 }
3639 }
3640 Ok(e)
3641 })?;
3642
3643 transform_recursive(normalized, &|e| {
3651 if let Expression::Function(ref f) = e {
3652 let n = f.name.to_ascii_uppercase();
3653 if n == "UNIFORM" || n == "NORMAL" || n == "ZIPF" {
3654 if let Expression::Function(mut f) = e {
3655 for arg in f.args.iter_mut() {
3656 if let Expression::Cast(ref cast) = arg {
3658 if matches!(
3659 cast.to,
3660 crate::expressions::DataType::BigInt { .. }
3661 ) {
3662 if let Expression::Add(ref add) = cast.this {
3663 if let Expression::Literal(ref lit) = add.left {
3664 if let crate::expressions::Literal::Number(
3665 ref num,
3666 ) = lit.as_ref()
3667 {
3668 if num == "-9.223372036854776E+18" {
3669 *arg = Expression::Random(
3670 crate::expressions::Random,
3671 );
3672 }
3673 }
3674 }
3675 }
3676 }
3677 }
3678 }
3679 return Ok(Expression::Function(f));
3680 }
3681 return Ok(e);
3682 }
3683 }
3684 match e {
3685 Expression::Random(_) => Ok(make_scaled_random()),
3686 Expression::Rand(ref r) if r.lower.is_none() && r.upper.is_none() => {
3689 Ok(make_scaled_random())
3690 }
3691 _ => Ok(e),
3692 }
3693 })?
3694 } else {
3695 normalized
3696 };
3697
3698 let normalized = normalization::normalize(normalized, self.dialect_type, target)?;
3700
3701 let normalized = if matches!(target, DialectType::TSQL | DialectType::Fabric) {
3702 Self::normalize_tsql_fetch_overlaps_date_bin(normalized)?
3703 } else {
3704 normalized
3705 };
3706
3707 let normalized =
3708 if matches!(
3709 self.dialect_type,
3710 DialectType::PostgreSQL | DialectType::CockroachDB
3711 ) && !matches!(target, DialectType::PostgreSQL | DialectType::CockroachDB)
3712 {
3713 Self::normalize_postgres_type_function_casts(normalized, target)?
3714 } else {
3715 normalized
3716 };
3717
3718 let normalized = if matches!(self.dialect_type, DialectType::SQLite)
3719 && !matches!(target, DialectType::SQLite)
3720 {
3721 Self::normalize_sqlite_double_quoted_defaults(normalized)?
3722 } else {
3723 normalized
3724 };
3725
3726 let normalized = if matches!(self.dialect_type, DialectType::PostgreSQL)
3727 && matches!(target, DialectType::SQLite)
3728 {
3729 Self::normalize_postgres_to_sqlite_types(normalized)?
3730 } else {
3731 normalized
3732 };
3733
3734 let normalized = if matches!(self.dialect_type, DialectType::PostgreSQL)
3735 && matches!(target, DialectType::Fabric)
3736 {
3737 Self::normalize_postgres_to_fabric_types(normalized)?
3738 } else {
3739 normalized
3740 };
3741
3742 let normalized = if matches!(self.dialect_type, DialectType::BigQuery)
3746 && matches!(target, DialectType::DuckDB)
3747 {
3748 crate::transforms::wrap_duckdb_unnest_struct(normalized)?
3749 } else {
3750 normalized
3751 };
3752
3753 let normalized = if matches!(self.dialect_type, DialectType::BigQuery)
3756 && matches!(
3757 target,
3758 DialectType::DuckDB
3759 | DialectType::Presto
3760 | DialectType::Trino
3761 | DialectType::Athena
3762 | DialectType::Spark
3763 | DialectType::Databricks
3764 ) {
3765 crate::transforms::unnest_alias_to_column_alias(normalized)?
3766 } else if matches!(self.dialect_type, DialectType::BigQuery)
3767 && matches!(target, DialectType::BigQuery | DialectType::Redshift)
3768 {
3769 let result = crate::transforms::unnest_from_to_cross_join(normalized)?;
3772 if matches!(target, DialectType::Redshift) {
3774 crate::transforms::strip_unnest_column_refs(result)?
3775 } else {
3776 result
3777 }
3778 } else {
3779 normalized
3780 };
3781
3782 let normalized = if matches!(
3785 self.dialect_type,
3786 DialectType::PostgreSQL | DialectType::Redshift
3787 ) && matches!(
3788 target,
3789 DialectType::Presto | DialectType::Trino | DialectType::Athena
3790 ) {
3791 crate::transforms::wrap_unnest_join_aliases(normalized)?
3792 } else {
3793 normalized
3794 };
3795
3796 let normalized = crate::transforms::eliminate_distinct_on_for_dialect(
3800 normalized,
3801 Some(target),
3802 Some(self.dialect_type),
3803 )?;
3804
3805 let normalized = if matches!(target, DialectType::Snowflake) {
3807 Self::transform_generate_date_array_snowflake(normalized)?
3808 } else {
3809 normalized
3810 };
3811
3812 let normalized = if matches!(
3814 target,
3815 DialectType::Spark | DialectType::Databricks | DialectType::Hive
3816 ) {
3817 crate::transforms::unnest_to_explode_select(normalized)?
3818 } else {
3819 normalized
3820 };
3821
3822 let normalized = if matches!(target, DialectType::ClickHouse | DialectType::TSQL) {
3824 crate::transforms::no_limit_order_by_union(normalized)?
3825 } else {
3826 normalized
3827 };
3828
3829 let normalized = if matches!(
3830 self.dialect_type,
3831 DialectType::PostgreSQL | DialectType::CockroachDB
3832 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
3833 {
3834 Self::normalize_postgres_boolean_semantics_for_tsql(normalized)?
3835 } else {
3836 normalized
3837 };
3838
3839 let normalized = if matches!(target, DialectType::TSQL | DialectType::Fabric)
3843 && !matches!(self.dialect_type, DialectType::TSQL | DialectType::Fabric)
3844 {
3845 transform_recursive(normalized, &|e| {
3846 if let Expression::Count(ref c) = e {
3847 let args = if c.star {
3849 vec![Expression::Star(crate::expressions::Star {
3850 table: None,
3851 except: None,
3852 replace: None,
3853 rename: None,
3854 trailing_comments: Vec::new(),
3855 span: None,
3856 })]
3857 } else if let Some(ref this) = c.this {
3858 vec![this.clone()]
3859 } else {
3860 vec![]
3861 };
3862 Ok(Expression::AggregateFunction(Box::new(
3863 crate::expressions::AggregateFunction {
3864 name: "COUNT_BIG".to_string(),
3865 args,
3866 distinct: c.distinct,
3867 filter: c.filter.clone(),
3868 order_by: Vec::new(),
3869 limit: None,
3870 ignore_nulls: None,
3871 inferred_type: None,
3872 },
3873 )))
3874 } else {
3875 Ok(e)
3876 }
3877 })?
3878 } else {
3879 normalized
3880 };
3881
3882 let normalized = if matches!(target, DialectType::TSQL | DialectType::Fabric)
3886 && !matches!(self.dialect_type, DialectType::TSQL | DialectType::Fabric)
3887 {
3888 Self::rewrite_boolean_values_for_tsql(normalized)?
3889 } else {
3890 normalized
3891 };
3892
3893 let normalized = if matches!(
3894 self.dialect_type,
3895 DialectType::PostgreSQL | DialectType::CockroachDB
3896 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
3897 {
3898 Self::rewrite_postgres_format_for_tsql(normalized, target)?
3899 } else {
3900 normalized
3901 };
3902
3903 let normalized = if self.dialect_type == DialectType::PostgreSQL
3904 && matches!(target, DialectType::TSQL | DialectType::Fabric)
3905 {
3906 Self::normalize_postgres_only_for_tsql(normalized)?
3907 } else {
3908 normalized
3909 };
3910
3911 let transformed =
3912 target_dialect.transform_with_guard(normalized, opts.complexity_guard)?;
3913
3914 let transformed = if matches!(target, DialectType::TSQL | DialectType::Fabric) {
3918 Self::rewrite_aggregate_filters_for_tsql(transformed)?
3919 } else {
3920 transformed
3921 };
3922
3923 let transformed = if matches!(
3924 self.dialect_type,
3925 DialectType::PostgreSQL | DialectType::CockroachDB
3926 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
3927 {
3928 crate::transforms::grouped_percentiles_to_tsql_windows(transformed)?
3929 } else {
3930 transformed
3931 };
3932
3933 let transformed = if matches!(
3934 self.dialect_type,
3935 DialectType::PostgreSQL | DialectType::CockroachDB
3936 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
3937 {
3938 Self::normalize_postgres_trim_for_tsql(transformed)?
3939 } else {
3940 transformed
3941 };
3942
3943 let transformed = if matches!(
3944 self.dialect_type,
3945 DialectType::PostgreSQL | DialectType::CockroachDB
3946 ) && matches!(target, DialectType::TSQL | DialectType::Fabric)
3947 {
3948 Self::rewrite_postgres_json_array_elements_select_for_tsql(transformed)?
3949 } else {
3950 transformed
3951 };
3952
3953 let transformed = if matches!(target, DialectType::DuckDB) {
3955 Self::seq_rownum_to_range(transformed)?
3956 } else {
3957 transformed
3958 };
3959
3960 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
3961 Self::reject_tsql_interval_casts(&transformed, target, opts)?;
3962 }
3963
3964 let transformed = if matches!(target, DialectType::TSQL | DialectType::Fabric) {
3965 Self::rewrite_tsql_interval_casts_to_varchar(transformed)?
3966 } else {
3967 transformed
3968 };
3969
3970 let transformed = if matches!(target, DialectType::TSQL | DialectType::Fabric) {
3971 Self::legalize_tsql_nested_order_by(transformed)?
3972 } else {
3973 transformed
3974 };
3975
3976 Self::reject_strict_unsupported(&transformed, self.dialect_type, target, opts)?;
3977
3978 let mut sql = target_dialect.generate_with_transpile_options(
3979 &transformed,
3980 self.dialect_type,
3981 opts,
3982 )?;
3983
3984 if opts.pretty && target == DialectType::Snowflake {
3986 sql = Self::normalize_snowflake_pretty(sql);
3987 }
3988
3989 Ok(sql)
3990 })
3991 .collect()
3992 }
3993}
3994
3995#[cfg(feature = "transpile")]
3997impl Dialect {
3998 fn legalize_tsql_nested_order_by(expr: Expression) -> Result<Expression> {
3999 let preserve_root_order = matches!(&expr, Expression::Select(select) if Self::tsql_select_needs_order_offset(select));
4000
4001 let mut transformed = transform_recursive(expr, &|node| match node {
4002 Expression::Select(mut select) => {
4003 Self::legalize_tsql_select_offset(&mut select);
4004 if Self::tsql_select_needs_order_offset(&select) {
4005 select.offset = Some(Offset {
4006 this: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
4007 rows: Some(true),
4008 });
4009 }
4010 Ok(Expression::Select(select))
4011 }
4012 Expression::Subquery(mut subquery) => {
4013 Self::legalize_tsql_offset(&mut subquery.order_by, &mut subquery.offset, false);
4014 Ok(Expression::Subquery(subquery))
4015 }
4016 Expression::Union(mut union) => {
4017 Self::legalize_tsql_set_offset(&mut union.order_by, &mut union.offset);
4018 Ok(Expression::Union(union))
4019 }
4020 Expression::Intersect(mut intersect) => {
4021 Self::legalize_tsql_set_offset(&mut intersect.order_by, &mut intersect.offset);
4022 Ok(Expression::Intersect(intersect))
4023 }
4024 Expression::Except(mut except) => {
4025 Self::legalize_tsql_set_offset(&mut except.order_by, &mut except.offset);
4026 Ok(Expression::Except(except))
4027 }
4028 other => Ok(other),
4029 })?;
4030
4031 if preserve_root_order {
4032 if let Expression::Select(select) = &mut transformed {
4033 select.offset = None;
4034 }
4035 }
4036
4037 Ok(transformed)
4038 }
4039
4040 fn legalize_tsql_select_offset(select: &mut crate::expressions::Select) {
4041 let has_fetch = select.fetch.is_some();
4042 Self::legalize_tsql_offset(&mut select.order_by, &mut select.offset, has_fetch);
4043 }
4044
4045 fn legalize_tsql_offset(
4046 order_by: &mut Option<OrderBy>,
4047 offset: &mut Option<Offset>,
4048 retain_inert_offset: bool,
4049 ) {
4050 if order_by.is_some() {
4051 return;
4052 }
4053
4054 if offset
4055 .as_ref()
4056 .is_some_and(|offset| Self::tsql_offset_is_inert(&offset.this))
4057 && !retain_inert_offset
4058 {
4059 *offset = None;
4060 } else if offset.is_some() {
4061 *order_by = Some(Generator::dummy_tsql_order_by());
4062 }
4063 }
4064
4065 fn legalize_tsql_set_offset(
4066 order_by: &mut Option<OrderBy>,
4067 offset: &mut Option<Box<Expression>>,
4068 ) {
4069 if order_by.is_some() {
4070 return;
4071 }
4072
4073 if offset.as_deref().is_some_and(Self::tsql_offset_is_inert) {
4074 *offset = None;
4075 } else if offset.is_some() {
4076 *order_by = Some(Generator::dummy_tsql_order_by());
4077 }
4078 }
4079
4080 fn tsql_offset_is_inert(expr: &Expression) -> bool {
4081 match expr {
4082 Expression::Null(_) => true,
4083 Expression::Literal(literal) => match literal.as_ref() {
4084 Literal::Number(value) => value.parse::<i128>().is_ok_and(|value| value == 0),
4085 _ => false,
4086 },
4087 _ => false,
4088 }
4089 }
4090
4091 fn tsql_select_needs_order_offset(select: &crate::expressions::Select) -> bool {
4092 select.order_by.is_some()
4093 && select.top.is_none()
4094 && select.limit.is_none()
4095 && select.offset.is_none()
4096 && select.fetch.is_none()
4097 && select.for_xml.is_empty()
4098 && select.for_json.is_empty()
4099 }
4100
4101 fn reject_strict_unsupported(
4102 expr: &Expression,
4103 source: DialectType,
4104 target: DialectType,
4105 opts: &TranspileOptions,
4106 ) -> Result<()> {
4107 if !matches!(
4108 opts.unsupported_level,
4109 UnsupportedLevel::Raise | UnsupportedLevel::Immediate
4110 ) {
4111 return Ok(());
4112 }
4113
4114 let mut diagnostics = Vec::new();
4115
4116 for node in expr.dfs() {
4117 if matches!(target, DialectType::Fabric | DialectType::Hive)
4118 && Self::node_has_recursive_with(node)
4119 {
4120 Self::push_unsupported_diagnostic(&mut diagnostics, "recursive CTEs");
4121 }
4122
4123 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4124 && Self::node_has_lateral(node)
4125 {
4126 Self::push_unsupported_diagnostic(&mut diagnostics, "LATERAL joins and subqueries");
4127 }
4128
4129 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4130 if Self::node_has_join_using(node) {
4131 Self::push_unsupported_diagnostic(&mut diagnostics, "JOIN USING clauses");
4132 }
4133 if Self::node_has_natural_join(node) {
4134 Self::push_unsupported_diagnostic(&mut diagnostics, "NATURAL JOIN");
4135 }
4136 if Self::node_has_unsupported_relation_column_aliases(node) {
4137 Self::push_unsupported_diagnostic(
4138 &mut diagnostics,
4139 "column alias lists on base or joined table references",
4140 );
4141 }
4142 if Self::node_has_qualified_whole_row_aggregate_argument(node) {
4143 Self::push_unsupported_diagnostic(
4144 &mut diagnostics,
4145 "qualified whole-row aggregate arguments",
4146 );
4147 }
4148 }
4149
4150 if !Self::target_supports_distinct_on(target) && Self::node_has_distinct_on(node) {
4151 Self::push_unsupported_diagnostic(&mut diagnostics, "DISTINCT ON");
4152 }
4153
4154 if !Self::target_supports_remaining_unnest(target) && Self::node_is_unnest(node) {
4155 Self::push_unsupported_diagnostic(&mut diagnostics, "UNNEST");
4156 }
4157
4158 if !Self::target_supports_remaining_explode(target) && Self::node_is_explode(node) {
4159 Self::push_unsupported_diagnostic(&mut diagnostics, "EXPLODE");
4160 }
4161
4162 if Self::target_lacks_array_agg(target) && Self::node_is_array_agg(node) {
4163 Self::push_unsupported_diagnostic(&mut diagnostics, "ARRAY_AGG");
4164 }
4165
4166 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4167 && Self::node_is_distinct_string_agg(node)
4168 {
4169 Self::push_unsupported_diagnostic(&mut diagnostics, "STRING_AGG with DISTINCT");
4170 }
4171
4172 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4173 && matches!(node, Expression::NthValue(_))
4174 {
4175 Self::push_unsupported_diagnostic(&mut diagnostics, "NTH_VALUE");
4176 }
4177
4178 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4179 if let Some(frame) = Self::node_window_frame(node) {
4180 if matches!(frame.kind, WindowFrameKind::Groups) {
4181 Self::push_unsupported_diagnostic(&mut diagnostics, "GROUPS window frames");
4182 }
4183 if matches!(frame.kind, WindowFrameKind::Range)
4184 && (Self::window_frame_bound_has_value_offset(&frame.start)
4185 || frame
4186 .end
4187 .as_ref()
4188 .is_some_and(Self::window_frame_bound_has_value_offset))
4189 {
4190 Self::push_unsupported_diagnostic(
4191 &mut diagnostics,
4192 "value-offset RANGE window frames",
4193 );
4194 }
4195 if frame.exclude.is_some() {
4196 Self::push_unsupported_diagnostic(
4197 &mut diagnostics,
4198 "window frame EXCLUDE clauses",
4199 );
4200 }
4201 }
4202 }
4203
4204 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4205 && Self::node_is_regex_predicate(node)
4206 {
4207 Self::push_unsupported_diagnostic(
4208 &mut diagnostics,
4209 "regular expression predicates",
4210 );
4211 }
4212
4213 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4214 && Self::node_is_non_subquery_any(node)
4215 {
4216 Self::push_unsupported_diagnostic(
4217 &mut diagnostics,
4218 "ANY over non-subquery expressions",
4219 );
4220 }
4221
4222 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4223 && Self::node_is_row_value_subquery_comparison(node)
4224 {
4225 Self::push_unsupported_diagnostic(
4226 &mut diagnostics,
4227 "row-value subquery comparisons",
4228 );
4229 }
4230
4231 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4232 && Self::node_is_row_value_values_membership(node)
4233 {
4234 Self::push_unsupported_diagnostic(
4235 &mut diagnostics,
4236 "row-value VALUES membership comparisons",
4237 );
4238 }
4239
4240 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4241 && Self::node_has_fetch_with_ties(node)
4242 {
4243 Self::push_unsupported_diagnostic(&mut diagnostics, "FETCH WITH TIES without TOP");
4244 }
4245
4246 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4247 && Self::node_is_overlaps(node)
4248 {
4249 Self::push_unsupported_diagnostic(&mut diagnostics, "OVERLAPS");
4250 }
4251
4252 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4253 && Self::node_is_date_bin(node)
4254 {
4255 Self::push_unsupported_diagnostic(&mut diagnostics, "DATE_BIN");
4256 }
4257
4258 if source == DialectType::PostgreSQL
4259 && matches!(target, DialectType::TSQL | DialectType::Fabric)
4260 && Self::node_is_unresolved_postgres_date_subtraction(node)
4261 {
4262 Self::push_unsupported_diagnostic(
4263 &mut diagnostics,
4264 "PostgreSQL date subtraction with an unresolved column type",
4265 );
4266 }
4267
4268 if matches!(source, DialectType::PostgreSQL | DialectType::CockroachDB)
4269 && !matches!(target, DialectType::PostgreSQL | DialectType::CockroachDB)
4270 {
4271 if Self::node_is_postgres_json_build_object(node)
4272 && !(matches!(target, DialectType::TSQL | DialectType::Fabric)
4273 && Self::postgres_json_build_object_can_lower_to_json_object(node))
4274 {
4275 Self::push_unsupported_diagnostic(
4276 &mut diagnostics,
4277 "PostgreSQL JSON_BUILD_OBJECT",
4278 );
4279 }
4280 if Self::node_is_function_named(node, "TO_TSVECTOR") {
4281 Self::push_unsupported_diagnostic(&mut diagnostics, "PostgreSQL TO_TSVECTOR");
4282 }
4283 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4284 if let Some(composite_semantics) =
4285 Self::postgres_tsql_unsupported_composite_semantics(node)
4286 {
4287 Self::push_unsupported_diagnostic(
4288 &mut diagnostics,
4289 &format!("PostgreSQL {composite_semantics}"),
4290 );
4291 }
4292 if Self::node_is_postgres_unknown_cast(node) {
4293 Self::push_unsupported_diagnostic(
4294 &mut diagnostics,
4295 "PostgreSQL unresolved UNKNOWN casts",
4296 );
4297 }
4298 if let Some(collation_name) =
4299 Self::postgres_tsql_unsupported_collation_name(node)
4300 {
4301 Self::push_unsupported_diagnostic(
4302 &mut diagnostics,
4303 &format!("PostgreSQL collation \"{collation_name}\""),
4304 );
4305 }
4306 if let Some(array_semantics) =
4307 Self::postgres_tsql_unsupported_array_semantics(node)
4308 {
4309 Self::push_unsupported_diagnostic(
4310 &mut diagnostics,
4311 &format!("PostgreSQL {array_semantics}"),
4312 );
4313 }
4314 if let Some(function_name) = Self::postgres_tsql_unsupported_function_name(node)
4315 {
4316 Self::push_unsupported_diagnostic(
4317 &mut diagnostics,
4318 &format!("PostgreSQL {function_name}"),
4319 );
4320 }
4321 }
4322 if matches!(target, DialectType::TSQL | DialectType::Fabric)
4323 && Self::node_is_postgres_type_function_cast(node)
4324 {
4325 Self::push_unsupported_diagnostic(
4326 &mut diagnostics,
4327 "PostgreSQL type-name function casts",
4328 );
4329 }
4330 }
4331
4332 if opts.unsupported_level == UnsupportedLevel::Immediate && !diagnostics.is_empty() {
4333 break;
4334 }
4335 }
4336
4337 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
4338 Self::collect_tsql_unsupported_ordered_sets(expr, &mut diagnostics);
4339 Self::collect_tsql_windows_missing_order(expr, &HashMap::new(), &mut diagnostics);
4340 }
4341
4342 if diagnostics.is_empty() {
4343 return Ok(());
4344 }
4345
4346 let limit = if opts.unsupported_level == UnsupportedLevel::Immediate {
4347 1
4348 } else {
4349 opts.max_unsupported.max(1)
4350 };
4351 let mut messages = diagnostics.iter().take(limit).cloned().collect::<Vec<_>>();
4352 if diagnostics.len() > limit {
4353 messages.push(format!("... and {} more", diagnostics.len() - limit));
4354 }
4355
4356 Err(crate::error::Error::unsupported(
4357 messages.join("; "),
4358 target.to_string(),
4359 ))
4360 }
4361
4362 fn reject_postgres_tsql_strict_regex_predicates(
4363 expr: &Expression,
4364 source: DialectType,
4365 target: DialectType,
4366 opts: &TranspileOptions,
4367 ) -> Result<()> {
4368 if !matches!(
4369 opts.unsupported_level,
4370 UnsupportedLevel::Raise | UnsupportedLevel::Immediate
4371 ) || !matches!(source, DialectType::PostgreSQL | DialectType::CockroachDB)
4372 || !matches!(target, DialectType::TSQL | DialectType::Fabric)
4373 {
4374 return Ok(());
4375 }
4376
4377 if expr.dfs().any(Self::node_is_regex_predicate) {
4378 return Err(crate::error::Error::unsupported(
4379 "regular expression predicates",
4380 target.to_string(),
4381 ));
4382 }
4383
4384 Ok(())
4385 }
4386
4387 fn reject_postgres_tsql_strict_unknown_text_casts(
4388 expr: &Expression,
4389 source: DialectType,
4390 target: DialectType,
4391 opts: &TranspileOptions,
4392 ) -> Result<()> {
4393 if !matches!(
4394 opts.unsupported_level,
4395 UnsupportedLevel::Raise | UnsupportedLevel::Immediate
4396 ) || !matches!(source, DialectType::PostgreSQL | DialectType::CockroachDB)
4397 || !matches!(target, DialectType::TSQL | DialectType::Fabric)
4398 {
4399 return Ok(());
4400 }
4401
4402 if expr.dfs().any(|node| {
4403 matches!(
4404 node,
4405 Expression::Cast(cast)
4406 if matches!(cast.to, DataType::Text)
4407 && Self::is_column_expr(&cast.this)
4408 )
4409 }) {
4410 return Err(crate::error::Error::unsupported(
4411 "PostgreSQL cast of a column with an unknown source type to text",
4412 target.to_string(),
4413 ));
4414 }
4415
4416 Ok(())
4417 }
4418
4419 fn push_unsupported_diagnostic(diagnostics: &mut Vec<String>, message: &str) {
4420 if !diagnostics.iter().any(|existing| existing == message) {
4421 diagnostics.push(message.to_string());
4422 }
4423 }
4424
4425 fn node_is_unresolved_postgres_date_subtraction(expr: &Expression) -> bool {
4426 let Expression::Sub(op) = expr else {
4427 return false;
4428 };
4429
4430 (Self::is_explicit_date_expr(&op.left) && Self::is_column_expr(&op.right))
4431 || (Self::is_column_expr(&op.left) && Self::is_explicit_date_expr(&op.right))
4432 }
4433
4434 fn is_column_expr(expr: &Expression) -> bool {
4435 match expr {
4436 Expression::Column(_) => true,
4437 Expression::Paren(paren) => Self::is_column_expr(&paren.this),
4438 _ => false,
4439 }
4440 }
4441
4442 fn node_window_frame(expr: &Expression) -> Option<&WindowFrame> {
4443 match expr {
4444 Expression::WindowFunction(window) => window.over.frame.as_ref(),
4445 Expression::Window(window) | Expression::WindowSpec(window) => window.frame.as_ref(),
4446 _ => None,
4447 }
4448 }
4449
4450 fn window_frame_bound_has_value_offset(bound: &WindowFrameBound) -> bool {
4451 matches!(
4452 bound,
4453 WindowFrameBound::Preceding(_)
4454 | WindowFrameBound::Following(_)
4455 | WindowFrameBound::Value(_)
4456 | WindowFrameBound::BarePreceding
4457 | WindowFrameBound::BareFollowing
4458 )
4459 }
4460
4461 fn collect_tsql_windows_missing_order(
4462 expr: &Expression,
4463 active_windows: &HashMap<String, Over>,
4464 diagnostics: &mut Vec<String>,
4465 ) {
4466 if let Expression::Select(select) = expr {
4467 let local_windows = select
4468 .windows
4469 .as_ref()
4470 .map(|windows| {
4471 windows
4472 .iter()
4473 .map(|window| (window.name.name.to_ascii_lowercase(), window.spec.clone()))
4474 .collect()
4475 })
4476 .unwrap_or_default();
4477
4478 for child in expr.children() {
4479 Self::collect_tsql_windows_missing_order(child, &local_windows, diagnostics);
4480 }
4481 return;
4482 }
4483
4484 if let Expression::WindowFunction(window) = expr {
4485 let (has_order, has_frame) = Self::effective_window_order_and_frame(
4486 &window.over,
4487 active_windows,
4488 &mut Vec::new(),
4489 );
4490
4491 if !has_order {
4492 if has_frame {
4493 Self::push_unsupported_diagnostic(
4494 diagnostics,
4495 "window frames without ORDER BY",
4496 );
4497 }
4498 if let Some(function_name) =
4499 Self::tsql_window_function_requiring_order(&window.this)
4500 {
4501 Self::push_unsupported_diagnostic(
4502 diagnostics,
4503 &format!("{function_name} without ORDER BY"),
4504 );
4505 }
4506 }
4507 }
4508
4509 for child in expr.children() {
4510 Self::collect_tsql_windows_missing_order(child, active_windows, diagnostics);
4511 }
4512 }
4513
4514 fn effective_window_order_and_frame(
4515 over: &Over,
4516 active_windows: &HashMap<String, Over>,
4517 seen: &mut Vec<String>,
4518 ) -> (bool, bool) {
4519 let inherited = over
4520 .window_name
4521 .as_ref()
4522 .and_then(|name| {
4523 let key = name.name.to_ascii_lowercase();
4524 if seen.iter().any(|seen_name| seen_name == &key) {
4525 return None;
4526 }
4527 let named = active_windows.get(&key)?;
4528 seen.push(key);
4529 let properties =
4530 Self::effective_window_order_and_frame(named, active_windows, seen);
4531 seen.pop();
4532 Some(properties)
4533 })
4534 .unwrap_or((false, false));
4535
4536 (
4537 !over.order_by.is_empty() || inherited.0,
4538 over.frame.is_some() || inherited.1,
4539 )
4540 }
4541
4542 fn tsql_window_function_requiring_order(expr: &Expression) -> Option<&'static str> {
4543 match expr {
4544 Expression::FirstValue(_) => Some("FIRST_VALUE"),
4545 Expression::LastValue(_) => Some("LAST_VALUE"),
4546 Expression::Function(function) if function.name.eq_ignore_ascii_case("FIRST_VALUE") => {
4547 Some("FIRST_VALUE")
4548 }
4549 Expression::Function(function) if function.name.eq_ignore_ascii_case("LAST_VALUE") => {
4550 Some("LAST_VALUE")
4551 }
4552 _ => None,
4553 }
4554 }
4555
4556 fn collect_tsql_unsupported_ordered_sets(expr: &Expression, diagnostics: &mut Vec<String>) {
4557 match expr {
4558 Expression::WindowFunction(window) => {
4559 if let Expression::WithinGroup(within_group) = &window.this {
4560 if Self::within_group_is_hypothetical_set(within_group) {
4561 Self::push_unsupported_diagnostic(
4562 diagnostics,
4563 "RANK/DENSE_RANK/CUME_DIST/PERCENT_RANK hypothetical-set aggregates",
4564 );
4565 return;
4566 }
4567
4568 if Self::within_group_is_mode(within_group) {
4569 Self::push_unsupported_diagnostic(
4570 diagnostics,
4571 "MODE ordered-set aggregates",
4572 );
4573 return;
4574 }
4575
4576 if Self::within_group_is_percentile(within_group) {
4577 if !window.over.order_by.is_empty() || window.over.frame.is_some() {
4578 Self::push_unsupported_diagnostic(
4579 diagnostics,
4580 "PERCENTILE_CONT/PERCENTILE_DISC window ORDER BY or frame clauses",
4581 );
4582 }
4583 return;
4584 }
4585 }
4586 }
4587 Expression::WithinGroup(within_group) => {
4588 if Self::within_group_is_hypothetical_set(within_group) {
4589 Self::push_unsupported_diagnostic(
4590 diagnostics,
4591 "RANK/DENSE_RANK/CUME_DIST/PERCENT_RANK hypothetical-set aggregates",
4592 );
4593 return;
4594 }
4595
4596 if Self::within_group_is_mode(within_group) {
4597 Self::push_unsupported_diagnostic(diagnostics, "MODE ordered-set aggregates");
4598 return;
4599 }
4600
4601 if Self::within_group_is_percentile(within_group) {
4602 Self::push_unsupported_diagnostic(
4603 diagnostics,
4604 "PERCENTILE_CONT/PERCENTILE_DISC ordered-set aggregates without OVER",
4605 );
4606 return;
4607 }
4608 }
4609 _ => {}
4610 }
4611
4612 for child in expr.children() {
4613 Self::collect_tsql_unsupported_ordered_sets(child, diagnostics);
4614 }
4615 }
4616
4617 fn within_group_is_hypothetical_set(within_group: &crate::expressions::WithinGroup) -> bool {
4618 match &within_group.this {
4619 Expression::Function(function) => Self::is_hypothetical_set_name(&function.name),
4620 Expression::AggregateFunction(function) => {
4621 Self::is_hypothetical_set_name(&function.name)
4622 }
4623 Expression::Rank(_)
4624 | Expression::DenseRank(_)
4625 | Expression::CumeDist(_)
4626 | Expression::PercentRank(_) => true,
4627 _ => false,
4628 }
4629 }
4630
4631 fn within_group_is_percentile(within_group: &crate::expressions::WithinGroup) -> bool {
4632 match &within_group.this {
4633 Expression::Function(function) => Self::is_percentile_ordered_set_name(&function.name),
4634 Expression::AggregateFunction(function) => {
4635 Self::is_percentile_ordered_set_name(&function.name)
4636 }
4637 Expression::PercentileCont(_) | Expression::PercentileDisc(_) => true,
4638 _ => false,
4639 }
4640 }
4641
4642 fn within_group_is_mode(within_group: &crate::expressions::WithinGroup) -> bool {
4643 match &within_group.this {
4644 Expression::Function(function) => function.name.eq_ignore_ascii_case("MODE"),
4645 Expression::AggregateFunction(function) => function.name.eq_ignore_ascii_case("MODE"),
4646 Expression::Mode(_) => true,
4647 _ => false,
4648 }
4649 }
4650
4651 fn is_percentile_ordered_set_name(name: &str) -> bool {
4652 name.eq_ignore_ascii_case("PERCENTILE_CONT") || name.eq_ignore_ascii_case("PERCENTILE_DISC")
4653 }
4654
4655 fn is_hypothetical_set_name(name: &str) -> bool {
4656 name.eq_ignore_ascii_case("RANK")
4657 || name.eq_ignore_ascii_case("DENSE_RANK")
4658 || name.eq_ignore_ascii_case("CUME_DIST")
4659 || name.eq_ignore_ascii_case("PERCENT_RANK")
4660 }
4661
4662 fn target_supports_distinct_on(target: DialectType) -> bool {
4663 matches!(target, DialectType::PostgreSQL | DialectType::DuckDB)
4664 }
4665
4666 fn node_has_distinct_on(expr: &Expression) -> bool {
4667 matches!(
4668 expr,
4669 Expression::Select(select)
4670 if select
4671 .distinct_on
4672 .as_ref()
4673 .is_some_and(|distinct_on| !distinct_on.is_empty())
4674 )
4675 }
4676
4677 fn node_has_recursive_with(expr: &Expression) -> bool {
4678 fn recursive(with: &Option<With>) -> bool {
4679 with.as_ref().is_some_and(|with| with.recursive)
4680 }
4681
4682 match expr {
4683 Expression::With(with) => with.recursive,
4684 Expression::Select(select) => recursive(&select.with),
4685 Expression::Union(union) => recursive(&union.with),
4686 Expression::Intersect(intersect) => recursive(&intersect.with),
4687 Expression::Except(except) => recursive(&except.with),
4688 Expression::Pivot(pivot) => recursive(&pivot.with),
4689 Expression::Insert(insert) => recursive(&insert.with),
4690 Expression::Update(update) => recursive(&update.with),
4691 Expression::Delete(delete) => recursive(&delete.with),
4692 _ => false,
4693 }
4694 }
4695
4696 fn node_has_lateral(expr: &Expression) -> bool {
4697 fn join_has_lateral(join: &Join) -> bool {
4698 matches!(
4699 join.kind,
4700 crate::expressions::JoinKind::Lateral | crate::expressions::JoinKind::LeftLateral
4701 ) || Dialect::node_has_lateral(&join.this)
4702 || join.on.as_ref().is_some_and(Dialect::node_has_lateral)
4703 || join
4704 .match_condition
4705 .as_ref()
4706 .is_some_and(Dialect::node_has_lateral)
4707 || join.pivots.iter().any(Dialect::node_has_lateral)
4708 }
4709
4710 fn joins_have_lateral(joins: &[Join]) -> bool {
4711 joins.iter().any(join_has_lateral)
4712 }
4713
4714 match expr {
4715 Expression::Subquery(subquery) => {
4716 subquery.lateral || Dialect::node_has_lateral(&subquery.this)
4717 }
4718 Expression::Lateral(_) | Expression::LateralView(_) => true,
4719 Expression::Join(join) => join_has_lateral(join),
4720 Expression::Select(select) => {
4721 !select.lateral_views.is_empty()
4722 || joins_have_lateral(&select.joins)
4723 || select
4724 .from
4725 .as_ref()
4726 .is_some_and(|from| from.expressions.iter().any(Dialect::node_has_lateral))
4727 }
4728 Expression::JoinedTable(joined) => {
4729 !joined.lateral_views.is_empty()
4730 || Dialect::node_has_lateral(&joined.left)
4731 || joins_have_lateral(&joined.joins)
4732 }
4733 Expression::Update(update) => {
4734 joins_have_lateral(&update.table_joins) || joins_have_lateral(&update.from_joins)
4735 }
4736 _ => false,
4737 }
4738 }
4739
4740 fn node_has_join_using(expr: &Expression) -> bool {
4741 fn has_using(joins: &[Join]) -> bool {
4742 joins.iter().any(|join| !join.using.is_empty())
4743 }
4744
4745 match expr {
4746 Expression::Join(join) => !join.using.is_empty(),
4747 Expression::Select(select) => has_using(&select.joins),
4748 Expression::JoinedTable(joined) => has_using(&joined.joins),
4749 Expression::Update(update) => {
4750 has_using(&update.table_joins) || has_using(&update.from_joins)
4751 }
4752 Expression::Delete(delete) => has_using(&delete.joins),
4753 _ => false,
4754 }
4755 }
4756
4757 fn node_has_natural_join(expr: &Expression) -> bool {
4758 fn is_natural(join: &Join) -> bool {
4759 matches!(
4760 join.kind,
4761 crate::expressions::JoinKind::Natural
4762 | crate::expressions::JoinKind::NaturalLeft
4763 | crate::expressions::JoinKind::NaturalRight
4764 | crate::expressions::JoinKind::NaturalFull
4765 )
4766 }
4767
4768 fn has_natural(joins: &[Join]) -> bool {
4769 joins.iter().any(is_natural)
4770 }
4771
4772 match expr {
4773 Expression::Join(join) => is_natural(join),
4774 Expression::Select(select) => has_natural(&select.joins),
4775 Expression::JoinedTable(joined) => has_natural(&joined.joins),
4776 Expression::Update(update) => {
4777 has_natural(&update.table_joins) || has_natural(&update.from_joins)
4778 }
4779 Expression::Delete(delete) => has_natural(&delete.joins),
4780 _ => false,
4781 }
4782 }
4783
4784 fn node_has_unsupported_relation_column_aliases(expr: &Expression) -> bool {
4785 match expr {
4786 Expression::Table(table) => !table.column_aliases.is_empty(),
4787 Expression::Alias(alias) => {
4788 !alias.column_aliases.is_empty()
4789 && matches!(
4790 alias.this,
4791 Expression::Table(_) | Expression::JoinedTable(_)
4792 )
4793 }
4794 _ => false,
4795 }
4796 }
4797
4798 fn node_has_qualified_whole_row_aggregate_argument(expr: &Expression) -> bool {
4799 fn contains_qualified_star(expr: &Expression) -> bool {
4800 match expr {
4801 Expression::Star(star) => star.table.is_some(),
4802 Expression::Select(_)
4805 | Expression::Subquery(_)
4806 | Expression::Union(_)
4807 | Expression::Intersect(_)
4808 | Expression::Except(_) => false,
4809 _ => expr.children().into_iter().any(contains_qualified_star),
4810 }
4811 }
4812
4813 let is_aggregate = matches!(
4814 expr,
4815 Expression::AggregateFunction(_)
4816 | Expression::Count(_)
4817 | Expression::Sum(_)
4818 | Expression::Avg(_)
4819 | Expression::Min(_)
4820 | Expression::Max(_)
4821 | Expression::GroupConcat(_)
4822 | Expression::StringAgg(_)
4823 | Expression::ListAgg(_)
4824 | Expression::ArrayAgg(_)
4825 | Expression::CountIf(_)
4826 | Expression::SumIf(_)
4827 | Expression::Stddev(_)
4828 | Expression::StddevPop(_)
4829 | Expression::StddevSamp(_)
4830 | Expression::Variance(_)
4831 | Expression::VarPop(_)
4832 | Expression::VarSamp(_)
4833 | Expression::Median(_)
4834 | Expression::Mode(_)
4835 | Expression::First(_)
4836 | Expression::Last(_)
4837 | Expression::AnyValue(_)
4838 | Expression::ApproxDistinct(_)
4839 | Expression::ApproxCountDistinct(_)
4840 | Expression::ApproxPercentile(_)
4841 | Expression::Percentile(_)
4842 | Expression::LogicalAnd(_)
4843 | Expression::LogicalOr(_)
4844 | Expression::Skewness(_)
4845 | Expression::BitwiseCount(_)
4846 | Expression::BitwiseAndAgg(_)
4847 | Expression::BitwiseOrAgg(_)
4848 | Expression::BitwiseXorAgg(_)
4849 | Expression::ArrayConcatAgg(_)
4850 | Expression::ArrayUniqueAgg(_)
4851 | Expression::BoolXorAgg(_)
4852 | Expression::JsonArrayAgg(_)
4853 | Expression::JsonObjectAgg(_)
4854 | Expression::ParameterizedAgg(_)
4855 | Expression::ArgMax(_)
4856 | Expression::ArgMin(_)
4857 | Expression::ApproxTopK(_)
4858 | Expression::ApproxTopKAccumulate(_)
4859 | Expression::ApproxTopKCombine(_)
4860 | Expression::ApproxTopKEstimate(_)
4861 | Expression::ApproxTopSum(_)
4862 | Expression::ApproxQuantiles(_)
4863 | Expression::AnonymousAggFunc(_)
4864 | Expression::CombinedAggFunc(_)
4865 | Expression::CombinedParameterizedAgg(_)
4866 | Expression::HashAgg(_)
4867 | Expression::ObjectAgg(_)
4868 | Expression::AIAgg(_)
4869 );
4870
4871 is_aggregate && expr.children().into_iter().any(contains_qualified_star)
4872 }
4873
4874 fn target_supports_remaining_unnest(target: DialectType) -> bool {
4875 matches!(
4876 target,
4877 DialectType::PostgreSQL
4878 | DialectType::BigQuery
4879 | DialectType::DuckDB
4880 | DialectType::Presto
4881 | DialectType::Trino
4882 | DialectType::Athena
4883 )
4884 }
4885
4886 fn target_supports_remaining_explode(target: DialectType) -> bool {
4887 matches!(
4888 target,
4889 DialectType::Spark | DialectType::Databricks | DialectType::Hive
4890 )
4891 }
4892
4893 fn target_lacks_array_agg(target: DialectType) -> bool {
4894 matches!(
4895 target,
4896 DialectType::Fabric
4897 | DialectType::TSQL
4898 | DialectType::MySQL
4899 | DialectType::SQLite
4900 | DialectType::Oracle
4901 )
4902 }
4903
4904 fn node_is_unnest(expr: &Expression) -> bool {
4905 matches!(expr, Expression::Unnest(_)) || Self::node_is_function_named(expr, "UNNEST")
4906 }
4907
4908 fn node_is_explode(expr: &Expression) -> bool {
4909 matches!(expr, Expression::Explode(_) | Expression::ExplodeOuter(_))
4910 || Self::node_is_function_named(expr, "EXPLODE")
4911 || Self::node_is_function_named(expr, "EXPLODE_OUTER")
4912 }
4913
4914 fn node_is_array_agg(expr: &Expression) -> bool {
4915 matches!(expr, Expression::ArrayAgg(_)) || Self::node_is_function_named(expr, "ARRAY_AGG")
4916 }
4917
4918 fn node_is_distinct_string_agg(expr: &Expression) -> bool {
4919 match expr {
4920 Expression::StringAgg(agg) => agg.distinct,
4921 Expression::Function(function) => {
4922 function.distinct && function.name.eq_ignore_ascii_case("STRING_AGG")
4923 }
4924 Expression::AggregateFunction(function) => {
4925 function.distinct && function.name.eq_ignore_ascii_case("STRING_AGG")
4926 }
4927 _ => false,
4928 }
4929 }
4930
4931 fn postgres_tsql_unsupported_collation_name(expr: &Expression) -> Option<&'static str> {
4932 let Expression::Collation(collation) = expr else {
4933 return None;
4934 };
4935
4936 if collation.collation.eq_ignore_ascii_case("C") {
4937 Some("C")
4938 } else if collation.collation.eq_ignore_ascii_case("POSIX") {
4939 Some("POSIX")
4940 } else {
4941 None
4942 }
4943 }
4944
4945 fn postgres_tsql_unsupported_composite_semantics(expr: &Expression) -> Option<&'static str> {
4946 match expr {
4947 Expression::Tuple(_) | Expression::Struct(_) | Expression::StructFunc(_) => {
4948 Some("row/composite values")
4949 }
4950 Expression::Function(function)
4951 if !function.quoted && function.name.eq_ignore_ascii_case("ROW") =>
4952 {
4953 Some("row/composite values")
4954 }
4955 Expression::StructExtract(_) => Some("row/composite field access"),
4956 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) if matches!(&cast.this, Expression::Star(star) if star.table.is_some()) => {
4957 Some("qualified whole-row casts")
4958 }
4959 _ => None,
4960 }
4961 }
4962
4963 fn node_is_postgres_unknown_cast(expr: &Expression) -> bool {
4964 match expr {
4965 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) => {
4966 normalization::is_postgres_unknown_type(&cast.to)
4967 }
4968 _ => false,
4969 }
4970 }
4971
4972 fn postgres_tsql_unsupported_array_semantics(expr: &Expression) -> Option<&'static str> {
4973 match expr {
4974 Expression::Array(_) | Expression::ArrayFunc(_) => Some("array literals"),
4975 Expression::Subscript(_) => Some("array subscripts"),
4976 Expression::ArraySlice(_) => Some("array slices"),
4977 Expression::DataType(DataType::Array { .. }) => Some("array data types"),
4978 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast)
4979 if matches!(&cast.to, DataType::Array { .. }) =>
4980 {
4981 Some("array data types")
4982 }
4983 Expression::ArrayLength(_) | Expression::ArraySize(_) => Some("ARRAY_LENGTH"),
4984 Expression::Cardinality(_) => Some("CARDINALITY"),
4985 Expression::ArrayToString(_) | Expression::ArrayJoin(_) => Some("ARRAY_TO_STRING"),
4986 Expression::StringToArray(_) => Some("STRING_TO_ARRAY"),
4987 Expression::ArrayContains(_)
4988 | Expression::ArrayPosition(_)
4989 | Expression::ArrayAppend(_)
4990 | Expression::ArrayPrepend(_)
4991 | Expression::ArrayConcat(_)
4992 | Expression::ArraySort(_)
4993 | Expression::ArrayReverse(_)
4994 | Expression::ArrayDistinct(_)
4995 | Expression::ArrayFilter(_)
4996 | Expression::ArrayTransform(_)
4997 | Expression::ArrayFlatten(_)
4998 | Expression::ArrayCompact(_)
4999 | Expression::ArrayIntersect(_)
5000 | Expression::ArrayUnion(_)
5001 | Expression::ArrayExcept(_)
5002 | Expression::ArrayRemove(_)
5003 | Expression::ArrayZip(_)
5004 | Expression::ArrayAll(_)
5005 | Expression::ArrayAny(_)
5006 | Expression::ArrayConstructCompact(_)
5007 | Expression::ArraySum(_) => Some("array functions"),
5008 Expression::ArrayContainsAll(_)
5009 | Expression::ArrayContainedBy(_)
5010 | Expression::ArrayOverlaps(_) => Some("array operators"),
5011 Expression::Function(function) => {
5012 Self::postgres_tsql_unsupported_array_function_name_str(&function.name)
5013 }
5014 Expression::AggregateFunction(function) => {
5015 Self::postgres_tsql_unsupported_array_function_name_str(&function.name)
5016 }
5017 _ => None,
5018 }
5019 }
5020
5021 fn postgres_tsql_unsupported_array_function_name_str(name: &str) -> Option<&'static str> {
5022 if name.eq_ignore_ascii_case("ARRAY") {
5023 Some("array literals")
5024 } else if name.eq_ignore_ascii_case("ARRAY_LENGTH")
5025 || name.eq_ignore_ascii_case("ARRAY_SIZE")
5026 {
5027 Some("ARRAY_LENGTH")
5028 } else if name.eq_ignore_ascii_case("CARDINALITY") {
5029 Some("CARDINALITY")
5030 } else if name.eq_ignore_ascii_case("ARRAY_TO_STRING")
5031 || name.eq_ignore_ascii_case("ARRAY_JOIN")
5032 {
5033 Some("ARRAY_TO_STRING")
5034 } else if name.eq_ignore_ascii_case("STRING_TO_ARRAY") {
5035 Some("STRING_TO_ARRAY")
5036 } else {
5037 None
5038 }
5039 }
5040
5041 fn node_is_regex_predicate(expr: &Expression) -> bool {
5042 matches!(
5043 expr,
5044 Expression::SimilarTo(_) | Expression::RegexpLike(_) | Expression::RegexpILike(_)
5045 ) || Self::node_is_function_named(expr, "REGEXP_LIKE")
5046 || Self::node_is_function_named(expr, "REGEXP_I_LIKE")
5047 || Self::node_is_function_named(expr, "REGEXP_ILIKE")
5048 }
5049
5050 fn node_is_non_subquery_any(expr: &Expression) -> bool {
5051 matches!(
5052 expr,
5053 Expression::Any(q) if !Self::quantified_rhs_is_subquery(&q.subquery)
5054 )
5055 }
5056
5057 fn quantified_rhs_is_subquery(expr: &Expression) -> bool {
5058 match expr {
5059 Expression::Select(_) | Expression::Subquery(_) => true,
5060 Expression::Paren(paren) => Self::quantified_rhs_is_subquery(&paren.this),
5061 _ => false,
5062 }
5063 }
5064
5065 fn node_is_row_value_subquery_comparison(expr: &Expression) -> bool {
5066 match expr {
5067 Expression::In(in_expr) => {
5068 Self::in_rhs_is_subquery_like(in_expr) && Self::expr_is_row_value(&in_expr.this)
5069 }
5070 Expression::Eq(op) | Expression::Neq(op) => {
5071 (Self::expr_is_row_value(&op.left) && Self::expr_is_subquery_like(&op.right))
5072 || (Self::expr_is_row_value(&op.right) && Self::expr_is_subquery_like(&op.left))
5073 }
5074 _ => false,
5075 }
5076 }
5077
5078 fn node_is_row_value_values_membership(expr: &Expression) -> bool {
5079 matches!(
5080 expr,
5081 Expression::In(in_expr)
5082 if Self::expr_is_row_value(&in_expr.this)
5083 && Self::in_rhs_is_values_like(in_expr)
5084 )
5085 }
5086
5087 fn expr_is_row_value(expr: &Expression) -> bool {
5088 match expr {
5089 Expression::Tuple(tuple) => tuple.expressions.len() > 1,
5090 Expression::Function(function) if function.name.eq_ignore_ascii_case("ROW") => {
5091 function.args.len() > 1
5092 }
5093 Expression::Paren(paren) => Self::expr_is_row_value(&paren.this),
5094 _ => false,
5095 }
5096 }
5097
5098 fn expr_is_subquery_like(expr: &Expression) -> bool {
5099 match expr {
5100 Expression::Select(_) | Expression::Subquery(_) => true,
5101 Expression::Paren(paren) => Self::expr_is_subquery_like(&paren.this),
5102 _ => false,
5103 }
5104 }
5105
5106 fn in_rhs_is_subquery_like(in_expr: &crate::expressions::In) -> bool {
5107 if in_expr
5108 .query
5109 .as_ref()
5110 .is_some_and(Self::expr_is_subquery_like)
5111 {
5112 return true;
5113 }
5114
5115 in_expr.expressions.len() == 1 && Self::expr_is_subquery_like(&in_expr.expressions[0])
5116 }
5117
5118 fn in_rhs_is_values_like(in_expr: &crate::expressions::In) -> bool {
5119 if in_expr
5120 .query
5121 .as_ref()
5122 .is_some_and(Self::expr_is_values_like)
5123 {
5124 return true;
5125 }
5126
5127 (in_expr.expressions.len() == 1
5128 && Self::expr_is_values_like(&in_expr.expressions[0]))
5129 || in_expr.expressions.first().is_some_and(|expr| {
5130 matches!(expr, Expression::Function(function) if function.name.eq_ignore_ascii_case("VALUES"))
5131 })
5132 }
5133
5134 fn expr_is_values_like(expr: &Expression) -> bool {
5135 match expr {
5136 Expression::Values(_) => true,
5137 Expression::Paren(paren) => Self::expr_is_values_like(&paren.this),
5138 Expression::Subquery(subquery) => Self::expr_is_values_like(&subquery.this),
5139 _ => false,
5140 }
5141 }
5142
5143 fn normalize_tsql_fetch_overlaps_date_bin(expr: Expression) -> Result<Expression> {
5144 transform_recursive(expr, &|e| match e {
5145 Expression::Select(mut select) => {
5146 if select.top.is_none() && select.offset.is_none() {
5147 if let Some(fetch) = select.fetch.take() {
5148 if let Some(top) = Self::fetch_with_ties_to_top(fetch.clone()) {
5149 select.top = Some(top);
5150 } else {
5151 select.fetch = Some(fetch);
5152 }
5153 }
5154 }
5155 Self::rewrite_tsql_overlaps_in_select_predicates(&mut select)?;
5156 Ok(Expression::Select(select))
5157 }
5158 Expression::DateBin(date_bin) => {
5159 let date_bin = *date_bin;
5160 if let Some(rewritten) = Self::date_bin_to_date_bucket(date_bin.clone()) {
5161 Ok(rewritten)
5162 } else {
5163 Ok(Expression::DateBin(Box::new(date_bin)))
5164 }
5165 }
5166 Expression::Function(function) => {
5167 let function = *function;
5168 if function.name.eq_ignore_ascii_case("DATE_BIN") {
5169 if let Some(rewritten) = Self::date_bin_function_to_date_bucket(&function) {
5170 Ok(rewritten)
5171 } else {
5172 Ok(Expression::Function(Box::new(function)))
5173 }
5174 } else {
5175 Ok(Expression::Function(Box::new(function)))
5176 }
5177 }
5178 _ => Ok(e),
5179 })
5180 }
5181
5182 fn rewrite_tsql_overlaps_in_select_predicates(
5183 select: &mut crate::expressions::Select,
5184 ) -> Result<()> {
5185 if let Some(where_clause) = &mut select.where_clause {
5186 where_clause.this = Self::rewrite_tsql_overlaps_predicate(where_clause.this.clone())?;
5187 }
5188 if let Some(having) = &mut select.having {
5189 having.this = Self::rewrite_tsql_overlaps_predicate(having.this.clone())?;
5190 }
5191 if let Some(qualify) = &mut select.qualify {
5192 qualify.this = Self::rewrite_tsql_overlaps_predicate(qualify.this.clone())?;
5193 }
5194 for join in &mut select.joins {
5195 if let Some(on) = join.on.take() {
5196 join.on = Some(Self::rewrite_tsql_overlaps_predicate(on)?);
5197 }
5198 if let Some(match_condition) = join.match_condition.take() {
5199 join.match_condition =
5200 Some(Self::rewrite_tsql_overlaps_predicate(match_condition)?);
5201 }
5202 }
5203 Ok(())
5204 }
5205
5206 fn rewrite_tsql_overlaps_predicate(expr: Expression) -> Result<Expression> {
5207 transform_recursive(expr, &|e| match e {
5208 Expression::Overlaps(overlaps) => {
5209 let overlaps = *overlaps;
5210 if let Some(rewritten) = Self::rewrite_full_overlaps_for_tsql(&overlaps) {
5211 Ok(rewritten)
5212 } else {
5213 Ok(Expression::Overlaps(Box::new(overlaps)))
5214 }
5215 }
5216 _ => Ok(e),
5217 })
5218 }
5219
5220 fn fetch_with_ties_to_top(fetch: Fetch) -> Option<Top> {
5221 if !fetch.with_ties {
5222 return None;
5223 }
5224
5225 fetch.count.map(|count| Top {
5226 this: count,
5227 percent: fetch.percent,
5228 with_ties: true,
5229 parenthesized: true,
5230 })
5231 }
5232
5233 fn rewrite_full_overlaps_for_tsql(
5234 overlaps: &crate::expressions::OverlapsExpr,
5235 ) -> Option<Expression> {
5236 let (left_start, left_end, right_start, right_end) =
5237 if let (Some(left_start), Some(left_end), Some(right_start), Some(right_end)) = (
5238 overlaps.left_start.as_ref(),
5239 overlaps.left_end.as_ref(),
5240 overlaps.right_start.as_ref(),
5241 overlaps.right_end.as_ref(),
5242 ) {
5243 (left_start, left_end, right_start, right_end)
5244 } else if let (
5245 Some(Expression::Tuple(left_tuple)),
5246 Some(Expression::Tuple(right_tuple)),
5247 ) = (&overlaps.this, &overlaps.expression)
5248 {
5249 if left_tuple.expressions.len() != 2 || right_tuple.expressions.len() != 2 {
5250 return None;
5251 }
5252 (
5253 &left_tuple.expressions[0],
5254 &left_tuple.expressions[1],
5255 &right_tuple.expressions[0],
5256 &right_tuple.expressions[1],
5257 )
5258 } else {
5259 return None;
5260 };
5261
5262 let left_min = Self::case_min(left_start.clone(), left_end.clone());
5263 let left_max = Self::case_max(left_start.clone(), left_end.clone());
5264 let right_min = Self::case_min(right_start.clone(), right_end.clone());
5265 let right_max = Self::case_max(right_start.clone(), right_end.clone());
5266
5267 Some(Expression::And(Box::new(BinaryOp::new(
5268 Expression::Lte(Box::new(BinaryOp::new(left_min, right_max))),
5269 Expression::Lte(Box::new(BinaryOp::new(right_min, left_max))),
5270 ))))
5271 }
5272
5273 fn case_min(left: Expression, right: Expression) -> Expression {
5274 Expression::Case(Box::new(Case {
5275 operand: None,
5276 whens: vec![(
5277 Expression::Lte(Box::new(BinaryOp::new(left.clone(), right.clone()))),
5278 left,
5279 )],
5280 else_: Some(right),
5281 comments: Vec::new(),
5282 inferred_type: None,
5283 }))
5284 }
5285
5286 fn case_max(left: Expression, right: Expression) -> Expression {
5287 Expression::Case(Box::new(Case {
5288 operand: None,
5289 whens: vec![(
5290 Expression::Gte(Box::new(BinaryOp::new(left.clone(), right.clone()))),
5291 left,
5292 )],
5293 else_: Some(right),
5294 comments: Vec::new(),
5295 inferred_type: None,
5296 }))
5297 }
5298
5299 fn date_bin_to_date_bucket(date_bin: DateBin) -> Option<Expression> {
5300 if date_bin.unit.is_some() || date_bin.zone.is_some() {
5301 return None;
5302 }
5303
5304 let (datepart, number) = Self::date_bucket_parts(&date_bin.this)?;
5305 let mut args = vec![
5306 Self::date_bucket_datepart(datepart),
5307 number,
5308 *date_bin.expression,
5309 ];
5310 if let Some(origin) = date_bin.origin {
5311 args.push(*origin);
5312 }
5313
5314 Some(Expression::Function(Box::new(Function::new(
5315 "DATE_BUCKET".to_string(),
5316 args,
5317 ))))
5318 }
5319
5320 fn date_bin_function_to_date_bucket(function: &Function) -> Option<Expression> {
5321 if !(2..=3).contains(&function.args.len()) {
5322 return None;
5323 }
5324
5325 let (datepart, number) = Self::date_bucket_parts(&function.args[0])?;
5326 let mut args = vec![
5327 Self::date_bucket_datepart(datepart),
5328 number,
5329 function.args[1].clone(),
5330 ];
5331 if let Some(origin) = function.args.get(2) {
5332 args.push(origin.clone());
5333 }
5334
5335 Some(Expression::Function(Box::new(Function::new(
5336 "DATE_BUCKET".to_string(),
5337 args,
5338 ))))
5339 }
5340
5341 fn date_bucket_parts(stride: &Expression) -> Option<(&'static str, Expression)> {
5342 match stride {
5343 Expression::Literal(lit) => match lit.as_ref() {
5344 Literal::String(value) => Self::date_bucket_parts_from_string(value),
5345 _ => None,
5346 },
5347 Expression::Interval(interval) => Self::date_bucket_parts_from_interval(interval),
5348 _ => None,
5349 }
5350 }
5351
5352 fn date_bucket_parts_from_interval(interval: &Interval) -> Option<(&'static str, Expression)> {
5353 match &interval.unit {
5354 Some(IntervalUnitSpec::Simple { unit, .. }) => {
5355 let datepart = Self::date_bucket_datepart_from_unit(*unit)?;
5356 let amount = interval
5357 .this
5358 .as_ref()
5359 .and_then(Self::date_bucket_amount_expr)?;
5360 Some((datepart, amount))
5361 }
5362 None => interval.this.as_ref().and_then(|expr| match expr {
5363 Expression::Literal(lit) => match lit.as_ref() {
5364 Literal::String(value) => Self::date_bucket_parts_from_string(value),
5365 _ => None,
5366 },
5367 _ => None,
5368 }),
5369 _ => None,
5370 }
5371 }
5372
5373 fn date_bucket_parts_from_string(value: &str) -> Option<(&'static str, Expression)> {
5374 let mut parts = value.split_whitespace();
5375 let amount = parts.next()?;
5376 let unit = parts.next()?;
5377 if parts.next().is_some() {
5378 return None;
5379 }
5380
5381 Some((
5382 Self::date_bucket_datepart_from_name(unit)?,
5383 Self::positive_integer_expr(amount)?,
5384 ))
5385 }
5386
5387 fn date_bucket_amount_expr(expr: &Expression) -> Option<Expression> {
5388 match expr {
5389 Expression::Literal(lit) => match lit.as_ref() {
5390 Literal::Number(value) => Self::positive_integer_expr(value),
5391 Literal::String(value) => Self::positive_integer_expr(value),
5392 _ => None,
5393 },
5394 _ => Some(expr.clone()),
5395 }
5396 }
5397
5398 fn positive_integer_expr(value: &str) -> Option<Expression> {
5399 let parsed = value.trim().parse::<i64>().ok()?;
5400 (parsed > 0).then(|| Expression::number(parsed))
5401 }
5402
5403 fn date_bucket_datepart(datepart: &str) -> Expression {
5404 Expression::Var(Box::new(Var {
5405 this: datepart.to_string(),
5406 }))
5407 }
5408
5409 fn date_bucket_datepart_from_unit(unit: IntervalUnit) -> Option<&'static str> {
5410 match unit {
5411 IntervalUnit::Week => Some("WEEK"),
5412 IntervalUnit::Day => Some("DAY"),
5413 IntervalUnit::Hour => Some("HOUR"),
5414 IntervalUnit::Minute => Some("MINUTE"),
5415 IntervalUnit::Second => Some("SECOND"),
5416 IntervalUnit::Millisecond => Some("MILLISECOND"),
5417 _ => None,
5418 }
5419 }
5420
5421 fn date_bucket_datepart_from_name(unit: &str) -> Option<&'static str> {
5422 match unit.trim().to_ascii_uppercase().as_str() {
5423 "WEEK" | "WEEKS" | "W" | "WK" | "WKS" | "WW" => Some("WEEK"),
5424 "DAY" | "DAYS" | "D" | "DD" => Some("DAY"),
5425 "HOUR" | "HOURS" | "H" | "HH" | "HR" | "HRS" => Some("HOUR"),
5426 "MINUTE" | "MINUTES" | "MI" | "MIN" | "MINS" | "N" => Some("MINUTE"),
5427 "SECOND" | "SECONDS" | "S" | "SEC" | "SECS" | "SS" => Some("SECOND"),
5428 "MILLISECOND" | "MILLISECONDS" | "MS" | "MSEC" | "MSECS" | "MILLISEC" | "MILLISECS" => {
5429 Some("MILLISECOND")
5430 }
5431 _ => None,
5432 }
5433 }
5434
5435 fn node_has_fetch_with_ties(expr: &Expression) -> bool {
5436 matches!(
5437 expr,
5438 Expression::Select(select)
5439 if select
5440 .fetch
5441 .as_ref()
5442 .is_some_and(|fetch| fetch.with_ties)
5443 )
5444 }
5445
5446 fn node_is_overlaps(expr: &Expression) -> bool {
5447 matches!(expr, Expression::Overlaps(_))
5448 }
5449
5450 fn node_is_date_bin(expr: &Expression) -> bool {
5451 matches!(expr, Expression::DateBin(_)) || Self::node_is_function_named(expr, "DATE_BIN")
5452 }
5453
5454 fn node_is_function_named(expr: &Expression, name: &str) -> bool {
5455 match expr {
5456 Expression::Function(function) => function.name.eq_ignore_ascii_case(name),
5457 Expression::AggregateFunction(function) => function.name.eq_ignore_ascii_case(name),
5458 _ => false,
5459 }
5460 }
5461
5462 fn node_is_postgres_json_build_object(expr: &Expression) -> bool {
5463 match expr {
5464 Expression::Function(function) => {
5465 function.name.eq_ignore_ascii_case("JSON_BUILD_OBJECT")
5466 || function.name.eq_ignore_ascii_case("JSONB_BUILD_OBJECT")
5467 }
5468 _ => false,
5469 }
5470 }
5471
5472 fn postgres_json_build_object_can_lower_to_json_object(expr: &Expression) -> bool {
5473 matches!(
5474 expr,
5475 Expression::Function(function)
5476 if (function.name.eq_ignore_ascii_case("JSON_BUILD_OBJECT")
5477 || function.name.eq_ignore_ascii_case("JSONB_BUILD_OBJECT"))
5478 && !function.distinct
5479 && function.args.len() % 2 == 0
5480 )
5481 }
5482
5483 fn node_is_postgres_json_array_elements(expr: &Expression) -> bool {
5484 matches!(
5485 expr,
5486 Expression::Function(function)
5487 if function.name.eq_ignore_ascii_case("JSON_ARRAY_ELEMENTS")
5488 || function.name.eq_ignore_ascii_case("JSONB_ARRAY_ELEMENTS")
5489 || function.name.eq_ignore_ascii_case("JSON_ARRAY_ELEMENTS_TEXT")
5490 || function.name.eq_ignore_ascii_case("JSONB_ARRAY_ELEMENTS_TEXT")
5491 )
5492 }
5493
5494 fn postgres_tsql_unsupported_function_name(expr: &Expression) -> Option<&'static str> {
5495 match expr {
5496 Expression::Lpad(_) => Some("LPAD"),
5497 Expression::Rpad(_) => Some("RPAD"),
5498 Expression::SplitPart(_) => Some("SPLIT_PART"),
5499 Expression::Initcap(_) => Some("INITCAP"),
5500 Expression::ToJson(_) => Some("TO_JSON"),
5501 Expression::JSONBObjectAgg(_) => Some("JSONB_OBJECT_AGG"),
5502 Expression::ToNumber(_) => Some("TO_NUMBER"),
5503 Expression::WidthBucket(_) => Some("WIDTH_BUCKET"),
5504 Expression::BitwiseAndAgg(_) => Some("BIT_AND"),
5505 Expression::BitwiseOrAgg(_) => Some("BIT_OR"),
5506 Expression::BitwiseXorAgg(_) => Some("BIT_XOR"),
5507 Expression::Corr(_) => Some("CORR"),
5508 Expression::CovarPop(_) => Some("COVAR_POP"),
5509 Expression::CovarSamp(_) => Some("COVAR_SAMP"),
5510 Expression::RegrAvgx(_) => Some("REGR_AVGX"),
5511 Expression::RegrAvgy(_) => Some("REGR_AVGY"),
5512 Expression::RegrCount(_) => Some("REGR_COUNT"),
5513 Expression::RegrIntercept(_) => Some("REGR_INTERCEPT"),
5514 Expression::RegrR2(_) => Some("REGR_R2"),
5515 Expression::RegrSlope(_) => Some("REGR_SLOPE"),
5516 Expression::RegrSxx(_) => Some("REGR_SXX"),
5517 Expression::RegrSxy(_) => Some("REGR_SXY"),
5518 Expression::RegrSyy(_) => Some("REGR_SYY"),
5519 Expression::Function(function) => {
5520 Self::postgres_tsql_unsupported_function_name_str(&function.name)
5521 }
5522 Expression::AggregateFunction(function) => {
5523 Self::postgres_tsql_unsupported_function_name_str(&function.name)
5524 }
5525 _ => None,
5526 }
5527 }
5528
5529 fn postgres_tsql_unsupported_function_name_str(name: &str) -> Option<&'static str> {
5530 if name.eq_ignore_ascii_case("LPAD") {
5531 Some("LPAD")
5532 } else if name.eq_ignore_ascii_case("RPAD") {
5533 Some("RPAD")
5534 } else if name.eq_ignore_ascii_case("SPLIT_PART") {
5535 Some("SPLIT_PART")
5536 } else if name.eq_ignore_ascii_case("INITCAP") {
5537 Some("INITCAP")
5538 } else if name.eq_ignore_ascii_case("TO_JSON") {
5539 Some("TO_JSON")
5540 } else if name.eq_ignore_ascii_case("TO_JSONB") {
5541 Some("TO_JSONB")
5542 } else if name.eq_ignore_ascii_case("JSONB_OBJECT_AGG") {
5543 Some("JSONB_OBJECT_AGG")
5544 } else if name.eq_ignore_ascii_case("ROW_TO_JSON") {
5545 Some("ROW_TO_JSON")
5546 } else if name.eq_ignore_ascii_case("JSON_ARRAY_ELEMENTS") {
5547 Some("JSON_ARRAY_ELEMENTS")
5548 } else if name.eq_ignore_ascii_case("JSONB_ARRAY_ELEMENTS") {
5549 Some("JSONB_ARRAY_ELEMENTS")
5550 } else if name.eq_ignore_ascii_case("JSON_ARRAY_ELEMENTS_TEXT") {
5551 Some("JSON_ARRAY_ELEMENTS_TEXT")
5552 } else if name.eq_ignore_ascii_case("JSONB_ARRAY_ELEMENTS_TEXT") {
5553 Some("JSONB_ARRAY_ELEMENTS_TEXT")
5554 } else if name.eq_ignore_ascii_case("ENCODE") {
5555 Some("ENCODE")
5556 } else if name.eq_ignore_ascii_case("AGE") {
5557 Some("AGE")
5558 } else if name.eq_ignore_ascii_case("ERF") {
5559 Some("ERF")
5560 } else if name.eq_ignore_ascii_case("GCD") {
5561 Some("GCD")
5562 } else if name.eq_ignore_ascii_case("LCM") {
5563 Some("LCM")
5564 } else if name.eq_ignore_ascii_case("QUOTE_LITERAL") {
5565 Some("QUOTE_LITERAL")
5566 } else if name.eq_ignore_ascii_case("WIDTH_BUCKET") {
5567 Some("WIDTH_BUCKET")
5568 } else if name.eq_ignore_ascii_case("SCALE") {
5569 Some("SCALE")
5570 } else if name.eq_ignore_ascii_case("TRIM_SCALE") {
5571 Some("TRIM_SCALE")
5572 } else if name.eq_ignore_ascii_case("MIN_SCALE") {
5573 Some("MIN_SCALE")
5574 } else if name.eq_ignore_ascii_case("FACTORIAL") {
5575 Some("FACTORIAL")
5576 } else if name.eq_ignore_ascii_case("PG_LSN") {
5577 Some("PG_LSN")
5578 } else if name.eq_ignore_ascii_case("TO_CHAR") {
5579 Some("TO_CHAR")
5580 } else if name.eq_ignore_ascii_case("PG_TYPEOF") {
5581 Some("PG_TYPEOF")
5582 } else if name.eq_ignore_ascii_case("BIT_AND") {
5583 Some("BIT_AND")
5584 } else if name.eq_ignore_ascii_case("BIT_OR") {
5585 Some("BIT_OR")
5586 } else if name.eq_ignore_ascii_case("BIT_XOR") {
5587 Some("BIT_XOR")
5588 } else if name.eq_ignore_ascii_case("CORR") {
5589 Some("CORR")
5590 } else if name.eq_ignore_ascii_case("COVAR_POP") {
5591 Some("COVAR_POP")
5592 } else if name.eq_ignore_ascii_case("COVAR_SAMP") {
5593 Some("COVAR_SAMP")
5594 } else if name.eq_ignore_ascii_case("REGR_AVGX") {
5595 Some("REGR_AVGX")
5596 } else if name.eq_ignore_ascii_case("REGR_AVGY") {
5597 Some("REGR_AVGY")
5598 } else if name.eq_ignore_ascii_case("REGR_COUNT") {
5599 Some("REGR_COUNT")
5600 } else if name.eq_ignore_ascii_case("REGR_INTERCEPT") {
5601 Some("REGR_INTERCEPT")
5602 } else if name.eq_ignore_ascii_case("REGR_R2") {
5603 Some("REGR_R2")
5604 } else if name.eq_ignore_ascii_case("REGR_SLOPE") {
5605 Some("REGR_SLOPE")
5606 } else if name.eq_ignore_ascii_case("REGR_SXX") {
5607 Some("REGR_SXX")
5608 } else if name.eq_ignore_ascii_case("REGR_SXY") {
5609 Some("REGR_SXY")
5610 } else if name.eq_ignore_ascii_case("REGR_SYY") {
5611 Some("REGR_SYY")
5612 } else if name.eq_ignore_ascii_case("FLOAT8_ACCUM") {
5613 Some("FLOAT8_ACCUM")
5614 } else if name.eq_ignore_ascii_case("FLOAT8_REGR_ACCUM") {
5615 Some("FLOAT8_REGR_ACCUM")
5616 } else if name.eq_ignore_ascii_case("FLOAT8_COMBINE") {
5617 Some("FLOAT8_COMBINE")
5618 } else if name.eq_ignore_ascii_case("FLOAT8_REGR_COMBINE") {
5619 Some("FLOAT8_REGR_COMBINE")
5620 } else if name.eq_ignore_ascii_case("BOOLAND_STATEFUNC") {
5621 Some("BOOLAND_STATEFUNC")
5622 } else if name.eq_ignore_ascii_case("BOOLOR_STATEFUNC") {
5623 Some("BOOLOR_STATEFUNC")
5624 } else {
5625 None
5626 }
5627 }
5628
5629 fn normalize_postgres_trim_for_tsql(expr: Expression) -> Result<Expression> {
5630 transform_recursive(expr, &|e| match e {
5631 Expression::Trim(trim) => {
5632 let mut trim = *trim;
5633 match trim.position {
5634 crate::expressions::TrimPosition::Both
5635 if trim.position_explicit && trim.characters.is_some() =>
5636 {
5637 trim.position_explicit = false;
5638 trim.sql_standard_syntax = true;
5639 Ok(Expression::Trim(Box::new(trim)))
5640 }
5641 crate::expressions::TrimPosition::Leading if trim.characters.is_some() => {
5642 let characters = trim.characters.take().expect("checked above");
5643 Ok(Expression::Function(Box::new(Function::new(
5644 "LTRIM",
5645 vec![trim.this, characters],
5646 ))))
5647 }
5648 crate::expressions::TrimPosition::Trailing if trim.characters.is_some() => {
5649 let characters = trim.characters.take().expect("checked above");
5650 Ok(Expression::Function(Box::new(Function::new(
5651 "RTRIM",
5652 vec![trim.this, characters],
5653 ))))
5654 }
5655 _ => Ok(Expression::Trim(Box::new(trim))),
5656 }
5657 }
5658 other => Ok(other),
5659 })
5660 }
5661
5662 fn normalize_postgres_only_for_tsql(expr: Expression) -> Result<Expression> {
5663 transform_recursive(expr, &|e| match e {
5664 Expression::Table(mut table) if table.only => {
5665 table.only = false;
5666 Ok(Expression::Table(table))
5667 }
5668 other => Ok(other),
5669 })
5670 }
5671
5672 fn rewrite_postgres_json_array_elements_select_for_tsql(
5673 expr: Expression,
5674 ) -> Result<Expression> {
5675 let Expression::Select(select) = expr else {
5676 return Ok(expr);
5677 };
5678 let mut select = *select;
5679 if !Self::is_plain_single_projection_select(&select) {
5680 return Ok(Expression::Select(Box::new(select)));
5681 }
5682
5683 let Some(json_arg) =
5684 Self::postgres_json_array_elements_projection_arg(&select.expressions[0])
5685 else {
5686 return Ok(Expression::Select(Box::new(select)));
5687 };
5688
5689 select.expressions = vec![Expression::column("value")];
5690 select.from = Some(From {
5691 expressions: vec![Expression::OpenJSON(Box::new(
5692 crate::expressions::OpenJSON {
5693 this: Box::new(json_arg),
5694 path: None,
5695 expressions: Vec::new(),
5696 },
5697 ))],
5698 });
5699
5700 Ok(Expression::Select(Box::new(select)))
5701 }
5702
5703 fn is_plain_single_projection_select(select: &crate::expressions::Select) -> bool {
5704 select.expressions.len() == 1
5705 && select.from.is_none()
5706 && select.joins.is_empty()
5707 && select.lateral_views.is_empty()
5708 && select.prewhere.is_none()
5709 && select.where_clause.is_none()
5710 && select.group_by.is_none()
5711 && select.having.is_none()
5712 && select.qualify.is_none()
5713 && select.order_by.is_none()
5714 && select.distribute_by.is_none()
5715 && select.cluster_by.is_none()
5716 && select.sort_by.is_none()
5717 && select.limit.is_none()
5718 && select.offset.is_none()
5719 && select.limit_by.is_none()
5720 && select.fetch.is_none()
5721 && !select.distinct
5722 && select.distinct_on.is_none()
5723 && select.top.is_none()
5724 && select.with.is_none()
5725 && select.sample.is_none()
5726 && select.into.is_none()
5727 && select.locks.is_empty()
5728 && select.for_xml.is_empty()
5729 && select.for_json.is_empty()
5730 && select.exclude.is_none()
5731 }
5732
5733 fn postgres_json_array_elements_projection_arg(expr: &Expression) -> Option<Expression> {
5734 match expr {
5735 Expression::Function(function)
5736 if Self::node_is_postgres_json_array_elements(expr) && function.args.len() == 1 =>
5737 {
5738 Some(function.args[0].clone())
5739 }
5740 Expression::Alias(alias) => {
5741 Self::postgres_json_array_elements_projection_arg(&alias.this)
5742 }
5743 _ => None,
5744 }
5745 }
5746
5747 fn normalize_postgres_type_function_casts(
5748 expr: Expression,
5749 target: DialectType,
5750 ) -> Result<Expression> {
5751 transform_recursive(expr, &|e| match e {
5752 Expression::Function(function) => {
5753 let mut function = *function;
5754 if function.args.len() == 1
5755 && !function.distinct
5756 && !function.quoted
5757 && !function.use_bracket_syntax
5758 && !function.name.contains('.')
5759 {
5760 if let Some(to) = Self::postgres_type_function_data_type(&function.name) {
5761 let this = function.args.remove(0);
5762 let cast = Cast {
5763 this,
5764 to,
5765 trailing_comments: function.trailing_comments,
5766 double_colon_syntax: false,
5767 format: None,
5768 default: None,
5769 inferred_type: function.inferred_type,
5770 };
5771 return Ok(
5772 if matches!(target, DialectType::TSQL | DialectType::Fabric) {
5773 normalization::rewrite_postgres_float_to_integer_cast(cast)
5774 } else {
5775 Expression::Cast(Box::new(cast))
5776 },
5777 );
5778 }
5779 }
5780 Ok(Expression::Function(Box::new(function)))
5781 }
5782 _ => Ok(e),
5783 })
5784 }
5785
5786 fn node_is_postgres_type_function_cast(expr: &Expression) -> bool {
5787 matches!(
5788 expr,
5789 Expression::Function(function)
5790 if !function.quoted
5791 && !function.use_bracket_syntax
5792 && !function.name.contains('.')
5793 && Self::postgres_type_function_data_type(&function.name).is_some()
5794 )
5795 }
5796
5797 fn postgres_type_function_data_type(name: &str) -> Option<DataType> {
5798 match name.to_ascii_uppercase().as_str() {
5799 "NUMERIC" | "DECIMAL" | "DEC" => Some(DataType::Decimal {
5800 precision: None,
5801 scale: None,
5802 }),
5803 "INT2" | "SMALLINT" => Some(DataType::SmallInt { length: None }),
5804 "INT4" | "INT" => Some(DataType::Int {
5805 length: None,
5806 integer_spelling: false,
5807 }),
5808 "INTEGER" => Some(DataType::Int {
5809 length: None,
5810 integer_spelling: true,
5811 }),
5812 "INT8" | "BIGINT" => Some(DataType::BigInt { length: None }),
5813 "FLOAT4" | "REAL" => Some(DataType::Float {
5814 precision: None,
5815 scale: None,
5816 real_spelling: true,
5817 }),
5818 "FLOAT8" => Some(DataType::Double {
5819 precision: None,
5820 scale: None,
5821 }),
5822 "BOOL" | "BOOLEAN" => Some(DataType::Boolean),
5823 "TEXT" => Some(DataType::Text),
5824 "VARCHAR" => Some(DataType::VarChar {
5825 length: None,
5826 parenthesized_length: false,
5827 }),
5828 "UUID" => Some(DataType::Uuid),
5829 _ => None,
5830 }
5831 }
5832
5833 fn rewrite_boolean_values_for_tsql(expr: Expression) -> Result<Expression> {
5834 match expr {
5835 Expression::Select(select) => Self::rewrite_boolean_values_in_tsql_select(select),
5836 Expression::Subquery(mut subquery) => {
5837 subquery.this = Self::rewrite_boolean_values_for_tsql(subquery.this)?;
5838 Ok(Expression::Subquery(subquery))
5839 }
5840 Expression::Union(mut union) => {
5841 let left = std::mem::replace(&mut union.left, Expression::null());
5842 let right = std::mem::replace(&mut union.right, Expression::null());
5843 union.left = Self::rewrite_boolean_values_for_tsql(left)?;
5844 union.right = Self::rewrite_boolean_values_for_tsql(right)?;
5845 if let Some(mut with) = union.with.take() {
5846 with.ctes = with
5847 .ctes
5848 .into_iter()
5849 .map(|mut cte| {
5850 cte.this = Self::rewrite_boolean_values_for_tsql(cte.this)?;
5851 Ok(cte)
5852 })
5853 .collect::<Result<Vec<_>>>()?;
5854 union.with = Some(with);
5855 }
5856 Ok(Expression::Union(union))
5857 }
5858 Expression::Intersect(mut intersect) => {
5859 let left = std::mem::replace(&mut intersect.left, Expression::null());
5860 let right = std::mem::replace(&mut intersect.right, Expression::null());
5861 intersect.left = Self::rewrite_boolean_values_for_tsql(left)?;
5862 intersect.right = Self::rewrite_boolean_values_for_tsql(right)?;
5863 Ok(Expression::Intersect(intersect))
5864 }
5865 Expression::Except(mut except) => {
5866 let left = std::mem::replace(&mut except.left, Expression::null());
5867 let right = std::mem::replace(&mut except.right, Expression::null());
5868 except.left = Self::rewrite_boolean_values_for_tsql(left)?;
5869 except.right = Self::rewrite_boolean_values_for_tsql(right)?;
5870 Ok(Expression::Except(except))
5871 }
5872 other => Self::rewrite_tsql_boolean_embedded_queries(other),
5873 }
5874 }
5875
5876 fn rewrite_postgres_format_for_tsql(
5877 expr: Expression,
5878 target: DialectType,
5879 ) -> Result<Expression> {
5880 transform_recursive(expr, &|e| match e {
5881 Expression::Function(f) if f.name.eq_ignore_ascii_case("FORMAT") => {
5882 Self::postgres_format_function_to_tsql(*f, target)
5883 }
5884 other => Ok(other),
5885 })
5886 }
5887
5888 fn postgres_format_function_to_tsql(f: Function, target: DialectType) -> Result<Expression> {
5889 let Some(format_expr) = f.args.first() else {
5890 return Err(Self::unsupported_postgres_format_for_tsql(
5891 target,
5892 "missing format string",
5893 ));
5894 };
5895
5896 let format = match format_expr {
5897 Expression::Literal(lit) if lit.is_string() => lit.value_str(),
5898 _ => {
5899 return Err(Self::unsupported_postgres_format_for_tsql(
5900 target,
5901 "dynamic format strings",
5902 ))
5903 }
5904 };
5905
5906 let value_args = &f.args[1..];
5907 let mut arg_index = 0usize;
5908 let mut literal = String::new();
5909 let mut segments = Vec::new();
5910 let mut chars = format.chars();
5911
5912 while let Some(ch) = chars.next() {
5913 if ch != '%' {
5914 literal.push(ch);
5915 continue;
5916 }
5917
5918 let Some(specifier) = chars.next() else {
5919 return Err(Self::unsupported_postgres_format_for_tsql(
5920 target,
5921 "unterminated format specifier",
5922 ));
5923 };
5924
5925 match specifier {
5926 '%' => literal.push('%'),
5927 's' => {
5928 if !literal.is_empty() {
5929 segments.push(Expression::string(std::mem::take(&mut literal)));
5930 }
5931 let Some(arg) = value_args.get(arg_index) else {
5932 return Err(Self::unsupported_postgres_format_for_tsql(
5933 target,
5934 "not enough arguments",
5935 ));
5936 };
5937 segments.push(arg.clone());
5938 arg_index += 1;
5939 }
5940 other => {
5941 return Err(Self::unsupported_postgres_format_for_tsql(
5942 target,
5943 format!("unsupported format specifier %{other}"),
5944 ))
5945 }
5946 }
5947 }
5948
5949 if !literal.is_empty() {
5950 segments.push(Expression::string(literal));
5951 }
5952
5953 if arg_index != value_args.len() {
5954 return Err(Self::unsupported_postgres_format_for_tsql(
5955 target,
5956 "unused format arguments",
5957 ));
5958 }
5959
5960 Ok(Self::postgres_format_segments_to_tsql_concat(segments))
5961 }
5962
5963 fn postgres_format_segments_to_tsql_concat(mut segments: Vec<Expression>) -> Expression {
5964 if segments.is_empty() {
5965 return Expression::string("");
5966 }
5967
5968 if segments.len() == 1 {
5969 let only = segments.pop().expect("one segment");
5970 if matches!(&only, Expression::Literal(lit) if lit.is_string()) {
5971 return only;
5972 }
5973
5974 return Expression::Function(Box::new(Function::new(
5975 "CONCAT".to_string(),
5976 vec![only, Expression::string("")],
5977 )));
5978 }
5979
5980 Expression::Function(Box::new(Function::new("CONCAT".to_string(), segments)))
5981 }
5982
5983 fn unsupported_postgres_format_for_tsql(
5984 target: DialectType,
5985 reason: impl Into<String>,
5986 ) -> crate::error::Error {
5987 crate::error::Error::unsupported(
5988 format!("PostgreSQL format() ({})", reason.into()),
5989 target.to_string(),
5990 )
5991 }
5992
5993 fn rewrite_boolean_values_in_tsql_select(
5994 mut select: Box<crate::expressions::Select>,
5995 ) -> Result<Expression> {
5996 if let Some(mut with) = select.with.take() {
5997 with.ctes = with
5998 .ctes
5999 .into_iter()
6000 .map(|mut cte| {
6001 cte.this = Self::rewrite_boolean_values_for_tsql(cte.this)?;
6002 Ok(cte)
6003 })
6004 .collect::<Result<Vec<_>>>()?;
6005 select.with = Some(with);
6006 }
6007
6008 select.expressions = select
6009 .expressions
6010 .into_iter()
6011 .map(Self::rewrite_tsql_boolean_scalar_value)
6012 .collect::<Result<Vec<_>>>()?;
6013
6014 if let Some(mut from) = select.from.take() {
6015 from.expressions = from
6016 .expressions
6017 .into_iter()
6018 .map(Self::rewrite_tsql_boolean_embedded_queries)
6019 .collect::<Result<Vec<_>>>()?;
6020 select.from = Some(from);
6021 }
6022
6023 select.joins = select
6024 .joins
6025 .into_iter()
6026 .map(|mut join| {
6027 join.this = Self::rewrite_tsql_boolean_embedded_queries(join.this)?;
6028 if let Some(on) = join.on.take() {
6029 join.on = Some(Self::rewrite_tsql_boolean_predicate_context(on)?);
6030 }
6031 if let Some(match_condition) = join.match_condition.take() {
6032 join.match_condition = Some(Self::rewrite_tsql_boolean_predicate_context(
6033 match_condition,
6034 )?);
6035 }
6036 join.pivots = join
6037 .pivots
6038 .into_iter()
6039 .map(Self::rewrite_tsql_boolean_embedded_queries)
6040 .collect::<Result<Vec<_>>>()?;
6041 Ok(join)
6042 })
6043 .collect::<Result<Vec<_>>>()?;
6044
6045 select.lateral_views = select
6046 .lateral_views
6047 .into_iter()
6048 .map(|mut lateral_view| {
6049 lateral_view.this = Self::rewrite_tsql_boolean_embedded_queries(lateral_view.this)?;
6050 Ok(lateral_view)
6051 })
6052 .collect::<Result<Vec<_>>>()?;
6053
6054 if let Some(prewhere) = select.prewhere.take() {
6055 select.prewhere = Some(Self::rewrite_tsql_boolean_predicate_context(prewhere)?);
6056 }
6057
6058 if let Some(mut where_clause) = select.where_clause.take() {
6059 where_clause.this = Self::rewrite_tsql_boolean_predicate_context(where_clause.this)?;
6060 select.where_clause = Some(where_clause);
6061 }
6062
6063 if let Some(mut group_by) = select.group_by.take() {
6064 group_by.expressions = group_by
6065 .expressions
6066 .into_iter()
6067 .map(Self::rewrite_tsql_boolean_scalar_value)
6068 .collect::<Result<Vec<_>>>()?;
6069 select.group_by = Some(group_by);
6070 }
6071
6072 if let Some(mut having) = select.having.take() {
6073 having.this = Self::rewrite_tsql_boolean_predicate_context(having.this)?;
6074 select.having = Some(having);
6075 }
6076
6077 if let Some(mut qualify) = select.qualify.take() {
6078 qualify.this = Self::rewrite_tsql_boolean_predicate_context(qualify.this)?;
6079 select.qualify = Some(qualify);
6080 }
6081
6082 if let Some(mut order_by) = select.order_by.take() {
6083 order_by.expressions = Self::rewrite_tsql_boolean_ordered_values(order_by.expressions)?;
6084 select.order_by = Some(order_by);
6085 }
6086
6087 if let Some(mut distribute_by) = select.distribute_by.take() {
6088 distribute_by.expressions = distribute_by
6089 .expressions
6090 .into_iter()
6091 .map(Self::rewrite_tsql_boolean_scalar_value)
6092 .collect::<Result<Vec<_>>>()?;
6093 select.distribute_by = Some(distribute_by);
6094 }
6095
6096 if let Some(mut cluster_by) = select.cluster_by.take() {
6097 cluster_by.expressions =
6098 Self::rewrite_tsql_boolean_ordered_values(cluster_by.expressions)?;
6099 select.cluster_by = Some(cluster_by);
6100 }
6101
6102 if let Some(mut sort_by) = select.sort_by.take() {
6103 sort_by.expressions = Self::rewrite_tsql_boolean_ordered_values(sort_by.expressions)?;
6104 select.sort_by = Some(sort_by);
6105 }
6106
6107 if let Some(limit_by) = select.limit_by.take() {
6108 select.limit_by = Some(
6109 limit_by
6110 .into_iter()
6111 .map(Self::rewrite_tsql_boolean_scalar_value)
6112 .collect::<Result<Vec<_>>>()?,
6113 );
6114 }
6115
6116 if let Some(distinct_on) = select.distinct_on.take() {
6117 select.distinct_on = Some(
6118 distinct_on
6119 .into_iter()
6120 .map(Self::rewrite_tsql_boolean_scalar_value)
6121 .collect::<Result<Vec<_>>>()?,
6122 );
6123 }
6124
6125 if let Some(mut sample) = select.sample.take() {
6126 sample.size = Self::rewrite_tsql_boolean_embedded_queries(sample.size)?;
6127 if let Some(offset) = sample.offset.take() {
6128 sample.offset = Some(Self::rewrite_tsql_boolean_embedded_queries(offset)?);
6129 }
6130 if let Some(bucket_numerator) = sample.bucket_numerator.take() {
6131 sample.bucket_numerator = Some(Box::new(
6132 Self::rewrite_tsql_boolean_embedded_queries(*bucket_numerator)?,
6133 ));
6134 }
6135 if let Some(bucket_denominator) = sample.bucket_denominator.take() {
6136 sample.bucket_denominator = Some(Box::new(
6137 Self::rewrite_tsql_boolean_embedded_queries(*bucket_denominator)?,
6138 ));
6139 }
6140 if let Some(bucket_field) = sample.bucket_field.take() {
6141 sample.bucket_field = Some(Box::new(Self::rewrite_tsql_boolean_embedded_queries(
6142 *bucket_field,
6143 )?));
6144 }
6145 select.sample = Some(sample);
6146 }
6147
6148 if let Some(settings) = select.settings.take() {
6149 select.settings = Some(
6150 settings
6151 .into_iter()
6152 .map(Self::rewrite_tsql_boolean_embedded_queries)
6153 .collect::<Result<Vec<_>>>()?,
6154 );
6155 }
6156
6157 if let Some(format) = select.format.take() {
6158 select.format = Some(Self::rewrite_tsql_boolean_embedded_queries(format)?);
6159 }
6160
6161 if let Some(mut windows) = select.windows.take() {
6162 for window in windows.iter_mut() {
6163 Self::rewrite_tsql_boolean_over_values(&mut window.spec)?;
6164 }
6165 select.windows = Some(windows);
6166 }
6167
6168 Ok(Expression::Select(select))
6169 }
6170
6171 fn normalize_postgres_boolean_semantics_for_tsql(expr: Expression) -> Result<Expression> {
6172 transform_recursive(expr, &|e| match e {
6173 Expression::Function(function)
6174 if function.args.len() == 2
6175 && (function.name.eq_ignore_ascii_case("BOOLEQ")
6176 || function.name.eq_ignore_ascii_case("BOOLNE")) =>
6177 {
6178 let is_equal = function.name.eq_ignore_ascii_case("BOOLEQ");
6179 let mut args = function.args.into_iter();
6180 let op = BinaryOp {
6181 left: args.next().expect("checked boolean operator arity"),
6182 right: args.next().expect("checked boolean operator arity"),
6183 left_comments: Vec::new(),
6184 operator_comments: Vec::new(),
6185 trailing_comments: function.trailing_comments,
6186 inferred_type: None,
6187 };
6188 if is_equal {
6189 Ok(Expression::Eq(Box::new(op)))
6190 } else {
6191 Ok(Expression::Neq(Box::new(op)))
6192 }
6193 }
6194 Expression::Cast(cast)
6195 if matches!(cast.to, DataType::Text)
6196 && Self::is_known_postgres_boolean_expression(&cast.this) =>
6197 {
6198 Ok(Self::postgres_boolean_text_value(cast.this))
6199 }
6200 other => Ok(other),
6201 })
6202 }
6203
6204 fn is_known_postgres_boolean_expression(expr: &Expression) -> bool {
6205 match expr {
6206 Expression::Boolean(_) => true,
6207 Expression::Cast(cast) => matches!(cast.to, DataType::Boolean),
6208 Expression::Paren(paren) => Self::is_known_postgres_boolean_expression(&paren.this),
6209 other => Self::is_tsql_boolean_value_expression(other),
6210 }
6211 }
6212
6213 fn postgres_boolean_text_value(predicate: Expression) -> Expression {
6214 if let Expression::Boolean(boolean) = predicate {
6215 return Expression::string(if boolean.value { "true" } else { "false" });
6216 }
6217
6218 let false_predicate = Expression::Not(Box::new(crate::expressions::UnaryOp {
6219 this: predicate.clone(),
6220 inferred_type: None,
6221 }));
6222 Expression::Case(Box::new(crate::expressions::Case {
6223 operand: None,
6224 whens: vec![
6225 (predicate, Expression::string("true")),
6226 (false_predicate, Expression::string("false")),
6227 ],
6228 else_: Some(Expression::null()),
6229 comments: Vec::new(),
6230 inferred_type: None,
6231 }))
6232 }
6233
6234 fn rewrite_tsql_boolean_scalar_value(expr: Expression) -> Result<Expression> {
6235 if let Expression::Boolean(boolean) = expr {
6236 return Ok(Expression::Cast(Box::new(Cast {
6237 this: Expression::Boolean(boolean),
6238 to: DataType::Boolean,
6239 trailing_comments: Vec::new(),
6240 double_colon_syntax: false,
6241 format: None,
6242 default: None,
6243 inferred_type: None,
6244 })));
6245 }
6246
6247 if Self::is_tsql_boolean_value_expression(&expr) {
6248 let predicate = Self::rewrite_tsql_boolean_predicate_context(expr)?;
6249 return Ok(Self::tsql_boolean_value_case(predicate));
6250 }
6251
6252 match expr {
6253 Expression::Alias(mut alias) => {
6254 alias.this = Self::rewrite_tsql_boolean_scalar_value(alias.this)?;
6255 Ok(Expression::Alias(alias))
6256 }
6257 Expression::Paren(mut paren) => {
6258 paren.this = Self::rewrite_tsql_boolean_scalar_value(paren.this)?;
6259 Ok(Expression::Paren(paren))
6260 }
6261 Expression::Cast(mut cast) => {
6262 cast.this = Self::rewrite_tsql_boolean_scalar_value(cast.this)?;
6263 if let Some(format) = cast.format.take() {
6264 cast.format = Some(Box::new(Self::rewrite_tsql_boolean_embedded_queries(
6265 *format,
6266 )?));
6267 }
6268 if let Some(default) = cast.default.take() {
6269 cast.default =
6270 Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*default)?));
6271 }
6272 Ok(Expression::Cast(cast))
6273 }
6274 Expression::TryCast(mut cast) => {
6275 cast.this = Self::rewrite_tsql_boolean_scalar_value(cast.this)?;
6276 if let Some(format) = cast.format.take() {
6277 cast.format = Some(Box::new(Self::rewrite_tsql_boolean_embedded_queries(
6278 *format,
6279 )?));
6280 }
6281 if let Some(default) = cast.default.take() {
6282 cast.default =
6283 Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*default)?));
6284 }
6285 Ok(Expression::TryCast(cast))
6286 }
6287 Expression::SafeCast(mut cast) => {
6288 cast.this = Self::rewrite_tsql_boolean_scalar_value(cast.this)?;
6289 if let Some(format) = cast.format.take() {
6290 cast.format = Some(Box::new(Self::rewrite_tsql_boolean_embedded_queries(
6291 *format,
6292 )?));
6293 }
6294 if let Some(default) = cast.default.take() {
6295 cast.default =
6296 Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*default)?));
6297 }
6298 Ok(Expression::SafeCast(cast))
6299 }
6300 Expression::Case(mut case) => {
6301 let is_simple_case = case.operand.is_some();
6302 if let Some(operand) = case.operand.take() {
6303 case.operand = Some(Self::rewrite_tsql_boolean_scalar_value(operand)?);
6304 }
6305 case.whens = case
6306 .whens
6307 .into_iter()
6308 .map(|(condition, result)| {
6309 let condition = if is_simple_case {
6310 Self::rewrite_tsql_boolean_scalar_value(condition)?
6311 } else {
6312 Self::rewrite_tsql_boolean_predicate_context(condition)?
6313 };
6314 Ok((condition, Self::rewrite_tsql_boolean_scalar_value(result)?))
6315 })
6316 .collect::<Result<Vec<_>>>()?;
6317 if let Some(else_) = case.else_.take() {
6318 case.else_ = Some(Self::rewrite_tsql_boolean_scalar_value(else_)?);
6319 }
6320 Ok(Expression::Case(case))
6321 }
6322 Expression::IfFunc(mut if_func) => {
6323 if_func.condition =
6324 Self::rewrite_tsql_boolean_predicate_context(if_func.condition)?;
6325 if_func.true_value = Self::rewrite_tsql_boolean_scalar_value(if_func.true_value)?;
6326 if let Some(false_value) = if_func.false_value.take() {
6327 if_func.false_value =
6328 Some(Self::rewrite_tsql_boolean_scalar_value(false_value)?);
6329 }
6330 Ok(Expression::IfFunc(if_func))
6331 }
6332 Expression::WindowFunction(mut window_function) => {
6333 window_function.this =
6334 Self::rewrite_tsql_boolean_embedded_queries(window_function.this)?;
6335 Self::rewrite_tsql_boolean_over_values(&mut window_function.over)?;
6336 if let Some(mut keep) = window_function.keep.take() {
6337 keep.order_by = Self::rewrite_tsql_boolean_ordered_values(keep.order_by)?;
6338 window_function.keep = Some(keep);
6339 }
6340 Ok(Expression::WindowFunction(window_function))
6341 }
6342 Expression::WithinGroup(mut within_group) => {
6343 within_group.this = Self::rewrite_tsql_boolean_embedded_queries(within_group.this)?;
6344 within_group.order_by =
6345 Self::rewrite_tsql_boolean_ordered_values(within_group.order_by)?;
6346 Ok(Expression::WithinGroup(within_group))
6347 }
6348 Expression::Subquery(mut subquery) => {
6349 subquery.this = Self::rewrite_boolean_values_for_tsql(subquery.this)?;
6350 Ok(Expression::Subquery(subquery))
6351 }
6352 Expression::Select(select) => Self::rewrite_boolean_values_in_tsql_select(select),
6353 other => Self::rewrite_tsql_boolean_embedded_queries(other),
6354 }
6355 }
6356
6357 fn rewrite_tsql_boolean_predicate_context(expr: Expression) -> Result<Expression> {
6358 let expr = Self::rewrite_tsql_boolean_embedded_queries(expr)?;
6359 Ok(crate::transforms::ensure_bool_condition(expr))
6360 }
6361
6362 fn rewrite_tsql_boolean_embedded_queries(expr: Expression) -> Result<Expression> {
6363 transform_recursive(expr, &|e| match e {
6364 Expression::Select(select) => Self::rewrite_boolean_values_in_tsql_select(select),
6365 Expression::Subquery(mut subquery) => {
6366 subquery.this = Self::rewrite_boolean_values_for_tsql(subquery.this)?;
6367 Ok(Expression::Subquery(subquery))
6368 }
6369 Expression::Union(_) | Expression::Intersect(_) | Expression::Except(_) => {
6370 Self::rewrite_boolean_values_for_tsql(e)
6371 }
6372 other => Ok(other),
6373 })
6374 }
6375
6376 fn rewrite_tsql_boolean_ordered_values(
6377 ordered: Vec<crate::expressions::Ordered>,
6378 ) -> Result<Vec<crate::expressions::Ordered>> {
6379 ordered
6380 .into_iter()
6381 .map(|mut ordered| {
6382 ordered.this = Self::rewrite_tsql_boolean_scalar_value(ordered.this)?;
6383 if let Some(with_fill) = ordered.with_fill.take() {
6384 ordered.with_fill = Some(Box::new(
6385 Self::rewrite_tsql_boolean_with_fill_values(*with_fill)?,
6386 ));
6387 }
6388 Ok(ordered)
6389 })
6390 .collect()
6391 }
6392
6393 fn rewrite_tsql_boolean_with_fill_values(
6394 mut with_fill: crate::expressions::WithFill,
6395 ) -> Result<crate::expressions::WithFill> {
6396 if let Some(from) = with_fill.from_.take() {
6397 with_fill.from_ = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*from)?));
6398 }
6399 if let Some(to) = with_fill.to.take() {
6400 with_fill.to = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*to)?));
6401 }
6402 if let Some(step) = with_fill.step.take() {
6403 with_fill.step = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(*step)?));
6404 }
6405 if let Some(staleness) = with_fill.staleness.take() {
6406 with_fill.staleness = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(
6407 *staleness,
6408 )?));
6409 }
6410 if let Some(interpolate) = with_fill.interpolate.take() {
6411 with_fill.interpolate = Some(Box::new(Self::rewrite_tsql_boolean_scalar_value(
6412 *interpolate,
6413 )?));
6414 }
6415 Ok(with_fill)
6416 }
6417
6418 fn rewrite_tsql_boolean_over_values(over: &mut crate::expressions::Over) -> Result<()> {
6419 over.partition_by = std::mem::take(&mut over.partition_by)
6420 .into_iter()
6421 .map(Self::rewrite_tsql_boolean_scalar_value)
6422 .collect::<Result<Vec<_>>>()?;
6423 over.order_by =
6424 Self::rewrite_tsql_boolean_ordered_values(std::mem::take(&mut over.order_by))?;
6425 Ok(())
6426 }
6427
6428 fn is_tsql_boolean_value_expression(expr: &Expression) -> bool {
6429 match expr {
6430 Expression::Paren(paren) => Self::is_tsql_boolean_value_expression(&paren.this),
6431 Expression::Eq(_)
6432 | Expression::Neq(_)
6433 | Expression::Lt(_)
6434 | Expression::Lte(_)
6435 | Expression::Gt(_)
6436 | Expression::Gte(_)
6437 | Expression::Is(_)
6438 | Expression::IsNull(_)
6439 | Expression::IsTrue(_)
6440 | Expression::IsFalse(_)
6441 | Expression::Like(_)
6442 | Expression::ILike(_)
6443 | Expression::StartsWith(_)
6444 | Expression::SimilarTo(_)
6445 | Expression::Glob(_)
6446 | Expression::RegexpLike(_)
6447 | Expression::In(_)
6448 | Expression::Between(_)
6449 | Expression::Exists(_)
6450 | Expression::And(_)
6451 | Expression::Or(_)
6452 | Expression::Not(_)
6453 | Expression::Any(_)
6454 | Expression::All(_)
6455 | Expression::NullSafeEq(_)
6456 | Expression::NullSafeNeq(_)
6457 | Expression::EqualNull(_) => true,
6458 _ => false,
6459 }
6460 }
6461
6462 fn tsql_boolean_value_case(predicate: Expression) -> Expression {
6463 let case = Expression::Case(Box::new(crate::expressions::Case {
6464 operand: None,
6465 whens: vec![(predicate, Expression::number(1))],
6466 else_: Some(Expression::number(0)),
6467 comments: Vec::new(),
6468 inferred_type: None,
6469 }));
6470
6471 Expression::Cast(Box::new(Cast {
6472 this: case,
6473 to: DataType::Boolean,
6474 trailing_comments: Vec::new(),
6475 double_colon_syntax: false,
6476 format: None,
6477 default: None,
6478 inferred_type: None,
6479 }))
6480 }
6481
6482 fn rewrite_aggregate_filters_for_tsql(expr: Expression) -> Result<Expression> {
6483 transform_recursive(expr, &|e| Self::rewrite_aggregate_filter_for_tsql(e))
6484 }
6485
6486 fn rewrite_aggregate_filter_for_tsql(expr: Expression) -> Result<Expression> {
6487 macro_rules! rewrite_agg_filter {
6488 ($variant:ident, $agg:expr) => {{
6489 let mut agg = $agg;
6490 if let Some(filter) = agg.filter.take() {
6491 let this = std::mem::replace(&mut agg.this, Expression::null());
6492 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6493 }
6494 Ok(Expression::$variant(agg))
6495 }};
6496 }
6497
6498 match expr {
6499 Expression::Filter(filter) => {
6500 let condition = match *filter.expression {
6501 Expression::Where(where_) => where_.this,
6502 other => other,
6503 };
6504 Ok(Self::push_filter_into_tsql_aggregate(
6505 *filter.this,
6506 condition,
6507 ))
6508 }
6509 Expression::AggregateFunction(mut agg) => {
6510 if let Some(filter) = agg.filter.take() {
6511 Self::rewrite_generic_aggregate_filter_for_tsql(&mut agg, filter);
6512 }
6513 Ok(Expression::AggregateFunction(agg))
6514 }
6515 Expression::Count(mut count) => {
6516 if let Some(filter) = count.filter.take() {
6517 let value = if count.star {
6518 Expression::number(1)
6519 } else {
6520 count.this.take().unwrap_or_else(|| Expression::number(1))
6521 };
6522 count.star = false;
6523 count.this = Some(Self::conditional_aggregate_value_for_tsql(filter, value));
6524 }
6525 Ok(Expression::Count(count))
6526 }
6527 Expression::Sum(agg) => rewrite_agg_filter!(Sum, agg),
6528 Expression::Avg(agg) => rewrite_agg_filter!(Avg, agg),
6529 Expression::Min(agg) => rewrite_agg_filter!(Min, agg),
6530 Expression::Max(agg) => rewrite_agg_filter!(Max, agg),
6531 Expression::ArrayAgg(agg) => rewrite_agg_filter!(ArrayAgg, agg),
6532 Expression::CountIf(agg) => Ok(Expression::CountIf(agg)),
6533 Expression::Stddev(agg) => rewrite_agg_filter!(Stddev, agg),
6534 Expression::StddevPop(agg) => rewrite_agg_filter!(StddevPop, agg),
6535 Expression::StddevSamp(agg) => rewrite_agg_filter!(StddevSamp, agg),
6536 Expression::Variance(agg) => rewrite_agg_filter!(Variance, agg),
6537 Expression::VarPop(agg) => rewrite_agg_filter!(VarPop, agg),
6538 Expression::VarSamp(agg) => rewrite_agg_filter!(VarSamp, agg),
6539 Expression::Median(agg) => rewrite_agg_filter!(Median, agg),
6540 Expression::Mode(agg) => rewrite_agg_filter!(Mode, agg),
6541 Expression::First(agg) => rewrite_agg_filter!(First, agg),
6542 Expression::Last(agg) => rewrite_agg_filter!(Last, agg),
6543 Expression::AnyValue(agg) => rewrite_agg_filter!(AnyValue, agg),
6544 Expression::ApproxDistinct(agg) => rewrite_agg_filter!(ApproxDistinct, agg),
6545 Expression::ApproxCountDistinct(agg) => {
6546 rewrite_agg_filter!(ApproxCountDistinct, agg)
6547 }
6548 Expression::LogicalAnd(agg) => rewrite_agg_filter!(LogicalAnd, agg),
6549 Expression::LogicalOr(agg) => rewrite_agg_filter!(LogicalOr, agg),
6550 Expression::Skewness(agg) => rewrite_agg_filter!(Skewness, agg),
6551 Expression::ArrayConcatAgg(agg) => rewrite_agg_filter!(ArrayConcatAgg, agg),
6552 Expression::ArrayUniqueAgg(agg) => rewrite_agg_filter!(ArrayUniqueAgg, agg),
6553 Expression::BoolXorAgg(agg) => rewrite_agg_filter!(BoolXorAgg, agg),
6554 Expression::BitwiseAndAgg(agg) => rewrite_agg_filter!(BitwiseAndAgg, agg),
6555 Expression::BitwiseOrAgg(agg) => rewrite_agg_filter!(BitwiseOrAgg, agg),
6556 Expression::BitwiseXorAgg(agg) => rewrite_agg_filter!(BitwiseXorAgg, agg),
6557 Expression::StringAgg(mut agg) => {
6558 if let Some(filter) = agg.filter.take() {
6559 let this = std::mem::replace(&mut agg.this, Expression::null());
6560 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6561 }
6562 Ok(Expression::StringAgg(agg))
6563 }
6564 Expression::GroupConcat(mut agg) => {
6565 if let Some(filter) = agg.filter.take() {
6566 let this = std::mem::replace(&mut agg.this, Expression::null());
6567 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6568 }
6569 Ok(Expression::GroupConcat(agg))
6570 }
6571 Expression::ListAgg(mut agg) => {
6572 if let Some(filter) = agg.filter.take() {
6573 let this = std::mem::replace(&mut agg.this, Expression::null());
6574 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6575 }
6576 Ok(Expression::ListAgg(agg))
6577 }
6578 Expression::WithinGroup(mut within_group) => {
6579 within_group.this = Self::rewrite_aggregate_filters_for_tsql(within_group.this)?;
6580 Ok(Expression::WithinGroup(within_group))
6581 }
6582 other => Ok(other),
6583 }
6584 }
6585
6586 fn push_filter_into_tsql_aggregate(expr: Expression, filter: Expression) -> Expression {
6587 macro_rules! push_agg_filter {
6588 ($variant:ident, $agg:expr) => {{
6589 let mut agg = $agg;
6590 let this = std::mem::replace(&mut agg.this, Expression::null());
6591 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6592 agg.filter = None;
6593 Expression::$variant(agg)
6594 }};
6595 }
6596
6597 match expr {
6598 Expression::AggregateFunction(mut agg) => {
6599 Self::rewrite_generic_aggregate_filter_for_tsql(&mut agg, filter);
6600 Expression::AggregateFunction(agg)
6601 }
6602 Expression::Count(mut count) => {
6603 let value = if count.star {
6604 Expression::number(1)
6605 } else {
6606 count.this.take().unwrap_or_else(|| Expression::number(1))
6607 };
6608 count.star = false;
6609 count.filter = None;
6610 count.this = Some(Self::conditional_aggregate_value_for_tsql(filter, value));
6611 Expression::Count(count)
6612 }
6613 Expression::Sum(agg) => push_agg_filter!(Sum, agg),
6614 Expression::Avg(agg) => push_agg_filter!(Avg, agg),
6615 Expression::Min(agg) => push_agg_filter!(Min, agg),
6616 Expression::Max(agg) => push_agg_filter!(Max, agg),
6617 Expression::ArrayAgg(agg) => push_agg_filter!(ArrayAgg, agg),
6618 Expression::CountIf(mut agg) => {
6619 agg.filter = Some(filter);
6620 Expression::CountIf(agg)
6621 }
6622 Expression::Stddev(agg) => push_agg_filter!(Stddev, agg),
6623 Expression::StddevPop(agg) => push_agg_filter!(StddevPop, agg),
6624 Expression::StddevSamp(agg) => push_agg_filter!(StddevSamp, agg),
6625 Expression::Variance(agg) => push_agg_filter!(Variance, agg),
6626 Expression::VarPop(agg) => push_agg_filter!(VarPop, agg),
6627 Expression::VarSamp(agg) => push_agg_filter!(VarSamp, agg),
6628 Expression::Median(agg) => push_agg_filter!(Median, agg),
6629 Expression::Mode(agg) => push_agg_filter!(Mode, agg),
6630 Expression::First(agg) => push_agg_filter!(First, agg),
6631 Expression::Last(agg) => push_agg_filter!(Last, agg),
6632 Expression::AnyValue(agg) => push_agg_filter!(AnyValue, agg),
6633 Expression::ApproxDistinct(agg) => push_agg_filter!(ApproxDistinct, agg),
6634 Expression::ApproxCountDistinct(agg) => {
6635 push_agg_filter!(ApproxCountDistinct, agg)
6636 }
6637 Expression::LogicalAnd(agg) => push_agg_filter!(LogicalAnd, agg),
6638 Expression::LogicalOr(agg) => push_agg_filter!(LogicalOr, agg),
6639 Expression::Skewness(agg) => push_agg_filter!(Skewness, agg),
6640 Expression::ArrayConcatAgg(agg) => push_agg_filter!(ArrayConcatAgg, agg),
6641 Expression::ArrayUniqueAgg(agg) => push_agg_filter!(ArrayUniqueAgg, agg),
6642 Expression::BoolXorAgg(agg) => push_agg_filter!(BoolXorAgg, agg),
6643 Expression::BitwiseAndAgg(agg) => push_agg_filter!(BitwiseAndAgg, agg),
6644 Expression::BitwiseOrAgg(agg) => push_agg_filter!(BitwiseOrAgg, agg),
6645 Expression::BitwiseXorAgg(agg) => push_agg_filter!(BitwiseXorAgg, agg),
6646 Expression::StringAgg(mut agg) => {
6647 let this = std::mem::replace(&mut agg.this, Expression::null());
6648 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6649 agg.filter = None;
6650 Expression::StringAgg(agg)
6651 }
6652 Expression::GroupConcat(mut agg) => {
6653 let this = std::mem::replace(&mut agg.this, Expression::null());
6654 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6655 agg.filter = None;
6656 Expression::GroupConcat(agg)
6657 }
6658 Expression::ListAgg(mut agg) => {
6659 let this = std::mem::replace(&mut agg.this, Expression::null());
6660 agg.this = Self::conditional_aggregate_value_for_tsql(filter, this);
6661 agg.filter = None;
6662 Expression::ListAgg(agg)
6663 }
6664 Expression::WithinGroup(mut within_group) => {
6665 within_group.this =
6666 Self::push_filter_into_tsql_aggregate(within_group.this, filter);
6667 Expression::WithinGroup(within_group)
6668 }
6669 other => Expression::Filter(Box::new(crate::expressions::Filter {
6670 this: Box::new(other),
6671 expression: Box::new(filter),
6672 })),
6673 }
6674 }
6675
6676 fn rewrite_generic_aggregate_filter_for_tsql(
6677 agg: &mut crate::expressions::AggregateFunction,
6678 filter: Expression,
6679 ) {
6680 let is_count =
6681 agg.name.eq_ignore_ascii_case("COUNT") || agg.name.eq_ignore_ascii_case("COUNT_BIG");
6682 let is_count_star = is_count
6683 && (agg.args.is_empty()
6684 || (agg.args.len() == 1 && matches!(agg.args[0], Expression::Star(_))));
6685
6686 if is_count_star {
6687 agg.args = vec![Self::conditional_aggregate_value_for_tsql(
6688 filter,
6689 Expression::number(1),
6690 )];
6691 } else if !agg.args.is_empty() {
6692 agg.args = agg
6693 .args
6694 .drain(..)
6695 .map(|arg| Self::conditional_aggregate_value_for_tsql(filter.clone(), arg))
6696 .collect();
6697 } else {
6698 agg.filter = Some(filter);
6699 }
6700 }
6701
6702 fn conditional_aggregate_value_for_tsql(filter: Expression, value: Expression) -> Expression {
6703 Expression::Case(Box::new(crate::expressions::Case {
6704 operand: None,
6705 whens: vec![(filter, value)],
6706 else_: None,
6707 comments: Vec::new(),
6708 inferred_type: None,
6709 }))
6710 }
6711
6712 fn reject_pgvector_distance_operators_for_sqlite(&self, sql: &str) -> Result<()> {
6713 let tokens = self.tokenize(sql)?;
6714 for (i, token) in tokens.iter().enumerate() {
6715 if token.token_type == TokenType::NullsafeEq {
6716 return Err(crate::error::Error::unsupported(
6717 "PostgreSQL pgvector cosine distance operator <=>",
6718 "SQLite",
6719 ));
6720 }
6721 if token.token_type == TokenType::Lt
6722 && tokens
6723 .get(i + 1)
6724 .is_some_and(|token| token.token_type == TokenType::Tilde)
6725 && tokens
6726 .get(i + 2)
6727 .is_some_and(|token| token.token_type == TokenType::Gt)
6728 {
6729 return Err(crate::error::Error::unsupported(
6730 "PostgreSQL pgvector Hamming distance operator <~>",
6731 "SQLite",
6732 ));
6733 }
6734 }
6735 Ok(())
6736 }
6737
6738 fn normalize_sqlite_double_quoted_defaults(expr: Expression) -> Result<Expression> {
6739 fn normalize_default_expr(expr: Expression) -> Result<Expression> {
6740 transform_recursive(expr, &|e| match e {
6741 Expression::Column(col)
6742 if col.table.is_none() && col.name.quoted && !col.join_mark =>
6743 {
6744 Ok(Expression::Literal(Box::new(Literal::String(
6745 col.name.name,
6746 ))))
6747 }
6748 Expression::Identifier(id) if id.quoted => {
6749 Ok(Expression::Literal(Box::new(Literal::String(id.name))))
6750 }
6751 _ => Ok(e),
6752 })
6753 }
6754
6755 fn normalize_column_default(col: &mut crate::expressions::ColumnDef) -> Result<()> {
6756 if let Some(default) = col.default.take() {
6757 col.default = Some(normalize_default_expr(default)?);
6758 }
6759
6760 for constraint in &mut col.constraints {
6761 if let ColumnConstraint::Default(default) = constraint {
6762 *default = normalize_default_expr(default.clone())?;
6763 }
6764 }
6765
6766 Ok(())
6767 }
6768
6769 transform_recursive(expr, &|e| match e {
6770 Expression::CreateTable(mut ct) => {
6771 for column in &mut ct.columns {
6772 normalize_column_default(column)?;
6773 }
6774 Ok(Expression::CreateTable(ct))
6775 }
6776 Expression::ColumnDef(mut col) => {
6777 normalize_column_default(&mut col)?;
6778 Ok(Expression::ColumnDef(col))
6779 }
6780 _ => Ok(e),
6781 })
6782 }
6783
6784 fn normalize_postgres_to_sqlite_types(expr: Expression) -> Result<Expression> {
6785 fn sqlite_type(dt: crate::expressions::DataType) -> crate::expressions::DataType {
6786 use crate::expressions::DataType;
6787
6788 match dt {
6789 DataType::Bit { .. } => DataType::Int {
6790 length: None,
6791 integer_spelling: true,
6792 },
6793 DataType::TextWithLength { .. } => DataType::Text,
6794 DataType::VarChar { .. } => DataType::Text,
6795 DataType::Char { .. } => DataType::Text,
6796 DataType::Timestamp { timezone: true, .. } => DataType::Text,
6797 DataType::Custom { name } => {
6798 let base = name
6799 .split_once('(')
6800 .map_or(name.as_str(), |(base, _)| base)
6801 .trim();
6802 if base.eq_ignore_ascii_case("TSVECTOR")
6803 || base.eq_ignore_ascii_case("TIMESTAMPTZ")
6804 || base.eq_ignore_ascii_case("TIMESTAMP WITH TIME ZONE")
6805 || base.eq_ignore_ascii_case("NVARCHAR")
6806 || base.eq_ignore_ascii_case("NCHAR")
6807 {
6808 DataType::Text
6809 } else {
6810 DataType::Custom { name }
6811 }
6812 }
6813 _ => dt,
6814 }
6815 }
6816
6817 transform_recursive(expr, &|e| match e {
6818 Expression::DataType(dt) => Ok(Expression::DataType(sqlite_type(dt))),
6819 Expression::CreateTable(mut ct) => {
6820 for column in &mut ct.columns {
6821 column.data_type = sqlite_type(column.data_type.clone());
6822 }
6823 Ok(Expression::CreateTable(ct))
6824 }
6825 _ => Ok(e),
6826 })
6827 }
6828
6829 fn normalize_postgres_to_fabric_types(expr: Expression) -> Result<Expression> {
6830 fn fabric_type(dt: crate::expressions::DataType) -> crate::expressions::DataType {
6831 use crate::expressions::DataType;
6832
6833 match dt {
6834 DataType::Decimal {
6835 precision: None,
6836 scale: None,
6837 } => DataType::Decimal {
6838 precision: Some(38),
6839 scale: Some(10),
6840 },
6841 DataType::Json | DataType::JsonB => DataType::Custom {
6842 name: "VARCHAR(MAX)".to_string(),
6843 },
6844 _ => dt,
6845 }
6846 }
6847
6848 transform_recursive(expr, &|e| match e {
6849 Expression::DataType(dt) => Ok(Expression::DataType(fabric_type(dt))),
6850 Expression::CreateTable(mut ct) => {
6851 for column in &mut ct.columns {
6852 column.data_type = fabric_type(column.data_type.clone());
6853 }
6854 Ok(Expression::CreateTable(ct))
6855 }
6856 Expression::ColumnDef(mut col) => {
6857 col.data_type = fabric_type(col.data_type);
6858 Ok(Expression::ColumnDef(col))
6859 }
6860 _ => Ok(e),
6861 })
6862 }
6863
6864 fn seq_rownum_to_range(expr: Expression) -> Result<Expression> {
6868 if let Expression::Select(mut select) = expr {
6869 let has_range_from = if let Some(ref from) = select.from {
6871 from.expressions.iter().any(|e| {
6872 match e {
6874 Expression::Function(f) => f.name.eq_ignore_ascii_case("RANGE"),
6875 Expression::Alias(a) => {
6876 matches!(&a.this, Expression::Function(f) if f.name.eq_ignore_ascii_case("RANGE"))
6877 }
6878 _ => false,
6879 }
6880 })
6881 } else {
6882 false
6883 };
6884
6885 if has_range_from {
6886 select.expressions = select
6888 .expressions
6889 .into_iter()
6890 .map(|e| Self::replace_rownum_with_range(e))
6891 .collect();
6892 }
6893
6894 Ok(Expression::Select(select))
6895 } else {
6896 Ok(expr)
6897 }
6898 }
6899
6900 fn replace_rownum_with_range(expr: Expression) -> Expression {
6902 match expr {
6903 Expression::Mod(op) => {
6905 let new_left = Self::try_replace_rownum_paren(&op.left);
6906 Expression::Mod(Box::new(crate::expressions::BinaryOp {
6907 left: new_left,
6908 right: op.right,
6909 left_comments: op.left_comments,
6910 operator_comments: op.operator_comments,
6911 trailing_comments: op.trailing_comments,
6912 inferred_type: op.inferred_type,
6913 }))
6914 }
6915 Expression::Paren(p) => {
6917 let inner = Self::replace_rownum_with_range(p.this);
6918 Expression::Paren(Box::new(crate::expressions::Paren {
6919 this: inner,
6920 trailing_comments: p.trailing_comments,
6921 }))
6922 }
6923 Expression::Case(mut c) => {
6924 c.whens = c
6926 .whens
6927 .into_iter()
6928 .map(|(cond, then)| {
6929 (
6930 Self::replace_rownum_with_range(cond),
6931 Self::replace_rownum_with_range(then),
6932 )
6933 })
6934 .collect();
6935 if let Some(else_) = c.else_ {
6936 c.else_ = Some(Self::replace_rownum_with_range(else_));
6937 }
6938 Expression::Case(c)
6939 }
6940 Expression::Gte(op) => Expression::Gte(Box::new(crate::expressions::BinaryOp {
6941 left: Self::replace_rownum_with_range(op.left),
6942 right: op.right,
6943 left_comments: op.left_comments,
6944 operator_comments: op.operator_comments,
6945 trailing_comments: op.trailing_comments,
6946 inferred_type: op.inferred_type,
6947 })),
6948 Expression::Sub(op) => Expression::Sub(Box::new(crate::expressions::BinaryOp {
6949 left: Self::replace_rownum_with_range(op.left),
6950 right: op.right,
6951 left_comments: op.left_comments,
6952 operator_comments: op.operator_comments,
6953 trailing_comments: op.trailing_comments,
6954 inferred_type: op.inferred_type,
6955 })),
6956 Expression::Alias(mut a) => {
6957 a.this = Self::replace_rownum_with_range(a.this);
6958 Expression::Alias(a)
6959 }
6960 other => other,
6961 }
6962 }
6963
6964 fn try_replace_rownum_paren(expr: &Expression) -> Expression {
6966 if let Expression::Paren(ref p) = expr {
6967 if let Expression::Sub(ref sub) = p.this {
6968 if let Expression::WindowFunction(ref wf) = sub.left {
6969 if let Expression::Function(ref f) = wf.this {
6970 if f.name.eq_ignore_ascii_case("ROW_NUMBER") {
6971 if let Expression::Literal(ref lit) = sub.right {
6972 if let crate::expressions::Literal::Number(ref n) = lit.as_ref() {
6973 if n == "1" {
6974 return Expression::column("range");
6975 }
6976 }
6977 }
6978 }
6979 }
6980 }
6981 }
6982 }
6983 expr.clone()
6984 }
6985
6986 fn transform_generate_date_array_snowflake(expr: Expression) -> Result<Expression> {
6993 use crate::expressions::*;
6994 transform_recursive(expr, &|e| {
6995 if let Expression::ArraySize(ref af) = e {
6997 if let Expression::Function(ref f) = af.this {
6998 if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") && f.args.len() >= 2 {
6999 let result = Self::convert_array_size_gda_snowflake(f)?;
7000 return Ok(result);
7001 }
7002 }
7003 }
7004
7005 let Expression::Select(mut sel) = e else {
7006 return Ok(e);
7007 };
7008
7009 let mut gda_info: Option<(String, Expression, Expression, String)> = None; let mut gda_join_idx: Option<usize> = None;
7012
7013 for (idx, join) in sel.joins.iter().enumerate() {
7014 let (unnest_ref, alias_name) = match &join.this {
7018 Expression::Unnest(ref unnest) => {
7019 let alias = unnest.alias.as_ref().map(|id| id.name.clone());
7020 (Some(unnest.as_ref()), alias)
7021 }
7022 Expression::Alias(ref a) => {
7023 if let Expression::Unnest(ref unnest) = a.this {
7024 (Some(unnest.as_ref()), Some(a.alias.name.clone()))
7025 } else {
7026 (None, None)
7027 }
7028 }
7029 _ => (None, None),
7030 };
7031
7032 if let (Some(unnest), Some(alias)) = (unnest_ref, alias_name) {
7033 if let Expression::Function(ref f) = unnest.this {
7035 if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") && f.args.len() >= 2 {
7036 let start_expr = f.args[0].clone();
7037 let end_expr = f.args[1].clone();
7038 let step = f.args.get(2).cloned();
7039
7040 let unit = if let Some(Expression::Interval(ref iv)) = step {
7042 if let Some(IntervalUnitSpec::Simple { ref unit, .. }) = iv.unit {
7043 Some(format!("{:?}", unit).to_ascii_uppercase())
7044 } else if let Some(ref this) = iv.this {
7045 if let Expression::Literal(lit) = this {
7047 if let Literal::String(ref s) = lit.as_ref() {
7048 let parts: Vec<&str> = s.split_whitespace().collect();
7049 if parts.len() == 2 {
7050 Some(parts[1].to_ascii_uppercase())
7051 } else if parts.len() == 1 {
7052 let upper = parts[0].to_ascii_uppercase();
7054 if matches!(
7055 upper.as_str(),
7056 "YEAR"
7057 | "QUARTER"
7058 | "MONTH"
7059 | "WEEK"
7060 | "DAY"
7061 | "HOUR"
7062 | "MINUTE"
7063 | "SECOND"
7064 ) {
7065 Some(upper)
7066 } else {
7067 None
7068 }
7069 } else {
7070 None
7071 }
7072 } else {
7073 None
7074 }
7075 } else {
7076 None
7077 }
7078 } else {
7079 None
7080 }
7081 } else {
7082 None
7083 };
7084
7085 if let Some(unit_str) = unit {
7086 gda_info = Some((alias, start_expr, end_expr, unit_str));
7087 gda_join_idx = Some(idx);
7088 }
7089 }
7090 }
7091 }
7092 if gda_info.is_some() {
7093 break;
7094 }
7095 }
7096
7097 let Some((alias_name, start_expr, end_expr, unit_str)) = gda_info else {
7098 let result = Self::try_transform_from_gda_snowflake(sel);
7101 return result;
7102 };
7103 let join_idx = gda_join_idx.unwrap();
7104
7105 let datediff = Expression::Function(Box::new(Function::new(
7109 "DATEDIFF".to_string(),
7110 vec![
7111 Expression::boxed_column(Column {
7112 name: Identifier::new(&unit_str),
7113 table: None,
7114 join_mark: false,
7115 trailing_comments: vec![],
7116 span: None,
7117 inferred_type: None,
7118 }),
7119 start_expr.clone(),
7120 end_expr.clone(),
7121 ],
7122 )));
7123 let datediff_plus_one = Expression::Add(Box::new(BinaryOp {
7124 left: datediff,
7125 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
7126 left_comments: vec![],
7127 operator_comments: vec![],
7128 trailing_comments: vec![],
7129 inferred_type: None,
7130 }));
7131
7132 let array_gen_range = Expression::Function(Box::new(Function::new(
7133 "ARRAY_GENERATE_RANGE".to_string(),
7134 vec![
7135 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
7136 datediff_plus_one,
7137 ],
7138 )));
7139
7140 let flatten_input = Expression::NamedArgument(Box::new(NamedArgument {
7142 name: Identifier::new("INPUT"),
7143 value: array_gen_range,
7144 separator: crate::expressions::NamedArgSeparator::DArrow,
7145 }));
7146 let flatten = Expression::Function(Box::new(Function::new(
7147 "FLATTEN".to_string(),
7148 vec![flatten_input],
7149 )));
7150
7151 let alias_table = Alias {
7153 this: flatten,
7154 alias: Identifier::new("_t0"),
7155 column_aliases: vec![
7156 Identifier::new("seq"),
7157 Identifier::new("key"),
7158 Identifier::new("path"),
7159 Identifier::new("index"),
7160 Identifier::new(&alias_name),
7161 Identifier::new("this"),
7162 ],
7163 alias_explicit_as: false,
7164 alias_keyword: None,
7165 pre_alias_comments: vec![],
7166 trailing_comments: vec![],
7167 inferred_type: None,
7168 };
7169 let lateral_expr = Expression::Lateral(Box::new(Lateral {
7170 this: Box::new(Expression::Alias(Box::new(alias_table))),
7171 view: None,
7172 outer: None,
7173 alias: None,
7174 alias_quoted: false,
7175 cross_apply: None,
7176 ordinality: None,
7177 column_aliases: vec![],
7178 }));
7179
7180 sel.joins.remove(join_idx);
7182 if let Some(ref mut from) = sel.from {
7183 from.expressions.push(lateral_expr);
7184 }
7185
7186 let dateadd_expr = Expression::Function(Box::new(Function::new(
7188 "DATEADD".to_string(),
7189 vec![
7190 Expression::boxed_column(Column {
7191 name: Identifier::new(&unit_str),
7192 table: None,
7193 join_mark: false,
7194 trailing_comments: vec![],
7195 span: None,
7196 inferred_type: None,
7197 }),
7198 Expression::Cast(Box::new(Cast {
7199 this: Expression::boxed_column(Column {
7200 name: Identifier::new(&alias_name),
7201 table: None,
7202 join_mark: false,
7203 trailing_comments: vec![],
7204 span: None,
7205 inferred_type: None,
7206 }),
7207 to: DataType::Int {
7208 length: None,
7209 integer_spelling: false,
7210 },
7211 trailing_comments: vec![],
7212 double_colon_syntax: false,
7213 format: None,
7214 default: None,
7215 inferred_type: None,
7216 })),
7217 Expression::Cast(Box::new(Cast {
7218 this: start_expr.clone(),
7219 to: DataType::Date,
7220 trailing_comments: vec![],
7221 double_colon_syntax: false,
7222 format: None,
7223 default: None,
7224 inferred_type: None,
7225 })),
7226 ],
7227 )));
7228
7229 let new_exprs: Vec<Expression> = sel
7231 .expressions
7232 .iter()
7233 .map(|expr| Self::replace_column_ref_with_dateadd(expr, &alias_name, &dateadd_expr))
7234 .collect();
7235 sel.expressions = new_exprs;
7236
7237 Ok(Expression::Select(sel))
7238 })
7239 }
7240
7241 fn replace_column_ref_with_dateadd(
7243 expr: &Expression,
7244 alias_name: &str,
7245 dateadd: &Expression,
7246 ) -> Expression {
7247 use crate::expressions::*;
7248 match expr {
7249 Expression::Column(c) if c.name.name == alias_name && c.table.is_none() => {
7250 Expression::Alias(Box::new(Alias {
7252 this: dateadd.clone(),
7253 alias: Identifier::new(alias_name),
7254 column_aliases: vec![],
7255 alias_explicit_as: false,
7256 alias_keyword: None,
7257 pre_alias_comments: vec![],
7258 trailing_comments: vec![],
7259 inferred_type: None,
7260 }))
7261 }
7262 Expression::Alias(a) => {
7263 let new_this = Self::replace_column_ref_inner(&a.this, alias_name, dateadd);
7265 Expression::Alias(Box::new(Alias {
7266 this: new_this,
7267 alias: a.alias.clone(),
7268 column_aliases: a.column_aliases.clone(),
7269 alias_explicit_as: false,
7270 alias_keyword: None,
7271 pre_alias_comments: a.pre_alias_comments.clone(),
7272 trailing_comments: a.trailing_comments.clone(),
7273 inferred_type: None,
7274 }))
7275 }
7276 _ => expr.clone(),
7277 }
7278 }
7279
7280 fn replace_column_ref_inner(
7282 expr: &Expression,
7283 alias_name: &str,
7284 dateadd: &Expression,
7285 ) -> Expression {
7286 use crate::expressions::*;
7287 match expr {
7288 Expression::Column(c) if c.name.name == alias_name && c.table.is_none() => {
7289 dateadd.clone()
7290 }
7291 Expression::Add(op) => {
7292 let left = Self::replace_column_ref_inner(&op.left, alias_name, dateadd);
7293 let right = Self::replace_column_ref_inner(&op.right, alias_name, dateadd);
7294 Expression::Add(Box::new(BinaryOp {
7295 left,
7296 right,
7297 left_comments: op.left_comments.clone(),
7298 operator_comments: op.operator_comments.clone(),
7299 trailing_comments: op.trailing_comments.clone(),
7300 inferred_type: None,
7301 }))
7302 }
7303 Expression::Sub(op) => {
7304 let left = Self::replace_column_ref_inner(&op.left, alias_name, dateadd);
7305 let right = Self::replace_column_ref_inner(&op.right, alias_name, dateadd);
7306 Expression::Sub(Box::new(BinaryOp {
7307 left,
7308 right,
7309 left_comments: op.left_comments.clone(),
7310 operator_comments: op.operator_comments.clone(),
7311 trailing_comments: op.trailing_comments.clone(),
7312 inferred_type: None,
7313 }))
7314 }
7315 Expression::Mul(op) => {
7316 let left = Self::replace_column_ref_inner(&op.left, alias_name, dateadd);
7317 let right = Self::replace_column_ref_inner(&op.right, alias_name, dateadd);
7318 Expression::Mul(Box::new(BinaryOp {
7319 left,
7320 right,
7321 left_comments: op.left_comments.clone(),
7322 operator_comments: op.operator_comments.clone(),
7323 trailing_comments: op.trailing_comments.clone(),
7324 inferred_type: None,
7325 }))
7326 }
7327 _ => expr.clone(),
7328 }
7329 }
7330
7331 fn try_transform_from_gda_snowflake(
7334 mut sel: Box<crate::expressions::Select>,
7335 ) -> Result<Expression> {
7336 use crate::expressions::*;
7337
7338 let mut gda_info: Option<(
7340 usize,
7341 String,
7342 Expression,
7343 Expression,
7344 String,
7345 Option<(String, Vec<Identifier>)>,
7346 )> = None; if let Some(ref from) = sel.from {
7349 for (idx, table_expr) in from.expressions.iter().enumerate() {
7350 let (unnest_opt, outer_alias_info) = match table_expr {
7353 Expression::Unnest(ref unnest) => (Some(unnest.as_ref()), None),
7354 Expression::Alias(ref a) => {
7355 if let Expression::Unnest(ref unnest) = a.this {
7356 let alias_info = (a.alias.name.clone(), a.column_aliases.clone());
7357 (Some(unnest.as_ref()), Some(alias_info))
7358 } else {
7359 (None, None)
7360 }
7361 }
7362 _ => (None, None),
7363 };
7364
7365 if let Some(unnest) = unnest_opt {
7366 let func_opt = match &unnest.this {
7368 Expression::Function(ref f)
7369 if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY")
7370 && f.args.len() >= 2 =>
7371 {
7372 Some(f)
7373 }
7374 _ => None,
7376 };
7377
7378 if let Some(f) = func_opt {
7379 let start_expr = f.args[0].clone();
7380 let end_expr = f.args[1].clone();
7381 let step = f.args.get(2).cloned();
7382
7383 let unit = Self::extract_interval_unit_str(&step);
7385 let col_name = outer_alias_info
7386 .as_ref()
7387 .and_then(|(_, cols)| cols.first().map(|id| id.name.clone()))
7388 .unwrap_or_else(|| "value".to_string());
7389
7390 if let Some(unit_str) = unit {
7391 gda_info = Some((
7392 idx,
7393 col_name,
7394 start_expr,
7395 end_expr,
7396 unit_str,
7397 outer_alias_info,
7398 ));
7399 break;
7400 }
7401 }
7402 }
7403 }
7404 }
7405
7406 let Some((from_idx, col_name, start_expr, end_expr, unit_str, outer_alias_info)) = gda_info
7407 else {
7408 return Ok(Expression::Select(sel));
7409 };
7410
7411 let datediff = Expression::Function(Box::new(Function::new(
7417 "DATEDIFF".to_string(),
7418 vec![
7419 Expression::boxed_column(Column {
7420 name: Identifier::new(&unit_str),
7421 table: None,
7422 join_mark: false,
7423 trailing_comments: vec![],
7424 span: None,
7425 inferred_type: None,
7426 }),
7427 start_expr.clone(),
7428 end_expr.clone(),
7429 ],
7430 )));
7431 let datediff_plus_one = Expression::Add(Box::new(BinaryOp {
7433 left: datediff,
7434 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
7435 left_comments: vec![],
7436 operator_comments: vec![],
7437 trailing_comments: vec![],
7438 inferred_type: None,
7439 }));
7440
7441 let array_gen_range = Expression::Function(Box::new(Function::new(
7442 "ARRAY_GENERATE_RANGE".to_string(),
7443 vec![
7444 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
7445 datediff_plus_one,
7446 ],
7447 )));
7448
7449 let flatten_input = Expression::NamedArgument(Box::new(NamedArgument {
7451 name: Identifier::new("INPUT"),
7452 value: array_gen_range,
7453 separator: crate::expressions::NamedArgSeparator::DArrow,
7454 }));
7455 let flatten = Expression::Function(Box::new(Function::new(
7456 "FLATTEN".to_string(),
7457 vec![flatten_input],
7458 )));
7459
7460 let table_alias_name = outer_alias_info
7462 .as_ref()
7463 .map(|(name, _)| name.clone())
7464 .unwrap_or_else(|| "_t0".to_string());
7465
7466 let table_func =
7468 Expression::Function(Box::new(Function::new("TABLE".to_string(), vec![flatten])));
7469 let flatten_aliased = Expression::Alias(Box::new(Alias {
7470 this: table_func,
7471 alias: Identifier::new(&table_alias_name),
7472 column_aliases: vec![
7473 Identifier::new("seq"),
7474 Identifier::new("key"),
7475 Identifier::new("path"),
7476 Identifier::new("index"),
7477 Identifier::new(&col_name),
7478 Identifier::new("this"),
7479 ],
7480 alias_explicit_as: false,
7481 alias_keyword: None,
7482 pre_alias_comments: vec![],
7483 trailing_comments: vec![],
7484 inferred_type: None,
7485 }));
7486
7487 let dateadd_expr = Expression::Function(Box::new(Function::new(
7489 "DATEADD".to_string(),
7490 vec![
7491 Expression::boxed_column(Column {
7492 name: Identifier::new(&unit_str),
7493 table: None,
7494 join_mark: false,
7495 trailing_comments: vec![],
7496 span: None,
7497 inferred_type: None,
7498 }),
7499 Expression::Cast(Box::new(Cast {
7500 this: Expression::boxed_column(Column {
7501 name: Identifier::new(&col_name),
7502 table: None,
7503 join_mark: false,
7504 trailing_comments: vec![],
7505 span: None,
7506 inferred_type: None,
7507 }),
7508 to: DataType::Int {
7509 length: None,
7510 integer_spelling: false,
7511 },
7512 trailing_comments: vec![],
7513 double_colon_syntax: false,
7514 format: None,
7515 default: None,
7516 inferred_type: None,
7517 })),
7518 start_expr.clone(),
7520 ],
7521 )));
7522 let dateadd_aliased = Expression::Alias(Box::new(Alias {
7523 this: dateadd_expr,
7524 alias: Identifier::new(&col_name),
7525 column_aliases: vec![],
7526 alias_explicit_as: false,
7527 alias_keyword: None,
7528 pre_alias_comments: vec![],
7529 trailing_comments: vec![],
7530 inferred_type: None,
7531 }));
7532
7533 let mut inner_select = Select::new();
7535 inner_select.expressions = vec![dateadd_aliased];
7536 inner_select.from = Some(From {
7537 expressions: vec![flatten_aliased],
7538 });
7539
7540 let inner_select_expr = Expression::Select(Box::new(inner_select));
7541 let subquery = Expression::Subquery(Box::new(Subquery {
7542 this: inner_select_expr,
7543 alias: None,
7544 column_aliases: vec![],
7545 alias_explicit_as: false,
7546 alias_keyword: None,
7547 order_by: None,
7548 limit: None,
7549 offset: None,
7550 distribute_by: None,
7551 sort_by: None,
7552 cluster_by: None,
7553 lateral: false,
7554 modifiers_inside: false,
7555 trailing_comments: vec![],
7556 inferred_type: None,
7557 }));
7558
7559 let replacement = if let Some((alias_name, col_aliases)) = outer_alias_info {
7561 Expression::Alias(Box::new(Alias {
7562 this: subquery,
7563 alias: Identifier::new(&alias_name),
7564 column_aliases: col_aliases,
7565 alias_explicit_as: false,
7566 alias_keyword: None,
7567 pre_alias_comments: vec![],
7568 trailing_comments: vec![],
7569 inferred_type: None,
7570 }))
7571 } else {
7572 subquery
7573 };
7574
7575 if let Some(ref mut from) = sel.from {
7577 from.expressions[from_idx] = replacement;
7578 }
7579
7580 Ok(Expression::Select(sel))
7581 }
7582
7583 fn convert_array_size_gda_snowflake(f: &crate::expressions::Function) -> Result<Expression> {
7587 use crate::expressions::*;
7588
7589 let start_expr = f.args[0].clone();
7590 let end_expr = f.args[1].clone();
7591 let step = f.args.get(2).cloned();
7592 let unit_str = Self::extract_interval_unit_str(&step).unwrap_or_else(|| "DAY".to_string());
7593 let col_name = "value";
7594
7595 let datediff = Expression::Function(Box::new(Function::new(
7597 "DATEDIFF".to_string(),
7598 vec![
7599 Expression::boxed_column(Column {
7600 name: Identifier::new(&unit_str),
7601 table: None,
7602 join_mark: false,
7603 trailing_comments: vec![],
7604 span: None,
7605 inferred_type: None,
7606 }),
7607 start_expr.clone(),
7608 end_expr.clone(),
7609 ],
7610 )));
7611 let datediff_plus_one = Expression::Add(Box::new(BinaryOp {
7613 left: datediff,
7614 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
7615 left_comments: vec![],
7616 operator_comments: vec![],
7617 trailing_comments: vec![],
7618 inferred_type: None,
7619 }));
7620
7621 let array_gen_range = Expression::Function(Box::new(Function::new(
7622 "ARRAY_GENERATE_RANGE".to_string(),
7623 vec![
7624 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
7625 datediff_plus_one,
7626 ],
7627 )));
7628
7629 let flatten_input = Expression::NamedArgument(Box::new(NamedArgument {
7630 name: Identifier::new("INPUT"),
7631 value: array_gen_range,
7632 separator: crate::expressions::NamedArgSeparator::DArrow,
7633 }));
7634 let flatten = Expression::Function(Box::new(Function::new(
7635 "FLATTEN".to_string(),
7636 vec![flatten_input],
7637 )));
7638
7639 let table_func =
7640 Expression::Function(Box::new(Function::new("TABLE".to_string(), vec![flatten])));
7641 let flatten_aliased = Expression::Alias(Box::new(Alias {
7642 this: table_func,
7643 alias: Identifier::new("_t0"),
7644 column_aliases: vec![
7645 Identifier::new("seq"),
7646 Identifier::new("key"),
7647 Identifier::new("path"),
7648 Identifier::new("index"),
7649 Identifier::new(col_name),
7650 Identifier::new("this"),
7651 ],
7652 alias_explicit_as: false,
7653 alias_keyword: None,
7654 pre_alias_comments: vec![],
7655 trailing_comments: vec![],
7656 inferred_type: None,
7657 }));
7658
7659 let dateadd_expr = Expression::Function(Box::new(Function::new(
7660 "DATEADD".to_string(),
7661 vec![
7662 Expression::boxed_column(Column {
7663 name: Identifier::new(&unit_str),
7664 table: None,
7665 join_mark: false,
7666 trailing_comments: vec![],
7667 span: None,
7668 inferred_type: None,
7669 }),
7670 Expression::Cast(Box::new(Cast {
7671 this: Expression::boxed_column(Column {
7672 name: Identifier::new(col_name),
7673 table: None,
7674 join_mark: false,
7675 trailing_comments: vec![],
7676 span: None,
7677 inferred_type: None,
7678 }),
7679 to: DataType::Int {
7680 length: None,
7681 integer_spelling: false,
7682 },
7683 trailing_comments: vec![],
7684 double_colon_syntax: false,
7685 format: None,
7686 default: None,
7687 inferred_type: None,
7688 })),
7689 start_expr.clone(),
7690 ],
7691 )));
7692 let dateadd_aliased = Expression::Alias(Box::new(Alias {
7693 this: dateadd_expr,
7694 alias: Identifier::new(col_name),
7695 column_aliases: vec![],
7696 alias_explicit_as: false,
7697 alias_keyword: None,
7698 pre_alias_comments: vec![],
7699 trailing_comments: vec![],
7700 inferred_type: None,
7701 }));
7702
7703 let mut inner_select = Select::new();
7705 inner_select.expressions = vec![dateadd_aliased];
7706 inner_select.from = Some(From {
7707 expressions: vec![flatten_aliased],
7708 });
7709
7710 let inner_subquery = Expression::Subquery(Box::new(Subquery {
7712 this: Expression::Select(Box::new(inner_select)),
7713 alias: None,
7714 column_aliases: vec![],
7715 alias_explicit_as: false,
7716 alias_keyword: None,
7717 order_by: None,
7718 limit: None,
7719 offset: None,
7720 distribute_by: None,
7721 sort_by: None,
7722 cluster_by: None,
7723 lateral: false,
7724 modifiers_inside: false,
7725 trailing_comments: vec![],
7726 inferred_type: None,
7727 }));
7728
7729 let star = Expression::Star(Star {
7731 table: None,
7732 except: None,
7733 replace: None,
7734 rename: None,
7735 trailing_comments: vec![],
7736 span: None,
7737 });
7738 let array_agg = Expression::ArrayAgg(Box::new(AggFunc {
7739 this: star,
7740 distinct: false,
7741 filter: None,
7742 order_by: vec![],
7743 name: Some("ARRAY_AGG".to_string()),
7744 ignore_nulls: None,
7745 having_max: None,
7746 limit: None,
7747 inferred_type: None,
7748 }));
7749
7750 let mut outer_select = Select::new();
7751 outer_select.expressions = vec![array_agg];
7752 outer_select.from = Some(From {
7753 expressions: vec![inner_subquery],
7754 });
7755
7756 let outer_subquery = Expression::Subquery(Box::new(Subquery {
7758 this: Expression::Select(Box::new(outer_select)),
7759 alias: None,
7760 column_aliases: vec![],
7761 alias_explicit_as: false,
7762 alias_keyword: None,
7763 order_by: None,
7764 limit: None,
7765 offset: None,
7766 distribute_by: None,
7767 sort_by: None,
7768 cluster_by: None,
7769 lateral: false,
7770 modifiers_inside: false,
7771 trailing_comments: vec![],
7772 inferred_type: None,
7773 }));
7774
7775 Ok(Expression::ArraySize(Box::new(UnaryFunc::new(
7777 outer_subquery,
7778 ))))
7779 }
7780
7781 fn extract_interval_unit_str(step: &Option<Expression>) -> Option<String> {
7783 use crate::expressions::*;
7784 if let Some(Expression::Interval(ref iv)) = step {
7785 if let Some(IntervalUnitSpec::Simple { ref unit, .. }) = iv.unit {
7786 return Some(format!("{:?}", unit).to_ascii_uppercase());
7787 }
7788 if let Some(ref this) = iv.this {
7789 if let Expression::Literal(lit) = this {
7790 if let Literal::String(ref s) = lit.as_ref() {
7791 let parts: Vec<&str> = s.split_whitespace().collect();
7792 if parts.len() == 2 {
7793 return Some(parts[1].to_ascii_uppercase());
7794 } else if parts.len() == 1 {
7795 let upper = parts[0].to_ascii_uppercase();
7796 if matches!(
7797 upper.as_str(),
7798 "YEAR"
7799 | "QUARTER"
7800 | "MONTH"
7801 | "WEEK"
7802 | "DAY"
7803 | "HOUR"
7804 | "MINUTE"
7805 | "SECOND"
7806 ) {
7807 return Some(upper);
7808 }
7809 }
7810 }
7811 }
7812 }
7813 }
7814 if step.is_none() {
7816 return Some("DAY".to_string());
7817 }
7818 None
7819 }
7820
7821 fn normalize_snowflake_pretty(mut sql: String) -> String {
7822 if sql.contains("LATERAL IFF(_u.pos = _u_2.pos_2, _u_2.entity, NULL) AS datasource(SEQ, KEY, PATH, INDEX, VALUE, THIS)")
7823 && sql.contains("ARRAY_GENERATE_RANGE(0, (GREATEST(ARRAY_SIZE(INPUT => PARSE_JSON(flags))) - 1) + 1)")
7824 {
7825 sql = sql.replace(
7826 "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')",
7827 "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 )",
7828 );
7829
7830 sql = sql.replace(
7831 "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)",
7832 "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)",
7833 );
7834
7835 sql = sql.replace(
7836 "OR (_u.pos > (ARRAY_SIZE(INPUT => PARSE_JSON(flags)) - 1)\n AND _u_2.pos_2 = (ARRAY_SIZE(INPUT => PARSE_JSON(flags)) - 1))",
7837 "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 )",
7838 );
7839 }
7840
7841 sql
7842 }
7843
7844 #[cfg(feature = "transpile")]
7845 fn wrap_tsql_top_level_values(expr: Expression) -> Expression {
7846 match expr {
7847 Expression::Values(values) => Self::tsql_values_as_select(*values),
7848 Expression::Union(mut union) => {
7849 let left = std::mem::replace(&mut union.left, Expression::Null(Null));
7850 let right = std::mem::replace(&mut union.right, Expression::Null(Null));
7851 union.left = Self::wrap_tsql_values_set_operand(left);
7852 union.right = Self::wrap_tsql_values_set_operand(right);
7853 Expression::Union(union)
7854 }
7855 Expression::Intersect(mut intersect) => {
7856 let left = std::mem::replace(&mut intersect.left, Expression::Null(Null));
7857 let right = std::mem::replace(&mut intersect.right, Expression::Null(Null));
7858 intersect.left = Self::wrap_tsql_values_set_operand(left);
7859 intersect.right = Self::wrap_tsql_values_set_operand(right);
7860 Expression::Intersect(intersect)
7861 }
7862 Expression::Except(mut except) => {
7863 let left = std::mem::replace(&mut except.left, Expression::Null(Null));
7864 let right = std::mem::replace(&mut except.right, Expression::Null(Null));
7865 except.left = Self::wrap_tsql_values_set_operand(left);
7866 except.right = Self::wrap_tsql_values_set_operand(right);
7867 Expression::Except(except)
7868 }
7869 other => other,
7870 }
7871 }
7872
7873 #[cfg(feature = "transpile")]
7874 fn wrap_tsql_values_set_operand(expr: Expression) -> Expression {
7875 match expr {
7876 Expression::Values(values) => Self::tsql_values_as_select(*values),
7877 Expression::Union(mut union) => {
7878 let left = std::mem::replace(&mut union.left, Expression::Null(Null));
7879 let right = std::mem::replace(&mut union.right, Expression::Null(Null));
7880 union.left = Self::wrap_tsql_values_set_operand(left);
7881 union.right = Self::wrap_tsql_values_set_operand(right);
7882 Expression::Union(union)
7883 }
7884 Expression::Intersect(mut intersect) => {
7885 let left = std::mem::replace(&mut intersect.left, Expression::Null(Null));
7886 let right = std::mem::replace(&mut intersect.right, Expression::Null(Null));
7887 intersect.left = Self::wrap_tsql_values_set_operand(left);
7888 intersect.right = Self::wrap_tsql_values_set_operand(right);
7889 Expression::Intersect(intersect)
7890 }
7891 Expression::Except(mut except) => {
7892 let left = std::mem::replace(&mut except.left, Expression::Null(Null));
7893 let right = std::mem::replace(&mut except.right, Expression::Null(Null));
7894 except.left = Self::wrap_tsql_values_set_operand(left);
7895 except.right = Self::wrap_tsql_values_set_operand(right);
7896 Expression::Except(except)
7897 }
7898 other => other,
7899 }
7900 }
7901
7902 #[cfg(feature = "transpile")]
7903 fn tsql_values_as_select(mut values: crate::expressions::Values) -> Expression {
7904 let column_aliases = if values.column_aliases.is_empty() {
7905 let column_count = values
7906 .expressions
7907 .first()
7908 .map(|row| row.expressions.len())
7909 .unwrap_or(0);
7910 (1..=column_count)
7911 .map(|index| Identifier::new(format!("column{index}")))
7912 .collect()
7913 } else {
7914 std::mem::take(&mut values.column_aliases)
7915 };
7916
7917 values.alias = None;
7918
7919 let values_subquery = Expression::Subquery(Box::new(crate::expressions::Subquery {
7920 this: Expression::Values(Box::new(values)),
7921 alias: Some(Identifier::new("_v")),
7922 column_aliases,
7923 alias_explicit_as: false,
7924 alias_keyword: None,
7925 order_by: None,
7926 limit: None,
7927 offset: None,
7928 distribute_by: None,
7929 sort_by: None,
7930 cluster_by: None,
7931 lateral: false,
7932 modifiers_inside: false,
7933 trailing_comments: Vec::new(),
7934 inferred_type: None,
7935 }));
7936
7937 let mut select = crate::expressions::Select::new();
7938 select.expressions = vec![Expression::star()];
7939 select.from = Some(From {
7940 expressions: vec![values_subquery],
7941 });
7942
7943 Expression::Select(Box::new(select))
7944 }
7945
7946 fn extract_interval_parts(
7947 interval_expr: &Expression,
7948 ) -> Option<(Expression, crate::expressions::IntervalUnit)> {
7949 use crate::expressions::{DataType, IntervalUnit, IntervalUnitSpec, Literal};
7950
7951 fn unit_from_str(unit: &str) -> Option<IntervalUnit> {
7952 match unit.trim().to_ascii_uppercase().as_str() {
7953 "YEAR" | "YEARS" | "Y" | "YR" | "YRS" | "YY" | "YYYY" => Some(IntervalUnit::Year),
7954 "QUARTER" | "QUARTERS" | "Q" | "QTR" | "QTRS" | "QQ" => Some(IntervalUnit::Quarter),
7955 "MONTH" | "MONTHS" | "MON" | "MONS" | "MM" => Some(IntervalUnit::Month),
7956 "WEEK" | "WEEKS" | "W" | "WK" | "WKS" | "WW" | "ISOWEEK" => {
7957 Some(IntervalUnit::Week)
7958 }
7959 "DAY" | "DAYS" | "D" | "DD" => Some(IntervalUnit::Day),
7960 "HOUR" | "HOURS" | "H" | "HH" | "HR" | "HRS" => Some(IntervalUnit::Hour),
7961 "MINUTE" | "MINUTES" | "MI" | "MIN" | "MINS" | "N" => Some(IntervalUnit::Minute),
7962 "SECOND" | "SECONDS" | "S" | "SEC" | "SECS" | "SS" => Some(IntervalUnit::Second),
7963 "MILLISECOND" | "MILLISECONDS" | "MS" | "MSEC" | "MSECS" | "MSECOND"
7964 | "MSECONDS" | "MILLISEC" | "MILLISECS" | "MILLISECON" => {
7965 Some(IntervalUnit::Millisecond)
7966 }
7967 "MICROSECOND" | "MICROSECONDS" | "US" | "USEC" | "USECS" | "USECOND"
7968 | "USECONDS" | "MICROSEC" | "MICROSECS" | "MCS" => Some(IntervalUnit::Microsecond),
7969 "NANOSECOND" | "NANOSECONDS" | "NS" | "NSEC" | "NSECS" | "NSECOND" | "NSECONDS"
7970 | "NANOSEC" | "NANOSECS" => Some(IntervalUnit::Nanosecond),
7971 _ => None,
7972 }
7973 }
7974
7975 fn parts_from_literal_string(s: &str) -> Option<(Expression, IntervalUnit)> {
7976 let mut parts = s.split_whitespace();
7977 let value = parts.next()?;
7978 let unit = unit_from_str(parts.next()?)?;
7979 Some((
7980 Expression::Literal(Box::new(Literal::String(value.to_string()))),
7981 unit,
7982 ))
7983 }
7984
7985 fn unit_from_spec(unit: &IntervalUnitSpec) -> Option<IntervalUnit> {
7986 match unit {
7987 IntervalUnitSpec::Simple { unit, .. } => Some(*unit),
7988 IntervalUnitSpec::Expr(expr) => match expr.as_ref() {
7989 Expression::Day(_) => Some(IntervalUnit::Day),
7990 Expression::Month(_) => Some(IntervalUnit::Month),
7991 Expression::Year(_) => Some(IntervalUnit::Year),
7992 Expression::Identifier(id) => unit_from_str(&id.name),
7993 Expression::Var(v) => unit_from_str(&v.this),
7994 Expression::Column(col) => unit_from_str(&col.name.name),
7995 _ => None,
7996 },
7997 _ => None,
7998 }
7999 }
8000
8001 match interval_expr {
8002 Expression::Interval(iv) => {
8003 let val = iv.this.clone().unwrap_or(Expression::number(0));
8004 if let Expression::Literal(lit) = &val {
8005 if let Literal::String(s) = lit.as_ref() {
8006 if let Some(parts) = parts_from_literal_string(s) {
8007 return Some(parts);
8008 }
8009 }
8010 }
8011 let unit = iv
8012 .unit
8013 .as_ref()
8014 .and_then(unit_from_spec)
8015 .unwrap_or(IntervalUnit::Day);
8016 Some((val, unit))
8017 }
8018 Expression::Cast(cast) if matches!(cast.to, DataType::Interval { .. }) => {
8019 if let Expression::Literal(lit) = &cast.this {
8020 if let Literal::String(s) = lit.as_ref() {
8021 if let Some(parts) = parts_from_literal_string(s) {
8022 return Some(parts);
8023 }
8024 }
8025 }
8026 let unit = match &cast.to {
8027 DataType::Interval {
8028 unit: Some(unit), ..
8029 } => unit_from_str(unit).unwrap_or(IntervalUnit::Day),
8030 _ => IntervalUnit::Day,
8031 };
8032 Some((cast.this.clone(), unit))
8033 }
8034 _ => None,
8035 }
8036 }
8037
8038 fn data_type_is_interval(dt: &DataType) -> bool {
8039 match dt {
8040 DataType::Interval { .. } => true,
8041 DataType::Custom { name } => name.trim().eq_ignore_ascii_case("INTERVAL"),
8042 _ => false,
8043 }
8044 }
8045
8046 fn node_is_interval_cast(node: &Expression) -> bool {
8047 match node {
8048 Expression::Cast(c) | Expression::TryCast(c) | Expression::SafeCast(c) => {
8049 Self::data_type_is_interval(&c.to)
8050 }
8051 _ => false,
8052 }
8053 }
8054
8055 fn reject_tsql_interval_casts(
8056 expr: &Expression,
8057 target: DialectType,
8058 opts: &TranspileOptions,
8059 ) -> Result<()> {
8060 if !matches!(
8061 opts.unsupported_level,
8062 UnsupportedLevel::Raise | UnsupportedLevel::Immediate
8063 ) {
8064 return Ok(());
8065 }
8066
8067 if expr.dfs().any(Self::node_is_interval_cast) {
8068 return Err(crate::error::Error::unsupported(
8069 "INTERVAL casts",
8070 target.to_string(),
8071 ));
8072 }
8073
8074 Ok(())
8075 }
8076
8077 fn tsql_varchar_max_type() -> DataType {
8078 DataType::Custom {
8079 name: "VARCHAR(MAX)".to_string(),
8080 }
8081 }
8082
8083 fn rewrite_tsql_interval_casts_to_varchar(expr: Expression) -> Result<Expression> {
8084 transform_recursive(expr, &|e| match e {
8085 Expression::Cast(mut cast) if Self::data_type_is_interval(&cast.to) => {
8086 cast.to = Self::tsql_varchar_max_type();
8087 cast.double_colon_syntax = false;
8088 Ok(Expression::Cast(cast))
8089 }
8090 Expression::TryCast(mut cast) if Self::data_type_is_interval(&cast.to) => {
8091 cast.to = Self::tsql_varchar_max_type();
8092 cast.double_colon_syntax = false;
8093 Ok(Expression::TryCast(cast))
8094 }
8095 Expression::SafeCast(mut cast) if Self::data_type_is_interval(&cast.to) => {
8096 cast.to = Self::tsql_varchar_max_type();
8097 cast.double_colon_syntax = false;
8098 Ok(Expression::SafeCast(cast))
8099 }
8100 _ => Ok(e),
8101 })
8102 }
8103
8104 fn rewrite_tsql_interval_arithmetic(
8105 expr: &Expression,
8106 source: DialectType,
8107 ) -> Option<Expression> {
8108 match expr {
8109 Expression::Add(op) => {
8110 if Self::extract_interval_parts(&op.right).is_some() {
8111 return Some(Self::build_tsql_dateadd_from_interval(
8112 op.left.clone(),
8113 &op.right,
8114 false,
8115 ));
8116 }
8117
8118 if Self::is_postgres_family_source(source) {
8119 if Self::is_explicit_date_expr(&op.left)
8120 && Self::is_integer_day_offset_expr(&op.right)
8121 {
8122 return Some(Self::build_tsql_dateadd_days(
8123 op.left.clone(),
8124 op.right.clone(),
8125 false,
8126 ));
8127 }
8128
8129 if Self::is_integer_day_offset_expr(&op.left)
8130 && Self::is_explicit_date_expr(&op.right)
8131 {
8132 return Some(Self::build_tsql_dateadd_days(
8133 op.right.clone(),
8134 op.left.clone(),
8135 false,
8136 ));
8137 }
8138 }
8139
8140 None
8141 }
8142 Expression::Sub(op) => {
8143 if Self::extract_interval_parts(&op.right).is_some() {
8144 return Some(Self::build_tsql_dateadd_from_interval(
8145 op.left.clone(),
8146 &op.right,
8147 true,
8148 ));
8149 }
8150
8151 if Self::is_postgres_family_source(source) {
8152 if Self::is_explicit_date_expr(&op.left)
8153 && Self::is_explicit_date_expr(&op.right)
8154 {
8155 return Some(Self::build_tsql_datediff_days(
8156 op.right.clone(),
8157 op.left.clone(),
8158 ));
8159 }
8160
8161 if Self::is_explicit_date_expr(&op.left)
8162 && Self::is_integer_day_offset_expr(&op.right)
8163 {
8164 return Some(Self::build_tsql_dateadd_days(
8165 op.left.clone(),
8166 op.right.clone(),
8167 true,
8168 ));
8169 }
8170 }
8171
8172 None
8173 }
8174 _ => None,
8175 }
8176 }
8177
8178 fn is_postgres_family_source(source: DialectType) -> bool {
8179 matches!(
8180 source,
8181 DialectType::PostgreSQL
8182 | DialectType::Redshift
8183 | DialectType::Materialize
8184 | DialectType::RisingWave
8185 | DialectType::CockroachDB
8186 )
8187 }
8188
8189 fn is_explicit_date_expr(expr: &Expression) -> bool {
8190 use crate::expressions::Literal;
8191
8192 match expr {
8193 Expression::Literal(lit) => matches!(lit.as_ref(), Literal::Date(_)),
8194 Expression::Cast(c) | Expression::TryCast(c) | Expression::SafeCast(c) => {
8195 matches!(c.to, crate::expressions::DataType::Date)
8196 }
8197 Expression::Paren(p) => Self::is_explicit_date_expr(&p.this),
8198 Expression::CurrentDate(_)
8199 | Expression::Date(_)
8200 | Expression::MakeDate(_)
8201 | Expression::ToDate(_)
8202 | Expression::DateStrToDate(_) => true,
8203 _ => false,
8204 }
8205 }
8206
8207 fn is_integer_day_offset_expr(expr: &Expression) -> bool {
8208 use crate::expressions::Literal;
8209
8210 match expr {
8211 Expression::Literal(lit) => match lit.as_ref() {
8212 Literal::Number(n) => n.parse::<i64>().is_ok(),
8213 _ => false,
8214 },
8215 Expression::Parameter(_) | Expression::Placeholder(_) => true,
8216 Expression::Neg(op) => Self::is_integer_day_offset_expr(&op.this),
8217 Expression::Paren(p) => Self::is_integer_day_offset_expr(&p.this),
8218 _ => false,
8219 }
8220 }
8221
8222 fn build_tsql_datediff_days(start: Expression, end: Expression) -> Expression {
8223 Expression::Function(Box::new(Function::new(
8224 "DATEDIFF".to_string(),
8225 vec![Expression::Identifier(Identifier::new("DAY")), start, end],
8226 )))
8227 }
8228
8229 fn build_tsql_dateadd_days(date: Expression, amount: Expression, subtract: bool) -> Expression {
8230 Expression::Function(Box::new(Function::new(
8231 "DATEADD".to_string(),
8232 vec![
8233 Expression::Identifier(Identifier::new("DAY")),
8234 Self::tsql_dateadd_amount(amount, subtract),
8235 date,
8236 ],
8237 )))
8238 }
8239
8240 fn build_tsql_dateadd_from_interval(
8241 date: Expression,
8242 interval: &Expression,
8243 subtract: bool,
8244 ) -> Expression {
8245 let (value, unit) = Self::extract_interval_parts(interval)
8246 .unwrap_or_else(|| (interval.clone(), crate::expressions::IntervalUnit::Day));
8247 let unit = normalization::temporal::interval_unit_to_string(&unit);
8248 let amount = Self::tsql_dateadd_amount(value, subtract);
8249
8250 Expression::Function(Box::new(Function::new(
8251 "DATEADD".to_string(),
8252 vec![Expression::Identifier(Identifier::new(unit)), amount, date],
8253 )))
8254 }
8255
8256 fn tsql_dateadd_amount(value: Expression, negate: bool) -> Expression {
8257 use crate::expressions::{Parameter, ParameterStyle, UnaryOp};
8258
8259 fn numeric_literal_value(value: &Expression) -> Option<&str> {
8260 match value {
8261 Expression::Literal(lit) => match lit.as_ref() {
8262 crate::expressions::Literal::Number(n)
8263 | crate::expressions::Literal::String(n) => Some(n.as_str()),
8264 _ => None,
8265 },
8266 _ => None,
8267 }
8268 }
8269
8270 fn colon_parameter(value: &Expression) -> Option<Expression> {
8271 let Expression::Literal(lit) = value else {
8272 return None;
8273 };
8274 let crate::expressions::Literal::String(s) = lit.as_ref() else {
8275 return None;
8276 };
8277 let name = s.strip_prefix(':')?;
8278 if name.is_empty()
8279 || !name
8280 .chars()
8281 .all(|ch| ch.is_ascii_alphanumeric() || ch == '_')
8282 {
8283 return None;
8284 }
8285
8286 Some(Expression::Parameter(Box::new(Parameter {
8287 name: if name.chars().all(|ch| ch.is_ascii_digit()) {
8288 None
8289 } else {
8290 Some(name.to_string())
8291 },
8292 index: name.parse::<u32>().ok(),
8293 style: ParameterStyle::Colon,
8294 quoted: false,
8295 string_quoted: false,
8296 expression: None,
8297 })))
8298 }
8299
8300 let value = colon_parameter(&value).unwrap_or(value);
8301
8302 if let Some(n) = numeric_literal_value(&value) {
8303 if let Ok(parsed) = n.parse::<f64>() {
8304 let normalized = if negate { -parsed } else { parsed };
8305 let rendered = if normalized.fract() == 0.0 {
8306 format!("{}", normalized as i64)
8307 } else {
8308 normalized.to_string()
8309 };
8310 return Expression::Literal(Box::new(crate::expressions::Literal::Number(
8311 rendered,
8312 )));
8313 }
8314 }
8315
8316 if !negate {
8317 return value;
8318 }
8319
8320 match value {
8321 Expression::Neg(op) => op.this,
8322 other => Expression::Neg(Box::new(UnaryOp {
8323 this: other,
8324 inferred_type: None,
8325 })),
8326 }
8327 }
8328
8329 const PRESERVED_TO_DATE: &'static str = "_POLYGLOT_TO_DATE";
8333}
8334
8335#[cfg(test)]
8336mod tests {
8337 use super::*;
8338
8339 #[test]
8340 fn built_in_dialect_instances_share_tokenizer_config() {
8341 let first = Dialect::get(DialectType::PostgreSQL);
8342 let second = Dialect::get(DialectType::PostgreSQL);
8343
8344 assert!(first.tokenizer.shares_config_with(&second.tokenizer));
8345 }
8346
8347 #[test]
8348 fn test_dialect_type_from_str() {
8349 assert_eq!(
8350 "postgres".parse::<DialectType>().unwrap(),
8351 DialectType::PostgreSQL
8352 );
8353 assert_eq!(
8354 "postgresql".parse::<DialectType>().unwrap(),
8355 DialectType::PostgreSQL
8356 );
8357 assert_eq!("mysql".parse::<DialectType>().unwrap(), DialectType::MySQL);
8358 assert_eq!(
8359 "bigquery".parse::<DialectType>().unwrap(),
8360 DialectType::BigQuery
8361 );
8362 }
8363
8364 #[test]
8365 fn test_basic_transpile() {
8366 let dialect = Dialect::get(DialectType::Generic);
8367 let result = dialect
8368 .transpile("SELECT 1", DialectType::PostgreSQL)
8369 .unwrap();
8370 assert_eq!(result.len(), 1);
8371 assert_eq!(result[0], "SELECT 1");
8372 }
8373
8374 #[test]
8375 fn test_sqlite_double_quoted_column_defaults_to_postgres_strings() {
8376 let sqlite = Dialect::get(DialectType::SQLite);
8377 let result = sqlite
8378 .transpile(
8379 r#"CREATE TABLE "_collections" (
8380 "type" TEXT DEFAULT "base" NOT NULL,
8381 "fields" JSON DEFAULT "[]" NOT NULL,
8382 "options" JSON DEFAULT "{}" NOT NULL
8383 )"#,
8384 DialectType::PostgreSQL,
8385 )
8386 .unwrap();
8387
8388 assert!(result[0].contains(r#""type" TEXT DEFAULT 'base' NOT NULL"#));
8389 assert!(result[0].contains(r#""fields" JSON DEFAULT '[]' NOT NULL"#));
8390 assert!(result[0].contains(r#""options" JSON DEFAULT '{}' NOT NULL"#));
8391 }
8392
8393 #[test]
8394 fn test_sqlite_identity_preserves_double_quoted_column_defaults() {
8395 let sqlite = Dialect::get(DialectType::SQLite);
8396 let result = sqlite
8397 .transpile(
8398 r#"CREATE TABLE "_collections" ("type" TEXT DEFAULT "base" NOT NULL)"#,
8399 DialectType::SQLite,
8400 )
8401 .unwrap();
8402
8403 assert_eq!(
8404 result[0],
8405 r#"CREATE TABLE "_collections" ("type" TEXT DEFAULT "base" NOT NULL)"#
8406 );
8407 }
8408
8409 #[test]
8410 fn test_function_transformation_mysql() {
8411 let dialect = Dialect::get(DialectType::Generic);
8413 let result = dialect
8414 .transpile("SELECT NVL(a, b)", DialectType::MySQL)
8415 .unwrap();
8416 assert_eq!(result[0], "SELECT IFNULL(a, b)");
8417 }
8418
8419 #[test]
8420 fn test_get_path_duckdb() {
8421 let snowflake = Dialect::get(DialectType::Snowflake);
8423
8424 let result_sf_sf = snowflake
8426 .transpile(
8427 "SELECT PARSE_JSON('{\"fruit\":\"banana\"}'):fruit",
8428 DialectType::Snowflake,
8429 )
8430 .unwrap();
8431 eprintln!("Snowflake->Snowflake colon: {}", result_sf_sf[0]);
8432
8433 let result_sf_dk = snowflake
8435 .transpile(
8436 "SELECT PARSE_JSON('{\"fruit\":\"banana\"}'):fruit",
8437 DialectType::DuckDB,
8438 )
8439 .unwrap();
8440 eprintln!("Snowflake->DuckDB colon: {}", result_sf_dk[0]);
8441
8442 let result_gp = snowflake
8444 .transpile(
8445 "SELECT GET_PATH(PARSE_JSON('{\"fruit\":\"banana\"}'), 'fruit')",
8446 DialectType::DuckDB,
8447 )
8448 .unwrap();
8449 eprintln!("Snowflake->DuckDB explicit GET_PATH: {}", result_gp[0]);
8450 }
8451
8452 #[test]
8453 fn test_function_transformation_postgres() {
8454 let dialect = Dialect::get(DialectType::Generic);
8456 let result = dialect
8457 .transpile("SELECT IFNULL(a, b)", DialectType::PostgreSQL)
8458 .unwrap();
8459 assert_eq!(result[0], "SELECT COALESCE(a, b)");
8460
8461 let result = dialect
8463 .transpile("SELECT NVL(a, b)", DialectType::PostgreSQL)
8464 .unwrap();
8465 assert_eq!(result[0], "SELECT COALESCE(a, b)");
8466 }
8467
8468 #[test]
8469 fn test_hive_cast_to_trycast() {
8470 let hive = Dialect::get(DialectType::Hive);
8472 let result = hive
8473 .transpile("CAST(1 AS INT)", DialectType::DuckDB)
8474 .unwrap();
8475 assert_eq!(result[0], "TRY_CAST(1 AS INT)");
8476
8477 let result = hive
8478 .transpile("CAST(1 AS INT)", DialectType::Presto)
8479 .unwrap();
8480 assert_eq!(result[0], "TRY_CAST(1 AS INTEGER)");
8481 }
8482
8483 #[test]
8484 fn test_hive_array_identity() {
8485 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')";
8487 let hive = Dialect::get(DialectType::Hive);
8488
8489 let result = hive.transpile(sql, DialectType::Hive).unwrap();
8491 eprintln!("Hive ARRAY via transpile: {}", result[0]);
8492 assert!(
8493 result[0].contains("ARRAY<DATE>"),
8494 "transpile: Expected ARRAY<DATE>, got: {}",
8495 result[0]
8496 );
8497
8498 let ast = hive.parse(sql).unwrap();
8500 let transformed = hive.transform(ast[0].clone()).unwrap();
8501 let output = hive.generate(&transformed).unwrap();
8502 eprintln!("Hive ARRAY via identity path: {}", output);
8503 assert!(
8504 output.contains("ARRAY<DATE>"),
8505 "identity path: Expected ARRAY<DATE>, got: {}",
8506 output
8507 );
8508 }
8509
8510 #[test]
8511 fn test_starrocks_delete_between_expansion() {
8512 let dialect = Dialect::get(DialectType::Generic);
8514
8515 let result = dialect
8517 .transpile(
8518 "DELETE FROM t WHERE a BETWEEN b AND c",
8519 DialectType::StarRocks,
8520 )
8521 .unwrap();
8522 assert_eq!(result[0], "DELETE FROM t WHERE a >= b AND a <= c");
8523
8524 let result = dialect
8526 .transpile(
8527 "DELETE FROM t WHERE a NOT BETWEEN b AND c",
8528 DialectType::StarRocks,
8529 )
8530 .unwrap();
8531 assert_eq!(result[0], "DELETE FROM t WHERE a < b OR a > c");
8532
8533 let result = dialect
8535 .transpile(
8536 "SELECT * FROM t WHERE a BETWEEN b AND c",
8537 DialectType::StarRocks,
8538 )
8539 .unwrap();
8540 assert!(
8541 result[0].contains("BETWEEN"),
8542 "BETWEEN should be preserved in SELECT"
8543 );
8544 }
8545
8546 #[test]
8547 fn test_snowflake_ltrim_rtrim_parse() {
8548 let sf = Dialect::get(DialectType::Snowflake);
8549 let sql = "SELECT LTRIM(RTRIM(col)) FROM t1";
8550 let result = sf.transpile(sql, DialectType::DuckDB);
8551 match &result {
8552 Ok(r) => eprintln!("LTRIM/RTRIM result: {}", r[0]),
8553 Err(e) => eprintln!("LTRIM/RTRIM error: {}", e),
8554 }
8555 assert!(
8556 result.is_ok(),
8557 "Expected successful parse of LTRIM(RTRIM(col)), got error: {:?}",
8558 result.err()
8559 );
8560 }
8561
8562 #[test]
8563 fn test_duckdb_count_if_parse() {
8564 let duck = Dialect::get(DialectType::DuckDB);
8565 let sql = "COUNT_IF(x)";
8566 let result = duck.transpile(sql, DialectType::DuckDB);
8567 match &result {
8568 Ok(r) => eprintln!("COUNT_IF result: {}", r[0]),
8569 Err(e) => eprintln!("COUNT_IF error: {}", e),
8570 }
8571 assert!(
8572 result.is_ok(),
8573 "Expected successful parse of COUNT_IF(x), got error: {:?}",
8574 result.err()
8575 );
8576 }
8577
8578 #[test]
8579 fn test_tsql_cast_tinyint_parse() {
8580 let tsql = Dialect::get(DialectType::TSQL);
8581 let sql = "CAST(X AS TINYINT)";
8582 let result = tsql.transpile(sql, DialectType::DuckDB);
8583 match &result {
8584 Ok(r) => eprintln!("TSQL CAST TINYINT result: {}", r[0]),
8585 Err(e) => eprintln!("TSQL CAST TINYINT error: {}", e),
8586 }
8587 assert!(
8588 result.is_ok(),
8589 "Expected successful transpile, got error: {:?}",
8590 result.err()
8591 );
8592 }
8593
8594 #[test]
8595 fn test_pg_hash_bitwise_xor() {
8596 let dialect = Dialect::get(DialectType::PostgreSQL);
8597 let result = dialect.transpile("x # y", DialectType::PostgreSQL).unwrap();
8598 assert_eq!(result[0], "x # y");
8599 }
8600
8601 #[test]
8602 fn test_pg_array_to_duckdb() {
8603 let dialect = Dialect::get(DialectType::PostgreSQL);
8604 let result = dialect
8605 .transpile("SELECT ARRAY[1, 2, 3] @> ARRAY[1, 2]", DialectType::DuckDB)
8606 .unwrap();
8607 assert_eq!(result[0], "SELECT [1, 2, 3] @> [1, 2]");
8608 }
8609
8610 #[test]
8611 fn test_array_remove_bigquery() {
8612 let dialect = Dialect::get(DialectType::Generic);
8613 let result = dialect
8614 .transpile("ARRAY_REMOVE(the_array, target)", DialectType::BigQuery)
8615 .unwrap();
8616 assert_eq!(
8617 result[0],
8618 "ARRAY(SELECT _u FROM UNNEST(the_array) AS _u WHERE _u <> target)"
8619 );
8620 }
8621
8622 #[test]
8623 fn test_map_clickhouse_case() {
8624 let dialect = Dialect::get(DialectType::Generic);
8625 let parsed = dialect
8626 .parse("CAST(MAP('a', '1') AS MAP(TEXT, TEXT))")
8627 .unwrap();
8628 eprintln!("MAP parsed: {:?}", parsed);
8629 let result = dialect
8630 .transpile(
8631 "CAST(MAP('a', '1') AS MAP(TEXT, TEXT))",
8632 DialectType::ClickHouse,
8633 )
8634 .unwrap();
8635 eprintln!("MAP result: {}", result[0]);
8636 }
8637
8638 #[test]
8639 fn test_generate_date_array_presto() {
8640 let dialect = Dialect::get(DialectType::Generic);
8641 let result = dialect.transpile(
8642 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8643 DialectType::Presto,
8644 ).unwrap();
8645 eprintln!("GDA -> Presto: {}", result[0]);
8646 assert_eq!(result[0], "SELECT * FROM UNNEST(SEQUENCE(CAST('2020-01-01' AS DATE), CAST('2020-02-01' AS DATE), (1 * INTERVAL '7' DAY)))");
8647 }
8648
8649 #[test]
8650 fn test_generate_date_array_postgres() {
8651 let dialect = Dialect::get(DialectType::Generic);
8652 let result = dialect.transpile(
8653 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8654 DialectType::PostgreSQL,
8655 ).unwrap();
8656 eprintln!("GDA -> PostgreSQL: {}", result[0]);
8657 }
8658
8659 #[test]
8660 fn test_generate_date_array_snowflake() {
8661 let dialect = Dialect::get(DialectType::Generic);
8662 let result = dialect
8663 .transpile(
8664 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8665 DialectType::Snowflake,
8666 )
8667 .unwrap();
8668 eprintln!("GDA -> Snowflake: {}", result[0]);
8669 }
8670
8671 #[test]
8672 fn test_array_length_generate_date_array_snowflake() {
8673 let dialect = Dialect::get(DialectType::Generic);
8674 let result = dialect.transpile(
8675 "SELECT ARRAY_LENGTH(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8676 DialectType::Snowflake,
8677 ).unwrap();
8678 eprintln!("ARRAY_LENGTH(GDA) -> Snowflake: {}", result[0]);
8679 }
8680
8681 #[test]
8682 fn test_generate_date_array_mysql() {
8683 let dialect = Dialect::get(DialectType::Generic);
8684 let result = dialect.transpile(
8685 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8686 DialectType::MySQL,
8687 ).unwrap();
8688 eprintln!("GDA -> MySQL: {}", result[0]);
8689 }
8690
8691 #[test]
8692 fn test_generate_date_array_redshift() {
8693 let dialect = Dialect::get(DialectType::Generic);
8694 let result = dialect.transpile(
8695 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8696 DialectType::Redshift,
8697 ).unwrap();
8698 eprintln!("GDA -> Redshift: {}", result[0]);
8699 }
8700
8701 #[test]
8702 fn test_generate_date_array_tsql() {
8703 let dialect = Dialect::get(DialectType::Generic);
8704 let result = dialect.transpile(
8705 "SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))",
8706 DialectType::TSQL,
8707 ).unwrap();
8708 eprintln!("GDA -> TSQL: {}", result[0]);
8709 }
8710
8711 #[test]
8712 fn test_struct_colon_syntax() {
8713 let dialect = Dialect::get(DialectType::Generic);
8714 let result = dialect.transpile(
8716 "CAST((1, 2, 3, 4) AS STRUCT<a TINYINT, b SMALLINT, c INT, d BIGINT>)",
8717 DialectType::ClickHouse,
8718 );
8719 match result {
8720 Ok(r) => eprintln!("STRUCT no colon -> ClickHouse: {}", r[0]),
8721 Err(e) => eprintln!("STRUCT no colon error: {}", e),
8722 }
8723 let result = dialect.transpile(
8725 "CAST((1, 2, 3, 4) AS STRUCT<a: TINYINT, b: SMALLINT, c: INT, d: BIGINT>)",
8726 DialectType::ClickHouse,
8727 );
8728 match result {
8729 Ok(r) => eprintln!("STRUCT colon -> ClickHouse: {}", r[0]),
8730 Err(e) => eprintln!("STRUCT colon error: {}", e),
8731 }
8732 }
8733
8734 #[test]
8735 fn test_generate_date_array_cte_wrapped_mysql() {
8736 let dialect = Dialect::get(DialectType::Generic);
8737 let result = dialect.transpile(
8738 "WITH dates AS (SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))) SELECT * FROM dates",
8739 DialectType::MySQL,
8740 ).unwrap();
8741 eprintln!("GDA CTE -> MySQL: {}", result[0]);
8742 }
8743
8744 #[test]
8745 fn test_generate_date_array_cte_wrapped_tsql() {
8746 let dialect = Dialect::get(DialectType::Generic);
8747 let result = dialect.transpile(
8748 "WITH dates AS (SELECT * FROM UNNEST(GENERATE_DATE_ARRAY(DATE '2020-01-01', DATE '2020-02-01', INTERVAL 1 WEEK))) SELECT * FROM dates",
8749 DialectType::TSQL,
8750 ).unwrap();
8751 eprintln!("GDA CTE -> TSQL: {}", result[0]);
8752 }
8753
8754 #[test]
8755 fn test_decode_literal_no_null_check() {
8756 let dialect = Dialect::get(DialectType::Oracle);
8758 let result = dialect
8759 .transpile("SELECT decode(1,2,3,4)", DialectType::DuckDB)
8760 .unwrap();
8761 assert_eq!(
8762 result[0], "SELECT CASE WHEN 1 = 2 THEN 3 ELSE 4 END",
8763 "Literal DECODE should not have IS NULL checks"
8764 );
8765 }
8766
8767 #[test]
8768 fn test_decode_column_vs_literal_no_null_check() {
8769 let dialect = Dialect::get(DialectType::Oracle);
8771 let result = dialect
8772 .transpile("SELECT decode(col, 2, 3, 4) FROM t", DialectType::DuckDB)
8773 .unwrap();
8774 assert_eq!(
8775 result[0], "SELECT CASE WHEN col = 2 THEN 3 ELSE 4 END FROM t",
8776 "Column vs literal DECODE should not have IS NULL checks"
8777 );
8778 }
8779
8780 #[test]
8781 fn test_decode_column_vs_column_keeps_null_check() {
8782 let dialect = Dialect::get(DialectType::Oracle);
8784 let result = dialect
8785 .transpile("SELECT decode(col, col2, 3, 4) FROM t", DialectType::DuckDB)
8786 .unwrap();
8787 assert!(
8788 result[0].contains("IS NULL"),
8789 "Column vs column DECODE should have IS NULL checks, got: {}",
8790 result[0]
8791 );
8792 }
8793
8794 #[test]
8795 fn test_decode_null_search() {
8796 let dialect = Dialect::get(DialectType::Oracle);
8798 let result = dialect
8799 .transpile("SELECT decode(col, NULL, 3, 4) FROM t", DialectType::DuckDB)
8800 .unwrap();
8801 assert_eq!(
8802 result[0],
8803 "SELECT CASE WHEN col IS NULL THEN 3 ELSE 4 END FROM t",
8804 );
8805 }
8806
8807 #[test]
8812 fn test_regexp_substr_snowflake_to_duckdb_2arg() {
8813 let dialect = Dialect::get(DialectType::Snowflake);
8814 let result = dialect
8815 .transpile("SELECT REGEXP_SUBSTR(s, 'pattern')", DialectType::DuckDB)
8816 .unwrap();
8817 assert_eq!(result[0], "SELECT REGEXP_EXTRACT(s, 'pattern')");
8818 }
8819
8820 #[test]
8821 fn test_regexp_substr_snowflake_to_duckdb_3arg_pos1() {
8822 let dialect = Dialect::get(DialectType::Snowflake);
8823 let result = dialect
8824 .transpile("SELECT REGEXP_SUBSTR(s, 'pattern', 1)", DialectType::DuckDB)
8825 .unwrap();
8826 assert_eq!(result[0], "SELECT REGEXP_EXTRACT(s, 'pattern')");
8827 }
8828
8829 #[test]
8830 fn test_regexp_substr_snowflake_to_duckdb_3arg_pos_gt1() {
8831 let dialect = Dialect::get(DialectType::Snowflake);
8832 let result = dialect
8833 .transpile("SELECT REGEXP_SUBSTR(s, 'pattern', 3)", DialectType::DuckDB)
8834 .unwrap();
8835 assert_eq!(
8836 result[0],
8837 "SELECT REGEXP_EXTRACT(NULLIF(SUBSTRING(s, 3), ''), 'pattern')"
8838 );
8839 }
8840
8841 #[test]
8842 fn test_regexp_substr_snowflake_to_duckdb_4arg_occ_gt1() {
8843 let dialect = Dialect::get(DialectType::Snowflake);
8844 let result = dialect
8845 .transpile(
8846 "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 3)",
8847 DialectType::DuckDB,
8848 )
8849 .unwrap();
8850 assert_eq!(
8851 result[0],
8852 "SELECT ARRAY_EXTRACT(REGEXP_EXTRACT_ALL(s, 'pattern'), 3)"
8853 );
8854 }
8855
8856 #[test]
8857 fn test_regexp_substr_snowflake_to_duckdb_5arg_e_flag() {
8858 let dialect = Dialect::get(DialectType::Snowflake);
8859 let result = dialect
8860 .transpile(
8861 "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 1, 'e')",
8862 DialectType::DuckDB,
8863 )
8864 .unwrap();
8865 assert_eq!(result[0], "SELECT REGEXP_EXTRACT(s, 'pattern')");
8866 }
8867
8868 #[test]
8869 fn test_regexp_substr_snowflake_to_duckdb_6arg_group0() {
8870 let dialect = Dialect::get(DialectType::Snowflake);
8871 let result = dialect
8872 .transpile(
8873 "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 1, 'e', 0)",
8874 DialectType::DuckDB,
8875 )
8876 .unwrap();
8877 assert_eq!(result[0], "SELECT REGEXP_EXTRACT(s, 'pattern')");
8878 }
8879
8880 #[test]
8881 fn test_regexp_substr_snowflake_identity_strip_group0() {
8882 let dialect = Dialect::get(DialectType::Snowflake);
8883 let result = dialect
8884 .transpile(
8885 "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 1, 'e', 0)",
8886 DialectType::Snowflake,
8887 )
8888 .unwrap();
8889 assert_eq!(result[0], "SELECT REGEXP_SUBSTR(s, 'pattern', 1, 1, 'e')");
8890 }
8891
8892 #[test]
8893 fn test_regexp_substr_all_snowflake_to_duckdb_2arg() {
8894 let dialect = Dialect::get(DialectType::Snowflake);
8895 let result = dialect
8896 .transpile(
8897 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern')",
8898 DialectType::DuckDB,
8899 )
8900 .unwrap();
8901 assert_eq!(result[0], "SELECT REGEXP_EXTRACT_ALL(s, 'pattern')");
8902 }
8903
8904 #[test]
8905 fn test_regexp_substr_all_snowflake_to_duckdb_3arg_pos_gt1() {
8906 let dialect = Dialect::get(DialectType::Snowflake);
8907 let result = dialect
8908 .transpile(
8909 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 3)",
8910 DialectType::DuckDB,
8911 )
8912 .unwrap();
8913 assert_eq!(
8914 result[0],
8915 "SELECT REGEXP_EXTRACT_ALL(SUBSTRING(s, 3), 'pattern')"
8916 );
8917 }
8918
8919 #[test]
8920 fn test_regexp_substr_all_snowflake_to_duckdb_5arg_e_flag() {
8921 let dialect = Dialect::get(DialectType::Snowflake);
8922 let result = dialect
8923 .transpile(
8924 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 1, 1, 'e')",
8925 DialectType::DuckDB,
8926 )
8927 .unwrap();
8928 assert_eq!(result[0], "SELECT REGEXP_EXTRACT_ALL(s, 'pattern')");
8929 }
8930
8931 #[test]
8932 fn test_regexp_substr_all_snowflake_to_duckdb_6arg_group0() {
8933 let dialect = Dialect::get(DialectType::Snowflake);
8934 let result = dialect
8935 .transpile(
8936 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 1, 1, 'e', 0)",
8937 DialectType::DuckDB,
8938 )
8939 .unwrap();
8940 assert_eq!(result[0], "SELECT REGEXP_EXTRACT_ALL(s, 'pattern')");
8941 }
8942
8943 #[test]
8944 fn test_regexp_substr_all_snowflake_identity_strip_group0() {
8945 let dialect = Dialect::get(DialectType::Snowflake);
8946 let result = dialect
8947 .transpile(
8948 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 1, 1, 'e', 0)",
8949 DialectType::Snowflake,
8950 )
8951 .unwrap();
8952 assert_eq!(
8953 result[0],
8954 "SELECT REGEXP_SUBSTR_ALL(s, 'pattern', 1, 1, 'e')"
8955 );
8956 }
8957
8958 #[test]
8959 fn test_regexp_count_snowflake_to_duckdb_2arg() {
8960 let dialect = Dialect::get(DialectType::Snowflake);
8961 let result = dialect
8962 .transpile("SELECT REGEXP_COUNT(s, 'pattern')", DialectType::DuckDB)
8963 .unwrap();
8964 assert_eq!(
8965 result[0],
8966 "SELECT CASE WHEN 'pattern' = '' THEN 0 ELSE LENGTH(REGEXP_EXTRACT_ALL(s, 'pattern')) END"
8967 );
8968 }
8969
8970 #[test]
8971 fn test_regexp_count_snowflake_to_duckdb_3arg() {
8972 let dialect = Dialect::get(DialectType::Snowflake);
8973 let result = dialect
8974 .transpile("SELECT REGEXP_COUNT(s, 'pattern', 3)", DialectType::DuckDB)
8975 .unwrap();
8976 assert_eq!(
8977 result[0],
8978 "SELECT CASE WHEN 'pattern' = '' THEN 0 ELSE LENGTH(REGEXP_EXTRACT_ALL(SUBSTRING(s, 3), 'pattern')) END"
8979 );
8980 }
8981
8982 #[test]
8983 fn test_regexp_count_snowflake_to_duckdb_4arg_flags() {
8984 let dialect = Dialect::get(DialectType::Snowflake);
8985 let result = dialect
8986 .transpile(
8987 "SELECT REGEXP_COUNT(s, 'pattern', 1, 'i')",
8988 DialectType::DuckDB,
8989 )
8990 .unwrap();
8991 assert_eq!(
8992 result[0],
8993 "SELECT CASE WHEN '(?i)' || 'pattern' = '' THEN 0 ELSE LENGTH(REGEXP_EXTRACT_ALL(SUBSTRING(s, 1), '(?i)' || 'pattern')) END"
8994 );
8995 }
8996
8997 #[test]
8998 fn test_regexp_count_snowflake_to_duckdb_4arg_flags_literal_string() {
8999 let dialect = Dialect::get(DialectType::Snowflake);
9000 let result = dialect
9001 .transpile(
9002 "SELECT REGEXP_COUNT('Hello World', 'L', 1, 'im')",
9003 DialectType::DuckDB,
9004 )
9005 .unwrap();
9006 assert_eq!(
9007 result[0],
9008 "SELECT CASE WHEN '(?im)' || 'L' = '' THEN 0 ELSE LENGTH(REGEXP_EXTRACT_ALL(SUBSTRING('Hello World', 1), '(?im)' || 'L')) END"
9009 );
9010 }
9011
9012 #[test]
9013 fn test_regexp_replace_snowflake_to_duckdb_5arg_pos1_occ1() {
9014 let dialect = Dialect::get(DialectType::Snowflake);
9015 let result = dialect
9016 .transpile(
9017 "SELECT REGEXP_REPLACE(s, 'pattern', 'repl', 1, 1)",
9018 DialectType::DuckDB,
9019 )
9020 .unwrap();
9021 assert_eq!(result[0], "SELECT REGEXP_REPLACE(s, 'pattern', 'repl')");
9022 }
9023
9024 #[test]
9025 fn test_regexp_replace_snowflake_to_duckdb_5arg_pos_gt1_occ0() {
9026 let dialect = Dialect::get(DialectType::Snowflake);
9027 let result = dialect
9028 .transpile(
9029 "SELECT REGEXP_REPLACE(s, 'pattern', 'repl', 3, 0)",
9030 DialectType::DuckDB,
9031 )
9032 .unwrap();
9033 assert_eq!(
9034 result[0],
9035 "SELECT SUBSTRING(s, 1, 2) || REGEXP_REPLACE(SUBSTRING(s, 3), 'pattern', 'repl', 'g')"
9036 );
9037 }
9038
9039 #[test]
9040 fn test_regexp_replace_snowflake_to_duckdb_5arg_pos_gt1_occ1() {
9041 let dialect = Dialect::get(DialectType::Snowflake);
9042 let result = dialect
9043 .transpile(
9044 "SELECT REGEXP_REPLACE(s, 'pattern', 'repl', 3, 1)",
9045 DialectType::DuckDB,
9046 )
9047 .unwrap();
9048 assert_eq!(
9049 result[0],
9050 "SELECT SUBSTRING(s, 1, 2) || REGEXP_REPLACE(SUBSTRING(s, 3), 'pattern', 'repl')"
9051 );
9052 }
9053
9054 #[test]
9055 fn test_rlike_snowflake_to_duckdb_2arg() {
9056 let dialect = Dialect::get(DialectType::Snowflake);
9057 let result = dialect
9058 .transpile("SELECT RLIKE(a, b)", DialectType::DuckDB)
9059 .unwrap();
9060 assert_eq!(result[0], "SELECT REGEXP_FULL_MATCH(a, b)");
9061 }
9062
9063 #[test]
9064 fn test_rlike_snowflake_to_duckdb_3arg_flags() {
9065 let dialect = Dialect::get(DialectType::Snowflake);
9066 let result = dialect
9067 .transpile("SELECT RLIKE(a, b, 'i')", DialectType::DuckDB)
9068 .unwrap();
9069 assert_eq!(result[0], "SELECT REGEXP_FULL_MATCH(a, b, 'i')");
9070 }
9071
9072 #[test]
9073 fn test_regexp_extract_all_bigquery_to_snowflake_no_capture() {
9074 let dialect = Dialect::get(DialectType::BigQuery);
9075 let result = dialect
9076 .transpile(
9077 "SELECT REGEXP_EXTRACT_ALL(s, 'pattern')",
9078 DialectType::Snowflake,
9079 )
9080 .unwrap();
9081 assert_eq!(result[0], "SELECT REGEXP_SUBSTR_ALL(s, 'pattern')");
9082 }
9083
9084 #[test]
9085 fn test_regexp_extract_all_bigquery_to_snowflake_with_capture() {
9086 let dialect = Dialect::get(DialectType::BigQuery);
9087 let result = dialect
9088 .transpile(
9089 "SELECT REGEXP_EXTRACT_ALL(s, '(a)[0-9]')",
9090 DialectType::Snowflake,
9091 )
9092 .unwrap();
9093 assert_eq!(
9094 result[0],
9095 "SELECT REGEXP_SUBSTR_ALL(s, '(a)[0-9]', 1, 1, 'c', 1)"
9096 );
9097 }
9098
9099 #[test]
9100 fn test_regexp_instr_snowflake_to_duckdb_2arg() {
9101 let dialect = Dialect::get(DialectType::Snowflake);
9102 let result = dialect
9103 .transpile("SELECT REGEXP_INSTR(s, 'pattern')", DialectType::DuckDB)
9104 .unwrap();
9105 assert!(
9106 result[0].contains("CASE WHEN"),
9107 "Expected CASE WHEN in result: {}",
9108 result[0]
9109 );
9110 assert!(
9111 result[0].contains("LIST_SUM"),
9112 "Expected LIST_SUM in result: {}",
9113 result[0]
9114 );
9115 }
9116
9117 #[test]
9118 fn test_array_except_generic_to_duckdb() {
9119 let dialect = Dialect::get(DialectType::Generic);
9120 let result = dialect
9121 .transpile(
9122 "SELECT ARRAY_EXCEPT(ARRAY(1, 2, 3), ARRAY(2))",
9123 DialectType::DuckDB,
9124 )
9125 .unwrap();
9126 eprintln!("ARRAY_EXCEPT Generic->DuckDB: {}", result[0]);
9127 assert!(
9128 result[0].contains("CASE WHEN"),
9129 "Expected CASE WHEN: {}",
9130 result[0]
9131 );
9132 assert!(
9133 result[0].contains("LIST_FILTER"),
9134 "Expected LIST_FILTER: {}",
9135 result[0]
9136 );
9137 assert!(
9138 result[0].contains("LIST_DISTINCT"),
9139 "Expected LIST_DISTINCT: {}",
9140 result[0]
9141 );
9142 assert!(
9143 result[0].contains("IS NOT DISTINCT FROM"),
9144 "Expected IS NOT DISTINCT FROM: {}",
9145 result[0]
9146 );
9147 assert!(
9148 result[0].contains("= 0"),
9149 "Expected = 0 filter: {}",
9150 result[0]
9151 );
9152 }
9153
9154 #[test]
9155 fn test_array_except_generic_to_snowflake() {
9156 let dialect = Dialect::get(DialectType::Generic);
9157 let result = dialect
9158 .transpile(
9159 "SELECT ARRAY_EXCEPT(ARRAY(1, 2, 3), ARRAY(2))",
9160 DialectType::Snowflake,
9161 )
9162 .unwrap();
9163 eprintln!("ARRAY_EXCEPT Generic->Snowflake: {}", result[0]);
9164 assert_eq!(result[0], "SELECT ARRAY_EXCEPT([1, 2, 3], [2])");
9165 }
9166
9167 #[test]
9168 fn test_array_except_generic_to_presto() {
9169 let dialect = Dialect::get(DialectType::Generic);
9170 let result = dialect
9171 .transpile(
9172 "SELECT ARRAY_EXCEPT(ARRAY(1, 2, 3), ARRAY(2))",
9173 DialectType::Presto,
9174 )
9175 .unwrap();
9176 eprintln!("ARRAY_EXCEPT Generic->Presto: {}", result[0]);
9177 assert_eq!(result[0], "SELECT ARRAY_EXCEPT(ARRAY[1, 2, 3], ARRAY[2])");
9178 }
9179
9180 #[test]
9181 fn test_array_except_snowflake_to_duckdb() {
9182 let dialect = Dialect::get(DialectType::Snowflake);
9183 let result = dialect
9184 .transpile("SELECT ARRAY_EXCEPT([1, 2, 3], [2])", DialectType::DuckDB)
9185 .unwrap();
9186 eprintln!("ARRAY_EXCEPT Snowflake->DuckDB: {}", result[0]);
9187 assert!(
9188 result[0].contains("CASE WHEN"),
9189 "Expected CASE WHEN: {}",
9190 result[0]
9191 );
9192 assert!(
9193 result[0].contains("LIST_TRANSFORM"),
9194 "Expected LIST_TRANSFORM: {}",
9195 result[0]
9196 );
9197 }
9198
9199 #[test]
9200 fn test_array_contains_snowflake_to_snowflake() {
9201 let dialect = Dialect::get(DialectType::Snowflake);
9202 let result = dialect
9203 .transpile(
9204 "SELECT ARRAY_CONTAINS(x, [1, NULL, 3])",
9205 DialectType::Snowflake,
9206 )
9207 .unwrap();
9208 eprintln!("ARRAY_CONTAINS Snowflake->Snowflake: {}", result[0]);
9209 assert_eq!(result[0], "SELECT ARRAY_CONTAINS(x, [1, NULL, 3])");
9210 }
9211
9212 #[test]
9213 fn test_array_contains_snowflake_to_duckdb() {
9214 let dialect = Dialect::get(DialectType::Snowflake);
9215 let result = dialect
9216 .transpile(
9217 "SELECT ARRAY_CONTAINS(x, [1, NULL, 3])",
9218 DialectType::DuckDB,
9219 )
9220 .unwrap();
9221 eprintln!("ARRAY_CONTAINS Snowflake->DuckDB: {}", result[0]);
9222 assert!(
9223 result[0].contains("CASE WHEN"),
9224 "Expected CASE WHEN: {}",
9225 result[0]
9226 );
9227 assert!(
9228 result[0].contains("NULLIF"),
9229 "Expected NULLIF: {}",
9230 result[0]
9231 );
9232 assert!(
9233 result[0].contains("ARRAY_CONTAINS"),
9234 "Expected ARRAY_CONTAINS: {}",
9235 result[0]
9236 );
9237 }
9238
9239 #[test]
9240 fn test_array_distinct_snowflake_to_duckdb() {
9241 let dialect = Dialect::get(DialectType::Snowflake);
9242 let result = dialect
9243 .transpile(
9244 "SELECT ARRAY_DISTINCT([1, 2, 2, 3, 1])",
9245 DialectType::DuckDB,
9246 )
9247 .unwrap();
9248 eprintln!("ARRAY_DISTINCT Snowflake->DuckDB: {}", result[0]);
9249 assert!(
9250 result[0].contains("CASE WHEN"),
9251 "Expected CASE WHEN: {}",
9252 result[0]
9253 );
9254 assert!(
9255 result[0].contains("LIST_DISTINCT"),
9256 "Expected LIST_DISTINCT: {}",
9257 result[0]
9258 );
9259 assert!(
9260 result[0].contains("LIST_APPEND"),
9261 "Expected LIST_APPEND: {}",
9262 result[0]
9263 );
9264 assert!(
9265 result[0].contains("LIST_FILTER"),
9266 "Expected LIST_FILTER: {}",
9267 result[0]
9268 );
9269 }
9270}