diff --git a/pkg/sql/logictest/testdata/logic_test/pg_catalog b/pkg/sql/logictest/testdata/logic_test/pg_catalog index 172336f2fa9f..4c1dbeb23363 100644 --- a/pkg/sql/logictest/testdata/logic_test/pg_catalog +++ b/pkg/sql/logictest/testdata/logic_test/pg_catalog @@ -1604,3 +1604,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 eeb0bec7dafd..ee032442f64c 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 4ccbb184f70c..46f6484ecf5a 100644 --- a/pkg/sql/sqlbase/structured.pb.go +++ b/pkg/sql/sqlbase/structured.pb.go @@ -649,6 +649,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 c6c1093b9370..08442b21eb86 100644 --- a/pkg/sql/sqlbase/structured.proto +++ b/pkg/sql/sqlbase/structured.proto @@ -278,6 +278,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"]; }