From 18d687281093d80e98254ae2fe6e56592df0d4d3 Mon Sep 17 00:00:00 2001
From: bantao <bantao@foxmail.com>
Date: Tue, 23 Apr 2024 17:25:22 +0800
Subject: [PATCH] fix oracle window between dialect error

Signed-off-by: bantao <bantao@foxmail.com>
---
 .../oracle/parser/OracleExprParser.java       |  4 ++
 .../oracle/visitor/OracleOutputVisitor.java   |  3 ++
 .../oracle/select/OracleSelectTest124.java    | 39 +++++++++++++++++++
 3 files changed, 46 insertions(+)

diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java b/core/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java
index 059e4a17e2..6452404ea1 100644
--- a/core/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java
+++ b/core/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java
@@ -928,6 +928,10 @@ protected SQLAggregateExpr parseAggregateExpr(String methodName) {
                             endExpr = relational();
                         }
 
+                        final SQLOver.WindowingBound endBound = parseWindowingBound();
+                        if (endBound != null) {
+                            over.setWindowingBetweenEndBound(endBound);
+                        }
                         SQLExpr expr = new SQLBetweenExpr(null, beginExpr, endExpr);
                         windowing.setExpr(expr);
                     } else {
diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java
index aa922efda4..9045a1eca8 100644
--- a/core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java
+++ b/core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java
@@ -99,6 +99,9 @@ public boolean visit(OracleAnalytic x) {
         if (x.isWindowingPreceding()) {
             print0(ucase ? " PRECEDING" : " preceding");
         }
+        if (x.isWindowingBetweenEndFollowing()) {
+            print0(ucase ? " FOLLOWING" : " following");
+        }
 
         print(')');
 
diff --git a/core/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest124.java b/core/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest124.java
index 83362f2dd8..1c0e05a35a 100644
--- a/core/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest124.java
+++ b/core/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest124.java
@@ -45,5 +45,44 @@ public void test_0() throws Exception {
         assertEquals("SELECT J01.COL_A, J01.COL_B, \"SUM\"(J01.COL_C) OVER (PARTITION BY J01.COL_A ORDER BY J01.COL_B NULLS FIRST ROWS  BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS COL_C\n" +
                 "FROM TAB_A J01", stmt.toString());
     }
+    public void test_1() throws Exception {
+        String sql = "SELECT\n" +
+                "J01.COL_A,\n" +
+                "J01.COL_B,\n" +
+                "\"SUM\"(J01.COL_C) OVER (\n" +
+                "PARTITION BY J01.COL_A ORDER BY J01.COL_B NULLS FIRST ROWS BETWEEN 5 PRECEDING AND 8 FOLLOWING\n" +
+                ") AS COL_C\n" +
+                "FROM\n" +
+                "TAB_A J01";
+
+        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE);
+
+        assertEquals(1, statementList.size());
+
+        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);
+        System.out.println(stmt.toString());
+
+        assertEquals("SELECT J01.COL_A, J01.COL_B, \"SUM\"(J01.COL_C) OVER (PARTITION BY J01.COL_A ORDER BY J01.COL_B NULLS FIRST ROWS  BETWEEN 5 PRECEDING AND 8 FOLLOWING) AS COL_C\n" +
+                "FROM TAB_A J01", stmt.toString());
+    }
 
+    public void test_2() throws Exception {
+        String sql = "SELECT\n" +
+                "J01.COL_A,\n" +
+                "J01.COL_B,\n" +
+                "\"SUM\"(J01.COL_C) OVER (\n" +
+                "PARTITION BY J01.COL_A ORDER BY J01.COL_B NULLS FIRST ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING\n" +
+                ") AS COL_C\n" +
+                "FROM\n" +
+                "TAB_A J01";
+
+        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE);
+
+        assertEquals(1, statementList.size());
+
+        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);
+        System.out.println(stmt.toString());
+        assertEquals("SELECT J01.COL_A, J01.COL_B, \"SUM\"(J01.COL_C) OVER (PARTITION BY J01.COL_A ORDER BY J01.COL_B NULLS FIRST ROWS  BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS COL_C\n" +
+                "FROM TAB_A J01", stmt.toString());
+    }
 }
\ No newline at end of file