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
Support COMMENT ON TABLE statement #200
Conversation
There's no equivalent functionality in the standard, but this syntax is fairly low risk with respect to future incompatibilities due to being a top-level statement that doesn't interact with anything else. While the syntax is not great (it's not consistent with every other operation on table metadata), it's similar to what Oracle and Postgres do, so let's stick with it. |
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.
Some initial comments
public void testCommentTable() | ||
{ | ||
// Accumulo connector currently does not support comment on table | ||
assertQueryFails("COMMENT ON TABLE orders IS 'hello'", "This connector does not support commenting tables"); |
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.
... does not support table comments ...
@@ -0,0 +1,22 @@ | |||
+============= | |||
COMMENT TABLE |
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'd refer to this just as "COMMENT". The current implementation only supports tables, but we might extend it in the future to support other object types like Postgres does (https://www.postgresql.org/docs/9.1/sql-comment.html)
@Override | ||
public String getName() | ||
{ | ||
return "COMMENT TABLE"; |
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.
Just "COMMENT"
* Check if identity is allowed to comment the specified table. | ||
* @throws io.prestosql.spi.security.AccessDeniedException if not allowed | ||
*/ | ||
void checkCanAddComment(TransactionId transactionId, Identity identity, QualifiedObjectName tableName); |
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'm not sure we want or need a dedicated access check for this operation. It should, generally, fall under "does the user have permission to update the table definition?".
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.
We don't have generic permissions like that. There are separate checks like checkCanAddColumns
, checkCanDropColumn
, checkCanRenameColumn
, checkCanRenameTable
, etc.
How about making this checkCanSetTableComment
?
import static com.google.common.base.MoreObjects.toStringHelper; | ||
import static java.util.Objects.requireNonNull; | ||
|
||
public final class CommentTable |
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'd make this a little more generic. I expect we'll be adding comments on other object types shortly after. It should be structured as
- Comment
- target: initially something that identifies a table, but eventually other types of entities, too. I'd make a new NamedObject that contains (type, name). Type can only be a table for now.
- comment: a string
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.
@martint My understanding is the suggestion means SqlBase.g4 also should be changed. Is it right?
Current:
| COMMENT ON TABLE qualifiedName IS string #commentTable
New:
| COMMENT ON commentObject qualifiedName IS string #comment
...
commentObject
: TABLE #commentTable
;
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.
No, the grammar is fine. Rather than introducing a literal object, we can add a Type enum like other AST nodes use. It can be refactored into object later if needed.
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. Thank you for answering.
* Check if identity is allowed to comment the specified table. | ||
* @throws io.prestosql.spi.security.AccessDeniedException if not allowed | ||
*/ | ||
void checkCanAddComment(TransactionId transactionId, Identity identity, QualifiedObjectName tableName); |
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.
We don't have generic permissions like that. There are separate checks like checkCanAddColumns
, checkCanDropColumn
, checkCanRenameColumn
, checkCanRenameTable
, etc.
How about making this checkCanSetTableComment
?
Description | ||
----------- | ||
|
||
Add a comment to an existing table. |
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.
This is not just "add", since this can update or remove an existing comment. How about
Set the comment for a table. The comment can be removed by setting the comment to ``NULL``.
Examples | ||
-------- | ||
|
||
Add the comment ``master table`` to the ``users`` table:: |
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.
Change the comment for the ``users`` table to be ``master table``::
/** | ||
* Comments to the specified table | ||
*/ | ||
default void commentTable(ConnectorSession session, ConnectorTableHandle tableHandle, String comment) |
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.
Let's name this setTableComment
and also change String
to be Optional<String>
. This aligns with how comment is represented in ConnectorTableMetadata
and allows a single call to add/update/remove.
*/ | ||
default void commentTable(ConnectorSession session, ConnectorTableHandle tableHandle, String comment) | ||
{ | ||
throw new PrestoException(NOT_SUPPORTED, "This connector does not support commenting tables"); |
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.
This connector does not support setting table comments
Changes:
|
public synchronized void commentTable(String databaseName, String tableName, Optional<String> comment) | ||
{ | ||
alterTable(databaseName, tableName, oldTable -> { | ||
return oldTable.withParameters(ImmutableMap.<String, String>builder() |
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.
This is a single expression, so return
and {}
are unnecessary.
org.apache.hadoop.hive.metastore.api.Table table = source.get(); | ||
|
||
Map<String, String> parameters = table.getParameters(); | ||
parameters.put(TABLE_COMMENT, comment.orElse("")); |
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 comment
is Optional.empty()
, the comment should be removed. Does the hive metastore support removing comments explicitly or does it consider an empty comment the same as not having a comment? What happens if after clearing the comment you run DESCRIBE <table>
? Does it show COMMENT ''
?
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.
hive supports both empty comment and removing a comment (ALTER UNSET
). Actually, I tryied to remove the comment when it is empty, but followed the hive behaviour. Which do you think is better?
hive> ALTER TABLE table1 SET TBLPROPERTIES ('comment' = '');
hive> desc formatted table1;
...
Table Parameters:
comment
last_modified_by root
...
hive> ALTER TABLE table1 UNSET TBLPROPERTIES ('comment');
hive> desc formatted table1;
...
Table Parameters:
last_modified_by root
...
@ebyhr, can you squash the fixups into the corresponding commits? I'll do another review pass after that. Reassign to me when you've done it. |
@martint Updated. Unfortunately, I don't have a permission to change the assignees. |
I think this @electrum 's comment #200 (comment) requires SqlBase.g4 change like below. Please let me know if my understanding is wrong. SqlBase.g4 COMMENT ON TABLE qualifiedName IS (string | NULL) #commentTable Current g4 shows mismatch error if I specify
|
@ebyhr Yes, we'll need a minor change to the grammar to support |
Thank you for answering. Let me update to accept |
Updated. Current behavior:
|
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.
Just a few minor comments, but otherwise looks great! Once you rebased and address those issues, I'll merge it.
{ | ||
Session session = stateMachine.getSession(); | ||
|
||
if (statement.getType() == Comment.Type.TABLE) { |
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.
We should thrown a PrestoException with UNSUPPORTED code, otherwise.
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.
Perhaps, NOT_SUPPORTED
is right? I couldn't find UNSUPPORTED
code. Updated like this.
else {
throw new PrestoException(NOT_SUPPORTED, "Unsupported comment type: " + statement.getType());
}
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.
Yeah, that’s what I meant.
@Override | ||
public void setTableComment(Session session, TableHandle tableHandle, Optional<String> comment) | ||
{ | ||
ConnectorId connectorId = tableHandle.getConnectorId(); |
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.
This has been changed to CatalogName in recent commits.
* | ||
* @throws io.prestosql.spi.security.AccessDeniedException if not allowed | ||
*/ | ||
default void checkCanCommentTable(ConnectorTransactionHandle transactionHandle, ConnectorIdentity identity, SchemaTableName tableName) |
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.
Rename to checkCanSetTableComment
for consistency with AccessControl.
@Override | ||
public Node visitCommentTable(SqlBaseParser.CommentTableContext context) | ||
{ | ||
String comment = context.string() != null ? ((StringLiteral) visit(context.string())).getValue() : null; |
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 find this form easier to read:
Optional<String> comment = Optional.empy();
if (context.string() != null) {
comment = Optional.of(((StringLiteral) visit(context.string())).getValue())
}
return new Comment(...)
See how other visitXXX methods are implemented.
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); | ||
comment.ifPresent(value -> parameters.put(TABLE_COMMENT, comment.get())); | ||
|
||
table.setParameters(ImmutableMap.copyOf(parameters)); |
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 ImmutableMap.copyOf?
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.
Removed. It was debris during development.
@martint Thank you for your reviews. Rebased and applied the comments. Travis result is green. |
* | ||
* @throws AccessDeniedException if not allowed | ||
*/ | ||
default void checkCanCommentTable(Identity identity, CatalogSchemaTableName table) |
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.
This should be checkCanSetTableComment
Sorry, overlooked that. Updated once again. |
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.
Looks great, thanks for your contribution!
Ref: prestodb/presto#8425