-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Extend syntax for Dynamic Catalogs #22188
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
base: master
Are you sure you want to change the base?
Conversation
@martint @dain @kokosing @nineinchnick @SemionPar please review |
@@ -155,6 +162,7 @@ statement | |||
| EXPLAIN ANALYZE VERBOSE? statement #explainAnalyze | |||
| SHOW CREATE TABLE qualifiedName #showCreateTable | |||
| SHOW CREATE SCHEMA qualifiedName #showCreateSchema | |||
| SHOW CREATE CATALOG identifier #showCreateCatalog |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation exposes all properties even if it's marked as @ConfigHidden
or @ConfigSecuritySensitive
. I think we should hide or redact such properties.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have removed SHOW CREATE CATALOG
from this PR. It should be possible to re-add it once the following are merged:
- Add connector SPI for returning redactable properties #24562
- Redact sensitive information in catalog queries #24563
I'm not sure if we want to introduce CREATE CATALOG LIKE
(at least not at this stage). One question that comes to mind is how to define access rules for it. According to the SQL specification for CREATE TABLE LIKE
:
If a <like clause> is contained in a <table definition>, then the applicable privileges for A shall include
SELECT privilege on the table identified in the <like clause>.
The issue is that we don’t have a SELECT privilege for catalogs.
I’m also not aware of any databases that provide CREATE ... LIKE
functionality for anything other than tables. This makes it difficult to infer whether there’s a common approach we could adopt in this scenario.
core/trino-grammar/src/main/antlr4/io/trino/grammar/sql/SqlBase.g4
Outdated
Show resolved
Hide resolved
This pull request has gone a while without any activity. Tagging the Trino developer relations team: @bitsondatadev @colebow @mosabua |
I am adding the stale-ignore label under the assumption that you are still driving this PR to completion @ssheikin |
Session session = stateMachine.getSession(); | ||
|
||
accessControl.checkCanRenameCatalog(session.toSecurityContext(), statement.getSource().getValue(), statement.getTarget().getValue()); | ||
|
||
catalogManager.renameCatalog(new CatalogName(statement.getSource().getValue()), new CatalogName(statement.getTarget().getValue())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you omit lowercase intentionally?
trino> CREATE CATALOG test USING memory;
CREATE CATALOG
trino> ALTER CATALOG test RENAME TO TEST;
RENAME CATALOG
trino> show catalogs;
Catalog
---------
TEST
memory
system
tpch
(4 rows)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it was unintentional. I updated it to match how other catalog statements work.
93954a1
to
315ed4d
Compare
Current status of this PR: it will no longer include |
I have updated the description |
core/trino-parser/src/test/java/io/trino/sql/parser/TestSqlParser.java
Outdated
Show resolved
Hide resolved
createCatalogLikeInternal(catalogName, newCatalogName, ImmutableMap.of()); | ||
catalogStore.removeCatalog(catalogName); | ||
activeCatalogs.remove(catalogName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how do we ensure this is "transactional"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a bug that caused activeCatalogs
to be updated even when persisting the catalog specification failed. I’ve fixed this.
Currently, I see one problematic scenario:
catalogStore.addOrReplaceCatalog(newCatalog)
succeeds.catalogStore.removeCatalog(oldCatalog)
fails.
If this happens, we end up with two catalogs, and the only way to recover is to manually DROP
the old one.
To address this, we might need to extend the SPI by adding CatalogStore.replace(oldCatalog, newCatalog)
and requiring implementations to perform this operation transactionally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the replace would probably also allow implementing ALTER CATALOG ... RENAME
properly instead of as DROP
+ CREATE
.
Let's skip for now and discuss it later.
core/trino-main/src/test/java/io/trino/execution/TestRenameCatalogTask.java
Outdated
Show resolved
Hide resolved
plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDynamicCatalogsSql.java
Show resolved
Hide resolved
/** | ||
* Check if identity is allowed to set properties to the specified catalog. | ||
* | ||
* @throws AccessDeniedException if not allowed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If any of the listed properties are not allowed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that this follows the pattern used for other methods in this file. I believe the idea is that this exception is thrown when accessing a given resource is not allowed.
core/trino-parser/src/main/java/io/trino/sql/tree/RenameCatalog.java
Outdated
Show resolved
Hide resolved
core/trino-parser/src/test/java/io/trino/sql/parser/TestSqlParser.java
Outdated
Show resolved
Hide resolved
core/trino-main/src/main/java/io/trino/connector/CoordinatorDynamicCatalogManager.java
Outdated
Show resolved
Hide resolved
throw new TrinoException(ALREADY_EXISTS, format("Catalog '%s' already exists", newCatalogName)); | ||
} | ||
|
||
createCatalogLikeInternal(catalogName, newCatalogName, ImmutableMap.of()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is rename modeled as "clone the catalog into a new one, drop the old one" vs adding proper support for renaming catalogs? I'm concerned about the impact of any state that needs to be dropped and re-created, caches, etc., that would otherwise not be necessary to manage with a proper rename.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renaming requires the following steps:
- Creating a new connector instance, with the catalog name passed to
ConnectorFactory::create
. - Updating in-memory data structures in
CoordinatorDynamicCatalogManager
(activeCatalogs
andallCatalogs
). - Persisting the updated catalog name and version via
CatalogStore
. - Marking the old catalog as inactive and eventually pruning it.
It looks like this is exactly what clone and drop do. Do you think there's a less invasive way to implement rename?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. It's not ideal, though. It shouldn't be necessary to re-create the catalog just to give it a new name.
I guess the underlying problem is that ConnectorFactory::create
takes a name. We should look into (for a future improvement) what it would take to decouple the instance from its name so that the name is just an entry in the catalog maps.
core/trino-main/src/test/java/io/trino/execution/TestRenameCatalogTask.java
Outdated
Show resolved
Hide resolved
core/trino-main/src/test/java/io/trino/execution/TestSetCatalogPropertiesTask.java
Outdated
Show resolved
Hide resolved
plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDynamicCatalogsSql.java
Outdated
Show resolved
Hide resolved
plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDynamicCatalogsSql.java
Outdated
Show resolved
Hide resolved
315ed4d
to
aba00a2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've addressed all the comments. Along the way, I discovered two bugs that should now be fixed:
- Previously, duplicated properties in
ALTER CATALOG ... SET PROPERTIES
caused an exception that could expose potentially security-sensitive property values. Now, only the last value is used, matching the behavior ofCREATE CATALOG
andALTER TABLE ... SET PROPERTIES
. - The in-memory state (
activeCatalogs
) was being updated even when persisting the catalog specification failed. Now, it is updated only when the correspondingCatalogStore
operation succeeds.
/** | ||
* Check if identity is allowed to set properties to the specified catalog. | ||
* | ||
* @throws AccessDeniedException if not allowed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that this follows the pattern used for other methods in this file. I believe the idea is that this exception is thrown when accessing a given resource is not allowed.
throw new TrinoException(ALREADY_EXISTS, format("Catalog '%s' already exists", newCatalogName)); | ||
} | ||
|
||
createCatalogLikeInternal(catalogName, newCatalogName, ImmutableMap.of()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renaming requires the following steps:
- Creating a new connector instance, with the catalog name passed to
ConnectorFactory::create
. - Updating in-memory data structures in
CoordinatorDynamicCatalogManager
(activeCatalogs
andallCatalogs
). - Persisting the updated catalog name and version via
CatalogStore
. - Marking the old catalog as inactive and eventually pruning it.
It looks like this is exactly what clone and drop do. Do you think there's a less invasive way to implement rename?
} | ||
} | ||
|
||
private CatalogConnector createCatalogLikeInternal(CatalogName oldCatalogName, CatalogName catalogName, Map<String, Optional<String>> properties) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've inlined this. The logic for rename and alter differs slightly, and I believe it's easier to follow the flow of these operations when all the steps are in one place.
createCatalogLikeInternal(catalogName, newCatalogName, ImmutableMap.of()); | ||
catalogStore.removeCatalog(catalogName); | ||
activeCatalogs.remove(catalogName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a bug that caused activeCatalogs
to be updated even when persisting the catalog specification failed. I’ve fixed this.
Currently, I see one problematic scenario:
catalogStore.addOrReplaceCatalog(newCatalog)
succeeds.catalogStore.removeCatalog(oldCatalog)
fails.
If this happens, we end up with two catalogs, and the only way to recover is to manually DROP
the old one.
To address this, we might need to extend the SPI by adding CatalogStore.replace(oldCatalog, newCatalog)
and requiring implementations to perform this operation transactionally.
core/trino-parser/src/test/java/io/trino/sql/parser/TestSqlParser.java
Outdated
Show resolved
Hide resolved
plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDynamicCatalogsSql.java
Show resolved
Hide resolved
db7c4b6
to
c3cc7db
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of minor comments.
Also, you should squash the first and second commits. Otherwise, the first commit is "broken", since there's no handling of the new statements in the analyzer. Either, it should fail with a proper error saying "RENAME not yet supported" or implement the functionality.
core/trino-main/src/main/java/io/trino/connector/CoordinatorDynamicCatalogManager.java
Outdated
Show resolved
Hide resolved
core/trino-main/src/main/java/io/trino/connector/CoordinatorDynamicCatalogManager.java
Outdated
Show resolved
Hide resolved
core/trino-main/src/test/java/io/trino/execution/TestRenameCatalogTask.java
Outdated
Show resolved
Hide resolved
c3cc7db
to
fb94819
Compare
I've addressed the latest comments. |
Co-authored-by: Jan Waś <[email protected]>
- RENAME - SET PROPERTIES
fb94819
to
b76977a
Compare
@martint Could you please take a look? I addressed your recent comments. |
This will also need docs before merge. Please work with @jhlodin and myself to get that added here or in a separate PR. |
Description
RENAME
,SET PROPERTIES
implementedcatalog owner
is not supported yet.catalog comment
is not supported yet.Additional context and related issues
Trino epic #12709
Release notes
( ) This is not user-visible or is docs only, and no release notes are required.
( ) Release notes are required. Please propose a release note for me.
(x) Release notes are required, with the following suggested text: