-
-
Notifications
You must be signed in to change notification settings - Fork 19
/
table_expr.go
155 lines (149 loc) · 4.22 KB
/
table_expr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Copyright 2023 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ast
import (
"fmt"
vitess "github.com/dolthub/vitess/go/vt/sqlparser"
"github.com/dolthub/doltgresql/postgres/parser/sem/tree"
)
// nodeTableExpr handles tree.TableExpr nodes.
func nodeTableExpr(node tree.TableExpr) (vitess.TableExpr, error) {
switch node := node.(type) {
case *tree.AliasedTableExpr:
return nodeAliasedTableExpr(node)
case *tree.JoinTableExpr:
left, err := nodeTableExpr(node.Left)
if err != nil {
return nil, err
}
right, err := nodeTableExpr(node.Right)
if err != nil {
return nil, err
}
var condition vitess.JoinCondition
switch treeCondition := node.Cond.(type) {
case tree.NaturalJoinCond:
// Nothing to do, the default value is equivalent
case *tree.OnJoinCond:
onExpr, err := nodeExpr(treeCondition.Expr)
if err != nil {
return nil, err
}
condition.On = onExpr
case *tree.UsingJoinCond:
condition.Using = make([]vitess.ColIdent, len(treeCondition.Cols))
for i := range treeCondition.Cols {
condition.Using[i] = vitess.NewColIdent(string(treeCondition.Cols[i]))
}
case nil:
// cross join (no join condition)
default:
return nil, fmt.Errorf("unknown JOIN condition: `%T`", treeCondition)
}
var joinType string
switch node.JoinType {
case tree.AstFull:
joinType = vitess.FullOuterJoinStr
case tree.AstLeft:
if condition.On == nil && len(condition.Using) == 0 {
joinType = vitess.NaturalLeftJoinStr
} else {
joinType = vitess.LeftJoinStr
}
case tree.AstRight:
if condition.On == nil && len(condition.Using) == 0 {
joinType = vitess.NaturalRightJoinStr
} else {
joinType = vitess.RightJoinStr
}
case tree.AstCross, tree.AstInner:
joinType = vitess.JoinStr
case "":
if condition.On == nil && len(condition.Using) == 0 {
joinType = vitess.NaturalJoinStr
} else {
joinType = vitess.JoinStr
}
default:
return nil, fmt.Errorf("unknown JOIN type: `%s`", node.JoinType)
}
return &vitess.JoinTableExpr{
LeftExpr: left,
Join: joinType,
RightExpr: right,
Condition: condition,
}, nil
case *tree.ParenTableExpr:
tableExpr, err := nodeTableExpr(node.Expr)
if err != nil {
return nil, err
}
return &vitess.ParenTableExpr{
Exprs: vitess.TableExprs{tableExpr},
}, nil
case *tree.RowsFromExpr:
exprs, err := nodeExprs(node.Items)
if err != nil {
return nil, err
}
//TODO: not sure if this is correct at all. I think we want to return one result per row, but maybe not.
// This needs to be tested to verify.
rows := make([]vitess.ValTuple, len(exprs))
for i := range exprs {
rows[i] = vitess.ValTuple{exprs[i]}
}
return &vitess.ValuesStatement{
Rows: rows,
}, nil
case *tree.StatementSource:
return nil, fmt.Errorf("this statement is not yet supported")
case *tree.Subquery:
return nodeSubqueryToTableExpr(node)
case *tree.TableName:
tableName, err := nodeTableName(node)
if err != nil {
return nil, err
}
return &vitess.AliasedTableExpr{
Expr: tableName,
}, nil
case *tree.TableRef:
return nil, fmt.Errorf("table refs are not yet supported")
case *tree.UnresolvedObjectName:
tableName, err := nodeUnresolvedObjectName(node)
if err != nil {
return nil, err
}
return &vitess.AliasedTableExpr{
Expr: tableName,
}, nil
default:
return nil, fmt.Errorf("unknown table expression: `%T`", node)
}
}
// nodeTableExprs handles tree.TableExprs nodes.
func nodeTableExprs(node tree.TableExprs) (vitess.TableExprs, error) {
if len(node) == 0 {
return nil, nil
}
exprs := make(vitess.TableExprs, len(node))
for i := range node {
var err error
exprs[i], err = nodeTableExpr(node[i])
if err != nil {
return nil, err
}
}
return exprs, nil
}