Skip to content

Commit

Permalink
Merge #33355
Browse files Browse the repository at this point in the history
33355: sql: support `COMMENT ON COLUMN` r=knz a=hueypark

Informs #19472.

This patch introduces support for table column comments.

The syntax to set or delete a comment is the same as postgres:
`COMMENT ON COLUMN ... IS ...`. See:
https://www.postgresql.org/docs/9.1/sql-comment.html

Release note (sql change): CockroachDB now supports associating
comments to SQL table column using PostgreSQL's `COMMENT ON COLIMN`
syntax. This also provides proper support for pg's
`pg_catalog.pg_description` and built-in function `col_description()`.

Co-authored-by: Jaewan Park <jaewan.huey.park@gmail.com>
  • Loading branch information
craig[bot] and hueypark committed Dec 31, 2018
2 parents 6dac732 + 52fa9cb commit a8afcab
Show file tree
Hide file tree
Showing 21 changed files with 525 additions and 62 deletions.
57 changes: 29 additions & 28 deletions docs/generated/sql/bnf/stmt_block.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ copy_from_stmt ::=
comment_stmt ::=
'COMMENT' 'ON' 'DATABASE' database_name 'IS' comment_text
| 'COMMENT' 'ON' 'TABLE' table_name 'IS' comment_text
| 'COMMENT' 'ON' 'COLUMN' column_path 'IS' comment_text

execute_stmt ::=
'EXECUTE' table_alias_name execute_param_clause
Expand Down Expand Up @@ -207,6 +208,10 @@ comment_text ::=
'SCONST'
| 'NULL'

column_path ::=
name
| prefixed_column_path

table_alias_name ::=
name

Expand Down Expand Up @@ -536,6 +541,11 @@ db_object_name ::=
simple_db_object_name
| complex_db_object_name

prefixed_column_path ::=
db_object_name_component '.' unrestricted_name
| db_object_name_component '.' unrestricted_name '.' unrestricted_name
| db_object_name_component '.' unrestricted_name '.' unrestricted_name '.' unrestricted_name

expr_list ::=
( a_expr ) ( ( ',' a_expr ) )*

Expand Down Expand Up @@ -1145,18 +1155,6 @@ complex_db_object_name ::=
db_object_name_component '.' unrestricted_name
| db_object_name_component '.' unrestricted_name '.' unrestricted_name

non_reserved_word ::=
'identifier'
| unreserved_keyword
| col_name_keyword
| type_func_name_keyword

kv_option ::=
name '=' string_or_placeholder
| name
| 'SCONST' '=' string_or_placeholder
| 'SCONST'

db_object_name_component ::=
name
| cockroachdb_extra_type_func_name_keyword
Expand All @@ -1169,6 +1167,18 @@ unrestricted_name ::=
| type_func_name_keyword
| reserved_keyword

non_reserved_word ::=
'identifier'
| unreserved_keyword
| col_name_keyword
| type_func_name_keyword

kv_option ::=
name '=' string_or_placeholder
| name
| 'SCONST' '=' string_or_placeholder
| 'SCONST'

transaction_mode ::=
transaction_user_priority
| transaction_read_mode
Expand Down Expand Up @@ -1481,6 +1491,13 @@ single_set_clause ::=
multiple_set_clause ::=
'(' insert_column_list ')' '=' in_expr

cockroachdb_extra_type_func_name_keyword ::=
'FAMILY'

cockroachdb_extra_reserved_keyword ::=
'INDEX'
| 'NOTHING'

type_func_name_keyword ::=
'COLLATION'
| 'CROSS'
Expand All @@ -1500,13 +1517,6 @@ type_func_name_keyword ::=
| 'SIMILAR'
| cockroachdb_extra_type_func_name_keyword

cockroachdb_extra_type_func_name_keyword ::=
'FAMILY'

cockroachdb_extra_reserved_keyword ::=
'INDEX'
| 'NOTHING'

reserved_keyword ::=
'ALL'
| 'ANALYSE'
Expand Down Expand Up @@ -1921,10 +1931,6 @@ opt_interval ::=
interval_qualifier
|

column_path ::=
name
| prefixed_column_path

func_application ::=
func_name '(' ')'
| func_name '(' expr_list ')'
Expand Down Expand Up @@ -2101,11 +2107,6 @@ interval_qualifier ::=
| 'HOUR' 'TO' interval_second
| 'MINUTE' 'TO' interval_second

prefixed_column_path ::=
db_object_name_component '.' unrestricted_name
| db_object_name_component '.' unrestricted_name '.' unrestricted_name
| db_object_name_component '.' unrestricted_name '.' unrestricted_name '.' unrestricted_name

