View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shardingsphere.sql.parser.sql92.visitor.statement.type;
19  
20  import org.antlr.v4.runtime.misc.Interval;
21  import org.apache.shardingsphere.sql.parser.api.ASTNode;
22  import org.apache.shardingsphere.sql.parser.api.visitor.statement.type.DMLStatementVisitor;
23  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.AliasContext;
24  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.AssignmentContext;
25  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.AssignmentValueContext;
26  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.AssignmentValuesContext;
27  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.ColumnNamesContext;
28  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.CombineClauseContext;
29  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.DeleteContext;
30  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.DuplicateSpecificationContext;
31  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.EscapedTableReferenceContext;
32  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.ExprContext;
33  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.FromClauseContext;
34  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.GroupByClauseContext;
35  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.HavingClauseContext;
36  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.InsertContext;
37  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.InsertValuesClauseContext;
38  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.JoinSpecificationContext;
39  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.JoinedTableContext;
40  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.OrderByItemContext;
41  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.ProjectionContext;
42  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.ProjectionsContext;
43  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.QualifiedShorthandContext;
44  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.SelectClauseContext;
45  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.SelectContext;
46  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.SelectSpecificationContext;
47  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.SetAssignmentsClauseContext;
48  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.SingleTableClauseContext;
49  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.SubqueryContext;
50  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.TableFactorContext;
51  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.TableReferenceContext;
52  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.TableReferencesContext;
53  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.UpdateContext;
54  import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.WhereClauseContext;
55  import org.apache.shardingsphere.sql.parser.sql.common.enums.JoinType;
56  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
57  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
58  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
59  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
60  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.InsertColumnsSegment;
61  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
62  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
63  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
64  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
65  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
66  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
67  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
68  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
69  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationProjectionSegment;
70  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
71  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
72  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
73  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
74  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ShorthandProjectionSegment;
75  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
76  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.GroupBySegment;
77  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.OrderBySegment;
78  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
79  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.HavingSegment;
80  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
81  import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
82  import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
83  import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
84  import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
85  import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
86  import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
87  import org.apache.shardingsphere.sql.parser.sql.common.value.collection.CollectionValue;
88  import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
89  import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.BooleanLiteralValue;
90  import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sql92.dml.SQL92DeleteStatement;
91  import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sql92.dml.SQL92InsertStatement;
92  import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sql92.dml.SQL92SelectStatement;
93  import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sql92.dml.SQL92UpdateStatement;
94  import org.apache.shardingsphere.sql.parser.sql92.visitor.statement.SQL92StatementVisitor;
95  
96  import java.util.Collection;
97  import java.util.Collections;
98  import java.util.LinkedList;
99  import java.util.List;
100 import java.util.stream.Collectors;
101 
102 /**
103  * DML statement visitor for SQL92.
104  */
105 public final class SQL92DMLStatementVisitor extends SQL92StatementVisitor implements DMLStatementVisitor {
106     
107     @Override
108     public ASTNode visitInsert(final InsertContext ctx) {
109         SQL92InsertStatement result = (SQL92InsertStatement) visit(ctx.insertValuesClause());
110         result.setTable((SimpleTableSegment) visit(ctx.tableName()));
111         result.addParameterMarkerSegments(getParameterMarkerSegments());
112         return result;
113     }
114     
115     @SuppressWarnings("unchecked")
116     @Override
117     public ASTNode visitInsertValuesClause(final InsertValuesClauseContext ctx) {
118         SQL92InsertStatement result = new SQL92InsertStatement();
119         if (null != ctx.columnNames()) {
120             ColumnNamesContext columnNames = ctx.columnNames();
121             CollectionValue<ColumnSegment> columnSegments = (CollectionValue<ColumnSegment>) visit(columnNames);
122             result.setInsertColumns(new InsertColumnsSegment(columnNames.start.getStartIndex(), columnNames.stop.getStopIndex(), columnSegments.getValue()));
123         } else {
124             result.setInsertColumns(new InsertColumnsSegment(ctx.start.getStartIndex() - 1, ctx.start.getStartIndex() - 1, Collections.emptyList()));
125         }
126         result.getValues().addAll(createInsertValuesSegments(ctx.assignmentValues()));
127         return result;
128     }
129     
130     private Collection<InsertValuesSegment> createInsertValuesSegments(final Collection<AssignmentValuesContext> assignmentValuesContexts) {
131         Collection<InsertValuesSegment> result = new LinkedList<>();
132         for (AssignmentValuesContext each : assignmentValuesContexts) {
133             result.add((InsertValuesSegment) visit(each));
134         }
135         return result;
136     }
137     
138     @Override
139     public ASTNode visitUpdate(final UpdateContext ctx) {
140         SQL92UpdateStatement result = new SQL92UpdateStatement();
141         result.setTable((TableSegment) visit(ctx.tableReferences()));
142         result.setSetAssignment((SetAssignmentSegment) visit(ctx.setAssignmentsClause()));
143         if (null != ctx.whereClause()) {
144             result.setWhere((WhereSegment) visit(ctx.whereClause()));
145         }
146         result.addParameterMarkerSegments(getParameterMarkerSegments());
147         return result;
148     }
149     
150     @Override
151     public ASTNode visitSetAssignmentsClause(final SetAssignmentsClauseContext ctx) {
152         Collection<ColumnAssignmentSegment> assignments = new LinkedList<>();
153         for (AssignmentContext each : ctx.assignment()) {
154             assignments.add((ColumnAssignmentSegment) visit(each));
155         }
156         return new SetAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), assignments);
157     }
158     
159     @Override
160     public ASTNode visitAssignmentValues(final AssignmentValuesContext ctx) {
161         List<ExpressionSegment> segments = new LinkedList<>();
162         for (AssignmentValueContext each : ctx.assignmentValue()) {
163             segments.add((ExpressionSegment) visit(each));
164         }
165         return new InsertValuesSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), segments);
166     }
167     
168     @Override
169     public ASTNode visitAssignment(final AssignmentContext ctx) {
170         ColumnSegment column = (ColumnSegment) visitColumnName(ctx.columnName());
171         List<ColumnSegment> columnSegments = new LinkedList<>();
172         columnSegments.add(column);
173         ExpressionSegment value = (ExpressionSegment) visit(ctx.assignmentValue());
174         ColumnAssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
175         result.getColumns().add(column);
176         return result;
177     }
178     
179     @Override
180     public ASTNode visitAssignmentValue(final AssignmentValueContext ctx) {
181         ExprContext expr = ctx.expr();
182         if (null != expr) {
183             return visit(expr);
184         }
185         return new CommonExpressionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getText());
186     }
187     
188     @Override
189     public ASTNode visitDelete(final DeleteContext ctx) {
190         SQL92DeleteStatement result = new SQL92DeleteStatement();
191         result.setTable((TableSegment) visit(ctx.singleTableClause()));
192         if (null != ctx.whereClause()) {
193             result.setWhere((WhereSegment) visit(ctx.whereClause()));
194         }
195         result.addParameterMarkerSegments(getParameterMarkerSegments());
196         return result;
197     }
198     
199     @Override
200     public ASTNode visitSingleTableClause(final SingleTableClauseContext ctx) {
201         SimpleTableSegment result = (SimpleTableSegment) visit(ctx.tableName());
202         if (null != ctx.alias()) {
203             result.setAlias((AliasSegment) visit(ctx.alias()));
204         }
205         return result;
206     }
207     
208     @Override
209     public ASTNode visitSelect(final SelectContext ctx) {
210         // TODO :Unsupported for withClause.
211         SQL92SelectStatement result = (SQL92SelectStatement) visit(ctx.combineClause());
212         result.addParameterMarkerSegments(getParameterMarkerSegments());
213         return result;
214     }
215     
216     @Override
217     public ASTNode visitCombineClause(final CombineClauseContext ctx) {
218         // TODO :Unsupported for union SQL.
219         return visit(ctx.selectClause(0));
220     }
221     
222     @Override
223     public ASTNode visitSelectClause(final SelectClauseContext ctx) {
224         SQL92SelectStatement result = new SQL92SelectStatement();
225         result.setProjections((ProjectionsSegment) visit(ctx.projections()));
226         if (!ctx.selectSpecification().isEmpty()) {
227             result.getProjections().setDistinctRow(isDistinct(ctx.selectSpecification().get(0)));
228         }
229         if (null != ctx.fromClause()) {
230             TableSegment tableSegment = (TableSegment) visit(ctx.fromClause());
231             result.setFrom(tableSegment);
232         }
233         if (null != ctx.whereClause()) {
234             result.setWhere((WhereSegment) visit(ctx.whereClause()));
235         }
236         if (null != ctx.groupByClause()) {
237             result.setGroupBy((GroupBySegment) visit(ctx.groupByClause()));
238         }
239         if (null != ctx.orderByClause()) {
240             result.setOrderBy((OrderBySegment) visit(ctx.orderByClause()));
241         }
242         if (null != ctx.havingClause()) {
243             result.setHaving((HavingSegment) visit(ctx.havingClause()));
244         }
245         return result;
246     }
247     
248     @Override
249     public ASTNode visitHavingClause(final HavingClauseContext ctx) {
250         ExpressionSegment expr = (ExpressionSegment) visit(ctx.expr());
251         return new HavingSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), expr);
252     }
253     
254     private boolean isDistinct(final SelectSpecificationContext ctx) {
255         return ((BooleanLiteralValue) visit(ctx.duplicateSpecification())).getValue();
256     }
257     
258     @Override
259     public ASTNode visitDuplicateSpecification(final DuplicateSpecificationContext ctx) {
260         return new BooleanLiteralValue(null != ctx.DISTINCT());
261     }
262     
263     @Override
264     public ASTNode visitProjections(final ProjectionsContext ctx) {
265         Collection<ProjectionSegment> projections = new LinkedList<>();
266         if (null != ctx.unqualifiedShorthand()) {
267             projections.add(new ShorthandProjectionSegment(ctx.unqualifiedShorthand().getStart().getStartIndex(), ctx.unqualifiedShorthand().getStop().getStopIndex()));
268         }
269         for (ProjectionContext each : ctx.projection()) {
270             projections.add((ProjectionSegment) visit(each));
271         }
272         ProjectionsSegment result = new ProjectionsSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex());
273         result.getProjections().addAll(projections);
274         return result;
275     }
276     
277     @Override
278     public ASTNode visitProjection(final ProjectionContext ctx) {
279         // FIXME :The stop index of project is the stop index of projection, instead of alias.
280         if (null != ctx.qualifiedShorthand()) {
281             QualifiedShorthandContext shorthand = ctx.qualifiedShorthand();
282             ShorthandProjectionSegment result = new ShorthandProjectionSegment(shorthand.getStart().getStartIndex(), shorthand.getStop().getStopIndex());
283             IdentifierValue identifier = new IdentifierValue(shorthand.identifier().getText());
284             result.setOwner(new OwnerSegment(shorthand.identifier().getStart().getStartIndex(), shorthand.identifier().getStop().getStopIndex(), identifier));
285             return result;
286         }
287         AliasSegment alias = null == ctx.alias() ? null : (AliasSegment) visit(ctx.alias());
288         if (null != ctx.columnName()) {
289             ColumnSegment column = (ColumnSegment) visit(ctx.columnName());
290             ColumnProjectionSegment result = new ColumnProjectionSegment(column);
291             result.setAlias(alias);
292             return result;
293         }
294         return createProjection(ctx, alias);
295     }
296     
297     @Override
298     public ASTNode visitAlias(final AliasContext ctx) {
299         return null == ctx.identifier()
300                 ? new AliasSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), new IdentifierValue(ctx.STRING_().getText()))
301                 : new AliasSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (IdentifierValue) visit(ctx.identifier()));
302     }
303     
304     private ASTNode createProjection(final ProjectionContext ctx, final AliasSegment alias) {
305         ASTNode projection = visit(ctx.expr());
306         if (projection instanceof AggregationProjectionSegment) {
307             ((AggregationProjectionSegment) projection).setAlias(alias);
308             return projection;
309         }
310         if (projection instanceof ExpressionProjectionSegment) {
311             ((ExpressionProjectionSegment) projection).setAlias(alias);
312             return projection;
313         }
314         if (projection instanceof FunctionSegment) {
315             FunctionSegment segment = (FunctionSegment) projection;
316             ExpressionProjectionSegment result = new ExpressionProjectionSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getText(), segment);
317             result.setAlias(alias);
318             return result;
319         }
320         if (projection instanceof CommonExpressionSegment) {
321             CommonExpressionSegment segment = (CommonExpressionSegment) projection;
322             ExpressionProjectionSegment result = new ExpressionProjectionSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getText(), segment);
323             result.setAlias(alias);
324             return result;
325         }
326         // FIXME :For DISTINCT()
327         if (projection instanceof ColumnSegment) {
328             ExpressionProjectionSegment result = new ExpressionProjectionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), getOriginalText(ctx), (ColumnSegment) projection);
329             result.setAlias(alias);
330             return result;
331         }
332         if (projection instanceof SubqueryExpressionSegment) {
333             SubqueryExpressionSegment subqueryExpressionSegment = (SubqueryExpressionSegment) projection;
334             String text = ctx.start.getInputStream().getText(new Interval(subqueryExpressionSegment.getStartIndex(), subqueryExpressionSegment.getStopIndex()));
335             SubqueryProjectionSegment result = new SubqueryProjectionSegment(((SubqueryExpressionSegment) projection).getSubquery(), text);
336             result.setAlias(alias);
337             return result;
338         }
339         if (projection instanceof BinaryOperationExpression) {
340             BinaryOperationExpression binaryExpression = (BinaryOperationExpression) projection;
341             int startIndex = binaryExpression.getStartIndex();
342             int stopIndex = null == alias ? binaryExpression.getStopIndex() : alias.getStopIndex();
343             ExpressionProjectionSegment result = new ExpressionProjectionSegment(startIndex, stopIndex, binaryExpression.getText(), binaryExpression);
344             result.setAlias(alias);
345             return result;
346         }
347         if (projection instanceof ParameterMarkerExpressionSegment) {
348             ParameterMarkerExpressionSegment result = (ParameterMarkerExpressionSegment) projection;
349             result.setAlias(alias);
350             return projection;
351         }
352         LiteralExpressionSegment column = (LiteralExpressionSegment) projection;
353         ExpressionProjectionSegment result = null == alias ? new ExpressionProjectionSegment(column.getStartIndex(), column.getStopIndex(), String.valueOf(column.getLiterals()), column)
354                 : new ExpressionProjectionSegment(column.getStartIndex(), ctx.alias().stop.getStopIndex(), String.valueOf(column.getLiterals()), column);
355         result.setAlias(alias);
356         return result;
357     }
358     
359     @Override
360     public ASTNode visitFromClause(final FromClauseContext ctx) {
361         return visit(ctx.tableReferences());
362     }
363     
364     @Override
365     public ASTNode visitTableReferences(final TableReferencesContext ctx) {
366         TableSegment result = (TableSegment) visit(ctx.escapedTableReference(0));
367         if (ctx.escapedTableReference().size() > 1) {
368             for (int i = 1; i < ctx.escapedTableReference().size(); i++) {
369                 result = generateJoinTableSourceFromEscapedTableReference(ctx.escapedTableReference(i), result);
370             }
371         }
372         return result;
373     }
374     
375     private JoinTableSegment generateJoinTableSourceFromEscapedTableReference(final EscapedTableReferenceContext ctx, final TableSegment tableSegment) {
376         JoinTableSegment result = new JoinTableSegment();
377         result.setStartIndex(tableSegment.getStartIndex());
378         result.setStopIndex(ctx.stop.getStopIndex());
379         result.setLeft(tableSegment);
380         result.setRight((TableSegment) visit(ctx));
381         result.setJoinType(JoinType.COMMA.name());
382         return result;
383     }
384     
385     @Override
386     public ASTNode visitEscapedTableReference(final EscapedTableReferenceContext ctx) {
387         return visit(ctx.tableReference());
388     }
389     
390     @Override
391     public ASTNode visitTableReference(final TableReferenceContext ctx) {
392         TableSegment result;
393         TableSegment left;
394         left = (TableSegment) visit(ctx.tableFactor());
395         if (!ctx.joinedTable().isEmpty()) {
396             for (JoinedTableContext each : ctx.joinedTable()) {
397                 left = visitJoinedTable(each, left);
398             }
399         }
400         result = left;
401         return result;
402     }
403     
404     @Override
405     public ASTNode visitTableFactor(final TableFactorContext ctx) {
406         if (null != ctx.subquery()) {
407             SQL92SelectStatement subquery = (SQL92SelectStatement) visit(ctx.subquery());
408             SubquerySegment subquerySegment = new SubquerySegment(ctx.subquery().start.getStartIndex(), ctx.subquery().stop.getStopIndex(), subquery, getOriginalText(ctx.subquery()));
409             SubqueryTableSegment result = new SubqueryTableSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), subquerySegment);
410             if (null != ctx.alias()) {
411                 result.setAlias((AliasSegment) visit(ctx.alias()));
412             }
413             return result;
414         }
415         if (null != ctx.tableName()) {
416             SimpleTableSegment result = (SimpleTableSegment) visit(ctx.tableName());
417             if (null != ctx.alias()) {
418                 result.setAlias((AliasSegment) visit(ctx.alias()));
419             }
420             return result;
421         }
422         return visit(ctx.tableReferences());
423     }
424     
425     private JoinTableSegment visitJoinedTable(final JoinedTableContext ctx, final TableSegment tableSegment) {
426         JoinTableSegment result = new JoinTableSegment();
427         result.setLeft(tableSegment);
428         result.setStartIndex(tableSegment.getStartIndex());
429         result.setStopIndex(ctx.stop.getStopIndex());
430         TableSegment right = (TableSegment) visit(ctx.tableFactor());
431         result.setRight(right);
432         result.setJoinType(getJoinType(ctx));
433         if (null != ctx.joinSpecification()) {
434             visitJoinSpecification(ctx.joinSpecification(), result);
435         }
436         return result;
437     }
438     
439     private String getJoinType(final JoinedTableContext ctx) {
440         if (null != ctx.LEFT()) {
441             return JoinType.LEFT.name();
442         } else if (null != ctx.RIGHT()) {
443             return JoinType.RIGHT.name();
444         } else if (null != ctx.INNER()) {
445             return JoinType.INNER.name();
446         } else if (null != ctx.CROSS()) {
447             return JoinType.CROSS.name();
448         }
449         return JoinType.INNER.name();
450     }
451     
452     private void visitJoinSpecification(final JoinSpecificationContext ctx, final JoinTableSegment joinTableSource) {
453         if (null != ctx.expr()) {
454             ExpressionSegment condition = (ExpressionSegment) visit(ctx.expr());
455             joinTableSource.setCondition(condition);
456         }
457         if (null != ctx.USING()) {
458             joinTableSource.setUsing(ctx.columnNames().columnName().stream().map(each -> (ColumnSegment) visit(each)).collect(Collectors.toList()));
459         }
460     }
461     
462     @Override
463     public ASTNode visitWhereClause(final WhereClauseContext ctx) {
464         ExpressionSegment segment = (ExpressionSegment) visit(ctx.expr());
465         return new WhereSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), segment);
466     }
467     
468     @Override
469     public ASTNode visitGroupByClause(final GroupByClauseContext ctx) {
470         Collection<OrderByItemSegment> items = new LinkedList<>();
471         for (OrderByItemContext each : ctx.orderByItem()) {
472             items.add((OrderByItemSegment) visit(each));
473         }
474         return new GroupBySegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), items);
475     }
476     
477     @Override
478     public ASTNode visitSubquery(final SubqueryContext ctx) {
479         return visit(ctx.combineClause());
480     }
481 }