Skip to content

Commit f927685

Browse files
authored
cache sql.Schema in plan.Project and plan.TableAlias (#3158)
1 parent 30de574 commit f927685

File tree

8 files changed

+55
-40
lines changed

8 files changed

+55
-40
lines changed

memory/index.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,9 @@ func (idx *Index) Reversible() bool {
298298
return true
299299
}
300300

301-
func (idx Index) copy() *Index {
302-
return &idx
301+
func (idx *Index) copy() *Index {
302+
newIdx := *idx
303+
return &newIdx
303304
}
304305

305306
// columnIndexes returns the indexes in the given schema for the fields in this index

sql/analyzer/common_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ func runTestCases(t *testing.T, ctx *sql.Context, testCases []analyzerFnTestCase
157157
if expected == nil {
158158
expected = tt.node
159159
}
160+
// Schema of certain nodes aren't filled until needed
161+
expected.Schema()
160162

161163
assertNodesEqualWithDiff(t, expected, result)
162164
})

sql/analyzer/index_analyzer_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,17 +131,18 @@ type dummyIdx struct {
131131

132132
var _ sql.Index = (*dummyIdx)(nil)
133133

134-
func (i dummyIdx) CanSupport(context *sql.Context, r ...sql.Range) bool {
134+
func (i *dummyIdx) CanSupport(context *sql.Context, r ...sql.Range) bool {
135135
return true
136136
}
137137

138-
func (i dummyIdx) Expressions() []string {
138+
func (i *dummyIdx) Expressions() []string {
139139
var exprs []string
140140
for _, e := range i.expr {
141141
exprs = append(exprs, e.String())
142142
}
143143
return exprs
144144
}
145+
145146
func (i *dummyIdx) ID() string { return i.id }
146147
func (i *dummyIdx) Database() string { return i.database }
147148
func (i *dummyIdx) Table() string { return i.table }

sql/index_registry_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ func (i dummyIdx) Expressions() []string {
443443
}
444444
return exprs
445445
}
446+
446447
func (i dummyIdx) ID() string { return i.id }
447448
func (i dummyIdx) Database() string { return i.database }
448449
func (i dummyIdx) Table() string { return i.table }

sql/memo/rel_props.go

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,13 @@ func newRelProps(rel RelExpr) *relProps {
131131
}
132132

133133
// idxExprsColumns returns the column names used in an index's expressions.
134-
// TODO: this is unstable as long as periods in Index.Expressions()
135-
// identifiers are ambiguous.
134+
// Identifiers are ambiguous.
136135
func idxExprsColumns(idx sql.Index) []string {
137-
columns := make([]string, len(idx.Expressions()))
138-
for i, e := range idx.Expressions() {
139-
parts := strings.Split(e, ".")
140-
columns[i] = strings.ToLower(parts[1])
136+
exprs := idx.Expressions()
137+
columns := make([]string, len(exprs))
138+
for i, e := range exprs {
139+
colName := e[strings.IndexRune(e, '.')+1:]
140+
columns[i] = strings.ToLower(colName)
141141
}
142142
return columns
143143
}
@@ -793,15 +793,12 @@ func sortedColsForRel(rel RelExpr) sql.Schema {
793793
var ret sql.Schema
794794
for _, e := range r.InnerScan.Table.Index().Expressions() {
795795
// TODO columns can have "." characters, this will miss cases
796-
parts := strings.Split(e, ".")
797-
var name string
798-
if len(parts) == 2 {
799-
name = parts[1]
800-
} else {
796+
idx := strings.IndexRune(e, '.')
797+
if idx == -1 {
801798
return nil
802799
}
803800
ret = append(ret, &sql.Column{
804-
Name: strings.ToLower(name),
801+
Name: strings.ToLower(e[idx+1:]),
805802
Source: strings.ToLower(r.InnerScan.Table.Name()),
806803
Nullable: true},
807804
)

sql/plan/project.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ type Project struct {
3535
// a RowIter.
3636
IncludesNestedIters bool
3737
deps sql.ColSet
38+
39+
sch sql.Schema
3840
}
3941

4042
var _ sql.Expressioner = (*Project)(nil)
@@ -122,14 +124,16 @@ func ExprDeps(exprs ...sql.Expression) sql.ColSet {
122124

123125
// Schema implements the Node interface.
124126
func (p *Project) Schema() sql.Schema {
125-
var s = make(sql.Schema, len(p.Projections))
126-
for i, expr := range p.Projections {
127-
s[i] = transform.ExpressionToColumn(expr, AliasSubqueryString(expr))
128-
if gf := unwrapGetField(expr); gf != nil {
129-
s[i].Default = findDefault(p.Child, gf)
127+
if p.sch == nil {
128+
p.sch = make(sql.Schema, len(p.Projections))
129+
for i, expr := range p.Projections {
130+
p.sch[i] = transform.ExpressionToColumn(expr, AliasSubqueryString(expr))
131+
if gf := unwrapGetField(expr); gf != nil {
132+
p.sch[i].Default = findDefault(p.Child, gf)
133+
}
130134
}
131135
}
132-
return s
136+
return p.sch
133137
}
134138

135139
// Resolved implements the Resolvable interface.
@@ -190,6 +194,7 @@ func (p *Project) WithChildren(children ...sql.Node) (sql.Node, error) {
190194
}
191195
np := *p
192196
np.Child = children[0]
197+
np.sch = nil
193198
return &np, nil
194199
}
195200

@@ -205,6 +210,7 @@ func (p *Project) WithExpressions(exprs ...sql.Expression) (sql.Node, error) {
205210
}
206211
np := *p
207212
np.Projections = exprs
213+
np.sch = nil
208214
return &np, nil
209215
}
210216

sql/plan/tablealias.go

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type TableAlias struct {
2525
comment string
2626
id sql.TableId
2727
cols sql.ColSet
28+
sch sql.Schema
2829
}
2930

3031
var _ sql.RenameableNode = (*TableAlias)(nil)
@@ -33,7 +34,10 @@ var _ sql.CollationCoercible = (*TableAlias)(nil)
3334

3435
// NewTableAlias returns a new Table alias node.
3536
func NewTableAlias(name string, node sql.Node) *TableAlias {
36-
ret := &TableAlias{UnaryNode: &UnaryNode{Child: node}, name: name}
37+
ret := &TableAlias{
38+
UnaryNode: &UnaryNode{Child: node},
39+
name: name,
40+
}
3741
if tin, ok := node.(TableIdNode); ok {
3842
ret.id = tin.Id()
3943
ret.cols = tin.Columns()
@@ -87,14 +91,16 @@ func (t *TableAlias) Comment() string {
8791
// Schema implements the Node interface. TableAlias alters the schema of its child element to rename the source of
8892
// columns to the alias.
8993
func (t *TableAlias) Schema() sql.Schema {
90-
childSchema := t.Child.Schema()
91-
copy := make(sql.Schema, len(childSchema))
92-
for i, col := range childSchema {
93-
colCopy := *col
94-
colCopy.Source = t.name
95-
copy[i] = &colCopy
94+
if t.sch == nil {
95+
childSchema := t.Child.Schema()
96+
t.sch = make(sql.Schema, len(childSchema))
97+
for i, col := range childSchema {
98+
newCol := *col
99+
newCol.Source = t.name
100+
t.sch[i] = &newCol
101+
}
96102
}
97-
return copy
103+
return t.sch
98104
}
99105

100106
// WithChildren implements the Node interface.
@@ -118,21 +124,22 @@ func (t *TableAlias) CollationCoercibility(ctx *sql.Context) (collation sql.Coll
118124
return sql.Collation_binary, 7
119125
}
120126

121-
func (t TableAlias) String() string {
127+
func (t *TableAlias) String() string {
122128
pr := sql.NewTreePrinter()
123129
_ = pr.WriteNode("TableAlias(%s)", t.name)
124130
_ = pr.WriteChildren(t.Child.String())
125131
return pr.String()
126132
}
127133

128-
func (t TableAlias) DebugString() string {
134+
func (t *TableAlias) DebugString() string {
129135
pr := sql.NewTreePrinter()
130136
_ = pr.WriteNode("TableAlias(%s)", t.name)
131137
_ = pr.WriteChildren(sql.DebugString(t.Child))
132138
return pr.String()
133139
}
134140

135-
func (t TableAlias) WithName(name string) sql.Node {
136-
t.name = name
137-
return &t
141+
func (t *TableAlias) WithName(name string) sql.Node {
142+
nt := *t
143+
nt.name = name
144+
return &nt
138145
}

sql/planbuilder/ddl.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -395,11 +395,11 @@ func (b *Builder) getIndexDefs(table sql.Table) sql.IndexDefs {
395395
if !isIdxTbl {
396396
return nil
397397
}
398-
var idxDefs sql.IndexDefs
399398
idxs, err := idxTbl.GetIndexes(b.ctx)
400399
if err != nil {
401400
b.handleErr(err)
402401
}
402+
idxDefs := make(sql.IndexDefs, 0, len(idxs))
403403
for _, idx := range idxs {
404404
if idx.IsGenerated() {
405405
continue
@@ -412,10 +412,10 @@ func (b *Builder) getIndexDefs(table sql.Table) sql.IndexDefs {
412412
constraint = sql.IndexConstraint_Unique
413413
}
414414
}
415-
columns := make([]sql.IndexColumn, len(idx.Expressions()))
416-
for i, col := range idx.Expressions() {
417-
// TODO: find a better way to get only the column name if the table is present
418-
col = strings.TrimPrefix(col, idxTbl.Name()+".")
415+
exprs := idx.Expressions()
416+
columns := make([]sql.IndexColumn, len(exprs))
417+
for i, col := range exprs {
418+
col = col[strings.IndexByte(col, '.')+1:]
419419
columns[i] = sql.IndexColumn{Name: col}
420420
}
421421
idxDefs = append(idxDefs, &sql.IndexDef{

0 commit comments

Comments
 (0)