Skip to content

Commit 4ce37f5

Browse files
authored
Support '2'::int statement in PostgreSQL and openGauss (#37962)
* support new function * realese-notes * npe * npe * support Expression * support new function * update code * update code
1 parent ad8ffb3 commit 4ce37f5

13 files changed

Lines changed: 450 additions & 42 deletions

File tree

RELEASE-NOTES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
2. SQL Parser: Fix escape '\' in SQL causing DialectSQLParsingException - [#37943](https://github.com/apache/shardingsphere/pull/37943)
1111
3. SQL Parser: Fix error parsing \l command SQL statement when front-end protocol is og - [#37953](https://github.com/apache/shardingsphere/pull/37953)
1212
4. SQL Parser:Fix SQLParsingException when using reserved word `order` in ORDER BY clause - [#37958](https://github.com/apache/shardingsphere/pull/37958)
13+
5. SQL Parser:Support '2'::int statement in PostgreSQL and openGauss - [#37962](https://github.com/apache/shardingsphere/pull/37962)
1314

1415
## Release 5.5.3
1516

infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/PaginationContext.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,15 @@
1919

2020
import lombok.Getter;
2121
import org.apache.shardingsphere.infra.binder.context.statement.type.dml.SelectStatementContext;
22+
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression;
23+
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.CaseWhenExpression;
24+
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
25+
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.LiteralExpressionSegment;
26+
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
2227
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.NumberLiteralPaginationValueSegment;
2328
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.PaginationValueSegment;
2429
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.ParameterMarkerPaginationValueSegment;
30+
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.ExpressionPaginationValueSegment;
2531
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitValueSegment;
2632
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.rownum.ExpressionRowNumberValueSegment;
2733

@@ -63,9 +69,74 @@ private Long getValue(final PaginationValueSegment paginationValueSegment, final
6369
if (paginationValueSegment instanceof ExpressionRowNumberValueSegment) {
6470
return ((ExpressionRowNumberValueSegment) paginationValueSegment).getValue(params);
6571
}
72+
if (paginationValueSegment instanceof ExpressionPaginationValueSegment) {
73+
Long result = getValueFromExpression(((ExpressionPaginationValueSegment) paginationValueSegment).getExpression(), params);
74+
return result;
75+
}
6676
return ((NumberLiteralPaginationValueSegment) paginationValueSegment).getValue();
6777
}
6878

79+
private Long getValueFromExpression(final ExpressionSegment expressionSegment, final List<Object> params) {
80+
if (expressionSegment instanceof BinaryOperationExpression) {
81+
return getValueFromBinaryOperationExpression((BinaryOperationExpression) expressionSegment, params);
82+
}
83+
if (expressionSegment instanceof CaseWhenExpression) {
84+
return getValueFromCaseWhenExpression((CaseWhenExpression) expressionSegment, params);
85+
}
86+
return null;
87+
}
88+
89+
private Long getValueFromBinaryOperationExpression(final BinaryOperationExpression binaryOperationExpression, final List<Object> params) {
90+
Long left = getValueFromExpression(binaryOperationExpression.getLeft(), params);
91+
Long right = getValueFromExpression(binaryOperationExpression.getRight(), params);
92+
if (null == left || null == right) {
93+
return null;
94+
}
95+
switch (binaryOperationExpression.getOperator()) {
96+
case "+":
97+
return left + right;
98+
case "-":
99+
return left - right;
100+
case "*":
101+
return left * right;
102+
case "/":
103+
return 0L == right ? null : left / right;
104+
default:
105+
return null;
106+
}
107+
}
108+
109+
private Long getValueFromCaseWhenExpression(final CaseWhenExpression caseWhenExpression, final List<Object> params) {
110+
if (null != caseWhenExpression.getCaseExpr()) {
111+
return null;
112+
}
113+
java.util.Iterator<ExpressionSegment> whenIterator = caseWhenExpression.getWhenExprs().iterator();
114+
java.util.Iterator<ExpressionSegment> thenIterator = caseWhenExpression.getThenExprs().iterator();
115+
while (whenIterator.hasNext() && thenIterator.hasNext()) {
116+
Boolean whenValue = getBooleanValueFromExpression(whenIterator.next(), params);
117+
if (Boolean.TRUE.equals(whenValue)) {
118+
return getValueFromExpression(thenIterator.next(), params);
119+
}
120+
thenIterator.next();
121+
}
122+
return null == caseWhenExpression.getElseExpr() ? null : getValueFromExpression(caseWhenExpression.getElseExpr(), params);
123+
}
124+
125+
private Boolean getBooleanValueFromExpression(final ExpressionSegment expressionSegment, final List<Object> params) {
126+
if (expressionSegment instanceof LiteralExpressionSegment) {
127+
Object literals = ((LiteralExpressionSegment) expressionSegment).getLiterals();
128+
if (literals instanceof Boolean) {
129+
return (Boolean) literals;
130+
}
131+
return null == literals ? null : Boolean.parseBoolean(literals.toString());
132+
}
133+
if (expressionSegment instanceof ParameterMarkerExpressionSegment) {
134+
Object obj = null == params || params.isEmpty() ? null : params.get(((ParameterMarkerExpressionSegment) expressionSegment).getParameterMarkerIndex());
135+
return null == obj ? null : Boolean.parseBoolean(obj.toString());
136+
}
137+
return null;
138+
}
139+
69140
/**
70141
* Get offset segment.
71142
*

kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/limit/PaginationValueSQLConverter.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323
import org.apache.calcite.sql.SqlLiteral;
2424
import org.apache.calcite.sql.SqlNode;
2525
import org.apache.calcite.sql.parser.SqlParserPos;
26+
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.ExpressionPaginationValueSegment;
2627
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.NumberLiteralPaginationValueSegment;
2728
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.PaginationValueSegment;
2829
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.ParameterMarkerLimitValueSegment;
30+
import org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.ExpressionConverter;
2931

3032
import java.util.Optional;
3133

@@ -42,9 +44,13 @@ public final class PaginationValueSQLConverter {
4244
* @return SQL node
4345
*/
4446
public static Optional<SqlNode> convert(final PaginationValueSegment segment) {
45-
return Optional.of(segment instanceof NumberLiteralPaginationValueSegment
46-
? getLiteralSQLNode((NumberLiteralPaginationValueSegment) segment)
47-
: getParameterMarkerSQLNode((ParameterMarkerLimitValueSegment) segment));
47+
if (segment instanceof NumberLiteralPaginationValueSegment) {
48+
return Optional.of(getLiteralSQLNode((NumberLiteralPaginationValueSegment) segment));
49+
}
50+
if (segment instanceof ExpressionPaginationValueSegment) {
51+
return ExpressionConverter.convert(((ExpressionPaginationValueSegment) segment).getExpression());
52+
}
53+
return Optional.of(getParameterMarkerSQLNode((ParameterMarkerLimitValueSegment) segment));
4854
}
4955

5056
private static SqlNode getLiteralSQLNode(final NumberLiteralPaginationValueSegment segment) {

parser/sql/engine/dialect/opengauss/src/main/antlr4/imports/opengauss/DMLStatement.g4

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,15 +231,15 @@ offsetClause
231231

232232
selectLimitValue
233233
: ALL
234-
| cExpr
234+
| aExpr
235235
;
236236

237237
selectOffsetValue
238-
: cExpr
238+
: aExpr
239239
;
240240

241241
selectFetchValue
242-
: cExpr
242+
: aExpr
243243
;
244244

245245
rowOrRows

parser/sql/engine/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/engine/opengauss/visitor/statement/OpenGaussStatementVisitor.java

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.OrderByItemSegment;
168168
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitSegment;
169169
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitValueSegment;
170+
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.ExpressionLimitValueSegment;
170171
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.NumberLiteralLimitValueSegment;
171172
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.ParameterMarkerLimitValueSegment;
172173
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.HavingSegment;
@@ -444,7 +445,7 @@ public ASTNode visitCaseExpr(final CaseExprContext ctx) {
444445
}
445446
ExpressionSegment caseExpr = null == ctx.caseArg() ? null : (ExpressionSegment) visit(ctx.caseArg().aExpr());
446447
ExpressionSegment elseExpr = null == ctx.caseDefault() ? null : (ExpressionSegment) visit(ctx.caseDefault().aExpr());
447-
return new CaseWhenExpression(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), caseExpr, whenExprs, thenExprs, elseExpr);
448+
return new CaseWhenExpression(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), caseExpr, whenExprs, thenExprs, elseExpr, getOriginalText(ctx));
448449
}
449450

450451
@Override
@@ -1393,29 +1394,37 @@ public ASTNode visitSelectLimitValue(final SelectLimitValueContext ctx) {
13931394
if (null != ctx.ALL()) {
13941395
return null;
13951396
}
1396-
ASTNode astNode = visit(ctx.cExpr());
1397-
if (astNode instanceof ParameterMarkerExpressionSegment) {
1398-
return new ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) astNode).getParameterMarkerIndex());
1399-
}
1400-
return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), Long.parseLong(((ExpressionSegment) astNode).getText()));
1397+
return createLimitValueSegment(ctx, (ExpressionSegment) visit(ctx.aExpr()));
14011398
}
14021399

14031400
@Override
14041401
public ASTNode visitSelectOffsetValue(final SelectOffsetValueContext ctx) {
1405-
ASTNode astNode = visit(ctx.cExpr());
1406-
if (astNode instanceof ParameterMarkerExpressionSegment) {
1407-
return new ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) astNode).getParameterMarkerIndex());
1408-
}
1409-
return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), Long.parseLong(((ExpressionSegment) astNode).getText()));
1402+
return createLimitValueSegment(ctx, (ExpressionSegment) visit(ctx.aExpr()));
14101403
}
14111404

14121405
@Override
14131406
public ASTNode visitSelectFetchValue(final SelectFetchValueContext ctx) {
1414-
ASTNode astNode = visit(ctx.cExpr());
1415-
if (astNode instanceof ParameterMarkerExpressionSegment) {
1416-
return new ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) astNode).getParameterMarkerIndex());
1407+
return createLimitValueSegment(ctx, (ExpressionSegment) visit(ctx.aExpr()));
1408+
}
1409+
1410+
private LimitValueSegment createLimitValueSegment(final ParserRuleContext ctx, final ExpressionSegment segment) {
1411+
if (segment instanceof ParameterMarkerExpressionSegment) {
1412+
return new ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(),
1413+
((ParameterMarkerExpressionSegment) segment).getParameterMarkerIndex());
1414+
}
1415+
if (segment instanceof TypeCastExpression) {
1416+
return createLimitValueSegment(ctx, ((TypeCastExpression) segment).getExpression());
1417+
}
1418+
if (segment instanceof LiteralExpressionSegment) {
1419+
Object literals = ((LiteralExpressionSegment) segment).getLiterals();
1420+
if (null == literals) {
1421+
return ctx instanceof SelectOffsetValueContext
1422+
? new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), 0L)
1423+
: null;
1424+
}
1425+
return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), Long.parseLong(literals.toString()));
14171426
}
1418-
return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), Long.parseLong(((ExpressionSegment) astNode).getText()));
1427+
return new ExpressionLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), segment);
14191428
}
14201429

