Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/sql-ref-ansi-compliance.md
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ Below is a list of all the keywords in Spark SQL.
|NULL|reserved|non-reserved|reserved|
|NULLS|non-reserved|non-reserved|non-reserved|
|OF|non-reserved|non-reserved|reserved|
|OFFSET|non-reserved|non-reserved|reserved|
|OFFSET|reserved|non-reserved|reserved|
|ON|reserved|strict-non-reserved|reserved|
|ONLY|reserved|non-reserved|reserved|
|OPTION|non-reserved|non-reserved|non-reserved|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,42 @@
* <li>Since version: 3.3.0</li>
* </ul>
* </li>
* <li>Name: <code>GREATEST</code>
* <ul>
* <li>SQL semantic: <code>GREATEST(expr, ...)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>LEAST</code>
* <ul>
* <li>SQL semantic: <code>LEAST(expr, ...)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>RAND</code>
* <ul>
* <li>SQL semantic: <code>RAND([seed])</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>LOG</code>
* <ul>
* <li>SQL semantic: <code>LOG(base, expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>LOG10</code>
* <ul>
* <li>SQL semantic: <code>LOG10(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>LOG2</code>
* <ul>
* <li>SQL semantic: <code>LOG2(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>LN</code>
* <ul>
* <li>SQL semantic: <code>LN(expr)</code></li>
Expand Down Expand Up @@ -142,6 +178,120 @@
* <li>Since version: 3.3.0</li>
* </ul>
* </li>
* <li>Name: <code>ROUND</code>
* <ul>
* <li>SQL semantic: <code>ROUND(expr, [scale])</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>SIN</code>
* <ul>
* <li>SQL semantic: <code>SIN(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>SINH</code>
* <ul>
* <li>SQL semantic: <code>SINH(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>COS</code>
* <ul>
* <li>SQL semantic: <code>COS(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>COSH</code>
* <ul>
* <li>SQL semantic: <code>COSH(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>TAN</code>
* <ul>
* <li>SQL semantic: <code>TAN(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>TANH</code>
* <ul>
* <li>SQL semantic: <code>TANH(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>COT</code>
* <ul>
* <li>SQL semantic: <code>COT(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>ASIN</code>
* <ul>
* <li>SQL semantic: <code>ASIN(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>ASINH</code>
* <ul>
* <li>SQL semantic: <code>ASINH(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>ACOS</code>
* <ul>
* <li>SQL semantic: <code>ACOS(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>ACOSH</code>
* <ul>
* <li>SQL semantic: <code>ACOSH(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>ATAN</code>
* <ul>
* <li>SQL semantic: <code>ATAN(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>ATANH</code>
* <ul>
* <li>SQL semantic: <code>ATANH(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>ATAN2</code>
* <ul>
* <li>SQL semantic: <code>ATAN2(exprY, exprX)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>CBRT</code>
* <ul>
* <li>SQL semantic: <code>CBRT(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>DEGREES</code>
* <ul>
* <li>SQL semantic: <code>DEGREES(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>RADIANS</code>
* <ul>
* <li>SQL semantic: <code>RADIANS(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>SIGN</code>
* <ul>
* <li>SQL semantic: <code>SIGN(expr)</code></li>
* <li>Since version: 3.4.0</li>
* </ul>
* </li>
* <li>Name: <code>WIDTH_BUCKET</code>
* <ul>
* <li>SQL semantic: <code>WIDTH_BUCKET(expr)</code></li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
* An interface for building the {@link Scan}. Implementations can mixin SupportsPushDownXYZ
* interfaces to do operator push down, and keep the operator push down result in the returned
* {@link Scan}. When pushing down operators, the push down order is:
* sample -&gt; filter -&gt; aggregate -&gt; limit -&gt; column pruning.
* sample -&gt; filter -&gt; aggregate -&gt; limit/top-n(sort + limit) -&gt; offset -&gt;
* column pruning.
*
* @since 3.0.0
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@

/**
* A mix-in interface for {@link ScanBuilder}. Data sources can implement this interface to
* push down LIMIT. Please note that the combination of LIMIT with other operations
* such as AGGREGATE, GROUP BY, SORT BY, CLUSTER BY, DISTRIBUTE BY, etc. is NOT pushed down.
* push down LIMIT. We can push down LIMIT with many other operations if they follow the
* operator order we defined in {@link ScanBuilder}'s class doc.
*
* @since 3.3.0
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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.spark.sql.connector.read;

import org.apache.spark.annotation.Evolving;

/**
* A mix-in interface for {@link ScanBuilder}. Data sources can implement this interface to
* push down OFFSET. We can push down OFFSET with many other operations if they follow the
* operator order we defined in {@link ScanBuilder}'s class doc.
*
* @since 3.4.0
*/
@Evolving
public interface SupportsPushDownOffset extends ScanBuilder {

/**
* Pushes down OFFSET to the data source.
*/
boolean pushOffset(int offset);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,22 @@

/**
* A mix-in interface for {@link ScanBuilder}. Data sources can implement this interface to
* push down top N(query with ORDER BY ... LIMIT n). Please note that the combination of top N
* with other operations such as AGGREGATE, GROUP BY, CLUSTER BY, DISTRIBUTE BY, etc.
* is NOT pushed down.
* push down top N(query with ORDER BY ... LIMIT n). We can push down top N with many other
* operations if they follow the operator order we defined in {@link ScanBuilder}'s class doc.
*
* @since 3.3.0
*/
@Evolving
public interface SupportsPushDownTopN extends ScanBuilder {

/**
* Pushes down top N to the data source.
*/
boolean pushTopN(SortOrder[] orders, int limit);
/**
* Pushes down top N to the data source.
*/
boolean pushTopN(SortOrder[] orders, int limit);

/**
* Whether the top N is partially pushed or not. If it returns true, then Spark will do top N
* again. This method will only be called when {@link #pushTopN} returns true.
*/
default boolean isPartiallyPushed() { return true; }
/**
* Whether the top N is partially pushed or not. If it returns true, then Spark will do top N
* again. This method will only be called when {@link #pushTopN} returns true.
*/
default boolean isPartiallyPushed() { return true; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,37 @@ public String build(Expression expr) {
return visitUnaryArithmetic(name, inputToSQL(e.children()[0]));
case "ABS":
case "COALESCE":
case "GREATEST":
case "LEAST":
case "RAND":
case "LOG":
case "LOG10":
case "LOG2":
case "LN":
case "EXP":
case "POWER":
case "SQRT":
case "FLOOR":
case "CEIL":
case "ROUND":
case "SIN":
case "SINH":
case "COS":
case "COSH":
case "TAN":
case "TANH":
case "COT":
case "ASIN":
case "ASINH":
case "ACOS":
case "ACOSH":
case "ATAN":
case "ATANH":
case "ATAN2":
case "CBRT":
case "DEGREES":
case "RADIANS":
case "SIGN":
case "WIDTH_BUCKET":
case "SUBSTRING":
case "UPPER":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,20 +393,17 @@ trait CheckAnalysis extends PredicateHelper with LookupCatalog {
val offset = offsetExpr.eval().asInstanceOf[Int]
if (Int.MaxValue - limit < offset) {
failAnalysis(
s"""The sum of limit and offset must not be greater than Int.MaxValue,
| but found limit = $limit, offset = $offset.""".stripMargin)
s"""
|The sum of the LIMIT clause and the OFFSET clause must not be greater than
|the maximum 32-bit integer value (2,147,483,647),
|but found limit = $limit, offset = $offset.
|""".stripMargin.replace("\n", " "))
}
case _ =>
}

case Offset(offsetExpr, _) => checkLimitLikeClause("offset", offsetExpr)

case o if !o.isInstanceOf[GlobalLimit] && !o.isInstanceOf[LocalLimit]
&& o.children.exists(_.isInstanceOf[Offset]) =>
failAnalysis(
s"""Only the OFFSET clause is allowed in the LIMIT clause, but the OFFSET
| clause found in: ${o.nodeName}.""".stripMargin)

case Tail(limitExpr, _) => checkLimitLikeClause("tail", limitExpr)

case _: Union | _: SetOperation if operator.children.length > 1 =>
Expand Down Expand Up @@ -567,7 +564,6 @@ trait CheckAnalysis extends PredicateHelper with LookupCatalog {
}
}
checkCollectedMetrics(plan)
checkOutermostOffset(plan)
extendedCheckRules.foreach(_(plan))
plan.foreachUp {
case o if !o.resolved =>
Expand All @@ -578,20 +574,6 @@ trait CheckAnalysis extends PredicateHelper with LookupCatalog {
plan.setAnalyzed()
}

/**
* Validate that the root node of query or subquery is [[Offset]].
*/
private def checkOutermostOffset(plan: LogicalPlan): Unit = {
plan match {
case Offset(offsetExpr, _) =>
checkLimitLikeClause("limit", offsetExpr)
failAnalysis(
s"""Only the OFFSET clause is allowed in the LIMIT clause, but the OFFSET
| clause is found to be the outermost node.""".stripMargin)
case _ =>
}
}

/**
* Validates subquery expressions in the plan. Upon failure, returns an user facing error.
*/
Expand Down
Loading