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

duanzhengqiang 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 7e5fbcaf365 Support parsing SQL Server SELECT ProductId, sql #29159 
(#29868)
7e5fbcaf365 is described below

commit 7e5fbcaf365b4cfdd487ba53eb5a894c32125216
Author: yydeng626 <[email protected]>
AuthorDate: Mon Jan 29 04:47:00 2024 -0600

    Support parsing SQL Server SELECT ProductId, sql #29159 (#29868)
    
    * Support parsing SQL Server SELECT ProductId, sql #29159
    
    * fix code style
---
 .../src/main/antlr4/imports/sqlserver/BaseRule.g4  |  16 +--
 .../src/main/antlr4/imports/sqlserver/Keyword.g4   |   8 ++
 .../statement/SQLServerStatementVisitor.java       |  79 ++++++++-------
 .../parser/src/main/resources/case/dml/insert.xml  |  14 +++
 .../resources/case/dml/select-special-function.xml | 108 +++++++++++++++++++++
 .../main/resources/sql/supported/dml/insert.xml    |   1 +
 .../sql/supported/dml/select-special-function.xml  |   1 +
 7 files changed, 188 insertions(+), 39 deletions(-)

diff --git 
a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/BaseRule.g4 
b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/BaseRule.g4
index eab5ea28c2e..c1e4f38083b 100644
--- a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/BaseRule.g4
+++ b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/BaseRule.g4
@@ -120,7 +120,7 @@ unreservedWord
     | DATA_RETENTION | TEMPORAL_HISTORY_RETENTION | EDITION | 
MIXED_PAGE_ALLOCATION | DISABLED | ALLOWED | HADR | MULTI_USER | 
RESTRICTED_USER | SINGLE_USER | OFFLINE | EMERGENCY | SUSPEND | 
DATE_CORRELATION_OPTIMIZATION
     | ELASTIC_POOL | SERVICE_OBJECTIVE | DATABASE_NAME | ALLOW_CONNECTIONS | 
GEO | NAMED | DATEFIRST | BACKUP_STORAGE_REDUNDANCY | 
FORCE_FAILOVER_ALLOW_DATA_LOSS | SECONDARY | FAILOVER | 
DEFAULT_FULLTEXT_LANGUAGE
     | DEFAULT_LANGUAGE | INLINE | NESTED_TRIGGERS | TRANSFORM_NOISE_WORDS | 
TWO_DIGIT_YEAR_CUTOFF | PERSISTENT_LOG_BUFFER | DIRECTORY_NAME | DATEFORMAT | 
DELAYED_DURABILITY | TRANSFER | SCHEMA | PASSWORD | AUTHORIZATION
-    | MEMBER | SEARCH | TEXT | SECOND | PRECISION | VIEWS | PROVIDER | COLUMNS 
| SUBSTRING | RETURNS | SIZE | CONTAINS | MONTH | INPUT
+    | MEMBER | SEARCH | TEXT | SECOND | PRECISION | VIEWS | PROVIDER | COLUMNS 
| SUBSTRING | RETURNS | SIZE | CONTAINS | MONTH | INPUT | YEAR
     | TIMESTAMP | TRIM
     ;
 
@@ -296,7 +296,7 @@ simpleExpr
     ;
 
 functionCall
-    : aggregationFunction | specialFunction | regularFunction 
+    : aggregationFunction | specialFunction | regularFunction
     ;
 
 aggregationFunction
@@ -312,7 +312,7 @@ distinct
     ;
 
 specialFunction
-    : conversionFunction | charFunction | openJsonFunction | jsonFunction | 
openRowSetFunction
+    : conversionFunction | charFunction | openJsonFunction | jsonFunction | 
openRowSetFunction | windowFunction
     ;
 
 conversionFunction
@@ -390,7 +390,7 @@ caseElse
     ;
 
 privateExprOfDb
-    : windowedFunction | atTimeZoneExpr | castExpr | convertExpr
+    : windowFunction | atTimeZoneExpr | castExpr | convertExpr
     ;
 
 orderByClause
@@ -425,8 +425,12 @@ convertExpr
     : CONVERT (dataType (LP_ NUMBER_ RP_)? COMMA_ expr (COMMA_ NUMBER_)?)
     ;
 
-windowedFunction
-    : functionCall overClause
+windowFunction
+    : funcName = (FIRST_VALUE | LAST_VALUE) LP_ expr RP_ nullTreatment? 
overClause
+    ;
+
+nullTreatment
+    : (RESPECT | IGNORE) NULLS
     ;
 
 overClause
diff --git 
a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/Keyword.g4 
b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/Keyword.g4
index f28dc17c8d8..a6ac558e186 100644
--- a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/Keyword.g4
+++ b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/Keyword.g4
@@ -779,3 +779,11 @@ JSON_OBJECT
 JSON_ARRAY
     : J S O N UL_ A R R A Y
     ;
+
+FIRST_VALUE
+    :F I R S T UL_ V A L U E
+    ;
+
+LAST_VALUE
+    :L A S T UL_ V A L U E
+    ;
diff --git 
a/parser/sql/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/SQLServerStatementVisitor.java
 
b/parser/sql/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/SQLServerStatementVisitor.java
index ea867652e3e..780f7d5b29b 100644
--- 
a/parser/sql/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/SQLServerStatementVisitor.java
+++ 
b/parser/sql/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/SQLServerStatementVisitor.java
@@ -53,6 +53,7 @@ import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.Dat
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.DeleteContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.DelimitedIdentifierContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.DuplicateSpecificationContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ExecContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ExprContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.FromClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.FunctionCallContext;
@@ -63,21 +64,23 @@ import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.Ide
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.IndexNameContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.InsertContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.InsertDefaultValueContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.InsertExecClauseContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.InsertSelectClauseContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.InsertValuesClauseContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JoinSpecificationContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JoinedTableContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JsonArrayFunctionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JsonFunctionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JsonKeyValueContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JsonNullClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JsonObjectFunctionContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.WithTableHintContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.InsertSelectClauseContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.InsertValuesClauseContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JoinSpecificationContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JoinedTableContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.LiteralsContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.MultipleTableNamesContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.MultipleTablesClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.NullValueLiteralsContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.NumberLiteralsContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.OpenJsonFunctionContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.OpenRowSetFunctionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.OrderByClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.OrderByItemContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.OutputClauseContext;
@@ -87,11 +90,13 @@ import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.Out
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.OwnerContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ParameterMarkerContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.PredicateContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ProcedureNameContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ProjectionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ProjectionsContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.QualifiedShorthandContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.RegularFunctionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.RegularIdentifierContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.SampleOptionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.SchemaNameContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ScriptVariableNameContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.SelectClauseContext;
@@ -100,9 +105,13 @@ import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.Set
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.SimpleExprContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.SingleTableClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.SpecialFunctionContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.StatisticsOptionContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.StatisticsOptionsContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.StatisticsWithClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.StringLiteralsContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.SubqueryContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.TableFactorContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.TableHintLimitedContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.TableNameContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.TableNamesContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.TableReferenceContext;
@@ -110,20 +119,12 @@ import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.Tab
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.TopContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.UnreservedWordContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.UpdateContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.UpdateStatisticsContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ViewNameContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.WhereClauseContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.WindowFunctionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.WithClauseContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.UpdateStatisticsContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.StatisticsWithClauseContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.StatisticsOptionContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.StatisticsOptionsContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.SampleOptionContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.InsertExecClauseContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ExecContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ProcedureNameContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.OpenJsonFunctionContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.TableHintLimitedContext;
-import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.OpenRowSetFunctionContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.WithTableHintContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.ConversionFunctionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.IntoClauseContext;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.AggregationType;
@@ -192,8 +193,6 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.Sim
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.sqlserver.hint.TableHintLimitedSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.sqlserver.hint.WithTableHintSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.util.SQLUtils;
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.collection.CollectionValue;
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
@@ -205,6 +204,8 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.OtherL
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.StringLiteralValue;
 import 
org.apache.shardingsphere.sql.parser.sql.common.value.parametermarker.ParameterMarkerValue;
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.sqlserver.exec.ExecSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.sqlserver.hint.TableHintLimitedSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.sqlserver.hint.WithTableHintSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.segment.sqlserver.json.JsonNullClauseSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.ddl.SQLServerCreateTableStatement;
 import 
org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.ddl.SQLServerUpdateStatisticsStatement;
@@ -674,6 +675,9 @@ public abstract class SQLServerStatementVisitor extends 
SQLServerStatementBaseVi
         if (null != ctx.jsonFunction()) {
             return visit(ctx.jsonFunction());
         }
+        if (null != ctx.windowFunction()) {
+            return visit(ctx.windowFunction());
+        }
         return new FunctionSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ctx.getChild(0).getChild(0).getText(), 
getOriginalText(ctx));
     }
     
