Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve round scalar function unparsing for Postgres #12744

Merged
merged 2 commits into from
Oct 6, 2024

Conversation

sgrebnov
Copy link
Member

@sgrebnov sgrebnov commented Oct 3, 2024

Which issue does this PR close?

PR improves unparsing to generate valid sql for Postgres and round scalar function by enforcing NUMERIC data type for it.

Postgres requires NUMERIC data type for round as it does not support Float arguments that are produced by default. Right now unparsed sql fails with the error "Query Error function round(double precision, integer) does not exist" if round is used.

https://www.postgresql.org/docs/17/functions-math.html

round ( v numeric, s integer ) → numeric
Rounds v to s decimal places. Ties are broken by rounding away from zero.
round(42.4382, 2) → 42.44
round(1234.56, -1) → 1230
-- SQL Error [42883]: ERROR: function round(double precision, integer) does not exist
select round(CAST(1.23456 AS float), 2)

-- 1.23
select round(CAST(1.23456 AS numeric), 2)

What changes are included in this PR?

  1. Support for dialects to override scalar functions unparsing via exposing scalar_function_to_sql_overrides
  2. Refactored date_part scalar function unparsing to rely on scalar_function_to_sql_overrides approach above
  3. Added logic to enforce NUMERIC for round scalar function unparsing for Postgres

Are these changes tested?

Unit test for round function unparsing for default dialect and Postgres

Are there any user-facing changes?

Unaprser will generate valid sql for round scalar function for Postgres dialect

…#34)

Includes initial support for dialects to override scalar functions unparsing
@github-actions github-actions bot added the sql SQL Planner label Oct 3, 2024
@sgrebnov sgrebnov changed the title Postgres: enforce required NUMERIC type for round scalar functio Improve round scalar function unparsing for Postgres Oct 3, 2024
if let Some(ast::FunctionArg::Unnamed(ast::FunctionArgExpr::Expr(expr))) =
args.first_mut()
{
if let ast::Expr::Cast { data_type, .. } = expr {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternative approach considered was removing casting altogether, but it seems less robust as the argument can be a complex expression.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than checking after unparsing, maybe this code could check before unparsing -- as in get the type of Expr in args[0] and use that to decide if a cast is needed

Copy link
Member Author

@sgrebnov sgrebnov Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good idea 👍. Unfortunately, we can't enforce NUMERIC before unparsing, as we operate on the Arrow DataType level, which includes FLOAT, DOUBLE, etc., and these types will be converted to FLOAT, DECIMAL, or DOUBLE PRECISION types and we can't enforce NUMERIC before unparsing. Since we require to do unparsing anyway, I think it is better to have all the relevant logic in the same place—right after unparsing.

Copy link
Contributor

@alamb alamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me -- thank you @sgrebnov

@@ -108,6 +113,15 @@ pub trait Dialect: Send + Sync {
fn supports_column_alias_in_table_alias(&self) -> bool {
true
}

fn scalar_function_to_sql_overrides(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Could you please add documentation here explaining what this function does / is used for?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alamb - thank you for pointing to this, missed this part, documented the scalar_function_to_sql_overrides

if let Some(ast::FunctionArg::Unnamed(ast::FunctionArgExpr::Expr(expr))) =
args.first_mut()
{
if let ast::Expr::Cast { data_type, .. } = expr {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than checking after unparsing, maybe this code could check before unparsing -- as in get the type of Expr in args[0] and use that to decide if a cast is needed

@@ -530,87 +520,6 @@ impl Unparser<'_> {
})
}

fn scalar_function_to_sql_overrides(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a nice refactor

@@ -2428,4 +2343,39 @@ mod tests {
assert_eq!(actual, expected);
}
}

#[test]
fn test_round_scalar_fn_to_expr() -> Result<()> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

@goldmedal goldmedal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @sgrebnov It's a nice improvement. scalar_function_to_sql_overrides would be very helpful. I agree with @alamb's comment. It's better to add some doc for this method. Others LGTM. 👍

Copy link
Contributor

@phillipleblanc phillipleblanc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Sergei!

Sergei and I worked together on this PR in our fork before he raised this PR: spiceai#34

I wasn't happy with how we were handle differences in function unparsing as part of the core datafusion code. I initially thought we shouldn't deal with it at all in this code, and perform another pass over the SQL AST in our own codebase. But I came around to the idea that the functions in a database system is part of the dialect, so it does make sense to handle them.

However, I wanted an approach that would allow people to implement their own function unparsing for custom dialects, without requiring changes to the core datafusion code. I thought maybe having a function registry on the dialect trait would be useful (i.e. register a function by name, along with how to unparse it).

The approach Sergei came up with here is pretty elegant imo and still simple. I expect once we get into the 10s of functions we need to customize, it might start to get unwieldy and we may consider refactoring it further. But for now I'm happy with this approach.

@goldmedal
Copy link
Contributor

However, I wanted an approach that would allow people to implement their own function unparsing for custom dialects, without requiring changes to the core datafusion code. I thought maybe having a function registry on the dialect trait would be useful (i.e. register a function by name, along with how to unparse it).

The approach Sergei came up with here is pretty elegant imo and still simple. I expect once we get into the 10s of functions we need to customize, it might start to get unwieldy and we may consider refactoring it further. But for now I'm happy with this approach.

Hi @phillipleblanc,

I believe this PR offers a valuable improvement by allowing a DataFusion function to be unparsed to another dialect's function. However, in my project, WrenAI, we face a similar scenario with custom functions used for unparsing. Our goal is to parse functions that are not part of DataFusion into the plan and then unparse them back to SQL.

I'm not entirely sure how Spiceai operates, but I assume you also perform some form of full pushdown things, correct? I'd like to share our use case with you.

In WrenAI, our process is as follows:

  • Parse SQL into a Logical Plan
  • Apply rewrite rules
  • Unparse the rewritten plan back to DataFusion SQL
  • Transpile the DataFusion SQL into other database SQL dialects using ibis-project and sqlglot

The challenge lies in parsing custom functions that aren't part of DataFusion's core into the logical plan. To address this, we've implemented a UDF called ByPassScalarUDF specifically for unparsing purposes.

You can view the implementation here:
https://github.com/Canner/wren-engine/blob/861f978df3438a1ba01d3518101de59bcffd1da8/wren-modeling-rs/core/src/mdl/function.rs#L15

At program startup, we can register the UDFs like this:

let ctx = SessionContext::new();
ctx.register_udf(ScalarUDF::new_from_impl(ByPassScalarUDF::new("date_diff", "bigint")));
ctx.register_udf(ScalarUDF::new_from_impl(ByPassScalarUDF::new("year", "bigint")));

Since this implementation only requires the function name and return type, we can easily define them in a file and register them from there. Once registered, the unparser can correctly output the function's SQL.

@sgrebnov
Copy link
Member Author

sgrebnov commented Oct 4, 2024

@alamb, @goldmedal, @phillipleblanc - thank you for review, documented scalar_function_to_sql_overrides , really missed that part - will do better next time :)

@alamb alamb merged commit 9b492c6 into apache:main Oct 6, 2024
24 checks passed
@alamb
Copy link
Contributor

alamb commented Oct 6, 2024

THanks again everyone -- if there are more improvements to be made, let's make them as follow on PRs!

@phillipleblanc phillipleblanc deleted the sgrebnov/pg-round-unparsing branch October 6, 2024 14:41
alamb added a commit that referenced this pull request Oct 8, 2024
* Add support for external tables with qualified names (#12645)

* Make  support schemas

* Set default name to table

* Remove print statements and stale comment

* Add tests for create table

* Fix typo

* Update datafusion/sql/src/statement.rs

Co-authored-by: Jonah Gao <[email protected]>

* convert create_external_table to objectname

* Add sqllogic tests

* Fix failing tests

---------

Co-authored-by: Jonah Gao <[email protected]>

* Fix Regex signature types (#12690)

* Fix Regex signature types

* Uncomment the shared tests in string_query.slt.part and removed tests copies everywhere else

* Test `LIKE` and `MATCH` with flags; Remove new tests from regexp.slt

* Refactor `ByteGroupValueBuilder` to use `MaybeNullBufferBuilder` (#12681)

* Fix malformed hex string literal in docs (#12708)

* Simplify match patterns in coercion rules (#12711)

Remove conditions where unnecessary.
Refactor to improve readability.

* Remove aggregate functions dependency on frontend (#12715)

* Remove aggregate functions dependency on frontend

DataFusion is a SQL query engine and also a reusable library for
building query engines. The core functionality should not depend on
frontend related functionalities like `sqlparser` or `datafusion-sql`.

* Remove duplicate license header

* Minor: Remove clone in `transform_to_states` (#12707)

* rm clone

Signed-off-by: jayzhan211 <[email protected]>

* fmt

Signed-off-by: jayzhan211 <[email protected]>

---------

Signed-off-by: jayzhan211 <[email protected]>

* Refactor tests for union sorting properties, add tests for unions and constants (#12702)

* Refactor tests for union sorting properties

* update doc test

* Undo import reordering

* remove unecessary static lifetimes

* Fix: support Qualified Wildcard in count aggregate function (#12673)

* Reduce code duplication in `PrimitiveGroupValueBuilder` with const generics (#12703)

* Reduce code duplication in `PrimitiveGroupValueBuilder` with const generics

* Fix docs

* Disallow duplicated qualified field names (#12608)

* Disallow duplicated qualified field names

* Fix tests

* Optimize base64/hex decoding by pre-allocating output buffers (~2x faster) (#12675)

* add bench

* replace macro with generic function

* remove duplicated code

* optimize base64/hex decode

* Allow DynamicFileCatalog support to query partitioned file (#12683)

* support to query partitioned table for dynamic file catalog

* cargo clippy

* split partitions inferring to another function

* Support `LIMIT` Push-down logical plan optimization for `Extension` nodes (#12685)

* Update trait `UserDefinedLogicalNodeCore`

Signed-off-by: Austin Liu <[email protected]>

* Update corresponding interface

Signed-off-by: Austin Liu <[email protected]>

Add rewrite rule for `push-down-limit` for `Extension`

Signed-off-by: Austin Liu <[email protected]>

* Add rewrite rule for `push-down-limit` for `Extension` and tests

Signed-off-by: Austin Liu <[email protected]>

* Update corresponding interface

Signed-off-by: Austin Liu <[email protected]>

* Reorganize to match guard

Signed-off-by: Austin Liu <[email protected]>

* Clena up

Signed-off-by: Austin Liu <[email protected]>

Clean up

Signed-off-by: Austin Liu <[email protected]>

---------

Signed-off-by: Austin Liu <[email protected]>

* Fix AvroReader: Add union resolving for nested struct arrays (#12686)

* Add union resolving for nested struct arrays

* Add test

* Change test

* Reproduce index error

* fmt

---------

Co-authored-by: Andrew Lamb <[email protected]>

* Adds macros for creating `WindowUDF` and `WindowFunction` expression (#12693)

* Adds macro for udwf singleton

* Adds a doc comment parameter to macro

* Add doc comment for `create_udwf` macro

* Uses default constructor

* Update `Cargo.lock` in `datafusion-cli`

* Fixes: expand `$FN_NAME` in doc strings

* Adds example for macro usage

* Renames macro

* Improve doc comments

* Rename udwf macro

* Minor: doc copy edits

* Adds macro for creating fluent-style expression API

* Adds support for 1 or more parameters in expression function

* Rewrite doc comments

* Rename parameters

* Minor: formatting

* Adds doc comment for `create_udwf_expr` macro

* Improve example docs

* Hides extraneous code in doc comments

* Add a one-line readme

* Adds doc test assertions + minor formatting fixes

* Adds common macro for defining user-defined window functions

* Adds doc comment for `define_udwf_and_expr`

* Defines `RowNumber` using common macro

* Add usage example for common macro

* Adds usage for custom constructor

* Add examples for remaining patterns

* Improve doc comments for usage examples

* Rewrite inner line docs

* Rewrite `create_udwf_expr!` doc comments

* Minor doc improvements

* Fix doc test and usage example

* Add inline comments for macro patterns

* Minor: change doc comment in example

* Support unparsing plans with both Aggregation and Window functions (#12705)

* Support unparsing plans with both Aggregation and Window functions (#35)

* Fix unparsing for aggregation grouping sets

* Add test for grouping set unparsing

* Update datafusion/sql/src/unparser/utils.rs

Co-authored-by: Jax Liu <[email protected]>

* Update datafusion/sql/src/unparser/utils.rs

Co-authored-by: Jax Liu <[email protected]>

* Update

* More tests

---------

Co-authored-by: Jax Liu <[email protected]>

* Fix strpos invocation with dictionary and null (#12712)

In 1b3608d `strpos` signature was
modified to indicate it supports dictionary as input argument, but the
invoke method doesn't support them.

* docs: Update DataFusion introduction to clarify that DataFusion does provide an "out of the box" query engine (#12666)

* Update DataFusion introduction to show that DataFusion offers packaged versions for end users

* change order

* Update README.md

Co-authored-by: Andrew Lamb <[email protected]>

* refine wording and update user guide for consistency

* prettier

---------

Co-authored-by: Andrew Lamb <[email protected]>

* Framework for generating function docs from embedded code documentation (#12668)

* Initial work on #12432 to allow for generation of udf docs from embedded documentation in the code

* Add missing license header.

* Fixed examples.

* Fixing a really weird RustRover/wsl ... something. No clue what happened there.

* permission change

* Cargo fmt update.

* Refactored Documentation to allow it to be used in a const.

* Add documentation for syntax_example

* Refactoring Documentation based on PR feedback.

* Cargo fmt update.

* Doc update

* Fixed copy/paste error.

* Minor text updates.

---------

Co-authored-by: Andrew Lamb <[email protected]>

* Add IMDB(JOB) Benchmark [2/N] (imdb queries) (#12529)

* imdb dataset

* cargo fmt

* Add 113 queries for IMDB(JOB)

Signed-off-by: Austin Liu <[email protected]>

* Add `get_query_sql` from `query_id` string

Signed-off-by: Austin Liu <[email protected]>

* Fix CSV reader & Remove Parquet partition

Signed-off-by: Austin Liu <[email protected]>

* Add benchmark IMDB runner

Signed-off-by: Austin Liu <[email protected]>

* Add `run_imdb` script

Signed-off-by: Austin Liu <[email protected]>

* Add checker for imdb option

Signed-off-by: Austin Liu <[email protected]>

* Add SLT for IMDB

Signed-off-by: Austin Liu <[email protected]>

* Fix `get_query_sql()` for CI roundtrip test

Signed-off-by: Austin Liu <[email protected]>

Fix `get_query_sql()` for CI roundtrip test

Signed-off-by: Austin Liu <[email protected]>

Fix `get_query_sql()` for CI roundtrip test

Signed-off-by: Austin Liu <[email protected]>

* Clean up

Signed-off-by: Austin Liu <[email protected]>

* Add missing license

Signed-off-by: Austin Liu <[email protected]>

* Add IMDB(JOB) queries `2b` to `5c`

Signed-off-by: Austin Liu <[email protected]>

* Add `INCLUDE_IMDB` in CI verify-benchmark-results

Signed-off-by: Austin Liu <[email protected]>

* Prepare IMDB dataset

Signed-off-by: Austin Liu <[email protected]>

Prepare IMDB dataset

Signed-off-by: Austin Liu <[email protected]>

* use uint as id type

* format

* Seperate `tpch` and `imdb` benchmarking CI jobs

Signed-off-by: Austin Liu <[email protected]>

Fix path

Signed-off-by: Austin Liu <[email protected]>

Fix path

Signed-off-by: Austin Liu <[email protected]>

Remove `tpch` in `imdb` benchmark

Signed-off-by: Austin Liu <[email protected]>

* Remove IMDB(JOB) slt in CI

Signed-off-by: Austin Liu <[email protected]>

Remove IMDB(JOB) slt in CI

Signed-off-by: Austin Liu <[email protected]>

---------

Signed-off-by: Austin Liu <[email protected]>
Co-authored-by: DouPache <[email protected]>

* Minor: avoid clone while calculating union equivalence properties (#12722)

* Minor: avoid clone while calculating union equivalence properties

* Update datafusion/physical-expr/src/equivalence/properties.rs

* fmt

* Simplify streaming_merge function parameters (#12719)

* simplify streaming_merge function parameters

* revert test change

* change StreamingMergeConfig into builder pattern

* Fix links on docs index page (#12750)

* Provide field and schema metadata missing on cross joins, and union with null fields. (#12729)

* test: reproducer for missing schema metadata on cross join

* fix: pass thru schema metadata on cross join

* fix: preserve metadata when transforming to view types

* test: reproducer for missing field metadata in left hand NULL field of union

* fix: preserve field metadata from right side of union

* chore: safe indexing

* Minor: Update string tests for strpos (#12739)

* Apply `type_union_resolution` to array and values (#12753)

* cleanup make array coercion rule

Signed-off-by: jayzhan211 <[email protected]>

* change to type union resolution

Signed-off-by: jayzhan211 <[email protected]>

* change value too

Signed-off-by: jayzhan211 <[email protected]>

* fix tpyo

Signed-off-by: jayzhan211 <[email protected]>

---------

Signed-off-by: jayzhan211 <[email protected]>

* Add `DocumentationBuilder::with_standard_argument` to reduce copy/paste (#12747)

* Add `DocumentationBuilder::with_standard_expression` to reduce copy/paste

* fix doc

* fix standard argument

* Update docs

* Improve documentation to explain what is different

* fix `equal_to` in `PrimitiveGroupValueBuilder` (#12758)

* fix `equal_to` in `PrimitiveGroupValueBuilder`.

* fix typo.

* add uts.

* reduce calling of `is_null`.

* Minor: doc how field name is to be set (#12757)

* Fix `equal_to` in `ByteGroupValueBuilder` (#12770)

* Fix `equal_to` in `ByteGroupValueBuilder`

* refactor null_equal_to

* Update datafusion/physical-plan/src/aggregates/group_values/group_column.rs

* Allow simplification even when nullable (#12746)

The nullable requirement seem to have been added in #1401 but as far as
I can tell they are not needed for these 2 cases.

I think this can be shown using this truth table: (generated using
datafusion-cli without this patch)
```
> CREATE TABLE t (v BOOLEAN) as values (true), (false), (NULL);
> select t.v, t2.v, t.v AND (t.v OR t2.v), t.v OR (t.v AND t2.v) from t cross join t as t2;
+-------+-------+---------------------+---------------------+
| v     | v     | t.v AND t.v OR t2.v | t.v OR t.v AND t2.v |
+-------+-------+---------------------+---------------------+
| true  | true  | true                | true                |
| true  | false | true                | true                |
| true  |       | true                | true                |
| false | true  | false               | false               |
| false | false | false               | false               |
| false |       | false               | false               |
|       | true  |                     |                     |
|       | false |                     |                     |
|       |       |                     |                     |
+-------+-------+---------------------+---------------------+
```

And it seems Spark applies both of these and DuckDB applies only the
first one.

* Fix unnest conjunction with selecting wildcard expression (#12760)

* fix unnest statement with wildcard expression

* add commnets

* Improve `round` scalar function unparsing for Postgres (#12744)

* Postgres: enforce required `NUMERIC` type for `round` scalar function (#34)

Includes initial support for dialects to override scalar functions unparsing

* Document scalar_function_to_sql_overrides fn

* Fix stack overflow calculating projected orderings (#12759)

* Fix stack overflow calculating projected orderings

* fix docs

* Port / Add Documentation for `VarianceSample` and `VariancePopulation` (#12742)

* Upgrade arrow/parquet to `53.1.0` / fix clippy (#12724)

* Update to arrow/parquet 53.1.0

* Update some API

* update for changed file sizes

* Use non deprecated APIs

* Use ParquetMetadataReader from @etseidl

* remove upstreamed implementation

* Update CSV schema

* Use upstream is_null and is_not_null kernels

* feat: add support for Substrait ExtendedExpression (#12728)

* Add support for serializing and deserializing Substrait ExtendedExpr message

* Address clippy reviews

* Reuse existing rename method

* Transformed::new_transformed: Fix documentation formatting (#12787)

Co-authored-by: Andrew Lamb <[email protected]>

* fix: Correct results for grouping sets when columns contain nulls (#12571)

* Fix grouping sets behavior when data contains nulls

* PR suggestion comment

* Update new test case

* Add grouping_id to the logical plan

* Add doc comment next to INTERNAL_GROUPING_ID

* Fix unparsing of Aggregate with grouping sets

---------

Co-authored-by: Andrew Lamb <[email protected]>

* Migrate documentation for all string functions from scalar_functions.md to code  (#12775)

* Added documentation for string and unicode functions.

* Fixed issues with aliases.

* Cargo fmt.

* Minor doc fixes.

* Update docs for var_pop/samp

---------

Co-authored-by: Andrew Lamb <[email protected]>

* Account for constant equivalence properties in union, tests (#12562)

* Minor: clarify comment about empty dependencies (#12786)

* Introduce Signature::String and return error if  input of `strpos` is integer (#12751)

* fix sig

Signed-off-by: jayzhan211 <[email protected]>

* fix

Signed-off-by: jayzhan211 <[email protected]>

* fix error

Signed-off-by: jayzhan211 <[email protected]>

* fix all signature

Signed-off-by: jayzhan211 <[email protected]>

* fix all signature

Signed-off-by: jayzhan211 <[email protected]>

* change default type

Signed-off-by: jayzhan211 <[email protected]>

* clippy

Signed-off-by: jayzhan211 <[email protected]>

* fix docs

Signed-off-by: jayzhan211 <[email protected]>

* rm deadcode

Signed-off-by: jayzhan211 <[email protected]>

* cleanup

Signed-off-by: jayzhan211 <[email protected]>

* cleanup

Signed-off-by: jayzhan211 <[email protected]>

* rm test

Signed-off-by: jayzhan211 <[email protected]>

---------

Signed-off-by: jayzhan211 <[email protected]>

* Minor: improve docs on MovingMin/MovingMax (#12790)

* Add slt tests (#12721)

---------

Signed-off-by: jayzhan211 <[email protected]>
Signed-off-by: Austin Liu <[email protected]>
Co-authored-by: OussamaSaoudi <[email protected]>
Co-authored-by: Jonah Gao <[email protected]>
Co-authored-by: Dmitrii Blaginin <[email protected]>
Co-authored-by: Andrew Lamb <[email protected]>
Co-authored-by: Tomoaki Kawada <[email protected]>
Co-authored-by: Piotr Findeisen <[email protected]>
Co-authored-by: Jay Zhan <[email protected]>
Co-authored-by: HuSen <[email protected]>
Co-authored-by: Emil Ejbyfeldt <[email protected]>
Co-authored-by: Simon Vandel Sillesen <[email protected]>
Co-authored-by: Jax Liu <[email protected]>
Co-authored-by: Austin Liu <[email protected]>
Co-authored-by: JonasDev1 <[email protected]>
Co-authored-by: jcsherin <[email protected]>
Co-authored-by: Sergei Grebnov <[email protected]>
Co-authored-by: Andy Grove <[email protected]>
Co-authored-by: Bruce Ritchie <[email protected]>
Co-authored-by: DouPache <[email protected]>
Co-authored-by: mertak-synnada <[email protected]>
Co-authored-by: Bryce Mecum <[email protected]>
Co-authored-by: wiedld <[email protected]>
Co-authored-by: kamille <[email protected]>
Co-authored-by: Weston Pace <[email protected]>
Co-authored-by: Val Lorentz <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sql SQL Planner
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants