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

sql: include partial index predicates in pg_catalog and pg builtins #53967

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions pkg/sql/logictest/testdata/logic_test/builtin_function
Original file line number Diff line number Diff line change
Expand Up @@ -2064,13 +2064,33 @@ SELECT pg_catalog.pg_get_indexdef(0)
NULL

statement ok
CREATE TABLE test.pg_indexdef_test (a INT, UNIQUE INDEX pg_indexdef_idx (a ASC), INDEX other (a DESC))
CREATE TYPE testenum AS ENUM ('foo', 'bar', 'baz')

statement ok
CREATE TABLE test.pg_indexdef_test (
a INT,
e testenum,
UNIQUE INDEX pg_indexdef_idx (a ASC),
INDEX pg_indexdef_partial_idx (a) WHERE a > 0,
INDEX pg_indexdef_partial_enum_idx (a) WHERE e IN ('foo', 'bar'),
INDEX other (a DESC)
)

query T
SELECT pg_catalog.pg_get_indexdef((SELECT oid from pg_class WHERE relname='pg_indexdef_idx'))
----
CREATE UNIQUE INDEX pg_indexdef_idx ON test.public.pg_indexdef_test USING btree (a ASC)

query T
SELECT pg_catalog.pg_get_indexdef((SELECT oid from pg_class WHERE relname='pg_indexdef_partial_idx'))
----
CREATE INDEX pg_indexdef_partial_idx ON test.public.pg_indexdef_test USING btree (a ASC) WHERE a > 0

query T
SELECT pg_catalog.pg_get_indexdef((SELECT oid from pg_class WHERE relname='pg_indexdef_partial_enum_idx'))
----
CREATE INDEX pg_indexdef_partial_enum_idx ON test.public.pg_indexdef_test USING btree (a ASC) WHERE e IN ('foo'::public.testenum, 'bar'::public.testenum)

query T
SELECT pg_catalog.pg_get_indexdef(0, 0, true)
----
Expand Down Expand Up @@ -2155,6 +2175,8 @@ CREATE TABLE test.pg_constraintdef_test (
a int,
b int unique,
c int check (c > a),
d string,
UNIQUE INDEX (a) WHERE d = 'foo',
FOREIGN KEY(a) REFERENCES test.pg_indexdef_test(a) ON DELETE CASCADE
)

Expand All @@ -2164,6 +2186,7 @@ FROM pg_catalog.pg_constraint
WHERE conrelid='pg_constraintdef_test'::regclass
----
UNIQUE (b ASC)
UNIQUE (a ASC) WHERE d = 'foo'::STRING
FOREIGN KEY (a) REFERENCES pg_indexdef_test(a) ON DELETE CASCADE
CHECK ((c > a))

Expand Down Expand Up @@ -2543,12 +2566,12 @@ NULL
query I
SELECT crdb_internal.get_namespace_id(0, 'root_test')
----
61
63

query I
SELECT crdb_internal.get_namespace_id(crdb_internal.get_namespace_id(0, 'root_test'), 't')
----
62
64

query T
SELECT crdb_internal.get_zone_config(-1)::string
Expand Down Expand Up @@ -2598,12 +2621,12 @@ user testuser
query I
SELECT crdb_internal.get_namespace_id(0, 'root_test')
----
61
63

query I
SELECT crdb_internal.get_namespace_id(crdb_internal.get_namespace_id(0, 'root_test'), 't')
----
62
64

query T
SELECT crdb_internal.get_zone_config(crdb_internal.get_namespace_id(0, 'root_test'))::string
Expand Down
15 changes: 15 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/partial_index
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,21 @@ t10 CREATE TABLE public.t10 (
FAMILY "primary" (a, b, rowid)
)

# SHOW CONSTRAINTS includes partial index predicate of UNIQUE partial indexes.

statement ok
CREATE TABLE t11 (a INT, b INT, UNIQUE INDEX (a) WHERE b > 0)

statement ok
CREATE UNIQUE INDEX t11_b_key ON t11 (b) WHERE a > 0

