Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
49335: sql: parse partial indexes r=mgartner a=mgartner

This commit adds support for parsing partial indexes. The parser can now
parse statements like:

    CREATE TABLE t (a INT, INDEX (a) WHERE a > 3)
    CREATE TABLE t (a INT, UNIQUE INDEX (a) WHERE a > 3)
    CREATE INDEX i ON t (a) WHERE a > 3

Note that these `WHERE` clauses have no effect as of this commit. Until
further work is done, the `WHERE` clauses are ignored and full indexes
are created.

This commit also adds the ability to format the `Predicate` expression
of `tree.CreateIndex` and `tree.IndexTableDef` expressions.

A temporary session setting has been added called `partial_indexes`.
When set to true, it enables the user to create partial indexes. By
default, it is false because partial indexes are not fully supported.
Once partial indexes are fully functional, this setting will be removed.

Release note: None

Co-authored-by: Marcus Gartner <[email protected]>
  • Loading branch information
craig[bot] and mgartner committed May 22, 2020
2 parents 0085cf4 + b774f2e commit d7985c5
Show file tree
Hide file tree
Showing 18 changed files with 156 additions and 62 deletions.
16 changes: 8 additions & 8 deletions docs/generated/sql/bnf/create_index_interleaved_stmt.bnf
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
create_index_stmt ::=
'CREATE' 'UNIQUE' 'INDEX' opt_concurrently '...' opt_hash_sharded 'STORING' '(' stored_columns ')' 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')'
| 'CREATE' 'UNIQUE' 'INDEX' opt_concurrently '...' opt_hash_sharded 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')'
| 'CREATE' 'INDEX' opt_concurrently '...' opt_hash_sharded 'STORING' '(' stored_columns ')' 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')'
| 'CREATE' 'INDEX' opt_concurrently '...' opt_hash_sharded 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')'
| 'CREATE' 'UNIQUE' 'INVERTED' 'INDEX' opt_concurrently '...' 'STORING' '(' stored_columns ')' 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')'
| 'CREATE' 'UNIQUE' 'INVERTED' 'INDEX' opt_concurrently '...' 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')'
| 'CREATE' 'INVERTED' 'INDEX' opt_concurrently '...' 'STORING' '(' stored_columns ')' 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')'
| 'CREATE' 'INVERTED' 'INDEX' opt_concurrently '...' 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')'
'CREATE' 'UNIQUE' 'INDEX' opt_concurrently '...' opt_hash_sharded 'STORING' '(' stored_columns ')' 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')' opt_where_clause
| 'CREATE' 'UNIQUE' 'INDEX' opt_concurrently '...' opt_hash_sharded 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')' opt_where_clause
| 'CREATE' 'INDEX' opt_concurrently '...' opt_hash_sharded 'STORING' '(' stored_columns ')' 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')' opt_where_clause
| 'CREATE' 'INDEX' opt_concurrently '...' opt_hash_sharded 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')' opt_where_clause
| 'CREATE' 'UNIQUE' 'INVERTED' 'INDEX' opt_concurrently '...' 'STORING' '(' stored_columns ')' 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')' opt_where_clause
| 'CREATE' 'UNIQUE' 'INVERTED' 'INDEX' opt_concurrently '...' 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')' opt_where_clause
| 'CREATE' 'INVERTED' 'INDEX' opt_concurrently '...' 'STORING' '(' stored_columns ')' 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')' opt_where_clause
| 'CREATE' 'INVERTED' 'INDEX' opt_concurrently '...' 'INTERLEAVE' 'IN' 'PARENT' parent_table '(' interleave_prefix ')' opt_where_clause
4 changes: 2 additions & 2 deletions docs/generated/sql/bnf/create_index_stmt.bnf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
create_index_stmt ::=
'CREATE' ( 'UNIQUE' | ) 'INDEX' opt_concurrently opt_index_name 'ON' table_name ( 'USING' name | ) '(' ( ( ( column_name ( 'ASC' | 'DESC' | ) ) ) ( ( ',' ( column_name ( 'ASC' | 'DESC' | ) ) ) )* ) ')' opt_hash_sharded ( ( 'COVERING' | 'STORING' | 'INCLUDE' ) '(' name_list ')' | ) opt_interleave opt_partition_by
| 'CREATE' ( 'UNIQUE' | ) 'INDEX' opt_concurrently 'IF' 'NOT' 'EXISTS' index_name 'ON' table_name ( 'USING' name | ) '(' ( ( ( column_name ( 'ASC' | 'DESC' | ) ) ) ( ( ',' ( column_name ( 'ASC' | 'DESC' | ) ) ) )* ) ')' opt_hash_sharded ( ( 'COVERING' | 'STORING' | 'INCLUDE' ) '(' name_list ')' | ) opt_interleave opt_partition_by
'CREATE' ( 'UNIQUE' | ) 'INDEX' opt_concurrently opt_index_name 'ON' table_name ( 'USING' name | ) '(' ( ( ( column_name ( 'ASC' | 'DESC' | ) ) ) ( ( ',' ( column_name ( 'ASC' | 'DESC' | ) ) ) )* ) ')' opt_hash_sharded ( ( 'COVERING' | 'STORING' | 'INCLUDE' ) '(' name_list ')' | ) opt_interleave opt_partition_by opt_where_clause
| 'CREATE' ( 'UNIQUE' | ) 'INDEX' opt_concurrently 'IF' 'NOT' 'EXISTS' index_name 'ON' table_name ( 'USING' name | ) '(' ( ( ( column_name ( 'ASC' | 'DESC' | ) ) ) ( ( ',' ( column_name ( 'ASC' | 'DESC' | ) ) ) )* ) ')' opt_hash_sharded ( ( 'COVERING' | 'STORING' | 'INCLUDE' ) '(' name_list ')' | ) opt_interleave opt_partition_by opt_where_clause


20 changes: 10 additions & 10 deletions docs/generated/sql/bnf/index_def.bnf
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
index_def ::=
'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded 'COVERING' '(' name_list ')' opt_interleave opt_partition_by
| 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded 'STORING' '(' name_list ')' opt_interleave opt_partition_by
| 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded 'INCLUDE' '(' name_list ')' opt_interleave opt_partition_by
| 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded opt_interleave opt_partition_by
| 'UNIQUE' 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded 'COVERING' '(' name_list ')' opt_interleave opt_partition_by
| 'UNIQUE' 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded 'STORING' '(' name_list ')' opt_interleave opt_partition_by
| 'UNIQUE' 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded 'INCLUDE' '(' name_list ')' opt_interleave opt_partition_by
| 'UNIQUE' 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded opt_interleave opt_partition_by
| 'INVERTED' 'INDEX' name '(' index_elem ( ( ',' index_elem ) )* ')'
| 'INVERTED' 'INDEX' '(' index_elem ( ( ',' index_elem ) )* ')'
'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded 'COVERING' '(' name_list ')' opt_interleave opt_partition_by opt_where_clause
| 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded 'STORING' '(' name_list ')' opt_interleave opt_partition_by opt_where_clause
| 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded 'INCLUDE' '(' name_list ')' opt_interleave opt_partition_by opt_where_clause
| 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded opt_interleave opt_partition_by opt_where_clause
| 'UNIQUE' 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded 'COVERING' '(' name_list ')' opt_interleave opt_partition_by opt_where_clause
| 'UNIQUE' 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded 'STORING' '(' name_list ')' opt_interleave opt_partition_by opt_where_clause
| 'UNIQUE' 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded 'INCLUDE' '(' name_list ')' opt_interleave opt_partition_by opt_where_clause
| 'UNIQUE' 'INDEX' opt_index_name '(' index_elem ( ( ',' index_elem ) )* ')' opt_hash_sharded opt_interleave opt_partition_by opt_where_clause
| 'INVERTED' 'INDEX' name '(' index_elem ( ( ',' index_elem ) )* ')' opt_where_clause
| 'INVERTED' 'INDEX' '(' index_elem ( ( ',' index_elem ) )* ')' opt_where_clause
16 changes: 8 additions & 8 deletions docs/generated/sql/bnf/stmt_block.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -1025,10 +1025,10 @@ create_database_stmt ::=
| 'CREATE' 'DATABASE' 'IF' 'NOT' 'EXISTS' database_name opt_with opt_template_clause opt_encoding_clause opt_lc_collate_clause opt_lc_ctype_clause

create_index_stmt ::=
'CREATE' opt_unique 'INDEX' opt_concurrently opt_index_name 'ON' table_name opt_using_gin_btree '(' index_params ')' opt_hash_sharded opt_storing opt_interleave opt_partition_by
| 'CREATE' opt_unique 'INDEX' opt_concurrently 'IF' 'NOT' 'EXISTS' index_name 'ON' table_name opt_using_gin_btree '(' index_params ')' opt_hash_sharded opt_storing opt_interleave opt_partition_by
| 'CREATE' opt_unique 'INVERTED' 'INDEX' opt_concurrently opt_index_name 'ON' table_name '(' index_params ')' opt_storing opt_interleave opt_partition_by
| 'CREATE' opt_unique 'INVERTED' 'INDEX' opt_concurrently 'IF' 'NOT' 'EXISTS' index_name 'ON' table_name '(' index_params ')' opt_storing opt_interleave opt_partition_by
'CREATE' opt_unique 'INDEX' opt_concurrently opt_index_name 'ON' table_name opt_using_gin_btree '(' index_params ')' opt_hash_sharded opt_storing opt_interleave opt_partition_by opt_where_clause
| 'CREATE' opt_unique 'INDEX' opt_concurrently 'IF' 'NOT' 'EXISTS' index_name 'ON' table_name opt_using_gin_btree '(' index_params ')' opt_hash_sharded opt_storing opt_interleave opt_partition_by opt_where_clause
| 'CREATE' opt_unique 'INVERTED' 'INDEX' opt_concurrently opt_index_name 'ON' table_name '(' index_params ')' opt_storing opt_interleave opt_partition_by opt_where_clause
| 'CREATE' opt_unique 'INVERTED' 'INDEX' opt_concurrently 'IF' 'NOT' 'EXISTS' index_name 'ON' table_name '(' index_params ')' opt_storing opt_interleave opt_partition_by opt_where_clause

create_schema_stmt ::=
'CREATE' 'SCHEMA' schema_name
Expand Down Expand Up @@ -1537,9 +1537,9 @@ column_def ::=
column_name typename col_qual_list

index_def ::=
'INDEX' opt_index_name '(' index_params ')' opt_hash_sharded opt_storing opt_interleave opt_partition_by
| 'UNIQUE' 'INDEX' opt_index_name '(' index_params ')' opt_hash_sharded opt_storing opt_interleave opt_partition_by
| 'INVERTED' 'INDEX' opt_name '(' index_params ')'
'INDEX' opt_index_name '(' index_params ')' opt_hash_sharded opt_storing opt_interleave opt_partition_by opt_where_clause
| 'UNIQUE' 'INDEX' opt_index_name '(' index_params ')' opt_hash_sharded opt_storing opt_interleave opt_partition_by opt_where_clause
| 'INVERTED' 'INDEX' opt_name '(' index_params ')' opt_where_clause

family_def ::=
'FAMILY' opt_family_name '(' name_list ')'
Expand Down Expand Up @@ -1867,7 +1867,7 @@ constraint_name ::=

constraint_elem ::=
'CHECK' '(' a_expr ')'
| 'UNIQUE' '(' index_params ')' opt_storing opt_interleave opt_partition_by
| 'UNIQUE' '(' index_params ')' opt_storing opt_interleave opt_partition_by opt_where_clause
| 'PRIMARY' 'KEY' '(' index_params ')' opt_hash_sharded opt_interleave
| 'FOREIGN' 'KEY' '(' name_list ')' 'REFERENCES' table_name opt_column_list key_match reference_actions

