From 0fd79ec354d774d8a5d62354b228263a392ea287 Mon Sep 17 00:00:00 2001 From: Bram Gruneir Date: Thu, 18 Oct 2018 16:57:35 -0400 Subject: [PATCH] sql: fix pg_catalog.pg_constraint's confkey column Prior to this patch, all columns in the index were included instead of only the ones being used in the foreign key reference. Fixes #31545. Release note (bug fix): Fix pg_catalog.pg_constraint's confkey column from including columns that were not involved in the foreign key reference. --- .../logictest/testdata/logic_test/pg_catalog | 58 +++++++++++++++++++ pkg/sql/pg_catalog.go | 16 ++++- pkg/sql/sqlbase/structured.pb.go | 2 + pkg/sql/sqlbase/structured.proto | 2 + 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/pkg/sql/logictest/testdata/logic_test/pg_catalog b/pkg/sql/logictest/testdata/logic_test/pg_catalog index 4936694555f2..9db78f852a9a 100644 --- a/pkg/sql/logictest/testdata/logic_test/pg_catalog +++ b/pkg/sql/logictest/testdata/logic_test/pg_catalog @@ -1624,3 +1624,61 @@ query OT SELECT typ.oid, typ.typname FROM pg_attribute att JOIN pg_type typ ON atttypid=typ.oid WHERE attrelid='coltab'::regclass AND attname='a' ---- 25 text + +subtest 31545 + +# Test an index of 2 referencing an index of 2. +statement ok +CREATE TABLE a ( + id_a_1 INT UNIQUE, + id_a_2 INT, + PRIMARY KEY (id_a_1, id_a_2) +) + +statement ok +CREATE TABLE b ( + id_b_1 INT, + id_b_2 INT, + PRIMARY KEY (id_b_1, id_b_2), + CONSTRAINT my_fkey FOREIGN KEY (id_b_1, id_b_2) REFERENCES a (id_a_1, id_a_2) +) + +query TT colnames +SELECT conkey, confkey FROM pg_catalog.pg_constraint WHERE conname = 'my_fkey' +---- +conkey confkey +{1,2} {1,2} + +# Test an index of 3 referencing an index of 2. +statement ok +DROP TABLE b; +CREATE TABLE b ( + id_b_1 INT, + id_b_2 INT, + id_b_3 INT, + PRIMARY KEY (id_b_1, id_b_2, id_b_3), + CONSTRAINT my_fkey FOREIGN KEY (id_b_1, id_b_2) REFERENCES a (id_a_1, id_a_2) +) + +query TT colnames +SELECT conkey, confkey FROM pg_catalog.pg_constraint WHERE conname = 'my_fkey' +---- +conkey confkey +{1,2} {1,2} + +# Test an index of 3 referencing an index of 1. +statement ok +DROP TABLE b; +CREATE TABLE b ( + id_b_1 INT, + id_b_2 INT, + id_b_3 INT, + PRIMARY KEY (id_b_1, id_b_2, id_b_3), + CONSTRAINT my_fkey FOREIGN KEY (id_b_1) REFERENCES a (id_a_1) +) + +query TT colnames +SELECT conkey, confkey FROM pg_catalog.pg_constraint WHERE conname = 'my_fkey' +---- +conkey confkey +{1} {1} diff --git a/pkg/sql/pg_catalog.go b/pkg/sql/pg_catalog.go index b87027ae93b3..ecb8e342b30a 100644 --- a/pkg/sql/pg_catalog.go +++ b/pkg/sql/pg_catalog.go @@ -680,7 +680,21 @@ CREATE TABLE pg_catalog.pg_constraint ( confupdtype = fkActionNone confdeltype = fkActionNone confmatchtype = fkMatchTypeSimple - if conkey, err = colIDArrayToDatum(con.Index.ColumnIDs); err != nil { + columnIDs := con.Index.ColumnIDs + if int(con.FK.SharedPrefixLen) > len(columnIDs) { + return errors.Errorf( + "For foreign key %q's shared prefix len (%d) is greater than the number of columns "+ + "in the index (%d). This might be an indication of inconsistency.", + con.FK.Name, + con.FK.SharedPrefixLen, + int32(len(columnIDs)), + ) + } + sharedPrefixLen := len(columnIDs) + if int(con.FK.SharedPrefixLen) > 0 { + sharedPrefixLen = int(con.FK.SharedPrefixLen) + } + if conkey, err = colIDArrayToDatum(columnIDs[:sharedPrefixLen]); err != nil { return err } if confkey, err = colIDArrayToDatum(con.ReferencedIndex.ColumnIDs); err != nil { diff --git a/pkg/sql/sqlbase/structured.pb.go b/pkg/sql/sqlbase/structured.pb.go index 0222d118a75a..c7ed7371b478 100644 --- a/pkg/sql/sqlbase/structured.pb.go +++ b/pkg/sql/sqlbase/structured.pb.go @@ -655,6 +655,8 @@ type InterleaveDescriptor_Ancestor struct { // grandparent. Thus, the sum of SharedPrefixLens in the components of an // InterleaveDescriptor is never more than the number of fields in the index // being interleaved. + // In cockroach 1.0, this value did not exist and thus a check for > 0 + // must be performed prior to its use. SharedPrefixLen uint32 `protobuf:"varint,3,opt,name=shared_prefix_len,json=sharedPrefixLen" json:"shared_prefix_len"` } diff --git a/pkg/sql/sqlbase/structured.proto b/pkg/sql/sqlbase/structured.proto index cc285625362e..bc3a90322d15 100644 --- a/pkg/sql/sqlbase/structured.proto +++ b/pkg/sql/sqlbase/structured.proto @@ -285,6 +285,8 @@ message InterleaveDescriptor { // grandparent. Thus, the sum of SharedPrefixLens in the components of an // InterleaveDescriptor is never more than the number of fields in the index // being interleaved. + // In cockroach 1.0, this value did not exist and thus a check for > 0 + // must be performed prior to its use. optional uint32 shared_prefix_len = 3 [(gogoproto.nullable) = false, (gogoproto.customname) = "SharedPrefixLen"]; }