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

[CALCITE-6313] Add POWER function for PostgreSQL #3762

Merged
merged 1 commit into from May 14, 2024

Conversation

normanj-bitquill
Copy link
Contributor

  • The existing power function is moved to all non PostgreSQL libraries
  • The new power function is only for PostgreSQL
  • The new function returns a decimal if any argument is a decimal

@normanj-bitquill
Copy link
Contributor Author

normanj-bitquill commented Apr 16, 2024

In order to separate the POWER function for PostgreSQL and non-PostgreSQL dialects, the POWER function was moved to the SqlLibraryOperators class. This downgrades the POWER function from a standard function to a function from a library. This is problematic for things like SQRT which is a standard function and gets rewritten to a POWER expression.

Is there a more clean way to separate the POWER function so that the PostgreSQL implementation is able to return Decimal values in some cases?

@@ -559,15 +558,6 @@ static SqlOperatorTable operatorTableFor(SqlLibrary library) {
}

@Test void testArithmeticOperatorsFails() {
expr("^power(2,'abc')^")
Copy link
Contributor

Choose a reason for hiding this comment

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

why delete these tests? What happens to them? They look like good tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The POWER function is no longer available in SqlStdOperatorTable. The implementation to use depends on which library is active since PostgreSQL can use a different return type.

This test fails as it was since POWER is not in StdOperatorTable. Is there a way to specify the library to use for the test?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, see the operatorTableFor() function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

@@ -2301,17 +2301,6 @@ where false;

!ok

# [CALCITE-2447] POWER, ATAN2 functions fail with NoSuchMethodException
Copy link
Contributor

Choose a reason for hiding this comment

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

why delete this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The POWER function is no longer available in SqlStdOperatorTable. Is there any way of specifying a library to use here?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think there is, but the question is whether there should be a standard power function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I found where the ChainedSqlOperatorTable is created and was able to give the library operator table precedence over the standard operator table.

@@ -2006,7 +2006,7 @@ void checkPeriodPredicate(Checker checker) {
expr("1-2+3*4/5/6-7")
.ok("(((1 - 2) + (((3 * 4) / 5) / 6)) - 7)");
expr("power(2,3)")
.ok("POWER(2, 3)");
.ok("`POWER`(2, 3)");
Copy link
Contributor

Choose a reason for hiding this comment

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

these quotes look suspicious

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will end up going through here:
https://github.com/apache/calcite/blob/main/core/src/main/java/org/apache/calcite/sql/SqlUtil.java#L393

and only look in SqlStdOperatorTable for the function.

Copy link
Contributor

Choose a reason for hiding this comment

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

Then it's related to my previous question: should there be a variant of this function in the standard operator table?
If not, I guess this is fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is it possible to have a power function in the standard operator table and still have an override for PostgreSQL that is able to return a decimal in some cases?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know the answer to this question. But I know that Calcite can load multiple libraries, and I believe a function will be resolved by trying the libraries in order. I also am assuming that there is nothing special about the standard operator table. So if you load the postgres operator table first, perhaps the right POWER will be used?

A quick experiment should be able answer this question.

If this works, we should probably document that the right way to implement a dialect is to load the dialect specific operator table first.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I found where the ChainedSqlOperatorTable is created and was able to give the library operator table precedence over the standard operator table.

With this change, no changes are needed to existing tests.

@normanj-bitquill normanj-bitquill force-pushed the calcite-6313 branch 5 times, most recently from 857f16d to d2cdb89 Compare April 24, 2024 18:09
@mihaibudiu
Copy link
Contributor

In general, until the changes are approved I would recommend adding new commits instead of force-pushing. It makes it easier for reviewers to see what's new. Then you can squash when the PR is approved.

@@ -117,8 +117,7 @@ private SqlOperatorTable create(ImmutableSet<SqlLibrary> librarySet) {
SqlOperatorTable operatorTable = SqlOperatorTables.of(list);
if (standard) {
operatorTable =
SqlOperatorTables.chain(SqlStdOperatorTable.instance(),
operatorTable);
SqlOperatorTables.chain(operatorTable, SqlStdOperatorTable.instance());
Copy link
Contributor

Choose a reason for hiding this comment

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

This may cause problems for other people. Ideally you want to do this just for your tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Understood. I'll take a look.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This has been fixed. The only changes needed now are in the unit test itself. I setup the operator table there such that PostgreSQL is first.

Copy link
Contributor

@mihaibudiu mihaibudiu left a comment

Choose a reason for hiding this comment

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

The second commit should have a descriptive name, e.g., "only update loading library order for tests." But that is moot now, since I think this is ready for merging, so the next step is to squash the commits. We can't merge this until 1.37 is released, though.

@mihaibudiu mihaibudiu added the LGTM-will-merge-soon Overall PR looks OK. Only minor things left. label Apr 24, 2024
* The existing power function is moved to all non PostgreSQL libraries
* The new power function is only for PostgreSQL
* The new function returns a decimal if any argument is a decimal
Copy link

sonarcloud bot commented Apr 26, 2024

@mihaibudiu mihaibudiu merged commit 5ab4397 into apache:main May 14, 2024
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
LGTM-will-merge-soon Overall PR looks OK. Only minor things left.
Projects
None yet
2 participants