query TTTTB colnames
SHOW CONSTRAINTS FROM t11
----
table_name constraint_name constraint_type details validated
t11 t11_a_key UNIQUE UNIQUE (a ASC) WHERE b > 0 true
t11 t11_b_key UNIQUE UNIQUE (b ASC) WHERE a > 0 true

# Update a non-indexed column referenced by the predicate.

statement ok
Expand Down
53 changes: 46 additions & 7 deletions pkg/sql/logictest/testdata/logic_test/pg_catalog
Original file line number Diff line number Diff line change
Expand Up @@ -2535,24 +2535,63 @@ primary CREATE UNIQUE INDEX "primary" ON test.public.geospatial_table USING b
idxa CREATE INDEX idxa ON test.public.geospatial_table USING gin (a ASC)
idxb CREATE INDEX idxb ON test.public.geospatial_table USING gin (b ASC)

subtest partial_index

statement ok
SET DATABASE = test

statement ok
CREATE TYPE testenum AS ENUM ('foo', 'bar', 'baz')

statement ok
CREATE TABLE partial_index_table (
a INT,
b testenum,
UNIQUE INDEX (a) WHERE a > 0
)

statement ok
CREATE UNIQUE INDEX ON partial_index_table (a) WHERE b IN ('foo', 'bar')

query TT colnames
SELECT indexname, indexdef
FROM pg_catalog.pg_indexes
WHERE tablename = 'partial_index_table'
----
indexname indexdef
primary CREATE UNIQUE INDEX "primary" ON test.public.partial_index_table USING btree (rowid ASC)
partial_index_table_a_key CREATE UNIQUE INDEX partial_index_table_a_key ON test.public.partial_index_table USING btree (a ASC) WHERE a > 0
partial_index_table_a_key1 CREATE UNIQUE INDEX partial_index_table_a_key1 ON test.public.partial_index_table USING btree (a ASC) WHERE b IN ('foo'::public.testenum, 'bar'::public.testenum)

query TT colnames
SELECT conname, condef
FROM pg_catalog.pg_constraint c JOIN pg_catalog.pg_class t
ON c.conrelid = t.oid
WHERE t.relname = 'partial_index_table'
ORDER BY conname
----
conname condef
partial_index_table_a_key UNIQUE (a ASC) WHERE a > 0
partial_index_table_a_key1 UNIQUE (a ASC) WHERE b IN ('foo'::public.testenum, 'bar'::public.testenum)

subtest regression_46799
statement ok
CREATE TABLE t(x INT DEFAULT 1, y INT DEFAULT 1);
CREATE TABLE t46799 (x INT DEFAULT 1, y INT DEFAULT 1);

query I
SELECT adnum FROM pg_attrdef WHERE adrelid = 91
SELECT adnum FROM pg_attrdef WHERE adrelid = 't46799'::REGCLASS
----
1
2
3

statement ok
ALTER TABLE t DROP COLUMN y;
ALTER TABLE t ADD COLUMN y INT DEFAULT 1;
ALTER TABLE t46799 DROP COLUMN y;
ALTER TABLE t46799 ADD COLUMN y INT DEFAULT 1;

# Make sure after adding and dropping the same column, the adnum for the re-added column increases.
query I
select adnum from pg_attrdef WHERE adrelid = 91
select adnum from pg_attrdef WHERE adrelid = 't46799'::REGCLASS
----
1
3
Expand All @@ -2565,13 +2604,13 @@ CREATE TABLE jt (a INT PRIMARY KEY); INSERT INTO jt VALUES(1); INSERT INTO jt VA
query ITT
SELECT a, oid, relname FROM jt INNER LOOKUP JOIN pg_class ON a::oid=oid
----
92 92 jt
95 95 jt

query ITT
SELECT a, oid, relname FROM jt LEFT OUTER LOOKUP JOIN pg_class ON a::oid=oid
----
1 NULL NULL
92 92 jt
95 95 jt

