Skip to content

Commit

Permalink
Merge #61629
Browse files Browse the repository at this point in the history
61629: sql: add internal tables cross db refs and interleaved indexes/tables r=fqazi a=fqazi

Fixes: #58867

Previously, users had no way of determining which objects in
their database utilized either deprecated features like
interleaved indexes/tables or cross DB references. This was
inadequate since users need to know which object utilize
this functionality. To address this, this patch introduces
the crdb_internal tables: cross_db_references, interleaved_indexes,
interleaved_tables.

Release justification: Low risk internal tables for detecting
deprecated features.
Release note (sql change): Added crdb_internal tables cross_db_references,
interleaved_indexes, and interleaved_tables for detecting the
deprecated features cross db references and interleaved tables
/ indexes within a given database.

Co-authored-by: Faizan Qazi <[email protected]>
  • Loading branch information
craig[bot] and fqazi committed Mar 12, 2021
2 parents e7f33b7 + 52e45e0 commit 377add4
Show file tree
Hide file tree
Showing 15 changed files with 540 additions and 168 deletions.
2 changes: 2 additions & 0 deletions pkg/cli/zip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ table_name NOT IN (
'builtin_functions',
'create_statements',
'create_type_statements',
'cross_db_references',
'databases',
'forward_dependencies',
'index_columns',
'interleaved',
'table_columns',
'table_indexes',
'table_row_statistics',
Expand Down
2 changes: 2 additions & 0 deletions pkg/sql/catalog/catconstants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ const (
CrdbInternalZonesTableID
CrdbInternalInvalidDescriptorsTableID
CrdbInternalClusterDatabasePrivilegesTableID
CrdbInternalInterleaved
CrdbInternalCrossDbRefrences
InformationSchemaID
InformationSchemaAdministrableRoleAuthorizationsID
InformationSchemaApplicableRolesID
Expand Down
203 changes: 203 additions & 0 deletions pkg/sql/crdb_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ var crdbInternal = virtualSchema{
catconstants.CrdbInternalZonesTableID: crdbInternalZonesTable,
catconstants.CrdbInternalInvalidDescriptorsTableID: crdbInternalInvalidDescriptorsTable,
catconstants.CrdbInternalClusterDatabasePrivilegesTableID: crdbInternalClusterDatabasePrivilegesTable,
catconstants.CrdbInternalInterleaved: crdbInternalInterleaved,
catconstants.CrdbInternalCrossDbRefrences: crdbInternalCrossDbReferences,
},
validWithNoDatabaseContext: true,
}
Expand Down Expand Up @@ -4024,3 +4026,204 @@ CREATE TABLE crdb_internal.cluster_database_privileges (
})
},
}

var crdbInternalInterleaved = virtualSchemaTable{
comment: `virtual table with interleaved table information`,
schema: `
CREATE TABLE crdb_internal.interleaved (
database_name
STRING NOT NULL,
schema_name
STRING NOT NULL,
table_name
STRING NOT NULL,
index_name
STRING NOT NULL,
parent_index
STRING NOT NULL
);`,
populate: func(ctx context.Context, p *planner, dbContext *dbdesc.Immutable, addRow func(...tree.Datum) error) error {
return forEachTableDescAllWithTableLookup(ctx, p, dbContext, hideVirtual,
func(db *dbdesc.Immutable, schemaName string, table catalog.TableDescriptor, lookupFn tableLookupFn) error {
if !table.IsInterleaved() {
return nil
}
indexes := table.NonDropIndexes()
for _, index := range indexes {
if index.NumInterleaveAncestors() == 0 {
continue
}

ancestor := index.GetInterleaveAncestor(index.NumInterleaveAncestors() - 1)
parentTable, err := lookupFn.getTableByID(ancestor.TableID)
if err != nil {
return err
}
parentIndex, err := parentTable.FindIndexWithID(ancestor.IndexID)
if err != nil {
return err
}
parentSchemaName, err := lookupFn.getSchemaNameByID(parentTable.GetParentSchemaID())
if err != nil {
return err
}
database, err := lookupFn.getDatabaseByID(parentTable.GetParentID())
if err != nil {
return err
}

if err := addRow(tree.NewDString(database.GetName()),
tree.NewDString(parentSchemaName),
tree.NewDString(table.GetName()),
tree.NewDString(index.GetName()),
tree.NewDString(parentIndex.GetName())); err != nil {
return err
}
}
return nil
})
},
}

