@@ -12,6 +12,79 @@ import (
1212 "gopkg.in/src-d/go-vitess.v1/vt/sqlparser"
1313)
1414
15+ func checkAliases (ctx * sql.Context , a * Analyzer , n sql.Node ) (sql.Node , error ) {
16+ span , _ := ctx .Span ("check_aliases" )
17+ defer span .Finish ()
18+
19+ a .Log ("check aliases" )
20+
21+ var err error
22+ plan .Inspect (n , func (node sql.Node ) bool {
23+ p , ok := node .(* plan.Project )
24+ if ! ok {
25+ return true
26+ }
27+
28+ aliases := lookForAliasDeclarations (p )
29+ for alias := range aliases {
30+ if isAliasUsed (p , alias ) {
31+ err = ErrMisusedAlias .New (alias )
32+ }
33+ }
34+
35+ return true
36+ })
37+
38+ return n , err
39+ }
40+
41+ func lookForAliasDeclarations (node sql.Expressioner ) map [string ]struct {} {
42+ var (
43+ aliases = map [string ]struct {}{}
44+ in = struct {}{}
45+ )
46+
47+ for _ , e := range node .Expressions () {
48+ expression .Inspect (e , func (expr sql.Expression ) bool {
49+ if alias , ok := expr .(* expression.Alias ); ok {
50+ aliases [alias .Name ()] = in
51+ }
52+
53+ return true
54+ })
55+ }
56+
57+ return aliases
58+ }
59+
60+ func isAliasUsed (node sql.Expressioner , alias string ) bool {
61+ var found bool
62+ for _ , e := range node .Expressions () {
63+ expression .Inspect (e , func (expr sql.Expression ) bool {
64+ if a , ok := expr .(* expression.Alias ); ok {
65+ if a .Name () == alias {
66+ return false
67+ }
68+
69+ return true
70+ }
71+
72+ if n , ok := expr .(sql.Nameable ); ok && n .Name () == alias {
73+ found = true
74+ return false
75+ }
76+
77+ return true
78+ })
79+
80+ if found {
81+ break
82+ }
83+ }
84+
85+ return found
86+ }
87+
1588// deferredColumn is a wrapper on UnresolvedColumn used only to defer the
1689// resolution of the column because it may require some work done by
1790// other analyzer phases.
@@ -221,18 +294,6 @@ func resolveColumns(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error)
221294 }
222295 }
223296
224- var (
225- aliasMap = make (map [string ]struct {})
226- exists = struct {}{}
227- )
228- if project , ok := n .(* plan.Project ); ok {
229- for _ , e := range project .Projections {
230- if alias , ok := e .(* expression.Alias ); ok {
231- aliasMap [strings .ToLower (alias .Name ())] = exists
232- }
233- }
234- }
235-
236297 expressioner , ok := n .(sql.Expressioner )
237298 if ! ok {
238299 return n , nil
@@ -287,11 +348,6 @@ func resolveColumns(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error)
287348 return nil , ErrColumnTableNotFound .New (uc .Table (), uc .Name ())
288349 }
289350
290- if _ , ok := aliasMap [name ]; ok {
291- // no nested aliases
292- return nil , ErrMisusedAlias .New (uc .Name ())
293- }
294-
295351 return nil , ErrColumnNotFound .New (uc .Name ())
296352 }
297353 }
0 commit comments