Skip to content

Commit a207ac7

Browse files
author
Brian Hendriks
authored
lazy loading of tables and indexes
1 parent e96a691 commit a207ac7

32 files changed

+412
-124
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,5 @@ Makefile.main
3131
_example/main
3232
_example/*.exe
3333
test-server
34+
35+
.idea/*

engine_test.go

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,6 +1520,7 @@ var infoSchemaQueries = []queryTest {
15201520
{"newlinetable"},
15211521
{"typestable"},
15221522
},
1523+
15231524
},
15241525
{
15251526
"SHOW FULL TABLES",
@@ -2873,6 +2874,7 @@ func TestAmbiguousColumnResolution(t *testing.T) {
28732874
}
28742875

28752876
func TestCreateTable(t *testing.T) {
2877+
ctx := context.Background()
28762878
require := require.New(t)
28772879

28782880
e := newEngine(t)
@@ -2886,7 +2888,8 @@ func TestCreateTable(t *testing.T) {
28862888
db, err := e.Catalog.Database("mydb")
28872889
require.NoError(err)
28882890

2889-
testTable, ok := db.Tables()["t1"]
2891+
testTable, ok, err := db.GetTableInsensitive(ctx, "t1")
2892+
require.NoError(err)
28902893
require.True(ok)
28912894

28922895
s := sql.Schema{
@@ -2913,7 +2916,8 @@ func TestCreateTable(t *testing.T) {
29132916
db, err = e.Catalog.Database("mydb")
29142917
require.NoError(err)
29152918

2916-
testTable, ok = db.Tables()["t2"]
2919+
testTable, ok, err = db.GetTableInsensitive(ctx, "t2")
2920+
require.NoError(err)
29172921
require.True(ok)
29182922

29192923
s = sql.Schema{
@@ -2933,7 +2937,8 @@ func TestCreateTable(t *testing.T) {
29332937
db, err = e.Catalog.Database("mydb")
29342938
require.NoError(err)
29352939

2936-
testTable, ok = db.Tables()["t3"]
2940+
testTable, ok, err = db.GetTableInsensitive(ctx, "t3")
2941+
require.NoError(err)
29372942
require.True(ok)
29382943

29392944
s = sql.Schema{
@@ -2954,7 +2959,8 @@ func TestCreateTable(t *testing.T) {
29542959
db, err = e.Catalog.Database("mydb")
29552960
require.NoError(err)
29562961

2957-
testTable, ok = db.Tables()["t4"]
2962+
testTable, ok, err = db.GetTableInsensitive(ctx, "t4")
2963+
require.NoError(err)
29582964
require.True(ok)
29592965

29602966
s = sql.Schema{
@@ -2967,36 +2973,44 @@ func TestCreateTable(t *testing.T) {
29672973
}
29682974

29692975
func TestDropTable(t *testing.T) {
2976+
ctx := context.Background()
29702977
require := require.New(t)
29712978

29722979
e := newEngine(t)
29732980
db, err := e.Catalog.Database("mydb")
29742981
require.NoError(err)
29752982

2976-
_, ok := db.Tables()["mytable"]
2983+
_, ok, err := db.GetTableInsensitive(ctx, "mytable")
29772984
require.True(ok)
29782985

29792986
testQuery(t, e,
29802987
"DROP TABLE IF EXISTS mytable, not_exist",
29812988
[]sql.Row(nil),
29822989
)
29832990

2984-
_, ok = db.Tables()["mytable"]
2991+
_, ok, err = db.GetTableInsensitive(ctx, "mytable")
2992+
require.NoError(err)
29852993
require.False(ok)
29862994

2987-
_, ok = db.Tables()["othertable"]
2995+
_, ok, err = db.GetTableInsensitive(ctx, "othertable")
2996+
require.NoError(err)
29882997
require.True(ok)
2989-
_, ok = db.Tables()["tabletest"]
2998+
2999+
_, ok, err = db.GetTableInsensitive(ctx, "tabletest")
3000+
require.NoError(err)
29903001
require.True(ok)
29913002

29923003
testQuery(t, e,
29933004
"DROP TABLE IF EXISTS othertable, tabletest",
29943005
[]sql.Row(nil),
29953006
)
29963007

2997-
_, ok = db.Tables()["othertable"]
3008+
_, ok, err = db.GetTableInsensitive(ctx, "othertable")
3009+
require.NoError(err)
29983010
require.False(ok)
2999-
_, ok = db.Tables()["tabletest"]
3011+
3012+
_, ok, err = db.GetTableInsensitive(ctx, "tabletest")
3013+
require.NoError(err)
30003014
require.False(ok)
30013015

30023016
_, _, err = e.Query(newCtx(), "DROP TABLE not_exist")

memory/database.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package memory
22

33
import (
4+
"context"
45
"github.com/src-d/go-mysql-server/sql"
56
)
67

8+
var _ sql.Database = (*Database)(nil)
9+
710
// Database is an in-memory database.
811
type Database struct {
912
name string
@@ -28,6 +31,20 @@ func (d *Database) Tables() map[string]sql.Table {
2831
return d.tables
2932
}
3033

34+
func (d *Database) GetTableInsensitive(ctx context.Context, tblName string) (sql.Table, bool, error) {
35+
tbl, ok := sql.GetTableInsensitive(tblName, d.tables)
36+
return tbl, ok, nil
37+
}
38+
39+
func (d *Database) GetTableNames(ctx context.Context) ([]string, error) {
40+
tblNames := make([]string, 0, len(d.tables))
41+
for k := range d.tables {
42+
tblNames = append(tblNames, k)
43+
}
44+
45+
return tblNames, nil
46+
}
47+
3148
// AddTable adds a new table to the database.
3249
func (d *Database) AddTable(name string, t sql.Table) {
3350
d.tables[name] = t

memory/table.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ func (t *Table) HandledFilters(filters []sql.Expression) []sql.Expression {
419419
var handled []sql.Expression
420420
for _, f := range filters {
421421
var hasOtherFields bool
422-
expression.Inspect(f, func(e sql.Expression) bool {
422+
sql.Inspect(f, func(e sql.Expression) bool {
423423
if e, ok := e.(*expression.GetField); ok {
424424
if e.Table() != t.name || !t.schema.Contains(e.Name(), t.name) {
425425
hasOtherFields = true

sql/analyzer/aggregations.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func containsHiddenAggregation(e sql.Expression) bool {
108108

109109
func containsAggregation(e sql.Expression) bool {
110110
var hasAgg bool
111-
expression.Inspect(e, func(e sql.Expression) bool {
111+
sql.Inspect(e, func(e sql.Expression) bool {
112112
if _, ok := e.(sql.Aggregation); ok {
113113
hasAgg = true
114114
return false

sql/analyzer/assign_indexes.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ func getIndexes(e sql.Expression, aliases map[string]sql.Expression, a *Analyzer
309309
// Returns the tables used in the expression given
310310
func findTables(e sql.Expression) []string {
311311
tables := make(map[string]bool)
312-
expression.Inspect(e, func(e sql.Expression) bool {
312+
sql.Inspect(e, func(e sql.Expression) bool {
313313
switch e := e.(type) {
314314
case *expression.GetField:
315315
tables[e.Table()] = true
@@ -792,7 +792,7 @@ func extractColumnExpr(e sql.Expression) (string, *columnExpr) {
792792

793793
func containsColumns(e sql.Expression) bool {
794794
var result bool
795-
expression.Inspect(e, func(e sql.Expression) bool {
795+
sql.Inspect(e, func(e sql.Expression) bool {
796796
if _, ok := e.(*expression.GetField); ok {
797797
result = true
798798
}
@@ -803,7 +803,7 @@ func containsColumns(e sql.Expression) bool {
803803

804804
func containsSubquery(e sql.Expression) bool {
805805
var result bool
806-
expression.Inspect(e, func(e sql.Expression) bool {
806+
sql.Inspect(e, func(e sql.Expression) bool {
807807
if _, ok := e.(*expression.Subquery); ok {
808808
result = true
809809
return false

sql/analyzer/filters.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func exprToTableFilters(expr sql.Expression) filters {
2020
for _, expr := range splitExpression(expr) {
2121
var seenTables = make(map[string]struct{})
2222
var lastTable string
23-
expression.Inspect(expr, func(e sql.Expression) bool {
23+
sql.Inspect(expr, func(e sql.Expression) bool {
2424
f, ok := e.(*expression.GetField)
2525
if ok {
2626
if _, ok := seenTables[f.Table()]; !ok {

sql/analyzer/optimization_rules.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func reorderProjection(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, err
100100
switch node := node.(type) {
101101
case *plan.Sort, *plan.Filter:
102102
for _, expr := range node.(sql.Expressioner).Expressions() {
103-
expression.Inspect(expr, func(e sql.Expression) bool {
103+
sql.Inspect(expr, func(e sql.Expression) bool {
104104
if e != nil && e.Resolved() {
105105
return true
106106
}
@@ -317,7 +317,7 @@ func expressionSources(expr sql.Expression) []string {
317317
var sources = make(map[string]struct{})
318318
var result []string
319319

320-
expression.Inspect(expr, func(expr sql.Expression) bool {
320+
sql.Inspect(expr, func(expr sql.Expression) bool {
321321
f, ok := expr.(*expression.GetField)
322322
if ok {
323323
if _, ok := sources[f.Table()]; !ok {

sql/analyzer/prune_columns.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ func addUsedProjectColumns(
240240

241241
func addUsedColumns(columns usedColumns, exprs []sql.Expression) {
242242
for _, e := range exprs {
243-
expression.Inspect(e, func(e sql.Expression) bool {
243+
sql.Inspect(e, func(e sql.Expression) bool {
244244
if gf, ok := e.(*expression.GetField); ok {
245245
if _, ok := columns[gf.Table()]; !ok {
246246
columns[gf.Table()] = make(map[string]struct{})

sql/analyzer/resolve_columns.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func lookForAliasDeclarations(node sql.Expressioner) map[string]struct{} {
4646
)
4747

4848
for _, e := range node.Expressions() {
49-
expression.Inspect(e, func(expr sql.Expression) bool {
49+
sql.Inspect(e, func(expr sql.Expression) bool {
5050
if alias, ok := expr.(*expression.Alias); ok {
5151
aliases[alias.Name()] = in
5252
}
@@ -61,7 +61,7 @@ func lookForAliasDeclarations(node sql.Expressioner) map[string]struct{} {
6161
func isAliasUsed(node sql.Expressioner, alias string) bool {
6262
var found bool
6363
for _, e := range node.Expressions() {
64-
expression.Inspect(e, func(expr sql.Expression) bool {
64+
sql.Inspect(e, func(expr sql.Expression) bool {
6565
if a, ok := expr.(*expression.Alias); ok {
6666
if a.Name() == alias {
6767
return false
@@ -542,7 +542,7 @@ func resolveGroupingColumns(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node
542542

543543
func findAllColumns(e sql.Expression) []string {
544544
var cols []string
545-
expression.Inspect(e, func(e sql.Expression) bool {
545+
sql.Inspect(e, func(e sql.Expression) bool {
546546
col, ok := e.(*expression.UnresolvedColumn)
547547
if ok {
548548
cols = append(cols, col.Name())

sql/analyzer/resolve_having.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ func aggregationEquals(a, b sql.Expression) bool {
442442
func aggregationChildEquals(a, b sql.Expression) bool {
443443
var fieldsByName = make(map[string]sql.Expression)
444444
var fieldsByTableCol = make(map[tableCol]sql.Expression)
445-
expression.Inspect(b, func(e sql.Expression) bool {
445+
sql.Inspect(b, func(e sql.Expression) bool {
446446
gf, ok := e.(*expression.GetField)
447447
if ok {
448448
fieldsByTableCol[tableCol{
@@ -490,7 +490,7 @@ var errHavingNeedsGroupBy = errors.NewKind("found HAVING clause with no GROUP BY
490490

491491
func hasAggregations(expr sql.Expression) bool {
492492
var has bool
493-
expression.Inspect(expr, func(e sql.Expression) bool {
493+
sql.Inspect(expr, func(e sql.Expression) bool {
494494
_, ok := e.(sql.Aggregation)
495495
if ok {
496496
has = true

sql/analyzer/resolve_orderby.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ func resolveOrderByLiterals(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node
254254

255255
func findExprNameables(e sql.Expression) []sql.Nameable {
256256
var result []sql.Nameable
257-
expression.Inspect(e, func(e sql.Expression) bool {
257+
sql.Inspect(e, func(e sql.Expression) bool {
258258
n, ok := e.(sql.Nameable)
259259
if ok {
260260
result = append(result, n)

sql/analyzer/validation_rules.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ func validateIndexCreation(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node,
183183

184184
var unknownColumns []string
185185
for _, expr := range ci.Exprs {
186-
expression.Inspect(expr, func(e sql.Expression) bool {
186+
sql.Inspect(expr, func(e sql.Expression) bool {
187187
gf, ok := e.(*expression.GetField)
188188
if ok {
189189
if gf.Table() != table || !schema.Contains(gf.Name(), gf.Table()) {

sql/catalog.go

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package sql
22

33
import (
4+
"context"
45
"fmt"
56
"strings"
67
"sync"
@@ -89,7 +90,7 @@ func (c *Catalog) Database(db string) (Database, error) {
8990
func (c *Catalog) Table(db, table string) (Table, error) {
9091
c.mu.RLock()
9192
defer c.mu.RUnlock()
92-
return c.dbs.Table(db, table)
93+
return c.dbs.Table(context.TODO(), db, table, c.IndexRegistry)
9394
}
9495

9596
// Databases is a collection of Database.
@@ -120,35 +121,30 @@ func (d *Databases) Add(db Database) {
120121
}
121122

122123
// Table returns the Table with the given name if it exists.
123-
func (d Databases) Table(dbName string, tableName string) (Table, error) {
124+
func (d Databases) Table(ctx context.Context, dbName string, tableName string, idxReg *IndexRegistry) (Table, error) {
124125
db, err := d.Database(dbName)
125126
if err != nil {
126127
return nil, err
127128
}
128129

129130
tableName = strings.ToLower(tableName)
130131

131-
tables := db.Tables()
132-
if len(tables) == 0 {
133-
return nil, ErrTableNotFound.New(tableName)
134-
}
132+
tbl, ok, err := db.GetTableInsensitive(ctx, tableName)
135133

136-
// Try to get the table by key, but if the name is not the same,
137-
// then use the slow path and iterate over all tables comparing
138-
// the name.
139-
table, ok := tables[tableName]
140-
if !ok {
141-
for name, table := range tables {
142-
if strings.ToLower(name) == tableName {
143-
return table, nil
144-
}
134+
if err != nil {
135+
return nil, err
136+
} else if !ok {
137+
tableNames, err := db.GetTableNames(ctx)
138+
139+
if err != nil {
140+
return nil, err
145141
}
146142

147-
similar := similartext.FindFromMap(tables, tableName)
143+
similar := similartext.Find(tableNames, tableName)
148144
return nil, ErrTableNotFound.New(tableName + similar)
149145
}
150146

151-
return table, nil
147+
return tbl, nil
152148
}
153149

154150
// LockTable adds a lock for the given table and session client. It is assumed
@@ -177,7 +173,7 @@ func (c *Catalog) UnlockTables(ctx *Context, id uint32) error {
177173
var errors []string
178174
for db, tables := range c.locks[id] {
179175
for t := range tables {
180-
table, err := c.dbs.Table(db, t)
176+
table, err := c.dbs.Table(ctx, db, t, c.IndexRegistry)
181177
if err == nil {
182178
if lockable, ok := table.(Lockable); ok {
183179
if e := lockable.Unlock(ctx, id); e != nil {

0 commit comments

Comments
 (0)