1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.sql.parser.mysql.visitor.statement;
19
20 import lombok.AccessLevel;
21 import lombok.Getter;
22 import org.antlr.v4.runtime.ParserRuleContext;
23 import org.antlr.v4.runtime.Token;
24 import org.antlr.v4.runtime.misc.Interval;
25 import org.antlr.v4.runtime.tree.TerminalNode;
26 import org.apache.shardingsphere.sql.parser.api.ASTNode;
27 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementBaseVisitor;
28 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.AggregationFunctionContext;
29 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.AliasContext;
30 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.AssignmentContext;
31 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.AssignmentValueContext;
32 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.AssignmentValuesContext;
33 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.BitExprContext;
34 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.BitValueLiteralsContext;
35 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.BlobValueContext;
36 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.BooleanLiteralsContext;
37 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.BooleanPrimaryContext;
38 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.CaseExpressionContext;
39 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.CaseWhenContext;
40 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.CastFunctionContext;
41 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.CastTypeContext;
42 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.CharFunctionContext;
43 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.CollateClauseContext;
44 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ColumnNameContext;
45 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ColumnNamesContext;
46 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ColumnRefContext;
47 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.CombineClauseContext;
48 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.CompleteRegularFunctionContext;
49 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ConstraintNameContext;
50 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ConvertFunctionContext;
51 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.CteClauseContext;
52 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.CurrentUserFunctionContext;
53 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.DataTypeContext;
54 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.DeleteContext;
55 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.DuplicateSpecificationContext;
56 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.EngineRefContext;
57 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.EscapedTableReferenceContext;
58 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ExprContext;
59 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ExtractFunctionContext;
60 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.FieldLengthContext;
61 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.FieldsContext;
62 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.FromClauseContext;
63 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.FunctionCallContext;
64 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.FunctionNameContext;
65 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.GroupByClauseContext;
66 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.GroupConcatFunctionContext;
67 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.HavingClauseContext;
68 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.HexadecimalLiteralsContext;
69 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.IdentifierContext;
70 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.IndexNameContext;
71 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.InsertContext;
72 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.InsertIdentifierContext;
73 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.InsertSelectClauseContext;
74 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.InsertValuesClauseContext;
75 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.IntervalExpressionContext;
76 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.JoinSpecificationContext;
77 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.JoinedTableContext;
78 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.JsonFunctionContext;
79 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.JsonFunctionNameContext;
80 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.LimitClauseContext;
81 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.LimitOffsetContext;
82 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.LimitRowCountContext;
83 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.LiteralsContext;
84 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.LockClauseContext;
85 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.LockClauseListContext;
86 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.MatchExpressionContext;
87 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.MultipleTablesClauseContext;
88 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.NaturalJoinTypeContext;
89 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.NullValueLiteralsContext;
90 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.NumberLiteralsContext;
91 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.OnDuplicateKeyClauseContext;
92 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.OrderByClauseContext;
93 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.OrderByItemContext;
94 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.OwnerContext;
95 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ParameterMarkerContext;
96 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.PositionFunctionContext;
97 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.PrecisionContext;
98 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.PredicateContext;
99 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ProjectionContext;
100 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ProjectionsContext;
101 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.QualifiedShorthandContext;
102 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.QueryExpressionBodyContext;
103 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.QueryExpressionContext;
104 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.QueryExpressionParensContext;
105 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.QueryPrimaryContext;
106 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.QuerySpecificationContext;
107 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.RegularFunctionContext;
108 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ReplaceContext;
109 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ReplaceSelectClauseContext;
110 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ReplaceValuesClauseContext;
111 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.RowConstructorListContext;
112 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.SchemaNameContext;
113 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.SelectContext;
114 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.SelectSpecificationContext;
115 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.SelectWithIntoContext;
116 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.SetAssignmentsClauseContext;
117 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ShorthandRegularFunctionContext;
118 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.SimpleExprContext;
119 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.SingleTableClauseContext;
120 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.SpecialFunctionContext;
121 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.StringLiteralsContext;
122 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.String_Context;
123 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.SubqueryContext;
124 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.SubstringFunctionContext;
125 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.SystemVariableContext;
126 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TableAliasRefListContext;
127 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TableFactorContext;
128 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TableIdentOptWildContext;
129 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TableListContext;
130 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TableNameContext;
131 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TableReferenceContext;
132 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TableReferencesContext;
133 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TableStatementContext;
134 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TableValueConstructorContext;
135 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TemporalLiteralsContext;
136 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TimeStampDiffFunctionContext;
137 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TrimFunctionContext;
138 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.TypeDatetimePrecisionContext;
139 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.UdfFunctionContext;
140 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.UpdateContext;
141 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.UserVariableContext;
142 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ValuesFunctionContext;
143 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.VariableContext;
144 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ViewNameContext;
145 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.ViewNamesContext;
146 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.WeightStringFunctionContext;
147 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.WhereClauseContext;
148 import org.apache.shardingsphere.sql.parser.autogen.MySQLStatementParser.WithClauseContext;
149 import org.apache.shardingsphere.sql.parser.sql.common.enums.AggregationType;
150 import org.apache.shardingsphere.sql.parser.sql.common.enums.CombineType;
151 import org.apache.shardingsphere.sql.parser.sql.common.enums.JoinType;
152 import org.apache.shardingsphere.sql.parser.sql.common.enums.OrderDirection;
153 import org.apache.shardingsphere.sql.parser.sql.common.enums.ParameterMarkerType;
154 import org.apache.shardingsphere.sql.parser.sql.common.enums.SubqueryType;
155 import org.apache.shardingsphere.sql.parser.sql.common.segment.dal.VariableSegment;
156 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.constraint.ConstraintSegment;
157 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.engine.EngineSegment;
158 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexNameSegment;
159 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.index.IndexSegment;
160 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
161 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.InsertValuesSegment;
162 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.SetAssignmentSegment;
163 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
164 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.InsertColumnsSegment;
165 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.OnDuplicateKeyColumnsSegment;
166 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.combine.CombineSegment;
167 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenExpression;
168 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
169 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CaseWhenExpression;
170 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.CollateExpression;
171 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExistsSubqueryExpression;
172 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
173 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
174 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
175 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
176 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.NotExpression;
177 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.RowExpression;
178 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.UnaryOperationExpression;
179 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ValuesExpression;
180 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
181 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonTableExpressionSegment;
182 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
183 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
184 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.SimpleExpressionSegment;
185 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
186 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
187 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationDistinctProjectionSegment;
188 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationProjectionSegment;
189 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
190 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
191 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
192 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
193 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ShorthandProjectionSegment;
194 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
195 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.GroupBySegment;
196 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.OrderBySegment;
197 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
198 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ExpressionOrderByItemSegment;
199 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.IndexOrderByItemSegment;
200 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
201 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.PaginationValueSegment;
202 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
203 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.NumberLiteralLimitValueSegment;
204 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.ParameterMarkerLimitValueSegment;
205 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.HavingSegment;
206 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.LockSegment;
207 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
208 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
209 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.DataTypeLengthSegment;
210 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.DataTypeSegment;
211 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.DatabaseSegment;
212 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
213 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ParameterMarkerSegment;
214 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ParenthesesSegment;
215 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.WindowSegment;
216 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.WithSegment;
217 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.DeleteMultiTableSegment;
218 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.IndexHintSegment;
219 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
220 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
221 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
222 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment;
223 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
224 import org.apache.shardingsphere.sql.parser.sql.common.util.SQLUtils;
225 import org.apache.shardingsphere.sql.parser.sql.common.value.collection.CollectionValue;
226 import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
227 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.BooleanLiteralValue;
228 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.NullLiteralValue;
229 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.NumberLiteralValue;
230 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.OtherLiteralValue;
231 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.StringLiteralValue;
232 import org.apache.shardingsphere.sql.parser.sql.common.value.parametermarker.ParameterMarkerValue;
233 import org.apache.shardingsphere.sql.parser.sql.dialect.segment.mysql.match.MatchAgainstExpression;
234 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLDeleteStatement;
235 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLInsertStatement;
236 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLSelectStatement;
237 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLUpdateStatement;
238
239 import java.math.BigDecimal;
240 import java.util.ArrayList;
241 import java.util.Collection;
242 import java.util.Collections;
243 import java.util.LinkedList;
244 import java.util.List;
245 import java.util.stream.Collectors;
246
247
248
249
250 @Getter(AccessLevel.PROTECTED)
251 public abstract class MySQLStatementVisitor extends MySQLStatementBaseVisitor<ASTNode> {
252
253 private final Collection<ParameterMarkerSegment> parameterMarkerSegments = new LinkedList<>();
254
255 @Override
256 public final ASTNode visitParameterMarker(final ParameterMarkerContext ctx) {
257 return new ParameterMarkerValue(parameterMarkerSegments.size(), ParameterMarkerType.QUESTION);
258 }
259
260 @Override
261 public final ASTNode visitLiterals(final LiteralsContext ctx) {
262 if (null != ctx.stringLiterals()) {
263 return visit(ctx.stringLiterals());
264 }
265 if (null != ctx.numberLiterals()) {
266 return visit(ctx.numberLiterals());
267 }
268 if (null != ctx.temporalLiterals()) {
269 return visit(ctx.temporalLiterals());
270 }
271 if (null != ctx.hexadecimalLiterals()) {
272 return visit(ctx.hexadecimalLiterals());
273 }
274 if (null != ctx.bitValueLiterals()) {
275 return visit(ctx.bitValueLiterals());
276 }
277 if (null != ctx.booleanLiterals()) {
278 return visit(ctx.booleanLiterals());
279 }
280 if (null != ctx.nullValueLiterals()) {
281 return visit(ctx.nullValueLiterals());
282 }
283 throw new IllegalStateException("Literals must have string, number, dateTime, hex, bit, boolean or null.");
284 }
285
286 @Override
287 public final ASTNode visitStringLiterals(final StringLiteralsContext ctx) {
288 return new StringLiteralValue(ctx.getText());
289 }
290
291 @Override
292 public ASTNode visitString_(final String_Context ctx) {
293 return new StringLiteralValue(ctx.getText());
294 }
295
296 @Override
297 public final ASTNode visitNumberLiterals(final NumberLiteralsContext ctx) {
298 return new NumberLiteralValue(ctx.getText());
299 }
300
301 @Override
302 public ASTNode visitTemporalLiterals(final TemporalLiteralsContext ctx) {
303
304 return new OtherLiteralValue(ctx.getText());
305 }
306
307 @Override
308 public final ASTNode visitHexadecimalLiterals(final HexadecimalLiteralsContext ctx) {
309
310 return new OtherLiteralValue(ctx.getText());
311 }
312
313 @Override
314 public final ASTNode visitBitValueLiterals(final BitValueLiteralsContext ctx) {
315
316 return new OtherLiteralValue(ctx.getText());
317 }
318
319 @Override
320 public final ASTNode visitBooleanLiterals(final BooleanLiteralsContext ctx) {
321 return new BooleanLiteralValue(ctx.getText());
322 }
323
324 @Override
325 public final ASTNode visitNullValueLiterals(final NullValueLiteralsContext ctx) {
326 return new NullLiteralValue(ctx.getText());
327 }
328
329 @Override
330 public final ASTNode visitIdentifier(final IdentifierContext ctx) {
331 return new IdentifierValue(ctx.getText());
332 }
333
334 @Override
335 public final ASTNode visitSchemaName(final SchemaNameContext ctx) {
336 return new DatabaseSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (IdentifierValue) visit(ctx.identifier()));
337 }
338
339 @Override
340 public final ASTNode visitTableName(final TableNameContext ctx) {
341 SimpleTableSegment result = new SimpleTableSegment(new TableNameSegment(ctx.name().getStart().getStartIndex(),
342 ctx.name().getStop().getStopIndex(), new IdentifierValue(ctx.name().identifier().getText())));
343 OwnerContext owner = ctx.owner();
344 if (null != owner) {
345 result.setOwner((OwnerSegment) visit(owner));
346 }
347 return result;
348 }
349
350 @Override
351 public final ASTNode visitViewName(final ViewNameContext ctx) {
352 SimpleTableSegment result = new SimpleTableSegment(new TableNameSegment(ctx.identifier().getStart().getStartIndex(),
353 ctx.identifier().getStop().getStopIndex(), new IdentifierValue(ctx.identifier().getText())));
354 OwnerContext owner = ctx.owner();
355 if (null != owner) {
356 result.setOwner((OwnerSegment) visit(owner));
357 }
358 return result;
359 }
360
361 @Override
362 public final ASTNode visitOwner(final OwnerContext ctx) {
363 return new OwnerSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (IdentifierValue) visit(ctx.identifier()));
364 }
365
366 @Override
367 public ASTNode visitFunctionName(final FunctionNameContext ctx) {
368 FunctionSegment result = new FunctionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.identifier().IDENTIFIER_().getText(), ctx.getText());
369 if (null != ctx.owner()) {
370 result.setOwner((OwnerSegment) visit(ctx.owner()));
371 }
372 return result;
373 }
374
375 @Override
376 public final ASTNode visitColumnName(final ColumnNameContext ctx) {
377 return new ColumnSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (IdentifierValue) visit(ctx.identifier()));
378 }
379
380 @Override
381 public final ASTNode visitIndexName(final IndexNameContext ctx) {
382 IndexNameSegment indexName = new IndexNameSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (IdentifierValue) visit(ctx.identifier()));
383 return new IndexSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), indexName);
384 }
385
386 @Override
387 public ASTNode visitTableList(final TableListContext ctx) {
388 CollectionValue<SimpleTableSegment> result = new CollectionValue<>();
389 for (TableNameContext each : ctx.tableName()) {
390 result.getValue().add((SimpleTableSegment) visit(each));
391 }
392 return result;
393 }
394
395 @Override
396 public final ASTNode visitViewNames(final ViewNamesContext ctx) {
397 CollectionValue<SimpleTableSegment> result = new CollectionValue<>();
398 for (ViewNameContext each : ctx.viewName()) {
399 result.getValue().add((SimpleTableSegment) visit(each));
400 }
401 return result;
402 }
403
404 @Override
405 public final ASTNode visitColumnNames(final ColumnNamesContext ctx) {
406 CollectionValue<ColumnSegment> result = new CollectionValue<>();
407 for (ColumnNameContext each : ctx.columnName()) {
408 result.getValue().add((ColumnSegment) visit(each));
409 }
410 return result;
411 }
412
413 @Override
414 public final ASTNode visitExpr(final ExprContext ctx) {
415 if (null != ctx.booleanPrimary()) {
416 return visit(ctx.booleanPrimary());
417 }
418 if (null != ctx.XOR()) {
419 return createBinaryOperationExpression(ctx, "XOR");
420 }
421 if (null != ctx.andOperator()) {
422 return createBinaryOperationExpression(ctx, ctx.andOperator().getText());
423 }
424 if (null != ctx.orOperator()) {
425 return createBinaryOperationExpression(ctx, ctx.orOperator().getText());
426 }
427 return new NotExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.expr(0)), false);
428 }
429
430 private BinaryOperationExpression createBinaryOperationExpression(final ExprContext ctx, final String operator) {
431 ExpressionSegment left = (ExpressionSegment) visit(ctx.expr(0));
432 ExpressionSegment right = (ExpressionSegment) visit(ctx.expr(1));
433 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
434 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
435 }
436
437 @Override
438 public final ASTNode visitBooleanPrimary(final BooleanPrimaryContext ctx) {
439 if (null != ctx.IS()) {
440
441 String rightText = "";
442 if (null != ctx.NOT()) {
443 rightText = rightText.concat(ctx.start.getInputStream().getText(new Interval(ctx.NOT().getSymbol().getStartIndex(),
444 ctx.NOT().getSymbol().getStopIndex()))).concat(" ");
445 }
446 Token operatorToken = null;
447 if (null != ctx.NULL()) {
448 operatorToken = ctx.NULL().getSymbol();
449 }
450 if (null != ctx.TRUE()) {
451 operatorToken = ctx.TRUE().getSymbol();
452 }
453 if (null != ctx.FALSE()) {
454 operatorToken = ctx.FALSE().getSymbol();
455 }
456 int startIndex = null == operatorToken ? ctx.IS().getSymbol().getStopIndex() + 2 : operatorToken.getStartIndex();
457 rightText = rightText.concat(ctx.start.getInputStream().getText(new Interval(startIndex, ctx.stop.getStopIndex())));
458 ExpressionSegment right = new LiteralExpressionSegment(ctx.IS().getSymbol().getStopIndex() + 2, ctx.stop.getStopIndex(), rightText);
459 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
460 ExpressionSegment left = (ExpressionSegment) visit(ctx.booleanPrimary());
461 String operator = "IS";
462 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
463 }
464 if (null != ctx.comparisonOperator() || null != ctx.SAFE_EQ_()) {
465 return createCompareSegment(ctx);
466 }
467 if (null != ctx.MEMBER()) {
468 int startIndex = ctx.MEMBER().getSymbol().getStopIndex() + 5;
469 int endIndex = ctx.stop.getStopIndex() - 1;
470 String rightText = ctx.start.getInputStream().getText(new Interval(startIndex, endIndex));
471 ExpressionSegment right = new ExpressionProjectionSegment(startIndex, endIndex, rightText);
472 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
473 ExpressionSegment left = (ExpressionSegment) visit(ctx.booleanPrimary());
474 String operator = "MEMBER OF";
475 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
476 }
477 if (null != ctx.assignmentOperator()) {
478 return createAssignmentSegment(ctx);
479 }
480 return visit(ctx.predicate());
481 }
482
483 private ASTNode createAssignmentSegment(final BooleanPrimaryContext ctx) {
484 ExpressionSegment left = (ExpressionSegment) visit(ctx.booleanPrimary());
485 ExpressionSegment right = (ExpressionSegment) visit(ctx.predicate());
486 String operator = ctx.assignmentOperator().getText();
487 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
488 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
489 }
490
491 private ASTNode createCompareSegment(final BooleanPrimaryContext ctx) {
492 ExpressionSegment left = (ExpressionSegment) visit(ctx.booleanPrimary());
493 ExpressionSegment right;
494 if (null != ctx.predicate()) {
495 right = (ExpressionSegment) visit(ctx.predicate());
496 } else {
497 right = new SubqueryExpressionSegment(
498 new SubquerySegment(ctx.subquery().start.getStartIndex(), ctx.subquery().stop.getStopIndex(), (MySQLSelectStatement) visit(ctx.subquery()), getOriginalText(ctx.subquery())));
499 }
500 String operator = null == ctx.SAFE_EQ_() ? ctx.comparisonOperator().getText() : ctx.SAFE_EQ_().getText();
501 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
502 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
503 }
504
505 @Override
506 public final ASTNode visitPredicate(final PredicateContext ctx) {
507 if (null != ctx.IN()) {
508 return createInSegment(ctx);
509 }
510 if (null != ctx.BETWEEN()) {
511 return createBetweenSegment(ctx);
512 }
513 if (null != ctx.LIKE()) {
514 return createBinaryOperationExpressionFromLike(ctx);
515 }
516 if (null != ctx.REGEXP()) {
517 return createBinaryOperationExpressionFromRegexp(ctx);
518 }
519 if (null != ctx.RLIKE()) {
520 return createBinaryOperationExpressionFromRlike(ctx);
521 }
522 return visit(ctx.bitExpr(0));
523 }
524
525 private InExpression createInSegment(final PredicateContext ctx) {
526 boolean not = null != ctx.NOT();
527 ExpressionSegment left = (ExpressionSegment) visit(ctx.bitExpr(0));
528 ExpressionSegment right;
529 if (null != ctx.subquery()) {
530 right = new SubqueryExpressionSegment(
531 new SubquerySegment(ctx.subquery().start.getStartIndex(), ctx.subquery().stop.getStopIndex(), (MySQLSelectStatement) visit(ctx.subquery()), getOriginalText(ctx.subquery())));
532 } else {
533 right = new ListExpression(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex());
534 for (ExprContext each : ctx.expr()) {
535 ((ListExpression) right).getItems().add((ExpressionSegment) visit(each));
536 }
537 }
538 return new InExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, not);
539 }
540
541 private BinaryOperationExpression createBinaryOperationExpressionFromLike(final PredicateContext ctx) {
542 ExpressionSegment left = (ExpressionSegment) visit(ctx.bitExpr(0));
543 String operator;
544 ExpressionSegment right;
545 if (null != ctx.SOUNDS()) {
546 right = (ExpressionSegment) visit(ctx.bitExpr(1));
547 operator = "SOUNDS LIKE";
548 } else {
549 ListExpression listExpression = new ListExpression(ctx.simpleExpr(0).start.getStartIndex(), ctx.simpleExpr().get(ctx.simpleExpr().size() - 1).stop.getStopIndex());
550 for (SimpleExprContext each : ctx.simpleExpr()) {
551 listExpression.getItems().add((ExpressionSegment) visit(each));
552 }
553 right = listExpression;
554 operator = null == ctx.NOT() ? "LIKE" : "NOT LIKE";
555 }
556 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
557 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
558 }
559
560 private BinaryOperationExpression createBinaryOperationExpressionFromRegexp(final PredicateContext ctx) {
561 ExpressionSegment left = (ExpressionSegment) visit(ctx.bitExpr(0));
562 ExpressionSegment right = (ExpressionSegment) visit(ctx.bitExpr(1));
563 String operator = null == ctx.NOT() ? "REGEXP" : "NOT REGEXP";
564 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
565 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
566 }
567
568 private BinaryOperationExpression createBinaryOperationExpressionFromRlike(final PredicateContext ctx) {
569 ExpressionSegment left = (ExpressionSegment) visit(ctx.bitExpr(0));
570 ExpressionSegment right = (ExpressionSegment) visit(ctx.bitExpr(1));
571 String operator = null == ctx.NOT() ? "RLIKE" : "NOT RLIKE";
572 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
573 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
574 }
575
576 private BetweenExpression createBetweenSegment(final PredicateContext ctx) {
577 ExpressionSegment left = (ExpressionSegment) visit(ctx.bitExpr(0));
578 ExpressionSegment between = (ExpressionSegment) visit(ctx.bitExpr(1));
579 ExpressionSegment and = (ExpressionSegment) visit(ctx.predicate());
580 boolean not = null != ctx.NOT();
581 return new BetweenExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, between, and, not);
582 }
583
584 @Override
585 public final ASTNode visitBitExpr(final BitExprContext ctx) {
586 if (null != ctx.simpleExpr()) {
587 return visit(ctx.simpleExpr());
588 }
589 ExpressionSegment left = (ExpressionSegment) visit(ctx.getChild(0));
590 ExpressionSegment right = (ExpressionSegment) visit(ctx.getChild(2));
591 String operator = ctx.getChild(1).getText();
592 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
593 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
594 }
595
596 @Override
597 public final ASTNode visitSimpleExpr(final SimpleExprContext ctx) {
598 int startIndex = ctx.start.getStartIndex();
599 int stopIndex = ctx.stop.getStopIndex();
600 if (null != ctx.subquery()) {
601 SubquerySegment subquerySegment = new SubquerySegment(ctx.subquery().getStart().getStartIndex(), ctx.subquery().getStop().getStopIndex(), (MySQLSelectStatement) visit(ctx.subquery()),
602 getOriginalText(ctx.subquery()));
603 if (null != ctx.EXISTS()) {
604 subquerySegment.setSubqueryType(SubqueryType.EXISTS_SUBQUERY);
605 return new ExistsSubqueryExpression(startIndex, stopIndex, subquerySegment);
606 }
607 return new SubqueryExpressionSegment(subquerySegment);
608 }
609 if (null != ctx.parameterMarker()) {
610 ParameterMarkerValue parameterMarker = (ParameterMarkerValue) visit(ctx.parameterMarker());
611 ParameterMarkerExpressionSegment result = new ParameterMarkerExpressionSegment(startIndex, stopIndex, parameterMarker.getValue(), parameterMarker.getType());
612 parameterMarkerSegments.add(result);
613 return result;
614 }
615 if (null != ctx.literals()) {
616 return SQLUtils.createLiteralExpression(visit(ctx.literals()), startIndex, stopIndex, ctx.literals().start.getInputStream().getText(new Interval(startIndex, stopIndex)));
617 }
618 if (null != ctx.intervalExpression()) {
619 return visit(ctx.intervalExpression());
620 }
621 if (null != ctx.functionCall()) {
622 return visit(ctx.functionCall());
623 }
624 if (null != ctx.collateClause()) {
625 if (null != ctx.simpleExpr()) {
626 ExpressionSegment expr = (ExpressionSegment) visit(ctx.simpleExpr(0));
627 return new CollateExpression(startIndex, stopIndex, (SimpleExpressionSegment) visit(ctx.collateClause()), expr);
628 }
629 return new CollateExpression(startIndex, stopIndex, (SimpleExpressionSegment) visit(ctx.collateClause()), null);
630 }
631 if (null != ctx.columnRef()) {
632 return visit(ctx.columnRef());
633 }
634 if (null != ctx.matchExpression()) {
635 return visit(ctx.matchExpression());
636 }
637 if (null != ctx.notOperator()) {
638 ASTNode expression = visit(ctx.simpleExpr(0));
639 if (expression instanceof ExistsSubqueryExpression) {
640 ((ExistsSubqueryExpression) expression).setNot(true);
641 return expression;
642 }
643 return new NotExpression(startIndex, stopIndex, (ExpressionSegment) expression, "!".equalsIgnoreCase(ctx.notOperator().getText()));
644 }
645 if (null != ctx.LP_() && 1 == ctx.expr().size()) {
646 ASTNode result = visit(ctx.expr(0));
647 if (result instanceof ColumnSegment) {
648 ((ColumnSegment) result).getParentheses().add(new ParenthesesSegment(ctx.LP_().getSymbol().getStartIndex(), ctx.LP_().getSymbol().getStopIndex(), true));
649 ((ColumnSegment) result).getParentheses().add(new ParenthesesSegment(ctx.RP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex(), false));
650 }
651 return result;
652 }
653 if (null != ctx.VERTICAL_BAR_() && 2 == ctx.VERTICAL_BAR_().size()) {
654 ExpressionSegment left = (ExpressionSegment) visit(ctx.simpleExpr(0));
655 ExpressionSegment right = (ExpressionSegment) visit(ctx.simpleExpr(1));
656 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
657 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, ctx.VERTICAL_BAR_(0).getText().concat(ctx.VERTICAL_BAR_(1).getText()), text);
658 }
659 return visitRemainSimpleExpr(ctx);
660 }
661
662 @Override
663 public ASTNode visitColumnRef(final ColumnRefContext ctx) {
664 int identifierCount = ctx.identifier().size();
665 ColumnSegment result;
666 if (1 == identifierCount) {
667 result = new ColumnSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (IdentifierValue) visit(ctx.identifier(0)));
668 } else if (2 == identifierCount) {
669 result = new ColumnSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (IdentifierValue) visit(ctx.identifier(1)));
670 result.setOwner(new OwnerSegment(ctx.identifier(0).start.getStartIndex(), ctx.identifier(0).stop.getStopIndex(), (IdentifierValue) visit(ctx.identifier(0))));
671 } else {
672 result = new ColumnSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (IdentifierValue) visit(ctx.identifier(2)));
673 OwnerSegment owner = new OwnerSegment(ctx.identifier(1).start.getStartIndex(), ctx.identifier(1).stop.getStopIndex(), (IdentifierValue) visit(ctx.identifier(1)));
674 owner.setOwner(new OwnerSegment(ctx.identifier(0).start.getStartIndex(), ctx.identifier(0).stop.getStopIndex(), (IdentifierValue) visit(ctx.identifier(0))));
675 result.setOwner(owner);
676 }
677 return result;
678 }
679
680 @Override
681 public ASTNode visitSubquery(final SubqueryContext ctx) {
682 return visit(ctx.queryExpressionParens());
683 }
684
685 @Override
686 public ASTNode visitQueryExpressionParens(final QueryExpressionParensContext ctx) {
687 if (null != ctx.queryExpressionParens()) {
688 return visit(ctx.queryExpressionParens());
689 }
690 MySQLSelectStatement result = (MySQLSelectStatement) visit(ctx.queryExpression());
691 if (null != ctx.lockClauseList()) {
692 result.setLock((LockSegment) visit(ctx.lockClauseList()));
693 }
694 result.addParameterMarkerSegments(getParameterMarkerSegments());
695 return result;
696 }
697
698 @Override
699 public ASTNode visitLockClauseList(final LockClauseListContext ctx) {
700 LockSegment result = new LockSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex());
701 for (LockClauseContext each : ctx.lockClause()) {
702 if (null != each.tableLockingList()) {
703 result.getTables().addAll(generateTablesFromTableAliasRefList(each.tableLockingList().tableAliasRefList()));
704 }
705 }
706 return result;
707 }
708
709 @Override
710 public ASTNode visitQueryExpression(final QueryExpressionContext ctx) {
711 MySQLSelectStatement result;
712 if (null != ctx.queryExpressionBody()) {
713 result = (MySQLSelectStatement) visit(ctx.queryExpressionBody());
714 } else {
715 result = (MySQLSelectStatement) visit(ctx.queryExpressionParens());
716 }
717 if (null != ctx.orderByClause()) {
718 result.setOrderBy((OrderBySegment) visit(ctx.orderByClause()));
719 }
720 if (null != ctx.limitClause()) {
721 result.setLimit((LimitSegment) visit(ctx.limitClause()));
722 }
723 if (null != result && null != ctx.withClause()) {
724 result.setWithSegment((WithSegment) visit(ctx.withClause()));
725 }
726 return result;
727 }
728
729 @Override
730 public ASTNode visitSelectWithInto(final SelectWithIntoContext ctx) {
731 if (null != ctx.selectWithInto()) {
732 return visit(ctx.selectWithInto());
733 }
734 MySQLSelectStatement result = (MySQLSelectStatement) visit(ctx.queryExpression());
735 if (null != ctx.lockClauseList()) {
736 result.setLock((LockSegment) visit(ctx.lockClauseList()));
737 }
738 return result;
739 }
740
741 @Override
742 public ASTNode visitWithClause(final WithClauseContext ctx) {
743 Collection<CommonTableExpressionSegment> commonTableExpressions = new LinkedList<>();
744 for (CteClauseContext each : ctx.cteClause()) {
745 commonTableExpressions.add((CommonTableExpressionSegment) visit(each));
746 }
747 return new WithSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), commonTableExpressions);
748 }
749
750 @SuppressWarnings("unchecked")
751 @Override
752 public ASTNode visitCteClause(final CteClauseContext ctx) {
753 CommonTableExpressionSegment result = new CommonTableExpressionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (IdentifierValue) visit(ctx.identifier()),
754 new SubquerySegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (MySQLSelectStatement) visit(ctx.subquery()), getOriginalText(ctx.subquery())));
755 if (null != ctx.columnNames()) {
756 CollectionValue<ColumnSegment> columns = (CollectionValue<ColumnSegment>) visit(ctx.columnNames());
757 result.getColumns().addAll(columns.getValue());
758 }
759 return result;
760 }
761
762 @Override
763 public ASTNode visitQueryExpressionBody(final QueryExpressionBodyContext ctx) {
764 if (1 == ctx.getChildCount() && ctx.getChild(0) instanceof QueryPrimaryContext) {
765 return visit(ctx.queryPrimary());
766 }
767 if (null != ctx.queryExpressionBody()) {
768 MySQLSelectStatement result = new MySQLSelectStatement();
769 SubquerySegment left = new SubquerySegment(ctx.queryExpressionBody().start.getStartIndex(), ctx.queryExpressionBody().stop.getStopIndex(),
770 (MySQLSelectStatement) visit(ctx.queryExpressionBody()), getOriginalText(ctx.queryExpressionBody()));
771 result.setProjections(left.getSelect().getProjections());
772 left.getSelect().getFrom().ifPresent(result::setFrom);
773 ((MySQLSelectStatement) left.getSelect()).getTable().ifPresent(result::setTable);
774 result.setCombine(createCombineSegment(ctx.combineClause(), left));
775 return result;
776 }
777 if (null != ctx.queryExpressionParens()) {
778 MySQLSelectStatement result = new MySQLSelectStatement();
779 SubquerySegment left = new SubquerySegment(ctx.queryExpressionParens().start.getStartIndex(), ctx.queryExpressionParens().stop.getStopIndex(),
780 (MySQLSelectStatement) visit(ctx.queryExpressionParens()), getOriginalText(ctx.queryExpressionParens()));
781 result.setProjections(left.getSelect().getProjections());
782 left.getSelect().getFrom().ifPresent(result::setFrom);
783 ((MySQLSelectStatement) left.getSelect()).getTable().ifPresent(result::setTable);
784 result.setCombine(createCombineSegment(ctx.combineClause(), left));
785 return result;
786 }
787 return visit(ctx.queryExpressionParens());
788 }
789
790 private CombineSegment createCombineSegment(final CombineClauseContext ctx, final SubquerySegment left) {
791 CombineType combineType;
792 if (null != ctx.EXCEPT()) {
793 combineType = CombineType.EXCEPT;
794 } else if (null != ctx.INTERSECT()) {
795 combineType = CombineType.INTERSECT;
796 } else {
797 combineType = null == ctx.combineOption() || null == ctx.combineOption().ALL() ? CombineType.UNION : CombineType.UNION_ALL;
798 }
799 ParserRuleContext ruleContext = null == ctx.queryPrimary() ? ctx.queryExpressionParens() : ctx.queryPrimary();
800 SubquerySegment right = new SubquerySegment(ruleContext.start.getStartIndex(), ruleContext.stop.getStopIndex(), (MySQLSelectStatement) visit(ruleContext), getOriginalText(ruleContext));
801 return new CombineSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), left, combineType, right);
802 }
803
804 @Override
805 public ASTNode visitQuerySpecification(final QuerySpecificationContext ctx) {
806 MySQLSelectStatement result = new MySQLSelectStatement();
807 result.setProjections((ProjectionsSegment) visit(ctx.projections()));
808 if (null != ctx.selectSpecification()) {
809 result.getProjections().setDistinctRow(isDistinct(ctx));
810 }
811 if (null != ctx.fromClause()) {
812 if (null != ctx.fromClause().tableReferences()) {
813 TableSegment tableSource = (TableSegment) visit(ctx.fromClause().tableReferences());
814 result.setFrom(tableSource);
815 }
816 if (null != ctx.fromClause().DUAL()) {
817 TableSegment tableSource = new SimpleTableSegment(new TableNameSegment(ctx.fromClause().DUAL().getSymbol().getStartIndex(),
818 ctx.fromClause().DUAL().getSymbol().getStopIndex(), new IdentifierValue(ctx.fromClause().DUAL().getText())));
819 result.setFrom(tableSource);
820 }
821 }
822 if (null != ctx.whereClause()) {
823 result.setWhere((WhereSegment) visit(ctx.whereClause()));
824 }
825 if (null != ctx.groupByClause()) {
826 result.setGroupBy((GroupBySegment) visit(ctx.groupByClause()));
827 }
828 if (null != ctx.havingClause()) {
829 result.setHaving((HavingSegment) visit(ctx.havingClause()));
830 }
831 if (null != ctx.windowClause()) {
832 result.setWindow((WindowSegment) visit(ctx.windowClause()));
833 }
834 return result;
835 }
836
837 @Override
838 public ASTNode visitTableValueConstructor(final TableValueConstructorContext ctx) {
839 MySQLSelectStatement result = new MySQLSelectStatement();
840 int startIndex = ctx.getStart().getStartIndex();
841 int stopIndex = ctx.getStop().getStopIndex();
842 ValuesExpression valuesExpression = new ValuesExpression(startIndex, stopIndex);
843 valuesExpression.getRowConstructorList().addAll(createRowConstructorList(ctx.rowConstructorList()));
844 result.setProjections(new ProjectionsSegment(startIndex, stopIndex));
845 result.getProjections().getProjections().add(new ExpressionProjectionSegment(startIndex, stopIndex, getOriginalText(ctx), valuesExpression));
846 return result;
847 }
848
849 private Collection<InsertValuesSegment> createRowConstructorList(final RowConstructorListContext ctx) {
850 Collection<InsertValuesSegment> result = new LinkedList<>();
851 for (AssignmentValuesContext each : ctx.assignmentValues()) {
852 result.add((InsertValuesSegment) visit(each));
853 }
854 return result;
855 }
856
857 @Override
858 public ASTNode visitTableStatement(final TableStatementContext ctx) {
859 MySQLSelectStatement result = new MySQLSelectStatement();
860 result.setProjections(new ProjectionsSegment(ctx.start.getStartIndex(), ctx.start.getStartIndex()));
861 result.getProjections().getProjections().add(new ShorthandProjectionSegment(ctx.start.getStartIndex(), ctx.start.getStartIndex()));
862 result.setFrom(new SimpleTableSegment(new TableNameSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), new IdentifierValue(ctx.tableName().getText()))));
863 return result;
864 }
865
866 @Override
867 public ASTNode visitHavingClause(final HavingClauseContext ctx) {
868 ExpressionSegment expr = (ExpressionSegment) visit(ctx.expr());
869 return new HavingSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), expr);
870 }
871
872 @Override
873 public final ASTNode visitIntervalExpression(final IntervalExpressionContext ctx) {
874 FunctionSegment result = new FunctionSegment(ctx.INTERVAL().getSymbol().getStartIndex(), ctx.INTERVAL().getSymbol().getStopIndex(), ctx.INTERVAL().getText(), ctx.INTERVAL().getText());
875 result.getParameters().add((ExpressionSegment) visit(ctx.intervalValue().expr()));
876 result.getParameters().add(new LiteralExpressionSegment(ctx.intervalValue().intervalUnit().getStart().getStartIndex(), ctx.intervalValue().intervalUnit().getStop().getStopIndex(),
877 ctx.intervalValue().intervalUnit().getText()));
878 return result;
879 }
880
881 @Override
882 public final ASTNode visitFunctionCall(final FunctionCallContext ctx) {
883 if (null != ctx.aggregationFunction()) {
884 return visit(ctx.aggregationFunction());
885 }
886 if (null != ctx.specialFunction()) {
887 return visit(ctx.specialFunction());
888 }
889 if (null != ctx.regularFunction()) {
890 return visit(ctx.regularFunction());
891 }
892 if (null != ctx.jsonFunction()) {
893 return visit(ctx.jsonFunction());
894 }
895 if (null != ctx.udfFunction()) {
896 return visit(ctx.udfFunction());
897 }
898 throw new IllegalStateException("FunctionCallContext must have aggregationFunction, regularFunction, specialFunction, jsonFunction or udfFunction.");
899 }
900
901 @Override
902 public ASTNode visitUdfFunction(final UdfFunctionContext ctx) {
903 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), getOriginalText(ctx), getOriginalText(ctx));
904 if (null != ctx.expr()) {
905 for (ExprContext each : ctx.expr()) {
906 result.getParameters().add((ExpressionSegment) visit(each));
907 }
908 }
909 return result;
910 }
911
912 @Override
913 public final ASTNode visitAggregationFunction(final AggregationFunctionContext ctx) {
914 String aggregationType = ctx.aggregationFunctionName().getText();
915 return AggregationType.isAggregationType(aggregationType)
916 ? createAggregationSegment(ctx, aggregationType)
917 : new ExpressionProjectionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), getOriginalText(ctx));
918 }
919
920 @Override
921 public final ASTNode visitJsonFunction(final JsonFunctionContext ctx) {
922 JsonFunctionNameContext functionNameContext = ctx.jsonFunctionName();
923 String functionName;
924 FunctionSegment result;
925 if (null != functionNameContext) {
926 functionName = functionNameContext.getText();
927 result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), functionName, getOriginalText(ctx));
928 for (ExprContext each : ctx.expr()) {
929 result.getParameters().add((ExpressionSegment) visit(each));
930 }
931 } else if (null != ctx.JSON_SEPARATOR()) {
932 functionName = ctx.JSON_SEPARATOR().getText();
933 result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), functionName, getOriginalText(ctx));
934 } else {
935 functionName = ctx.JSON_UNQUOTED_SEPARATOR().getText();
936 result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), functionName, getOriginalText(ctx));
937 }
938 return result;
939 }
940
941 private ASTNode createAggregationSegment(final AggregationFunctionContext ctx, final String aggregationType) {
942 AggregationType type = AggregationType.valueOf(aggregationType.toUpperCase());
943 if (null != ctx.distinct()) {
944 AggregationDistinctProjectionSegment result =
945 new AggregationDistinctProjectionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), type, getOriginalText(ctx), getDistinctExpression(ctx));
946 result.getParameters().addAll(getExpressions(ctx.expr()));
947 return result;
948 }
949 AggregationProjectionSegment result = new AggregationProjectionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), type, getOriginalText(ctx));
950 result.getParameters().addAll(getExpressions(ctx.expr()));
951 return result;
952 }
953
954 protected Collection<ExpressionSegment> getExpressions(final List<ExprContext> exprList) {
955 if (null == exprList) {
956 return Collections.emptyList();
957 }
958 Collection<ExpressionSegment> result = new ArrayList<>(exprList.size());
959 for (ExprContext each : exprList) {
960 result.add((ExpressionSegment) visit(each));
961 }
962 return result;
963 }
964
965 private String getDistinctExpression(final AggregationFunctionContext ctx) {
966 StringBuilder result = new StringBuilder();
967 for (int i = 3; i < ctx.getChildCount() - 1; i++) {
968 result.append(ctx.getChild(i).getText());
969 }
970 return result.toString();
971 }
972
973 @Override
974 public final ASTNode visitSpecialFunction(final SpecialFunctionContext ctx) {
975 if (null != ctx.groupConcatFunction()) {
976 return visit(ctx.groupConcatFunction());
977 }
978 if (null != ctx.windowFunction()) {
979 return visit(ctx.windowFunction());
980 }
981 if (null != ctx.castFunction()) {
982 return visit(ctx.castFunction());
983 }
984 if (null != ctx.convertFunction()) {
985 return visit(ctx.convertFunction());
986 }
987 if (null != ctx.positionFunction()) {
988 return visit(ctx.positionFunction());
989 }
990 if (null != ctx.substringFunction()) {
991 return visit(ctx.substringFunction());
992 }
993 if (null != ctx.extractFunction()) {
994 return visit(ctx.extractFunction());
995 }
996 if (null != ctx.charFunction()) {
997 return visit(ctx.charFunction());
998 }
999 if (null != ctx.trimFunction()) {
1000 return visit(ctx.trimFunction());
1001 }
1002 if (null != ctx.weightStringFunction()) {
1003 return visit(ctx.weightStringFunction());
1004 }
1005 if (null != ctx.valuesFunction()) {
1006 return visit(ctx.valuesFunction());
1007 }
1008 if (null != ctx.currentUserFunction()) {
1009 return visit(ctx.currentUserFunction());
1010 }
1011 if (null != ctx.timeStampDiffFunction()) {
1012 return visit(ctx.timeStampDiffFunction());
1013 }
1014 return new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), getOriginalText(ctx), getOriginalText(ctx));
1015 }
1016
1017 @Override
1018 public final ASTNode visitGroupConcatFunction(final GroupConcatFunctionContext ctx) {
1019 calculateParameterCount(ctx.expr());
1020 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.GROUP_CONCAT().getText(), getOriginalText(ctx));
1021 for (ExprContext each : ctx.expr()) {
1022 result.getParameters().add((ExpressionSegment) visit(each));
1023 }
1024 return result;
1025 }
1026
1027 @Override
1028 public final ASTNode visitCastFunction(final CastFunctionContext ctx) {
1029 calculateParameterCount(ctx.expr());
1030 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.CAST().getText(), getOriginalText(ctx));
1031 for (ExprContext each : ctx.expr()) {
1032 ASTNode expr = visit(each);
1033 if (expr instanceof ColumnSegment) {
1034 result.getParameters().add((ColumnSegment) expr);
1035 } else if (expr instanceof LiteralExpressionSegment) {
1036 result.getParameters().add((LiteralExpressionSegment) expr);
1037 }
1038 }
1039 if (null != ctx.castType()) {
1040 result.getParameters().add((DataTypeSegment) visit(ctx.castType()));
1041 }
1042 if (null != ctx.DATETIME()) {
1043 DataTypeSegment dataType = new DataTypeSegment();
1044 dataType.setDataTypeName(ctx.DATETIME().getText());
1045 dataType.setStartIndex(ctx.DATETIME().getSymbol().getStartIndex());
1046 dataType.setStopIndex(ctx.DATETIME().getSymbol().getStopIndex());
1047 if (null != ctx.typeDatetimePrecision()) {
1048 dataType.setDataLength((DataTypeLengthSegment) visit(ctx.typeDatetimePrecision()));
1049 }
1050 result.getParameters().add(dataType);
1051 }
1052 return result;
1053 }
1054
1055 @Override
1056 public ASTNode visitCastType(final CastTypeContext ctx) {
1057 DataTypeSegment result = new DataTypeSegment();
1058 result.setDataTypeName(ctx.castTypeName.getText());
1059 result.setStartIndex(ctx.start.getStartIndex());
1060 result.setStopIndex(ctx.stop.getStopIndex());
1061 if (null != ctx.fieldLength()) {
1062 DataTypeLengthSegment dataTypeLengthSegment = (DataTypeLengthSegment) visit(ctx.fieldLength());
1063 result.setDataLength(dataTypeLengthSegment);
1064 }
1065 if (null != ctx.precision()) {
1066 DataTypeLengthSegment dataTypeLengthSegment = (DataTypeLengthSegment) visit(ctx.precision());
1067 result.setDataLength(dataTypeLengthSegment);
1068 }
1069 return result;
1070 }
1071
1072 @Override
1073 public final ASTNode visitConvertFunction(final ConvertFunctionContext ctx) {
1074 calculateParameterCount(Collections.singleton(ctx.expr()));
1075 return new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.CONVERT().getText(), getOriginalText(ctx));
1076 }
1077
1078 @Override
1079 public final ASTNode visitPositionFunction(final PositionFunctionContext ctx) {
1080 calculateParameterCount(ctx.expr());
1081 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.POSITION().getText(), getOriginalText(ctx));
1082 result.getParameters().add((ExpressionSegment) visit(ctx.expr(0)));
1083 result.getParameters().add((ExpressionSegment) visit(ctx.expr(1)));
1084 return result;
1085 }
1086
1087 @Override
1088 public final ASTNode visitSubstringFunction(final SubstringFunctionContext ctx) {
1089 FunctionSegment result = new FunctionSegment(
1090 ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), null == ctx.SUBSTR() ? ctx.SUBSTRING().getText() : ctx.SUBSTR().getText(), getOriginalText(ctx));
1091 result.getParameters().add((ExpressionSegment) visit(ctx.expr()));
1092 for (TerminalNode each : ctx.NUMBER_()) {
1093 result.getParameters().add(new LiteralExpressionSegment(each.getSymbol().getStartIndex(), each.getSymbol().getStopIndex(), new NumberLiteralValue(each.getText()).getValue()));
1094 }
1095 return result;
1096 }
1097
1098 @Override
1099 public final ASTNode visitExtractFunction(final ExtractFunctionContext ctx) {
1100 calculateParameterCount(Collections.singleton(ctx.expr()));
1101 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.EXTRACT().getText(), getOriginalText(ctx));
1102 result.getParameters().add(new LiteralExpressionSegment(ctx.intervalUnit().getStart().getStartIndex(), ctx.intervalUnit().getStop().getStopIndex(), ctx.intervalUnit().getText()));
1103 result.getParameters().add((ExpressionSegment) visit(ctx.expr()));
1104 return result;
1105 }
1106
1107 @Override
1108 public final ASTNode visitCharFunction(final CharFunctionContext ctx) {
1109 calculateParameterCount(ctx.expr());
1110 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.CHAR().getText(), getOriginalText(ctx));
1111 for (ExprContext each : ctx.expr()) {
1112 ASTNode expr = visit(each);
1113 result.getParameters().add((ExpressionSegment) expr);
1114 }
1115 return result;
1116 }
1117
1118 @Override
1119 public final ASTNode visitTrimFunction(final TrimFunctionContext ctx) {
1120 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.TRIM().getText(), getOriginalText(ctx));
1121 if (null != ctx.BOTH()) {
1122 result.getParameters().add(new LiteralExpressionSegment(ctx.BOTH().getSymbol().getStartIndex(), ctx.BOTH().getSymbol().getStopIndex(),
1123 new OtherLiteralValue(ctx.BOTH().getSymbol().getText()).getValue()));
1124 }
1125 if (null != ctx.TRAILING()) {
1126 result.getParameters().add(new LiteralExpressionSegment(ctx.TRAILING().getSymbol().getStartIndex(), ctx.TRAILING().getSymbol().getStopIndex(),
1127 new OtherLiteralValue(ctx.TRAILING().getSymbol().getText()).getValue()));
1128 }
1129 if (null != ctx.LEADING()) {
1130 result.getParameters().add(new LiteralExpressionSegment(ctx.LEADING().getSymbol().getStartIndex(), ctx.LEADING().getSymbol().getStopIndex(),
1131 new OtherLiteralValue(ctx.LEADING().getSymbol().getText()).getValue()));
1132 }
1133 for (ExprContext each : ctx.expr()) {
1134 result.getParameters().add((ExpressionSegment) visit(each));
1135 }
1136 return result;
1137 }
1138
1139 @Override
1140 public final ASTNode visitWeightStringFunction(final WeightStringFunctionContext ctx) {
1141 calculateParameterCount(Collections.singleton(ctx.expr()));
1142 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.WEIGHT_STRING().getText(), getOriginalText(ctx));
1143 result.getParameters().add((ExpressionSegment) visit(ctx.expr()));
1144 return result;
1145 }
1146
1147 @Override
1148 public final ASTNode visitValuesFunction(final ValuesFunctionContext ctx) {
1149 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.VALUES().getText(), getOriginalText(ctx));
1150 if (!ctx.columnRefList().columnRef().isEmpty()) {
1151 ColumnSegment columnSegment = (ColumnSegment) visit(ctx.columnRefList().columnRef(0));
1152 result.getParameters().add(columnSegment);
1153 }
1154 return result;
1155 }
1156
1157 @Override
1158 public final ASTNode visitCurrentUserFunction(final CurrentUserFunctionContext ctx) {
1159 return new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.CURRENT_USER().getText(), getOriginalText(ctx));
1160 }
1161
1162 @Override
1163 public ASTNode visitTimeStampDiffFunction(final TimeStampDiffFunctionContext ctx) {
1164 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.TIMESTAMPDIFF().getText(), getOriginalText(ctx));
1165 result.getParameters().addAll(getExpressions(ctx.expr()));
1166 return result;
1167 }
1168
1169 @Override
1170 public final ASTNode visitRegularFunction(final RegularFunctionContext ctx) {
1171 return null == ctx.completeRegularFunction() ? visit(ctx.shorthandRegularFunction()) : visit(ctx.completeRegularFunction());
1172 }
1173
1174 @Override
1175 public ASTNode visitCompleteRegularFunction(final CompleteRegularFunctionContext ctx) {
1176 FunctionSegment result = new FunctionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.regularFunctionName().getText(), getOriginalText(ctx));
1177 Collection<ExpressionSegment> expressionSegments = ctx.expr().stream().map(each -> (ExpressionSegment) visit(each)).collect(Collectors.toList());
1178 result.getParameters().addAll(expressionSegments);
1179 return result;
1180 }
1181
1182 @Override
1183 public ASTNode visitShorthandRegularFunction(final ShorthandRegularFunctionContext ctx) {
1184 String text = getOriginalText(ctx);
1185 FunctionSegment result;
1186 if (null != ctx.CURRENT_TIME()) {
1187 result = new FunctionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.CURRENT_TIME().getText(), text);
1188 if (null != ctx.NUMBER_()) {
1189 result.getParameters().add(new LiteralExpressionSegment(ctx.NUMBER_().getSymbol().getStartIndex(), ctx.NUMBER_().getSymbol().getStopIndex(),
1190 new NumberLiteralValue(ctx.NUMBER_().getText())));
1191 }
1192 } else {
1193 result = new FunctionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.getText(), text);
1194 }
1195 return result;
1196 }
1197
1198 private ASTNode visitRemainSimpleExpr(final SimpleExprContext ctx) {
1199 if (null != ctx.caseExpression()) {
1200 return visit(ctx.caseExpression());
1201 }
1202 if (null != ctx.BINARY()) {
1203 return visit(ctx.simpleExpr(0));
1204 }
1205 if (null != ctx.TILDE_()) {
1206 return new UnaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.simpleExpr(0)), "~", ctx.getText());
1207 }
1208 if (null != ctx.variable()) {
1209 return visit(ctx.variable());
1210 }
1211 if (null != ctx.LP_()) {
1212 RowExpression result = new RowExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.getText());
1213 for (ExprContext each : ctx.expr()) {
1214 result.getItems().add((ExpressionSegment) visit(each));
1215 }
1216 return result;
1217 }
1218 if (null != ctx.RETURNING()) {
1219 ListExpression result = new ListExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex());
1220 result.getItems().add(new LiteralExpressionSegment(ctx.path().start.getStartIndex(), ctx.path().stop.getStopIndex(), ctx.path().getText()));
1221 result.getItems().add(new LiteralExpressionSegment(ctx.RETURNING().getSymbol().getStartIndex(), ctx.RETURNING().getSymbol().getStopIndex(), ctx.RETURNING().getSymbol().getText()));
1222 result.getItems().add((ExpressionSegment) visit(ctx.dataType()));
1223 return result;
1224 }
1225 if (null != ctx.LBE_()) {
1226 return visit(ctx.expr(0));
1227 }
1228 for (ExprContext each : ctx.expr()) {
1229 visit(each);
1230 }
1231 for (SimpleExprContext each : ctx.simpleExpr()) {
1232 visit(each);
1233 }
1234 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
1235 return new CommonExpressionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), text);
1236 }
1237
1238 @Override
1239 public ASTNode visitCaseExpression(final CaseExpressionContext ctx) {
1240 Collection<ExpressionSegment> whenExprs = new LinkedList<>();
1241 Collection<ExpressionSegment> thenExprs = new LinkedList<>();
1242 for (CaseWhenContext each : ctx.caseWhen()) {
1243 whenExprs.add((ExpressionSegment) visit(each.expr(0)));
1244 thenExprs.add((ExpressionSegment) visit(each.expr(1)));
1245 }
1246 ExpressionSegment caseExpr = null == ctx.expr() ? null : (ExpressionSegment) visit(ctx.expr());
1247 ExpressionSegment elseExpr = null == ctx.caseElse() ? null : (ExpressionSegment) visit(ctx.caseElse().expr());
1248 return new CaseWhenExpression(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), caseExpr, whenExprs, thenExprs, elseExpr);
1249 }
1250
1251 @Override
1252 public ASTNode visitVariable(final VariableContext ctx) {
1253 return null == ctx.systemVariable() ? visit(ctx.userVariable()) : visit(ctx.systemVariable());
1254 }
1255
1256 @Override
1257 public ASTNode visitUserVariable(final UserVariableContext ctx) {
1258 return new VariableSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.textOrIdentifier().getText());
1259 }
1260
1261 @Override
1262 public ASTNode visitSystemVariable(final SystemVariableContext ctx) {
1263 VariableSegment result = new VariableSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.rvalueSystemVariable().getText());
1264 if (null != ctx.systemVariableScope) {
1265 result.setScope(ctx.systemVariableScope.getText());
1266 }
1267 return result;
1268 }
1269
1270 @Override
1271 public final ASTNode visitMatchExpression(final MatchExpressionContext ctx) {
1272 ColumnSegment columnSegment = (ColumnSegment) visit(ctx.columnRefList().columnRef(0));
1273 ExpressionSegment expressionSegment = (ExpressionSegment) visit(ctx.expr());
1274 return new MatchAgainstExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), columnSegment, expressionSegment, getOriginalText(ctx.matchSearchModifier()), getOriginalText(ctx));
1275 }
1276
1277
1278 private void calculateParameterCount(final Collection<ExprContext> exprContexts) {
1279 for (ExprContext each : exprContexts) {
1280 visit(each);
1281 }
1282 }
1283
1284 @Override
1285 public final ASTNode visitDataType(final DataTypeContext ctx) {
1286 DataTypeSegment result = new DataTypeSegment();
1287 result.setDataTypeName(ctx.dataTypeName.getText());
1288 result.setStartIndex(ctx.start.getStartIndex());
1289 result.setStopIndex(ctx.stop.getStopIndex());
1290 if (null != ctx.fieldLength()) {
1291 DataTypeLengthSegment dataTypeLengthSegment = (DataTypeLengthSegment) visit(ctx.fieldLength());
1292 result.setDataLength(dataTypeLengthSegment);
1293 }
1294 if (null != ctx.precision()) {
1295 DataTypeLengthSegment dataTypeLengthSegment = (DataTypeLengthSegment) visit(ctx.precision());
1296 result.setDataLength(dataTypeLengthSegment);
1297 }
1298 return result;
1299 }
1300
1301 @Override
1302 public ASTNode visitFieldLength(final FieldLengthContext ctx) {
1303 DataTypeLengthSegment result = new DataTypeLengthSegment();
1304 result.setStartIndex(ctx.start.getStartIndex());
1305 result.setStopIndex(ctx.stop.getStartIndex());
1306 result.setPrecision(new BigDecimal(ctx.length.getText()).intValue());
1307 return result;
1308 }
1309
1310 @Override
1311 public ASTNode visitPrecision(final PrecisionContext ctx) {
1312 DataTypeLengthSegment result = new DataTypeLengthSegment();
1313 result.setStartIndex(ctx.start.getStartIndex());
1314 result.setStopIndex(ctx.stop.getStartIndex());
1315 List<TerminalNode> numbers = ctx.NUMBER_();
1316 result.setPrecision(Integer.parseInt(numbers.get(0).getText()));
1317 result.setScale(Integer.parseInt(numbers.get(1).getText()));
1318 return result;
1319 }
1320
1321 @Override
1322 public ASTNode visitTypeDatetimePrecision(final TypeDatetimePrecisionContext ctx) {
1323 DataTypeLengthSegment result = new DataTypeLengthSegment();
1324 result.setStartIndex(ctx.start.getStartIndex());
1325 result.setStopIndex(ctx.stop.getStartIndex());
1326 result.setPrecision(Integer.parseInt(ctx.NUMBER_().getText()));
1327 return result;
1328 }
1329
1330 @Override
1331 public final ASTNode visitOrderByClause(final OrderByClauseContext ctx) {
1332 Collection<OrderByItemSegment> items = new LinkedList<>();
1333 for (OrderByItemContext each : ctx.orderByItem()) {
1334 items.add((OrderByItemSegment) visit(each));
1335 }
1336 return new OrderBySegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), items);
1337 }
1338
1339 @Override
1340 public final ASTNode visitOrderByItem(final OrderByItemContext ctx) {
1341 OrderDirection orderDirection;
1342 if (null != ctx.direction()) {
1343 orderDirection = null == ctx.direction().DESC() ? OrderDirection.ASC : OrderDirection.DESC;
1344 } else {
1345 orderDirection = OrderDirection.ASC;
1346 }
1347 if (null != ctx.numberLiterals()) {
1348 return new IndexOrderByItemSegment(ctx.numberLiterals().getStart().getStartIndex(), ctx.numberLiterals().getStop().getStopIndex(),
1349 SQLUtils.getExactlyNumber(ctx.numberLiterals().getText(), 10).intValue(), orderDirection, null);
1350 } else {
1351 ASTNode expr = visitExpr(ctx.expr());
1352 if (expr instanceof ColumnSegment) {
1353 return new ColumnOrderByItemSegment((ColumnSegment) expr, orderDirection, null);
1354 } else {
1355 return new ExpressionOrderByItemSegment(ctx.expr().getStart().getStartIndex(),
1356 ctx.expr().getStop().getStopIndex(), getOriginalText(ctx.expr()), orderDirection, null, (ExpressionSegment) expr);
1357 }
1358 }
1359 }
1360
1361 @Override
1362 public ASTNode visitInsert(final InsertContext ctx) {
1363
1364 MySQLInsertStatement result;
1365 if (null != ctx.insertValuesClause()) {
1366 result = (MySQLInsertStatement) visit(ctx.insertValuesClause());
1367 } else if (null != ctx.insertSelectClause()) {
1368 result = (MySQLInsertStatement) visit(ctx.insertSelectClause());
1369 } else {
1370 result = new MySQLInsertStatement();
1371 result.setSetAssignment((SetAssignmentSegment) visit(ctx.setAssignmentsClause()));
1372 }
1373 if (null != ctx.onDuplicateKeyClause()) {
1374 result.setOnDuplicateKeyColumns((OnDuplicateKeyColumnsSegment) visit(ctx.onDuplicateKeyClause()));
1375 }
1376 result.setTable((SimpleTableSegment) visit(ctx.tableName()));
1377 result.addParameterMarkerSegments(getParameterMarkerSegments());
1378 return result;
1379 }
1380
1381 @Override
1382 public ASTNode visitInsertSelectClause(final InsertSelectClauseContext ctx) {
1383 MySQLInsertStatement result = new MySQLInsertStatement();
1384 result.setInsertSelect(createInsertSelectSegment(ctx));
1385 if (null != ctx.LP_()) {
1386 if (null != ctx.fields()) {
1387 result.setInsertColumns(new InsertColumnsSegment(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex(), createInsertColumns(ctx.fields())));
1388 } else {
1389 result.setInsertColumns(new InsertColumnsSegment(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex(), Collections.emptyList()));
1390 }
1391 } else {
1392 result.setInsertColumns(new InsertColumnsSegment(ctx.start.getStartIndex() - 1, ctx.start.getStartIndex() - 1, Collections.emptyList()));
1393 }
1394 return result;
1395 }
1396
1397 private SubquerySegment createInsertSelectSegment(final InsertSelectClauseContext ctx) {
1398 MySQLSelectStatement selectStatement = (MySQLSelectStatement) visit(ctx.select());
1399 selectStatement.getParameterMarkerSegments().addAll(getParameterMarkerSegments());
1400 return new SubquerySegment(ctx.select().start.getStartIndex(), ctx.select().stop.getStopIndex(), selectStatement, getOriginalText(ctx.select()));
1401 }
1402
1403 @Override
1404 public ASTNode visitInsertValuesClause(final InsertValuesClauseContext ctx) {
1405 MySQLInsertStatement result = new MySQLInsertStatement();
1406 if (null != ctx.LP_()) {
1407 if (null != ctx.fields()) {
1408 result.setInsertColumns(new InsertColumnsSegment(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex(), createInsertColumns(ctx.fields())));
1409 } else {
1410 result.setInsertColumns(new InsertColumnsSegment(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex(), Collections.emptyList()));
1411 }
1412 } else {
1413 result.setInsertColumns(new InsertColumnsSegment(ctx.start.getStartIndex() - 1, ctx.start.getStartIndex() - 1, Collections.emptyList()));
1414 }
1415 result.getValues().addAll(createInsertValuesSegments(ctx.assignmentValues()));
1416 return result;
1417 }
1418
1419 private Collection<InsertValuesSegment> createInsertValuesSegments(final Collection<AssignmentValuesContext> assignmentValuesContexts) {
1420 Collection<InsertValuesSegment> result = new LinkedList<>();
1421 for (AssignmentValuesContext each : assignmentValuesContexts) {
1422 result.add((InsertValuesSegment) visit(each));
1423 }
1424 return result;
1425 }
1426
1427 @Override
1428 public ASTNode visitOnDuplicateKeyClause(final OnDuplicateKeyClauseContext ctx) {
1429 Collection<ColumnAssignmentSegment> columns = new LinkedList<>();
1430 for (AssignmentContext each : ctx.assignment()) {
1431 columns.add((ColumnAssignmentSegment) visit(each));
1432 }
1433 return new OnDuplicateKeyColumnsSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columns);
1434 }
1435
1436 @Override
1437 public ASTNode visitReplace(final ReplaceContext ctx) {
1438
1439 MySQLInsertStatement result;
1440 if (null != ctx.replaceValuesClause()) {
1441 result = (MySQLInsertStatement) visit(ctx.replaceValuesClause());
1442 } else if (null != ctx.replaceSelectClause()) {
1443 result = (MySQLInsertStatement) visit(ctx.replaceSelectClause());
1444 } else {
1445 result = new MySQLInsertStatement();
1446 result.setSetAssignment((SetAssignmentSegment) visit(ctx.setAssignmentsClause()));
1447 }
1448 result.setTable((SimpleTableSegment) visit(ctx.tableName()));
1449 result.addParameterMarkerSegments(getParameterMarkerSegments());
1450 return result;
1451 }
1452
1453 @Override
1454 public ASTNode visitReplaceSelectClause(final ReplaceSelectClauseContext ctx) {
1455 MySQLInsertStatement result = new MySQLInsertStatement();
1456 if (null != ctx.LP_()) {
1457 if (null != ctx.fields()) {
1458 result.setInsertColumns(new InsertColumnsSegment(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex(), createInsertColumns(ctx.fields())));
1459 } else {
1460 result.setInsertColumns(new InsertColumnsSegment(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex(), Collections.emptyList()));
1461 }
1462 } else {
1463 result.setInsertColumns(new InsertColumnsSegment(ctx.start.getStartIndex() - 1, ctx.start.getStartIndex() - 1, Collections.emptyList()));
1464 }
1465 result.setInsertSelect(createReplaceSelectSegment(ctx));
1466 return result;
1467 }
1468
1469 private SubquerySegment createReplaceSelectSegment(final ReplaceSelectClauseContext ctx) {
1470 MySQLSelectStatement selectStatement = (MySQLSelectStatement) visit(ctx.select());
1471 return new SubquerySegment(ctx.select().start.getStartIndex(), ctx.select().stop.getStopIndex(), selectStatement, getOriginalText(ctx.select()));
1472 }
1473
1474 @Override
1475 public ASTNode visitReplaceValuesClause(final ReplaceValuesClauseContext ctx) {
1476 MySQLInsertStatement result = new MySQLInsertStatement();
1477 if (null != ctx.LP_()) {
1478 if (null != ctx.fields()) {
1479 result.setInsertColumns(new InsertColumnsSegment(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex(), createInsertColumns(ctx.fields())));
1480 } else {
1481 result.setInsertColumns(new InsertColumnsSegment(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex(), Collections.emptyList()));
1482 }
1483 } else {
1484 result.setInsertColumns(new InsertColumnsSegment(ctx.start.getStartIndex() - 1, ctx.start.getStartIndex() - 1, Collections.emptyList()));
1485 }
1486 result.getValues().addAll(createInsertValuesSegments(ctx.assignmentValues()));
1487 return result;
1488 }
1489
1490 private List<ColumnSegment> createInsertColumns(final FieldsContext fields) {
1491 List<ColumnSegment> result = new LinkedList<>();
1492 for (InsertIdentifierContext each : fields.insertIdentifier()) {
1493 result.add((ColumnSegment) visit(each));
1494 }
1495 return result;
1496 }
1497
1498 @Override
1499 public ASTNode visitUpdate(final UpdateContext ctx) {
1500 MySQLUpdateStatement result = new MySQLUpdateStatement();
1501 TableSegment tableSegment = (TableSegment) visit(ctx.tableReferences());
1502 result.setTable(tableSegment);
1503 result.setSetAssignment((SetAssignmentSegment) visit(ctx.setAssignmentsClause()));
1504 if (null != ctx.whereClause()) {
1505 result.setWhere((WhereSegment) visit(ctx.whereClause()));
1506 }
1507 if (null != ctx.orderByClause()) {
1508 result.setOrderBy((OrderBySegment) visit(ctx.orderByClause()));
1509 }
1510 if (null != ctx.limitClause()) {
1511 result.setLimit((LimitSegment) visit(ctx.limitClause()));
1512 }
1513 result.addParameterMarkerSegments(getParameterMarkerSegments());
1514 return result;
1515 }
1516
1517 @Override
1518 public ASTNode visitSetAssignmentsClause(final SetAssignmentsClauseContext ctx) {
1519 Collection<ColumnAssignmentSegment> assignments = new LinkedList<>();
1520 for (AssignmentContext each : ctx.assignment()) {
1521 assignments.add((ColumnAssignmentSegment) visit(each));
1522 }
1523 return new SetAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), assignments);
1524 }
1525
1526 @Override
1527 public ASTNode visitAssignmentValues(final AssignmentValuesContext ctx) {
1528 List<ExpressionSegment> segments = new LinkedList<>();
1529 for (AssignmentValueContext each : ctx.assignmentValue()) {
1530 segments.add((ExpressionSegment) visit(each));
1531 }
1532 return new InsertValuesSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), segments);
1533 }
1534
1535 @Override
1536 public ASTNode visitAssignment(final AssignmentContext ctx) {
1537 ColumnSegment column = (ColumnSegment) visit(ctx.columnRef());
1538 ExpressionSegment value = (ExpressionSegment) visit(ctx.assignmentValue());
1539 List<ColumnSegment> columnSegments = new LinkedList<>();
1540 columnSegments.add(column);
1541 return new ColumnAssignmentSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), columnSegments, value);
1542 }
1543
1544 @Override
1545 public ASTNode visitAssignmentValue(final AssignmentValueContext ctx) {
1546 ExprContext expr = ctx.expr();
1547 if (null != expr) {
1548 ASTNode result = visit(expr);
1549 if (result instanceof ColumnSegment) {
1550 return new CommonExpressionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getText());
1551 } else {
1552 return result;
1553 }
1554 }
1555 return new CommonExpressionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getText());
1556 }
1557
1558 @Override
1559 public ASTNode visitBlobValue(final BlobValueContext ctx) {
1560 return new StringLiteralValue(ctx.string_().getText());
1561 }
1562
1563 @Override
1564 public ASTNode visitDelete(final DeleteContext ctx) {
1565 MySQLDeleteStatement result = new MySQLDeleteStatement();
1566 if (null != ctx.multipleTablesClause()) {
1567 result.setTable((TableSegment) visit(ctx.multipleTablesClause()));
1568 } else {
1569 result.setTable((TableSegment) visit(ctx.singleTableClause()));
1570 }
1571 if (null != ctx.whereClause()) {
1572 result.setWhere((WhereSegment) visit(ctx.whereClause()));
1573 }
1574 if (null != ctx.orderByClause()) {
1575 result.setOrderBy((OrderBySegment) visit(ctx.orderByClause()));
1576 }
1577 if (null != ctx.limitClause()) {
1578 result.setLimit((LimitSegment) visit(ctx.limitClause()));
1579 }
1580 result.addParameterMarkerSegments(getParameterMarkerSegments());
1581 return result;
1582 }
1583
1584 @Override
1585 public ASTNode visitSingleTableClause(final SingleTableClauseContext ctx) {
1586 SimpleTableSegment result = (SimpleTableSegment) visit(ctx.tableName());
1587 if (null != ctx.alias()) {
1588 result.setAlias((AliasSegment) visit(ctx.alias()));
1589 }
1590 return result;
1591 }
1592
1593 @Override
1594 public ASTNode visitMultipleTablesClause(final MultipleTablesClauseContext ctx) {
1595 DeleteMultiTableSegment result = new DeleteMultiTableSegment();
1596 TableSegment relateTableSource = (TableSegment) visit(ctx.tableReferences());
1597 result.setRelationTable(relateTableSource);
1598 result.setActualDeleteTables(generateTablesFromTableAliasRefList(ctx.tableAliasRefList()));
1599 return result;
1600 }
1601
1602 private List<SimpleTableSegment> generateTablesFromTableAliasRefList(final TableAliasRefListContext ctx) {
1603 List<SimpleTableSegment> result = new LinkedList<>();
1604 for (TableIdentOptWildContext each : ctx.tableIdentOptWild()) {
1605 result.add((SimpleTableSegment) visit(each.tableName()));
1606 }
1607 return result;
1608 }
1609
1610 @Override
1611 public ASTNode visitSelect(final SelectContext ctx) {
1612 MySQLSelectStatement result;
1613 if (null != ctx.queryExpression()) {
1614 result = (MySQLSelectStatement) visit(ctx.queryExpression());
1615 if (null != ctx.lockClauseList()) {
1616 result.setLock((LockSegment) visit(ctx.lockClauseList()));
1617 }
1618 } else if (null != ctx.selectWithInto()) {
1619 result = (MySQLSelectStatement) visit(ctx.selectWithInto());
1620 } else {
1621 result = (MySQLSelectStatement) visit(ctx.getChild(0));
1622 }
1623 result.addParameterMarkerSegments(getParameterMarkerSegments());
1624 return result;
1625 }
1626
1627 private boolean isDistinct(final QuerySpecificationContext ctx) {
1628 for (SelectSpecificationContext each : ctx.selectSpecification()) {
1629 if (((BooleanLiteralValue) visit(each)).getValue()) {
1630 return true;
1631 }
1632 }
1633 return false;
1634 }
1635
1636 @Override
1637 public ASTNode visitSelectSpecification(final SelectSpecificationContext ctx) {
1638 if (null != ctx.duplicateSpecification()) {
1639 return visit(ctx.duplicateSpecification());
1640 }
1641 return new BooleanLiteralValue(false);
1642 }
1643
1644 @Override
1645 public ASTNode visitDuplicateSpecification(final DuplicateSpecificationContext ctx) {
1646 String text = ctx.getText();
1647 if ("DISTINCT".equalsIgnoreCase(text) || "DISTINCTROW".equalsIgnoreCase(text)) {
1648 return new BooleanLiteralValue(true);
1649 }
1650 return new BooleanLiteralValue(false);
1651 }
1652
1653 @Override
1654 public ASTNode visitProjections(final ProjectionsContext ctx) {
1655 Collection<ProjectionSegment> projections = new LinkedList<>();
1656 if (null != ctx.unqualifiedShorthand()) {
1657 projections.add(new ShorthandProjectionSegment(ctx.unqualifiedShorthand().getStart().getStartIndex(), ctx.unqualifiedShorthand().getStop().getStopIndex()));
1658 }
1659 for (ProjectionContext each : ctx.projection()) {
1660 projections.add((ProjectionSegment) visit(each));
1661 }
1662 ProjectionsSegment result = new ProjectionsSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex());
1663 result.getProjections().addAll(projections);
1664 return result;
1665 }
1666
1667 @Override
1668 public ASTNode visitProjection(final ProjectionContext ctx) {
1669
1670 if (null != ctx.qualifiedShorthand()) {
1671 return createShorthandProjection(ctx.qualifiedShorthand());
1672 }
1673 AliasSegment alias = null == ctx.alias() ? null : (AliasSegment) visit(ctx.alias());
1674 ExpressionSegment exprProjection = (ExpressionSegment) visit(ctx.expr());
1675 if (exprProjection instanceof ColumnSegment) {
1676 ColumnProjectionSegment result = new ColumnProjectionSegment((ColumnSegment) exprProjection);
1677 result.setAlias(alias);
1678 return result;
1679 }
1680 if (exprProjection instanceof SubquerySegment) {
1681 SubquerySegment subquerySegment = (SubquerySegment) exprProjection;
1682 String text = ctx.start.getInputStream().getText(new Interval(subquerySegment.getStartIndex(), subquerySegment.getStopIndex()));
1683 SubqueryProjectionSegment result = new SubqueryProjectionSegment((SubquerySegment) exprProjection, text);
1684 result.setAlias(alias);
1685 return result;
1686 }
1687 if (exprProjection instanceof ExistsSubqueryExpression) {
1688 ExistsSubqueryExpression existsSubqueryExpression = (ExistsSubqueryExpression) exprProjection;
1689 String text = ctx.start.getInputStream().getText(new Interval(existsSubqueryExpression.getStartIndex(), existsSubqueryExpression.getStopIndex()));
1690 SubqueryProjectionSegment result = new SubqueryProjectionSegment(((ExistsSubqueryExpression) exprProjection).getSubquery(), text);
1691 result.setAlias(alias);
1692 return result;
1693 }
1694 return createProjection(ctx, alias, exprProjection);
1695 }
1696
1697 private ShorthandProjectionSegment createShorthandProjection(final QualifiedShorthandContext shorthand) {
1698 ShorthandProjectionSegment result = new ShorthandProjectionSegment(shorthand.getStart().getStartIndex(), shorthand.getStop().getStopIndex());
1699 IdentifierContext identifier = shorthand.identifier().get(shorthand.identifier().size() - 1);
1700 OwnerSegment owner = new OwnerSegment(identifier.getStart().getStartIndex(), identifier.getStop().getStopIndex(), new IdentifierValue(identifier.getText()));
1701 result.setOwner(owner);
1702 if (shorthand.identifier().size() > 1) {
1703 IdentifierContext schemaIdentifier = shorthand.identifier().get(0);
1704 owner.setOwner(new OwnerSegment(schemaIdentifier.getStart().getStartIndex(), schemaIdentifier.getStop().getStopIndex(), new IdentifierValue(schemaIdentifier.getText())));
1705 }
1706 return result;
1707 }
1708
1709 @Override
1710 public ASTNode visitAlias(final AliasContext ctx) {
1711 return new AliasSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), new IdentifierValue(ctx.textOrIdentifier().getText()));
1712 }
1713
1714 private ASTNode createProjection(final ProjectionContext ctx, final AliasSegment alias, final ExpressionSegment projection) {
1715 if (projection instanceof AggregationProjectionSegment) {
1716 ((AggregationProjectionSegment) projection).setAlias(alias);
1717 return projection;
1718 }
1719 if (projection instanceof ExpressionProjectionSegment) {
1720 ((ExpressionProjectionSegment) projection).setAlias(alias);
1721 return projection;
1722 }
1723 if (projection instanceof FunctionSegment) {
1724 FunctionSegment functionSegment = (FunctionSegment) projection;
1725 ExpressionProjectionSegment result = new ExpressionProjectionSegment(functionSegment.getStartIndex(), functionSegment.getStopIndex(), functionSegment.getText(), functionSegment);
1726 result.setAlias(alias);
1727 return result;
1728 }
1729 if (projection instanceof CommonExpressionSegment) {
1730 CommonExpressionSegment segment = (CommonExpressionSegment) projection;
1731 ExpressionProjectionSegment result = new ExpressionProjectionSegment(segment.getStartIndex(), segment.getStopIndex(), segment.getText(), segment);
1732 result.setAlias(alias);
1733 return result;
1734 }
1735
1736 if (projection instanceof ColumnSegment) {
1737 ExpressionProjectionSegment result = new ExpressionProjectionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), getOriginalText(ctx), projection);
1738 result.setAlias(alias);
1739 return result;
1740 }
1741 if (projection instanceof SubqueryExpressionSegment) {
1742 SubqueryExpressionSegment subqueryExpressionSegment = (SubqueryExpressionSegment) projection;
1743 String text = ctx.start.getInputStream().getText(new Interval(subqueryExpressionSegment.getStartIndex(), subqueryExpressionSegment.getStopIndex()));
1744 SubqueryProjectionSegment result = new SubqueryProjectionSegment(subqueryExpressionSegment.getSubquery(), text);
1745 result.setAlias(alias);
1746 return result;
1747 }
1748 if (projection instanceof BinaryOperationExpression) {
1749 int startIndex = projection.getStartIndex();
1750 int stopIndex = null == alias ? projection.getStopIndex() : alias.getStopIndex();
1751 ExpressionProjectionSegment result = new ExpressionProjectionSegment(startIndex, stopIndex, projection.getText(), projection);
1752 result.setAlias(alias);
1753 return result;
1754 }
1755 if (projection instanceof ParameterMarkerExpressionSegment) {
1756 ParameterMarkerExpressionSegment result = (ParameterMarkerExpressionSegment) projection;
1757 result.setAlias(alias);
1758 return projection;
1759 }
1760 if (projection instanceof CaseWhenExpression || projection instanceof VariableSegment || projection instanceof BetweenExpression || projection instanceof InExpression
1761 || projection instanceof CollateExpression || projection instanceof NotExpression) {
1762 return createExpressionProjectionSegment(ctx, alias, projection);
1763 }
1764 LiteralExpressionSegment column = (LiteralExpressionSegment) projection;
1765 ExpressionProjectionSegment result = null == alias
1766 ? new ExpressionProjectionSegment(column.getStartIndex(), column.getStopIndex(), String.valueOf(column.getLiterals()), column)
1767 : new ExpressionProjectionSegment(column.getStartIndex(), ctx.alias().stop.getStopIndex(), String.valueOf(column.getLiterals()), column);
1768 result.setAlias(alias);
1769 return result;
1770 }
1771
1772 private ExpressionProjectionSegment createExpressionProjectionSegment(final ProjectionContext ctx, final AliasSegment alias, final ExpressionSegment projection) {
1773 ExpressionProjectionSegment result = new ExpressionProjectionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), getOriginalText(ctx.expr()), projection);
1774 result.setAlias(alias);
1775 return result;
1776 }
1777
1778 @Override
1779 public ASTNode visitFromClause(final FromClauseContext ctx) {
1780 return visit(ctx.tableReferences());
1781 }
1782
1783 @Override
1784 public ASTNode visitTableReferences(final TableReferencesContext ctx) {
1785 TableSegment result = (TableSegment) visit(ctx.tableReference(0));
1786 if (ctx.tableReference().size() > 1) {
1787 for (int i = 1; i < ctx.tableReference().size(); i++) {
1788 result = generateJoinTableSourceFromEscapedTableReference(ctx.tableReference(i), result);
1789 }
1790 }
1791 return result;
1792 }
1793
1794 private JoinTableSegment generateJoinTableSourceFromEscapedTableReference(final TableReferenceContext ctx, final TableSegment tableSegment) {
1795 JoinTableSegment result = new JoinTableSegment();
1796 result.setStartIndex(tableSegment.getStartIndex());
1797 result.setStopIndex(ctx.stop.getStopIndex());
1798 result.setLeft(tableSegment);
1799 result.setJoinType(JoinType.COMMA.name());
1800 result.setRight((TableSegment) visit(ctx));
1801 return result;
1802 }
1803
1804 @Override
1805 public ASTNode visitEscapedTableReference(final EscapedTableReferenceContext ctx) {
1806 TableSegment result;
1807 TableSegment left;
1808 left = (TableSegment) visit(ctx.tableFactor());
1809 for (JoinedTableContext each : ctx.joinedTable()) {
1810 left = visitJoinedTable(each, left);
1811 }
1812 result = left;
1813 return result;
1814 }
1815
1816 @Override
1817 public ASTNode visitTableReference(final TableReferenceContext ctx) {
1818 TableSegment result;
1819 TableSegment left;
1820 left = null == ctx.tableFactor() ? (TableSegment) visit(ctx.escapedTableReference()) : (TableSegment) visit(ctx.tableFactor());
1821 for (JoinedTableContext each : ctx.joinedTable()) {
1822 left = visitJoinedTable(each, left);
1823 }
1824 result = left;
1825 return result;
1826 }
1827
1828 @Override
1829 public ASTNode visitTableFactor(final TableFactorContext ctx) {
1830 if (null != ctx.subquery()) {
1831 MySQLSelectStatement subquery = (MySQLSelectStatement) visit(ctx.subquery());
1832 SubquerySegment subquerySegment = new SubquerySegment(ctx.subquery().start.getStartIndex(), ctx.subquery().stop.getStopIndex(), subquery, getOriginalText(ctx.subquery()));
1833 SubqueryTableSegment result = new SubqueryTableSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), subquerySegment);
1834 if (null != ctx.alias()) {
1835 result.setAlias((AliasSegment) visit(ctx.alias()));
1836 }
1837 return result;
1838 }
1839 if (null != ctx.tableName()) {
1840 SimpleTableSegment result = (SimpleTableSegment) visit(ctx.tableName());
1841 if (null != ctx.alias()) {
1842 result.setAlias((AliasSegment) visit(ctx.alias()));
1843 }
1844 if (null != ctx.indexHintList()) {
1845 ctx.indexHintList().indexHint().forEach(each -> result.getIndexHintSegments().add((IndexHintSegment) visit(each)));
1846 }
1847 return result;
1848 }
1849 return visit(ctx.tableReferences());
1850 }
1851
1852 private JoinTableSegment visitJoinedTable(final JoinedTableContext ctx, final TableSegment tableSegment) {
1853 JoinTableSegment result = new JoinTableSegment();
1854 result.setLeft(tableSegment);
1855 result.setStartIndex(tableSegment.getStartIndex());
1856 result.setStopIndex(ctx.stop.getStopIndex());
1857 result.setJoinType(getJoinType(ctx));
1858 result.setNatural(null != ctx.naturalJoinType());
1859 TableSegment right = null == ctx.tableFactor() ? (TableSegment) visit(ctx.tableReference()) : (TableSegment) visit(ctx.tableFactor());
1860 result.setRight(right);
1861 return null == ctx.joinSpecification() ? result : visitJoinSpecification(ctx.joinSpecification(), result);
1862 }
1863
1864 private String getJoinType(final JoinedTableContext ctx) {
1865 if (null != ctx.innerJoinType()) {
1866 return JoinType.INNER.name();
1867 }
1868 if (null != ctx.outerJoinType()) {
1869 return null == ctx.outerJoinType().LEFT() ? JoinType.RIGHT.name() : JoinType.LEFT.name();
1870 }
1871 if (null != ctx.naturalJoinType()) {
1872 return getNaturalJoinType(ctx.naturalJoinType());
1873 }
1874 return JoinType.COMMA.name();
1875 }
1876
1877 private String getNaturalJoinType(final NaturalJoinTypeContext ctx) {
1878 if (null != ctx.LEFT()) {
1879 return JoinType.LEFT.name();
1880 }
1881 if (null != ctx.RIGHT()) {
1882 return JoinType.RIGHT.name();
1883 }
1884 return JoinType.INNER.name();
1885 }
1886
1887 private JoinTableSegment visitJoinSpecification(final JoinSpecificationContext ctx, final JoinTableSegment result) {
1888 if (null != ctx.expr()) {
1889 ExpressionSegment condition = (ExpressionSegment) visit(ctx.expr());
1890 result.setCondition(condition);
1891 }
1892 if (null != ctx.USING()) {
1893 result.setUsing(ctx.columnNames().columnName().stream().map(each -> (ColumnSegment) visit(each)).collect(Collectors.toList()));
1894 }
1895 return result;
1896 }
1897
1898 @Override
1899 public ASTNode visitWhereClause(final WhereClauseContext ctx) {
1900 ASTNode segment = visit(ctx.expr());
1901 return new WhereSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (ExpressionSegment) segment);
1902 }
1903
1904 @Override
1905 public ASTNode visitGroupByClause(final GroupByClauseContext ctx) {
1906 Collection<OrderByItemSegment> items = new LinkedList<>();
1907 for (OrderByItemContext each : ctx.orderByItem()) {
1908 items.add((OrderByItemSegment) visit(each));
1909 }
1910 return new GroupBySegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), items);
1911 }
1912
1913 @Override
1914 public ASTNode visitLimitClause(final LimitClauseContext ctx) {
1915 if (null == ctx.limitOffset()) {
1916 return new LimitSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), null, (PaginationValueSegment) visit(ctx.limitRowCount()));
1917 }
1918 PaginationValueSegment rowCount;
1919 PaginationValueSegment offset;
1920 if (null != ctx.OFFSET()) {
1921 rowCount = (PaginationValueSegment) visit(ctx.limitRowCount());
1922 offset = (PaginationValueSegment) visit(ctx.limitOffset());
1923 } else {
1924 offset = (PaginationValueSegment) visit(ctx.limitOffset());
1925 rowCount = (PaginationValueSegment) visit(ctx.limitRowCount());
1926 }
1927 return new LimitSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), offset, rowCount);
1928 }
1929
1930 @Override
1931 public ASTNode visitLimitRowCount(final LimitRowCountContext ctx) {
1932 if (null != ctx.numberLiterals()) {
1933 return new NumberLiteralLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((NumberLiteralValue) visit(ctx.numberLiterals())).getValue().longValue());
1934 }
1935 ParameterMarkerSegment result = new ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(),
1936 ((ParameterMarkerValue) visit(ctx.parameterMarker())).getValue());
1937 parameterMarkerSegments.add(result);
1938 return result;
1939 }
1940
1941 @Override
1942 public final ASTNode visitConstraintName(final ConstraintNameContext ctx) {
1943 return new ConstraintSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (IdentifierValue) visit(ctx.identifier()));
1944 }
1945
1946 @Override
1947 public ASTNode visitLimitOffset(final LimitOffsetContext ctx) {
1948 if (null != ctx.numberLiterals()) {
1949 return new NumberLiteralLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((NumberLiteralValue) visit(ctx.numberLiterals())).getValue().longValue());
1950 }
1951 ParameterMarkerSegment result = new ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(),
1952 ((ParameterMarkerValue) visit(ctx.parameterMarker())).getValue());
1953 parameterMarkerSegments.add(result);
1954 return result;
1955 }
1956
1957 @Override
1958 public ASTNode visitCollateClause(final CollateClauseContext ctx) {
1959 if (null != ctx.collationName()) {
1960 return new LiteralExpressionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.collationName().textOrIdentifier().getText());
1961 }
1962 ParameterMarkerExpressionSegment segment = new ParameterMarkerExpressionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(),
1963 ((ParameterMarkerValue) visit(ctx.parameterMarker())).getValue());
1964 parameterMarkerSegments.add(segment);
1965 return segment;
1966 }
1967
1968 @Override
1969 public ASTNode visitEngineRef(final EngineRefContext ctx) {
1970 return new EngineSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), SQLUtils.getExactlyValue(ctx.textOrIdentifier().getText()));
1971 }
1972
1973 protected String getOriginalText(final ParserRuleContext ctx) {
1974 return ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
1975 }
1976 }