Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

Commit f2fefea

Browse files
authored
Merge pull request #182 from erizocosmico/feature/create-index
sql/*: add support for create index statement
2 parents c0784a9 + ec1c75a commit f2fefea

21 files changed

+1164
-92
lines changed

benchmark/tpc_h_test.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,14 @@ func executeQueries(b *testing.B, e *sqle.Engine) error {
8585
func genDB(b *testing.B) (sql.Database, error) {
8686
db := mem.NewDatabase("tpch")
8787

88-
memDb, ok := db.(*mem.Database)
89-
if !ok {
90-
b.Fatal("database cannot be casted to mem database")
91-
}
92-
9388
for _, m := range tpchTableMetadata {
9489
b.Log("generating table", m.name)
9590
t := mem.NewTable(m.name, m.schema)
9691
if err := insertDataToTable(t, len(m.schema)); err != nil {
9792
return nil, err
9893
}
9994

100-
memDb.AddTable(m.name, t)
95+
db.AddTable(m.name, t)
10196
}
10297

10398
return db, nil

engine_test.go

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -259,12 +259,8 @@ func TestAmbiguousColumnResolution(t *testing.T) {
259259
require.Nil(table2.Insert(sql.NewRow("pux", int64(1))))
260260

261261
db := mem.NewDatabase("mydb")
262-
263-
memDb, ok := db.(*mem.Database)
264-
require.True(ok)
265-
266-
memDb.AddTable(table.Name(), table)
267-
memDb.AddTable(table2.Name(), table2)
262+
db.AddTable(table.Name(), table)
263+
db.AddTable(table2.Name(), table2)
268264

269265
e := sqle.New()
270266
e.AddDatabase(db)
@@ -374,12 +370,9 @@ func newEngine(t *testing.T) *sqle.Engine {
374370
require.Nil(table3.Insert(sql.NewRow("c", int32(3))))
375371

376372
db := mem.NewDatabase("mydb")
377-
memDb, ok := db.(*mem.Database)
378-
require.True(ok)
379-
380-
memDb.AddTable(table.Name(), table)
381-
memDb.AddTable(table2.Name(), table2)
382-
memDb.AddTable(table3.Name(), table3)
373+
db.AddTable(table.Name(), table)
374+
db.AddTable(table2.Name(), table2)
375+
db.AddTable(table3.Name(), table3)
383376

384377
e := sqle.New()
385378
e.AddDatabase(db)

example_test.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ func Example() {
2323

2424
// Iterate results and print them.
2525
for {
26-
ro, err := r.Next()
26+
row, err := r.Next()
2727
if err == io.EOF {
2828
break
2929
}
3030
checkIfError(err)
3131

32-
name := ro[0]
33-
count := ro[1]
32+
name := row[0]
33+
count := row[1]
3434

3535
fmt.Println(name, count)
3636
}
@@ -50,9 +50,7 @@ func createTestDatabase() sql.Database {
5050
{Name: "name", Type: sql.Text, Source: "mytable"},
5151
{Name: "email", Type: sql.Text, Source: "mytable"},
5252
})
53-
memDb, _ := db.(*mem.Database)
54-
55-
memDb.AddTable("mytable", table)
53+
db.AddTable("mytable", table)
5654
table.Insert(sql.NewRow("John Doe", "john@doe.com"))
5755
table.Insert(sql.NewRow("John Doe", "johnalt@doe.com"))
5856
table.Insert(sql.NewRow("Jane Doe", "jane@doe.com"))

mem/database.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ type Database struct {
1111
}
1212

1313
// NewDatabase creates a new database with the given name.
14-
func NewDatabase(name string) sql.Database {
14+
func NewDatabase(name string) *Database {
1515
return &Database{
1616
name: name,
1717
tables: map[string]sql.Table{},
@@ -29,7 +29,7 @@ func (d *Database) Tables() map[string]sql.Table {
2929
}
3030

3131
// AddTable adds a new table to the database.
32-
func (d *Database) AddTable(name string, t *Table) {
32+
func (d *Database) AddTable(name string, t sql.Table) {
3333
d.tables[name] = t
3434
}
3535

mem/database_test.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ func TestDatabase_AddTable(t *testing.T) {
1919
tables := db.Tables()
2020
require.Equal(0, len(tables))
2121

22-
altDb, ok := db.(sql.Alterable)
23-
require.True(ok)
24-
22+
var altDb sql.Alterable = db
2523
err := altDb.Create("test_table", sql.Schema{})
2624
require.NoError(err)
2725

server/handler_test.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,13 @@ func setupMemDB(require *require.Assertions) *sqle.Engine {
1818
db := mem.NewDatabase("test")
1919
e.AddDatabase(db)
2020

21-
memDb, ok := db.(*mem.Database)
22-
require.True(ok)
23-
2421
tableTest := mem.NewTable("test", sql.Schema{{Name: "c1", Type: sql.Int32, Source: "test"}})
2522

2623
for i := 0; i < 1010; i++ {
2724
require.NoError(tableTest.Insert(sql.NewRow(int32(i))))
2825
}
2926

30-
memDb.AddTable("test", tableTest)
27+
db.AddTable("test", tableTest)
3128

3229
return e
3330
}

sql/analyzer/analyzer_test.go

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,8 @@ func TestAnalyzer_Analyze(t *testing.T) {
2121
})
2222
table2 := mem.NewTable("mytable2", sql.Schema{{Name: "i2", Type: sql.Int32, Source: "mytable2"}})
2323
db := mem.NewDatabase("mydb")
24-
25-
memDb, ok := db.(*mem.Database)
26-
require.True(ok)
27-
28-
memDb.AddTable("mytable", table)
29-
memDb.AddTable("mytable2", table2)
24+
db.AddTable("mytable", table)
25+
db.AddTable("mytable2", table2)
3026

3127
catalog := &sql.Catalog{Databases: []sql.Database{db}}
3228
a := New(catalog)
@@ -208,16 +204,16 @@ func TestAddRule(t *testing.T) {
208204
require := require.New(t)
209205

210206
a := New(nil)
211-
require.Len(a.Rules, 12)
212-
a.AddRule("foo", pushdown)
213207
require.Len(a.Rules, 13)
208+
a.AddRule("foo", pushdown)
209+
require.Len(a.Rules, 14)
214210
}
215211

216212
func TestAddValidationRule(t *testing.T) {
217213
require := require.New(t)
218214

219215
a := New(nil)
220-
require.Len(a.ValidationRules, 5)
221-
a.AddValidationRule("foo", validateGroupBy)
222216
require.Len(a.ValidationRules, 6)
217+
a.AddValidationRule("foo", validateGroupBy)
218+
require.Len(a.ValidationRules, 7)
223219
}

sql/analyzer/rules.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var DefaultRules = []Rule{
2424
{"pushdown", pushdown},
2525
{"optimize_distinct", optimizeDistinct},
2626
{"erase_projection", eraseProjection},
27+
{"index_catalog", indexCatalog},
2728
}
2829

2930
var (
@@ -638,6 +639,27 @@ func dedupStrings(in []string) []string {
638639
return result
639640
}
640641

642+
// indexCatalog sets the catalog in the CreateIndex nodes.
643+
func indexCatalog(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error) {
644+
if !n.Resolved() {
645+
return n, nil
646+
}
647+
648+
ci, ok := n.(*plan.CreateIndex)
649+
if !ok {
650+
return n, nil
651+
}
652+
653+
span, ctx := ctx.Span("index_catalog")
654+
defer span.Finish()
655+
656+
nc := *ci
657+
ci.Catalog = a.Catalog
658+
ci.CurrentDatabase = a.CurrentDatabase
659+
660+
return &nc, nil
661+
}
662+
641663
func pushdown(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error) {
642664
span, ctx := ctx.Span("pushdown")
643665
defer span.Finish()

sql/analyzer/rules_test.go

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,9 @@ func TestResolveSubqueries(t *testing.T) {
2121
})
2222
table3 := mem.NewTable("baz", sql.Schema{{Name: "c", Type: sql.Int64, Source: "baz"}})
2323
db := mem.NewDatabase("mydb")
24-
memDb, ok := db.(*mem.Database)
25-
require.True(ok)
26-
27-
memDb.AddTable("foo", table1)
28-
memDb.AddTable("bar", table2)
29-
memDb.AddTable("baz", table3)
24+
db.AddTable("foo", table1)
25+
db.AddTable("bar", table2)
26+
db.AddTable("baz", table3)
3027

3128
catalog := &sql.Catalog{Databases: []sql.Database{db}}
3229
a := New(catalog)
@@ -106,10 +103,7 @@ func TestResolveTables(t *testing.T) {
106103

107104
table := mem.NewTable("mytable", sql.Schema{{Name: "i", Type: sql.Int32}})
108105
db := mem.NewDatabase("mydb")
109-
memDb, ok := db.(*mem.Database)
110-
require.True(ok)
111-
112-
memDb.AddTable("mytable", table)
106+
db.AddTable("mytable", table)
113107

114108
catalog := &sql.Catalog{Databases: []sql.Database{db}}
115109

@@ -144,10 +138,7 @@ func TestResolveTablesNested(t *testing.T) {
144138

145139
table := mem.NewTable("mytable", sql.Schema{{Name: "i", Type: sql.Int32}})
146140
db := mem.NewDatabase("mydb")
147-
memDb, ok := db.(*mem.Database)
148-
require.True(ok)
149-
150-
memDb.AddTable("mytable", table)
141+
db.AddTable("mytable", table)
151142

152143
catalog := &sql.Catalog{Databases: []sql.Database{db}}
153144

sql/analyzer/validation_rules.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package analyzer
22

33
import (
4+
"strings"
5+
46
errors "gopkg.in/src-d/go-errors.v1"
57
"gopkg.in/src-d/go-mysql-server.v0/sql"
68
"gopkg.in/src-d/go-mysql-server.v0/sql/expression"
@@ -13,6 +15,7 @@ const (
1315
validateGroupByRule = "validate_group_by"
1416
validateSchemaSourceRule = "validate_schema_source"
1517
validateProjectTuplesRule = "validate_project_tuples"
18+
validateIndexCreationRule = "validate_index_creation"
1619
)
1720

1821
var (
@@ -30,6 +33,9 @@ var (
3033
// ErrProjectTuple is returned when there is a tuple of more than 1 column
3134
// inside a projection.
3235
ErrProjectTuple = errors.NewKind("selected field %d should have 1 column, but has %d")
36+
// ErrUnknownIndexColumns is returned when there are columns in the expr
37+
// to index that are unknown in the table.
38+
ErrUnknownIndexColumns = errors.NewKind("unknown columns to index for table %q: %s")
3339
)
3440

3541
// DefaultValidationRules to apply while analyzing nodes.
@@ -39,6 +45,7 @@ var DefaultValidationRules = []ValidationRule{
3945
{validateGroupByRule, validateGroupBy},
4046
{validateSchemaSourceRule, validateSchemaSource},
4147
{validateProjectTuplesRule, validateProjectTuples},
48+
{validateIndexCreationRule, validateIndexCreation},
4249
}
4350

4451
func validateIsResolved(ctx *sql.Context, n sql.Node) error {
@@ -130,6 +137,38 @@ func validateSchemaSource(ctx *sql.Context, n sql.Node) error {
130137
return nil
131138
}
132139

140+
func validateIndexCreation(ctx *sql.Context, n sql.Node) error {
141+
span, ctx := ctx.Span("validate_index_creation")
142+
defer span.Finish()
143+
144+
ci, ok := n.(*plan.CreateIndex)
145+
if !ok {
146+
return nil
147+
}
148+
149+
schema := ci.Table.Schema()
150+
table := schema[0].Source
151+
152+
var unknownColumns []string
153+
for _, expr := range ci.Exprs {
154+
expression.Inspect(expr, func(e sql.Expression) bool {
155+
gf, ok := e.(*expression.GetField)
156+
if ok {
157+
if gf.Table() != table || !schema.Contains(gf.Name()) {
158+
unknownColumns = append(unknownColumns, gf.Name())
159+
}
160+
}
161+
return true
162+
})
163+
}
164+
165+
if len(unknownColumns) > 0 {
166+
return ErrUnknownIndexColumns.New(table, strings.Join(unknownColumns, ", "))
167+
}
168+
169+
return nil
170+
}
171+
133172
func validateSchema(t sql.Table) error {
134173
name := t.Name()
135174
for _, col := range t.Schema() {

0 commit comments

Comments
 (0)