@@ -688,6 +692,13 @@ public abstract class SQLServerStatementVisitor extends 
SQLServerStatementBaseVi
         return new FunctionSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ctx.getChild(0).getChild(0).getText(), 
getOriginalText(ctx));
     }
     
+    @Override
+    public final ASTNode visitWindowFunction(final WindowFunctionContext ctx) {
+        FunctionSegment result = new 
FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), 
ctx.funcName.getText(), getOriginalText(ctx));
+        result.getParameters().add((ExpressionSegment) visit(ctx.expr()));
+        return result;
+    }
+    
     @Override
     public final ASTNode visitJsonFunction(final JsonFunctionContext ctx) {
         if (null != ctx.jsonArrayFunction()) {
@@ -915,7 +926,8 @@ public abstract class SQLServerStatementVisitor extends 
SQLServerStatementBaseVi
             result.setHaving((HavingSegment) visit(ctx.havingClause()));
         }
         if (null != ctx.orderByClause()) {
-            visitOrderBy(result, ctx.orderByClause());
+            result.setOrderBy(getOrderBySegment(ctx.orderByClause()));
+            result.setLimit(getLimitSegment(ctx.orderByClause()));
         }
         return result;
     }
@@ -943,19 +955,10 @@ public abstract class SQLServerStatementVisitor extends 
SQLServerStatementBaseVi
         return new HavingSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), expr);
     }
     
-    private SQLServerSelectStatement visitOrderBy(final 
SQLServerSelectStatement selectStatement, final OrderByClauseContext ctx) {
-        Collection<OrderByItemSegment> items = new LinkedList<>();
-        int orderByStartIndex = ctx.start.getStartIndex();
-        int orderByStopIndex = ctx.start.getStartIndex();
-        for (OrderByItemContext each : ctx.orderByItem()) {
-            items.add((OrderByItemSegment) visit(each));
-            orderByStopIndex = each.stop.getStopIndex();
-        }
-        OrderBySegment orderBySegment = new OrderBySegment(orderByStartIndex, 
orderByStopIndex, items);
-        selectStatement.setOrderBy(orderBySegment);
+    private LimitSegment getLimitSegment(final OrderByClauseContext ctx) {
+        LimitSegment result = null;
         PaginationValueSegment offset = null;
         PaginationValueSegment rowcount = null;
-        LimitSegment limitSegment = null;
         if (null != ctx.OFFSET()) {
             ASTNode astNode = visit(ctx.expr(0));
             if (astNode instanceof LiteralExpressionSegment && 
((LiteralExpressionSegment) astNode).getLiterals() instanceof Number) {
@@ -975,10 +978,20 @@ public abstract class SQLServerStatementVisitor extends 
SQLServerStatementBaseVi
             }
         }
         if (null != offset) {
-            limitSegment = new 
LimitSegment(ctx.OFFSET().getSymbol().getStartIndex(), ctx.stop.getStopIndex(), 
offset, rowcount);
+            result = new 
LimitSegment(ctx.OFFSET().getSymbol().getStartIndex(), ctx.stop.getStopIndex(), 
offset, rowcount);
+        }
+        return result;
+    }
+    
+    private OrderBySegment getOrderBySegment(final OrderByClauseContext ctx) {
+        Collection<OrderByItemSegment> items = new LinkedList<>();
+        int orderByStartIndex = ctx.start.getStartIndex();
+        int orderByStopIndex = ctx.start.getStartIndex();
+        for (OrderByItemContext each : ctx.orderByItem()) {
+            items.add((OrderByItemSegment) visit(each));
+            orderByStopIndex = each.stop.getStopIndex();
         }
-        selectStatement.setLimit(limitSegment);
-        return selectStatement;
+        return new OrderBySegment(orderByStartIndex, orderByStopIndex, items);
     }
     
     private boolean isDistinct(final SelectClauseContext ctx) {
diff --git a/test/it/parser/src/main/resources/case/dml/insert.xml 
b/test/it/parser/src/main/resources/case/dml/insert.xml
index bad62ceb897..4b632442106 100644
--- a/test/it/parser/src/main/resources/case/dml/insert.xml
+++ b/test/it/parser/src/main/resources/case/dml/insert.xml
@@ -3443,4 +3443,18 @@
             </value>
         </values>
     </insert>
+    
+    <insert sql-case-id="insert_with_exec_prediction_results">
+        <table name="prediction_results" start-index="12" stop-index="29" />
+        <columns start-index="31" stop-index="127">
+            <column name="tipped_Pred" start-index="32" stop-index="42" />
+            <column name="payment_type" start-index="44" stop-index="55" />
+            <column name="tipped" start-index="57" stop-index="62" />
+            <column name="passenger_count" start-index="64" stop-index="78" />
+            <column name="trip_distance" start-index="80" stop-index="92" />
+            <column name="trip_time_in_secs" start-index="94" stop-index="110" 
/>
+            <column name="direct_distance" start-index="112" stop-index="126" 
/>
+        </columns>
+        <exec name="predict_per_partition" start-index="129" stop-index="159" 
start-delimiter="[" end-delimiter="]" />
+    </insert>
 </sql-parser-test-cases>
diff --git 
a/test/it/parser/src/main/resources/case/dml/select-special-function.xml 
b/test/it/parser/src/main/resources/case/dml/select-special-function.xml
index b48088bf69e..bea78475efe 100644
--- a/test/it/parser/src/main/resources/case/dml/select-special-function.xml
+++ b/test/it/parser/src/main/resources/case/dml/select-special-function.xml
@@ -987,4 +987,112 @@
             </expr>
         </where>
     </select>
+    
+    <select sql-case-id="select_first_last_value_function">
+        <projections start-index="7" stop-index="493">
+            <column-projection name="BusinessEntityID" start-index="7" 
stop-index="22" />
+            <expression-projection text="DATEPART(QUARTER, QuotaDate)" 
alias="Quarter" start-index="25" stop-index="63">
+                <expr>
+                    <function function-name="DATEPART" text="DATEPART(QUARTER, 
QuotaDate)" start-index="25" stop-index="52">
+                        <parameter>
+                            <column name="QUARTER" start-index="34" 
stop-index="40" />
+                        </parameter>
+                        <parameter>
+                            <column name="QuotaDate" start-index="43" 
stop-index="51" />
+                        </parameter>
+                    </function>
+                </expr>
+            </expression-projection>
+            <expression-projection text="YEAR(QuotaDate)" start-index="66" 
stop-index="93" alias="SalesYear">
+                <expr>
+                    <function function-name="YEAR" text="YEAR(QuotaDate)" 
start-index="66" stop-index="80">
+                        <parameter>
+                            <column name="QuotaDate" start-index="71" 
stop-index="79" />
+                        </parameter>
+                    </function>
+                </expr>
+            </expression-projection>
+            <column-projection name="SalesQuota" alias="QuotaThisQuarter" 
start-index="96" stop-index="125" />
+            <expression-projection text="SalesQuota - FIRST_VALUE(SalesQuota) 
OVER (PARTITION BY BusinessEntityID, YEAR(QuotaDate) ORDER BY DATEPART(QUARTER, 
QuotaDate))" alias="DifferenceFromFirstQuarter" start-index="128" 
stop-index="285">
+                <expr>
+                    <binary-operation-expression start-index="128" 
stop-index="255">
+                        <left>
+                            <column name="SalesQuota" start-index="128" 
stop-index="137" />
+                        </left>
+                        <right>
+                            <function function-name="FIRST_VALUE" 
text="FIRST_VALUE(SalesQuota) OVER (PARTITION BY BusinessEntityID, 
YEAR(QuotaDate) ORDER BY DATEPART(QUARTER, QuotaDate))" start-index="141" 
stop-index="255">
+                                <parameter>
+                                    <column name="SalesQuota" 
start-index="153" stop-index="162" />
+                                </parameter>
+                            </function>
+                        </right>
+                        <operator>-</operator>
+                    </binary-operation-expression>
+                </expr>
+            </expression-projection>
+            <expression-projection start-index="288" stop-index="493" 
text="SalesQuota - LAST_VALUE(SalesQuota) OVER (PARTITION BY BusinessEntityID, 
YEAR(QuotaDate) ORDER BY DATEPART(QUARTER, QuotaDate) RANGE BETWEEN CURRENT ROW 
AND UNBOUNDED FOLLOWING)" alias="DifferenceFromLastQuarter">
+                <expr>
+                    <binary-operation-expression start-index="288" 
stop-index="464">
+                        <left>
+                            <column name="SalesQuota" start-index="288" 
stop-index="297" />
+                        </left>
+                        <right>
+                            <function function-name="LAST_VALUE" 
text="LAST_VALUE(SalesQuota) OVER (PARTITION BY BusinessEntityID, 
YEAR(QuotaDate) ORDER BY DATEPART(QUARTER, QuotaDate) RANGE BETWEEN CURRENT ROW 
AND UNBOUNDED FOLLOWING)" start-index="301" stop-index="464">
+                                <parameter>
+                                    <column name="SalesQuota" 
start-index="312" stop-index="321" />
+                                </parameter>
+                            </function>
+                        </right>
+                        <operator>-</operator>
+                    </binary-operation-expression>
+                </expr>
+            </expression-projection>
+        </projections>
+        <from>
+            <simple-table name="SalesPersonQuotaHistory" start-index="500" 
stop-index="528">
+                <owner name="Sales" start-index="500" stop-index="504" />
+            </simple-table>
+        </from>
+        <where start-index="530" stop-index="598">
+            <expr>
+                <binary-operation-expression start-index="536" 
stop-index="598" text="YEAR(QuotaDate) > 2005 AND BusinessEntityID BETWEEN 274 
AND 275">
+                    <left>
+                        <binary-operation-expression start-index="536" 
stop-index="557" text="YEAR(QuotaDate) > 2005">
+                            <left>
+                                <function function-name="YEAR" 
text="YEAR(QuotaDate)" start-index="536" stop-index="550">
+                                    <parameter>
+                                        <column name="QuotaDate" 
start-index="541" stop-index="549" />
+                                    </parameter>
+                                </function>
+                            </left>
+                            <right>
+                                <literal-expression value="2005" 
start-index="554" stop-index="557" />
+                            </right>
+                            <operator>></operator>
+                        </binary-operation-expression>
+                    </left>
+                    <right>
+                        <between-expression start-index="563" stop-index="598">
+                            <not>false</not>
+                            <left>
+                                <column name="BusinessEntityID" 
start-index="563" stop-index="578" />
+                            </left>
+                            <between-expr>
+                                <literal-expression value="274" 
start-index="588" stop-index="590" />
+                            </between-expr>
+                            <and-expr>
+                                <literal-expression value="275" 
start-index="596" stop-index="598" />
+                            </and-expr>
+                        </between-expression>
+                    </right>
+                    <operator>AND</operator>
+                </binary-operation-expression>
+            </expr>
+        </where>
+        <order-by>
+            <column-item name="BusinessEntityID" order-direction="ASC" 
start-index="609" stop-index="624" />
+            <column-item name="SalesYear" order-direction="ASC" 
start-index="627" stop-index="635" />
+            <column-item name="Quarter" order-direction="ASC" 
start-index="638" stop-index="644" />
+        </order-by>
+    </select>
 </sql-parser-test-cases>
