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

Commit d038f7f

Browse files
author
Juanjo Alvarez
committed
generalize the tuple detection for projectsions and groupbys
Signed-off-by: Juanjo Alvarez <[email protected]>
1 parent c19f89a commit d038f7f

File tree

3 files changed

+76
-26
lines changed

3 files changed

+76
-26
lines changed

sql/analyzer/resolve_columns.go

+31-19
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"sort"
66
"strings"
77

8-
errors "gopkg.in/src-d/go-errors.v1"
8+
"gopkg.in/src-d/go-errors.v1"
99
"gopkg.in/src-d/go-mysql-server.v0/sql"
1010
"gopkg.in/src-d/go-mysql-server.v0/sql/expression"
1111
"gopkg.in/src-d/go-mysql-server.v0/sql/plan"
@@ -38,29 +38,41 @@ func checkAliases(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error) {
3838
return n, err
3939
}
4040

41-
func checkDistinctNoTuples(ctx *sql.Context, a *Analyzer, node sql.Node) (sql.Node, error) {
42-
span, _ := ctx.Span("no_distinct_tuples")
41+
func checkNoTuplesProjected(ctx *sql.Context, a *Analyzer, node sql.Node) (sql.Node, error) {
42+
span, _ := ctx.Span("no_tuples_projected")
4343
defer span.Finish()
4444

45-
a.Log("check no tuples as distinct projection, node of type: %T", node)
46-
var err error
47-
if node, ok := node.(*plan.Distinct); ok {
48-
_, err = node.TransformUp(func(node sql.Node) (sql.Node, error) {
49-
project, ok := node.(*plan.Project)
50-
if ok {
51-
for _, col := range project.Projections {
52-
_, ok := col.(expression.Tuple)
53-
if ok {
54-
return node, ErrDistinctTuple.New()
55-
}
45+
a.Log("check no tuples as in projection, node of type: %T", node)
46+
return node.TransformUp(func(node sql.Node) (sql.Node, error) {
47+
project, ok := node.(*plan.Project)
48+
if ok {
49+
for _, col := range project.Projections {
50+
_, ok := col.(expression.Tuple)
51+
if ok {
52+
return node, ErrTupleProjected.New()
5653
}
5754
}
55+
}
56+
groupby, ok := node.(*plan.GroupBy)
57+
if ok {
58+
for _, c := range groupby.Grouping {
59+
fmt.Println("XXX grouping: ", c)
60+
_, ok := c.(expression.Tuple)
61+
if ok {
62+
return node, ErrTupleProjected.New()
63+
}
64+
}
65+
for _, c := range groupby.Aggregate {
66+
fmt.Println("XXX aggregate: ", c)
67+
_, ok := c.(expression.Tuple)
68+
if ok {
69+
return node, ErrTupleProjected.New()
70+
}
71+
}
72+
}
5873

59-
return node, nil
60-
})
61-
}
62-
63-
return node, err
74+
return node, nil
75+
})
6476
}
6577

6678
func lookForAliasDeclarations(node sql.Expressioner) map[string]struct{} {

sql/analyzer/resolve_columns_test.go

+43-5
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ func TestMisusedAlias(t *testing.T) {
7575
require.EqualError(err, ErrMisusedAlias.New("alias_i").Error())
7676
}
7777

78-
func TestDistinctNoTuples(t *testing.T) {
78+
func TestNoTuplesProjected(t *testing.T) {
7979
require := require.New(t)
80-
f := getRule("check_distinct_no_tuples")
80+
f := getRule("no_tuples_projected")
8181

8282
table := mem.NewTable("mytable", sql.Schema{
8383
{Name: "i", Type: sql.Int32},
@@ -89,10 +89,48 @@ func TestDistinctNoTuples(t *testing.T) {
8989
expression.NewLiteral(2, sql.Int64),
9090
),
9191
}, plan.NewResolvedTable(table))
92-
d := plan.NewDistinct(node)
9392

94-
_, err := f.Apply(sql.NewEmptyContext(), nil, d)
95-
require.EqualError(err, ErrDistinctTuple.New().Error())
93+
_, err := f.Apply(sql.NewEmptyContext(), nil, node)
94+
require.EqualError(err, ErrTupleProjected.New().Error())
95+
}
96+
97+
func TestNoTuplesGroupBy(t *testing.T) {
98+
require := require.New(t)
99+
f := getRule("no_tuples_projected")
100+
101+
table := mem.NewTable("mytable", sql.Schema{
102+
{Name: "i", Type: sql.Int32},
103+
})
104+
105+
node := plan.NewGroupBy([]sql.Expression{
106+
expression.NewUnresolvedColumn("a"),
107+
expression.NewUnresolvedColumn("b"),
108+
},
109+
[]sql.Expression{
110+
expression.NewTuple(
111+
expression.NewLiteral(1, sql.Int64),
112+
expression.NewLiteral(2, sql.Int64),
113+
),
114+
},
115+
plan.NewResolvedTable(table))
116+
117+
_, err := f.Apply(sql.NewEmptyContext(), nil, node)
118+
require.EqualError(err, ErrTupleProjected.New().Error())
119+
120+
node = plan.NewGroupBy([]sql.Expression{
121+
expression.NewTuple(
122+
expression.NewLiteral(1, sql.Int64),
123+
expression.NewLiteral(2, sql.Int64),
124+
),
125+
},
126+
[]sql.Expression{
127+
expression.NewUnresolvedColumn("a"),
128+
expression.NewUnresolvedColumn("b"),
129+
},
130+
plan.NewResolvedTable(table))
131+
132+
_, err = f.Apply(sql.NewEmptyContext(), nil, node)
133+
require.EqualError(err, ErrTupleProjected.New().Error())
96134
}
97135

98136
func TestQualifyColumns(t *testing.T) {

sql/analyzer/rules.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var OnceBeforeDefault = []Rule{
2828
{"resolve_subqueries", resolveSubqueries},
2929
{"resolve_tables", resolveTables},
3030
{"check_aliases", checkAliases},
31-
{"check_distinct_no_tuples", checkDistinctNoTuples},
31+
{"no_tuples_projected", checkNoTuplesProjected},
3232
}
3333

3434
// OnceAfterDefault contains the rules to be applied just once after the
@@ -67,5 +67,5 @@ var (
6767
// ErrMisusedAlias is returned when a alias is defined and used in the same projection.
6868
ErrMisusedAlias = errors.NewKind("column %q does not exist in scope, but there is an alias defined in" +
6969
" this projection with that name. Aliases cannot be used in the same projection they're defined in")
70-
ErrDistinctTuple = errors.NewKind("tuple used as DISTINCT argument, remove the ()")
70+
ErrTupleProjected = errors.NewKind("unexpected tuple found, maybe remove the ()?")
7171
)

0 commit comments

Comments
 (0)