Skip to content

Commit f028104

Browse files
authoredNov 18, 2016
sql: support DESCRIBE table. (#66)
1 parent cf242a8 commit f028104

File tree

7 files changed

+134
-1
lines changed

7 files changed

+134
-1
lines changed
 

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ gitql supports a subset of the SQL standard, currently including:
5858
* `ORDER BY` (with `ASC` and `DESC`)
5959
* `LIMIT`
6060
* `SHOW TABLES`
61+
* `DESCRIBE TABLE`
6162

6263
## License
6364

‎sql/analyzer/analyzer_test.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,21 @@ func TestAnalyzer_Analyze(t *testing.T) {
4545
plan.NewUnresolvedTable("mytable"),
4646
)
4747
analyzed, err = a.Analyze(notAnalyzed)
48-
expected := plan.NewProject(
48+
var expected sql.Node = plan.NewProject(
4949
[]sql.Expression{expression.NewGetField(0, sql.Integer, "i")},
5050
table,
5151
)
5252
assert.Nil(err)
5353
assert.Equal(expected, analyzed)
5454

55+
notAnalyzed = plan.NewDescribe(
56+
plan.NewUnresolvedTable("mytable"),
57+
)
58+
analyzed, err = a.Analyze(notAnalyzed)
59+
expected = plan.NewDescribe(table)
60+
assert.Nil(err)
61+
assert.Equal(expected, analyzed)
62+
5563
notAnalyzed = plan.NewProject(
5664
[]sql.Expression{expression.NewStar()},
5765
plan.NewUnresolvedTable("mytable"),

‎sql/parse/parse.go

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package parse
22

33
import (
44
"fmt"
5+
"regexp"
56
"strconv"
67
"strings"
78

@@ -34,6 +35,11 @@ func Parse(s string) (sql.Node, error) {
3435
return plan.NewShowTables(&sql.UnresolvedDatabase{}), nil
3536
}
3637

38+
t := regexp.MustCompile(`^describe\s+table\s+(.*)`).FindStringSubmatch(strings.ToLower(s))
39+
if len(t) == 2 && t[1] != "" {
40+
return plan.NewDescribe(plan.NewUnresolvedTable(t[1])), nil
41+
}
42+
3743
stmt, err := sqlparser.Parse(s)
3844
if err != nil {
3945
return nil, err

‎sql/parse/parse_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import (
1111
)
1212

1313
var fixtures = map[string]sql.Node{
14+
`DESCRIBE TABLE foo;`: plan.NewDescribe(
15+
plan.NewUnresolvedTable("foo"),
16+
),
1417
`SELECT foo, bar FROM foo;`: plan.NewProject(
1518
[]sql.Expression{
1619
expression.NewUnresolvedColumn("foo"),

‎sql/plan/common.go

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ type UnaryNode struct {
66
Child sql.Node
77
}
88

9+
func (n UnaryNode) Resolved() bool {
10+
return n.Child.Resolved()
11+
}
12+
913
func (n UnaryNode) Children() []sql.Node {
1014
return []sql.Node{n.Child}
1115
}

‎sql/plan/describe.go

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package plan
2+
3+
import (
4+
"io"
5+
6+
"github.com/gitql/gitql/sql"
7+
)
8+
9+
type Describe struct {
10+
UnaryNode
11+
}
12+
13+
func NewDescribe(child sql.Node) *Describe {
14+
return &Describe{UnaryNode{child}}
15+
}
16+
17+
func (d *Describe) Schema() sql.Schema {
18+
return sql.Schema{
19+
sql.Field{
20+
Name: "name",
21+
Type: sql.String,
22+
},
23+
sql.Field{
24+
Name: "type",
25+
Type: sql.String,
26+
},
27+
}
28+
}
29+
30+
func (d *Describe) RowIter() (sql.RowIter, error) {
31+
return &describeIter{schema: d.Child.Schema()}, nil
32+
}
33+
34+
func (d *Describe) TransformUp(f func(sql.Node) sql.Node) sql.Node {
35+
c := d.UnaryNode.Child.TransformUp(f)
36+
n := NewDescribe(c)
37+
38+
return f(n)
39+
}
40+
41+
func (d *Describe) TransformExpressionsUp(f func(sql.Expression) sql.Expression) sql.Node {
42+
c := d.UnaryNode.Child.TransformExpressionsUp(f)
43+
n := NewDescribe(c)
44+
45+
return n
46+
}
47+
48+
type describeIter struct {
49+
schema sql.Schema
50+
i int
51+
}
52+
53+
func (i *describeIter) Next() (sql.Row, error) {
54+
if i.i >= len(i.schema) {
55+
return nil, io.EOF
56+
}
57+
58+
f := i.schema[i.i]
59+
i.i++
60+
return sql.NewMemoryRow(f.Name, f.Type.Name()), nil
61+
}

‎sql/plan/describe_test.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package plan
2+
3+
import (
4+
"io"
5+
"testing"
6+
7+
"github.com/gitql/gitql/mem"
8+
"github.com/gitql/gitql/sql"
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestDescribe(t *testing.T) {
13+
assert := assert.New(t)
14+
15+
table := mem.NewTable("test", sql.Schema{
16+
sql.Field{Name: "c1", Type: sql.String},
17+
sql.Field{Name: "c2", Type: sql.Integer},
18+
})
19+
20+
d := NewDescribe(table)
21+
iter, err := d.RowIter()
22+
assert.Nil(err)
23+
assert.NotNil(iter)
24+
25+
n, err := iter.Next()
26+
assert.Nil(err)
27+
assert.Equal(sql.NewMemoryRow("c1", "string"), n)
28+
29+
n, err = iter.Next()
30+
assert.Nil(err)
31+
assert.Equal(sql.NewMemoryRow("c2", "integer"), n)
32+
33+
n, err = iter.Next()
34+
assert.Equal(io.EOF, err)
35+
assert.Nil(n)
36+
}
37+
38+
func TestDescribe_Empty(t *testing.T) {
39+
assert := assert.New(t)
40+
41+
d := NewDescribe(NewUnresolvedTable("test_table"))
42+
43+
iter, err := d.RowIter()
44+
assert.Nil(err)
45+
assert.NotNil(iter)
46+
47+
n, err := iter.Next()
48+
assert.Equal(io.EOF, err)
49+
assert.Nil(n)
50+
}

0 commit comments

Comments
 (0)
Please sign in to comment.