var crdbInternalCrossDbReferences = virtualSchemaTable{
comment: `virtual table with cross db references`,
schema: `
CREATE TABLE crdb_internal.cross_db_references (
object_database
STRING NOT NULL,
object_schema
STRING NOT NULL,
object_name
STRING NOT NULL,
referenced_object_database
STRING NOT NULL,
referenced_object_schema
STRING NOT NULL,
referenced_object_name
STRING NOT NULL,
cross_database_reference_description
STRING NOT NULL
);`,
populate: func(ctx context.Context, p *planner, dbContext *dbdesc.Immutable, addRow func(...tree.Datum) error) error {
return forEachTableDescAllWithTableLookup(ctx, p, dbContext, hideVirtual,
func(db *dbdesc.Immutable, schemaName string, table catalog.TableDescriptor, lookupFn tableLookupFn) error {
// For tables detect if foreign key references point at a different
// database. Additionally, check if any of the columns have sequence
// references to a different database.
if table.IsTable() {
objectDatabaseName := lookupFn.getDatabaseName(table)
err := table.ForeachOutboundFK(
func(fk *descpb.ForeignKeyConstraint) error {
referencedTable, err := lookupFn.getTableByID(fk.ReferencedTableID)
if err != nil {
return err
}
if referencedTable.GetParentID() != table.GetParentID() {
refSchemaName, err := lookupFn.getSchemaNameByID(referencedTable.GetParentSchemaID())
if err != nil {
return err
}
refDatabaseName := lookupFn.getDatabaseName(referencedTable)

if err := addRow(tree.NewDString(objectDatabaseName),
tree.NewDString(schemaName),
tree.NewDString(table.GetName()),
tree.NewDString(refDatabaseName),
tree.NewDString(refSchemaName),
tree.NewDString(referencedTable.GetName()),
tree.NewDString("table foreign key reference")); err != nil {
return err
}
}
return nil
})
if err != nil {
return err
}

// Check for sequence dependencies
for _, col := range table.PublicColumns() {
for i := 0; i < col.NumUsesSequences(); i++ {
sequenceID := col.GetUsesSequenceID(i)
seqDesc, err := lookupFn.getTableByID(sequenceID)
if err != nil {
return err
}
if seqDesc.GetParentID() != table.GetParentID() {
seqSchemaName, err := lookupFn.getSchemaNameByID(seqDesc.GetParentSchemaID())
if err != nil {
return err
}
refDatabaseName := lookupFn.getDatabaseName(seqDesc)
if err := addRow(tree.NewDString(objectDatabaseName),
tree.NewDString(schemaName),
tree.NewDString(table.GetName()),
tree.NewDString(refDatabaseName),
tree.NewDString(seqSchemaName),
tree.NewDString(seqDesc.GetName()),
tree.NewDString("table column refers to sequence")); err != nil {
return err
}
}
}
}
} else if table.IsView() {
// For views check if we depend on tables in a different database.
dependsOn := table.GetDependsOn()
for _, dependency := range dependsOn {
dependentTable, err := lookupFn.getTableByID(dependency)
if err != nil {
return err
}
if dependentTable.GetParentID() != table.GetParentID() {
objectDatabaseName := lookupFn.getDatabaseName(table)
refSchemaName, err := lookupFn.getSchemaNameByID(dependentTable.GetParentSchemaID())
if err != nil {
return err
}
refDatabaseName := lookupFn.getDatabaseName(dependentTable)

if err := addRow(tree.NewDString(objectDatabaseName),
tree.NewDString(schemaName),
tree.NewDString(table.GetName()),
tree.NewDString(refDatabaseName),
tree.NewDString(refSchemaName),
tree.NewDString(dependentTable.GetName()),
tree.NewDString("view references table")); err != nil {
return err
}
}
}
} else if table.IsSequence() {
// For sequences check if the sequence is owned by
// a different database.
sequenceOpts := table.GetSequenceOpts()
if sequenceOpts.SequenceOwner.OwnerTableID != descpb.InvalidID {
ownerTable, err := lookupFn.getTableByID(sequenceOpts.SequenceOwner.OwnerTableID)
if err != nil {
return err
}
if ownerTable.GetParentID() != table.GetParentID() {
objectDatabaseName := lookupFn.getDatabaseName(table)
refSchemaName, err := lookupFn.getSchemaNameByID(ownerTable.GetParentSchemaID())
if err != nil {
return err
}
refDatabaseName := lookupFn.getDatabaseName(ownerTable)

if err := addRow(tree.NewDString(objectDatabaseName),
tree.NewDString(schemaName),
tree.NewDString(table.GetName()),
tree.NewDString(refDatabaseName),
tree.NewDString(refSchemaName),
tree.NewDString(ownerTable.GetName()),
tree.NewDString("sequences owning table")); err != nil {
return err
}
}
}
}
return nil
})
},
}
2 changes: 2 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/crdb_internal
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ crdb_internal cluster_settings table NULL NULL NULL
crdb_internal cluster_transactions table NULL NULL NULL
crdb_internal create_statements table NULL NULL NULL
crdb_internal create_type_statements table NULL NULL NULL
crdb_internal cross_db_references table NULL NULL NULL
crdb_internal databases table NULL NULL NULL
crdb_internal feature_usage table NULL NULL NULL
crdb_internal forward_dependencies table NULL NULL NULL
Expand All @@ -32,6 +33,7 @@ crdb_internal gossip_liveness table NULL NULL NULL
crdb_internal gossip_network table NULL NULL NULL
crdb_internal gossip_nodes table NULL NULL NULL
crdb_internal index_columns table NULL NULL NULL
crdb_internal interleaved table NULL NULL NULL
crdb_internal invalid_objects table NULL NULL NULL
crdb_internal jobs table NULL NULL NULL
crdb_internal kv_node_status table NULL NULL NULL
Expand Down
2 changes: 2 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/crdb_internal_tenant
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ crdb_internal cluster_settings table NULL NULL NULL
crdb_internal cluster_transactions table NULL NULL NULL
crdb_internal create_statements table NULL NULL NULL
crdb_internal create_type_statements table NULL NULL NULL
crdb_internal cross_db_references table NULL NULL NULL
crdb_internal databases table NULL NULL NULL
crdb_internal feature_usage table NULL NULL NULL
crdb_internal forward_dependencies table NULL NULL NULL
Expand All @@ -44,6 +45,7 @@ crdb_internal gossip_liveness table NULL NULL NULL
crdb_internal gossip_network table NULL NULL NULL
crdb_internal gossip_nodes table NULL NULL NULL
crdb_internal index_columns table NULL NULL NULL
crdb_internal interleaved table NULL NULL NULL
crdb_internal invalid_objects table NULL NULL NULL
crdb_internal jobs table NULL NULL NULL
crdb_internal kv_node_status table NULL NULL NULL
Expand Down
30 changes: 30 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/create_statements
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,23 @@ CREATE TABLE crdb_internal.create_type_statements (
enum_members STRING[] NULL,
INDEX create_type_statements_descriptor_id_idx (descriptor_id ASC) STORING (database_id, database_name, schema_name, descriptor_name, create_statement, enum_members)
) {} {}
CREATE TABLE crdb_internal.cross_db_references (
object_database STRING NOT NULL,
object_schema STRING NOT NULL,
object_name STRING NOT NULL,
referenced_object_database STRING NOT NULL,
referenced_object_schema STRING NOT NULL,
referenced_object_name STRING NOT NULL,
cross_database_reference_description STRING NOT NULL
) CREATE TABLE crdb_internal.cross_db_references (
object_database STRING NOT NULL,
object_schema STRING NOT NULL,
object_name STRING NOT NULL,
referenced_object_database STRING NOT NULL,
referenced_object_schema STRING NOT NULL,
referenced_object_name STRING NOT NULL,
cross_database_reference_description STRING NOT NULL
) {} {}
CREATE TABLE crdb_internal.databases (
id INT8 NOT NULL,
name STRING NOT NULL,
Expand Down Expand Up @@ -364,6 +381,19 @@ CREATE TABLE crdb_internal.index_columns (
column_direction STRING NULL,
implicit BOOL NULL
) {} {}
CREATE TABLE crdb_internal.interleaved (
database_name STRING NOT NULL,
schema_name STRING NOT NULL,
table_name STRING NOT NULL,
index_name STRING NOT NULL,
parent_index STRING NOT NULL
) CREATE TABLE crdb_internal.interleaved (
database_name STRING NOT NULL,
schema_name STRING NOT NULL,
table_name STRING NOT NULL,
index_name STRING NOT NULL,
parent_index STRING NOT NULL
) {} {}
CREATE TABLE crdb_internal.invalid_objects (
id INT8 NULL,
database_name STRING NULL,
Expand Down
9 changes: 9 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/fk
Original file line number Diff line number Diff line change
Expand Up @@ -3633,6 +3633,15 @@ USE db2
statement ok
CREATE TABLE child2 (c INT PRIMARY KEY, p INT REFERENCES db1.public.parent(p))


# Validate that cross DB foreign keys are detected by internal tables
query TTTTTTT
select * from "".crdb_internal.cross_db_references;
----
db2 public child db1 public parent table foreign key reference
db2 public child2 db1 public parent table foreign key reference


# Test that foreign keys cannot reference columns that are indexed by a partial
# unique index or a partial unique constraint. Partial unique indexes and
# constraints do not guarantee uniqueness in the entire table.
Expand Down
2 changes: 2 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/grant_table
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ test crdb_internal cluster_settings public
test crdb_internal cluster_transactions public SELECT
test crdb_internal create_statements public SELECT
test crdb_internal create_type_statements public SELECT
test crdb_internal cross_db_references public SELECT
test crdb_internal databases public SELECT
test crdb_internal feature_usage public SELECT
test crdb_internal forward_dependencies public SELECT
Expand All @@ -44,6 +45,7 @@ test crdb_internal gossip_liveness public
test crdb_internal gossip_network public SELECT
test crdb_internal gossip_nodes public SELECT
test crdb_internal index_columns public SELECT
test crdb_internal interleaved public SELECT
test crdb_internal invalid_objects public SELECT
test crdb_internal jobs public SELECT
test crdb_internal kv_node_status public SELECT
Expand Down
Loading

0 comments on commit 377add4

Please sign in to comment.