func_name ::=
type_function_name
| prefixed_column_path
Expand Down
2 changes: 1 addition & 1 deletion pkg/keys/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,5 +333,5 @@ const (
// CommentType is type for system.comments
DatabaseCommentType = 0
TableCommentType = 1
// ColumnCommentType = 2
ColumnCommentType = 2
)
23 changes: 23 additions & 0 deletions pkg/sql/alter_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
gojson "encoding/json"
"fmt"

"github.com/cockroachdb/cockroach/pkg/keys"
"github.com/cockroachdb/cockroach/pkg/sql/coltypes"
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
"github.com/cockroachdb/cockroach/pkg/sql/privilege"
Expand Down Expand Up @@ -411,6 +412,13 @@ func (n *alterTableNode) startExec(params runParams) error {
descriptorChanged = true
}

if err != nil {
return err
}
if err := params.p.removeColumnComment(params.ctx, n.tableDesc.ID, col.ID); err != nil {
return err
}

found := false
for i := range n.tableDesc.Columns {
if n.tableDesc.Columns[i].ID == col.ID {
Expand Down Expand Up @@ -873,3 +881,18 @@ func injectTableStats(

return stats.GossipTableStatAdded(params.extendedEvalCtx.ExecCfg.Gossip, desc.ID)
}

func (p *planner) removeColumnComment(
ctx context.Context, tableID sqlbase.ID, columnID sqlbase.ColumnID,
) error {
_, err := p.ExtendedEvalContext().ExecCfg.InternalExecutor.Exec(
ctx,
"delete-column-comment",
p.txn,
"DELETE FROM system.comments WHERE type=$1 AND object_id=$2 AND sub_id=$3",
keys.ColumnCommentType,
tableID,
columnID)

return err
}
106 changes: 106 additions & 0 deletions pkg/sql/comment_on_column.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright 2018 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.

package sql

import (
"context"

"github.com/cockroachdb/cockroach/pkg/keys"
"github.com/cockroachdb/cockroach/pkg/sql/privilege"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
)

type commentOnColumnNode struct {
n *tree.CommentOnColumn
tableDesc *MutableTableDescriptor
}

// CommentOnColumn add comment on a column.
// Privileges: CREATE on table.
func (p *planner) CommentOnColumn(ctx context.Context, n *tree.CommentOnColumn) (planNode, error) {
tableName, err := tree.NormalizeTableName(&n.ColumnItem.TableName)
if err != nil {
return nil, err
}

tableDesc, err := p.ResolveMutableTableDescriptor(ctx, &tableName, true, requireTableDesc)
if err != nil {
return nil, err
}

if err := p.CheckPrivilege(ctx, tableDesc, privilege.CREATE); err != nil {
return nil, err
}

return &commentOnColumnNode{n: n, tableDesc: tableDesc}, nil
}

func (n *commentOnColumnNode) startExec(params runParams) error {
col, _, err := n.tableDesc.FindColumnByName(n.n.ColumnItem.ColumnName)
if err != nil {
return err
}

if n.n.Comment != nil {
_, err := params.p.extendedEvalCtx.ExecCfg.InternalExecutor.Exec(
params.ctx,
"set-column-comment",
params.p.Txn(),
"UPSERT INTO system.comments VALUES ($1, $2, $3, $4)",
keys.ColumnCommentType,
n.tableDesc.ID,
col.ID,
*n.n.Comment)
if err != nil {
return err
}
} else {
_, err := params.p.extendedEvalCtx.ExecCfg.InternalExecutor.Exec(
params.ctx,
"delete-column-comment",
params.p.Txn(),
"DELETE FROM system.comments WHERE type=$1 AND object_id=$2 AND sub_id=$3",
keys.ColumnCommentType,
n.tableDesc.ID,
col.ID)
if err != nil {
return err
}
}

return MakeEventLogger(params.extendedEvalCtx.ExecCfg).InsertEventRecord(
params.ctx,
params.p.txn,
EventLogCommentOnColumn,
int32(n.tableDesc.ID),
int32(params.extendedEvalCtx.NodeID),
struct {
TableName string
ColumnName string
Statement string
User string
Comment *string
}{
n.tableDesc.Name,
string(n.n.ColumnItem.ColumnName),
n.n.String(),
params.SessionData().User,
n.n.Comment},
)
}

func (n *commentOnColumnNode) Next(runParams) (bool, error) { return false, nil }
func (n *commentOnColumnNode) Values() tree.Datums { return tree.Datums{} }
func (n *commentOnColumnNode) Close(context.Context) {}
Loading

0 comments on commit a8afcab

Please sign in to comment.