subtest regression_49207
statement ok
Expand Down
30 changes: 28 additions & 2 deletions pkg/sql/pg_catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/catalog/schemadesc"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/tabledesc"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/typedesc"
"github.com/cockroachdb/cockroach/pkg/sql/parser"
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
"github.com/cockroachdb/cockroach/pkg/sql/schemaexpr"
Expand Down Expand Up @@ -961,6 +962,14 @@ func populateTableConstraints(
f.WriteString("UNIQUE (")
con.Index.ColNamesFormat(f)
f.WriteByte(')')
if con.Index.IsPartial() {
pred, err := schemaexpr.FormatExprForDisplay(ctx, table, con.Index.Predicate, p.SemaCtx(), tree.FmtPGCatalog)
if err != nil {
return err
}
f.WriteString(" WHERE ")
f.WriteString(pred)
}
condef = tree.NewDString(f.CloseAndGetString())

case descpb.ConstraintTypeCheck:
Expand Down Expand Up @@ -1203,7 +1212,7 @@ CREATE TABLE pg_catalog.pg_conversion (
conforencoding INT4,
contoencoding INT4,
conproc OID,
condefault BOOL
condefault BOOL
)`,
populate: func(ctx context.Context, p *planner, dbContext *dbdesc.Immutable, addRow func(...tree.Datum) error) error {
return nil
Expand Down Expand Up @@ -1826,7 +1835,24 @@ func indexDefFromDescriptor(
}
indexDef.Interleave = intlDef
}
fmtCtx := tree.NewFmtCtx(tree.FmtPGIndexDef)
if index.IsPartial() {
// Format the raw predicate for display in order to resolve user-defined
// types to a human readable form.
//
// TODO(mgartner): Avoid parsing the predicate expression twice. It is
// parsed in schemaexpr.FormatExprForDisplay and again here.
formattedPred, err := schemaexpr.FormatExprForDisplay(ctx, table, index.Predicate, p.SemaCtx(), tree.FmtPGCatalog)
if err != nil {
return "", err
}

pred, err := parser.ParseExpr(formattedPred)
if err != nil {
return "", err
}
indexDef.Predicate = pred
}
fmtCtx := tree.NewFmtCtx(tree.FmtPGCatalog)
fmtCtx.FormatNode(&indexDef)
return fmtCtx.String(), nil
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/sql/sem/tree/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func (node *CreateIndex) Format(ctx *FmtCtx) {
if node.Unique {
ctx.WriteString("UNIQUE ")
}
if node.Inverted && !ctx.HasFlags(FmtPGIndexDef) {
if node.Inverted && !ctx.HasFlags(FmtPGCatalog) {
ctx.WriteString("INVERTED ")
}
ctx.WriteString("INDEX ")
Expand All @@ -143,7 +143,7 @@ func (node *CreateIndex) Format(ctx *FmtCtx) {
}
ctx.WriteString("ON ")
ctx.FormatNode(&node.Table)
if ctx.HasFlags(FmtPGIndexDef) {
if ctx.HasFlags(FmtPGCatalog) {
ctx.WriteString(" USING")
if node.Inverted {
ctx.WriteString(" gin")
Expand Down
11 changes: 4 additions & 7 deletions pkg/sql/sem/tree/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,12 @@ const (

// FmtPGCatalog is used to produce expressions formatted in a way that's as
// close as possible to what clients expect to live in pg_catalog (e.g.
// pg_attrdef.adbin and pg_constraint.condef columns). Specifically, this
// strips type annotations, since Postgres doesn't know what those are, and
// adds cast expressions for non-numeric constants.
// pg_attrdef.adbin, pg_constraint.condef and pg_indexes.indexdef columns).
// Specifically, this strips type annotations (Postgres doesn't know what
// those are), adds cast expressions for non-numeric constants, and formats
// indexes in Postgres-specific syntax.
FmtPGCatalog

// FmtPGIndexDef is used to produce CREATE INDEX statements that are
// compatible with pg_get_indexdef.
FmtPGIndexDef

// If set, user defined types and datums of user defined types will be
// formatted in a way that is stable across changes to the underlying type.
// For type names, this means that they will be formatted as '@id'. For enum
Expand Down