14211430
private LimitSegment createLimitSegmentWhenLimitAndOffset(final SelectLimitContext ctx) {

parser/sql/engine/dialect/postgresql/src/main/antlr4/imports/postgresql/DMLStatement.g4

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,16 +233,16 @@ offsetClause
233233
;
234234

235235
selectLimitValue
236-
: cExpr
236+
: aExpr
237237
| ALL
238238
;
239239

240240
selectOffsetValue
241-
: cExpr
241+
: aExpr
242242
;
243243

244244
selectFetchValue
245-
: cExpr
245+
: aExpr
246246
;
247247

248248
rowOrRows

parser/sql/engine/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitor.java

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@
168168
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.OrderByItemSegment;
169169
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitSegment;
170170
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitValueSegment;
171+
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.ExpressionLimitValueSegment;
171172
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.NumberLiteralLimitValueSegment;
172173
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.ParameterMarkerLimitValueSegment;
173174
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.HavingSegment;
@@ -445,7 +446,7 @@ public ASTNode visitCaseExpr(final CaseExprContext ctx) {
445446
}
446447
ExpressionSegment caseExpr = null == ctx.caseArg() ? null : (ExpressionSegment) visit(ctx.caseArg().aExpr());
447448
ExpressionSegment elseExpr = null == ctx.caseDefault() ? null : (ExpressionSegment) visit(ctx.caseDefault().aExpr());
448-
return new CaseWhenExpression(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), caseExpr, whenExprs, thenExprs, elseExpr);
449+
return new CaseWhenExpression(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), caseExpr, whenExprs, thenExprs, elseExpr, getOriginalText(ctx));
449450
}
450451