Expand Down
16 changes: 8 additions & 8 deletions docs/generated/sql/bnf/table_constraint.bnf
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
table_constraint ::=
'CONSTRAINT' constraint_name 'CHECK' '(' a_expr ')'
| 'CONSTRAINT' constraint_name 'UNIQUE' '(' index_params ')' 'COVERING' '(' name_list ')' opt_interleave opt_partition_by
| 'CONSTRAINT' constraint_name 'UNIQUE' '(' index_params ')' 'STORING' '(' name_list ')' opt_interleave opt_partition_by
| 'CONSTRAINT' constraint_name 'UNIQUE' '(' index_params ')' 'INCLUDE' '(' name_list ')' opt_interleave opt_partition_by
| 'CONSTRAINT' constraint_name 'UNIQUE' '(' index_params ')' opt_interleave opt_partition_by
| 'CONSTRAINT' constraint_name 'UNIQUE' '(' index_params ')' 'COVERING' '(' name_list ')' opt_interleave opt_partition_by opt_where_clause
| 'CONSTRAINT' constraint_name 'UNIQUE' '(' index_params ')' 'STORING' '(' name_list ')' opt_interleave opt_partition_by opt_where_clause
| 'CONSTRAINT' constraint_name 'UNIQUE' '(' index_params ')' 'INCLUDE' '(' name_list ')' opt_interleave opt_partition_by opt_where_clause
| 'CONSTRAINT' constraint_name 'UNIQUE' '(' index_params ')' opt_interleave opt_partition_by opt_where_clause
| 'CONSTRAINT' constraint_name 'PRIMARY' 'KEY' '(' index_params ')' opt_hash_sharded opt_interleave
| 'CONSTRAINT' constraint_name 'FOREIGN' 'KEY' '(' name_list ')' 'REFERENCES' table_name opt_column_list key_match reference_actions
| 'CHECK' '(' a_expr ')'
| 'UNIQUE' '(' index_params ')' 'COVERING' '(' name_list ')' opt_interleave opt_partition_by
| 'UNIQUE' '(' index_params ')' 'STORING' '(' name_list ')' opt_interleave opt_partition_by
| 'UNIQUE' '(' index_params ')' 'INCLUDE' '(' name_list ')' opt_interleave opt_partition_by
| 'UNIQUE' '(' index_params ')' opt_interleave opt_partition_by
| 'UNIQUE' '(' index_params ')' 'COVERING' '(' name_list ')' opt_interleave opt_partition_by opt_where_clause
| 'UNIQUE' '(' index_params ')' 'STORING' '(' name_list ')' opt_interleave opt_partition_by opt_where_clause
| 'UNIQUE' '(' index_params ')' 'INCLUDE' '(' name_list ')' opt_interleave opt_partition_by opt_where_clause
| 'UNIQUE' '(' index_params ')' opt_interleave opt_partition_by opt_where_clause
| 'PRIMARY' 'KEY' '(' index_params ')' opt_hash_sharded opt_interleave
| 'FOREIGN' 'KEY' '(' name_list ')' 'REFERENCES' table_name opt_column_list key_match reference_actions
6 changes: 6 additions & 0 deletions pkg/sql/create_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
"github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry"
"github.com/cockroachdb/cockroach/pkg/sql/types"
"github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented"
"github.com/cockroachdb/errors"
)

Expand Down Expand Up @@ -198,6 +199,11 @@ func MakeIndexDescriptor(
telemetry.Inc(sqltelemetry.HashShardedIndexCounter)
}

// TODO(mgartner): remove this once partial indexes are fully supported.
if n.Predicate != nil && !params.SessionData().PartialIndexes {
return nil, unimplemented.NewWithIssue(9683, "partial indexes are not supported")
}

if err := indexDesc.FillColumns(n.Columns); err != nil {
return nil, err
}
Expand Down
8 changes: 8 additions & 0 deletions pkg/sql/create_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -1465,6 +1465,10 @@ func MakeTableDesc(
}
idx.Partitioning = partitioning
}
// TODO(mgartner): remove this once partial indexes are fully supported.
if d.Predicate != nil && !sessionData.PartialIndexes {
return desc, unimplemented.NewWithIssue(9683, "partial indexes are not supported")
}

if err := desc.AddIndex(idx, false); err != nil {
return desc, err
Expand Down Expand Up @@ -1497,6 +1501,10 @@ func MakeTableDesc(
}
idx.Partitioning = partitioning
}
// TODO(mgartner): remove this once partial indexes are fully supported.
if d.Predicate != nil && !sessionData.PartialIndexes {
return desc, unimplemented.NewWithIssue(9683, "partial indexes are not supported")
}
if err := desc.AddIndex(idx, d.PrimaryKey); err != nil {
return desc, err
}
Expand Down
12 changes: 12 additions & 0 deletions pkg/sql/exec_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,13 @@ var optUseMultiColStatsClusterMode = settings.RegisterBoolSetting(
true,
)

