Skip to content

Preserve quotedness in QualifiedName#19827

Closed
imjalpreet wants to merge 1 commit into
prestodb:masterfrom
imjalpreet:preserveQuotedness
Closed

Preserve quotedness in QualifiedName#19827
imjalpreet wants to merge 1 commit into
prestodb:masterfrom
imjalpreet:preserveQuotedness

Conversation

@imjalpreet

Copy link
Copy Markdown
Member

Presto doesn't maintain the quotedness of an identifier when using SqlQueryFormatter so it results in throwing parsing error if quoted table name is a reserved word

Test plan

Before this PR, presto throws an error when using a reserved keyword in a prepared statement or while creating a view.

presto:imjalpreet> create view group_view security invoker as select * from imjalpreet."group";

Query 20230530_141710_00001_fxwah failed: Formatted query does not parse: Query{queryBody=QuerySpecification{select=Select{distinct=false, selectItems=[*]}, from=Optional[Table{imjalpreet.group}], where=null, groupBy=Optional.empty, having=null, orderBy=Optional.empty, offset=null, limit=null}, orderBy=Optional.empty}

presto:imjalpreet> PREPARE stmt0 FROM select * from imjalpreet."group";

Query 20230530_142117_00003_fxwah failed: Formatted query does not parse: Query{queryBody=QuerySpecification{select=Select{distinct=false, selectItems=[*]}, from=Optional[Table{imjalpreet.group}], where=null, groupBy=Optional.empty, having=null, orderBy=Optional.empty, offset=null, limit=null}, orderBy=Optional.empty}

After this PR, queries runs successfully.

presto:imjalpreet> create view group_view security invoker as select * from imjalpreet."group";
CREATE VIEW

presto:imjalpreet> PREPARE stmt0 FROM select * from imjalpreet."group";
PREPARE
== RELEASE NOTES ==

General Changes
* Preserve table name quoting in the output of ``SHOW CREATE VIEW``.
* Fix failure when preparing statements or creating views that contain a quoted reserved word as a table name.

Cherry-pick of trinodb/trino#80

Presto doesn't maintain the quotedness of an identifier when
using SqlQueryFormatter so it results in throwing parsing error
if quoted table name is a reserved word
Co-authored-by: praveenkrishna <praveenkrishna@tutanota.com>
@imjalpreet imjalpreet requested a review from a team as a code owner June 8, 2023 15:05
@imjalpreet imjalpreet self-assigned this Jun 8, 2023
@imjalpreet imjalpreet requested a review from presto-oss June 8, 2023 15:05
@linux-foundation-easycla

Copy link
Copy Markdown

CLA Not Signed

@imjalpreet

Copy link
Copy Markdown
Member Author

@agrawalreetika Added the tests as mentioned in #19752

@imjalpreet imjalpreet requested a review from agrawalreetika June 8, 2023 15:07
@imjalpreet

Copy link
Copy Markdown
Member Author

@prestodb/committers Hi, can someone help with the review for this PR?

@rschlussel rschlussel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Last time we had this change, it needed to be reverted do to a bug in creating the qualified name for views. Can you check that the issue here is resolved and add a test #17446

private QualifiedName getQualifiedName(ShowCreate node, QualifiedObjectName objectName)
{
List<Identifier> parts = node.getName().getOriginalParts();
Identifier tableName = (parts.size() > 2) ? parts.get(2) : ((parts.size() > 1) ? parts.get(1) : parts.get(0));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can simplify to Identifier tableName = parts.get(parts.size() -1)

{
List<Identifier> parts = node.getName().getOriginalParts();
Identifier tableName = (parts.size() > 2) ? parts.get(2) : ((parts.size() > 1) ? parts.get(1) : parts.get(0));
Identifier schemaName = (parts.size() > 2) ? parts.get(1) : ((parts.size() > 1) ? parts.get(0) : new Identifier(objectName.getSchemaName()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Identifier schemaName = parts.size() > 1 ? : parts.get(parts.size() - 2) : new Identifier(objectName.getSchemaName())

@imjalpreet

Copy link
Copy Markdown
Member Author

@rschlussel I just had a look at the PR you mentioned above and I have already fixed the issue seen due to which it was reverted.

I have already added some tests to test this PR in AbstractTestDistributedQueries#testViewWithReservedKeywords. Let me know if you meant writing a test for generating qualified name for a view.

@rschlussel

Copy link
Copy Markdown
Contributor

@rschlussel I just had a look at the PR you mentioned above and I have already fixed the issue seen due to which it was reverted.

I have already added some tests to test this PR in AbstractTestDistributedQueries#testViewWithReservedKeywords. Let me know if you meant writing a test for generating qualified name for a view.

Thanks, I see now you've fixed it. I think we need the test to also run SHOW CREATE VIEW on the view that it created to exercise the codepath you fixed.

assetQuery("SELECT id\nFROM\n \"public\".\"order\"\"2\"\n");
}

private void assetQuery(String query)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

typo: asset -> assert, but maybe give this function a more descriptive name so you don't have to read the code for this function to understand what the test is doing, e.g. assertFormattedEqualsOriginal

@@ -76,7 +74,20 @@ public Identifier getField()
*/
public static QualifiedName getQualifiedName(DereferenceExpression expression)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I know you aren't changing the signature here, but in Presto we usually avoid returning nulls anywhere, and prefer explicitly using optionals if something might not be there. Looks like there are a bunch of usages of this function that aren't checking for null return values. Would be nice as a separate commit to switch to using optional instead of returning null to be sure this is used correctly throughout.

{
assetQuery("SELECT id\nFROM\n public.orders\n");
assetQuery("SELECT id\nFROM\n \"public\".\"order\"\n");
assetQuery("SELECT id\nFROM\n \"public\".\"order\"\"2\"\n");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what kind of format is this last test. looks like

SELECT id FROM "public"."order""2"?

Can you add a test for a three part schema?
Also can you add a test where only one or two parts of the qualified name are quoted

@agrawalreetika

Copy link
Copy Markdown
Member

This is already covered as part of #25528

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants