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.oracle.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.OracleStatementParser.AliasContext;
24  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AssignmentValueContext;
25  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AssignmentValuesContext;
26  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CellAssignmentContext;
27  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CollectionExprContext;
28  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ColumnNameContext;
29  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ColumnNamesContext;
30  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ConditionalInsertClauseContext;
31  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ConditionalInsertElsePartContext;
32  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ConditionalInsertWhenPartContext;
33  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ContainersClauseContext;
34  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.CrossOuterApplyClauseContext;
35  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DeleteContext;
36  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DeleteSpecificationContext;
37  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DeleteWhereClauseContext;
38  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DimensionColumnContext;
39  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DmlSubqueryClauseContext;
40  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DmlTableClauseContext;
41  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DuplicateSpecificationContext;
42  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ExecuteContext;
43  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ExprContext;
44  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ExpressionListContext;
45  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ForUpdateClauseContext;
46  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ForUpdateClauseListContext;
47  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ForUpdateClauseOptionContext;
48  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FromClauseListContext;
49  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FromClauseOptionContext;
50  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.GroupByClauseContext;
51  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.GroupByItemContext;
52  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.GroupingExprListContext;
53  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.GroupingSetsClauseContext;
54  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.HavingClauseContext;
55  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InnerCrossJoinClauseContext;
56  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InsertContext;
57  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InsertIntoClauseContext;
58  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InsertMultiTableContext;
59  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InsertSingleTableContext;
60  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.InsertValuesClauseContext;
61  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.IntoClauseContext;
62  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.JoinClauseContext;
63  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.MergeAssignmentContext;
64  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.MergeAssignmentValueContext;
65  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.MergeColumnValueContext;
66  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.MergeContext;
67  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.MergeInsertClauseContext;
68  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.MergeInsertColumnContext;
69  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.MergeSetAssignmentsClauseContext;
70  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.MergeUpdateClauseContext;
71  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ModelClauseContext;
72  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.MultiColumnForLoopContext;
73  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.MultiTableElementContext;
74  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OrderByClauseContext;
75  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.OuterJoinClauseContext;
76  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ParenthesisSelectSubqueryContext;
77  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.PivotClauseContext;
78  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.QueryBlockContext;
79  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.QueryNameContext;
80  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.QueryTableExprClauseContext;
81  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.QueryTableExprContext;
82  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ReferenceModelContext;
83  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.RollupCubeClauseContext;
84  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectContext;
85  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectFromClauseContext;
86  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectIntoStatementContext;
87  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectJoinOptionContext;
88  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectJoinSpecificationContext;
89  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectListContext;
90  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectProjectionContext;
91  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectProjectionExprClauseContext;
92  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectSubqueryContext;
93  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SelectTableReferenceContext;
94  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ShardsClauseContext;
95  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SingleColumnForLoopContext;
96  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SubqueryContext;
97  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SubqueryFactoringClauseContext;
98  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TableCollectionExprContext;
99  import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TableNameContext;
100 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UnpivotClauseContext;
101 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UpdateContext;
102 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UpdateSetClauseContext;
103 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UpdateSetColumnClauseContext;
104 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UpdateSetValueClauseContext;
105 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UpdateSpecificationContext;
106 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UsingClauseContext;
107 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.WhereClauseContext;
108 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.WithClauseContext;
109 import org.apache.shardingsphere.sql.parser.oracle.visitor.statement.OracleStatementVisitor;
110 import org.apache.shardingsphere.sql.parser.statement.core.enums.CombineType;
111 import org.apache.shardingsphere.sql.parser.statement.core.enums.JoinType;
112 import org.apache.shardingsphere.sql.parser.statement.core.enums.OrderDirection;
113 import org.apache.shardingsphere.sql.parser.statement.core.segment.dal.VariableSegment;
114 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.ColumnAssignmentSegment;
115 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.InsertValuesSegment;
116 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.SetAssignmentSegment;
117 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
118 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.InsertColumnsSegment;
119 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.combine.CombineSegment;
120 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.datetime.DatetimeExpression;
121 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BetweenExpression;
122 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression;
123 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.CaseWhenExpression;
124 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.CollateExpression;
125 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
126 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionWithParamsSegment;
127 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.FunctionSegment;
128 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.InExpression;
129 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.complex.CommonExpressionSegment;
130 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.complex.CommonTableExpressionSegment;
131 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.complex.ComplexExpressionSegment;
132 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.LiteralExpressionSegment;
133 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.SimpleExpressionSegment;
134 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubqueryExpressionSegment;
135 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment;
136 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ColumnProjectionSegment;
137 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.DatetimeProjectionSegment;
138 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ExpressionProjectionSegment;
139 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.IntervalExpressionProjection;
140 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionSegment;
141 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionsSegment;
142 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ShorthandProjectionSegment;
143 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.SubqueryProjectionSegment;
144 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.multiset.MultisetExpression;
145 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.GroupBySegment;
146 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.OrderBySegment;
147 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.ColumnOrderByItemSegment;
148 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.ExpressionOrderByItemSegment;
149 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.IndexOrderByItemSegment;
150 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.OrderByItemSegment;
151 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.HavingSegment;
152 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.LockSegment;
153 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment;
154 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.table.MultiTableConditionalIntoElseSegment;
155 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.table.MultiTableConditionalIntoSegment;
156 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.table.MultiTableConditionalIntoThenSegment;
157 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.table.MultiTableConditionalIntoWhenThenSegment;
158 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.table.MultiTableInsertIntoSegment;
159 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.table.MultiTableInsertType;
160 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.xml.XmlElementFunctionSegment;
161 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.xml.XmlPiFunctionSegment;
162 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.xml.XmlQueryAndExistsFunctionSegment;
163 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.xml.XmlSerializeFunctionSegment;
164 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.xml.XmlTableFunctionSegment;
165 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.AliasAvailable;
166 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.AliasSegment;
167 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.ModelSegment;
168 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.OwnerSegment;
169 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.ParameterMarkerSegment;
170 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.PivotSegment;
171 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.WithSegment;
172 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.CollectionTableSegment;
173 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.FunctionTableSegment;
174 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.JoinTableSegment;
175 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
176 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SubqueryTableSegment;
177 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableNameSegment;
178 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableSegment;
179 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.DeleteStatement;
180 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.InsertStatement;
181 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.MergeStatement;
182 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
183 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.UpdateStatement;
184 import org.apache.shardingsphere.sql.parser.statement.core.util.SQLUtils;
185 import org.apache.shardingsphere.sql.parser.statement.core.value.collection.CollectionValue;
186 import org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
187 import org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.BooleanLiteralValue;
188 
189 import java.util.ArrayList;
190 import java.util.Collection;
191 import java.util.Collections;
192 import java.util.HashSet;
193 import java.util.LinkedList;
194 import java.util.List;
195 import java.util.stream.Collectors;
196 
197 /**
198  * DML statement visitor for Oracle.
199  */
200 public final class OracleDMLStatementVisitor extends OracleStatementVisitor implements DMLStatementVisitor {
201     
202     @Override
203     public ASTNode visitUpdate(final UpdateContext ctx) {
204         UpdateStatement result = new UpdateStatement();
205         result.setTable((TableSegment) visit(ctx.updateSpecification()));
206         if (null != ctx.alias()) {
207             result.getTable().setAlias((AliasSegment) visit(ctx.alias()));
208         }
209         result.setSetAssignment((SetAssignmentSegment) visit(ctx.updateSetClause()));
210         if (null != ctx.whereClause()) {
211             result.setWhere((WhereSegment) visit(ctx.whereClause()));
212         }
213         result.addParameterMarkers(ctx.getParent() instanceof ExecuteContext ? getGlobalParameterMarkerSegments() : popAllStatementParameterMarkerSegments());
214         result.getVariableNames().addAll(getVariableNames());
215         return result;
216     }
217     
218     @Override
219     public ASTNode visitUpdateSpecification(final UpdateSpecificationContext ctx) {
220         if (null != ctx.dmlTableExprClause().dmlTableClause()) {
221             return visit(ctx.dmlTableExprClause().dmlTableClause());
222         }
223         if (null != ctx.dmlTableExprClause().dmlSubqueryClause()) {
224             SubquerySegment subquerySegment = (SubquerySegment) visit(ctx.dmlTableExprClause().dmlSubqueryClause());
225             return new SubqueryTableSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), subquerySegment);
226         }
227         SubquerySegment subquerySegment = (SubquerySegment) visit(ctx.dmlTableExprClause().tableCollectionExpr());
228         return new SubqueryTableSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), subquerySegment);
229     }
230     
231     @Override
232     public ASTNode visitUpdateSetClause(final UpdateSetClauseContext ctx) {
233         Collection<ColumnAssignmentSegment> assignments = new LinkedList<>();
234         if (null != ctx.updateSetColumnList()) {
235             for (UpdateSetColumnClauseContext each : ctx.updateSetColumnList().updateSetColumnClause()) {
236                 assignments.add((ColumnAssignmentSegment) visit(each));
237             }
238         } else {
239             assignments.add((ColumnAssignmentSegment) visit(ctx.updateSetValueClause()));
240         }
241         return new SetAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), assignments);
242     }
243     
244     @Override
245     public ASTNode visitUpdateSetColumnClause(final UpdateSetColumnClauseContext ctx) {
246         return 1 == ctx.columnName().size() ? createAssignmentSegmentFromSingleColumnAssignment(ctx) : createAssignmentSegmentFromMultiColumnAssignment(ctx);
247     }
248     
249     private ColumnAssignmentSegment createAssignmentSegmentFromSingleColumnAssignment(final UpdateSetColumnClauseContext ctx) {
250         ColumnSegment column = (ColumnSegment) visitColumnName(ctx.columnName(0));
251         List<ColumnSegment> columnSegments = new LinkedList<>();
252         columnSegments.add(column);
253         if (null != ctx.expr()) {
254             ExpressionSegment value = (ExpressionSegment) visit(ctx.expr());
255             return new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
256         }
257         if (null != ctx.selectSubquery()) {
258             SubquerySegment subquerySegment = new SubquerySegment(ctx.selectSubquery().start.getStartIndex(), ctx.selectSubquery().stop.getStopIndex(),
259                     (SelectStatement) visit(ctx.selectSubquery()), getOriginalText(ctx.selectSubquery()));
260             SubqueryExpressionSegment value = new SubqueryExpressionSegment(subquerySegment);
261             ColumnAssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
262             result.getColumns().add(column);
263             return result;
264         }
265         CommonExpressionSegment value = new CommonExpressionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.DEFAULT().getText());
266         ColumnAssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
267         result.getColumns().add(column);
268         return result;
269     }
270     
271     private ColumnAssignmentSegment createAssignmentSegmentFromMultiColumnAssignment(final UpdateSetColumnClauseContext ctx) {
272         List<ColumnSegment> columnSegments = new LinkedList<>();
273         for (ColumnNameContext each : ctx.columnName()) {
274             columnSegments.add((ColumnSegment) visit(each));
275         }
276         SubquerySegment subquerySegment = new SubquerySegment(ctx.selectSubquery().start.getStartIndex(), ctx.selectSubquery().stop.getStopIndex(),
277                 (SelectStatement) visit(ctx.selectSubquery()), getOriginalText(ctx.selectSubquery()));
278         SubqueryExpressionSegment value = new SubqueryExpressionSegment(subquerySegment);
279         return new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
280     }
281     
282     @Override
283     public ASTNode visitUpdateSetValueClause(final UpdateSetValueClauseContext ctx) {
284         ColumnSegment column = (ColumnSegment) visit(ctx.columnName());
285         List<ColumnSegment> columnSegments = new LinkedList<>();
286         columnSegments.add(column);
287         if (null != ctx.expr()) {
288             ExpressionSegment value = (ExpressionSegment) visit(ctx.expr());
289             ColumnAssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
290             result.getColumns().add(column);
291             return result;
292         } else {
293             SubquerySegment subquerySegment = new SubquerySegment(ctx.selectSubquery().start.getStartIndex(), ctx.selectSubquery().stop.getStopIndex(),
294                     (SelectStatement) visit(ctx.selectSubquery()), getOriginalText(ctx.selectSubquery()));
295             SubqueryExpressionSegment value = new SubqueryExpressionSegment(subquerySegment);
296             ColumnAssignmentSegment result = new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
297             result.getColumns().add(column);
298             return result;
299         }
300     }
301     
302     @Override
303     public ASTNode visitInsert(final InsertContext ctx) {
304         // TODO :FIXME, since there is no segment for insertValuesClause, insertStatement is created by sub rule.
305         InsertStatement result = (InsertStatement) (null == ctx.insertSingleTable() ? visit(ctx.insertMultiTable()) : visit(ctx.insertSingleTable()));
306         result.addParameterMarkers(ctx.getParent() instanceof ExecuteContext ? getGlobalParameterMarkerSegments() : popAllStatementParameterMarkerSegments());
307         return result;
308     }
309     
310     @Override
311     public ASTNode visitInsertSingleTable(final InsertSingleTableContext ctx) {
312         InsertStatement result = (InsertStatement) visit(ctx.insertIntoClause());
313         if (null != ctx.insertValuesClause()) {
314             result.getValues().addAll(createInsertValuesSegments(ctx.insertValuesClause().assignmentValues()));
315         }
316         if (null != ctx.selectSubquery()) {
317             SelectStatement subquery = (SelectStatement) visit(ctx.selectSubquery());
318             SubquerySegment subquerySegment = new SubquerySegment(ctx.selectSubquery().start.getStartIndex(), ctx.selectSubquery().stop.getStopIndex(), subquery,
319                     getOriginalText(ctx.selectSubquery()));
320             result.setInsertSelect(subquerySegment);
321         }
322         result.getVariableNames().addAll(getVariableNames());
323         return result;
324     }
325     
326     private Collection<InsertValuesSegment> createInsertValuesSegments(final AssignmentValuesContext ctx) {
327         Collection<InsertValuesSegment> result = new LinkedList<>();
328         result.add((InsertValuesSegment) visit(ctx));
329         return result;
330     }
331     
332     @Override
333     public ASTNode visitInsertMultiTable(final InsertMultiTableContext ctx) {
334         InsertStatement result = new InsertStatement();
335         result.setMultiTableInsertType(null != ctx.conditionalInsertClause() && null != ctx.conditionalInsertClause().FIRST() ? MultiTableInsertType.FIRST : MultiTableInsertType.ALL);
336         List<MultiTableElementContext> multiTableElementContexts = ctx.multiTableElement();
337         if (null != multiTableElementContexts && !multiTableElementContexts.isEmpty()) {
338             MultiTableInsertIntoSegment multiTableInsertIntoSegment = new MultiTableInsertIntoSegment(
339                     multiTableElementContexts.get(0).getStart().getStartIndex(), multiTableElementContexts.get(multiTableElementContexts.size() - 1).getStop().getStopIndex());
340             multiTableInsertIntoSegment.getInsertStatements().addAll(createInsertIntoSegments(multiTableElementContexts));
341             result.setMultiTableInsertInto(multiTableInsertIntoSegment);
342         } else {
343             result.setMultiTableConditionalInto((MultiTableConditionalIntoSegment) visit(ctx.conditionalInsertClause()));
344         }
345         result.setInsertSelect(new SubquerySegment(ctx.selectSubquery().start.getStartIndex(), ctx.selectSubquery().stop.getStopIndex(), (SelectStatement) visit(ctx.selectSubquery()),
346                 getOriginalText(ctx.selectSubquery())));
347         result.getVariableNames().addAll(getVariableNames());
348         return result;
349     }
350     
351     private Collection<InsertStatement> createInsertIntoSegments(final List<MultiTableElementContext> ctx) {
352         Collection<InsertStatement> result = new LinkedList<>();
353         Collection<ParameterMarkerSegment> addedSegments = new HashSet<>();
354         for (MultiTableElementContext each : ctx) {
355             InsertStatement insertStatement = (InsertStatement) visit(each);
356             addParameterMarkerSegments(addedSegments, insertStatement);
357             result.add(insertStatement);
358         }
359         return result;
360     }
361     
362     private void addParameterMarkerSegments(final Collection<ParameterMarkerSegment> addedSegments, final InsertStatement insertStatement) {
363         for (ParameterMarkerSegment parameterMarkerSegment : popAllStatementParameterMarkerSegments()) {
364             if (addedSegments.add(parameterMarkerSegment)) {
365                 insertStatement.addParameterMarkers(Collections.singletonList(parameterMarkerSegment));
366             }
367         }
368     }
369     
370     @Override
371     public ASTNode visitInsertValuesClause(final InsertValuesClauseContext ctx) {
372         InsertStatement result = new InsertStatement();
373         result.getValues().addAll(createInsertValuesSegments(ctx.assignmentValues()));
374         return result;
375     }
376     
377     @SuppressWarnings("unchecked")
378     @Override
379     public ASTNode visitInsertIntoClause(final InsertIntoClauseContext ctx) {
380         InsertStatement result = new InsertStatement();
381         if (null != ctx.dmlTableExprClause().dmlTableClause()) {
382             result.setTable((SimpleTableSegment) visit(ctx.dmlTableExprClause().dmlTableClause()));
383         } else if (null != ctx.dmlTableExprClause().dmlSubqueryClause()) {
384             result.setInsertSelect((SubquerySegment) visit(ctx.dmlTableExprClause().dmlSubqueryClause()));
385         } else {
386             result.setInsertSelect((SubquerySegment) visit(ctx.dmlTableExprClause().tableCollectionExpr()));
387         }
388         if (null != ctx.columnNames()) {
389             ColumnNamesContext columnNames = ctx.columnNames();
390             CollectionValue<ColumnSegment> columnSegments = (CollectionValue<ColumnSegment>) visit(columnNames);
391             result.setInsertColumns(new InsertColumnsSegment(columnNames.start.getStartIndex(), columnNames.stop.getStopIndex(), columnSegments.getValue()));
392         } else {
393             result.setInsertColumns(new InsertColumnsSegment(ctx.stop.getStopIndex() + 1, ctx.stop.getStopIndex() + 1, Collections.emptyList()));
394         }
395         return result;
396     }
397     
398     @Override
399     public ASTNode visitDelete(final DeleteContext ctx) {
400         DeleteStatement result = new DeleteStatement();
401         result.setTable((TableSegment) visit(ctx.deleteSpecification()));
402         if (null != ctx.alias()) {
403             result.getTable().setAlias((AliasSegment) visit(ctx.alias()));
404         }
405         if (null != ctx.whereClause()) {
406             result.setWhere((WhereSegment) visit(ctx.whereClause()));
407         }
408         result.addParameterMarkers(ctx.getParent() instanceof ExecuteContext ? getGlobalParameterMarkerSegments() : popAllStatementParameterMarkerSegments());
409         result.getVariableNames().addAll(getVariableNames());
410         return result;
411     }
412     
413     @Override
414     public ASTNode visitDeleteSpecification(final DeleteSpecificationContext ctx) {
415         if (null != ctx.dmlTableExprClause().dmlTableClause()) {
416             return visit(ctx.dmlTableExprClause().dmlTableClause());
417         }
418         if (null != ctx.dmlTableExprClause().dmlSubqueryClause()) {
419             SubquerySegment subquerySegment = (SubquerySegment) visit(ctx.dmlTableExprClause().dmlSubqueryClause());
420             return new SubqueryTableSegment(ctx.dmlTableExprClause().dmlSubqueryClause().start.getStartIndex(), ctx.dmlTableExprClause().dmlSubqueryClause().stop.getStopIndex(), subquerySegment);
421         }
422         SubquerySegment subquerySegment = (SubquerySegment) visit(ctx.dmlTableExprClause().tableCollectionExpr());
423         return new SubqueryTableSegment(ctx.dmlTableExprClause().tableCollectionExpr().start.getStartIndex(), ctx.dmlTableExprClause().tableCollectionExpr().stop.getStopIndex(), subquerySegment);
424     }
425     
426     @Override
427     public SelectStatement visitSelectIntoStatement(final SelectIntoStatementContext ctx) {
428         SelectStatement result = new SelectStatement();
429         result.setProjections((ProjectionsSegment) visit(ctx.selectList()));
430         // TODO Visit selectIntoClause, bulkCollectIntoClause
431         result.setFrom((TableSegment) visit(ctx.fromClauseList()));
432         if (null != ctx.whereClause()) {
433             result.setWhere((WhereSegment) visit(ctx.whereClause()));
434         }
435         if (null != ctx.groupByClause()) {
436             result.setGroupBy((GroupBySegment) visit(ctx.groupByClause()));
437         }
438         // TODO Visit hierarchicalQueryClause
439         if (null != ctx.modelClause()) {
440             result.setModel((ModelSegment) visit(ctx.modelClause()));
441         }
442         // TODO Visit windowClause
443         if (null != ctx.orderByClause()) {
444             result.setOrderBy((OrderBySegment) visit(ctx.orderByClause()));
445         }
446         // TODO Visit rowLimitingClause
447         result.addParameterMarkers(ctx.getParent() instanceof ExecuteContext ? getGlobalParameterMarkerSegments() : popAllStatementParameterMarkerSegments());
448         result.getVariableNames().addAll(getVariableNames());
449         return result;
450     }
451     
452     @Override
453     public ASTNode visitMultiTableElement(final MultiTableElementContext ctx) {
454         InsertStatement result = (InsertStatement) visit(ctx.insertIntoClause());
455         if (null != ctx.insertValuesClause()) {
456             result.getValues().addAll(createInsertValuesSegments(ctx.insertValuesClause().assignmentValues()));
457         }
458         result.addParameterMarkers(ctx.getParent() instanceof ExecuteContext ? getGlobalParameterMarkerSegments() : popAllStatementParameterMarkerSegments());
459         return result;
460     }
461     
462     @Override
463     public ASTNode visitSelect(final SelectContext ctx) {
464         SelectStatement result = (SelectStatement) visit(ctx.selectSubquery());
465         result.addParameterMarkers(ctx.getParent() instanceof ExecuteContext ? getGlobalParameterMarkerSegments() : popAllStatementParameterMarkerSegments());
466         result.getVariableNames().addAll(getVariableNames());
467         if (null != ctx.forUpdateClause()) {
468             result.setLock((LockSegment) visit(ctx.forUpdateClause()));
469         }
470         return result;
471     }
472     
473     @Override
474     public ASTNode visitPivotClause(final PivotClauseContext ctx) {
475         Collection<ColumnSegment> pivotInColumns = new LinkedList<>();
476         if (null != ctx.pivotInClause()) {
477             ctx.pivotInClause().pivotInClauseExpr().forEach(each -> {
478                 ExpressionSegment expr = (ExpressionSegment) visit(each.expr());
479                 String columnName = null != each.alias() && null != each.alias().identifier() ? each.alias().identifier().IDENTIFIER_().getText() : expr.getText();
480                 ColumnSegment columnSegment = new ColumnSegment(each.getStart().getStartIndex(), each.getStop().getStopIndex(), new IdentifierValue(columnName));
481                 pivotInColumns.add(columnSegment);
482             });
483         }
484         return new PivotSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((CollectionValue<ColumnSegment>) visit(ctx.pivotForClause().columnNames())).getValue(), pivotInColumns);
485     }
486     
487     @Override
488     public ASTNode visitUnpivotClause(final UnpivotClauseContext ctx) {
489         Collection<ColumnSegment> unpivotInColumns = new LinkedList<>();
490         if (null != ctx.unpivotInClause()) {
491             ctx.unpivotInClause().unpivotInClauseExpr().forEach(each -> unpivotInColumns.addAll(((CollectionValue<ColumnSegment>) visit(ctx.columnNames())).getValue()));
492         }
493         PivotSegment result = new PivotSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((CollectionValue<ColumnSegment>) visit(ctx.pivotForClause().columnNames())).getValue(),
494                 unpivotInColumns, true);
495         result.setUnpivotColumns(((CollectionValue<ColumnSegment>) visit(ctx.columnNames())).getValue());
496         return result;
497     }
498     
499     @Override
500     public ASTNode visitDmlTableClause(final DmlTableClauseContext ctx) {
501         if (null != ctx.AT_() && null != ctx.dbLink()) {
502             SimpleTableSegment result = new SimpleTableSegment(new TableNameSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), new IdentifierValue(ctx.tableName().name().getText())));
503             if (null != ctx.tableName().owner()) {
504                 result.setOwner(
505                         new OwnerSegment(ctx.tableName().owner().start.getStartIndex(), ctx.tableName().owner().stop.getStopIndex(), (IdentifierValue) visit(ctx.tableName().owner().identifier())));
506             }
507             result.setAt(new IdentifierValue(ctx.AT_().getText()));
508             result.setDbLink(new IdentifierValue(ctx.dbLink().identifier(0).getText()));
509             return result;
510         }
511         return visit(ctx.tableName());
512     }
513     
514     @Override
515     public ASTNode visitDmlSubqueryClause(final DmlSubqueryClauseContext ctx) {
516         SelectStatement subquery = (SelectStatement) visit(ctx.selectSubquery());
517         return new SubquerySegment(ctx.selectSubquery().start.getStartIndex(), ctx.selectSubquery().stop.getStopIndex(), subquery, getOriginalText(ctx.selectSubquery()));
518     }
519     
520     @Override
521     public ASTNode visitTableCollectionExpr(final TableCollectionExprContext ctx) {
522         if (null != ctx.collectionExpr().selectSubquery()) {
523             SelectStatement subquery = (SelectStatement) visit(ctx.collectionExpr().selectSubquery());
524             return new SubquerySegment(ctx.collectionExpr().selectSubquery().start.getStartIndex(), ctx.collectionExpr().selectSubquery().stop.getStopIndex(), subquery,
525                     getOriginalText(ctx.collectionExpr().selectSubquery()));
526         }
527         if (null != ctx.collectionExpr().functionCall()) {
528             return visit(ctx.collectionExpr().functionCall());
529         }
530         if (null != ctx.collectionExpr().columnName()) {
531             return visit(ctx.collectionExpr().columnName());
532         }
533         if (null != ctx.collectionExpr().expr()) {
534             return visit(ctx.collectionExpr().expr());
535         }
536         throw new UnsupportedOperationException("Unhandled table collection expr");
537     }
538     
539     @Override
540     public ASTNode visitConditionalInsertClause(final ConditionalInsertClauseContext ctx) {
541         Collection<MultiTableConditionalIntoWhenThenSegment> whenThenSegments = new LinkedList<>();
542         for (ConditionalInsertWhenPartContext each : ctx.conditionalInsertWhenPart()) {
543             whenThenSegments.add((MultiTableConditionalIntoWhenThenSegment) visit(each));
544         }
545         MultiTableConditionalIntoSegment result = new MultiTableConditionalIntoSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex());
546         result.getWhenThenSegments().addAll(whenThenSegments);
547         if (null != ctx.conditionalInsertElsePart()) {
548             result.setElseSegment((MultiTableConditionalIntoElseSegment) visit(ctx.conditionalInsertElsePart()));
549         }
550         return result;
551     }
552     
553     @Override
554     public ASTNode visitConditionalInsertWhenPart(final ConditionalInsertWhenPartContext ctx) {
555         List<MultiTableElementContext> multiTableElementContexts = ctx.multiTableElement();
556         MultiTableConditionalIntoThenSegment thenSegment = new MultiTableConditionalIntoThenSegment(multiTableElementContexts.get(0).start.getStartIndex(),
557                 multiTableElementContexts.get(multiTableElementContexts.size() - 1).stop.getStopIndex(), createInsertIntoSegments(multiTableElementContexts));
558         return new MultiTableConditionalIntoWhenThenSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.expr()), thenSegment);
559     }
560     
561     @Override
562     public ASTNode visitConditionalInsertElsePart(final ConditionalInsertElsePartContext ctx) {
563         return new MultiTableConditionalIntoElseSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), createInsertIntoSegments(ctx.multiTableElement()));
564     }
565     
566     @Override
567     public ASTNode visitAssignmentValues(final AssignmentValuesContext ctx) {
568         List<ExpressionSegment> segments = new LinkedList<>();
569         for (AssignmentValueContext each : ctx.assignmentValue()) {
570             segments.add((ExpressionSegment) visit(each));
571         }
572         return new InsertValuesSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), segments);
573     }
574     
575     @Override
576     public ASTNode visitAssignmentValue(final AssignmentValueContext ctx) {
577         ExprContext expr = ctx.expr();
578         return null == expr ? new CommonExpressionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getText()) : visit(expr);
579     }
580     
581     @Override
582     public ASTNode visitSelectSubquery(final SelectSubqueryContext ctx) {
583         SelectStatement result;
584         if (null != ctx.combineType()) {
585             result = new SelectStatement();
586             SelectStatement left = (SelectStatement) visit(ctx.selectSubquery(0));
587             result.setProjections(left.getProjections());
588             left.getFrom().ifPresent(result::setFrom);
589             left.getWith().ifPresent(result::setWith);
590             createSelectCombineClause(ctx, result, left);
591         } else {
592             result = null != ctx.queryBlock() ? (SelectStatement) visit(ctx.queryBlock()) : (SelectStatement) visit(ctx.parenthesisSelectSubquery());
593         }
594         if (null != ctx.orderByClause()) {
595             result.setOrderBy((OrderBySegment) visit(ctx.orderByClause()));
596         }
597         result.addParameterMarkers(ctx.getParent() instanceof ExecuteContext ? getGlobalParameterMarkerSegments() : popAllStatementParameterMarkerSegments());
598         result.getVariableNames().addAll(getVariableNames());
599         return result;
600     }
601     
602     private void createSelectCombineClause(final SelectSubqueryContext ctx, final SelectStatement result, final SelectStatement left) {
603         CombineType combineType;
604         if (null != ctx.combineType().UNION() && null != ctx.combineType().ALL()) {
605             combineType = CombineType.UNION_ALL;
606         } else if (null != ctx.combineType().UNION()) {
607             combineType = CombineType.UNION;
608         } else if (null != ctx.combineType().INTERSECT()) {
609             combineType = CombineType.INTERSECT;
610         } else {
611             combineType = CombineType.MINUS;
612         }
613         SelectStatement right = (SelectStatement) visit(ctx.selectSubquery(1));
614         result.setCombine(new CombineSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), createSubquerySegment(ctx.selectSubquery(0), left), combineType,
615                 createSubquerySegment(ctx.selectSubquery(1), right)));
616         result.addParameterMarkers(left.getParameterMarkers());
617         result.addParameterMarkers(right.getParameterMarkers());
618     }
619     
620     private SubquerySegment createSubquerySegment(final SelectSubqueryContext ctx, final SelectStatement selectStatement) {
621         return new SubquerySegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), selectStatement, getOriginalText(ctx));
622     }
623     
624     @Override
625     public ASTNode visitQueryBlock(final QueryBlockContext ctx) {
626         SelectStatement result = new SelectStatement();
627         result.setProjections((ProjectionsSegment) visit(ctx.selectList()));
628         if (null != ctx.withClause()) {
629             result.setWith((WithSegment) visit(ctx.withClause()));
630         }
631         if (null != ctx.duplicateSpecification()) {
632             result.getProjections().setDistinctRow(isDistinct(ctx));
633         }
634         if (null != ctx.selectFromClause()) {
635             TableSegment tableSegment = (TableSegment) visit(ctx.selectFromClause());
636             result.setFrom(tableSegment);
637         }
638         if (null != ctx.whereClause()) {
639             result.setWhere((WhereSegment) visit(ctx.whereClause()));
640         }
641         if (null != ctx.groupByClause()) {
642             result.setGroupBy((GroupBySegment) visit(ctx.groupByClause()));
643             if (null != ctx.groupByClause().havingClause()) {
644                 result.setHaving((HavingSegment) visit(ctx.groupByClause().havingClause()));
645             }
646         }
647         if (null != ctx.modelClause()) {
648             result.setModel((ModelSegment) visit(ctx.modelClause()));
649         }
650         return result;
651     }
652     
653     @Override
654     public ASTNode visitHavingClause(final HavingClauseContext ctx) {
655         ExpressionSegment expr = (ExpressionSegment) visit(ctx.expr());
656         return new HavingSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), expr);
657     }
658     
659     @Override
660     public ASTNode visitModelClause(final ModelClauseContext ctx) {
661         ModelSegment result = new ModelSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex());
662         if (null != ctx.referenceModel()) {
663             for (ReferenceModelContext each : ctx.referenceModel()) {
664                 result.getReferenceModelSelects().add((SubquerySegment) visit(each));
665             }
666         }
667         if (null != ctx.mainModel().modelRulesClause().orderByClause()) {
668             for (OrderByClauseContext each : ctx.mainModel().modelRulesClause().orderByClause()) {
669                 result.getOrderBySegments().add((OrderBySegment) visit(each));
670             }
671         }
672         for (CellAssignmentContext each : ctx.mainModel().modelRulesClause().cellAssignment()) {
673             result.getCellAssignmentColumns().add((ColumnSegment) visit(each.measureColumn().columnName()));
674             if (null != each.singleColumnForLoop()) {
675                 result.getCellAssignmentColumns().addAll(extractColumnValuesFromSingleColumnForLoop(each.singleColumnForLoop()));
676                 result.getCellAssignmentSelects().addAll(extractSelectSubqueryValuesFromSingleColumnForLoop(each.singleColumnForLoop()));
677             }
678             if (null != each.multiColumnForLoop()) {
679                 result.getCellAssignmentColumns().addAll(extractColumnValuesFromMultiColumnForLoop(each.multiColumnForLoop()));
680                 result.getCellAssignmentSelects().add(extractSelectSubqueryValueFromMultiColumnForLoop(each.multiColumnForLoop()));
681             }
682         }
683         return result;
684     }
685     
686     private Collection<ColumnSegment> extractColumnValuesFromSingleColumnForLoop(final List<SingleColumnForLoopContext> ctx) {
687         Collection<ColumnSegment> result = new LinkedList<>();
688         for (SingleColumnForLoopContext each : ctx) {
689             result.add((ColumnSegment) visit(each.dimensionColumn().columnName()));
690         }
691         return result;
692     }
693     
694     private Collection<SubquerySegment> extractSelectSubqueryValuesFromSingleColumnForLoop(final List<SingleColumnForLoopContext> ctx) {
695         Collection<SubquerySegment> result = new LinkedList<>();
696         for (SingleColumnForLoopContext each : ctx) {
697             if (null != each.selectSubquery()) {
698                 SelectStatement subquery = (SelectStatement) visit(each.selectSubquery());
699                 SubquerySegment subquerySegment = new SubquerySegment(each.selectSubquery().start.getStartIndex(), each.selectSubquery().stop.getStopIndex(), subquery,
700                         getOriginalText(each.selectSubquery()));
701                 result.add(subquerySegment);
702             }
703         }
704         return result;
705     }
706     
707     private Collection<ColumnSegment> extractColumnValuesFromMultiColumnForLoop(final MultiColumnForLoopContext ctx) {
708         Collection<ColumnSegment> result = new LinkedList<>();
709         for (DimensionColumnContext each : ctx.dimensionColumn()) {
710             result.add((ColumnSegment) visit(each.columnName()));
711         }
712         return result;
713     }
714     
715     private SubquerySegment extractSelectSubqueryValueFromMultiColumnForLoop(final MultiColumnForLoopContext ctx) {
716         SelectStatement subquery = (SelectStatement) visit(ctx.selectSubquery());
717         return new SubquerySegment(ctx.selectSubquery().start.getStartIndex(), ctx.selectSubquery().stop.getStopIndex(), subquery, getOriginalText(ctx.selectSubquery()));
718     }
719     
720     @Override
721     public ASTNode visitReferenceModel(final ReferenceModelContext ctx) {
722         SelectStatement subquery = (SelectStatement) visit(ctx.selectSubquery());
723         return new SubquerySegment(ctx.selectSubquery().start.getStartIndex(), ctx.selectSubquery().stop.getStopIndex(), subquery, getOriginalText(ctx.selectSubquery()));
724     }
725     
726     @Override
727     public ASTNode visitParenthesisSelectSubquery(final ParenthesisSelectSubqueryContext ctx) {
728         return visit(ctx.selectSubquery());
729     }
730     
731     @Override
732     public ASTNode visitWithClause(final WithClauseContext ctx) {
733         Collection<CommonTableExpressionSegment> commonTableExpressions = new LinkedList<>();
734         if (null != ctx.subqueryFactoringClause()) {
735             for (SubqueryFactoringClauseContext each : ctx.subqueryFactoringClause()) {
736                 SubquerySegment subquery = new SubquerySegment(each.selectSubquery().start.getStartIndex(), each.selectSubquery().stop.getStopIndex(), (SelectStatement) visit(each),
737                         getOriginalText(each));
738                 CommonTableExpressionSegment commonTableExpression = new CommonTableExpressionSegment(each.start.getStartIndex(), each.stop.getStopIndex(),
739                         (AliasSegment) visit(each.queryName().alias()), subquery);
740                 if (null != each.searchClause()) {
741                     ColumnNameContext columnName = each.searchClause().orderingColumn().columnName();
742                     commonTableExpression.getColumns().add((ColumnSegment) visit(columnName));
743                 }
744                 commonTableExpressions.add(commonTableExpression);
745             }
746         }
747         return new WithSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), commonTableExpressions);
748     }
749     
750     @Override
751     public ASTNode visitSubqueryFactoringClause(final SubqueryFactoringClauseContext ctx) {
752         return visit(ctx.selectSubquery());
753     }
754     
755     private boolean isDistinct(final QueryBlockContext ctx) {
756         return ((BooleanLiteralValue) visit(ctx.duplicateSpecification())).getValue();
757     }
758     
759     @Override
760     public ASTNode visitDuplicateSpecification(final DuplicateSpecificationContext ctx) {
761         if (null != ctx.DISTINCT() || null != ctx.UNIQUE()) {
762             return new BooleanLiteralValue(true);
763         }
764         return new BooleanLiteralValue(false);
765     }
766     
767     @Override
768     public ASTNode visitSelectList(final SelectListContext ctx) {
769         ProjectionsSegment result = new ProjectionsSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex());
770         Collection<ProjectionSegment> projections = new LinkedList<>();
771         if (null != ctx.unqualifiedShorthand()) {
772             projections.add(new ShorthandProjectionSegment(ctx.unqualifiedShorthand().getStart().getStartIndex(), ctx.unqualifiedShorthand().getStop().getStopIndex()));
773             result.getProjections().addAll(projections);
774             return result;
775         }
776         for (SelectProjectionContext each : ctx.selectProjection()) {
777             projections.add((ProjectionSegment) visit(each));
778         }
779         result.getProjections().addAll(projections);
780         return result;
781     }
782     
783     @Override
784     public ASTNode visitSelectProjection(final SelectProjectionContext ctx) {
785         // FIXME :The stop index of project is the stop index of projection, instead of alias.
786         if (null != ctx.queryName()) {
787             QueryNameContext queryName = ctx.queryName();
788             ShorthandProjectionSegment result = new ShorthandProjectionSegment(queryName.getStart().getStartIndex(), ctx.DOT_ASTERISK_().getSymbol().getStopIndex());
789             IdentifierValue identifier = new IdentifierValue(queryName.getText());
790             result.setOwner(new OwnerSegment(queryName.getStart().getStartIndex(), queryName.getStop().getStopIndex(), identifier));
791             return result;
792         }
793         if (null != ctx.tableName()) {
794             TableNameContext tableName = ctx.tableName();
795             ShorthandProjectionSegment result = new ShorthandProjectionSegment(tableName.getStart().getStartIndex(), ctx.DOT_ASTERISK_().getSymbol().getStopIndex());
796             IdentifierValue identifier = new IdentifierValue(tableName.getText());
797             result.setOwner(new OwnerSegment(tableName.getStart().getStartIndex(), tableName.getStop().getStopIndex(), identifier));
798             return result;
799         }
800         if (null != ctx.alias()) {
801             AliasContext aliasContext = ctx.alias();
802             ShorthandProjectionSegment result = new ShorthandProjectionSegment(aliasContext.getStart().getStartIndex(), ctx.DOT_ASTERISK_().getSymbol().getStopIndex());
803             IdentifierValue identifier = new IdentifierValue(aliasContext.getText());
804             result.setOwner(new OwnerSegment(aliasContext.getStart().getStartIndex(), aliasContext.getStop().getStopIndex(), identifier));
805             return result;
806         }
807         return createProjection(ctx.selectProjectionExprClause());
808     }
809     
810     @Override
811     public ASTNode visitAlias(final AliasContext ctx) {
812         if (null != ctx.identifier()) {
813             return new AliasSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (IdentifierValue) visit(ctx.identifier()));
814         }
815         return new AliasSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), new IdentifierValue(ctx.STRING_().getText()));
816     }
817     
818     private ASTNode createProjection(final SelectProjectionExprClauseContext ctx) {
819         AliasSegment alias = null == ctx.alias() ? null : (AliasSegment) visit(ctx.alias());
820         ASTNode projection = visit(ctx.expr());
821         if (projection instanceof AliasAvailable) {
822             ((AliasAvailable) projection).setAlias(alias);
823             return projection;
824         }
825         if (projection instanceof ComplexExpressionSegment) {
826             return createProjectionForComplexExpressionSegment(projection, alias);
827         }
828         if (projection instanceof SimpleExpressionSegment) {
829             return createProjectionForSimpleExpressionSegment(projection, alias, ctx);
830         }
831         if (projection instanceof ExpressionSegment) {
832             return createProjectionForExpressionSegment(projection, alias);
833         }
834         throw new UnsupportedOperationException("Unhandled case");
835     }
836     
837     private ASTNode createProjectionForComplexExpressionSegment(final ASTNode projection, final AliasSegment alias) {
838         if (projection instanceof FunctionSegment) {
839             FunctionSegment segment = (FunctionSegment) projection;
840             ExpressionProjectionSegment result = new ExpressionProjectionSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getText(), segment);
841             result.setAlias(alias);
842             return result;
843         }
844         if (projection instanceof CommonExpressionSegment) {
845             CommonExpressionSegment segment = (CommonExpressionSegment) projection;
846             ExpressionProjectionSegment result = new ExpressionProjectionSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getText(), segment);
847             result.setAlias(alias);
848             return result;
849         }
850         if (projection instanceof XmlQueryAndExistsFunctionSegment || projection instanceof XmlPiFunctionSegment || projection instanceof XmlSerializeFunctionSegment
851                 || projection instanceof XmlElementFunctionSegment) {
852             return projection;
853         }
854         throw new UnsupportedOperationException("Unsupported Complex Expression");
855     }
856     
857     private ASTNode createProjectionForSimpleExpressionSegment(final ASTNode projection, final AliasSegment alias, final SelectProjectionExprClauseContext ctx) {
858         if (projection instanceof SubqueryExpressionSegment) {
859             SubqueryExpressionSegment subqueryExpressionSegment = (SubqueryExpressionSegment) projection;
860             String text = ctx.start.getInputStream().getText(new Interval(subqueryExpressionSegment.getStartIndex(), subqueryExpressionSegment.getStopIndex()));
861             SubqueryProjectionSegment result = new SubqueryProjectionSegment(((SubqueryExpressionSegment) projection).getSubquery(), text);
862             result.setAlias(alias);
863             return result;
864         }
865         if (projection instanceof LiteralExpressionSegment) {
866             LiteralExpressionSegment column = (LiteralExpressionSegment) projection;
867             ExpressionProjectionSegment result = null == alias
868                     ? new ExpressionProjectionSegment(column.getStartIndex(), column.getStopIndex(), String.valueOf(column.getLiterals()), column)
869                     : new ExpressionProjectionSegment(column.getStartIndex(), ctx.alias().stop.getStopIndex(), String.valueOf(column.getLiterals()), column);
870             result.setAlias(alias);
871             return result;
872         }
873         throw new UnsupportedOperationException("Unsupported Simple Expression");
874     }
875     
876     private ASTNode createProjectionForExpressionSegment(final ASTNode projection, final AliasSegment alias) {
877         // FIXME :For DISTINCT()
878         if (projection instanceof ColumnSegment) {
879             return createColumnProjectionSegment((ColumnSegment) projection, alias);
880         }
881         if (projection instanceof BinaryOperationExpression) {
882             return createExpressionProjectionSegment((BinaryOperationExpression) projection, alias);
883         }
884         if (projection instanceof MultisetExpression) {
885             return createExpressionProjectionSegment((MultisetExpression) projection, alias);
886         }
887         if (projection instanceof DatetimeExpression) {
888             return createDatetimeProjectionSegment((DatetimeExpression) projection);
889         }
890         if (projection instanceof IntervalExpressionProjection) {
891             return createIntervalExpressionProjection((IntervalExpressionProjection) projection);
892         }
893         if (projection instanceof CaseWhenExpression || projection instanceof VariableSegment
894                 || projection instanceof BetweenExpression || projection instanceof InExpression || projection instanceof CollateExpression) {
895             return createExpressionProjectionSegment((ExpressionSegment) projection, alias);
896         }
897         throw new UnsupportedOperationException("Unsupported Expression");
898     }
899     
900     private ColumnProjectionSegment createColumnProjectionSegment(final ColumnSegment projection, final AliasSegment alias) {
901         ColumnProjectionSegment result = new ColumnProjectionSegment(projection);
902         result.setAlias(alias);
903         return result;
904     }
905     
906     private ExpressionProjectionSegment createExpressionProjectionSegment(final BinaryOperationExpression projection, final AliasSegment alias) {
907         int startIndex = projection.getStartIndex();
908         int stopIndex = null == alias ? projection.getStopIndex() : alias.getStopIndex();
909         ExpressionProjectionSegment result = new ExpressionProjectionSegment(startIndex, stopIndex, projection.getText(), projection);
910         result.setAlias(alias);
911         return result;
912     }
913     
914     private ExpressionProjectionSegment createExpressionProjectionSegment(final MultisetExpression projection, final AliasSegment alias) {
915         int startIndex = projection.getStartIndex();
916         int stopIndex = null == alias ? projection.getStopIndex() : alias.getStopIndex();
917         ExpressionProjectionSegment result = new ExpressionProjectionSegment(startIndex, stopIndex, projection.getText(), projection);
918         result.setAlias(alias);
919         return result;
920     }
921     
922     private ExpressionProjectionSegment createExpressionProjectionSegment(final ExpressionSegment projection, final AliasSegment alias) {
923         ExpressionProjectionSegment result = new ExpressionProjectionSegment(projection.getStartIndex(), projection.getStopIndex(), projection.getText(), projection);
924         result.setAlias(alias);
925         return result;
926     }
927     
928     private DatetimeProjectionSegment createDatetimeProjectionSegment(final DatetimeExpression projection) {
929         return null == projection.getRight()
930                 ? new DatetimeProjectionSegment(projection.getStartIndex(), projection.getStopIndex(), projection.getLeft(), projection.getText())
931                 : new DatetimeProjectionSegment(projection.getStartIndex(), projection.getStopIndex(), projection.getLeft(), projection.getRight(), projection.getText());
932     }
933     
934     private IntervalExpressionProjection createIntervalExpressionProjection(final IntervalExpressionProjection projection) {
935         IntervalExpressionProjection result = new IntervalExpressionProjection(
936                 projection.getStartIndex(), projection.getStopIndex(), projection.getLeft(), projection.getMinus(), projection.getRight(), projection.getText());
937         if (null != projection.getDayToSecondExpression()) {
938             result.setDayToSecondExpression(projection.getDayToSecondExpression());
939         } else {
940             result.setYearToMonthExpression(projection.getYearToMonthExpression());
941         }
942         return result;
943     }
944     
945     @Override
946     public ASTNode visitSelectFromClause(final SelectFromClauseContext ctx) {
947         return visit(ctx.fromClauseList());
948     }
949     
950     @Override
951     public ASTNode visitFromClauseList(final FromClauseListContext ctx) {
952         TableSegment result = (TableSegment) visit(ctx.fromClauseOption(0));
953         if (ctx.fromClauseOption().size() > 1) {
954             for (int i = 1; i < ctx.fromClauseOption().size(); i++) {
955                 result = generateJoinTableSourceFromFromClauseOption(ctx.fromClauseOption(i), result);
956             }
957         }
958         return result;
959     }
960     
961     private JoinTableSegment generateJoinTableSourceFromFromClauseOption(final FromClauseOptionContext ctx, final TableSegment tableSegment) {
962         JoinTableSegment result = new JoinTableSegment();
963         result.setStartIndex(tableSegment.getStartIndex());
964         result.setStopIndex(ctx.stop.getStopIndex());
965         result.setLeft(tableSegment);
966         result.setJoinType(JoinType.COMMA.name());
967         result.setRight((TableSegment) visit(ctx));
968         return result;
969     }
970     
971     @Override
972     public ASTNode visitFromClauseOption(final FromClauseOptionContext ctx) {
973         if (null != ctx.joinClause()) {
974             return visit(ctx.joinClause());
975         }
976         if (null != ctx.regularFunction()) {
977             FunctionSegment functionSegment = (FunctionSegment) visit(ctx.regularFunction());
978             FunctionTableSegment result = new FunctionTableSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), functionSegment);
979             if (null != ctx.alias()) {
980                 result.setAlias((AliasSegment) visit(ctx.alias()));
981             }
982             return result;
983         }
984         if (null != ctx.xmlTableFunction()) {
985             XmlTableFunctionSegment functionSegment = (XmlTableFunctionSegment) visit(ctx.xmlTableFunction());
986             FunctionTableSegment result = new FunctionTableSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), functionSegment);
987             if (null != ctx.alias()) {
988                 result.setAlias((AliasSegment) visit(ctx.alias()));
989             }
990             return result;
991         }
992         return visit(ctx.selectTableReference());
993     }
994     
995     @Override
996     public ASTNode visitJoinClause(final JoinClauseContext ctx) {
997         TableSegment result;
998         TableSegment left;
999         left = (TableSegment) visit(ctx.selectTableReference());
1000         for (SelectJoinOptionContext each : ctx.selectJoinOption()) {
1001             left = visitJoinedTable(each, left);
1002         }
1003         result = left;
1004         return result;
1005     }
1006     
1007     private JoinTableSegment visitJoinedTable(final SelectJoinOptionContext ctx, final TableSegment tableSegment) {
1008         JoinTableSegment result = new JoinTableSegment();
1009         result.setLeft(tableSegment);
1010         result.setStartIndex(tableSegment.getStartIndex());
1011         result.setStopIndex(ctx.stop.getStopIndex());
1012         result.setJoinType(getJoinType(ctx));
1013         result.setNatural(isNatural(ctx));
1014         if (null != ctx.innerCrossJoinClause()) {
1015             TableSegment right = (TableSegment) visit(ctx.innerCrossJoinClause().selectTableReference());
1016             result.setRight(right);
1017             if (null != ctx.innerCrossJoinClause().selectJoinSpecification()) {
1018                 visitSelectJoinSpecification(ctx.innerCrossJoinClause().selectJoinSpecification(), result);
1019             }
1020         } else if (null != ctx.outerJoinClause()) {
1021             TableSegment right = (TableSegment) visit(ctx.outerJoinClause().selectTableReference());
1022             result.setRight(right);
1023             if (null != ctx.outerJoinClause().selectJoinSpecification()) {
1024                 visitSelectJoinSpecification(ctx.outerJoinClause().selectJoinSpecification(), result);
1025             }
1026         } else {
1027             TableSegment right = (TableSegment) visit(ctx.crossOuterApplyClause());
1028             result.setRight(right);
1029         }
1030         return result;
1031     }
1032     
1033     private boolean isNatural(final SelectJoinOptionContext ctx) {
1034         if (null != ctx.innerCrossJoinClause()) {
1035             return null != ctx.innerCrossJoinClause().NATURAL();
1036         }
1037         if (null != ctx.outerJoinClause()) {
1038             return null != ctx.outerJoinClause().NATURAL();
1039         }
1040         return false;
1041     }
1042     
1043     private String getJoinType(final SelectJoinOptionContext ctx) {
1044         if (null != ctx.innerCrossJoinClause()) {
1045             return getInnerCrossJoinType(ctx.innerCrossJoinClause());
1046         }
1047         if (null != ctx.outerJoinClause()) {
1048             return getOuterJoinType(ctx.outerJoinClause());
1049         }
1050         if (null != ctx.crossOuterApplyClause()) {
1051             return getCrossOuterApplyType(ctx.crossOuterApplyClause());
1052         }
1053         return JoinType.COMMA.name();
1054     }
1055     
1056     private String getCrossOuterApplyType(final CrossOuterApplyClauseContext ctx) {
1057         if (null != ctx.CROSS()) {
1058             return JoinType.CROSS.name();
1059         }
1060         return JoinType.LEFT.name();
1061     }
1062     
1063     private String getOuterJoinType(final OuterJoinClauseContext ctx) {
1064         if (null != ctx.outerJoinType().FULL()) {
1065             return JoinType.FULL.name();
1066         } else if (null != ctx.outerJoinType().LEFT()) {
1067             return JoinType.LEFT.name();
1068         }
1069         return JoinType.RIGHT.name();
1070     }
1071     
1072     private String getInnerCrossJoinType(final InnerCrossJoinClauseContext ctx) {
1073         return null == ctx.CROSS() ? JoinType.INNER.name() : JoinType.CROSS.name();
1074     }
1075     
1076     private void visitSelectJoinSpecification(final SelectJoinSpecificationContext ctx, final JoinTableSegment joinTableSource) {
1077         if (null != ctx.expr()) {
1078             ExpressionSegment condition = (ExpressionSegment) visit(ctx.expr());
1079             joinTableSource.setCondition(condition);
1080         }
1081         if (null != ctx.USING()) {
1082             joinTableSource.setUsing(ctx.columnNames().columnName().stream().map(each -> (ColumnSegment) visit(each)).collect(Collectors.toList()));
1083         }
1084     }
1085     
1086     @Override
1087     public ASTNode visitCrossOuterApplyClause(final CrossOuterApplyClauseContext ctx) {
1088         TableSegment result;
1089         if (null != ctx.selectTableReference()) {
1090             result = (TableSegment) visit(ctx.selectTableReference());
1091         } else {
1092             SubquerySegment subquerySegment = (SubquerySegment) visit(ctx.collectionExpr());
1093             result = new SubqueryTableSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), subquerySegment);
1094         }
1095         return result;
1096     }
1097     
1098     @Override
1099     public ASTNode visitCollectionExpr(final CollectionExprContext ctx) {
1100         SelectStatement subquery = (SelectStatement) visit(ctx.selectSubquery());
1101         return new SubquerySegment(ctx.selectSubquery().start.getStartIndex(), ctx.selectSubquery().stop.getStopIndex(), subquery, getOriginalText(ctx.selectSubquery()));
1102     }
1103     
1104     @Override
1105     public ASTNode visitSelectTableReference(final SelectTableReferenceContext ctx) {
1106         TableSegment result;
1107         if (null != ctx.containersClause()) {
1108             result = (TableSegment) visit(ctx.containersClause());
1109         } else if (null != ctx.shardsClause()) {
1110             result = (TableSegment) visit(ctx.shardsClause());
1111         } else if (null != ctx.joinClause()) {
1112             result = (TableSegment) visit(ctx.joinClause());
1113         } else {
1114             result = (TableSegment) visit(ctx.queryTableExprClause());
1115         }
1116         if (null != ctx.alias()) {
1117             result.setAlias((AliasSegment) visit(ctx.alias()));
1118         }
1119         return result;
1120     }
1121     
1122     @Override
1123     public ASTNode visitContainersClause(final ContainersClauseContext ctx) {
1124         return visit(ctx.tableName());
1125     }
1126     
1127     @Override
1128     public ASTNode visitShardsClause(final ShardsClauseContext ctx) {
1129         return visit(ctx.tableName());
1130     }
1131     
1132     @Override
1133     public ASTNode visitQueryTableExprClause(final QueryTableExprClauseContext ctx) {
1134         ASTNode result = visit(ctx.queryTableExpr());
1135         if (null != ctx.pivotClause()) {
1136             PivotSegment pivotClause = (PivotSegment) visit(ctx.pivotClause());
1137             if (result instanceof SubqueryTableSegment) {
1138                 ((SubqueryTableSegment) result).setPivot(pivotClause);
1139             }
1140             if (result instanceof SimpleTableSegment) {
1141                 ((SimpleTableSegment) result).setPivot(pivotClause);
1142             }
1143         }
1144         if (null != ctx.unpivotClause()) {
1145             PivotSegment pivotClause = (PivotSegment) visit(ctx.unpivotClause());
1146             if (result instanceof SubqueryTableSegment) {
1147                 ((SubqueryTableSegment) result).setPivot(pivotClause);
1148             }
1149             if (result instanceof SimpleTableSegment) {
1150                 ((SimpleTableSegment) result).setPivot(pivotClause);
1151             }
1152         }
1153         return result;
1154     }
1155     
1156     @Override
1157     public ASTNode visitQueryTableExpr(final QueryTableExprContext ctx) {
1158         TableSegment result;
1159         if (null != ctx.queryTableExprSampleClause()) {
1160             result = (SimpleTableSegment) visit(ctx.queryTableExprSampleClause().queryTableExprTableClause().tableName());
1161         } else if (null != ctx.lateralClause()) {
1162             SelectStatement subquery = (SelectStatement) visit(ctx.lateralClause().selectSubquery());
1163             SubquerySegment subquerySegment = new SubquerySegment(ctx.lateralClause().selectSubquery().start.getStartIndex(), ctx.lateralClause().selectSubquery().stop.getStopIndex(), subquery,
1164                     getOriginalText(ctx.lateralClause().selectSubquery()));
1165             result = new SubqueryTableSegment(ctx.lateralClause().LP_().getSymbol().getStartIndex(), ctx.lateralClause().RP_().getSymbol().getStopIndex(), subquerySegment);
1166         } else {
1167             if (null != ctx.tableCollectionExpr().collectionExpr().selectSubquery()) {
1168                 SubquerySegment subquerySegment = (SubquerySegment) visit(ctx.tableCollectionExpr());
1169                 result = new SubqueryTableSegment(ctx.tableCollectionExpr().start.getStartIndex(), ctx.tableCollectionExpr().stop.getStopIndex(), subquerySegment);
1170             } else {
1171                 result = new CollectionTableSegment((ExpressionSegment) visit(ctx.tableCollectionExpr()));
1172             }
1173         }
1174         return result;
1175     }
1176     
1177     @Override
1178     public ASTNode visitWhereClause(final WhereClauseContext ctx) {
1179         ASTNode segment = visit(ctx.expr());
1180         return new WhereSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (ExpressionSegment) segment);
1181     }
1182     
1183     @Override
1184     public ASTNode visitGroupByClause(final GroupByClauseContext ctx) {
1185         Collection<OrderByItemSegment> items = new LinkedList<>();
1186         for (GroupByItemContext each : ctx.groupByItem()) {
1187             items.addAll(generateOrderByItemsFromGroupByItem(each));
1188         }
1189         return new GroupBySegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), items);
1190     }
1191     
1192     private Collection<OrderByItemSegment> generateOrderByItemsFromGroupByItem(final GroupByItemContext ctx) {
1193         Collection<OrderByItemSegment> result = new LinkedList<>();
1194         if (null != ctx.expr()) {
1195             OrderByItemSegment item = (OrderByItemSegment) extractValueFromGroupByItemExpression(ctx.expr());
1196             result.add(item);
1197         } else if (null != ctx.rollupCubeClause()) {
1198             result.addAll(generateOrderByItemSegmentsFromRollupCubeClause(ctx.rollupCubeClause()));
1199         } else {
1200             result.addAll(generateOrderByItemSegmentsFromGroupingSetsClause(ctx.groupingSetsClause()));
1201         }
1202         return result;
1203     }
1204     
1205     private ASTNode extractValueFromGroupByItemExpression(final ExprContext ctx) {
1206         ASTNode expression = visit(ctx);
1207         if (expression instanceof ColumnSegment) {
1208             ColumnSegment column = (ColumnSegment) expression;
1209             return new ColumnOrderByItemSegment(column, OrderDirection.ASC, null);
1210         }
1211         if (expression instanceof LiteralExpressionSegment) {
1212             LiteralExpressionSegment literalExpression = (LiteralExpressionSegment) expression;
1213             return new IndexOrderByItemSegment(literalExpression.getStartIndex(), literalExpression.getStopIndex(),
1214                     SQLUtils.getExactlyNumber(literalExpression.getLiterals().toString(), 10).intValue(), OrderDirection.ASC, null);
1215         }
1216         return new ExpressionOrderByItemSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), getOriginalText(ctx), OrderDirection.ASC, null, (ExpressionSegment) expression);
1217     }
1218     
1219     private Collection<OrderByItemSegment> generateOrderByItemSegmentsFromRollupCubeClause(final RollupCubeClauseContext ctx) {
1220         return new LinkedList<>(generateOrderByItemSegmentsFromGroupingExprList(ctx.groupingExprList()));
1221     }
1222     
1223     private Collection<OrderByItemSegment> generateOrderByItemSegmentsFromGroupingSetsClause(final GroupingSetsClauseContext ctx) {
1224         Collection<OrderByItemSegment> result = new LinkedList<>();
1225         if (null != ctx.rollupCubeClause()) {
1226             for (RollupCubeClauseContext each : ctx.rollupCubeClause()) {
1227                 result.addAll(generateOrderByItemSegmentsFromRollupCubeClause(each));
1228             }
1229         }
1230         if (null != ctx.groupingExprList()) {
1231             for (GroupingExprListContext each : ctx.groupingExprList()) {
1232                 result.addAll(generateOrderByItemSegmentsFromGroupingExprList(each));
1233             }
1234         }
1235         return result;
1236     }
1237     
1238     private Collection<OrderByItemSegment> generateOrderByItemSegmentsFromGroupingExprList(final GroupingExprListContext ctx) {
1239         Collection<OrderByItemSegment> result = new LinkedList<>();
1240         for (ExpressionListContext each : ctx.expressionList()) {
1241             result.addAll(generateOrderByItemSegmentsFromExpressionList(each));
1242         }
1243         return result;
1244     }
1245     
1246     private Collection<OrderByItemSegment> generateOrderByItemSegmentsFromExpressionList(final ExpressionListContext ctx) {
1247         Collection<OrderByItemSegment> result = new LinkedList<>();
1248         if (null != ctx.expr()) {
1249             for (ExprContext each : ctx.expr()) {
1250                 result.add((OrderByItemSegment) extractValueFromGroupByItemExpression(each));
1251             }
1252         }
1253         if (null != ctx.exprs()) {
1254             for (ExprContext each : ctx.exprs().expr()) {
1255                 result.add((OrderByItemSegment) extractValueFromGroupByItemExpression(each));
1256             }
1257         }
1258         return result;
1259     }
1260     
1261     @Override
1262     public ASTNode visitSubquery(final SubqueryContext ctx) {
1263         return visit(ctx.selectSubquery());
1264     }
1265     
1266     @Override
1267     public ASTNode visitForUpdateClause(final ForUpdateClauseContext ctx) {
1268         LockSegment result = new LockSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex());
1269         if (null != ctx.forUpdateClauseList()) {
1270             result.getTables().addAll(generateTablesFromforUpdateClauseOption(ctx.forUpdateClauseList()));
1271             result.getColumns().addAll(generateColumnsFromforUpdateClauseOption(ctx.forUpdateClauseList()));
1272         }
1273         return result;
1274     }
1275     
1276     private List<SimpleTableSegment> generateTablesFromforUpdateClauseOption(final ForUpdateClauseListContext ctx) {
1277         List<SimpleTableSegment> result = new LinkedList<>();
1278         for (ForUpdateClauseOptionContext each : ctx.forUpdateClauseOption()) {
1279             if (null != each.tableName()) {
1280                 result.add((SimpleTableSegment) visit(each.tableName()));
1281             }
1282         }
1283         return result;
1284     }
1285     
1286     private List<ColumnSegment> generateColumnsFromforUpdateClauseOption(final ForUpdateClauseListContext ctx) {
1287         List<ColumnSegment> result = new LinkedList<>();
1288         for (ForUpdateClauseOptionContext each : ctx.forUpdateClauseOption()) {
1289             if (null != each.columnName()) {
1290                 result.add((ColumnSegment) visit(each.columnName()));
1291             }
1292         }
1293         return result;
1294     }
1295     
1296     @Override
1297     public ASTNode visitMerge(final MergeContext ctx) {
1298         MergeStatement result = new MergeStatement();
1299         result.setTarget((TableSegment) visit(ctx.intoClause()));
1300         result.setSource((TableSegment) visit(ctx.usingClause()));
1301         ExpressionWithParamsSegment onExpression = new ExpressionWithParamsSegment(ctx.usingClause().expr().start.getStartIndex(), ctx.usingClause().expr().stop.getStopIndex(),
1302                 (ExpressionSegment) visit(ctx.usingClause().expr()));
1303         onExpression.getParameterMarkerSegments().addAll(popAllStatementParameterMarkerSegments());
1304         result.setExpression(onExpression);
1305         if (null != ctx.mergeUpdateClause() && null != ctx.mergeInsertClause() && ctx.mergeUpdateClause().start.getStartIndex() > ctx.mergeInsertClause().start.getStartIndex()) {
1306             result.setInsert((InsertStatement) visitMergeInsertClause(ctx.mergeInsertClause()));
1307             result.setUpdate((UpdateStatement) visitMergeUpdateClause(ctx.mergeUpdateClause()));
1308             result.addParameterMarkers(ctx.getParent() instanceof ExecuteContext ? getGlobalParameterMarkerSegments() : popAllStatementParameterMarkerSegments());
1309             return result;
1310         }
1311         if (null != ctx.mergeUpdateClause()) {
1312             result.setUpdate((UpdateStatement) visitMergeUpdateClause(ctx.mergeUpdateClause()));
1313         }
1314         if (null != ctx.mergeInsertClause()) {
1315             result.setInsert((InsertStatement) visitMergeInsertClause(ctx.mergeInsertClause()));
1316         }
1317         result.addParameterMarkers(ctx.getParent() instanceof ExecuteContext ? getGlobalParameterMarkerSegments() : popAllStatementParameterMarkerSegments());
1318         return result;
1319     }
1320     
1321     @SuppressWarnings("unchecked")
1322     @Override
1323     public ASTNode visitMergeInsertClause(final MergeInsertClauseContext ctx) {
1324         InsertStatement result = new InsertStatement();
1325         if (null != ctx.mergeInsertColumn()) {
1326             result.setInsertColumns((InsertColumnsSegment) visit(ctx.mergeInsertColumn()));
1327         }
1328         if (null != ctx.mergeColumnValue()) {
1329             result.getValues().addAll(((CollectionValue<InsertValuesSegment>) visit(ctx.mergeColumnValue())).getValue());
1330         }
1331         if (null != ctx.whereClause()) {
1332             result.setWhere((WhereSegment) visit(ctx.whereClause()));
1333         }
1334         result.addParameterMarkers(popAllStatementParameterMarkerSegments());
1335         return result;
1336     }
1337     
1338     @Override
1339     public ASTNode visitMergeInsertColumn(final MergeInsertColumnContext ctx) {
1340         Collection<ColumnSegment> columnSegments = new ArrayList<>(ctx.columnName().size());
1341         for (ColumnNameContext each : ctx.columnName()) {
1342             if (null != each.name()) {
1343                 columnSegments.add((ColumnSegment) visit(each));
1344             }
1345         }
1346         return new InsertColumnsSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), columnSegments);
1347     }
1348     
1349     @Override
1350     public ASTNode visitMergeColumnValue(final MergeColumnValueContext ctx) {
1351         CollectionValue<InsertValuesSegment> result = new CollectionValue<>();
1352         List<ExpressionSegment> segments = new LinkedList<>();
1353         for (ExprContext each : ctx.expr()) {
1354             segments.add(null == each ? new CommonExpressionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getText()) : (ExpressionSegment) visit(each));
1355         }
1356         result.getValue().add(new InsertValuesSegment(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex(), segments));
1357         return result;
1358     }
1359     
1360     @Override
1361     public ASTNode visitIntoClause(final IntoClauseContext ctx) {
1362         if (null != ctx.tableName()) {
1363             SimpleTableSegment result = (SimpleTableSegment) visit(ctx.tableName());
1364             if (null != ctx.alias()) {
1365                 result.setAlias((AliasSegment) visit(ctx.alias()));
1366             }
1367             return result;
1368         }
1369         if (null != ctx.viewName()) {
1370             SimpleTableSegment result = (SimpleTableSegment) visit(ctx.viewName());
1371             if (null != ctx.alias()) {
1372                 result.setAlias((AliasSegment) visit(ctx.alias()));
1373             }
1374             return result;
1375         }
1376         SelectStatement subquery = (SelectStatement) visit(ctx.subquery());
1377         SubquerySegment subquerySegment = new SubquerySegment(ctx.subquery().start.getStartIndex(), ctx.subquery().stop.getStopIndex(), subquery, getOriginalText(ctx.subquery()));
1378         SubqueryTableSegment result = new SubqueryTableSegment(ctx.subquery().start.getStartIndex(), ctx.subquery().stop.getStopIndex(), subquerySegment);
1379         if (null != ctx.alias()) {
1380             result.setAlias((AliasSegment) visit(ctx.alias()));
1381         }
1382         return result;
1383     }
1384     
1385     @Override
1386     public ASTNode visitUsingClause(final UsingClauseContext ctx) {
1387         if (null != ctx.tableName()) {
1388             SimpleTableSegment result = (SimpleTableSegment) visit(ctx.tableName());
1389             if (null != ctx.alias()) {
1390                 result.setAlias((AliasSegment) visit(ctx.alias()));
1391             }
1392             return result;
1393         }
1394         if (null != ctx.viewName()) {
1395             SimpleTableSegment result = (SimpleTableSegment) visit(ctx.viewName());
1396             if (null != ctx.alias()) {
1397                 result.setAlias((AliasSegment) visit(ctx.alias()));
1398             }
1399             return result;
1400         }
1401         SelectStatement subquery = (SelectStatement) visit(ctx.subquery());
1402         SubquerySegment subquerySegment = new SubquerySegment(ctx.subquery().start.getStartIndex(), ctx.subquery().stop.getStopIndex(), subquery, getOriginalText(ctx.subquery()));
1403         subquerySegment.getSelect().addParameterMarkers(popAllStatementParameterMarkerSegments());
1404         SubqueryTableSegment result = new SubqueryTableSegment(ctx.subquery().start.getStartIndex(), ctx.subquery().stop.getStopIndex(), subquerySegment);
1405         if (null != ctx.alias()) {
1406             result.setAlias((AliasSegment) visit(ctx.alias()));
1407         }
1408         return result;
1409     }
1410     
1411     @Override
1412     public ASTNode visitMergeUpdateClause(final MergeUpdateClauseContext ctx) {
1413         UpdateStatement result = new UpdateStatement();
1414         result.setSetAssignment((SetAssignmentSegment) visit(ctx.mergeSetAssignmentsClause()));
1415         if (null != ctx.whereClause()) {
1416             result.setWhere((WhereSegment) visit(ctx.whereClause()));
1417         }
1418         if (null != ctx.deleteWhereClause()) {
1419             result.setDeleteWhere((WhereSegment) visit(ctx.deleteWhereClause()));
1420         }
1421         result.addParameterMarkers(popAllStatementParameterMarkerSegments());
1422         return result;
1423     }
1424     
1425     @Override
1426     public ASTNode visitMergeSetAssignmentsClause(final MergeSetAssignmentsClauseContext ctx) {
1427         Collection<ColumnAssignmentSegment> assignments = new LinkedList<>();
1428         for (MergeAssignmentContext each : ctx.mergeAssignment()) {
1429             assignments.add((ColumnAssignmentSegment) visit(each));
1430         }
1431         return new SetAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), assignments);
1432     }
1433     
1434     @Override
1435     public ASTNode visitMergeAssignment(final MergeAssignmentContext ctx) {
1436         ColumnSegment column = (ColumnSegment) visitColumnName(ctx.columnName());
1437         ExpressionSegment value = (ExpressionSegment) visit(ctx.mergeAssignmentValue());
1438         List<ColumnSegment> columnSegments = new LinkedList<>();
1439         columnSegments.add(column);
1440         return new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
1441     }
1442     
1443     @Override
1444     public ASTNode visitMergeAssignmentValue(final MergeAssignmentValueContext ctx) {
1445         ExprContext expr = ctx.expr();
1446         return null == expr ? new CommonExpressionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getText()) : visit(expr);
1447     }
1448     
1449     @Override
1450     public ASTNode visitDeleteWhereClause(final DeleteWhereClauseContext ctx) {
1451         ASTNode segment = visit(ctx.whereClause().expr());
1452         return new WhereSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (ExpressionSegment) segment);
1453     }
1454 }