use crate::error::ParseResult;
use crate::parser::{Parsed, parse_with};
mod ansi;
#[cfg(feature = "bigquery")]
mod bigquery;
mod builtin;
#[cfg(feature = "clickhouse")]
mod clickhouse;
#[cfg(feature = "databricks")]
mod databricks;
#[cfg(feature = "duckdb")]
mod duckdb;
#[cfg(feature = "hive")]
mod hive;
#[cfg(feature = "lenient")]
mod lenient;
#[cfg(feature = "mssql")]
mod mssql;
#[cfg(feature = "mysql")]
mod mysql;
#[cfg(feature = "postgres")]
mod postgres;
#[cfg(feature = "quiltdb")]
mod quiltdb;
#[cfg(feature = "redshift")]
mod redshift;
#[cfg(feature = "snowflake")]
mod snowflake;
#[cfg(feature = "sqlite")]
mod sqlite;
mod support;
pub use ansi::Ansi;
#[cfg(feature = "bigquery")]
pub use bigquery::BigQuery;
pub use builtin::{
BuiltinDialect, ParseBuiltinDialectError, parse_builtin, parse_builtin_with,
parse_recovering_builtin, parse_recovering_builtin_with, tokenize_with_builtin,
tokenize_with_builtin_trivia,
};
#[cfg(feature = "clickhouse")]
pub use clickhouse::ClickHouse;
#[cfg(feature = "databricks")]
pub use databricks::Databricks;
#[cfg(feature = "duckdb")]
pub use duckdb::DuckDb;
#[cfg(feature = "hive")]
pub use hive::Hive;
#[cfg(feature = "lenient")]
pub use lenient::Lenient;
#[cfg(feature = "mssql")]
pub use mssql::Mssql;
#[cfg(feature = "mysql")]
pub use mysql::MySql;
#[cfg(feature = "postgres")]
pub use postgres::Postgres;
#[cfg(feature = "quiltdb")]
pub use quiltdb::QuiltDb;
#[cfg(feature = "redshift")]
pub use redshift::Redshift;
#[cfg(feature = "snowflake")]
pub use snowflake::Snowflake;
#[cfg(feature = "sqlite")]
pub use sqlite::Sqlite;
pub use support::ProductSurface;
pub fn parse(src: &str) -> ParseResult<Parsed> {
parse_with(src, crate::parser::ParseConfig::default())
}
#[cfg(test)]
pub(crate) mod test_support {
use crate::ast::NoExt;
use crate::ast::{
CreateTableBody, DataType, SelectItem, SetExpr, SetOperator, Statement, TableElement,
};
use crate::parser::{Dialect, parse_with};
pub(crate) const REPRESENTATIVE: &str = "SELECT a, b AS x \
FROM t1 JOIN t2 ON t1.id = t2.id \
WHERE a > 1 GROUP BY a HAVING a < 9 \
UNION ALL SELECT c, d FROM t3 \
ORDER BY x LIMIT 10 OFFSET 5";
pub(crate) fn assert_full_grammar<D: Dialect<Ext = NoExt>>(dialect: D) {
let parsed = parse_with(REPRESENTATIVE, crate::ParseConfig::new(dialect))
.expect("the representative query parses");
assert_eq!(parsed.statements().len(), 1, "exactly one statement");
let Statement::Query { query, .. } = &parsed.statements()[0] else {
panic!("expected a query statement");
};
assert_eq!(query.order_by.len(), 1, "one ORDER BY key");
assert!(query.limit.is_some(), "a LIMIT/OFFSET tail");
let SetExpr::SetOperation {
op: SetOperator::Union,
all,
left,
..
} = &query.body
else {
panic!("expected a UNION set operation");
};
assert!(*all, "UNION ALL");
let SetExpr::Select { select, .. } = &**left else {
panic!("the left operand is a SELECT");
};
assert_eq!(select.projection.len(), 2, "two projection items");
assert!(
matches!(
select.projection[1],
SelectItem::Expr { alias: Some(_), .. }
),
"the second item is aliased `b AS x`",
);
assert_eq!(select.from.len(), 1, "one FROM relation");
assert_eq!(select.from[0].joins.len(), 1, "one JOIN … ON");
assert!(select.selection.is_some(), "a WHERE predicate");
assert_eq!(select.group_by.len(), 1, "one GROUP BY key");
assert!(select.having.is_some(), "a HAVING predicate");
}
pub(crate) fn first_column_type<D: Dialect<Ext = NoExt>>(dialect: D, sql: &str) -> DataType {
let parsed = parse_with(sql, crate::ParseConfig::new(dialect))
.unwrap_or_else(|err| panic!("{sql:?}: {err:?}"));
let Statement::CreateTable { create, .. } = &parsed.statements()[0] else {
panic!("{sql:?}: expected a CREATE TABLE statement");
};
let CreateTableBody::Definition { elements, .. } = &create.body else {
panic!("{sql:?}: expected a column-definition body");
};
let TableElement::Column { column, .. } = &elements[0] else {
panic!("{sql:?}: expected a column element");
};
column
.data_type
.clone()
.unwrap_or_else(|| panic!("{sql:?}: the probed column has an explicit type"))
}
}