Skip to content

Commit fb17c2f

Browse files
authored
sql: split Catalog API into Databases/FunctionRegistry (#113)
1 parent a6fe13d commit fb17c2f

File tree

4 files changed

+287
-249
lines changed

4 files changed

+287
-249
lines changed

sql/catalog.go

+15-107
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
11
package sql
22

33
import (
4-
"errors"
54
"fmt"
6-
"reflect"
75
)
86

7+
// Catalog holds databases, tables and functions.
98
type Catalog struct {
10-
Databases []Database
11-
Functions map[string]*FunctionEntry
9+
Databases
10+
FunctionRegistry
1211
}
1312

13+
// NewCatalog returns a new empty Catalog.
1414
func NewCatalog() *Catalog {
1515
return &Catalog{
16-
Functions: map[string]*FunctionEntry{},
16+
Databases: Databases{},
17+
FunctionRegistry: NewFunctionRegistry(),
1718
}
1819
}
1920

20-
func (c Catalog) Database(name string) (Database, error) {
21-
for _, db := range c.Databases {
21+
// Databases is a collection of Database.
22+
type Databases []Database
23+
24+
// Database returns the Database with the given name if it exists.
25+
func (d Databases) Database(name string) (Database, error) {
26+
for _, db := range d {
2227
if db.Name() == name {
2328
return db, nil
2429
}
@@ -27,8 +32,9 @@ func (c Catalog) Database(name string) (Database, error) {
2732
return nil, fmt.Errorf("database not found: %s", name)
2833
}
2934

30-
func (c Catalog) Table(dbName string, tableName string) (Table, error) {
31-
db, err := c.Database(dbName)
35+
// Table returns the Table with the given name if it exists.
36+
func (d Databases) Table(dbName string, tableName string) (Table, error) {
37+
db, err := d.Database(dbName)
3238
if err != nil {
3339
return nil, err
3440
}
@@ -41,101 +47,3 @@ func (c Catalog) Table(dbName string, tableName string) (Table, error) {
4147

4248
return table, nil
4349
}
44-
45-
func (c Catalog) RegisterFunction(name string, f interface{}) error {
46-
e, err := inspectFunction(f)
47-
if err != nil {
48-
return err
49-
}
50-
51-
c.Functions[name] = e
52-
return nil
53-
}
54-
55-
func (c Catalog) Function(name string) (*FunctionEntry, error) {
56-
e, ok := c.Functions[name]
57-
if !ok {
58-
return nil, fmt.Errorf("function not found: %s", name)
59-
}
60-
61-
return e, nil
62-
}
63-
64-
type FunctionEntry struct {
65-
v reflect.Value
66-
}
67-
68-
func (e *FunctionEntry) Build(args ...Expression) (Expression, error) {
69-
t := e.v.Type()
70-
if !t.IsVariadic() && len(args) != t.NumIn() {
71-
return nil, fmt.Errorf("expected %d args, got %d",
72-
t.NumIn(), len(args))
73-
}
74-
75-
if t.IsVariadic() && len(args) < t.NumIn()-1 {
76-
return nil, fmt.Errorf("expected at least %d args, got %d",
77-
t.NumIn(), len(args))
78-
}
79-
80-
var in []reflect.Value
81-
for _, arg := range args {
82-
in = append(in, reflect.ValueOf(arg))
83-
}
84-
85-
out := e.v.Call(in)
86-
if len(out) != 1 {
87-
return nil, fmt.Errorf("expected 1 return value, got %d: ", len(out))
88-
}
89-
90-
expr, ok := out[0].Interface().(Expression)
91-
if !ok {
92-
return nil, errors.New("return value doesn't implement Expression")
93-
}
94-
95-
return expr, nil
96-
}
97-
98-
var (
99-
expressionType = buildExpressionType()
100-
expressionSliceType = buildExpressionSliceType()
101-
)
102-
103-
func buildExpressionType() reflect.Type {
104-
var v Expression
105-
return reflect.ValueOf(&v).Elem().Type()
106-
}
107-
108-
func buildExpressionSliceType() reflect.Type {
109-
var v []Expression
110-
return reflect.ValueOf(&v).Elem().Type()
111-
}
112-
113-
func inspectFunction(f interface{}) (*FunctionEntry, error) {
114-
v := reflect.ValueOf(f)
115-
t := v.Type()
116-
if t.Kind() != reflect.Func {
117-
return nil, fmt.Errorf("expected function, got: %s", t.Kind())
118-
}
119-
120-
if t.NumOut() != 1 {
121-
return nil, errors.New("function builders must return a single Expression")
122-
}
123-
124-
out := t.Out(0)
125-
if !out.Implements(expressionType) {
126-
return nil, fmt.Errorf("return value doesn't implement Expression: %s", out)
127-
}
128-
129-
for i := 0; i < t.NumIn(); i++ {
130-
in := t.In(i)
131-
if i == t.NumIn()-1 && t.IsVariadic() && in == expressionSliceType {
132-
continue
133-
}
134-
135-
if in != expressionType {
136-
return nil, fmt.Errorf("input argument %d is not a Expression", i)
137-
}
138-
}
139-
140-
return &FunctionEntry{v}, nil
141-
}

sql/catalog_test.go

-142
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"github.com/gitql/gitql/mem"
77
"github.com/gitql/gitql/sql"
88

9-
"github.com/gitql/gitql/sql/expression"
109
"github.com/stretchr/testify/assert"
1110
)
1211

@@ -49,144 +48,3 @@ func TestCatalog_Table(t *testing.T) {
4948
assert.NoError(err)
5049
assert.Equal(mytable, table)
5150
}
52-
53-
func TestCatalog_RegisterFunction_NoArgs(t *testing.T) {
54-
assert := assert.New(t)
55-
56-
c := sql.NewCatalog()
57-
name := "func"
58-
var expected sql.Expression = expression.NewStar()
59-
err := c.RegisterFunction(name, func() sql.Expression {
60-
return expected
61-
})
62-
assert.Nil(err)
63-
64-
f, err := c.Function(name)
65-
assert.Nil(err)
66-
67-
e, err := f.Build()
68-
assert.Nil(err)
69-
assert.Equal(expected, e)
70-
71-
e, err = f.Build(expression.NewStar())
72-
assert.NotNil(err)
73-
assert.Nil(e)
74-
75-
e, err = f.Build(expression.NewStar(), expression.NewStar())
76-
assert.NotNil(err)
77-
assert.Nil(e)
78-
}
79-
80-
func TestCatalog_RegisterFunction_OneArg(t *testing.T) {
81-
assert := assert.New(t)
82-
83-
c := sql.NewCatalog()
84-
name := "func"
85-
var expected sql.Expression = expression.NewStar()
86-
err := c.RegisterFunction(name, func(sql.Expression) sql.Expression {
87-
return expected
88-
})
89-
assert.Nil(err)
90-
91-
f, err := c.Function(name)
92-
assert.Nil(err)
93-
94-
e, err := f.Build()
95-
assert.NotNil(err)
96-
assert.Nil(e)
97-
98-
e, err = f.Build(expression.NewStar())
99-
assert.Nil(err)
100-
assert.Equal(expected, e)
101-
102-
e, err = f.Build(expression.NewStar(), expression.NewStar())
103-
assert.NotNil(err)
104-
assert.Nil(e)
105-
}
106-
107-
func TestCatalog_RegisterFunction_Variadic(t *testing.T) {
108-
assert := assert.New(t)
109-
110-
c := sql.NewCatalog()
111-
name := "func"
112-
var expected sql.Expression = expression.NewStar()
113-
err := c.RegisterFunction(name, func(...sql.Expression) sql.Expression {
114-
return expected
115-
})
116-
assert.Nil(err)
117-
118-
f, err := c.Function(name)
119-
assert.Nil(err)
120-
121-
e, err := f.Build()
122-
assert.Nil(err)
123-
assert.Equal(expected, e)
124-
125-
e, err = f.Build(expression.NewStar())
126-
assert.Nil(err)
127-
assert.Equal(expected, e)
128-
129-
e, err = f.Build(expression.NewStar(), expression.NewStar())
130-
assert.Nil(err)
131-
assert.Equal(expected, e)
132-
}
133-
134-
func TestCatalog_RegisterFunction_OneAndVariadic(t *testing.T) {
135-
assert := assert.New(t)
136-
137-
c := sql.NewCatalog()
138-
name := "func"
139-
var expected sql.Expression = expression.NewStar()
140-
err := c.RegisterFunction(name, func(sql.Expression, ...sql.Expression) sql.Expression {
141-
return expected
142-
})
143-
assert.Nil(err)
144-
145-
f, err := c.Function(name)
146-
assert.Nil(err)
147-
148-
e, err := f.Build()
149-
assert.NotNil(err)
150-
assert.Nil(e)
151-
152-
e, err = f.Build(expression.NewStar())
153-
assert.Nil(err)
154-
assert.Equal(expected, e)
155-
156-
e, err = f.Build(expression.NewStar(), expression.NewStar())
157-
assert.Nil(err)
158-
assert.Equal(expected, e)
159-
}
160-
161-
func TestCatalog_RegisterFunction_Invalid(t *testing.T) {
162-
assert := assert.New(t)
163-
164-
c := sql.NewCatalog()
165-
name := "func"
166-
err := c.RegisterFunction(name, func(sql.Table) sql.Expression {
167-
return nil
168-
})
169-
assert.NotNil(err)
170-
171-
err = c.RegisterFunction(name, func(sql.Expression) sql.Table {
172-
return nil
173-
})
174-
assert.NotNil(err)
175-
176-
err = c.RegisterFunction(name, func(sql.Expression) (sql.Table, error) {
177-
return nil, nil
178-
})
179-
assert.NotNil(err)
180-
181-
err = c.RegisterFunction(name, 1)
182-
assert.NotNil(err)
183-
}
184-
185-
func TestCatalog_Function_NotExists(t *testing.T) {
186-
assert := assert.New(t)
187-
188-
c := sql.NewCatalog()
189-
f, err := c.Function("func")
190-
assert.NotNil(err)
191-
assert.Nil(f)
192-
}

0 commit comments

Comments
 (0)