451452
@Override
@@ -1361,32 +1362,34 @@ public ASTNode visitSelectLimitValue(final SelectLimitValueContext ctx) {
13611362
if (null != ctx.ALL()) {
13621363
return null;
13631364
}
1364-
ASTNode astNode = visit(ctx.cExpr());
1365-
if (astNode instanceof ParameterMarkerExpressionSegment) {
1366-
return new ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) astNode).getParameterMarkerIndex());
1367-
}
1368-
return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(),
1369-
(null == ((ExpressionSegment) astNode).getText()) ? null : Long.parseLong(((ExpressionSegment) astNode).getText()));
1365+
return createLimitValueSegment(ctx, (ExpressionSegment) visit(ctx.aExpr()));
13701366
}
13711367

13721368
@Override
13731369
public ASTNode visitSelectOffsetValue(final SelectOffsetValueContext ctx) {
1374-
ASTNode astNode = visit(ctx.cExpr());
1375-
if (astNode instanceof ParameterMarkerExpressionSegment) {
1376-
return new ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) astNode).getParameterMarkerIndex());
1377-
}
1378-
return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(),
1379-
(null == ((ExpressionSegment) astNode).getText()) ? null : Long.parseLong(((ExpressionSegment) astNode).getText()));
1370+
return createLimitValueSegment(ctx, (ExpressionSegment) visit(ctx.aExpr()));
13801371
}
13811372

13821373
@Override
13831374
public ASTNode visitSelectFetchValue(final SelectFetchValueContext ctx) {
1384-
ASTNode astNode = visit(ctx.cExpr());
1385-
if (astNode instanceof ParameterMarkerExpressionSegment) {
1386-
return new ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) astNode).getParameterMarkerIndex());
1375+
return createLimitValueSegment(ctx, (ExpressionSegment) visit(ctx.aExpr()));
1376+
}
1377+
1378+
private LimitValueSegment createLimitValueSegment(final ParserRuleContext ctx, final ExpressionSegment segment) {
1379+
if (segment instanceof ParameterMarkerExpressionSegment) {
1380+
return new ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) segment).getParameterMarkerIndex());
1381+
}
1382+
if (segment instanceof TypeCastExpression) {
1383+
return createLimitValueSegment(ctx, ((TypeCastExpression) segment).getExpression());
1384+
}
1385+
if (segment instanceof LiteralExpressionSegment) {
1386+
Object literals = ((LiteralExpressionSegment) segment).getLiterals();
1387+
if (null == literals) {
1388+
return ctx instanceof SelectOffsetValueContext ? new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), 0L) : null;
1389+
}
1390+
return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), Long.parseLong(literals.toString()));
13871391
}
1388-
return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(),
1389-
(null == ((ExpressionSegment) astNode).getText()) ? null : Long.parseLong(((ExpressionSegment) astNode).getText()));
1392+
return new ExpressionLimitValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), segment);
13901393
}
13911394

13921395
private LimitSegment createLimitSegmentWhenLimitAndOffset(final SelectLimitContext ctx) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination;
19+
20+
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
21+
22+
/**
23+
* Pagination value segment for expression.
24+
*/
25+
public interface ExpressionPaginationValueSegment extends PaginationValueSegment {
26+
27+
/**
28+
* Get expression segment.
29+
*
30+
* @return expression segment
31+
*/
32+
ExpressionSegment getExpression();
33+
}

0 commit comments

Comments
 (0)