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

Commit 56556f1

Browse files
author
Juanjo Alvarez
committed
Fix validation rule for tuples in Projections
Signed-off-by: Juanjo Alvarez <[email protected]>
1 parent 20fabe4 commit 56556f1

6 files changed

+30
-107
lines changed

Diff for: engine_test.go

-2
Original file line numberDiff line numberDiff line change
@@ -909,8 +909,6 @@ var queries = []struct {
909909
"SELECT FROM_BASE64('YmFy')",
910910
[]sql.Row{{string("bar")}},
911911
},
912-
<<<<<<< HEAD
913-
<<<<<<< HEAD
914912
{
915913
"SELECT DATE_ADD('2018-05-02', INTERVAL 1 DAY)",
916914
[]sql.Row{{time.Date(2018, time.May, 3, 0, 0, 0, 0, time.UTC)}},

Diff for: sql/analyzer/resolve_columns.go

-35
Original file line numberDiff line numberDiff line change
@@ -38,41 +38,6 @@ func checkAliases(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error) {
3838
return n, err
3939
}
4040

41-
func checkNoTuplesProjected(ctx *sql.Context, a *Analyzer, node sql.Node) (sql.Node, error) {
42-
span, _ := ctx.Span("no_tuples_projected")
43-
defer span.Finish()
44-
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()
53-
}
54-
}
55-
}
56-
groupby, ok := node.(*plan.GroupBy)
57-
if ok {
58-
for _, c := range groupby.Grouping {
59-
_, ok := c.(expression.Tuple)
60-
if ok {
61-
return node, ErrTupleProjected.New()
62-
}
63-
}
64-
for _, c := range groupby.Aggregate {
65-
_, ok := c.(expression.Tuple)
66-
if ok {
67-
return node, ErrTupleProjected.New()
68-
}
69-
}
70-
}
71-
72-
return node, nil
73-
})
74-
}
75-
7641
func lookForAliasDeclarations(node sql.Expressioner) map[string]struct{} {
7742
var (
7843
aliases = map[string]struct{}{}

Diff for: sql/analyzer/resolve_columns_test.go

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

78-
func TestNoTuplesProjected(t *testing.T) {
79-
require := require.New(t)
80-
f := getRule("no_tuples_projected")
81-
82-
table := mem.NewTable("mytable", sql.Schema{
83-
{Name: "i", Type: sql.Int32},
84-
})
85-
86-
node := plan.NewProject([]sql.Expression{
87-
expression.NewTuple(
88-
expression.NewLiteral(1, sql.Int64),
89-
expression.NewLiteral(2, sql.Int64),
90-
),
91-
}, plan.NewResolvedTable(table))
92-
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())
134-
}
135-
13678
func TestQualifyColumns(t *testing.T) {
13779
require := require.New(t)
13880
f := getRule("qualify_columns")

Diff for: sql/analyzer/rules.go

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

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

Diff for: sql/analyzer/validation_rules.go

+18-9
Original file line numberDiff line numberDiff line change
@@ -195,27 +195,36 @@ func validateSchema(t *plan.ResolvedTable) error {
195195
return nil
196196
}
197197

198-
func validateProjectTuples(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error) {
199-
span, _ := ctx.Span("validate_project_tuples")
200-
defer span.Finish()
198+
func findProjectTuples(n sql.Node) (sql.Node, error) {
199+
if n == nil {
200+
return n, nil
201+
}
201202

202203
switch n := n.(type) {
203-
case *plan.Project:
204-
for i, e := range n.Projections {
204+
case *plan.Project, *plan.GroupBy:
205+
for i, e := range n.(sql.Expressioner).Expressions() {
205206
if sql.IsTuple(e.Type()) {
206207
return nil, ErrProjectTuple.New(i+1, sql.NumColumns(e.Type()))
207208
}
208209
}
209-
case *plan.GroupBy:
210-
for i, e := range n.Aggregate {
211-
if sql.IsTuple(e.Type()) {
212-
return nil, ErrProjectTuple.New(i+1, sql.NumColumns(e.Type()))
210+
default:
211+
for _, ch := range n.Children() {
212+
_, err := findProjectTuples(ch)
213+
if err != nil {
214+
return nil, err
213215
}
214216
}
215217
}
218+
216219
return n, nil
217220
}
218221

222+
func validateProjectTuples(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error) {
223+
span, _ := ctx.Span("validate_project_tuples")
224+
defer span.Finish()
225+
return findProjectTuples(n)
226+
}
227+
219228
func validateCaseResultTypes(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error) {
220229
span, ctx := ctx.Span("validate_case_result_types")
221230
defer span.Finish()

Diff for: sql/analyzer/validation_rules_test.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,22 @@ func TestValidateProjectTuples(t *testing.T) {
235235
plan.NewProject([]sql.Expression{
236236
expression.NewTuple(
237237
expression.NewLiteral(1, sql.Int64),
238-
expression.NewLiteral(1, sql.Int64),
238+
expression.NewLiteral(2, sql.Int64),
239239
),
240240
}, nil),
241241
false,
242242
},
243+
{
244+
"distinct with a 2 elem tuple inside the project",
245+
plan.NewDistinct(
246+
plan.NewProject([]sql.Expression{
247+
expression.NewTuple(
248+
expression.NewLiteral(1, sql.Int64),
249+
expression.NewLiteral(2, sql.Int64),
250+
),
251+
}, nil)),
252+
false,
253+
},
243254
{
244255
"groupby with no tuple",
245256
plan.NewGroupBy([]sql.Expression{

0 commit comments

Comments
 (0)