diff --git a/CHANGELOG.md b/CHANGELOG.md index 46d58973f856..e969ef78e247 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ **Features**: +- Add a very early `sql.oracle` dialect. It currently only forces identifier + quoting to accommodate Oracle's case-folding rules; most other features fall + back to generic SQL. (@julien-pinchelimouroux, #5821) + **Fixes**: **Documentation**: diff --git a/prqlc/bindings/elixir/lib/prql.ex b/prqlc/bindings/elixir/lib/prql.ex index 47d756c3375c..60d1c2694f4d 100644 --- a/prqlc/bindings/elixir/lib/prql.ex +++ b/prqlc/bindings/elixir/lib/prql.ex @@ -18,6 +18,7 @@ defmodule PRQL do | :clickhouse | :duckdb | :glaredb + | :oracle | :redshift | :sqlite | :snowflake @@ -39,7 +40,7 @@ defmodule PRQL do * `:target` - Dialect used for generate SQL. Accepted values are `:generic`, `:mssql`, `:mysql`, `:postgres`, `:ansi`, `:bigquery`, - `:clickhouse`, `:duckdb`, `:glaredb`, `:redshift`, `:sqlite`, `:snowflake` + `:clickhouse`, `:duckdb`, `:glaredb`, `:oracle`, `:redshift`, `:sqlite`, `:snowflake` * `:format` - Formats the output, defaults to `true` diff --git a/prqlc/bindings/elixir/lib/prql/native.ex b/prqlc/bindings/elixir/lib/prql/native.ex index a3d18905b093..870c6e2f2d25 100644 --- a/prqlc/bindings/elixir/lib/prql/native.ex +++ b/prqlc/bindings/elixir/lib/prql/native.ex @@ -26,6 +26,7 @@ defmodule PRQL.Native.CompileOptions do | :bigquery | :clickhouse | :glaredb + | :oracle | :redshift | :sqlite | :snowflake diff --git a/prqlc/bindings/elixir/native/prql/src/lib.rs b/prqlc/bindings/elixir/native/prql/src/lib.rs index 24b105515ab3..4fe206785ade 100644 --- a/prqlc/bindings/elixir/native/prql/src/lib.rs +++ b/prqlc/bindings/elixir/native/prql/src/lib.rs @@ -22,6 +22,7 @@ mod atoms { generic, mssql, mysql, + oracle, postgres, redshift, sqlite, @@ -63,6 +64,8 @@ fn target_from_atom(a: Atom) -> prqlc::Target { MsSql } else if a == atoms::mysql() { MySql + } else if a == atoms::oracle() { + Oracle } else if a == atoms::postgres() { Postgres } else if a == atoms::redshift() { diff --git a/prqlc/prqlc/src/cli/test.rs b/prqlc/prqlc/src/cli/test.rs index 8d0b3f381a10..88f11b61f357 100644 --- a/prqlc/prqlc/src/cli/test.rs +++ b/prqlc/prqlc/src/cli/test.rs @@ -86,6 +86,7 @@ fn get_targets() { sql.glaredb sql.mssql sql.mysql + sql.oracle sql.postgres sql.redshift sql.sqlite diff --git a/prqlc/prqlc/src/sql/dialect.rs b/prqlc/prqlc/src/sql/dialect.rs index 6255016c3758..7f3f17e8fa97 100644 --- a/prqlc/prqlc/src/sql/dialect.rs +++ b/prqlc/prqlc/src/sql/dialect.rs @@ -89,6 +89,7 @@ pub enum Dialect { GlareDb, MsSql, MySql, + Oracle, Postgres, Redshift, SQLite, @@ -112,6 +113,7 @@ impl Dialect { Dialect::Postgres => Box::new(PostgresDialect), Dialect::Redshift => Box::new(RedshiftDialect), Dialect::GlareDb => Box::new(GlareDbDialect), + Dialect::Oracle => Box::new(OracleDialect), Dialect::Ansi | Dialect::Generic => Box::new(GenericDialect), } } @@ -126,9 +128,11 @@ impl Dialect { | Dialect::Generic | Dialect::GlareDb | Dialect::ClickHouse => SupportLevel::Supported, - Dialect::MsSql | Dialect::Ansi | Dialect::BigQuery | Dialect::Snowflake => { - SupportLevel::Unsupported - } + Dialect::MsSql + | Dialect::Ansi + | Dialect::BigQuery + | Dialect::Snowflake + | Dialect::Oracle => SupportLevel::Unsupported, } } @@ -166,6 +170,8 @@ pub struct PostgresDialect; pub struct RedshiftDialect; #[derive(Debug)] pub struct GlareDbDialect; +#[derive(Debug)] +pub struct OracleDialect; pub(super) enum ColumnExclude { Exclude, @@ -736,6 +742,14 @@ impl DialectHandler for DuckDbDialect { } } +impl DialectHandler for OracleDialect { + fn ident_quoting_style(&self) -> IdentQuotingStyle { + // Due to oraclesql identifier casing rules, identifiers are always quoted + // https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/Database-Object-Names-and-Qualifiers.html + IdentQuotingStyle::AlwaysQuoted + } +} + #[cfg(test)] mod tests { use std::str::FromStr; diff --git a/prqlc/prqlc/tests/integration/sql.rs b/prqlc/prqlc/tests/integration/sql.rs index be2dcda4b037..d40bc4ff567d 100644 --- a/prqlc/prqlc/tests/integration/sql.rs +++ b/prqlc/prqlc/tests/integration/sql.rs @@ -240,6 +240,17 @@ FROM "employees" "# )] +#[case::oracle( + sql::Dialect::Oracle, + r#" +SELECT + "a", + "b", + "col space" +FROM + "employees" +"# +)] fn test_quoting_style(#[case] dialect: sql::Dialect, #[case] expected_sql: &'static str) { let query = r#" from employees diff --git a/web/book/src/project/target.md b/web/book/src/project/target.md index 485499af92fa..43e6ad9033e7 100644 --- a/web/book/src/project/target.md +++ b/web/book/src/project/target.md @@ -51,6 +51,9 @@ additional dialects. - `sql.ansi` - `sql.bigquery` - `sql.snowflake` +- `sql.oracle` — very early; currently only ensures identifiers are quoted to + accommodate Oracle's case-folding rules. Most other language features fall + back to generic SQL and may not execute correctly against Oracle. ## Priority of targets