// TODO(mgartner): Remove this setting once partial indexes are fully supported.
var partialIndexClusterMode = settings.RegisterBoolSetting(
"sql.defaults.experimental_partial_indexes.enabled",
"default value for experimental_partial_indexes session setting; disables creation of partial indexes by default",
false,
)

var implicitSelectForUpdateClusterMode = settings.RegisterBoolSetting(
"sql.defaults.implicit_select_for_update.enabled",
"default value for enable_implicit_select_for_update session setting; enables FOR UPDATE locking during the row-fetch phase of mutation statements",
Expand Down Expand Up @@ -1981,6 +1988,11 @@ func (m *sessionDataMutator) SetOptimizerUseMultiColStats(val bool) {
m.data.OptimizerUseMultiColStats = val
}

// TODO(mgartner): remove this once partial indexes are fully supported.
func (m *sessionDataMutator) SetPartialIndexes(val bool) {
m.data.PartialIndexes = val
}

func (m *sessionDataMutator) SetImplicitSelectForUpdate(val bool) {
m.data.ImplicitSelectForUpdate = val
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/sql/explain_bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,8 @@ func (c *stmtEnvCollector) PrintSettings(w io.Writer) error {
{sessionSetting: "experimental_optimizer_foreign_key_cascades", clusterSetting: optDrivenFKCascadesClusterMode},
{sessionSetting: "optimizer_use_histograms", clusterSetting: optUseHistogramsClusterMode},
{sessionSetting: "optimizer_use_multicol_stats", clusterSetting: optUseMultiColStatsClusterMode},
// TODO(mgartner): remove this once partial indexes are fully supported.
{sessionSetting: "experimental_partial_indexes", clusterSetting: partialIndexClusterMode},
}

for _, s := range relevantSettings {
Expand Down
3 changes: 3 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/pg_catalog
Original file line number Diff line number Diff line change
Expand Up @@ -1714,6 +1714,7 @@ enable_zigzag_join on NULL NULL
experimental_enable_hash_sharded_indexes off NULL NULL NULL string
experimental_enable_temp_tables off NULL NULL NULL string
experimental_optimizer_foreign_key_cascades on NULL NULL NULL string
experimental_partial_indexes off NULL NULL NULL string
extra_float_digits 0 NULL NULL NULL string
force_savepoint_restart off NULL NULL NULL string
foreign_key_cascades_limit 10000 NULL NULL NULL string
Expand Down Expand Up @@ -1778,6 +1779,7 @@ enable_zigzag_join on NULL user
experimental_enable_hash_sharded_indexes off NULL user NULL off off
experimental_enable_temp_tables off NULL user NULL off off
experimental_optimizer_foreign_key_cascades on NULL user NULL on on
experimental_partial_indexes off NULL user NULL off off
extra_float_digits 0 NULL user NULL 0 2
force_savepoint_restart off NULL user NULL off off
foreign_key_cascades_limit 10000 NULL user NULL 10000 10000
Expand Down Expand Up @@ -1838,6 +1840,7 @@ enable_zigzag_join NULL NULL NULL NULL
experimental_enable_hash_sharded_indexes NULL NULL NULL NULL NULL
experimental_enable_temp_tables NULL NULL NULL NULL NULL
experimental_optimizer_foreign_key_cascades NULL NULL NULL NULL NULL
experimental_partial_indexes NULL NULL NULL NULL NULL
extra_float_digits NULL NULL NULL NULL NULL
force_savepoint_restart NULL NULL NULL NULL NULL
foreign_key_cascades_limit NULL NULL NULL NULL NULL
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/logictest/testdata/logic_test/show_source
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ enable_zigzag_join on
experimental_enable_hash_sharded_indexes off
experimental_enable_temp_tables off
experimental_optimizer_foreign_key_cascades on
experimental_partial_indexes off
extra_float_digits 0
force_savepoint_restart off
foreign_key_cascades_limit 10000
Expand Down
Loading

0 comments on commit d7985c5

Please sign in to comment.