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

opt: add support for ALTER TABLE/INDEX SPLIT AT #38585

Merged
merged 2 commits into from
Jul 2, 2019
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
2 changes: 1 addition & 1 deletion pkg/sql/data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ func (p *planner) getSequenceSource(
}
return planDataSource{
plan: node,
info: sqlbase.NewSourceInfoForSingleTable(tn, sequenceSelectColumns),
info: sqlbase.NewSourceInfoForSingleTable(tn, sqlbase.SequenceSelectColumns),
}, nil
}

Expand Down
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 @@ -289,3 +289,9 @@ func (f *stubFactory) ConstructErrorIfRows(
func (f *stubFactory) ConstructOpaque(metadata opt.OpaqueMetadata) (exec.Node, error) {
return struct{}{}, nil
}

func (f *stubFactory) ConstructAlterTableSplit(
index cat.Index, input exec.Node, expiration tree.TypedExpr,
) (exec.Node, error) {
return struct{}{}, nil
}
4 changes: 4 additions & 0 deletions pkg/sql/opt/cat/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ type Index interface {
// Table returns a reference to the table this index is based on.
Table() Table

// Ordinal returns the ordinal of this index within the context of its Table.
// Specifically idx = Table().Index(idx.Ordinal).
Ordinal() int

// IsUnique returns true if this index is declared as UNIQUE in the schema.
IsUnique() bool

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 @@ -244,6 +244,9 @@ func (b *Builder) buildRelational(e memo.RelExpr) (execPlan, error) {
case *memo.OpaqueRelExpr:
ep, err = b.buildOpaque(t)

case *memo.AlterTableSplitExpr:
ep, err = b.buildAlterTableSplit(t)

default:
if opt.IsSetOp(e) {
ep, err = b.buildSetOp(e)
Expand Down
36 changes: 30 additions & 6 deletions pkg/sql/opt/exec/execbuilder/statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ func (b *Builder) buildExplain(explain *memo.ExplainExpr) (execPlan, error) {
}

ep := execPlan{root: node}
for i := range explain.ColList {
ep.outputCols.Set(int(explain.ColList[i]), i)
for i, c := range explain.ColList {
ep.outputCols.Set(int(c), i)
}
// The subqueries are now owned by the explain node; remove them so they don't
// also show up in the final plan.
Expand All @@ -110,10 +110,34 @@ func (b *Builder) buildShowTrace(show *memo.ShowTraceForSessionExpr) (execPlan,
return execPlan{}, err
}
ep := execPlan{root: node}
for i := range show.ColList {
ep.outputCols.Set(int(show.ColList[i]), i)
for i, c := range show.ColList {
ep.outputCols.Set(int(c), i)
}
return ep, nil
}

func (b *Builder) buildAlterTableSplit(split *memo.AlterTableSplitExpr) (execPlan, error) {
input, err := b.buildRelational(split.Input)
if err != nil {
return execPlan{}, err
}
scalarCtx := buildScalarCtx{}
expiration, err := b.buildScalar(&scalarCtx, split.Expiration)
if err != nil {
return execPlan{}, err
}
table := b.mem.Metadata().Table(split.Table)
node, err := b.factory.ConstructAlterTableSplit(
table.Index(split.Index),
input.root,
expiration,
)
if err != nil {
return execPlan{}, err
}
ep := execPlan{root: node}
for i, c := range split.Columns {
ep.outputCols.Set(int(c), i)
}
// The subqueries are now owned by the explain node; remove them so they don't
// also show up in the final plan.
return ep, nil
}
17 changes: 6 additions & 11 deletions pkg/sql/opt/exec/execbuilder/testdata/ddl
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,12 @@ CREATE TABLE s (k1 INT, k2 INT, v INT, PRIMARY KEY (k1,k2))
query TTTTT colnames
EXPLAIN (VERBOSE) ALTER TABLE s SPLIT AT SELECT k1,k2 FROM s ORDER BY k1 LIMIT 3
----
tree field description columns ordering
split · · (key, pretty, split_enforced_until) ·
└── limit · · (k1, k2) k1!=NULL; k2!=NULL; key(k1,k2); +k1
│ count 3 · ·
└── render · · (k1, k2) k1!=NULL; k2!=NULL; key(k1,k2); +k1
│ render 0 test.public.s.k1 · ·
│ render 1 test.public.s.k2 · ·
└── scan · · (k1, k2, v[omitted]) k1!=NULL; k2!=NULL; key(k1,k2); +k1
· table s@primary · ·
· spans ALL · ·
· limit 3 · ·
tree field description columns ordering
split · · (key, pretty, split_enforced_until) ·
└── scan · · (k1, k2) +k1
· table s@primary · ·
· spans ALL · ·
· limit 3 · ·

statement ok
DROP TABLE t; DROP TABLE other
Expand Down
23 changes: 10 additions & 13 deletions pkg/sql/opt/exec/execbuilder/testdata/subquery
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,16 @@ CREATE TABLE abc (a INT PRIMARY KEY, b INT, c INT)
query TTT
EXPLAIN ALTER TABLE abc SPLIT AT VALUES ((SELECT 42))
----
root · ·
├── split · ·
│ └── values · ·
│ size 1 column, 1 row
└── subquery · ·
│ id @S1
│ original sql (SELECT 42)
│ exec mode one row
└── max1row · ·
└── limit · ·
│ count 2
└── render · ·
└── emptyrow · ·
root · ·
├── split · ·
│ └── values · ·
│ size 1 column, 1 row
└── subquery · ·
│ id @S1
│ original sql (SELECT 42)
│ exec mode one row
└── values · ·
· size 1 column, 1 row

statement ok
ALTER TABLE abc SPLIT AT VALUES ((SELECT 1))
Expand Down
4 changes: 4 additions & 0 deletions pkg/sql/opt/exec/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,10 @@ type Factory interface {

// ConstructOpaque creates a node for an opaque operator.
ConstructOpaque(metadata opt.OpaqueMetadata) (Node, error)

// ConstructAlterTableSplit creates a node that implements ALTER TABLE/INDEX
// SPLIT AT.
ConstructAlterTableSplit(index cat.Index, input Node, expiration tree.TypedExpr) (Node, error)
}

// OutputOrdering indicates the required output ordering on a Node that is being
Expand Down
8 changes: 8 additions & 0 deletions pkg/sql/opt/memo/expr_format.go
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,14 @@ func FormatPrivate(f *ExprFmtCtx, private interface{}, physProps *physical.Requi
f.Buffer.WriteByte(' ')
f.Buffer.WriteString(t.Metadata.String())

case *AlterTableSplitPrivate:
tab := f.Memo.metadata.Table(t.Table)
if t.Index == cat.PrimaryIndex {
fmt.Fprintf(f.Buffer, " %s", tableAlias(f, t.Table))
} else {
fmt.Fprintf(f.Buffer, " %s@%s", tableAlias(f, t.Table), tab.Index(t.Index).Name())
}

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

Expand Down
89 changes: 22 additions & 67 deletions pkg/sql/opt/memo/logical_props_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,25 +684,24 @@ func (b *logicalPropsBuilder) buildValuesProps(values *ValuesExpr, rel *props.Re
}
}

func (b *logicalPropsBuilder) buildExplainProps(explain *ExplainExpr, rel *props.Relational) {
BuildSharedProps(b.mem, explain, &rel.Shared)
func (b *logicalPropsBuilder) buildBasicProps(e opt.Expr, cols opt.ColList, rel *props.Relational) {
BuildSharedProps(b.mem, e, &rel.Shared)

// Output Columns
// --------------
// Output columns are stored in the definition.
rel.OutputCols = explain.ColList.ToSet()
rel.OutputCols = cols.ToSet()

// Not Null Columns
// ----------------
// All columns are assumed to be nullable.

// Outer Columns
// -------------
// EXPLAIN doesn't allow outer columns.
// No outer columns.

// Functional Dependencies
// -----------------------
// Explain operator has an empty FD set.
// Empty FD set.

// Cardinality
// -----------
Expand All @@ -716,39 +715,28 @@ func (b *logicalPropsBuilder) buildExplainProps(explain *ExplainExpr, rel *props
}
}

func (b *logicalPropsBuilder) buildExplainProps(explain *ExplainExpr, rel *props.Relational) {
b.buildBasicProps(explain, explain.ColList, rel)
}

func (b *logicalPropsBuilder) buildShowTraceForSessionProps(
showTrace *ShowTraceForSessionExpr, rel *props.Relational,
) {
BuildSharedProps(b.mem, showTrace, &rel.Shared)

// Output Columns
// --------------
// Output columns are stored in the definition.
rel.OutputCols = showTrace.ColList.ToSet()

// Not Null Columns
// ----------------
// All columns are assumed to be nullable.

// Outer Columns
// -------------
// SHOW TRACE doesn't allow outer columns.

// Functional Dependencies
// -----------------------
// ShowTrace operator has an empty FD set.

// Cardinality
// -----------
// Don't make any assumptions about cardinality of output.
rel.Cardinality = props.AnyCardinality
b.buildBasicProps(showTrace, showTrace.ColList, rel)
}

// Statistics
// ----------
if !b.disableStats {
b.sb.buildUnknown(rel)
}
func (b *logicalPropsBuilder) buildOpaqueRelProps(op *OpaqueRelExpr, rel *props.Relational) {
b.buildBasicProps(op, op.Columns, rel)
rel.CanHaveSideEffects = true
rel.CanMutate = true
}

func (b *logicalPropsBuilder) buildAlterTableSplitProps(
split *AlterTableSplitExpr, rel *props.Relational,
) {
b.buildBasicProps(split, split.Columns, rel)
rel.CanHaveSideEffects = true
rel.CanMutate = true
}

func (b *logicalPropsBuilder) buildLimitProps(limit *LimitExpr, rel *props.Relational) {
Expand Down Expand Up @@ -1785,39 +1773,6 @@ func (h *joinPropsHelper) cardinality() props.Cardinality {
}
}

func (b *logicalPropsBuilder) buildOpaqueRelProps(op *OpaqueRelExpr, rel *props.Relational) {
BuildSharedProps(b.mem, op, &rel.Shared)
rel.CanHaveSideEffects = true
rel.CanMutate = true

// Output Columns
// --------------
rel.OutputCols = op.Columns.ToSet()

// Not Null Columns
// ----------------
// All columns are assumed to be nullable.

// Outer Columns
// -------------
// No outer columns.

// Functional Dependencies
// -----------------------
// None.

// Cardinality
// -----------
// Any.
rel.Cardinality = props.AnyCardinality

// Statistics
// ----------
if !b.disableStats {
b.sb.buildUnknown(rel)
}
}

func (b *logicalPropsBuilder) buildFakeRelProps(fake *FakeRelExpr, rel *props.Relational) {
*rel = *fake.Props
}
33 changes: 33 additions & 0 deletions pkg/sql/opt/ops/statement.opt
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,36 @@ define OpaqueRelPrivate {
Columns ColList
Metadata OpaqueMetadata
}

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

# Expiration is a string scalar that indicates a timestamp after which the
# ranges are eligible for automatic merging (or Null if there is no
# expiration).
Expiration ScalarExpr

_ AlterTableSplitPrivate
}

[Private]
define AlterTableSplitPrivate {
# Table identifies the table to alter. It is an id that can be passed to
# the Metadata.Table method in order to fetch cat.Table metadata.
Table TableID

# Index identifies the index to scan (whether primary or secondary). It
# can be passed to the cat.Table.Index(i int) method in order to fetch the
# cat.Index metadata.
Index int

# Props stores the required physical properties for the enclosed expression.
Props PhysProps

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