diff --git a/test/it/parser/src/main/resources/sql/supported/dml/insert.xml 
b/test/it/parser/src/main/resources/sql/supported/dml/insert.xml
index 233753880b6..cf6f6407abe 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/insert.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/insert.xml
@@ -126,4 +126,5 @@
     <sql-case id="insert_into_table_get_date" value="INSERT INTO #Test VALUES 
(N'OC', N'Ounces', GETDATE())" db-types="SQLServer"/>
     <sql-case id="insert_into_table_from_table" value="INSERT INTO #Test 
SELECT * FROM Production.UnitMeasure" db-types="SQLServer"/>
     <sql-case id="insert_into_production_location" value="INSERT INTO 
AdventureWorks2022.Production.Location(Name, CostRate, Availability, 
ModifiedDate) VALUES (NEWID(), .5, 5.2, GETDATE())" db-types="SQLServer"/>
+    <sql-case id="insert_with_exec_prediction_results" value="INSERT INTO 
prediction_results 
(tipped_Pred,payment_type,tipped,passenger_count,trip_distance,trip_time_in_secs,direct_distance)
 EXECUTE [predict_per_partition]" db-types="SQLServer"/>
 </sql-cases>
diff --git 
a/test/it/parser/src/main/resources/sql/supported/dml/select-special-function.xml
 
