Commit 2ac28f8f authored by Rohan Yadav's avatar Rohan Yadav

sql: enable creation of indexes on tables with user defined types

Work for #48728.

This PR teaches the index backfill infrastructure to hydrate types
before use.

Release note: None
parent fd1bccfd
......@@ -17,6 +17,7 @@ import (
"github.com/cockroachdb/cockroach/pkg/kv"
"github.com/cockroachdb/cockroach/pkg/roachpb"
"github.com/cockroachdb/cockroach/pkg/sql/execinfrapb"
"github.com/cockroachdb/cockroach/pkg/sql/row"
"github.com/cockroachdb/cockroach/pkg/sql/sem/transform"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
......@@ -364,6 +365,25 @@ func (ib *IndexBackfiller) Init(
ib.types[i] = cols[i].Type
}
// Hydrate types used by the backfiller.
// TODO (rohany): As part of #49261, this needs to use cached enum data.
if evalCtx.Txn != nil {
// If the evalCtx has a transaction (if the schema change is running on a
// new table within a transaction), then use that.
if err := execinfrapb.HydrateTypeSlice(evalCtx, ib.types); err != nil {
return err
}
} else {
// Otherwise, make a new transaction. This case will happen when we are
// performing a distributed schema change outside of a transaction.
if err := ib.evalCtx.DB.Txn(evalCtx.Context, func(_ context.Context, txn *kv.Txn) error {
evalCtx.Txn = txn
return execinfrapb.HydrateTypeSlice(evalCtx, ib.types)
}); err != nil {
return err
}
}
ib.colIdxMap = make(map[sqlbase.ColumnID]int, len(cols))
for i := range cols {
ib.colIdxMap[cols[i].ID] = i
......
......@@ -585,3 +585,84 @@ enum_checks CREATE TABLE enum_checks (
CONSTRAINT check_x CHECK (x = 'hello':::test.public.greeting::test.public.greeting),
CONSTRAINT "check" CHECK ('hello':::test.public.greeting = 'hello':::test.public.greeting)
)
subtest schema_changes
# Ensure that we can drop and create indexes on user defined type columns,
# as well as on other columns when the table has a user defined type column.
statement ok
CREATE TABLE sc (x greeting NOT NULL, y int NOT NULL);
INSERT INTO sc VALUES ('hello', 0), ('howdy', 1), ('hi', 2);
statement ok
CREATE INDEX i1 ON sc (x);
CREATE INDEX i2 ON sc (y);
CREATE INDEX i3 ON sc (x, y)
query T rowsort
SELECT x FROM [email protected]
----
hello
howdy
hi
query TI rowsort
SELECT x, y FROM [email protected]
----
hello 0
howdy 1
hi 2
statement ok
DROP INDEX [email protected];
DROP INDEX [email protected];
DROP INDEX [email protected]
# Test the above, but exercise the schema change in txn code path.
statement ok
DROP TABLE sc
statement ok
BEGIN;
CREATE TABLE sc (x greeting NOT NULL, y int NOT NULL);
INSERT INTO sc VALUES ('hello', 0), ('howdy', 1), ('hi', 2);
CREATE INDEX i1 ON sc (x);
CREATE INDEX i2 ON sc (y);
CREATE INDEX i3 ON sc (x, y)
query T rowsort
SELECT x FROM [email protected]
----
hello
howdy
hi
query TI rowsort
SELECT x, y FROM [email protected]
----
hello 0
howdy 1
hi 2
statement ok
DROP INDEX [email protected];
DROP INDEX [email protected];
DROP INDEX [email protected];
COMMIT
# Ensure that we can create an index on a table and type created in
# the same transaction.
statement ok
BEGIN;
CREATE TYPE in_txn AS ENUM ('in', 'txn');
CREATE TABLE tbl_in_txn (x in_txn);
INSERT INTO tbl_in_txn VALUES ('txn');
CREATE INDEX i ON tbl_in_txn (x)
query T
SELECT * FROM [email protected]
----
txn
statement ok
ROLLBACK
......@@ -79,7 +79,11 @@ func newIndexBackfiller(
}
ib.backfiller.chunks = ib
if err := ib.IndexBackfiller.Init(flowCtx.NewEvalCtx(), ib.desc); err != nil {
// Copy in the DB pointer from flowCtx into evalCtx, because the Init
// step needs access to the DB.
evalCtx := flowCtx.NewEvalCtx()
evalCtx.DB = flowCtx.Cfg.DB
if err := ib.IndexBackfiller.Init(evalCtx, ib.desc); err != nil {
return nil, err
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment