This is an automated email from the ASF dual-hosted git repository.

zhangliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new dad1b290908 [Parser][PostgreSQL] Preserve unary NOT as NotExpression 
for scalar-subquery table extraction (#38187)
dad1b290908 is described below

commit dad1b290908e75f0777df73e1c067f8bab9f98ab
Author: ym0506 <[email protected]>
AuthorDate: Thu Feb 26 00:13:45 2026 +0900

    [Parser][PostgreSQL] Preserve unary NOT as NotExpression for 
scalar-subquery table extraction (#38187)
    
    * [Parser][PostgreSQL] Handle unary NOT as NotExpression in AExpr
    
    Fixes #37770.
    
    PostgreSQL visitor could parse unary NOT expression in scalar-subquery form 
as CommonExpressionSegment, which prevents recursive table extraction for inner 
subquery tables.
    
    This can skip sharding table rewrite and send logical names (for example 
t23/t22) to backend.
    
    Add explicit unary NOT handling in visitAExpr and a regression test for the 
reported SQL shape.
    
    * [Parser][PostgreSQL] Avoid static Matcher import in visitor test
    
    * [Parser][PostgreSQL] Limit unary NOT handling to NOT aExpr
---
 .../statement/PostgreSQLStatementVisitor.java      |  4 ++
 .../statement/PostgreSQLStatementVisitorTest.java  | 52 ++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git 
a/parser/sql/engine/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
 
b/parser/sql/engine/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
index 76014f3b6b2..c4cb6799556 100644
--- 
a/parser/sql/engine/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
+++ 
b/parser/sql/engine/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
@@ -145,6 +145,7 @@ import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.Extr
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.FunctionSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.InExpression;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ListExpression;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.NotExpression;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.TypeCastExpression;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.complex.CommonExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.complex.CommonTableExpressionSegment;
@@ -325,6 +326,9 @@ public abstract class PostgreSQLStatementVisitor extends 
PostgreSQLStatementPars
         if (null != ctx.patternMatchingOperator()) {
             return createPatternMatchingOperationSegment(ctx);
         }
+        if (null != ctx.NOT() && null == ctx.IS() && 1 == ctx.aExpr().size()) {
+            return new NotExpression(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), (ExpressionSegment) visit(ctx.aExpr(0)), false);
+        }
         Optional<String> binaryOperator = findBinaryOperator(ctx);
         if (binaryOperator.isPresent()) {
             return createBinaryOperationSegment(ctx, binaryOperator.get());
diff --git 
a/parser/sql/engine/dialect/postgresql/src/test/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitorTest.java
 
b/parser/sql/engine/dialect/postgresql/src/test/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitorTest.java
new file mode 100644
index 00000000000..98de69063d0
--- /dev/null
+++ 
b/parser/sql/engine/dialect/postgresql/src/test/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitorTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 
org.apache.shardingsphere.sql.parser.engine.postgresql.visitor.statement;
+
+import org.apache.shardingsphere.sql.parser.engine.api.CacheOption;
+import org.apache.shardingsphere.sql.parser.engine.api.SQLParserEngine;
+import 
org.apache.shardingsphere.sql.parser.engine.api.SQLStatementVisitorEngine;
+import org.apache.shardingsphere.sql.parser.engine.core.ParseASTNode;
+import 
org.apache.shardingsphere.sql.parser.statement.core.extractor.TableExtractor;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.NotExpression;
+import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class PostgreSQLStatementVisitorTest {
+    
+    @Test
+    void assertVisitUnaryNotWithScalarSubquery() {
+        String sql = "select 1 from t17 as ref_0 where not ((ref_0.c59) < 
(select ref_1.c36 as c_0 from t23 as ref_1 join t22 as ref_2 "
+                + "on(ref_1.colocated_key = ref_2.colocated_key)))";
+        ParseASTNode parseASTNode = new SQLParserEngine("PostgreSQL", new 
CacheOption(128, 1024L)).parse(sql, false);
+        SelectStatement statement = (SelectStatement) new 
SQLStatementVisitorEngine("PostgreSQL").visit(parseASTNode);
+        assertTrue(statement.getWhere().isPresent());
+        assertThat(statement.getWhere().get().getExpr(), 
Matchers.instanceOf(NotExpression.class));
+        TableExtractor tableExtractor = new TableExtractor();
+        tableExtractor.extractTablesFromSelect(statement);
+        Collection<String> rewriteTableNames = 
tableExtractor.getRewriteTables().stream()
+                .map(each -> 
each.getTableName().getIdentifier().getValue()).collect(Collectors.toList());
+        assertThat(rewriteTableNames, Matchers.hasItems("t17", "t23", "t22"));
+    }
+}

Reply via email to