b/test/it/parser/src/main/resources/sql/supported/dml/select-special-function.xml
index 07b03cb04c8..a77c62a0f1a 100644
--- 
a/test/it/parser/src/main/resources/sql/supported/dml/select-special-function.xml
+++ 
b/test/it/parser/src/main/resources/sql/supported/dml/select-special-function.xml
@@ -55,4 +55,5 @@
     <sql-case id="select_nest_json_object" value="SELECT 
JSON_OBJECT('name':'value', 'type':JSON_OBJECT('type_id':1, 'name':'a'))" 
db-types="SQLServer" />
     <sql-case id="select_json_object_with_subquery" value="SELECT 
JSON_OBJECT('user_name':USER_NAME(), @id_key:@id_value, 'sid':(SELECT @@SPID))" 
db-types="SQLServer" />
     <sql-case id="select_dm_exec_sessions_with_json_object_function" 
value="SELECT s.session_id, JSON_OBJECT('security_id':s.security_id, 
'login':s.login_name, 'status':s.status) as info FROM sys.dm_exec_sessions AS s 
WHERE s.is_user_process = 1" db-types="SQLServer" />
+    <sql-case id="select_first_last_value_function" value="SELECT 
BusinessEntityID, DATEPART(QUARTER, QuotaDate) AS Quarter, YEAR(QuotaDate) AS 
SalesYear, SalesQuota AS QuotaThisQuarter, SalesQuota - FIRST_VALUE(SalesQuota) 
OVER (PARTITION BY BusinessEntityID, YEAR(QuotaDate) ORDER BY DATEPART(QUARTER, 
QuotaDate)) AS DifferenceFromFirstQuarter, SalesQuota - LAST_VALUE(SalesQuota) 
OVER (PARTITION BY BusinessEntityID, YEAR(QuotaDate) ORDER BY DATEPART(QUARTER, 
QuotaDate) RANGE BETWEEN CURR [...]
 </sql-cases>

Reply via email to