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