Skip to content

Commit

Permalink
sql: add ALTER RANGE RELOCATE
Browse files Browse the repository at this point in the history
This commit introduces a new ALTER RANGE RELOCATE
command, which will allow an admin to move a lease
or replica for a specific range. Unlike ALTER TABLE RELOCATE
this command works on a range_id, which makes it a lot easier
to use since the user does not have to worry about range keys, which
are difficult to deal with in an emergncy situation.

Release note (sql change): Introduce new SQL syntax ALTER RANGE RELOCATE
to move a lease or replica between stores. This is helpful in an emergency
situation to relocate data in the cluster.
  • Loading branch information
lunevalex committed Nov 1, 2021
1 parent e9b69a8 commit 9843c0d
Show file tree
Hide file tree
Showing 29 changed files with 430 additions and 11 deletions.
1 change: 1 addition & 0 deletions docs/generated/sql/bnf/alter_index_stmt.bnf
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
alter_index_stmt ::=
alter_oneindex_stmt
| alter_relocate_index_stmt
| alter_split_index_stmt
| alter_unsplit_index_stmt
| alter_scatter_index_stmt
Expand Down
2 changes: 2 additions & 0 deletions docs/generated/sql/bnf/alter_range_relocate_lease_stmt.bnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alter_range_relocate_lease_stmt ::=
'ALTER' 'RANGE' iconst64 relocate_kw 'LEASE' 'TO' iconst64
1 change: 1 addition & 0 deletions docs/generated/sql/bnf/alter_range_stmt.bnf
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
alter_range_stmt ::=
alter_zone_range_stmt
| alter_range_relocate_lease_stmt
3 changes: 3 additions & 0 deletions docs/generated/sql/bnf/alter_relocate_index_stmt.bnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
alter_relocate_index_stmt ::=
'ALTER' 'RANGE' iconst64 relocate_kw voters_kw 'FROM' iconst64 'TO' iconst64
| 'ALTER' 'RANGE' iconst64 relocate_kw voters_kw 'NON_VOTERS' iconst64 'TO' iconst64
19 changes: 19 additions & 0 deletions docs/generated/sql/bnf/stmt_block.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,7 @@ unreserved_keyword ::=
| 'REGIONS'
| 'REINDEX'
| 'RELEASE'
| 'RELOCATE'
| 'RENAME'
| 'REPEATABLE'
| 'REPLACE'
Expand Down Expand Up @@ -1320,6 +1321,7 @@ alter_table_stmt ::=

alter_index_stmt ::=
alter_oneindex_stmt
| alter_relocate_index_stmt
| alter_split_index_stmt
| alter_unsplit_index_stmt
| alter_scatter_index_stmt
Expand Down Expand Up @@ -1349,6 +1351,7 @@ alter_database_stmt ::=

alter_range_stmt ::=
alter_zone_range_stmt
| alter_range_relocate_lease_stmt

alter_partition_stmt ::=
alter_zone_partition_stmt
Expand Down Expand Up @@ -1760,6 +1763,10 @@ alter_oneindex_stmt ::=
'ALTER' 'INDEX' table_index_name alter_index_cmds
| 'ALTER' 'INDEX' 'IF' 'EXISTS' table_index_name alter_index_cmds

alter_relocate_index_stmt ::=
'ALTER' 'RANGE' iconst64 relocate_kw voters_kw 'FROM' iconst64 'TO' iconst64
| 'ALTER' 'RANGE' iconst64 relocate_kw voters_kw 'NON_VOTERS' iconst64 'TO' iconst64

alter_split_index_stmt ::=
'ALTER' 'INDEX' table_index_name 'SPLIT' 'AT' select_stmt
| 'ALTER' 'INDEX' table_index_name 'SPLIT' 'AT' select_stmt 'WITH' 'EXPIRATION' a_expr
Expand Down Expand Up @@ -1843,6 +1850,9 @@ alter_database_primary_region_stmt ::=
alter_zone_range_stmt ::=
'ALTER' 'RANGE' zone_name set_zone_config

alter_range_relocate_lease_stmt ::=
'ALTER' 'RANGE' iconst64 relocate_kw 'LEASE' 'TO' iconst64

alter_zone_partition_stmt ::=
'ALTER' 'PARTITION' partition_name 'OF' 'TABLE' table_name set_zone_config
| 'ALTER' 'PARTITION' partition_name 'OF' 'INDEX' table_index_name set_zone_config
Expand Down Expand Up @@ -2328,6 +2338,15 @@ locality ::=
alter_index_cmds ::=
( alter_index_cmd ) ( ( ',' alter_index_cmd ) )*

relocate_kw ::=
'TESTING_RELOCATE'
| 'EXPERIMENTAL_RELOCATE'
| 'RELOCATE'

voters_kw ::=
'VOTERS'
|

sequence_option_list ::=
( sequence_option_elem ) ( ( sequence_option_elem ) )*

Expand Down
7 changes: 7 additions & 0 deletions pkg/sql/catalog/colinfo/result_columns.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,13 @@ var AlterTableScatterColumns = ResultColumns{
{Name: "pretty", Typ: types.String},
}

// AlterRangeRelocateColumns are the result columns of an
// ALTER RANGE .. RELOCATE statement.
var AlterRangeRelocateColumns = ResultColumns{
{Name: "key", Typ: types.Bytes},
{Name: "pretty", Typ: types.String},
}

// ScrubColumns are the result columns of a SCRUB statement.
var ScrubColumns = ResultColumns{
{Name: "job_uuid", Typ: types.Uuid},
Expand Down
6 changes: 6 additions & 0 deletions pkg/sql/distsql_spec_exec_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,12 @@ func (e *distSQLSpecExecFactory) ConstructAlterTableRelocate(
return nil, unimplemented.NewWithIssue(47473, "experimental opt-driven distsql planning: alter table relocate")
}

func (e *distSQLSpecExecFactory) ConstructAlterRangeRelocate(
relocateLease bool, relocateNonVoters bool, rangeID int64, toStoreID int64, fromStoreID int64,
) (exec.Node, error) {
return nil, unimplemented.NewWithIssue(47473, "experimental opt-driven distsql planning: alter range relocate")
}

func (e *distSQLSpecExecFactory) ConstructBuffer(input exec.Node, label string) (exec.Node, error) {
return nil, unimplemented.NewWithIssue(47473, "experimental opt-driven distsql planning: buffer")
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/sql/opt/exec/execbuilder/relational.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,9 @@ func (b *Builder) buildRelational(e memo.RelExpr) (execPlan, error) {
case *memo.AlterTableRelocateExpr:
ep, err = b.buildAlterTableRelocate(t)

case *memo.AlterRangeRelocateExpr:
ep, err = b.buildAlterRangeRelocate(t)

case *memo.ControlJobsExpr:
ep, err = b.buildControlJobs(t)

Expand Down
14 changes: 14 additions & 0 deletions pkg/sql/opt/exec/execbuilder/statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,20 @@ func (b *Builder) buildAlterTableRelocate(relocate *memo.AlterTableRelocateExpr)
return planWithColumns(node, relocate.Columns), nil
}

func (b *Builder) buildAlterRangeRelocate(relocate *memo.AlterRangeRelocateExpr) (execPlan, error) {
node, err := b.factory.ConstructAlterRangeRelocate(
relocate.RelocateLease,
relocate.RelocateNonVoters,
relocate.RangeID,
relocate.ToStoreID,
relocate.FromStoreID,
)
if err != nil {
return execPlan{}, err
}
return planWithColumns(node, relocate.Columns), nil
}

func (b *Builder) buildControlJobs(ctl *memo.ControlJobsExpr) (execPlan, error) {
input, err := b.buildRelational(ctl.Input)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions pkg/sql/opt/exec/explain/emit.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ func (e *emitter) nodeName(n *Node) (string, error) {
}

var nodeNames = [...]string{
alterRangeRelocateOp: "relocate",
alterTableRelocateOp: "relocate",
alterTableSplitOp: "split",
alterTableUnsplitAllOp: "unsplit all",
Expand Down Expand Up @@ -815,6 +816,7 @@ func (e *emitter) emitNodeAttributes(n *Node) error {
alterTableUnsplitOp,
alterTableUnsplitAllOp,
alterTableRelocateOp,
alterRangeRelocateOp,
controlJobsOp,
controlSchedulesOp,
cancelQueriesOp,
Expand Down
3 changes: 3 additions & 0 deletions pkg/sql/opt/exec/explain/result_columns.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ func getResultColumns(
case alterTableRelocateOp:
return colinfo.AlterTableRelocateColumns, nil

case alterRangeRelocateOp:
return colinfo.AlterRangeRelocateColumns, nil

case exportOp:
return colinfo.ExportColumns, nil

Expand Down
9 changes: 9 additions & 0 deletions pkg/sql/opt/exec/factory.opt
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,15 @@ define AlterTableRelocate {
relocateNonVoters bool
}

# AlterTableRelocate implements ALTER RANGE RELOCATE.
define AlterRangeRelocate {
relocateLease bool
relocateNonVoters bool
rangeId int64
toStoreId int64
fromStoreId int64
}

# Buffer passes through the input rows but also saves them in a buffer, which
# can be referenced from elsewhere in the query (using ScanBuffer).
define Buffer {
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/opt/memo/expr_format.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ func (f *ExprFmtCtx) formatRelational(e RelExpr, tp treeprinter.Node) {
*InsertExpr, *UpdateExpr, *UpsertExpr, *DeleteExpr, *SequenceSelectExpr,
*WindowExpr, *OpaqueRelExpr, *OpaqueMutationExpr, *OpaqueDDLExpr,
*AlterTableSplitExpr, *AlterTableUnsplitExpr, *AlterTableUnsplitAllExpr,
*AlterTableRelocateExpr, *ControlJobsExpr, *CancelQueriesExpr,
*AlterTableRelocateExpr, *AlterRangeRelocateExpr, *ControlJobsExpr, *CancelQueriesExpr,
*CancelSessionsExpr, *CreateViewExpr, *ExportExpr:
fmt.Fprintf(f.Buffer, "%v", e.Op())
FormatPrivate(f, e.Private(), required)
Expand Down
6 changes: 6 additions & 0 deletions pkg/sql/opt/memo/logical_props_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,12 @@ func (b *logicalPropsBuilder) buildAlterTableRelocateProps(
b.buildBasicProps(relocate, relocate.Columns, rel)
}

func (b *logicalPropsBuilder) buildAlterRangeRelocateProps(
relocate *AlterRangeRelocateExpr, rel *props.Relational,
) {
b.buildBasicProps(relocate, relocate.Columns, rel)
}

func (b *logicalPropsBuilder) buildControlJobsProps(ctl *ControlJobsExpr, rel *props.Relational) {
b.buildBasicProps(ctl, opt.ColList{}, rel)
}
Expand Down
21 changes: 21 additions & 0 deletions pkg/sql/opt/ops/statement.opt
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,24 @@ define CreateStatisticsPrivate {
# Syntax is the tree.CreateStats AST node.
Syntax CreateStats
}

# AlterTableRelocateRange represents an `ALTER RANGE .. RELOCATE ..` statement.
[Relational, Mutation]
define AlterRangeRelocate {
_ AlterRangeRelocatePrivate
}

[Private]
define AlterRangeRelocatePrivate {
RelocateLease bool
RelocateNonVoters bool
RangeID int64
ToStoreID int64
FromStoreID int64

# Columns stores the column IDs for the statement result columns.
Columns ColList

# Props stores the required physical properties for the input expression.
Props PhysProps
}
43 changes: 43 additions & 0 deletions pkg/sql/opt/optbuilder/alter_range.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2018 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package optbuilder

import (
"github.com/cockroachdb/cockroach/pkg/sql/catalog/colinfo"
"github.com/cockroachdb/cockroach/pkg/sql/opt/memo"
"github.com/cockroachdb/cockroach/pkg/sql/opt/props/physical"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
)

// buildAlterTableRelocate builds an ALTER RANGE RELOCATE (LEASE).
func (b *Builder) buildAlterRangeRelocate(
relocate *tree.RelocateRange, inScope *scope,
) (outScope *scope) {
//TODO(lunevalex) we need to go from a rangeId to a tableOrIndex name to get perms check to work

b.DisableMemoReuse = true

outScope = inScope.push()
b.synthesizeResultColumns(outScope, colinfo.AlterTableRelocateColumns)

outScope.expr = b.factory.ConstructAlterRangeRelocate(
&memo.AlterRangeRelocatePrivate{
RelocateLease: relocate.RelocateLease,
RelocateNonVoters: relocate.RelocateNonVoters,
RangeID: relocate.RangeID,
ToStoreID: relocate.ToStoreID,
FromStoreID: relocate.FromStoreID,
Columns: colsToColList(outScope.cols),
Props: physical.MinRequired,
},
)
return outScope
}
5 changes: 4 additions & 1 deletion pkg/sql/opt/optbuilder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ func (b *Builder) buildStmt(
// A blocklist of statements that can't be used from inside a view.
switch stmt := stmt.(type) {
case *tree.Delete, *tree.Insert, *tree.Update, *tree.CreateTable, *tree.CreateView,
*tree.Split, *tree.Unsplit, *tree.Relocate,
*tree.Split, *tree.Unsplit, *tree.Relocate, *tree.RelocateRange,
*tree.ControlJobs, *tree.ControlSchedules, *tree.CancelQueries, *tree.CancelSessions:
panic(pgerror.Newf(
pgcode.Syntax, "%s cannot be used inside a view definition", stmt.StatementTag(),
Expand Down Expand Up @@ -323,6 +323,9 @@ func (b *Builder) buildStmt(
case *tree.Relocate:
return b.buildAlterTableRelocate(stmt, inScope)

case *tree.RelocateRange:
return b.buildAlterRangeRelocate(stmt, inScope)

case *tree.ControlJobs:
return b.buildControlJobs(stmt, inScope)

Expand Down
5 changes: 5 additions & 0 deletions pkg/sql/opt/ordering/ordering.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,11 @@ func init() {
buildChildReqOrdering: alterTableRelocateBuildChildReqOrdering,
buildProvidedOrdering: noProvidedOrdering,
}
funcMap[opt.AlterRangeRelocateOp] = funcs{
canProvideOrdering: canNeverProvideOrdering,
buildChildReqOrdering: alterRangeRelocateBuildChildReqOrdering,
buildProvidedOrdering: noProvidedOrdering,
}
funcMap[opt.ControlJobsOp] = funcs{
canProvideOrdering: canNeverProvideOrdering,
buildChildReqOrdering: controlJobsBuildChildReqOrdering,
Expand Down
9 changes: 9 additions & 0 deletions pkg/sql/opt/ordering/statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ func alterTableRelocateBuildChildReqOrdering(
return parent.(*memo.AlterTableRelocateExpr).Props.Ordering
}

func alterRangeRelocateBuildChildReqOrdering(
parent memo.RelExpr, required *props.OrderingChoice, childIdx int,
) props.OrderingChoice {
if childIdx != 0 {
return props.OrderingChoice{}
}
return parent.(*memo.AlterRangeRelocateExpr).Props.Ordering
}

func controlJobsBuildChildReqOrdering(
parent memo.RelExpr, required *props.OrderingChoice, childIdx int,
) props.OrderingChoice {
Expand Down
2 changes: 2 additions & 0 deletions pkg/sql/opt/xform/physical_props.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ func BuildChildPhysicalProps(
childProps.Presentation = parent.(*memo.AlterTableUnsplitExpr).Props.Presentation
case opt.AlterTableRelocateOp:
childProps.Presentation = parent.(*memo.AlterTableRelocateExpr).Props.Presentation
case opt.AlterRangeRelocateOp:
childProps.Presentation = parent.(*memo.AlterRangeRelocateExpr).Props.Presentation
case opt.ControlJobsOp:
childProps.Presentation = parent.(*memo.ControlJobsExpr).Props.Presentation
case opt.CancelQueriesOp:
Expand Down
17 changes: 17 additions & 0 deletions pkg/sql/opt_exec_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -1978,6 +1978,23 @@ func (ef *execFactory) ConstructAlterTableRelocate(
}, nil
}

// ConstructAlterRangeRelocate is part of the exec.Factory interface.
func (ef *execFactory) ConstructAlterRangeRelocate(
relocateLease bool, relocateNonVoters bool, rangeID int64, toStoreID int64, fromStoreID int64,
) (exec.Node, error) {
if !ef.planner.ExecCfg().Codec.ForSystemTenant() {
return nil, errorutil.UnsupportedWithMultiTenancy(54250)
}

return &relocateRange{
relocateLease: relocateLease,
relocateNonVoters: relocateNonVoters,
rangeID: roachpb.RangeID(rangeID),
toStoreID: roachpb.StoreID(toStoreID),
fromStoreID: roachpb.StoreID(fromStoreID),
}, nil
}

// ConstructControlJobs is part of the exec.Factory interface.
func (ef *execFactory) ConstructControlJobs(
command tree.JobCommand, input exec.Node, reason tree.TypedExpr,
Expand Down
Loading

0 comments on commit 9843c0d

Please sign in to comment.