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.statement.core.enums.AggregationType;
61 import org.apache.shardingsphere.sql.parser.statement.core.enums.OrderDirection;
62 import org.apache.shardingsphere.sql.parser.statement.core.enums.ParameterMarkerType;
63 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
64 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BetweenExpression;
65 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression;
66 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
67 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.FunctionSegment;
68 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.InExpression;
69 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ListExpression;
70 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.NotExpression;
71 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.complex.CommonExpressionSegment;
72 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.LiteralExpressionSegment;
73 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
74 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubqueryExpressionSegment;
75 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment;
76 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.AggregationDistinctProjectionSegment;
77 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.AggregationProjectionSegment;
78 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ExpressionProjectionSegment;
79 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.OrderBySegment;
80 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.ColumnOrderByItemSegment;
81 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.IndexOrderByItemSegment;
82 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.OrderByItemSegment;
83 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.DataTypeLengthSegment;
84 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.DataTypeSegment;
85 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.OwnerSegment;
86 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.ParameterMarkerSegment;
87 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
88 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableNameSegment;
89 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
90 import org.apache.shardingsphere.sql.parser.statement.core.util.SQLUtils;
91 import org.apache.shardingsphere.sql.parser.statement.core.value.collection.CollectionValue;
92 import org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
93 import org.apache.shardingsphere.sql.parser.statement.core.value.keyword.KeywordValue;
94 import org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.BooleanLiteralValue;
95 import org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.NullLiteralValue;
96 import org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.NumberLiteralValue;
97 import org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.OtherLiteralValue;
98 import org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.StringLiteralValue;
99 import org.apache.shardingsphere.sql.parser.statement.core.value.parametermarker.ParameterMarkerValue;
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 + ctx.start.getInputStream().getText(new Interval(ctx.NOT().getSymbol().getStartIndex(), ctx.NOT().getSymbol().getStopIndex())) + " ";
259 }
260 Token operatorToken = null;
261 if (null != ctx.NULL()) {
262 operatorToken = ctx.NULL().getSymbol();
263 }
264 if (null != ctx.TRUE()) {
265 operatorToken = ctx.TRUE().getSymbol();
266 }
267 if (null != ctx.FALSE()) {
268 operatorToken = ctx.FALSE().getSymbol();
269 }
270 int startIndex = null == operatorToken ? ctx.IS().getSymbol().getStopIndex() + 2 : operatorToken.getStartIndex();
271 rightText = rightText + ctx.start.getInputStream().getText(new Interval(startIndex, ctx.stop.getStopIndex()));
272 ExpressionSegment right = new LiteralExpressionSegment(ctx.IS().getSymbol().getStopIndex() + 2, ctx.stop.getStopIndex(), rightText);
273 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
274 ExpressionSegment left = (ExpressionSegment) visit(ctx.booleanPrimary());
275 String operator = "IS";
276 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
277 }
278 if (null != ctx.comparisonOperator() || null != ctx.SAFE_EQ_()) {
279 return createCompareSegment(ctx);
280 }
281 return visit(ctx.predicate());
282 }
283
284 private ASTNode createCompareSegment(final BooleanPrimaryContext ctx) {
285 ExpressionSegment left = (ExpressionSegment) visit(ctx.booleanPrimary());
286 ExpressionSegment right;
287 if (null != ctx.predicate()) {
288 right = (ExpressionSegment) visit(ctx.predicate());
289 } else {
290 right = (ExpressionSegment) visit(ctx.subquery());
291 }
292 String operator = null == ctx.SAFE_EQ_() ? ctx.comparisonOperator().getText() : ctx.SAFE_EQ_().getText();
293 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
294 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
295 }
296
297 @Override
298 public final ASTNode visitPredicate(final PredicateContext ctx) {
299 if (null != ctx.IN()) {
300 return createInSegment(ctx);
301 }
302 if (null != ctx.BETWEEN()) {
303 return createBetweenSegment(ctx);
304 }
305 if (null != ctx.LIKE()) {
306 return createBinaryOperationExpressionFromLike(ctx);
307 }
308 return visit(ctx.bitExpr(0));
309 }
310
311 private BinaryOperationExpression createBinaryOperationExpressionFromLike(final PredicateContext ctx) {
312 ExpressionSegment left = (ExpressionSegment) visit(ctx.bitExpr(0));
313 ListExpression right = new ListExpression(ctx.simpleExpr(0).start.getStartIndex(), ctx.simpleExpr().get(ctx.simpleExpr().size() - 1).stop.getStopIndex());
314 for (SimpleExprContext each : ctx.simpleExpr()) {
315 right.getItems().add((ExpressionSegment) visit(each));
316 }
317 String operator = null == ctx.NOT() ? "LIKE" : "NOT LIKE";
318 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
319 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
320 }
321
322 private InExpression createInSegment(final PredicateContext ctx) {
323 ExpressionSegment left = (ExpressionSegment) visit(ctx.bitExpr(0));
324 ExpressionSegment right;
325 if (null != ctx.subquery()) {
326 right = new SubqueryExpressionSegment(new SubquerySegment(ctx.subquery().start.getStartIndex(), ctx.subquery().stop.getStopIndex(), (SelectStatement) visit(ctx.subquery()),
327 getOriginalText(ctx.subquery())));
328 } else {
329 ListExpression listExpression = new ListExpression(ctx.LP_().getSymbol().getStartIndex(), ctx.RP_().getSymbol().getStopIndex());
330 for (ExprContext each : ctx.expr()) {
331 listExpression.getItems().add((ExpressionSegment) visit(each));
332 }
333 right = listExpression;
334 }
335 boolean not = null != ctx.NOT();
336 return new InExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, not);
337 }
338
339 private BetweenExpression createBetweenSegment(final PredicateContext ctx) {
340 ExpressionSegment left = (ExpressionSegment) visit(ctx.bitExpr(0));
341 ExpressionSegment between = (ExpressionSegment) visit(ctx.bitExpr(1));
342 ExpressionSegment and = (ExpressionSegment) visit(ctx.predicate());
343 boolean not = null != ctx.NOT();
344 return new BetweenExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, between, and, not);
345 }
346
347 @Override
348 public final ASTNode visitBitExpr(final BitExprContext ctx) {
349 if (null != ctx.simpleExpr()) {
350 return createExpressionSegment(visit(ctx.simpleExpr()), ctx);
351 }
352 ExpressionSegment left = (ExpressionSegment) visit(ctx.getChild(0));
353 ExpressionSegment right = (ExpressionSegment) visit(ctx.getChild(2));
354 String operator = ctx.getChild(1).getText();
355 String text = ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
356 return new BinaryOperationExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), left, right, operator, text);
357 }
358
359 private ASTNode createExpressionSegment(final ASTNode astNode, final ParserRuleContext context) {
360 if (astNode instanceof StringLiteralValue) {
361 return new LiteralExpressionSegment(context.start.getStartIndex(), context.stop.getStopIndex(), ((StringLiteralValue) astNode).getValue());
362 }
363 if (astNode instanceof NumberLiteralValue) {
364 return new LiteralExpressionSegment(context.start.getStartIndex(), context.stop.getStopIndex(), ((NumberLiteralValue) astNode).getValue());
365 }
366 if (astNode instanceof BooleanLiteralValue) {
367 return new LiteralExpressionSegment(context.start.getStartIndex(), context.stop.getStopIndex(), ((BooleanLiteralValue) astNode).getValue());
368 }
369 if (astNode instanceof ParameterMarkerValue) {
370 ParameterMarkerValue parameterMarker = (ParameterMarkerValue) astNode;
371 ParameterMarkerExpressionSegment segment = new ParameterMarkerExpressionSegment(context.start.getStartIndex(), context.stop.getStopIndex(),
372 parameterMarker.getValue(), parameterMarker.getType());
373 parameterMarkerSegments.add(segment);
374 return segment;
375 }
376 if (astNode instanceof SubquerySegment) {
377 return new SubqueryExpressionSegment((SubquerySegment) astNode);
378 }
379 if (astNode instanceof OtherLiteralValue) {
380 return new CommonExpressionSegment(context.getStart().getStartIndex(), context.getStop().getStopIndex(), ((OtherLiteralValue) astNode).getValue());
381 }
382 return astNode;
383 }
384
385 @Override
386 public final ASTNode visitSimpleExpr(final SimpleExprContext ctx) {
387 int startIndex = ctx.getStart().getStartIndex();
388 int stopIndex = ctx.getStop().getStopIndex();
389 if (null != ctx.subquery()) {
390 return new SubquerySegment(startIndex, stopIndex, (SelectStatement) visit(ctx.subquery()), getOriginalText(ctx.subquery()));
391 }
392 if (null != ctx.parameterMarker()) {
393 ParameterMarkerValue parameterMarker = (ParameterMarkerValue) visit(ctx.parameterMarker());
394 ParameterMarkerExpressionSegment segment = new ParameterMarkerExpressionSegment(startIndex, stopIndex, parameterMarker.getValue(), parameterMarker.getType());
395 parameterMarkerSegments.add(segment);
396 return segment;
397 }
398 if (null != ctx.literals()) {
399 return SQLUtils.createLiteralExpression(visit(ctx.literals()), startIndex, stopIndex, ctx.literals().start.getInputStream().getText(new Interval(startIndex, stopIndex)));
400 }
401 if (null != ctx.functionCall()) {
402 return visit(ctx.functionCall());
403 }
404 if (null != ctx.columnName()) {
405 return visit(ctx.columnName());
406 }
407 return new CommonExpressionSegment(startIndex, stopIndex, ctx.getText());
408 }
409
410 @Override
411 public final ASTNode visitIntervalExpression(final IntervalExpressionContext ctx) {
412 calculateParameterCount(Collections.singleton(ctx.expr()));
413 return new ExpressionProjectionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), getOriginalText(ctx));
414 }
415
416 @Override
417 public final ASTNode visitFunctionCall(final FunctionCallContext ctx) {
418 if (null != ctx.aggregationFunction()) {
419 return visit(ctx.aggregationFunction());
420 }
421 if (null != ctx.specialFunction()) {
422 return visit(ctx.specialFunction());
423 }
424 if (null != ctx.regularFunction()) {
425 return visit(ctx.regularFunction());
426 }
427 throw new IllegalStateException("FunctionCallContext must have aggregationFunction, regularFunction or specialFunction.");
428 }
429
430 @Override
431 public final ASTNode visitAggregationFunction(final AggregationFunctionContext ctx) {
432 String aggregationType = ctx.aggregationFunctionName().getText();
433 return AggregationType.isAggregationType(aggregationType)
434 ? createAggregationSegment(ctx, aggregationType)
435 : new ExpressionProjectionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), getOriginalText(ctx));
436 }
437
438 private ASTNode createAggregationSegment(final AggregationFunctionContext ctx, final String aggregationType) {
439 AggregationType type = AggregationType.valueOf(aggregationType.toUpperCase());
440 if (null != ctx.distinct()) {
441 AggregationDistinctProjectionSegment result =
442 new AggregationDistinctProjectionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), type, getOriginalText(ctx), getDistinctExpression(ctx));
443 result.getParameters().addAll(getExpressions(ctx));
444 return result;
445 }
446 AggregationProjectionSegment result = new AggregationProjectionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), type, getOriginalText(ctx));
447 result.getParameters().addAll(getExpressions(ctx));
448 return result;
449 }
450
451 private Collection<ExpressionSegment> getExpressions(final AggregationFunctionContext ctx) {
452 if (null == ctx.expr()) {
453 return Collections.emptyList();
454 }
455 Collection<ExpressionSegment> result = new LinkedList<>();
456 for (ExprContext each : ctx.expr()) {
457 result.add((ExpressionSegment) visit(each));
458 }
459 return result;
460 }
461
462 private String getDistinctExpression(final AggregationFunctionContext ctx) {
463 StringBuilder result = new StringBuilder();
464 for (int i = 3; i < ctx.getChildCount() - 1; i++) {
465 result.append(ctx.getChild(i).getText());
466 }
467 return result.toString();
468 }
469
470 @Override
471 public final ASTNode visitSpecialFunction(final SpecialFunctionContext ctx) {
472 if (null != ctx.castFunction()) {
473 return visit(ctx.castFunction());
474 }
475 return new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getChild(0).getChild(0).getText(), getOriginalText(ctx));
476 }
477
478 @Override
479 public final ASTNode visitCastFunction(final CastFunctionContext ctx) {
480 calculateParameterCount(Collections.singleton(ctx.expr()));
481 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.CAST().getText(), getOriginalText(ctx));
482 ASTNode exprSegment = visit(ctx.expr());
483 if (exprSegment instanceof ColumnSegment) {
484 result.getParameters().add((ColumnSegment) exprSegment);
485 } else if (exprSegment instanceof LiteralExpressionSegment) {
486 result.getParameters().add((LiteralExpressionSegment) exprSegment);
487 }
488 result.getParameters().add((DataTypeSegment) visit(ctx.dataType()));
489 return result;
490 }
491
492 @Override
493 public final ASTNode visitRegularFunction(final RegularFunctionContext ctx) {
494 FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.regularFunctionName().getText(), getOriginalText(ctx));
495 Collection<ExpressionSegment> expressionSegments = ctx.expr().stream().map(each -> (ExpressionSegment) visit(each)).collect(Collectors.toList());
496 result.getParameters().addAll(expressionSegments);
497 return result;
498 }
499
500 @Override
501 public final ASTNode visitDataTypeName(final DataTypeNameContext ctx) {
502 Collection<String> dataTypeNames = new LinkedList<>();
503 for (int i = 0; i < ctx.getChildCount(); i++) {
504 dataTypeNames.add(ctx.getChild(i).getText());
505 }
506 return new KeywordValue(String.join(" ", dataTypeNames));
507 }
508
509
510 private void calculateParameterCount(final Collection<ExprContext> exprContexts) {
511 for (ExprContext each : exprContexts) {
512 visit(each);
513 }
514 }
515
516 @Override
517 public final ASTNode visitOrderByClause(final OrderByClauseContext ctx) {
518 Collection<OrderByItemSegment> items = new LinkedList<>();
519 for (OrderByItemContext each : ctx.orderByItem()) {
520 items.add((OrderByItemSegment) visit(each));
521 }
522 return new OrderBySegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), items);
523 }
524
525 @Override
526 public final ASTNode visitOrderByItem(final OrderByItemContext ctx) {
527 OrderDirection orderDirection = null == ctx.DESC() ? OrderDirection.ASC : OrderDirection.DESC;
528 if (null != ctx.columnName()) {
529 ColumnSegment column = (ColumnSegment) visit(ctx.columnName());
530 return new ColumnOrderByItemSegment(column, orderDirection, null);
531 }
532 return new IndexOrderByItemSegment(ctx.numberLiterals().getStart().getStartIndex(), ctx.numberLiterals().getStop().getStopIndex(),
533 SQLUtils.getExactlyNumber(ctx.numberLiterals().getText(), 10).intValue(), orderDirection, null);
534 }
535
536 @Override
537 public final ASTNode visitDataType(final DataTypeContext ctx) {
538 DataTypeSegment result = new DataTypeSegment();
539 result.setDataTypeName(((KeywordValue) visit(ctx.dataTypeName())).getValue());
540 result.setStartIndex(ctx.start.getStartIndex());
541 result.setStopIndex(ctx.stop.getStopIndex());
542 if (null != ctx.dataTypeLength()) {
543 DataTypeLengthSegment dataTypeLengthSegment = (DataTypeLengthSegment) visit(ctx.dataTypeLength());
544 result.setDataLength(dataTypeLengthSegment);
545 }
546 return result;
547 }
548
549 @Override
550 public final ASTNode visitDataTypeLength(final DataTypeLengthContext ctx) {
551 DataTypeLengthSegment result = new DataTypeLengthSegment();
552 result.setStartIndex(ctx.start.getStartIndex());
553 result.setStopIndex(ctx.stop.getStartIndex());
554 List<TerminalNode> numbers = ctx.NUMBER_();
555 if (numbers.size() == 1) {
556 result.setPrecision(Integer.parseInt(numbers.get(0).getText()));
557 }
558 if (numbers.size() == 2) {
559 result.setPrecision(Integer.parseInt(numbers.get(0).getText()));
560 result.setScale(Integer.parseInt(numbers.get(1).getText()));
561 }
562 return result;
563 }
564
565
566
567
568
569
570
571 protected String getOriginalText(final ParserRuleContext ctx) {
572 return ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex()));
573 }
574 }