Skip to content

Commit

Permalink
opt: support EXPERIMENTAL_RELOCATE
Browse files Browse the repository at this point in the history
Also fix the formatting of details for split/unsplit.

Release note: None
  • Loading branch information
RaduBerinde committed Jul 3, 2019
1 parent ccaa1ec commit 852a6cb
Show file tree
Hide file tree
Showing 15 changed files with 260 additions and 20 deletions.
6 changes: 6 additions & 0 deletions pkg/sql/opt/bench/stub_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,9 @@ func (f *stubFactory) ConstructAlterTableUnsplit(
func (f *stubFactory) ConstructAlterTableUnsplitAll(index cat.Index) (exec.Node, error) {
return struct{}{}, nil
}

func (f *stubFactory) ConstructAlterTableRelocate(
index cat.Index, input exec.Node, relocateLease bool,
) (exec.Node, error) {
return struct{}{}, nil
}
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 @@ -253,6 +253,9 @@ func (b *Builder) buildRelational(e memo.RelExpr) (execPlan, error) {
case *memo.AlterTableUnsplitAllExpr:
ep, err = b.buildAlterTableUnsplitAll(t)

case *memo.AlterTableRelocateExpr:
ep, err = b.buildAlterTableRelocate(t)

default:
if opt.IsSetOp(e) {
ep, err = b.buildSetOp(e)
Expand Down
21 changes: 21 additions & 0 deletions pkg/sql/opt/exec/execbuilder/statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,24 @@ func (b *Builder) buildAlterTableUnsplitAll(
}
return ep, nil
}

func (b *Builder) buildAlterTableRelocate(relocate *memo.AlterTableRelocateExpr) (execPlan, error) {
input, err := b.buildRelational(relocate.Input)
if err != nil {
return execPlan{}, err
}
table := b.mem.Metadata().Table(relocate.Table)
node, err := b.factory.ConstructAlterTableRelocate(
table.Index(relocate.Index),
input.root,
relocate.RelocateLease,
)
if err != nil {
return execPlan{}, err
}
ep := execPlan{root: node}
for i, c := range relocate.Columns {
ep.outputCols.Set(int(c), i)
}
return ep, nil
}
4 changes: 4 additions & 0 deletions pkg/sql/opt/exec/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,10 @@ type Factory interface {
// ConstructAlterTableUnsplitAll creates a node that implements ALTER TABLE/INDEX
// UNSPLIT ALL.
ConstructAlterTableUnsplitAll(index cat.Index) (Node, error)

// ConstructAlterTableRelocate creates a node that implements ALTER TABLE/INDEX
// UNSPLIT AT.
ConstructAlterTableRelocate(index cat.Index, input Node, relocateLease bool) (Node, error)
}

// OutputOrdering indicates the required output ordering on a Node that is being
Expand Down
9 changes: 8 additions & 1 deletion pkg/sql/opt/memo/expr_format.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ func (f *ExprFmtCtx) formatRelational(e RelExpr, tp treeprinter.Node) {

case *ScanExpr, *VirtualScanExpr, *IndexJoinExpr, *ShowTraceForSessionExpr,
*InsertExpr, *UpdateExpr, *UpsertExpr, *DeleteExpr, *SequenceSelectExpr,
*WindowExpr, *OpaqueRelExpr:
*WindowExpr, *OpaqueRelExpr, *AlterTableSplitExpr, *AlterTableUnsplitExpr,
*AlterTableUnsplitAllExpr, *AlterTableRelocateExpr:
fmt.Fprintf(f.Buffer, "%v", e.Op())
FormatPrivate(f, e.Private(), required)

Expand Down Expand Up @@ -981,6 +982,12 @@ func FormatPrivate(f *ExprFmtCtx, private interface{}, physProps *physical.Requi
fmt.Fprintf(f.Buffer, " %s@%s", tableAlias(f, t.Table), tab.Index(t.Index).Name())
}

case *AlterTableRelocatePrivate:
FormatPrivate(f, &t.AlterTableSplitPrivate, nil)
if t.RelocateLease {
f.Buffer.WriteString(" [lease]")
}

case *JoinPrivate:
// Nothing to show; flags are shown separately.

Expand Down
8 changes: 8 additions & 0 deletions pkg/sql/opt/memo/logical_props_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,14 @@ func (b *logicalPropsBuilder) buildAlterTableUnsplitAllProps(
rel.CanMutate = true
}

func (b *logicalPropsBuilder) buildAlterTableRelocateProps(
relocate *AlterTableRelocateExpr, rel *props.Relational,
) {
b.buildBasicProps(relocate, relocate.Columns, rel)
rel.CanHaveSideEffects = true
rel.CanMutate = true
}

func (b *logicalPropsBuilder) buildLimitProps(limit *LimitExpr, rel *props.Relational) {
BuildSharedProps(b.mem, limit, &rel.Shared)

Expand Down
17 changes: 17 additions & 0 deletions pkg/sql/opt/ops/statement.opt
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,20 @@ define AlterTableUnsplit {
define AlterTableUnsplitAll {
_ AlterTableSplitPrivate
}

# AlterTableRelocate represents an `ALTER TABLE/INDEX .. SPLIT AT ..` statement.
[Relational, DDL]
define AlterTableRelocate {
# The input expression provides values for the index columns (or a prefix of
# them).
Input RelExpr

_ AlterTableRelocatePrivate
}

[Private]
define AlterTableRelocatePrivate {
RelocateLease bool

_ AlterTableSplitPrivate
}
68 changes: 63 additions & 5 deletions pkg/sql/opt/optbuilder/alter_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ func (b *Builder) buildAlterTableSplit(split *tree.Split, inScope *scope) (outSc

b.DisableMemoReuse = true

// Calculate the desired types for the select statement. It is OK if the
// select statement returns fewer columns (the relevant prefix is used).
// Calculate the desired types for the input expression. It is OK if it
// returns fewer columns (the relevant prefix is used).
colNames, colTypes := getIndexColumnNamesAndTypes(index)

// We don't allow the input statement to reference outer columns, so we
Expand Down Expand Up @@ -112,8 +112,8 @@ func (b *Builder) buildAlterTableUnsplit(unsplit *tree.Unsplit, inScope *scope)
return outScope
}

// Calculate the desired types for the select statement. It is OK if the
// select statement returns fewer columns (the relevant prefix is used).
// Calculate the desired types for the input expression. It is OK if it
// returns fewer columns (the relevant prefix is used).
colNames, colTypes := getIndexColumnNamesAndTypes(index)

// We don't allow the input statement to reference outer columns, so we
Expand All @@ -129,6 +129,64 @@ func (b *Builder) buildAlterTableUnsplit(unsplit *tree.Unsplit, inScope *scope)
return outScope
}

// buildAlterTableRelocate builds an ALTER TABLE/INDEX .. UNSPLIT AT/ALL .. statement.
func (b *Builder) buildAlterTableRelocate(
relocate *tree.Relocate, inScope *scope,
) (outScope *scope) {
flags := cat.Flags{
AvoidDescriptorCaches: true,
NoTableStats: true,
}
index, err := cat.ResolveTableIndex(b.ctx, b.catalog, flags, &relocate.TableOrIndex)
if err != nil {
panic(builderError{err})
}
table := index.Table()
if err := b.catalog.CheckPrivilege(b.ctx, table, privilege.INSERT); err != nil {
panic(builderError{err})
}

b.DisableMemoReuse = true

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

// Calculate the desired types for the input expression. It is OK if it
// returns fewer columns (the relevant prefix is used).
colNames, colTypes := getIndexColumnNamesAndTypes(index)

// The first column is the target leaseholder or the relocation array,
// depending on variant.
cmdName := "EXPERIMENTAL_RELOCATE"
if relocate.RelocateLease {
cmdName += " LEASE"
colNames = append([]string{"target leaseholder"}, colNames...)
colTypes = append([]*types.T{types.Int}, colTypes...)
} else {
colNames = append([]string{"relocation array"}, colNames...)
colTypes = append([]*types.T{types.IntArray}, colTypes...)
}

// We don't allow the input statement to reference outer columns, so we
// pass a "blank" scope rather than inScope.
inputScope := b.buildStmt(relocate.Rows, colTypes, &scope{builder: b})
checkInputColumns(cmdName, inputScope, colNames, colTypes, 2)

outScope.expr = b.factory.ConstructAlterTableRelocate(
inputScope.expr.(memo.RelExpr),
&memo.AlterTableRelocatePrivate{
RelocateLease: relocate.RelocateLease,
AlterTableSplitPrivate: memo.AlterTableSplitPrivate{
Table: b.factory.Metadata().AddTable(table),
Index: index.Ordinal(),
Columns: colsToColList(outScope.cols),
Props: inputScope.makePhysicalProps(),
},
},
)
return outScope
}

// getIndexColumnNamesAndTypes returns the names and types of the index columns.
func getIndexColumnNamesAndTypes(index cat.Index) (colNames []string, colTypes []*types.T) {
colNames = make([]string, index.LaxKeyColumnCount())
Expand All @@ -151,7 +209,7 @@ func checkInputColumns(
if len(inputScope.cols) == 0 {
panic(pgerror.Newf(pgcode.Syntax, "no columns in %s data", context))
}
panic(pgerror.Newf(pgcode.Syntax, "too few columns in %s data", context))
panic(pgerror.Newf(pgcode.Syntax, "less than %d columns in %s data", minPrefix, context))
}
if len(inputScope.cols) > len(colTypes) {
panic(pgerror.Newf(pgcode.Syntax, "too many columns in %s data", context))
Expand Down
3 changes: 3 additions & 0 deletions pkg/sql/opt/optbuilder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ func (b *Builder) buildStmt(
case *tree.Unsplit:
return b.buildAlterTableUnsplit(stmt, inScope)

case *tree.Relocate:
return b.buildAlterTableRelocate(stmt, inScope)

default:
// See if this statement can be rewritten to another statement using the
// delegate functionality.
Expand Down
Loading

0 comments on commit 852a6cb

Please sign in to comment.