1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.sql.parser.sql92.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.SQL92StatementBaseVisitor;
28 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.AggregationFunctionContext;
29 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.BitExprContext;
30 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.BitValueLiteralsContext;
31 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.BooleanLiteralsContext;
32 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.BooleanPrimaryContext;
33 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.CastFunctionContext;
34 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.ColumnNameContext;
35 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.ColumnNamesContext;
36 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.DataTypeContext;
37 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.DataTypeLengthContext;
38 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.DataTypeNameContext;
39 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.ExprContext;
40 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.FunctionCallContext;
41 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.HexadecimalLiteralsContext;
42 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.IdentifierContext;
43 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.IntervalExpressionContext;
44 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.LiteralsContext;
45 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.NullValueLiteralsContext;
46 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.NumberLiteralsContext;
47 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.OrderByClauseContext;
48 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.OrderByItemContext;
49 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.OwnerContext;
50 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.ParameterMarkerContext;
51 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.PredicateContext;
52 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.RegularFunctionContext;
53 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.SchemaNameContext;
54 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.SimpleExprContext;
55 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.SpecialFunctionContext;
56 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.StringLiteralsContext;
57 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.TableNameContext;
58 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.TableNamesContext;
59 import org.apache.shardingsphere.sql.parser.autogen.SQL92StatementParser.UnreservedWordContext;
60 import org.apache.shardingsphere.sql.parser.sql.common.enums.AggregationType;
61 import org.apache.shardingsphere.sql.parser.sql.common.enums.OrderDirection;
62 import org.apache.shardingsphere.sql.parser.sql.common.enums.ParameterMarkerType;
63 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
64 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenExpression;
65 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
66 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
67 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
68 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
69 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
70 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.NotExpression;
71 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
72 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
73 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
74 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
75 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubquerySegment;
76 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationDistinctProjectionSegment;
77 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationProjectionSegment;
78 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
79 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.OrderBySegment;
80 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
81 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.IndexOrderByItemSegment;
82 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.OrderByItemSegment;
83 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.DataTypeLengthSegment;
84 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.DataTypeSegment;
85 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
86 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ParameterMarkerSegment;
87 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
88 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment;
89 import org.apache.shardingsphere.sql.parser.sql.common.util.SQLUtils;
90 import org.apache.shardingsphere.sql.parser.sql.common.value.collection.CollectionValue;
91 import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
92 import org.apache.shardingsphere.sql.parser.sql.common.value.keyword.KeywordValue;
93 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.BooleanLiteralValue;
94 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.NullLiteralValue;
95 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.NumberLiteralValue;
96 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.OtherLiteralValue;
97 import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.StringLiteralValue;
98 import org.apache.shardingsphere.sql.parser.sql.common.value.parametermarker.ParameterMarkerValue;
99 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sql92.dml.SQL92SelectStatement;
100
101 import java.util.Collection;
102 import java.util.Collections;
103 import java.util.LinkedList;
104 import java.util.List;
105 import java.util.stream.Collectors;
106
107
108
109
110 @Getter(AccessLevel.PROTECTED)
111 public abstract class SQL92StatementVisitor extends SQL92StatementBaseVisitor<ASTNode> {
112
113 private final Collection<ParameterMarkerSegment> parameterMarkerSegments = new LinkedList<>();
114
115 @Override
116 public final ASTNode visitParameterMarker(final ParameterMarkerContext ctx) {
117 return new ParameterMarkerValue(parameterMarkerSegments.size(), ParameterMarkerType.QUESTION);
118 }
119
120 @Override
121 public final ASTNode visitLiterals(final LiteralsContext ctx) {
122 if (null != ctx.stringLiterals()) {
123 return visit(ctx.stringLiterals());
124 }
125 if (null != ctx.numberLiterals()) {
126 return visit(ctx.numberLiterals());
127 }
128 if (null != ctx.hexadecimalLiterals()) {
129 return visit(ctx.hexadecimalLiterals());
130 }
131 if (null != ctx.bitValueLiterals()) {
132 return visit(ctx.bitValueLiterals());
133 }
134 if (null != ctx.booleanLiterals()) {
135 return visit(ctx.booleanLiterals());
136 }
137 if (null != ctx.nullValueLiterals()) {
138 return visit(ctx.nullValueLiterals());
139 }
140 throw new IllegalStateException("Literals must have string, number, dateTime, hex, bit, boolean or null.");
141 }
142
143 @Override
144 public final ASTNode visitStringLiterals(final StringLiteralsContext ctx) {
145 return new StringLiteralValue(ctx.getText());
146 }
147
148 @Override
149 public final ASTNode visitNumberLiterals(final NumberLiteralsContext ctx) {
150 return new NumberLiteralValue(ctx.getText());
151 }
152
153 @Override
154 public final ASTNode visitHexadecimalLiterals(final HexadecimalLiteralsContext ctx) {
155
156 return new OtherLiteralValue(ctx.getText());
157 }
158
159 @Override
160 public final ASTNode visitBitValueLiterals(final BitValueLiteralsContext ctx) {
161
162 return new OtherLiteralValue(ctx.getText());
163 }
164
165 @Override
166 public final ASTNode visitBooleanLiterals(final BooleanLiteralsContext ctx) {
167 return new BooleanLiteralValue(ctx.getText());
168 }
169
170 @Override
171 public final ASTNode visitNullValueLiterals(final NullValueLiteralsContext ctx) {
172 return new NullLiteralValue(ctx.getText());
173 }
174
175 @Override
176 public final ASTNode visitIdentifier(final IdentifierContext ctx) {
177 UnreservedWordContext unreservedWord = ctx.unreservedWord();
178 return null == unreservedWord ? new IdentifierValue(ctx.getText()) : visit(unreservedWord);
179 }
180
181 @Override
182 public final ASTNode visitUnreservedWord(final UnreservedWordContext ctx) {
183 return new IdentifierValue(ctx.getText());
184 }
185
186 @Override
187 public final ASTNode visitSchemaName(final SchemaNameContext ctx) {
188 return visit(ctx.identifier());
189 }
190
191 @Override
192 public final ASTNode visitTableName(final TableNameContext ctx) {
193 SimpleTableSegment result = new SimpleTableSegment(new TableNameSegment(ctx.name().getStart().getStartIndex(), ctx.name().getStop().getStopIndex(), (IdentifierValue) visit(ctx.name())));
194 OwnerContext owner = ctx.owner();
195 if (null != owner) {
196 result.setOwner(new OwnerSegment(owner.getStart().getStartIndex(), owner.getStop().getStopIndex(), (IdentifierValue) visit(owner.identifier())));
197 }
198 return result;
199 }
200
201 @Override
202 public final ASTNode visitColumnName(final ColumnNameContext ctx) {
203 ColumnSegment result = new ColumnSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), (IdentifierValue) visit(ctx.name()));
204 OwnerContext owner = ctx.owner();
205 if (null != owner) {
206 result.setOwner(new OwnerSegment(owner.getStart().getStartIndex(), owner.getStop().getStopIndex(), (IdentifierValue) visit(owner.identifier())));
207 }
208 return result;
209 }
210
211 @Override
212 public final ASTNode visitTableNames(final TableNamesContext ctx) {
213 CollectionValue<SimpleTableSegment> result = new CollectionValue<>();
214 for (TableNameContext each : ctx.tableName()) {
215 result.getValue().add((SimpleTableSegment) visit(each));
216 }
217 return result;
218 }
219
220 @Override
221 public final ASTNode visitColumnNames(final ColumnNamesContext ctx) {
222 CollectionValue<ColumnSegment> result = new CollectionValue<>();
223 for (ColumnNameContext each : ctx.columnName()) {
224 result.getValue().add((ColumnSegment) visit(each));
225 }
226 return result;
227 }
228
229 @Override
230 public final ASTNode visitExpr(final ExprContext ctx) {
231 if (null != ctx.booleanPrimary()) {
232 return visit(ctx.booleanPrimary());
233 }
234 if (null != ctx.LP_()) {
235 return visit(ctx.expr(0));
236 }
237 if (null != ctx.andOperator()) {
238 return createBinaryOperationExpression(ctx, ctx.andOperator().getText());
239 }
240 if (null != ctx.orOperator()) {
241 return createBinaryOperationExpression(ctx, ctx.orOperator().getText());
242 }
243 return new NotExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.expr(0)), false);
244 }
245
246 private ASTNode createBinaryOperationExpression(final ExprContext ctx, final String operator) {
247 ExpressionSegment left = (ExpressionSegment) visit(ctx.expr(0));
248 ExpressionSegment right = (ExpressionSegment) visit(ctx.expr(1));
249 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
250 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
251 }
252
253 @Override
254 public final ASTNode visitBooleanPrimary(final BooleanPrimaryContext ctx) {
255 if (null != ctx.IS()) {
256 String rightText = "";
257 if (null != ctx.NOT()) {
258 rightText = rightText.concat(ctx.start.getInputStream().getText(new Interval(ctx.NOT().getSymbol().getStartIndex(),
259 ctx.NOT().getSymbol().getStopIndex()))).concat(" ");
260 }
261 Token operatorToken = null;
262 if (null != ctx.NULL()) {
263 operatorToken = ctx.NULL().getSymbol();
264 }
265 if (null != ctx.TRUE()) {
266 operatorToken = ctx.TRUE().getSymbol();
267 }
268 if (null != ctx.FALSE()) {
269 operatorToken = ctx.FALSE().getSymbol();
270 }
271 int startIndex = null == operatorToken ? ctx.IS().getSymbol().getStopIndex() + 2 : operatorToken.getStartIndex();
272 rightText = rightText.concat(ctx.start.getInputStream().getText(new Interval(startIndex, ctx.stop.getStopIndex())));
273 ExpressionSegment right = new LiteralExpressionSegment(ctx.IS().getSymbol().getStopIndex() + 2, ctx.stop.getStopIndex(), rightText);
274 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
275 ExpressionSegment left = (ExpressionSegment) visit(ctx.booleanPrimary());
276 String operator = "IS";
277 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
278 }
279 if (null != ctx.comparisonOperator() || null != ctx.SAFE_EQ_()) {
280 return createCompareSegment(ctx);
281 }
282 return visit(ctx.predicate());
283 }
284
285 private ASTNode createCompareSegment(final BooleanPrimaryContext ctx) {
286 ExpressionSegment left = (ExpressionSegment) visit(ctx.booleanPrimary());
287 ExpressionSegment right;
288 if (null != ctx.predicate()) {
289 right = (ExpressionSegment) visit(ctx.predicate());
290 } else {
291 right = (ExpressionSegment) visit(ctx.subquery());
292 }
293 String operator = null == ctx.SAFE_EQ_() ? ctx.comparisonOperator().getText() : ctx.SAFE_EQ_().getText();
294 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
295 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
296 }
297
298 @Override
299 public final ASTNode visitPredicate(final PredicateContext ctx) {
300 if (null != ctx.IN()) {
301 return createInSegment(ctx);
302 }
303 if (null != ctx.BETWEEN()) {
304 return createBetweenSegment(ctx);
305 }
306 if (null != ctx.LIKE()) {
307 return createBinaryOperationExpressionFromLike(ctx);
308 }
309 return visit(ctx.bitExpr(0));
310 }
311
312 private BinaryOperationExpression createBinaryOperationExpressionFromLike(final PredicateContext ctx) {
313 ExpressionSegment left = (ExpressionSegment) visit(ctx.bitExpr(0));
314 ListExpression right = new ListExpression(ctx.simpleExpr(0).start.getStartIndex(), ctx.simpleExpr().get(ctx.simpleExpr().size() - 1).stop.getStopIndex());
315 for (SimpleExprContext each : ctx.simpleExpr()) {
316 right.getItems().add((ExpressionSegment) visit(each));
317 }
318 String operator = null == ctx.NOT() ? "LIKE" : "NOT LIKE";
319 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
320 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
321 }
322
323 private InExpression createInSegment(final PredicateContext ctx) {
324 ExpressionSegment left = (ExpressionSegment) visit(ctx.bitExpr(0));
325 ExpressionSegment right;
326 if (null != ctx.subquery()) {
327 right = new SubqueryExpressionSegment(new SubquerySegment(ctx.subquery().start.getStartIndex(), ctx.subquery().stop.getStopIndex(), (SQL92SelectStatement) visit(ctx.subquery()),
328 getOriginalText(ctx.subquery())));
329 } else {
330 ListExpression listExpression = new ListExpression(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex());
331 for (ExprContext each : ctx.expr()) {
332 listExpression.getItems().add((ExpressionSegment) visit(each));
333 }
334 right = listExpression;
335 }
336 boolean not = null != ctx.NOT();
337 return new InExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, not);
338 }
339
340 private BetweenExpression createBetweenSegment(final PredicateContext ctx) {
341 ExpressionSegment left = (ExpressionSegment) visit(ctx.bitExpr(0));
342 ExpressionSegment between = (ExpressionSegment) visit(ctx.bitExpr(1));
343 ExpressionSegment and = (ExpressionSegment) visit(ctx.predicate());
344 boolean not = null != ctx.NOT();
345 return new BetweenExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, between, and, not);
346 }
347
348 @Override
349 public final ASTNode visitBitExpr(final BitExprContext ctx) {
350 if (null != ctx.simpleExpr()) {
351 return createExpressionSegment(visit(ctx.simpleExpr()), ctx);
352 }
353 ExpressionSegment left = (ExpressionSegment) visit(ctx.getChild(0));
354 ExpressionSegment right = (ExpressionSegment) visit(ctx.getChild(2));
355 String operator = ctx.getChild(1).getText();
356 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
357 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
358 }
359
360 private ASTNode createExpressionSegment(final ASTNode astNode, final ParserRuleContext context) {
361 if (astNode instanceof StringLiteralValue) {
362 return new LiteralExpressionSegment(context.start.getStartIndex(), context.stop.getStopIndex(), ((StringLiteralValue) astNode).getValue());
363 }
364 if (astNode instanceof NumberLiteralValue) {
365 return new LiteralExpressionSegment(context.start.getStartIndex(), context.stop.getStopIndex(), ((NumberLiteralValue) astNode).getValue());
366 }
367 if (astNode instanceof BooleanLiteralValue) {
368 return new LiteralExpressionSegment(context.start.getStartIndex(), context.stop.getStopIndex(), ((BooleanLiteralValue) astNode).getValue());
369 }
370 if (astNode instanceof ParameterMarkerValue) {
371 ParameterMarkerValue parameterMarker = (ParameterMarkerValue) astNode;
372 ParameterMarkerExpressionSegment segment = new ParameterMarkerExpressionSegment(context.start.getStartIndex(), context.stop.getStopIndex(),
373 parameterMarker.getValue(), parameterMarker.getType());
374 parameterMarkerSegments.add(segment);
375 return segment;
376 }
377 if (astNode instanceof SubquerySegment) {
378 return new SubqueryExpressionSegment((SubquerySegment) astNode);
379 }
380 if (astNode instanceof OtherLiteralValue) {
381 return new CommonExpressionSegment(context.getStart().getStartIndex(), context.getStop().getStopIndex(), ((OtherLiteralValue) astNode).getValue());
382 }
383 return astNode;
384 }
385
386 @Override
387 public final ASTNode visitSimpleExpr(final SimpleExprContext ctx) {
388 int startIndex = ctx.getStart().getStartIndex();
389 int stopIndex = ctx.getStop().getStopIndex();
390 if (null != ctx.subquery()) {
391 return new SubquerySegment(startIndex, stopIndex, (SQL92SelectStatement) visit(ctx.subquery()), getOriginalText(ctx.subquery()));
392 }
393 if (null != ctx.parameterMarker()) {
394 ParameterMarkerValue parameterMarker = (ParameterMarkerValue) visit(ctx.parameterMarker());
395 ParameterMarkerExpressionSegment segment = new ParameterMarkerExpressionSegment(startIndex, stopIndex, parameterMarker.getValue(), parameterMarker.getType());
396 parameterMarkerSegments.add(segment);
397 return segment;
398 }
399 if (null != ctx.literals()) {
400 return SQLUtils.createLiteralExpression(visit(ctx.literals()), startIndex, stopIndex, ctx.literals().start.getInputStream().getText(new Interval(startIndex, stopIndex)));
401 }
402 if (null != ctx.functionCall()) {
403 return visit(ctx.functionCall());
404 }
405 if (null != ctx.columnName()) {
406 return visit(ctx.columnName());
407 }
408 return new CommonExpressionSegment(startIndex, stopIndex, ctx.getText());
409 }
410
411 @Override
412 public final ASTNode visitIntervalExpression(final IntervalExpressionContext ctx) {
413 calculateParameterCount(Collections.singleton(ctx.expr()));
414 return new ExpressionProjectionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), getOriginalText(ctx));
415 }
416
417 @Override
418 public final ASTNode visitFunctionCall(final FunctionCallContext ctx) {
419 if (null != ctx.aggregationFunction()) {
420 return visit(ctx.aggregationFunction());
421 }
422 if (null != ctx.specialFunction()) {
423 return visit(ctx.specialFunction());
424 }
425 if (null != ctx.regularFunction()) {
426 return visit(ctx.regularFunction());
427 }
428 throw new IllegalStateException("FunctionCallContext must have aggregationFunction, regularFunction or specialFunction.");
429 }
430
431 @Override
432 public final ASTNode visitAggregationFunction(final AggregationFunctionContext ctx) {
433 String aggregationType = ctx.aggregationFunctionName().getText();
434 return AggregationType.isAggregationType(aggregationType)
435 ? createAggregationSegment(ctx, aggregationType)
436 : new ExpressionProjectionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), getOriginalText(ctx));
437 }
438
439 private ASTNode createAggregationSegment(final AggregationFunctionContext ctx, final String aggregationType) {
440 AggregationType type = AggregationType.valueOf(aggregationType.toUpperCase());
441 if (null != ctx.distinct()) {
442 AggregationDistinctProjectionSegment result =
443 new AggregationDistinctProjectionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), type, getOriginalText(ctx), getDistinctExpression(ctx));
444 result.getParameters().addAll(getExpressions(ctx));
445 return result;
446 }
447 AggregationProjectionSegment result = new AggregationProjectionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), type, getOriginalText(ctx));
448 result.getParameters().addAll(getExpressions(ctx));
449 return result;
450 }
451
452 private Collection<ExpressionSegment> getExpressions(final AggregationFunctionContext ctx) {
453 if (null == ctx.expr()) {
454 return Collections.emptyList();
455 }
456 Collection<ExpressionSegment> result = new LinkedList<>();
457 for (ExprContext each : ctx.expr()) {
458 result.add((ExpressionSegment) visit(each));
459 }
460 return result;
461 }
462
463 private String getDistinctExpression(final AggregationFunctionContext ctx) {
464 StringBuilder result = new StringBuilder();
465 for (int i = 3; i < ctx.getChildCount() - 1; i++) {
466 result.append(ctx.getChild(i).getText());
467 }
468 return result.toString();
469 }
470
471 @Override
472 public final ASTNode visitSpecialFunction(final SpecialFunctionContext ctx) {
473 if (null != ctx.castFunction()) {
474 return visit(ctx.castFunction());
475 }
476 return new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getChild(0).getChild(0).getText(), getOriginalText(ctx));
477 }
478
479 @Override
480 public final ASTNode visitCastFunction(final CastFunctionContext ctx) {
481 calculateParameterCount(Collections.singleton(ctx.expr()));
482 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.CAST().getText(), getOriginalText(ctx));
483 ASTNode exprSegment = visit(ctx.expr());
484 if (exprSegment instanceof ColumnSegment) {
485 result.getParameters().add((ColumnSegment) exprSegment);
486 } else if (exprSegment instanceof LiteralExpressionSegment) {
487 result.getParameters().add((LiteralExpressionSegment) exprSegment);
488 }
489 result.getParameters().add((DataTypeSegment) visit(ctx.dataType()));
490 return result;
491 }
492
493 @Override
494 public final ASTNode visitRegularFunction(final RegularFunctionContext ctx) {
495 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.regularFunctionName().getText(), getOriginalText(ctx));
496 Collection<ExpressionSegment> expressionSegments = ctx.expr().stream().map(each -> (ExpressionSegment) visit(each)).collect(Collectors.toList());
497 result.getParameters().addAll(expressionSegments);
498 return result;
499 }
500
501 @Override
502 public final ASTNode visitDataTypeName(final DataTypeNameContext ctx) {
503 Collection<String> dataTypeNames = new LinkedList<>();
504 for (int i = 0; i < ctx.getChildCount(); i++) {
505 dataTypeNames.add(ctx.getChild(i).getText());
506 }
507 return new KeywordValue(String.join(" ", dataTypeNames));
508 }
509
510
511 private void calculateParameterCount(final Collection<ExprContext> exprContexts) {
512 for (ExprContext each : exprContexts) {
513 visit(each);
514 }
515 }
516
517 @Override
518 public final ASTNode visitOrderByClause(final OrderByClauseContext ctx) {
519 Collection<OrderByItemSegment> items = new LinkedList<>();
520 for (OrderByItemContext each : ctx.orderByItem()) {
521 items.add((OrderByItemSegment) visit(each));
522 }
523 return new OrderBySegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), items);
524 }
525
526 @Override
527 public final ASTNode visitOrderByItem(final OrderByItemContext ctx) {
528 OrderDirection orderDirection = null == ctx.DESC() ? OrderDirection.ASC : OrderDirection.DESC;
529 if (null != ctx.columnName()) {
530 ColumnSegment column = (ColumnSegment) visit(ctx.columnName());
531 return new ColumnOrderByItemSegment(column, orderDirection, null);
532 }
533 return new IndexOrderByItemSegment(ctx.numberLiterals().getStart().getStartIndex(), ctx.numberLiterals().getStop().getStopIndex(),
534 SQLUtils.getExactlyNumber(ctx.numberLiterals().getText(), 10).intValue(), orderDirection, null);
535 }
536
537 @Override
538 public final ASTNode visitDataType(final DataTypeContext ctx) {
539 DataTypeSegment result = new DataTypeSegment();
540 result.setDataTypeName(((KeywordValue) visit(ctx.dataTypeName())).getValue());
541 result.setStartIndex(ctx.start.getStartIndex());
542 result.setStopIndex(ctx.stop.getStopIndex());
543 if (null != ctx.dataTypeLength()) {
544 DataTypeLengthSegment dataTypeLengthSegment = (DataTypeLengthSegment) visit(ctx.dataTypeLength());
545 result.setDataLength(dataTypeLengthSegment);
546 }
547 return result;
548 }
549
550 @Override
551 public final ASTNode visitDataTypeLength(final DataTypeLengthContext ctx) {
552 DataTypeLengthSegment result = new DataTypeLengthSegment();
553 result.setStartIndex(ctx.start.getStartIndex());
554 result.setStopIndex(ctx.stop.getStartIndex());
555 List<TerminalNode> numbers = ctx.NUMBER_();
556 if (numbers.size() == 1) {
557 result.setPrecision(Integer.parseInt(numbers.get(0).getText()));
558 }
559 if (numbers.size() == 2) {
560 result.setPrecision(Integer.parseInt(numbers.get(0).getText()));
561 result.setScale(Integer.parseInt(numbers.get(1).getText()));
562 }
563 return result;
564 }
565
566
567
568
569
570
571
572 protected String getOriginalText(final ParserRuleContext ctx) {
573 return ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
574 }
575 }