Skip to content

Commit

Permalink
sql: print comments in SHOW CREATE TABLE
Browse files Browse the repository at this point in the history
Fixes cockroachdb#42875

Release note (sql change): SHOW CREATE TABLE now prints comments.
  • Loading branch information
hueypark committed Jan 20, 2020
1 parent 3bb1834 commit 8288533
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 69 deletions.
6 changes: 3 additions & 3 deletions pkg/ccl/backupccl/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func showBackupPlanHook(
case tree.BackupFileDetails:
shower = backupShowerFiles
default:
shower = backupShowerDefault(ctx, backup.ShouldIncludeSchemas)
shower = backupShowerDefault(ctx, p, backup.ShouldIncludeSchemas)
}

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

func backupShowerDefault(ctx context.Context, showSchemas bool) backupShower {
func backupShowerDefault(ctx context.Context, p sql.PlanHookState, showSchemas bool) backupShower {
return backupShower{
header: backupShowerHeaders(showSchemas),
fn: func(desc BackupDescriptor) []tree.Datums {
Expand Down Expand Up @@ -157,7 +157,7 @@ func backupShowerDefault(ctx context.Context, showSchemas bool) backupShower {
tree.NewDInt(tree.DInt(descSizes[table.ID].Rows)),
}
if showSchemas {
schema, err := sql.ShowCreate(ctx, dbName, desc.Descriptors, table, sql.OmitMissingFKClausesFromCreate)
schema, err := sql.ShowCreate(ctx, p, dbName, desc.Descriptors, table, sql.OmitMissingFKClausesFromCreate)
if err != nil {
continue
}
Expand Down
19 changes: 13 additions & 6 deletions pkg/ccl/backupccl/show_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,24 @@ func TestShowBackup(t *testing.T) {
// Test that tables, views and sequences are all supported.
{
viewTableSeq := localFoo + "/tableviewseq"
sqlDB.Exec(t, `CREATE TABLE data.tableA (a int primary key, b int)`)
sqlDB.Exec(t, `CREATE TABLE data.tableA (a int primary key, b int, INDEX tableA_b_idx (b ASC))`)
sqlDB.Exec(t, `COMMENT ON TABLE data.tableA IS 'table'`)
sqlDB.Exec(t, `COMMENT ON COLUMN data.tableA.a IS 'column'`)
sqlDB.Exec(t, `COMMENT ON INDEX data.tableA_b_idx IS 'index'`)
sqlDB.Exec(t, `CREATE VIEW data.viewA AS SELECT a from data.tableA`)
sqlDB.Exec(t, `CREATE SEQUENCE data.seqA START 1 INCREMENT 2 MAXVALUE 20`)
sqlDB.Exec(t, `BACKUP data.tableA, data.viewA, data.seqA TO $1;`, viewTableSeq)

expectedCreateTable := `CREATE TABLE tablea (
a INT8 NOT NULL,
b INT8 NULL,
CONSTRAINT "primary" PRIMARY KEY (a ASC),
FAMILY "primary" (a, b)
)`
a INT8 NOT NULL,
b INT8 NULL,
CONSTRAINT "primary" PRIMARY KEY (a ASC),
INDEX tablea_b_idx (b ASC),
FAMILY "primary" (a, b)
);
COMMENT ON TABLE tablea IS 'table';
COMMENT ON COLUMN tablea.a IS 'column';
COMMENT ON INDEX tablea_b_idx IS 'index'`
expectedCreateView := `CREATE VIEW viewa (a) AS SELECT a FROM data.public.tablea`
expectedCreateSeq := `CREATE SEQUENCE seqa MINVALUE 1 MAXVALUE 20 INCREMENT 2 START 1`

Expand Down
4 changes: 2 additions & 2 deletions pkg/sql/crdb_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -1260,15 +1260,15 @@ CREATE TABLE crdb_internal.create_statements (
} else {
descType = typeTable
tn := (*tree.Name)(&table.Name)
createNofk, err = ShowCreateTable(ctx, tn, contextName, table, lCtx, OmitFKClausesFromCreate)
createNofk, err = ShowCreateTable(ctx, p, tn, contextName, table, lCtx, OmitFKClausesFromCreate)
if err != nil {
return err
}
allIdx := append(table.Indexes, table.PrimaryIndex)
if err := showAlterStatementWithInterleave(ctx, tn, contextName, lCtx, allIdx, table, alterStmts, validateStmts); err != nil {
return err
}
stmt, err = ShowCreateTable(ctx, tn, contextName, table, lCtx, IncludeFkClausesInCreate)
stmt, err = ShowCreateTable(ctx, p, tn, contextName, table, lCtx, IncludeFkClausesInCreate)
}
if err != nil {
return err
Expand Down
37 changes: 37 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/create_statements
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@ CREATE TABLE v (
FAMILY "primary" ("'", s, rowid)
)

statement ok
CREATE TABLE c (
a INT NOT NULL,
b INT NULL,
INDEX c_a_b_idx (a ASC, b ASC),
FAMILY fam_0_a_rowid (a, rowid),
FAMILY fam_1_b (b)
)

statement ok
COMMENT ON TABLE c IS 'table'

statement ok
COMMENT ON COLUMN c.a IS 'column'

statement ok
COMMENT ON INDEX c_a_b_idx IS 'index'

query TTTT colnames
SELECT create_statement, create_nofks, alter_statements, validate_statements FROM crdb_internal.create_statements WHERE database_name = 'test'
----
Expand Down Expand Up @@ -39,6 +57,25 @@ CREATE TABLE v (
INDEX "v_auto_index_fk_'_ref_t" ("'" ASC),
FAMILY "primary" ("'", s, rowid)
) {"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"}
CREATE TABLE c (
a INT8 NOT NULL,
b INT8 NULL,
INDEX c_a_b_idx (a ASC, b ASC),
FAMILY fam_0_a_rowid (a, rowid),
FAMILY fam_1_b (b)
);
COMMENT ON TABLE c IS 'table';
COMMENT ON COLUMN c.a IS 'column';
COMMENT ON INDEX c_a_b_idx IS 'index' CREATE TABLE c (
a INT8 NOT NULL,
b INT8 NULL,
INDEX c_a_b_idx (a ASC, b ASC),
FAMILY fam_0_a_rowid (a, rowid),
FAMILY fam_1_b (b)
);
COMMENT ON TABLE c IS 'table';
COMMENT ON COLUMN c.a IS 'column';
COMMENT ON INDEX c_a_b_idx IS 'index' {} {}

statement error invalid storage parameter "foo"
CREATE TABLE a (b INT) WITH (foo=100);
Expand Down
33 changes: 33 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/show_create
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
statement ok
CREATE TABLE c (
a INT NOT NULL,
b INT NULL,
INDEX c_a_b_idx (a ASC, b ASC),
FAMILY fam_0_a_rowid (a, rowid),
FAMILY fam_1_b (b)
)

statement ok
COMMENT ON TABLE c IS 'table'

statement ok
COMMENT ON COLUMN c.a IS 'column'

statement ok
COMMENT ON INDEX c_a_b_idx IS 'index'

query TT colnames
SHOW CREATE c
----
table_name create_statement
c CREATE TABLE c (
a INT8 NOT NULL,
b INT8 NULL,
INDEX c_a_b_idx (a ASC, b ASC),
FAMILY fam_0_a_rowid (a, rowid),
FAMILY fam_1_b (b)
);
COMMENT ON TABLE c IS 'table';
COMMENT ON COLUMN c.a IS 'column';
COMMENT ON INDEX c_a_b_idx IS 'index'

8 changes: 7 additions & 1 deletion pkg/sql/show_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const (
// current database.
func ShowCreateTable(
ctx context.Context,
p PlanHookState,
tn *tree.Name,
dbPrefix string,
desc *sqlbase.TableDescriptor,
Expand Down Expand Up @@ -150,6 +151,10 @@ func ShowCreateTable(
return "", err
}

if err := showComment(desc, selectComment(ctx, p, desc.ID), &f.Buffer); err != nil {
return "", err
}

return f.CloseAndGetString(), nil
}

Expand All @@ -175,6 +180,7 @@ func formatQuoteNames(buf *bytes.Buffer, names ...string) {
// current database.
func ShowCreate(
ctx context.Context,
p PlanHookState,
dbPrefix string,
allDescs []sqlbase.Descriptor,
desc *sqlbase.TableDescriptor,
Expand All @@ -189,7 +195,7 @@ func ShowCreate(
stmt, err = ShowCreateSequence(ctx, tn, desc)
} else {
lCtx := newInternalLookupCtxFromDescriptors(allDescs, nil /* want all tables */)
stmt, err = ShowCreateTable(ctx, tn, dbPrefix, desc, lCtx, ignoreFKs)
stmt, err = ShowCreateTable(ctx, p, tn, dbPrefix, desc, lCtx, ignoreFKs)
}

return stmt, err
Expand Down
83 changes: 83 additions & 0 deletions pkg/sql/show_create_clauses.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,60 @@ import (
"fmt"
"strings"

"github.com/cockroachdb/cockroach/pkg/keys"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
"github.com/cockroachdb/cockroach/pkg/util/log"
"github.com/pkg/errors"
)

// tableComment has comment data for table.
type tableComment struct {
comment *string
columns []comment
indexes []comment
}

type comment struct {
subID int
comment string
}

// selectComment returns table comment.
func selectComment(ctx context.Context, p PlanHookState, tableID sqlbase.ID) (tc *tableComment) {
query := fmt.Sprintf("SELECT type, object_id, sub_id, comment FROM system.comments WHERE object_id = %d", tableID)

commentRows, err := p.ExtendedEvalContext().ExecCfg.InternalExecutor.Query(
ctx, "show-tables-with-comment", p.Txn(), query)
if err != nil {
log.VEventf(ctx, 1, "%q", err)
} else {
for _, row := range commentRows {
commentType := int(tree.MustBeDInt(row[0]))
switch commentType {
case keys.TableCommentType, keys.ColumnCommentType, keys.IndexCommentType:
subID := int(tree.MustBeDInt(row[2]))
cmt := string(tree.MustBeDString(row[3]))

if tc == nil {
tc = &tableComment{}
}

switch commentType {
case keys.TableCommentType:
tc.comment = &cmt
case keys.ColumnCommentType:
tc.columns = append(tc.columns, comment{subID, cmt})
case keys.IndexCommentType:
tc.indexes = append(tc.indexes, comment{subID, cmt})
}
}
}
}

return tc
}

// ShowCreateView returns a valid SQL representation of the CREATE VIEW
// statement used to create the given view. It is used in the implementation of
// the crdb_internal.create_statements virtual table.
Expand All @@ -42,6 +91,40 @@ func ShowCreateView(
return f.CloseAndGetString(), nil
}

// showComment writes a valid SQL representation of a COMMENT clause.
func showComment(table *sqlbase.TableDescriptor, tc *tableComment, buf *bytes.Buffer) error {
if tc == nil {
return nil
}

if tc.comment != nil {
buf.WriteString(";\n")
buf.WriteString(fmt.Sprintf("COMMENT ON TABLE %s IS '%s'", table.Name, *tc.comment))
}

for _, columnComment := range tc.columns {
col, err := table.FindColumnByID(sqlbase.ColumnID(columnComment.subID))
if err != nil {
return err
}

buf.WriteString(";\n")
buf.WriteString(fmt.Sprintf("COMMENT ON COLUMN %s.%s IS '%s'", table.Name, col.Name, columnComment.comment))
}

for _, indexComment := range tc.indexes {
idx, err := table.FindIndexByID(sqlbase.IndexID(indexComment.subID))
if err != nil {
return err
}

buf.WriteString(";\n")
buf.WriteString(fmt.Sprintf("COMMENT ON INDEX %s IS '%s'", idx.Name, indexComment.comment))
}

return nil
}

// showForeignKeyConstraint returns a valid SQL representation of a FOREIGN KEY
// clause for a given index.
func showForeignKeyConstraint(
Expand Down
57 changes: 0 additions & 57 deletions pkg/sql/show_create_test.go

This file was deleted.

0 comments on commit 8288533

Please sign in to comment.