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.postgresql.visitor.statement;
19  
20  import lombok.AccessLevel;
21  import lombok.Getter;
22  import org.antlr.v4.runtime.ParserRuleContext;
23  import org.antlr.v4.runtime.misc.Interval;
24  import org.antlr.v4.runtime.tree.ParseTree;
25  import org.antlr.v4.runtime.tree.TerminalNode;
26  import org.apache.shardingsphere.infra.database.core.metadata.database.enums.NullsOrderType;
27  import org.apache.shardingsphere.sql.parser.api.ASTNode;
28  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.AExprContext;
29  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.AexprConstContext;
30  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.AliasClauseContext;
31  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.AnyNameContext;
32  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.AscDescContext;
33  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.AttrNameContext;
34  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.AttrsContext;
35  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.BExprContext;
36  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.CExprContext;
37  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.CaseExprContext;
38  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ColIdContext;
39  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ColumnNameContext;
40  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ColumnNamesContext;
41  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ColumnrefContext;
42  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ConstraintNameContext;
43  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.DataTypeContext;
44  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.DataTypeLengthContext;
45  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.DataTypeNameContext;
46  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.DeleteContext;
47  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ExecuteStmtContext;
48  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ExprListContext;
49  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ExtractArgContext;
50  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ForLockingClauseContext;
51  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.FromClauseContext;
52  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.FromListContext;
53  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.FuncApplicationContext;
54  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.FuncExprContext;
55  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.FunctionExprCommonSubexprContext;
56  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.GroupByItemContext;
57  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.GroupClauseContext;
58  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.HavingClauseContext;
59  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.IdentifierContext;
60  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.InExprContext;
61  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.IndexNameContext;
62  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.IndirectionContext;
63  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.InsertColumnItemContext;
64  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.InsertColumnListContext;
65  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.InsertContext;
66  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.InsertRestContext;
67  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.InsertTargetContext;
68  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.IntoClauseContext;
69  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.JoinQualContext;
70  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.JoinedTableContext;
71  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.LimitClauseContext;
72  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.NameContext;
73  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.NameListContext;
74  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.NaturalJoinTypeContext;
75  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.NullsOrderContext;
76  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.NumberLiteralsContext;
77  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.OptOnConflictContext;
78  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.OuterJoinTypeContext;
79  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.OwnerContext;
80  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ParameterMarkerContext;
81  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.QualifiedNameContext;
82  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.QualifiedNameListContext;
83  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.RelationExprOptAliasContext;
84  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SchemaNameContext;
85  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SelectClauseNContext;
86  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SelectContext;
87  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SelectFetchValueContext;
88  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SelectLimitContext;
89  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SelectLimitValueContext;
90  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SelectNoParensContext;
91  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SelectOffsetValueContext;
92  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SelectWithParensContext;
93  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SetClauseContext;
94  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SetClauseListContext;
95  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SetTargetContext;
96  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SignedIconstContext;
97  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SimpleSelectContext;
98  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SortClauseContext;
99  import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.SortbyContext;
100 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.TableNameContext;
101 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.TableNamesContext;
102 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.TableReferenceContext;
103 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.TargetElContext;
104 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.TargetListContext;
105 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.UnreservedWordContext;
106 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.UpdateContext;
107 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.ValuesClauseContext;
108 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.WhenClauseContext;
109 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.WhereClauseContext;
110 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.WhereOrCurrentClauseContext;
111 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.WindowClauseContext;
112 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.WindowDefinitionContext;
113 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParser.WindowDefinitionListContext;
114 import org.apache.shardingsphere.sql.parser.autogen.PostgreSQLStatementParserBaseVisitor;
115 import org.apache.shardingsphere.sql.parser.sql.common.enums.AggregationType;
116 import org.apache.shardingsphere.sql.parser.sql.common.enums.CombineType;
117 import org.apache.shardingsphere.sql.parser.sql.common.enums.JoinType;
118 import org.apache.shardingsphere.sql.parser.sql.common.enums.OrderDirection;
119 import org.apache.shardingsphere.sql.parser.sql.common.enums.ParameterMarkerType;
120 import org.apache.shardingsphere.sql.parser.sql.common.enums.SubqueryType;
121 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.constraint.ConstraintSegment;
122 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexNameSegment;
123 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexSegment;
124 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.ReturningSegment;
125 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
126 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
127 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
128 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
129 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.InsertColumnsSegment;
130 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.OnDuplicateKeyColumnsSegment;
131 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.combine.CombineSegment;
132 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenExpression;
133 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
134 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CaseWhenExpression;
135 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression;
136 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
137 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExtractArgExpression;
138 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
139 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
140 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
141 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.TypeCastExpression;
142 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
143 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
144 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
145 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
146 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
147 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationDistinctProjectionSegment;
148 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationProjectionSegment;
149 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
150 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
151 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
152 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
153 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ShorthandProjectionSegment;
154 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
155 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.GroupBySegment;
156 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.OrderBySegment;
157 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
158 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ExpressionOrderByItemSegment;
159 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.IndexOrderByItemSegment;
160 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
161 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
162 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitValueSegment;
163 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.NumberLiteralLimitValueSegment;
164 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.ParameterMarkerLimitValueSegment;
165 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.HavingSegment;
166 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.LockSegment;
167 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
168 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasAvailable;
169 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
170 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.DataTypeLengthSegment;
171 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.DataTypeSegment;
172 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.NameSegment;
173 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
174 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ParameterMarkerSegment;
175 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.WindowItemSegment;
176 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.WindowSegment;
177 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
178 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
179 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
180 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment;
181 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
182 import org.apache.shardingsphere.sql.parser.sql.common.util.SQLUtils;
183 import org.apache.shardingsphere.sql.parser.sql.common.value.collection.CollectionValue;
184 import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
185 import org.apache.shardingsphere.sql.parser.sql.common.value.keyword.KeywordValue;
186 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.LiteralValue;
187 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.BooleanLiteralValue;
188 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.NullLiteralValue;
189 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.NumberLiteralValue;
190 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.OtherLiteralValue;
191 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.StringLiteralValue;
192 import org.apache.shardingsphere.sql.parser.sql.common.value.parametermarker.ParameterMarkerValue;
193 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.ddl.PostgreSQLExecuteStatement;
194 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.dml.PostgreSQLDeleteStatement;
195 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.dml.PostgreSQLInsertStatement;
196 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.dml.PostgreSQLSelectStatement;
197 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.dml.PostgreSQLUpdateStatement;
198 
199 import java.util.ArrayList;
200 import java.util.Collection;
201 import java.util.Collections;
202 import java.util.LinkedList;
203 import java.util.List;
204 import java.util.Optional;
205 
206 /**
207  * Statement visitor for PostgreSQL.
208  */
209 @Getter(AccessLevel.PROTECTED)
210 public abstract class PostgreSQLStatementVisitor extends PostgreSQLStatementParserBaseVisitor<ASTNode> {
211     
212     private final Collection<ParameterMarkerSegment> parameterMarkerSegments = new LinkedList<>();
213     
214     @Override
215     public final ASTNode visitParameterMarker(final ParameterMarkerContext ctx) {
216         if (null == ctx.DOLLAR_()) {
217             return new ParameterMarkerValue(parameterMarkerSegments.size(), ParameterMarkerType.QUESTION);
218         }
219         return new ParameterMarkerValue(new NumberLiteralValue(ctx.NUMBER_().getText()).getValue().intValue() - 1, ParameterMarkerType.DOLLAR);
220     }
221     
222     @Override
223     public final ASTNode visitNumberLiterals(final NumberLiteralsContext ctx) {
224         return new NumberLiteralValue(ctx.NUMBER_().getText());
225     }
226     
227     @Override
228     public final ASTNode visitIdentifier(final IdentifierContext ctx) {
229         UnreservedWordContext unreservedWord = ctx.unreservedWord();
230         return null == unreservedWord ? new IdentifierValue(ctx.getText()) : visit(unreservedWord);
231     }
232     
233     @Override
234     public final ASTNode visitUnreservedWord(final UnreservedWordContext ctx) {
235         return new IdentifierValue(ctx.getText());
236     }
237     
238     @Override
239     public final ASTNode visitSchemaName(final SchemaNameContext ctx) {
240         return visit(ctx.identifier());
241     }
242     
243     @Override
244     public final ASTNode visitTableName(final TableNameContext ctx) {
245         SimpleTableSegment result = new SimpleTableSegment(new TableNameSegment(ctx.name().getStart().getStartIndex(), ctx.name().getStop().getStopIndex(), (IdentifierValue) visit(ctx.name())));
246         OwnerContext owner = ctx.owner();
247         if (null != owner) {
248             result.setOwner(new OwnerSegment(owner.getStart().getStartIndex(), owner.getStop().getStopIndex(), (IdentifierValue) visit(owner.identifier())));
249         }
250         return result;
251     }
252     
253     @Override
254     public final ASTNode visitColumnName(final ColumnNameContext ctx) {
255         ColumnSegment result = new ColumnSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (IdentifierValue) visit(ctx.name()));
256         OwnerContext owner = ctx.owner();
257         if (null != owner) {
258             result.setOwner(new OwnerSegment(owner.getStart().getStartIndex(), owner.getStop().getStopIndex(), (IdentifierValue) visit(owner.identifier())));
259         }
260         return result;
261     }
262     
263     @Override
264     public final ASTNode visitIndexName(final IndexNameContext ctx) {
265         IndexNameSegment indexName = new IndexNameSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (IdentifierValue) visit(ctx.identifier()));
266         return new IndexSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), indexName);
267     }
268     
269     @Override
270     public final ASTNode visitConstraintName(final ConstraintNameContext ctx) {
271         return new ConstraintSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (IdentifierValue) visit(ctx.identifier()));
272     }
273     
274     @Override
275     public final ASTNode visitTableNames(final TableNamesContext ctx) {
276         CollectionValue<SimpleTableSegment> result = new CollectionValue<>();
277         for (TableNameContext each : ctx.tableName()) {
278             result.getValue().add((SimpleTableSegment) visit(each));
279         }
280         return result;
281     }
282     
283     @Override
284     public final ASTNode visitColumnNames(final ColumnNamesContext ctx) {
285         CollectionValue<ColumnSegment> result = new CollectionValue<>();
286         for (ColumnNameContext each : ctx.columnName()) {
287             result.getValue().add((ColumnSegment) visit(each));
288         }
289         return result;
290     }
291     
292     @Override
293     public ASTNode visitAExpr(final AExprContext ctx) {
294         if (null != ctx.cExpr()) {
295             return visit(ctx.cExpr());
296         }
297         if (null != ctx.TYPE_CAST_()) {
298             return new TypeCastExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.getText(), (ExpressionSegment) visit(ctx.aExpr(0)), ctx.typeName().getText());
299         }
300         if (null != ctx.BETWEEN()) {
301             return createBetweenSegment(ctx);
302         }
303         if (null != ctx.IN()) {
304             return createInSegment(ctx);
305         }
306         if (null != ctx.patternMatchingOperator()) {
307             return createPatternMatchingOperationSegment(ctx);
308         }
309         Optional<String> binaryOperator = findBinaryOperator(ctx);
310         if (binaryOperator.isPresent()) {
311             return createBinaryOperationSegment(ctx, binaryOperator.get());
312         }
313         super.visitAExpr(ctx);
314         String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
315         return new CommonExpressionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), text);
316     }
317     
318     private Optional<String> findBinaryOperator(final AExprContext ctx) {
319         if (null != ctx.IS()) {
320             return Optional.of(ctx.IS().getText());
321         }
322         if (null != ctx.ISNULL()) {
323             return Optional.of("IS");
324         }
325         if (1 == ctx.aExpr().size()) {
326             return Optional.empty();
327         }
328         if (null != ctx.comparisonOperator()) {
329             return Optional.of(ctx.comparisonOperator().getText());
330         }
331         if (null != ctx.andOperator()) {
332             return Optional.of(ctx.andOperator().getText());
333         }
334         if (null != ctx.orOperator()) {
335             return Optional.of(ctx.orOperator().getText());
336         }
337         if (null != ctx.PLUS_()) {
338             return Optional.of(ctx.PLUS_().getText());
339         }
340         if (null != ctx.MINUS_()) {
341             return Optional.of(ctx.MINUS_().getText());
342         }
343         if (null != ctx.ASTERISK_()) {
344             return Optional.of(ctx.ASTERISK_().getText());
345         }
346         if (null != ctx.SLASH_()) {
347             return Optional.of(ctx.SLASH_().getText());
348         }
349         return Optional.empty();
350     }
351     
352     private BinaryOperationExpression createPatternMatchingOperationSegment(final AExprContext ctx) {
353         String operator = getOriginalText(ctx.patternMatchingOperator()).toUpperCase();
354         ExpressionSegment left = (ExpressionSegment) visit(ctx.aExpr(0));
355         ListExpression right = new ListExpression(ctx.aExpr(1).start.getStartIndex(), ctx.aExpr().get(ctx.aExpr().size() - 1).stop.getStopIndex());
356         for (int i = 1; i < ctx.aExpr().size(); i++) {
357             right.getItems().add((ExpressionSegment) visit(ctx.aExpr().get(i)));
358         }
359         String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
360         return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
361     }
362     
363     private BinaryOperationExpression createBinaryOperationSegment(final AExprContext ctx, final String operator) {
364         if ("IS".equalsIgnoreCase(operator)) {
365             ExpressionSegment left = (ExpressionSegment) visit(ctx.aExpr(0));
366             String rightText;
367             ExpressionSegment right;
368             if (null != ctx.IS()) {
369                 rightText = ctx.start.getInputStream().getText(new Interval(ctx.IS().getSymbol().getStopIndex() + 2, ctx.stop.getStopIndex())).trim();
370                 right = new LiteralExpressionSegment(ctx.IS().getSymbol().getStopIndex() + 2, ctx.stop.getStopIndex(), rightText);
371             } else {
372                 rightText = ctx.start.getInputStream().getText(new Interval(ctx.ISNULL().getSymbol().getStartIndex() + 2, ctx.stop.getStopIndex())).trim();
373                 right = new LiteralExpressionSegment(ctx.ISNULL().getSymbol().getStartIndex() + 2, ctx.stop.getStopIndex(), rightText);
374             }
375             return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, "IS",
376                     ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex())));
377         }
378         ExpressionSegment left = (ExpressionSegment) visit(ctx.aExpr(0));
379         ExpressionSegment right = (ExpressionSegment) visit(ctx.aExpr(1));
380         String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
381         return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
382     }
383     
384     @Override
385     public ASTNode visitCExpr(final CExprContext ctx) {
386         if (null != ctx.columnref()) {
387             return visit(ctx.columnref());
388         }
389         if (null != ctx.parameterMarker()) {
390             ParameterMarkerValue parameterMarker = (ParameterMarkerValue) visit(ctx.parameterMarker());
391             ParameterMarkerExpressionSegment result = new ParameterMarkerExpressionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), parameterMarker.getValue(), parameterMarker.getType());
392             parameterMarkerSegments.add(result);
393             return result;
394         }
395         if (null != ctx.aexprConst()) {
396             return visit(ctx.aexprConst());
397         }
398         if (null != ctx.aExpr()) {
399             return visit(ctx.aExpr());
400         }
401         if (null != ctx.funcExpr()) {
402             return visit(ctx.funcExpr());
403         }
404         if (null != ctx.selectWithParens()) {
405             return createSubqueryExpressionSegment(ctx);
406         }
407         if (null != ctx.caseExpr()) {
408             return visit(ctx.caseExpr());
409         }
410         super.visitCExpr(ctx);
411         String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
412         return new CommonExpressionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), text);
413     }
414     
415     private ExpressionSegment createSubqueryExpressionSegment(final CExprContext ctx) {
416         SubquerySegment subquerySegment = new SubquerySegment(ctx.selectWithParens().getStart().getStartIndex(),
417                 ctx.selectWithParens().getStop().getStopIndex(), (PostgreSQLSelectStatement) visit(ctx.selectWithParens()), getOriginalText(ctx.selectWithParens()));
418         if (null != ctx.EXISTS()) {
419             subquerySegment.setSubqueryType(SubqueryType.EXISTS_SUBQUERY);
420             return new ExistsSubqueryExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), subquerySegment);
421         }
422         return new SubqueryExpressionSegment(subquerySegment);
423     }
424     
425     @Override
426     public ASTNode visitCaseExpr(final CaseExprContext ctx) {
427         Collection<ExpressionSegment> whenExprs = new LinkedList<>();
428         Collection<ExpressionSegment> thenExprs = new LinkedList<>();
429         for (WhenClauseContext each : ctx.whenClauseList().whenClause()) {
430             whenExprs.add((ExpressionSegment) visit(each.aExpr(0)));
431             thenExprs.add((ExpressionSegment) visit(each.aExpr(1)));
432         }
433         ExpressionSegment caseExpr = null == ctx.caseArg() ? null : (ExpressionSegment) visit(ctx.caseArg().aExpr());
434         ExpressionSegment elseExpr = null == ctx.caseDefault() ? null : (ExpressionSegment) visit(ctx.caseDefault().aExpr());
435         return new CaseWhenExpression(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), caseExpr, whenExprs, thenExprs, elseExpr);
436     }
437     
438     @Override
439     public ASTNode visitFuncExpr(final FuncExprContext ctx) {
440         if (null != ctx.functionExprCommonSubexpr()) {
441             return visit(ctx.functionExprCommonSubexpr());
442         }
443         Collection<ExpressionSegment> expressionSegments = getExpressionSegments(getTargetRuleContextFromParseTree(ctx, AExprContext.class));
444         // TODO replace aggregation segment
445         String aggregationType = ctx.funcApplication().funcName().getText();
446         if (AggregationType.isAggregationType(aggregationType)) {
447             return createAggregationSegment(ctx.funcApplication(), aggregationType, expressionSegments);
448         }
449         FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.funcApplication().funcName().getText(), getOriginalText(ctx));
450         result.getParameters().addAll(expressionSegments);
451         return result;
452     }
453     
454     @Override
455     public ASTNode visitFunctionExprCommonSubexpr(final FunctionExprCommonSubexprContext ctx) {
456         if (null != ctx.CAST()) {
457             return new TypeCastExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.getText(), (ExpressionSegment) visit(ctx.aExpr(0)), ctx.typeName().getText());
458         }
459         FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getChild(0).getText(), getOriginalText(ctx));
460         Collection<ExpressionSegment> expressionSegments = getExpressionSegments(getTargetRuleContextFromParseTree(ctx, AExprContext.class));
461         if ("EXTRACT".equalsIgnoreCase(ctx.getChild(0).getText())) {
462             result.getParameters().add((ExpressionSegment) visit(getTargetRuleContextFromParseTree(ctx, ExtractArgContext.class).iterator().next()));
463         }
464         result.getParameters().addAll(expressionSegments);
465         return result;
466     }
467     
468     @Override
469     public ASTNode visitExtractArg(final ExtractArgContext ctx) {
470         return new ExtractArgExpression(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getChild(0).getText());
471     }
472     
473     private <T extends ParseTree> Collection<T> getTargetRuleContextFromParseTree(final ParseTree parseTree, final Class<? extends T> clazz) {
474         Collection<T> result = new LinkedList<>();
475         for (int index = 0; index < parseTree.getChildCount(); index++) {
476             ParseTree child = parseTree.getChild(index);
477             if (clazz.isInstance(child)) {
478                 result.add(clazz.cast(child));
479             } else {
480                 result.addAll(getTargetRuleContextFromParseTree(child, clazz));
481             }
482         }
483         return result;
484     }
485     
486     private Collection<ExpressionSegment> getExpressionSegments(final Collection<AExprContext> aExprContexts) {
487         Collection<ExpressionSegment> result = new LinkedList<>();
488         for (AExprContext each : aExprContexts) {
489             result.add((ExpressionSegment) visit(each));
490         }
491         return result;
492     }
493     
494     @Override
495     public ASTNode visitAexprConst(final AexprConstContext ctx) {
496         LiteralValue<?> value;
497         if (null != ctx.numberConst()) {
498             value = new NumberLiteralValue(ctx.numberConst().getText());
499         } else if (null != ctx.STRING_()) {
500             value = new StringLiteralValue(ctx.STRING_().getText());
501         } else if (null != ctx.FALSE()) {
502             value = new BooleanLiteralValue(ctx.FALSE().getText());
503         } else if (null != ctx.TRUE()) {
504             value = new BooleanLiteralValue(ctx.TRUE().getText());
505         } else if (null != ctx.NULL()) {
506             value = new NullLiteralValue(ctx.getText());
507         } else {
508             value = new OtherLiteralValue(ctx.getText());
509         }
510         if (null != ctx.constTypeName() || null != ctx.funcName() && null == ctx.LP_()) {
511             LiteralExpressionSegment expression = new LiteralExpressionSegment(ctx.STRING_().getSymbol().getStartIndex(), ctx.STRING_().getSymbol().getStopIndex(), value.getValue().toString());
512             String dataType = null == ctx.constTypeName() ? ctx.funcName().getText() : ctx.constTypeName().getText();
513             return new TypeCastExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.getText(), expression, dataType);
514         }
515         return SQLUtils.createLiteralExpression(value, ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.getText());
516     }
517     
518     @Override
519     public ASTNode visitColumnref(final ColumnrefContext ctx) {
520         if (null != ctx.indirection() && null != ctx.indirection().indirectionEl().attrName()) {
521             AttrNameContext attrName = ctx.indirection().indirectionEl().attrName();
522             ColumnSegment result = new ColumnSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), new IdentifierValue(attrName.getText()));
523             OwnerSegment owner = new OwnerSegment(ctx.colId().start.getStartIndex(), ctx.colId().stop.getStopIndex(), new IdentifierValue(ctx.colId().getText()));
524             result.setOwner(owner);
525             return result;
526         }
527         return new ColumnSegment(ctx.colId().start.getStartIndex(), ctx.colId().stop.getStopIndex(), new IdentifierValue(ctx.colId().getText()));
528     }
529     
530     private InExpression createInSegment(final AExprContext ctx) {
531         ExpressionSegment left = (ExpressionSegment) visit(ctx.aExpr(0));
532         ExpressionSegment right = createInExpressionSegment(ctx.inExpr());
533         boolean not = null != ctx.NOT();
534         return new InExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, not);
535     }
536     
537     @SuppressWarnings("unchecked")
538     private ExpressionSegment createInExpressionSegment(final InExprContext ctx) {
539         if (null != ctx.selectWithParens()) {
540             PostgreSQLSelectStatement select = (PostgreSQLSelectStatement) visit(ctx.selectWithParens());
541             SubquerySegment subquerySegment = new SubquerySegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), select, getOriginalText(ctx.selectWithParens()));
542             return new SubqueryExpressionSegment(subquerySegment);
543         }
544         ListExpression result = new ListExpression(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex());
545         result.getItems().addAll(((CollectionValue<ExpressionSegment>) visit(ctx.exprList())).getValue());
546         return result;
547     }
548     
549     @SuppressWarnings("unchecked")
550     @Override
551     public ASTNode visitExprList(final ExprListContext ctx) {
552         CollectionValue<ExpressionSegment> result = new CollectionValue<>();
553         if (null != ctx.exprList()) {
554             result.combine((CollectionValue<ExpressionSegment>) visitExprList(ctx.exprList()));
555         }
556         result.getValue().add((ExpressionSegment) visit(ctx.aExpr()));
557         return result;
558     }
559     
560     private BetweenExpression createBetweenSegment(final AExprContext ctx) {
561         ExpressionSegment left = (ExpressionSegment) visit(ctx.aExpr(0));
562         ExpressionSegment between = (ExpressionSegment) visit(ctx.bExpr());
563         ExpressionSegment and = (ExpressionSegment) visit(ctx.aExpr(1));
564         boolean not = null != ctx.NOT();
565         return new BetweenExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, between, and, not);
566     }
567     
568     @Override
569     public ASTNode visitBExpr(final BExprContext ctx) {
570         if (null != ctx.cExpr()) {
571             return visit(ctx.cExpr());
572         }
573         if (null != ctx.TYPE_CAST_()) {
574             return new TypeCastExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.getText(), (ExpressionSegment) visit(ctx.bExpr(0)), ctx.typeName().getText());
575         }
576         if (null != ctx.qualOp()) {
577             ExpressionSegment left = (ExpressionSegment) visit(ctx.bExpr(0));
578             ExpressionSegment right = (ExpressionSegment) visit(ctx.bExpr(1));
579             String operator = ctx.qualOp().getText();
580             String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
581             return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
582         }
583         for (BExprContext each : ctx.bExpr()) {
584             visit(each);
585         }
586         return new LiteralExpressionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.getText());
587     }
588     
589     private ProjectionSegment createAggregationSegment(final FuncApplicationContext ctx, final String aggregationType, final Collection<ExpressionSegment> expressionSegments) {
590         AggregationType type = AggregationType.valueOf(aggregationType.toUpperCase());
591         if (null == ctx.DISTINCT()) {
592             AggregationProjectionSegment result = new AggregationProjectionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), type, getOriginalText(ctx));
593             result.getParameters().addAll(expressionSegments);
594             return result;
595         }
596         AggregationDistinctProjectionSegment result =
597                 new AggregationDistinctProjectionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), type, getOriginalText(ctx), getDistinctExpression(ctx));
598         result.getParameters().addAll(expressionSegments);
599         return result;
600     }
601     
602     private String getDistinctExpression(final FuncApplicationContext ctx) {
603         StringBuilder result = new StringBuilder();
604         result.append(ctx.funcArgList().getText());
605         if (null != ctx.sortClause()) {
606             result.append(ctx.sortClause().getText());
607         }
608         return result.toString();
609     }
610     
611     @Override
612     public final ASTNode visitDataTypeName(final DataTypeNameContext ctx) {
613         IdentifierContext identifierContext = ctx.identifier();
614         if (null != identifierContext) {
615             return new KeywordValue(identifierContext.getText());
616         }
617         Collection<String> dataTypeNames = new LinkedList<>();
618         for (int i = 0; i < ctx.getChildCount(); i++) {
619             dataTypeNames.add(ctx.getChild(i).getText());
620         }
621         return new KeywordValue(String.join(" ", dataTypeNames));
622     }
623     
624     @Override
625     public final ASTNode visitSortClause(final SortClauseContext ctx) {
626         Collection<OrderByItemSegment> items = new LinkedList<>();
627         for (SortbyContext each : ctx.sortbyList().sortby()) {
628             items.add((OrderByItemSegment) visit(each));
629         }
630         return new OrderBySegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), items);
631     }
632     
633     @Override
634     public final ASTNode visitSortby(final SortbyContext ctx) {
635         OrderDirection orderDirection = null == ctx.ascDesc() ? OrderDirection.ASC : generateOrderDirection(ctx.ascDesc());
636         NullsOrderType nullsOrderType = generateNullsOrderType(ctx.nullsOrder());
637         ASTNode expr = visit(ctx.aExpr());
638         if (expr instanceof ColumnSegment) {
639             ColumnSegment column = (ColumnSegment) expr;
640             return new ColumnOrderByItemSegment(column, orderDirection, nullsOrderType);
641         }
642         if (expr instanceof LiteralExpressionSegment) {
643             LiteralExpressionSegment index = (LiteralExpressionSegment) expr;
644             return new IndexOrderByItemSegment(index.getStartIndex(), index.getStopIndex(), Integer.parseInt(index.getLiterals().toString()), orderDirection, nullsOrderType);
645         }
646         if (expr instanceof ExpressionSegment) {
647             return new ExpressionOrderByItemSegment(ctx.aExpr().getStart().getStartIndex(),
648                     ctx.aExpr().getStop().getStopIndex(), getOriginalText(ctx.aExpr()), orderDirection, nullsOrderType, (ExpressionSegment) expr);
649         }
650         return new ExpressionOrderByItemSegment(ctx.aExpr().getStart().getStartIndex(), ctx.aExpr().getStop().getStopIndex(), getOriginalText(ctx.aExpr()), orderDirection, nullsOrderType);
651     }
652     
653     private NullsOrderType generateNullsOrderType(final NullsOrderContext ctx) {
654         if (null == ctx) {
655             return null;
656         }
657         return null == ctx.FIRST() ? NullsOrderType.LAST : NullsOrderType.FIRST;
658     }
659     
660     private OrderDirection generateOrderDirection(final AscDescContext ctx) {
661         return null == ctx.DESC() ? OrderDirection.ASC : OrderDirection.DESC;
662     }
663     
664     @Override
665     public final ASTNode visitDataType(final DataTypeContext ctx) {
666         DataTypeSegment result = new DataTypeSegment();
667         result.setDataTypeName(((KeywordValue) visit(ctx.dataTypeName())).getValue());
668         result.setStartIndex(ctx.start.getStartIndex());
669         result.setStopIndex(ctx.stop.getStopIndex());
670         if (null != ctx.dataTypeLength()) {
671             DataTypeLengthSegment dataTypeLengthSegment = (DataTypeLengthSegment) visit(ctx.dataTypeLength());
672             result.setDataLength(dataTypeLengthSegment);
673         }
674         return result;
675     }
676     
677     @Override
678     public final ASTNode visitDataTypeLength(final DataTypeLengthContext ctx) {
679         DataTypeLengthSegment result = new DataTypeLengthSegment();
680         result.setStartIndex(ctx.start.getStartIndex());
681         result.setStopIndex(ctx.stop.getStartIndex());
682         List<TerminalNode> numbers = ctx.NUMBER_();
683         if (1 == numbers.size()) {
684             result.setPrecision(Integer.parseInt(numbers.get(0).getText()));
685         }
686         if (2 == numbers.size()) {
687             result.setPrecision(Integer.parseInt(numbers.get(0).getText()));
688             result.setScale(Integer.parseInt(numbers.get(1).getText()));
689         }
690         return result;
691     }
692     
693     @Override
694     public ASTNode visitInsert(final InsertContext ctx) {
695         // TODO :FIXME, since there is no segment for insertValuesClause, InsertStatement is created by sub rule.
696         // TODO :deal with insert select
697         PostgreSQLInsertStatement result = (PostgreSQLInsertStatement) visit(ctx.insertRest());
698         result.setTable((SimpleTableSegment) visit(ctx.insertTarget()));
699         if (null != ctx.optOnConflict()) {
700             result.setOnDuplicateKeyColumnsSegment((OnDuplicateKeyColumnsSegment) visit(ctx.optOnConflict()));
701         }
702         if (null != ctx.returningClause()) {
703             result.setReturningSegment((ReturningSegment) visit(ctx.returningClause()));
704         }
705         result.addParameterMarkerSegments(getParameterMarkerSegments());
706         return result;
707     }
708     
709     @Override
710     public ASTNode visitOptOnConflict(final OptOnConflictContext ctx) {
711         Collection<ColumnAssignmentSegment> assignments = new LinkedList<>();
712         if (null != ctx.setClauseList()) {
713             assignments = ((SetAssignmentSegment) visit(ctx.setClauseList())).getAssignments();
714         }
715         return new OnDuplicateKeyColumnsSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), assignments);
716     }
717     
718     @Override
719     public ASTNode visitInsertTarget(final InsertTargetContext ctx) {
720         SimpleTableSegment result = (SimpleTableSegment) visit(ctx.qualifiedName());
721         if (null != ctx.AS()) {
722             ColIdContext colId = ctx.colId();
723             result.setAlias(new AliasSegment(colId.start.getStartIndex(), colId.stop.getStopIndex(), new IdentifierValue(colId.getText())));
724         }
725         return result;
726     }
727     
728     @Override
729     public ASTNode visitQualifiedNameList(final QualifiedNameListContext ctx) {
730         CollectionValue<SimpleTableSegment> result = new CollectionValue<>();
731         if (null != ctx.qualifiedName()) {
732             result.getValue().add((SimpleTableSegment) visit(ctx.qualifiedName()));
733         }
734         if (null != ctx.qualifiedNameList()) {
735             result.combine((CollectionValue) visit(ctx.qualifiedNameList()));
736         }
737         return result;
738     }
739     
740     @Override
741     public ASTNode visitQualifiedName(final QualifiedNameContext ctx) {
742         if (null != ctx.indirection()) {
743             AttrNameContext attrName = ctx.indirection().indirectionEl().attrName();
744             TableNameSegment tableName = new TableNameSegment(attrName.start.getStartIndex(), attrName.stop.getStopIndex(), new IdentifierValue(attrName.getText()));
745             OwnerSegment owner = new OwnerSegment(ctx.colId().start.getStartIndex(), ctx.colId().stop.getStopIndex(), new IdentifierValue(ctx.colId().getText()));
746             SimpleTableSegment result = new SimpleTableSegment(tableName);
747             if (null != ctx.indirection().indirection()) {
748                 OwnerSegment tableOwner = createTableOwner(ctx.indirection().indirection());
749                 tableOwner.setOwner(owner);
750                 result.setOwner(tableOwner);
751             } else {
752                 result.setOwner(owner);
753             }
754             return result;
755         }
756         return new SimpleTableSegment(new TableNameSegment(ctx.colId().start.getStartIndex(), ctx.colId().stop.getStopIndex(), new IdentifierValue(ctx.colId().getText())));
757     }
758     
759     @Override
760     public ASTNode visitInsertRest(final InsertRestContext ctx) {
761         PostgreSQLInsertStatement result = new PostgreSQLInsertStatement();
762         ValuesClauseContext valuesClause = ctx.select().selectNoParens().selectClauseN().simpleSelect().valuesClause();
763         if (null == valuesClause) {
764             PostgreSQLSelectStatement selectStatement = (PostgreSQLSelectStatement) visit(ctx.select());
765             result.setInsertSelect(new SubquerySegment(ctx.select().start.getStartIndex(), ctx.select().stop.getStopIndex(), selectStatement, getOriginalText(ctx.select())));
766         } else {
767             result.getValues().addAll(createInsertValuesSegments(valuesClause));
768         }
769         if (null == ctx.insertColumnList()) {
770             result.setInsertColumns(new InsertColumnsSegment(ctx.start.getStartIndex() - 1, ctx.start.getStartIndex() - 1, Collections.emptyList()));
771         } else {
772             InsertColumnListContext insertColumns = ctx.insertColumnList();
773             CollectionValue<ColumnSegment> columns = (CollectionValue<ColumnSegment>) visit(insertColumns);
774             InsertColumnsSegment insertColumnsSegment = new InsertColumnsSegment(insertColumns.start.getStartIndex() - 1, insertColumns.stop.getStopIndex() + 1, columns.getValue());
775             result.setInsertColumns(insertColumnsSegment);
776         }
777         return result;
778     }
779     
780     @Override
781     public ASTNode visitInsertColumnList(final InsertColumnListContext ctx) {
782         CollectionValue<ColumnSegment> result = new CollectionValue<>();
783         if (null != ctx.insertColumnList()) {
784             result.getValue().addAll(((CollectionValue<ColumnSegment>) visit(ctx.insertColumnList())).getValue());
785         }
786         result.getValue().add((ColumnSegment) visit(ctx.insertColumnItem()));
787         return result;
788     }
789     
790     @Override
791     public ASTNode visitInsertColumnItem(final InsertColumnItemContext ctx) {
792         if (null == ctx.optIndirection().indirectionEl()) {
793             return new ColumnSegment(ctx.colId().start.getStartIndex(), ctx.colId().stop.getStopIndex(), new IdentifierValue(ctx.colId().getText()));
794         }
795         ColumnSegment result = new ColumnSegment(ctx.colId().start.getStartIndex(), ctx.optIndirection().stop.getStopIndex(),
796                 new IdentifierValue(ctx.optIndirection().indirectionEl().attrName().getText()));
797         result.setOwner(new OwnerSegment(ctx.colId().start.getStartIndex(), ctx.colId().stop.getStopIndex(), new IdentifierValue(ctx.colId().getText())));
798         return result;
799     }
800     
801     private Collection<InsertValuesSegment> createInsertValuesSegments(final ValuesClauseContext ctx) {
802         Collection<InsertValuesSegment> result = new LinkedList<>();
803         if (null != ctx.valuesClause()) {
804             Collection<InsertValuesSegment> expressions = createInsertValuesSegments(ctx.valuesClause());
805             result.addAll(expressions);
806         }
807         Collection<ExpressionSegment> expressions = createInsertValuesSegments(ctx.exprList());
808         InsertValuesSegment insertValuesSegment = new InsertValuesSegment(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex(), (List<ExpressionSegment>) expressions);
809         result.add(insertValuesSegment);
810         return result;
811     }
812     
813     private Collection<ExpressionSegment> createInsertValuesSegments(final ExprListContext ctx) {
814         Collection<ExpressionSegment> result = new LinkedList<>();
815         if (null != ctx.exprList()) {
816             Collection<ExpressionSegment> tmpResult = createInsertValuesSegments(ctx.exprList());
817             result.addAll(tmpResult);
818         }
819         ExpressionSegment expr = (ExpressionSegment) visit(ctx.aExpr());
820         result.add(expr);
821         return result;
822     }
823     
824     private Collection<ColumnAssignmentSegment> generateAssignmentSegments(final SetClauseListContext ctx) {
825         Collection<ColumnAssignmentSegment> result = new LinkedList<>();
826         if (null != ctx.setClauseList()) {
827             Collection<ColumnAssignmentSegment> tmpResult = generateAssignmentSegments(ctx.setClauseList());
828             result.addAll(tmpResult);
829         }
830         ColumnAssignmentSegment assignmentSegment = (ColumnAssignmentSegment) visit(ctx.setClause());
831         result.add(assignmentSegment);
832         return result;
833     }
834     
835     @Override
836     public ASTNode visitSetClause(final SetClauseContext ctx) {
837         ColumnSegment columnSegment = (ColumnSegment) visit(ctx.setTarget());
838         List<ColumnSegment> columnSegments = new LinkedList<>();
839         columnSegments.add(columnSegment);
840         ExpressionSegment expressionSegment = (ExpressionSegment) visit(ctx.aExpr());
841         return new ColumnAssignmentSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), columnSegments, expressionSegment);
842     }
843     
844     @Override
845     public ASTNode visitSetTarget(final SetTargetContext ctx) {
846         IdentifierValue identifierValue = new IdentifierValue(ctx.colId().getText());
847         return new ColumnSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), identifierValue);
848     }
849     
850     @Override
851     public ASTNode visitRelationExprOptAlias(final RelationExprOptAliasContext ctx) {
852         SimpleTableSegment result = (SimpleTableSegment) visit(ctx.relationExpr().qualifiedName());
853         if (null != ctx.colId()) {
854             result.setAlias(new AliasSegment(ctx.colId().start.getStartIndex(), ctx.stop.getStopIndex(), new IdentifierValue(ctx.colId().getText())));
855         }
856         return result;
857     }
858     
859     @Override
860     public ASTNode visitUpdate(final UpdateContext ctx) {
861         PostgreSQLUpdateStatement result = new PostgreSQLUpdateStatement();
862         SimpleTableSegment tableSegment = (SimpleTableSegment) visit(ctx.relationExprOptAlias());
863         result.setTable(tableSegment);
864         result.setSetAssignment((SetAssignmentSegment) visit(ctx.setClauseList()));
865         if (null != ctx.whereOrCurrentClause()) {
866             result.setWhere((WhereSegment) visit(ctx.whereOrCurrentClause()));
867         }
868         result.addParameterMarkerSegments(getParameterMarkerSegments());
869         return result;
870     }
871     
872     @Override
873     public ASTNode visitSetClauseList(final SetClauseListContext ctx) {
874         Collection<ColumnAssignmentSegment> assignments = generateAssignmentSegments(ctx);
875         return new SetAssignmentSegment(ctx.start.getStartIndex() - 4, ctx.stop.getStopIndex(), assignments);
876     }
877     
878     @Override
879     public ASTNode visitDelete(final DeleteContext ctx) {
880         PostgreSQLDeleteStatement result = new PostgreSQLDeleteStatement();
881         SimpleTableSegment tableSegment = (SimpleTableSegment) visit(ctx.relationExprOptAlias());
882         result.setTable(tableSegment);
883         if (null != ctx.whereOrCurrentClause()) {
884             result.setWhere((WhereSegment) visit(ctx.whereOrCurrentClause()));
885         }
886         result.addParameterMarkerSegments(getParameterMarkerSegments());
887         return result;
888     }
889     
890     @Override
891     public ASTNode visitWhereOrCurrentClause(final WhereOrCurrentClauseContext ctx) {
892         return visit(ctx.whereClause());
893     }
894     
895     @Override
896     public ASTNode visitSelect(final SelectContext ctx) {
897         // TODO :Unsupported for withClause.
898         PostgreSQLSelectStatement result = (PostgreSQLSelectStatement) visit(ctx.selectNoParens());
899         result.addParameterMarkerSegments(getParameterMarkerSegments());
900         return result;
901     }
902     
903     @Override
904     public ASTNode visitSelectNoParens(final SelectNoParensContext ctx) {
905         PostgreSQLSelectStatement result = (PostgreSQLSelectStatement) visit(ctx.selectClauseN());
906         if (null != ctx.sortClause()) {
907             OrderBySegment orderBySegment = (OrderBySegment) visit(ctx.sortClause());
908             result.setOrderBy(orderBySegment);
909         }
910         if (null != ctx.selectLimit()) {
911             LimitSegment limitSegment = (LimitSegment) visit(ctx.selectLimit());
912             result.setLimit(limitSegment);
913         }
914         if (null != ctx.forLockingClause()) {
915             LockSegment lockSegment = (LockSegment) visit(ctx.forLockingClause());
916             result.setLock(lockSegment);
917         }
918         return result;
919     }
920     
921     @Override
922     public ASTNode visitForLockingClause(final ForLockingClauseContext ctx) {
923         return new LockSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex());
924     }
925     
926     @Override
927     public ASTNode visitSelectWithParens(final SelectWithParensContext ctx) {
928         if (null != ctx.selectWithParens()) {
929             return visit(ctx.selectWithParens());
930         }
931         return visit(ctx.selectNoParens());
932     }
933     
934     @Override
935     public ASTNode visitSelectClauseN(final SelectClauseNContext ctx) {
936         if (null != ctx.simpleSelect()) {
937             return visit(ctx.simpleSelect());
938         }
939         if (null != ctx.selectClauseN() && !ctx.selectClauseN().isEmpty()) {
940             PostgreSQLSelectStatement result = new PostgreSQLSelectStatement();
941             PostgreSQLSelectStatement left = (PostgreSQLSelectStatement) visit(ctx.selectClauseN(0));
942             result.setProjections(left.getProjections());
943             left.getFrom().ifPresent(result::setFrom);
944             CombineSegment combineSegment = new CombineSegment(((TerminalNode) ctx.getChild(1)).getSymbol().getStartIndex(), ctx.getStop().getStopIndex(),
945                     createSubquerySegment(ctx.selectClauseN(0), left), getCombineType(ctx), createSubquerySegment(ctx.selectClauseN(1), (PostgreSQLSelectStatement) visit(ctx.selectClauseN(1))));
946             result.setCombine(combineSegment);
947             return result;
948         }
949         return visit(ctx.selectWithParens());
950     }
951     
952     private SubquerySegment createSubquerySegment(final SelectClauseNContext ctx, final PostgreSQLSelectStatement selectStatement) {
953         return new SubquerySegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), selectStatement, getOriginalText(ctx));
954     }
955     
956     private CombineType getCombineType(final SelectClauseNContext ctx) {
957         boolean isDistinct = null == ctx.allOrDistinct() || null != ctx.allOrDistinct().DISTINCT();
958         if (null != ctx.UNION()) {
959             return isDistinct ? CombineType.UNION : CombineType.UNION_ALL;
960         }
961         if (null != ctx.INTERSECT()) {
962             return isDistinct ? CombineType.INTERSECT : CombineType.INTERSECT_ALL;
963         }
964         return isDistinct ? CombineType.EXCEPT : CombineType.EXCEPT_ALL;
965     }
966     
967     @Override
968     public ASTNode visitSimpleSelect(final SimpleSelectContext ctx) {
969         PostgreSQLSelectStatement result = new PostgreSQLSelectStatement();
970         if (null == ctx.targetList()) {
971             result.setProjections(new ProjectionsSegment(-1, -1));
972         } else {
973             ProjectionsSegment projects = (ProjectionsSegment) visit(ctx.targetList());
974             if (null != ctx.distinctClause()) {
975                 projects.setDistinctRow(true);
976             }
977             result.setProjections(projects);
978         }
979         if (null != ctx.intoClause()) {
980             result.setIntoSegment((TableSegment) visit(ctx.intoClause()));
981         }
982         if (null != ctx.fromClause()) {
983             TableSegment tableSegment = (TableSegment) visit(ctx.fromClause());
984             result.setFrom(tableSegment);
985         }
986         if (null != ctx.whereClause()) {
987             result.setWhere((WhereSegment) visit(ctx.whereClause()));
988         }
989         if (null != ctx.groupClause()) {
990             result.setGroupBy((GroupBySegment) visit(ctx.groupClause()));
991         }
992         if (null != ctx.havingClause()) {
993             result.setHaving((HavingSegment) visit(ctx.havingClause()));
994         }
995         if (null != ctx.windowClause()) {
996             result.setWindow((WindowSegment) visit(ctx.windowClause()));
997         }
998         return result;
999     }
1000     
1001     @Override
1002     public ASTNode visitIntoClause(final IntoClauseContext ctx) {
1003         return visit(ctx.optTempTableName().qualifiedName());
1004     }
1005     
1006     @Override
1007     public ASTNode visitHavingClause(final HavingClauseContext ctx) {
1008         ExpressionSegment expr = (ExpressionSegment) visit(ctx.aExpr());
1009         return new HavingSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), expr);
1010     }
1011     
1012     @Override
1013     public ASTNode visitWindowClause(final WindowClauseContext ctx) {
1014         WindowSegment result = new WindowSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex());
1015         appendWindowItems(ctx.windowDefinitionList(), result.getItemSegments());
1016         return result;
1017     }
1018     
1019     private void appendWindowItems(final WindowDefinitionListContext ctx, final Collection<WindowItemSegment> windowItems) {
1020         if (null != ctx.windowDefinitionList()) {
1021             appendWindowItems(ctx.windowDefinitionList(), windowItems);
1022             windowItems.add((WindowItemSegment) visit(ctx.windowDefinition()));
1023             return;
1024         }
1025         windowItems.add((WindowItemSegment) visit(ctx.windowDefinition()));
1026     }
1027     
1028     @SuppressWarnings("unchecked")
1029     @Override
1030     public ASTNode visitWindowDefinition(final WindowDefinitionContext ctx) {
1031         WindowItemSegment result = new WindowItemSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex());
1032         result.setWindowName(new IdentifierValue(ctx.colId().getText()));
1033         if (null != ctx.windowSpecification().partitionClause()) {
1034             CollectionValue<ExpressionSegment> value = (CollectionValue<ExpressionSegment>) visit(ctx.windowSpecification().partitionClause().exprList());
1035             result.setPartitionListSegments(value.getValue());
1036         }
1037         if (null != ctx.windowSpecification().sortClause()) {
1038             OrderBySegment orderBySegment = (OrderBySegment) visit(ctx.windowSpecification().sortClause());
1039             result.setOrderBySegment(orderBySegment);
1040         }
1041         if (null != ctx.windowSpecification().frameClause()) {
1042             result.setFrameClause(new CommonExpressionSegment(ctx.windowSpecification().frameClause().start.getStartIndex(), ctx.windowSpecification().frameClause().stop.getStopIndex(),
1043                     ctx.windowSpecification().frameClause().getText()));
1044         }
1045         return result;
1046     }
1047     
1048     @Override
1049     public ASTNode visitGroupClause(final GroupClauseContext ctx) {
1050         Collection<OrderByItemSegment> items = new LinkedList<>();
1051         for (GroupByItemContext each : ctx.groupByList().groupByItem()) {
1052             items.add((OrderByItemSegment) visit(each));
1053         }
1054         return new GroupBySegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), items);
1055     }
1056     
1057     @Override
1058     public ASTNode visitGroupByItem(final GroupByItemContext ctx) {
1059         if (null != ctx.aExpr()) {
1060             ASTNode astNode = visit(ctx.aExpr());
1061             if (astNode instanceof ColumnSegment) {
1062                 return new ColumnOrderByItemSegment((ColumnSegment) astNode, OrderDirection.ASC, null);
1063             }
1064             if (astNode instanceof LiteralExpressionSegment) {
1065                 LiteralExpressionSegment index = (LiteralExpressionSegment) astNode;
1066                 return new IndexOrderByItemSegment(index.getStartIndex(), index.getStopIndex(),
1067                         Integer.parseInt(index.getLiterals().toString()), OrderDirection.ASC, null);
1068             }
1069             return new ExpressionOrderByItemSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), getOriginalText(ctx), OrderDirection.ASC, null, (ExpressionSegment) visit(ctx.aExpr()));
1070         }
1071         return new ExpressionOrderByItemSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), getOriginalText(ctx), OrderDirection.ASC, null);
1072     }
1073     
1074     @Override
1075     public ASTNode visitTargetList(final TargetListContext ctx) {
1076         ProjectionsSegment result = new ProjectionsSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex());
1077         if (null != ctx.targetList()) {
1078             ProjectionsSegment projections = (ProjectionsSegment) visit(ctx.targetList());
1079             result.getProjections().addAll(projections.getProjections());
1080         }
1081         ProjectionSegment projection = (ProjectionSegment) visit(ctx.targetEl());
1082         result.getProjections().add(projection);
1083         return result;
1084     }
1085     
1086     @Override
1087     public ASTNode visitTargetEl(final TargetElContext ctx) {
1088         ProjectionSegment result = createProjectionSegment(ctx, ctx.aExpr());
1089         if (null != ctx.identifier()) {
1090             ((AliasAvailable) result).setAlias(new AliasSegment(ctx.identifier().start.getStartIndex(), ctx.identifier().stop.getStopIndex(), new IdentifierValue(ctx.identifier().getText())));
1091         }
1092         return result;
1093     }
1094     
1095     private ProjectionSegment createProjectionSegment(final TargetElContext ctx, final AExprContext expr) {
1096         if (null != ctx.ASTERISK_()) {
1097             return new ShorthandProjectionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex());
1098         }
1099         if (null != ctx.DOT_ASTERISK_()) {
1100             ShorthandProjectionSegment result = new ShorthandProjectionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex());
1101             result.setOwner(new OwnerSegment(ctx.colId().start.getStartIndex(), ctx.colId().stop.getStopIndex(), new IdentifierValue(ctx.colId().getText())));
1102             return result;
1103         }
1104         if (null != ctx.aExpr()) {
1105             ASTNode projection = visit(ctx.aExpr());
1106             return createProjectionSegment(ctx, expr, projection);
1107         }
1108         return new ExpressionProjectionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), getOriginalText(expr), null);
1109     }
1110     
1111     private ProjectionSegment createProjectionSegment(final TargetElContext ctx, final AExprContext expr, final ASTNode projection) {
1112         if (projection instanceof ColumnSegment) {
1113             return new ColumnProjectionSegment((ColumnSegment) projection);
1114         }
1115         if (projection instanceof AggregationProjectionSegment) {
1116             return (AggregationProjectionSegment) projection;
1117         }
1118         if (projection instanceof SubqueryExpressionSegment) {
1119             SubqueryExpressionSegment subqueryExpression = (SubqueryExpressionSegment) projection;
1120             String text = ctx.start.getInputStream().getText(new Interval(subqueryExpression.getStartIndex(), subqueryExpression.getStopIndex()));
1121             return new SubqueryProjectionSegment(subqueryExpression.getSubquery(), text);
1122         }
1123         if (projection instanceof ExistsSubqueryExpression) {
1124             ExistsSubqueryExpression existsSubqueryExpression = (ExistsSubqueryExpression) projection;
1125             String text = ctx.start.getInputStream().getText(new Interval(existsSubqueryExpression.getStartIndex(), existsSubqueryExpression.getStopIndex()));
1126             return new SubqueryProjectionSegment(existsSubqueryExpression.getSubquery(), text);
1127         }
1128         if (projection instanceof ExpressionSegment) {
1129             return new ExpressionProjectionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), getOriginalText(expr), (ExpressionSegment) projection);
1130         }
1131         return new ExpressionProjectionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), getOriginalText(expr), null);
1132     }
1133     
1134     @Override
1135     public ASTNode visitFromClause(final FromClauseContext ctx) {
1136         return visit(ctx.fromList());
1137     }
1138     
1139     @Override
1140     public ASTNode visitFromList(final FromListContext ctx) {
1141         if (null != ctx.fromList()) {
1142             JoinTableSegment result = new JoinTableSegment();
1143             result.setStartIndex(ctx.start.getStartIndex());
1144             result.setStopIndex(ctx.stop.getStopIndex());
1145             result.setLeft((TableSegment) visit(ctx.fromList()));
1146             result.setRight((TableSegment) visit(ctx.tableReference()));
1147             result.setJoinType(JoinType.COMMA.name());
1148             return result;
1149         }
1150         return visit(ctx.tableReference());
1151     }
1152     
1153     @Override
1154     public ASTNode visitTableReference(final TableReferenceContext ctx) {
1155         if (null != ctx.relationExpr()) {
1156             SimpleTableSegment result = (SimpleTableSegment) visit(ctx.relationExpr().qualifiedName());
1157             if (null != ctx.aliasClause()) {
1158                 result.setAlias((AliasSegment) visit(ctx.aliasClause()));
1159             }
1160             return result;
1161         }
1162         if (null != ctx.selectWithParens()) {
1163             PostgreSQLSelectStatement select = (PostgreSQLSelectStatement) visit(ctx.selectWithParens());
1164             SubquerySegment subquery = new SubquerySegment(ctx.selectWithParens().start.getStartIndex(), ctx.selectWithParens().stop.getStopIndex(), select, getOriginalText(ctx.selectWithParens()));
1165             AliasSegment alias = null == ctx.aliasClause() ? null : (AliasSegment) visit(ctx.aliasClause());
1166             SubqueryTableSegment result = new SubqueryTableSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), subquery);
1167             result.setAlias(alias);
1168             return result;
1169         }
1170         if (null == ctx.tableReference()) {
1171             // TODO deal with functionTable and xmlTable
1172             TableNameSegment tableName = new TableNameSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), new IdentifierValue("not support"));
1173             return new SimpleTableSegment(tableName);
1174         }
1175         JoinTableSegment result = new JoinTableSegment();
1176         result.setLeft((TableSegment) visit(ctx.tableReference()));
1177         int startIndex = null == ctx.LP_() ? ctx.tableReference().start.getStartIndex() : ctx.LP_().getSymbol().getStartIndex();
1178         int stopIndex = 0;
1179         AliasSegment alias = null;
1180         if (null == ctx.aliasClause()) {
1181             stopIndex = null == ctx.RP_() ? ctx.tableReference().start.getStopIndex() : ctx.RP_().getSymbol().getStopIndex();
1182         } else {
1183             alias = (AliasSegment) visit(ctx.aliasClause());
1184             startIndex = null == ctx.RP_() ? ctx.joinedTable().stop.getStopIndex() : ctx.RP_().getSymbol().getStopIndex();
1185         }
1186         result.setStartIndex(startIndex);
1187         result.setStopIndex(stopIndex);
1188         visitJoinedTable(ctx.joinedTable(), result);
1189         result.setAlias(alias);
1190         return result;
1191     }
1192     
1193     private JoinTableSegment visitJoinedTable(final JoinedTableContext ctx, final JoinTableSegment tableSegment) {
1194         TableSegment right = (TableSegment) visit(ctx.tableReference());
1195         tableSegment.setRight(right);
1196         tableSegment.setJoinType(getJoinType(ctx));
1197         tableSegment.setNatural(null != ctx.naturalJoinType());
1198         return null == ctx.joinQual() ? tableSegment : visitJoinQual(ctx.joinQual(), tableSegment);
1199     }
1200     
1201     private String getJoinType(final JoinedTableContext ctx) {
1202         if (null != ctx.crossJoinType()) {
1203             return JoinType.CROSS.name();
1204         }
1205         if (null != ctx.innerJoinType()) {
1206             return JoinType.INNER.name();
1207         }
1208         if (null != ctx.outerJoinType()) {
1209             return getOutJoinType(ctx.outerJoinType());
1210         }
1211         if (null != ctx.naturalJoinType()) {
1212             return getNaturalJoinType(ctx.naturalJoinType());
1213         }
1214         return JoinType.COMMA.name();
1215     }
1216     
1217     private static String getNaturalJoinType(final NaturalJoinTypeContext ctx) {
1218         if (null != ctx.INNER()) {
1219             return JoinType.INNER.name();
1220         }
1221         if (null != ctx.FULL()) {
1222             return JoinType.FULL.name();
1223         }
1224         if (null != ctx.LEFT()) {
1225             return JoinType.LEFT.name();
1226         }
1227         if (null != ctx.RIGHT()) {
1228             return JoinType.RIGHT.name();
1229         }
1230         return JoinType.INNER.name();
1231     }
1232     
1233     private static String getOutJoinType(final OuterJoinTypeContext ctx) {
1234         if (null == ctx.FULL()) {
1235             return null == ctx.LEFT() ? JoinType.RIGHT.name() : JoinType.LEFT.name();
1236         }
1237         return JoinType.FULL.name();
1238     }
1239     
1240     private JoinTableSegment visitJoinQual(final JoinQualContext ctx, final JoinTableSegment joinTableSource) {
1241         if (null != ctx.aExpr()) {
1242             ExpressionSegment condition = (ExpressionSegment) visit(ctx.aExpr());
1243             joinTableSource.setCondition(condition);
1244         }
1245         if (null != ctx.USING()) {
1246             joinTableSource.setUsing(generateUsingColumn(ctx.nameList()));
1247         }
1248         return joinTableSource;
1249     }
1250     
1251     private List<ColumnSegment> generateUsingColumn(final NameListContext ctx) {
1252         List<ColumnSegment> result = new ArrayList<>();
1253         if (null != ctx.nameList()) {
1254             result.addAll(generateUsingColumn(ctx.nameList()));
1255         }
1256         if (null != ctx.name()) {
1257             result.add(new ColumnSegment(ctx.name().start.getStartIndex(), ctx.name().stop.getStopIndex(), new IdentifierValue(ctx.name().getText())));
1258         }
1259         return result;
1260     }
1261     
1262     @Override
1263     public ASTNode visitAliasClause(final AliasClauseContext ctx) {
1264         StringBuilder aliasName = new StringBuilder(ctx.colId().getText());
1265         if (null != ctx.nameList()) {
1266             aliasName.append(ctx.LP_().getText());
1267             aliasName.append(ctx.nameList().getText());
1268             aliasName.append(ctx.RP_().getText());
1269         }
1270         return new AliasSegment(ctx.colId().start.getStartIndex(), ctx.stop.getStopIndex(), new IdentifierValue(aliasName.toString()));
1271     }
1272     
1273     private OwnerSegment createTableOwner(final IndirectionContext ctx) {
1274         AttrNameContext attrName = ctx.indirectionEl().attrName();
1275         return new OwnerSegment(attrName.start.getStartIndex(), attrName.stop.getStopIndex(), new IdentifierValue(attrName.getText()));
1276     }
1277     
1278     @Override
1279     public ASTNode visitWhereClause(final WhereClauseContext ctx) {
1280         ExpressionSegment expr = (ExpressionSegment) visit(ctx.aExpr());
1281         return new WhereSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), expr);
1282     }
1283     
1284     @Override
1285     public ASTNode visitSelectLimit(final SelectLimitContext ctx) {
1286         if (null != ctx.limitClause() && null != ctx.offsetClause()) {
1287             return createLimitSegmentWhenLimitAndOffset(ctx);
1288         }
1289         return createLimitSegmentWhenRowCountOrOffsetAbsent(ctx);
1290     }
1291     
1292     @Override
1293     public ASTNode visitSelectLimitValue(final SelectLimitValueContext ctx) {
1294         if (null != ctx.ALL()) {
1295             return null;
1296         }
1297         ASTNode astNode = visit(ctx.cExpr());
1298         if (astNode instanceof ParameterMarkerExpressionSegment) {
1299             return new ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) astNode).getParameterMarkerIndex());
1300         }
1301         return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), Long.parseLong(((LiteralExpressionSegment) astNode).getLiterals().toString()));
1302     }
1303     
1304     @Override
1305     public ASTNode visitSelectOffsetValue(final SelectOffsetValueContext ctx) {
1306         ASTNode astNode = visit(ctx.cExpr());
1307         if (astNode instanceof ParameterMarkerExpressionSegment) {
1308             return new ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) astNode).getParameterMarkerIndex());
1309         }
1310         return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), Long.parseLong(((LiteralExpressionSegment) astNode).getLiterals().toString()));
1311     }
1312     
1313     @Override
1314     public ASTNode visitSelectFetchValue(final SelectFetchValueContext ctx) {
1315         ASTNode astNode = visit(ctx.cExpr());
1316         if (astNode instanceof ParameterMarkerExpressionSegment) {
1317             return new ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) astNode).getParameterMarkerIndex());
1318         }
1319         return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), Long.parseLong(((LiteralExpressionSegment) astNode).getLiterals().toString()));
1320     }
1321     
1322     private LimitSegment createLimitSegmentWhenLimitAndOffset(final SelectLimitContext ctx) {
1323         ParseTree astNode0 = ctx.getChild(0);
1324         LimitValueSegment rowCount = null;
1325         LimitValueSegment offset = null;
1326         if (astNode0 instanceof LimitClauseContext) {
1327             rowCount = null == ctx.limitClause().selectLimitValue() ? null : (LimitValueSegment) visit(ctx.limitClause().selectLimitValue());
1328         } else {
1329             offset = (LimitValueSegment) visit(ctx.offsetClause().selectOffsetValue());
1330         }
1331         ParseTree astNode1 = ctx.getChild(1);
1332         if (astNode1 instanceof LimitClauseContext) {
1333             rowCount = null == ctx.limitClause().selectLimitValue() ? null : (LimitValueSegment) visit(ctx.limitClause().selectLimitValue());
1334         } else {
1335             offset = (LimitValueSegment) visit(ctx.offsetClause().selectOffsetValue());
1336         }
1337         return new LimitSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), offset, rowCount);
1338     }
1339     
1340     private LimitSegment createLimitSegmentWhenRowCountOrOffsetAbsent(final SelectLimitContext ctx) {
1341         if (null != ctx.limitClause()) {
1342             if (null != ctx.limitClause().selectFetchValue()) {
1343                 LimitValueSegment limit = (LimitValueSegment) visit(ctx.limitClause().selectFetchValue());
1344                 return new LimitSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), null, limit);
1345             }
1346             LimitValueSegment limit = (LimitValueSegment) visit(ctx.limitClause().selectLimitValue());
1347             return new LimitSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), null, limit);
1348         }
1349         LimitValueSegment offset = (LimitValueSegment) visit(ctx.offsetClause().selectOffsetValue());
1350         return new LimitSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), offset, null);
1351     }
1352     
1353     @Override
1354     public ASTNode visitExecuteStmt(final ExecuteStmtContext ctx) {
1355         return new PostgreSQLExecuteStatement();
1356     }
1357     
1358     /**
1359      * Get original text.
1360      *
1361      * @param ctx context
1362      * @return original text
1363      */
1364     protected String getOriginalText(final ParserRuleContext ctx) {
1365         return ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
1366     }
1367     
1368     @Override
1369     @SuppressWarnings("unchecked")
1370     public ASTNode visitAnyName(final AnyNameContext ctx) {
1371         CollectionValue<NameSegment> result = new CollectionValue<>();
1372         if (null != ctx.attrs()) {
1373             result.combine((CollectionValue<NameSegment>) visit(ctx.attrs()));
1374         }
1375         result.getValue().add(new NameSegment(ctx.colId().getStart().getStartIndex(), ctx.colId().getStop().getStopIndex(), new IdentifierValue(ctx.colId().getText())));
1376         return result;
1377     }
1378     
1379     @Override
1380     @SuppressWarnings("unchecked")
1381     public ASTNode visitAttrs(final AttrsContext ctx) {
1382         CollectionValue<NameSegment> result = new CollectionValue<>();
1383         result.getValue().add(new NameSegment(ctx.attrName().getStart().getStartIndex(), ctx.attrName().getStop().getStopIndex(), new IdentifierValue(ctx.attrName().getText())));
1384         if (null != ctx.attrs()) {
1385             result.combine((CollectionValue<NameSegment>) visit(ctx.attrs()));
1386         }
1387         return result;
1388     }
1389     
1390     @Override
1391     public ASTNode visitName(final NameContext ctx) {
1392         return visit(ctx.identifier());
1393     }
1394     
1395     @Override
1396     public ASTNode visitSignedIconst(final SignedIconstContext ctx) {
1397         return new NumberLiteralValue(ctx.getText());
1398     }
1399 }