Skip to content
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

*: add infoschema.referential_constraints #26450

Merged
merged 7 commits into from
Aug 10, 2021
1 change: 1 addition & 0 deletions executor/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1564,6 +1564,7 @@ func (b *executorBuilder) buildMemTable(v *plannercore.PhysicalMemTable) Executo
strings.ToLower(infoschema.TableTiDBIndexes),
strings.ToLower(infoschema.TableViews),
strings.ToLower(infoschema.TableTables),
strings.ToLower(infoschema.TableReferConst),
strings.ToLower(infoschema.TableSequences),
strings.ToLower(infoschema.TablePartitions),
strings.ToLower(infoschema.TableEngines),
Expand Down
43 changes: 43 additions & 0 deletions executor/infoschema_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/pingcap/errors"
"github.com/pingcap/failpoint"
"github.com/pingcap/kvproto/pkg/deadlock"
"github.com/pingcap/parser/ast"
"github.com/pingcap/parser/charset"
"github.com/pingcap/parser/model"
"github.com/pingcap/parser/mysql"
Expand Down Expand Up @@ -101,6 +102,8 @@ func (e *memtableRetriever) retrieve(ctx context.Context, sctx sessionctx.Contex
e.setDataForStatistics(sctx, dbs)
case infoschema.TableTables:
err = e.setDataFromTables(ctx, sctx, dbs)
case infoschema.TableReferConst:
err = e.setDataFromReferConst(ctx, sctx, dbs)
case infoschema.TableSequences:
e.setDataFromSequences(sctx, dbs)
case infoschema.TablePartitions:
Expand Down Expand Up @@ -459,6 +462,46 @@ func (e *memtableRetriever) setDataForStatisticsInTable(schema *model.DBInfo, ta
e.rows = append(e.rows, rows...)
}

func (e *memtableRetriever) setDataFromReferConst(ctx context.Context, sctx sessionctx.Context, schemas []*model.DBInfo) error {
checker := privilege.GetPrivilegeManager(sctx)
var rows [][]types.Datum
for _, schema := range schemas {
for _, table := range schema.Tables {
if !table.IsBaseTable() {
continue
}
if checker != nil && !checker.RequestVerification(sctx.GetSessionVars().ActiveRoles, schema.Name.L, table.Name.L, "", mysql.AllPrivMask) {
continue
}
for _, fk := range table.ForeignKeys {
updateRule, deleteRule := "NO ACTION", "NO ACTION"
if ast.ReferOptionType(fk.OnUpdate) != 0 {
updateRule = ast.ReferOptionType(fk.OnUpdate).String()
}
if ast.ReferOptionType(fk.OnDelete) != 0 {
deleteRule = ast.ReferOptionType(fk.OnDelete).String()
}
record := types.MakeDatums(
infoschema.CatalogVal, // CONSTRAINT_CATALOG
schema.Name.O, // CONSTRAINT_SCHEMA
fk.Name.O, // CONSTRAINT_NAME
infoschema.CatalogVal, // UNIQUE_CONSTRAINT_CATALOG
schema.Name.O, // UNIQUE_CONSTRAINT_SCHEMA
"PRIMARY", // UNIQUE_CONSTRAINT_NAME
"NONE", // MATCH_OPTION
updateRule, // UPDATE_RULE
deleteRule, // DELETE_RULE
table.Name.O, // TABLE_NAME
fk.RefTable.O, // REFERENCED_TABLE_NAME
)
rows = append(rows, record)
}
}
}
e.rows = rows
return nil
}

func (e *memtableRetriever) setDataFromTables(ctx context.Context, sctx sessionctx.Context, schemas []*model.DBInfo) error {
tableRowsMap, colLengthMap, err := tableStatsCache.get(ctx, sctx)
if err != nil {
Expand Down
35 changes: 35 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10054,6 +10054,41 @@ func (s *testIntegrationSuite) TestTimestampIssue25093(c *C) {
tk.MustQuery("select timestamp(101.234) from t;").Check(testkit.Rows("2000-01-01 00:00:00.000"))
}

// issue https://github.com/pingcap/tidb/issues/26111
func (s *testIntegrationSuite) TestRailsFKUsage(c *C) {
defer s.cleanEnv(c)
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec(`CREATE TABLE author_addresses (
id bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`)
tk.MustExec(`CREATE TABLE authors (
id bigint(20) NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
author_address_id bigint(20) DEFAULT NULL,
author_address_extra_id bigint(20) DEFAULT NULL,
organization_id varchar(255) DEFAULT NULL,
owned_essay_id varchar(255) DEFAULT NULL,
PRIMARY KEY (id),
KEY index_authors_on_author_address_id (author_address_id),
KEY index_authors_on_author_address_extra_id (author_address_extra_id),
CONSTRAINT fk_rails_94423a17a3 FOREIGN KEY (author_address_id) REFERENCES author_addresses (id) ON UPDATE CASCADE ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`)
tk.MustQuery(`SELECT fk.referenced_table_name AS 'to_table',
fk.referenced_column_name AS 'primary_key',
fk.column_name AS 'column',
fk.constraint_name AS 'name',
rc.update_rule AS 'on_update',
rc.delete_rule AS 'on_delete'
FROM information_schema.referential_constraints rc
JOIN information_schema.key_column_usage fk
USING (constraint_schema, constraint_name)
WHERE fk.referenced_column_name IS NOT NULL
AND fk.table_schema = database()
AND fk.table_name = 'authors';`).Check(testkit.Rows("author_addresses id author_address_id fk_rails_94423a17a3 CASCADE RESTRICT"))
}

func (s *testIntegrationSuite) TestTranslate(c *C) {
cases := []string{"'ABC'", "'AABC'", "'A.B.C'", "'aaaaabbbbb'", "'abc'", "'aaa'", "NULL"}
tk := testkit.NewTestKit(c, s.store)
Expand Down
10 changes: 5 additions & 5 deletions infoschema/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@ const (
// TablePartitions is the string constant of infoschema table.
TablePartitions = "PARTITIONS"
// TableKeyColumn is the string constant of KEY_COLUMN_USAGE.
TableKeyColumn = "KEY_COLUMN_USAGE"
tableReferConst = "REFERENTIAL_CONSTRAINTS"
TableKeyColumn = "KEY_COLUMN_USAGE"
// TableReferConst is the string constant of REFERENTIAL_CONSTRAINTS.
TableReferConst = "REFERENTIAL_CONSTRAINTS"
// TableSessionVar is the string constant of SESSION_VARIABLES.
TableSessionVar = "SESSION_VARIABLES"
tablePlugins = "PLUGINS"
Expand Down Expand Up @@ -203,7 +204,7 @@ var tableIDMap = map[string]int64{
TableProfiling: autoid.InformationSchemaDBID + 10,
TablePartitions: autoid.InformationSchemaDBID + 11,
TableKeyColumn: autoid.InformationSchemaDBID + 12,
tableReferConst: autoid.InformationSchemaDBID + 13,
TableReferConst: autoid.InformationSchemaDBID + 13,
TableSessionVar: autoid.InformationSchemaDBID + 14,
tablePlugins: autoid.InformationSchemaDBID + 15,
TableConstraints: autoid.InformationSchemaDBID + 16,
Expand Down Expand Up @@ -1741,7 +1742,7 @@ var tableNameToColumns = map[string][]columnInfo{
TableProfiling: profilingCols,
TablePartitions: partitionsCols,
TableKeyColumn: keyColumnUsageCols,
tableReferConst: referConstCols,
TableReferConst: referConstCols,
TableSessionVar: sessionVarCols,
tablePlugins: pluginsCols,
TableConstraints: tableConstraintsCols,
Expand Down Expand Up @@ -1839,7 +1840,6 @@ func (it *infoschemaTable) getRows(ctx sessionctx.Context, cols []*table.Column)
sort.Sort(SchemasSorter(dbs))
switch it.meta.Name.O {
case tableFiles:
case tableReferConst:
case tablePlugins, tableTriggers:
case tableRoutines:
// TODO: Fill the following tables.
Expand Down
12 changes: 12 additions & 0 deletions infoschema/tables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1850,3 +1850,15 @@ func (s *testClusterTableSuite) TestDataLockWaitsPrivilege(c *C) {
}, nil, nil), IsTrue)
_ = tk.MustQuery("select * from information_schema.DATA_LOCK_WAITS")
}

func (s *testTableSuite) TestReferentialConstraints(c *C) {
tk := testkit.NewTestKit(c, s.store)

tk.MustExec("CREATE DATABASE referconstraints")
tk.MustExec("use referconstraints")

tk.MustExec("CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY)")
tk.MustExec("CREATE TABLE t2 (id INT NOT NULL PRIMARY KEY, t1_id INT DEFAULT NULL, INDEX (t1_id), CONSTRAINT `fk_to_t1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`))")

tk.MustQuery(`SELECT * FROM information_schema.referential_constraints WHERE table_name='t2'`).Check(testkit.Rows("def referconstraints fk_to_t1 def referconstraints PRIMARY NONE NO ACTION NO ACTION t2 t1"))
}