Skip to content

Commit 8cf3adf

Browse files
craig[bot]hueypark
craig[bot]
andcommitted
Merge #43152
43152: sql: print comments in SHOW CREATE TABLE r=knz a=hueypark Fixes #42875 Release note (sql change): SHOW CREATE TABLE now prints comments. Co-authored-by: Jaewan Park <[email protected]>
2 parents 3bb1834 + 08be7c4 commit 8cf3adf

File tree

9 files changed

+183
-70
lines changed

9 files changed

+183
-70
lines changed

pkg/ccl/backupccl/show.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func showBackupPlanHook(
5555
case tree.BackupFileDetails:
5656
shower = backupShowerFiles
5757
default:
58-
shower = backupShowerDefault(ctx, backup.ShouldIncludeSchemas)
58+
shower = backupShowerDefault(ctx, p, backup.ShouldIncludeSchemas)
5959
}
6060

6161
fn := func(ctx context.Context, _ []sql.PlanNode, resultsCh chan<- tree.Datums) error {
@@ -112,7 +112,7 @@ func backupShowerHeaders(showSchemas bool) sqlbase.ResultColumns {
112112
return baseHeaders
113113
}
114114

115-
func backupShowerDefault(ctx context.Context, showSchemas bool) backupShower {
115+
func backupShowerDefault(ctx context.Context, p sql.PlanHookState, showSchemas bool) backupShower {
116116
return backupShower{
117117
header: backupShowerHeaders(showSchemas),
118118
fn: func(desc BackupDescriptor) []tree.Datums {
@@ -157,7 +157,7 @@ func backupShowerDefault(ctx context.Context, showSchemas bool) backupShower {
157157
tree.NewDInt(tree.DInt(descSizes[table.ID].Rows)),
158158
}
159159
if showSchemas {
160-
schema, err := sql.ShowCreate(ctx, dbName, desc.Descriptors, table, sql.OmitMissingFKClausesFromCreate)
160+
schema, err := p.ShowCreate(ctx, dbName, desc.Descriptors, table, sql.OmitMissingFKClausesFromCreate)
161161
if err != nil {
162162
continue
163163
}

pkg/ccl/backupccl/show_test.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,17 +119,24 @@ func TestShowBackup(t *testing.T) {
119119
// Test that tables, views and sequences are all supported.
120120
{
121121
viewTableSeq := localFoo + "/tableviewseq"
122-
sqlDB.Exec(t, `CREATE TABLE data.tableA (a int primary key, b int)`)
122+
sqlDB.Exec(t, `CREATE TABLE data.tableA (a int primary key, b int, INDEX tableA_b_idx (b ASC))`)
123+
sqlDB.Exec(t, `COMMENT ON TABLE data.tableA IS 'table'`)
124+
sqlDB.Exec(t, `COMMENT ON COLUMN data.tableA.a IS 'column'`)
125+
sqlDB.Exec(t, `COMMENT ON INDEX data.tableA_b_idx IS 'index'`)
123126
sqlDB.Exec(t, `CREATE VIEW data.viewA AS SELECT a from data.tableA`)
124127
sqlDB.Exec(t, `CREATE SEQUENCE data.seqA START 1 INCREMENT 2 MAXVALUE 20`)
125128
sqlDB.Exec(t, `BACKUP data.tableA, data.viewA, data.seqA TO $1;`, viewTableSeq)
126129

127130
expectedCreateTable := `CREATE TABLE tablea (
128-
a INT8 NOT NULL,
129-
b INT8 NULL,
130-
CONSTRAINT "primary" PRIMARY KEY (a ASC),
131-
FAMILY "primary" (a, b)
132-
)`
131+
a INT8 NOT NULL,
132+
b INT8 NULL,
133+
CONSTRAINT "primary" PRIMARY KEY (a ASC),
134+
INDEX tablea_b_idx (b ASC),
135+
FAMILY "primary" (a, b)
136+
);
137+
COMMENT ON TABLE tablea IS 'table';
138+
COMMENT ON COLUMN tablea.a IS 'column';
139+
COMMENT ON INDEX tablea_b_idx IS 'index'`
133140
expectedCreateView := `CREATE VIEW viewa (a) AS SELECT a FROM data.public.tablea`
134141
expectedCreateSeq := `CREATE SEQUENCE seqa MINVALUE 1 MAXVALUE 20 INCREMENT 2 START 1`
135142

pkg/sql/crdb_internal.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,15 +1260,15 @@ CREATE TABLE crdb_internal.create_statements (
12601260
} else {
12611261
descType = typeTable
12621262
tn := (*tree.Name)(&table.Name)
1263-
createNofk, err = ShowCreateTable(ctx, tn, contextName, table, lCtx, OmitFKClausesFromCreate)
1263+
createNofk, err = ShowCreateTable(ctx, p, tn, contextName, table, lCtx, OmitFKClausesFromCreate)
12641264
if err != nil {
12651265
return err
12661266
}
12671267
allIdx := append(table.Indexes, table.PrimaryIndex)
12681268
if err := showAlterStatementWithInterleave(ctx, tn, contextName, lCtx, allIdx, table, alterStmts, validateStmts); err != nil {
12691269
return err
12701270
}
1271-
stmt, err = ShowCreateTable(ctx, tn, contextName, table, lCtx, IncludeFkClausesInCreate)
1271+
stmt, err = ShowCreateTable(ctx, p, tn, contextName, table, lCtx, IncludeFkClausesInCreate)
12721272
}
12731273
if err != nil {
12741274
return err

pkg/sql/logictest/testdata/logic_test/create_statements

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,24 @@ CREATE TABLE v (
1010
FAMILY "primary" ("'", s, rowid)
1111
)
1212

13+
statement ok
14+
CREATE TABLE c (
15+
a INT NOT NULL,
16+
b INT NULL,
17+
INDEX c_a_b_idx (a ASC, b ASC),
18+
FAMILY fam_0_a_rowid (a, rowid),
19+
FAMILY fam_1_b (b)
20+
)
21+
22+
statement ok
23+
COMMENT ON TABLE c IS 'table'
24+
25+
statement ok
26+
COMMENT ON COLUMN c.a IS 'column'
27+
28+
statement ok
29+
COMMENT ON INDEX c_a_b_idx IS 'index'
30+
1331
query TTTT colnames
1432
SELECT create_statement, create_nofks, alter_statements, validate_statements FROM crdb_internal.create_statements WHERE database_name = 'test'
1533
----
@@ -39,6 +57,25 @@ CREATE TABLE v (
3957
INDEX "v_auto_index_fk_'_ref_t" ("'" ASC),
4058
FAMILY "primary" ("'", s, rowid)
4159
) {"ALTER TABLE v ADD CONSTRAINT \"fk_'_ref_t\" FOREIGN KEY (\"'\") REFERENCES t(rowid)","ALTER TABLE v ADD CONSTRAINT fk_s_ref_v FOREIGN KEY (s) REFERENCES v(s)"} {"ALTER TABLE v VALIDATE CONSTRAINT \"fk_'_ref_t\"","ALTER TABLE v VALIDATE CONSTRAINT fk_s_ref_v"}
60+
CREATE TABLE c (
61+
a INT8 NOT NULL,
62+
b INT8 NULL,
63+
INDEX c_a_b_idx (a ASC, b ASC),
64+
FAMILY fam_0_a_rowid (a, rowid),
65+
FAMILY fam_1_b (b)
66+
);
67+
COMMENT ON TABLE c IS 'table';
68+
COMMENT ON COLUMN c.a IS 'column';
69+
COMMENT ON INDEX c_a_b_idx IS 'index' CREATE TABLE c (
70+
a INT8 NOT NULL,
71+
b INT8 NULL,
72+
INDEX c_a_b_idx (a ASC, b ASC),
73+
FAMILY fam_0_a_rowid (a, rowid),
74+
FAMILY fam_1_b (b)
75+
);
76+
COMMENT ON TABLE c IS 'table';
77+
COMMENT ON COLUMN c.a IS 'column';
78+
COMMENT ON INDEX c_a_b_idx IS 'index' {} {}
4279

4380
statement error invalid storage parameter "foo"
4481
CREATE TABLE a (b INT) WITH (foo=100);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
statement ok
2+
CREATE TABLE c (
3+
a INT NOT NULL,
4+
b INT NULL,
5+
INDEX c_a_b_idx (a ASC, b ASC),
6+
FAMILY fam_0_a_rowid (a, rowid),
7+
FAMILY fam_1_b (b)
8+
)
9+
10+
statement ok
11+
COMMENT ON TABLE c IS 'table'
12+
13+
statement ok
14+
COMMENT ON COLUMN c.a IS 'column'
15+
16+
statement ok
17+
COMMENT ON INDEX c_a_b_idx IS 'index'
18+
19+
query TT colnames
20+
SHOW CREATE c
21+
----
22+
table_name create_statement
23+
c CREATE TABLE c (
24+
a INT8 NOT NULL,
25+
b INT8 NULL,
26+
INDEX c_a_b_idx (a ASC, b ASC),
27+
FAMILY fam_0_a_rowid (a, rowid),
28+
FAMILY fam_1_b (b)
29+
);
30+
COMMENT ON TABLE c IS 'table';
31+
COMMENT ON COLUMN c.a IS 'column';
32+
COMMENT ON INDEX c_a_b_idx IS 'index'
33+

pkg/sql/planhook.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ type PlanHookState interface {
9797
ResolveMutableTableDescriptor(
9898
ctx context.Context, tn *ObjectName, required bool, requiredType ResolveRequiredType,
9999
) (table *MutableTableDescriptor, err error)
100+
ShowCreate(
101+
ctx context.Context, dbPrefix string, allDescs []sqlbase.Descriptor, desc *sqlbase.TableDescriptor, ignoreFKs shouldOmitFKClausesFromCreate,
102+
) (string, error)
100103
}
101104

102105
// AddPlanHook adds a hook used to short-circuit creating a planNode from a

pkg/sql/show_create.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const (
4747
// current database.
4848
func ShowCreateTable(
4949
ctx context.Context,
50+
p PlanHookState,
5051
tn *tree.Name,
5152
dbPrefix string,
5253
desc *sqlbase.TableDescriptor,
@@ -150,6 +151,10 @@ func ShowCreateTable(
150151
return "", err
151152
}
152153

154+
if err := showComments(desc, selectComment(ctx, p, desc.ID), &f.Buffer); err != nil {
155+
return "", err
156+
}
157+
153158
return f.CloseAndGetString(), nil
154159
}
155160

@@ -173,7 +178,7 @@ func formatQuoteNames(buf *bytes.Buffer, names ...string) {
173178
// unless it is equal to the given dbPrefix. This allows us to elide
174179
// the prefix when the given table references other tables in the
175180
// current database.
176-
func ShowCreate(
181+
func (p *planner) ShowCreate(
177182
ctx context.Context,
178183
dbPrefix string,
179184
allDescs []sqlbase.Descriptor,
@@ -189,7 +194,7 @@ func ShowCreate(
189194
stmt, err = ShowCreateSequence(ctx, tn, desc)
190195
} else {
191196
lCtx := newInternalLookupCtxFromDescriptors(allDescs, nil /* want all tables */)
192-
stmt, err = ShowCreateTable(ctx, tn, dbPrefix, desc, lCtx, ignoreFKs)
197+
stmt, err = ShowCreateTable(ctx, p, tn, dbPrefix, desc, lCtx, ignoreFKs)
193198
}
194199

195200
return stmt, err

pkg/sql/show_create_clauses.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,61 @@ import (
1616
"fmt"
1717
"strings"
1818

19+
"github.com/cockroachdb/cockroach/pkg/keys"
1920
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
2021
"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
22+
"github.com/cockroachdb/cockroach/pkg/util/log"
2123
"github.com/pkg/errors"
2224
)
2325

26+
// tableComments stores the comment data for a table.
27+
type tableComments struct {
28+
comment *string
29+
columns []comment
30+
indexes []comment
31+
}
32+
33+
type comment struct {
34+
subID int
35+
comment string
36+
}
37+
38+
// selectComment retrieves all the comments pertaining to a table (comments on the table
39+
// itself but also column and index comments.)
40+
func selectComment(ctx context.Context, p PlanHookState, tableID sqlbase.ID) (tc *tableComments) {
41+
query := fmt.Sprintf("SELECT type, object_id, sub_id, comment FROM system.comments WHERE object_id = %d", tableID)
42+
43+
commentRows, err := p.ExtendedEvalContext().ExecCfg.InternalExecutor.Query(
44+
ctx, "show-tables-with-comment", p.Txn(), query)
45+
if err != nil {
46+
log.VEventf(ctx, 1, "%q", err)
47+
} else {
48+
for _, row := range commentRows {
49+
commentType := int(tree.MustBeDInt(row[0]))
50+
switch commentType {
51+
case keys.TableCommentType, keys.ColumnCommentType, keys.IndexCommentType:
52+
subID := int(tree.MustBeDInt(row[2]))
53+
cmt := string(tree.MustBeDString(row[3]))
54+
55+
if tc == nil {
56+
tc = &tableComments{}
57+
}
58+
59+
switch commentType {
60+
case keys.TableCommentType:
61+
tc.comment = &cmt
62+
case keys.ColumnCommentType:
63+
tc.columns = append(tc.columns, comment{subID, cmt})
64+
case keys.IndexCommentType:
65+
tc.indexes = append(tc.indexes, comment{subID, cmt})
66+
}
67+
}
68+
}
69+
}
70+
71+
return tc
72+
}
73+
2474
// ShowCreateView returns a valid SQL representation of the CREATE VIEW
2575
// statement used to create the given view. It is used in the implementation of
2676
// the crdb_internal.create_statements virtual table.
@@ -42,6 +92,41 @@ func ShowCreateView(
4292
return f.CloseAndGetString(), nil
4393
}
4494

95+
// showComments prints out the COMMENT statements sufficient to populate a
96+
// table's comments, including its index and column comments.
97+
func showComments(table *sqlbase.TableDescriptor, tc *tableComments, buf *bytes.Buffer) error {
98+
if tc == nil {
99+
return nil
100+
}
101+
102+
if tc.comment != nil {
103+
buf.WriteString(";\n")
104+
buf.WriteString(fmt.Sprintf("COMMENT ON TABLE %s IS '%s'", table.Name, *tc.comment))
105+
}
106+
107+
for _, columnComment := range tc.columns {
108+
col, err := table.FindColumnByID(sqlbase.ColumnID(columnComment.subID))
109+
if err != nil {
110+
return err
111+
}
112+
113+
buf.WriteString(";\n")
114+
buf.WriteString(fmt.Sprintf("COMMENT ON COLUMN %s.%s IS '%s'", table.Name, col.Name, columnComment.comment))
115+
}
116+
117+
for _, indexComment := range tc.indexes {
118+
idx, err := table.FindIndexByID(sqlbase.IndexID(indexComment.subID))
119+
if err != nil {
120+
return err
121+
}
122+
123+
buf.WriteString(";\n")
124+
buf.WriteString(fmt.Sprintf("COMMENT ON INDEX %s IS '%s'", idx.Name, indexComment.comment))
125+
}
126+
127+
return nil
128+
}
129+
45130
// showForeignKeyConstraint returns a valid SQL representation of a FOREIGN KEY
46131
// clause for a given index.
47132
func showForeignKeyConstraint(

pkg/sql/show_create_test.go

Lines changed: 0 additions & 57 deletions
This file was deleted.

0 commit comments

Comments
 (0)