From ccec920f57da621f30fb703b1646f19e8c128df7 Mon Sep 17 00:00:00 2001 From: gaoyangxiaozhu Date: Wed, 5 Jun 2024 18:44:30 +0800 Subject: [PATCH 01/13] raise_error spark function --- velox/functions/sparksql/RaiseError.h | 32 +++++++++++++++ velox/functions/sparksql/Register.cpp | 4 ++ velox/functions/sparksql/tests/CMakeLists.txt | 1 + .../sparksql/tests/RaiseErrorTest.cpp | 40 +++++++++++++++++++ 4 files changed, 77 insertions(+) create mode 100644 velox/functions/sparksql/RaiseError.h create mode 100644 velox/functions/sparksql/tests/RaiseErrorTest.cpp diff --git a/velox/functions/sparksql/RaiseError.h b/velox/functions/sparksql/RaiseError.h new file mode 100644 index 000000000000..f36844a7cd43 --- /dev/null +++ b/velox/functions/sparksql/RaiseError.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed 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. + */ +#pragma once + +#include +#include "velox/functions/Macros.h" +namespace facebook::velox::functions::sparksql { + +template +struct RaiseErrorFunction { + VELOX_DEFINE_FUNCTION_TYPES(T); + + FOLLY_ALWAYS_INLINE bool call( + UnknownValue& result, + const arg_type& input) { + throw std::runtime_error(input); + } +}; +} // namespace facebook::velox::functions::sparksql \ No newline at end of file diff --git a/velox/functions/sparksql/Register.cpp b/velox/functions/sparksql/Register.cpp index 0c945a5931be..29893b8c6600 100644 --- a/velox/functions/sparksql/Register.cpp +++ b/velox/functions/sparksql/Register.cpp @@ -39,6 +39,7 @@ #include "velox/functions/sparksql/LeastGreatest.h" #include "velox/functions/sparksql/MightContain.h" #include "velox/functions/sparksql/MonotonicallyIncreasingId.h" +#include "velox/functions/sparksql/RaiseError.h" #include "velox/functions/sparksql/RegexFunctions.h" #include "velox/functions/sparksql/RegisterArithmetic.h" #include "velox/functions/sparksql/RegisterCompare.h" @@ -460,6 +461,9 @@ void registerFunctions(const std::string& prefix) { Array>>>({prefix + "flatten"}); registerFunction({prefix + "soundex"}); + + registerFunction( + {prefix + "raise_error"}); } } // namespace sparksql diff --git a/velox/functions/sparksql/tests/CMakeLists.txt b/velox/functions/sparksql/tests/CMakeLists.txt index 56b3fea8da6b..3ab4d1487404 100644 --- a/velox/functions/sparksql/tests/CMakeLists.txt +++ b/velox/functions/sparksql/tests/CMakeLists.txt @@ -39,6 +39,7 @@ add_executable( MapTest.cpp MightContainTest.cpp MonotonicallyIncreasingIdTest.cpp + RaiseErrorTest.cpp RandTest.cpp RegexFunctionsTest.cpp SizeTest.cpp diff --git a/velox/functions/sparksql/tests/RaiseErrorTest.cpp b/velox/functions/sparksql/tests/RaiseErrorTest.cpp new file mode 100644 index 000000000000..419a89a62655 --- /dev/null +++ b/velox/functions/sparksql/tests/RaiseErrorTest.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed 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. + */ + +#include "velox/common/base/tests/GTestUtils.h" +#include "velox/functions/sparksql/tests/SparkFunctionBaseTest.h" + +namespace facebook::velox::functions::sparksql::test { +namespace { + +class RaiseErrorTest : public SparkFunctionBaseTest { + protected: + void raiseError(const std::optional& errMsg) { + evaluateOnce("raise_error(c0)", errMsg); + } + void testRaiseError( + const std::optional& errMsg, + std::string expectedMsg) { + VELOX_ASSERT_THROW(raiseError(errMsg), expectedMsg); + } +}; + +TEST_F(RaiseErrorTest, basic) { + testRaiseError("", ""); + testRaiseError("0 > 1 is not true", "0 > 1 is not true"); +} +} // namespace +} // namespace facebook::velox::functions::sparksql::test From 191245808c1059ddfbe83da6116ed6a569fa50b3 Mon Sep 17 00:00:00 2001 From: gaoyangxiaozhu Date: Tue, 11 Jun 2024 11:57:46 +0800 Subject: [PATCH 02/13] add doc desc --- velox/docs/functions/spark/misc.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/velox/docs/functions/spark/misc.rst b/velox/docs/functions/spark/misc.rst index 362c76a3c20b..4d87fbe6753b 100644 --- a/velox/docs/functions/spark/misc.rst +++ b/velox/docs/functions/spark/misc.rst @@ -31,3 +31,7 @@ Miscellaneous Functions ``seed`` must be constant. :: SELECT uuid(0); -- "8c7f0aac-97c4-4a2f-b716-a675d821ccc0" + + +.. spark:function:: raise_error(str) -> void + Throws an runtime exception with ``str``. \ No newline at end of file From 023996d40435fc1323dc244f7d57fa27223531a1 Mon Sep 17 00:00:00 2001 From: gaoyangxiaozhu Date: Wed, 12 Jun 2024 10:53:42 +0800 Subject: [PATCH 03/13] address comments --- velox/docs/functions/spark/misc.rst | 10 +++++----- velox/functions/sparksql/RaiseError.h | 5 ++--- velox/functions/sparksql/tests/RaiseErrorTest.cpp | 9 ++------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/velox/docs/functions/spark/misc.rst b/velox/docs/functions/spark/misc.rst index 4d87fbe6753b..7a381f6c42ba 100644 --- a/velox/docs/functions/spark/misc.rst +++ b/velox/docs/functions/spark/misc.rst @@ -13,6 +13,10 @@ Miscellaneous Functions The function relies on partition IDs, which are provided by the framework via the configuration 'spark.partition_id'. +.. spark:function:: raise_error(str) -> void + + Throws an runtime exception with ``str``. + .. spark:function:: spark_partition_id() -> integer Returns the current partition id. @@ -30,8 +34,4 @@ Miscellaneous Functions ``seed`` and the configuration `spark.partition_id`. ``seed`` must be constant. :: - SELECT uuid(0); -- "8c7f0aac-97c4-4a2f-b716-a675d821ccc0" - - -.. spark:function:: raise_error(str) -> void - Throws an runtime exception with ``str``. \ No newline at end of file + SELECT uuid(0); -- "8c7f0aac-97c4-4a2f-b716-a675d821ccc0" \ No newline at end of file diff --git a/velox/functions/sparksql/RaiseError.h b/velox/functions/sparksql/RaiseError.h index f36844a7cd43..655197cedf65 100644 --- a/velox/functions/sparksql/RaiseError.h +++ b/velox/functions/sparksql/RaiseError.h @@ -15,7 +15,6 @@ */ #pragma once -#include #include "velox/functions/Macros.h" namespace facebook::velox::functions::sparksql { @@ -23,10 +22,10 @@ template struct RaiseErrorFunction { VELOX_DEFINE_FUNCTION_TYPES(T); - FOLLY_ALWAYS_INLINE bool call( + FOLLY_ALWAYS_INLINE void call( UnknownValue& result, const arg_type& input) { throw std::runtime_error(input); } }; -} // namespace facebook::velox::functions::sparksql \ No newline at end of file +} // namespace facebook::velox::functions::sparksql diff --git a/velox/functions/sparksql/tests/RaiseErrorTest.cpp b/velox/functions/sparksql/tests/RaiseErrorTest.cpp index 419a89a62655..c9891e521ab7 100644 --- a/velox/functions/sparksql/tests/RaiseErrorTest.cpp +++ b/velox/functions/sparksql/tests/RaiseErrorTest.cpp @@ -25,16 +25,11 @@ class RaiseErrorTest : public SparkFunctionBaseTest { void raiseError(const std::optional& errMsg) { evaluateOnce("raise_error(c0)", errMsg); } - void testRaiseError( - const std::optional& errMsg, - std::string expectedMsg) { - VELOX_ASSERT_THROW(raiseError(errMsg), expectedMsg); - } }; TEST_F(RaiseErrorTest, basic) { - testRaiseError("", ""); - testRaiseError("0 > 1 is not true", "0 > 1 is not true"); + VELOX_ASSERT_THROW(raiseError(""), ""); + VELOX_ASSERT_THROW(raiseError("0 > 1 is not true"), "0 > 1 is not true"); } } // namespace } // namespace facebook::velox::functions::sparksql::test From 51d523ac573a3073d76c6aa0ca8fbe23e6f7152f Mon Sep 17 00:00:00 2001 From: gaoyangxiaozhu Date: Wed, 12 Jun 2024 10:55:48 +0800 Subject: [PATCH 04/13] small change --- velox/docs/functions/spark/misc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/velox/docs/functions/spark/misc.rst b/velox/docs/functions/spark/misc.rst index 7a381f6c42ba..86228be442a0 100644 --- a/velox/docs/functions/spark/misc.rst +++ b/velox/docs/functions/spark/misc.rst @@ -34,4 +34,4 @@ Miscellaneous Functions ``seed`` and the configuration `spark.partition_id`. ``seed`` must be constant. :: - SELECT uuid(0); -- "8c7f0aac-97c4-4a2f-b716-a675d821ccc0" \ No newline at end of file + SELECT uuid(0); -- "8c7f0aac-97c4-4a2f-b716-a675d821ccc0" From 4fc2dac1bd111977f78e9f4f4b14414f2f4cd137 Mon Sep 17 00:00:00 2001 From: gaoyangxiaozhu Date: Mon, 17 Jun 2024 14:27:15 +0800 Subject: [PATCH 05/13] address comments --- velox/docs/functions/spark/misc.rst | 4 ++-- velox/functions/sparksql/RaiseError.h | 7 +++++++ velox/functions/sparksql/tests/RaiseErrorTest.cpp | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/velox/docs/functions/spark/misc.rst b/velox/docs/functions/spark/misc.rst index 86228be442a0..3bc4f0fe2963 100644 --- a/velox/docs/functions/spark/misc.rst +++ b/velox/docs/functions/spark/misc.rst @@ -13,9 +13,9 @@ Miscellaneous Functions The function relies on partition IDs, which are provided by the framework via the configuration 'spark.partition_id'. -.. spark:function:: raise_error(str) -> void +.. spark:function:: raise_error(str) - Throws an runtime exception with ``str``. + Throws a runtime exception with the specified message ``str``. .. spark:function:: spark_partition_id() -> integer diff --git a/velox/functions/sparksql/RaiseError.h b/velox/functions/sparksql/RaiseError.h index 655197cedf65..ea823ad903e9 100644 --- a/velox/functions/sparksql/RaiseError.h +++ b/velox/functions/sparksql/RaiseError.h @@ -27,5 +27,12 @@ struct RaiseErrorFunction { const arg_type& input) { throw std::runtime_error(input); } + + template + FOLLY_ALWAYS_INLINE void callNullable( + UnknownValue& result, + const TInput* /*input*/) { + throw std::runtime_error(""); + } }; } // namespace facebook::velox::functions::sparksql diff --git a/velox/functions/sparksql/tests/RaiseErrorTest.cpp b/velox/functions/sparksql/tests/RaiseErrorTest.cpp index c9891e521ab7..1e0ed3044f57 100644 --- a/velox/functions/sparksql/tests/RaiseErrorTest.cpp +++ b/velox/functions/sparksql/tests/RaiseErrorTest.cpp @@ -30,6 +30,7 @@ class RaiseErrorTest : public SparkFunctionBaseTest { TEST_F(RaiseErrorTest, basic) { VELOX_ASSERT_THROW(raiseError(""), ""); VELOX_ASSERT_THROW(raiseError("0 > 1 is not true"), "0 > 1 is not true"); + VELOX_ASSERT_THROW(raiseError(std::nullopt), ""); } } // namespace } // namespace facebook::velox::functions::sparksql::test From 889900153110ac2848bd7d924dadd31ce971fba7 Mon Sep 17 00:00:00 2001 From: gaoyangxiaozhu Date: Mon, 17 Jun 2024 20:09:49 +0800 Subject: [PATCH 06/13] address comment --- velox/functions/sparksql/RaiseError.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/velox/functions/sparksql/RaiseError.h b/velox/functions/sparksql/RaiseError.h index ea823ad903e9..b46fac86d67f 100644 --- a/velox/functions/sparksql/RaiseError.h +++ b/velox/functions/sparksql/RaiseError.h @@ -22,17 +22,14 @@ template struct RaiseErrorFunction { VELOX_DEFINE_FUNCTION_TYPES(T); - FOLLY_ALWAYS_INLINE void call( - UnknownValue& result, - const arg_type& input) { - throw std::runtime_error(input); - } - template FOLLY_ALWAYS_INLINE void callNullable( UnknownValue& result, - const TInput* /*input*/) { - throw std::runtime_error(""); + const TInput* input) { + if (input) { + VELOX_FAIL(*input); + } + VELOX_FAIL(""); } }; } // namespace facebook::velox::functions::sparksql From 6e99d9bdc3c71d6ff8cb824a6f460ac318334190 Mon Sep 17 00:00:00 2001 From: gaoyangxiaozhu Date: Tue, 18 Jun 2024 16:41:37 +0800 Subject: [PATCH 07/13] skip raise_error fuzzer test due to it throw runtime error --- velox/expression/fuzzer/SparkExpressionFuzzerTest.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/velox/expression/fuzzer/SparkExpressionFuzzerTest.cpp b/velox/expression/fuzzer/SparkExpressionFuzzerTest.cpp index ffba105e2e08..450f72f0e4ad 100644 --- a/velox/expression/fuzzer/SparkExpressionFuzzerTest.cpp +++ b/velox/expression/fuzzer/SparkExpressionFuzzerTest.cpp @@ -54,7 +54,8 @@ int main(int argc, char** argv) { "chr", "replace", "might_contain", - "unix_timestamp"}; + "unix_timestamp", + "raise_error"}; // Required by spark_partition_id function. std::unordered_map queryConfigs = { From 1937da477372800a67eeda89f4c2058c1ee38349 Mon Sep 17 00:00:00 2001 From: gaoyangxiaozhu Date: Wed, 19 Jun 2024 18:09:46 +0800 Subject: [PATCH 08/13] address comment --- velox/docs/functions/spark/misc.rst | 4 ++-- velox/functions/sparksql/RaiseError.h | 9 ++++----- velox/functions/sparksql/tests/RaiseErrorTest.cpp | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/velox/docs/functions/spark/misc.rst b/velox/docs/functions/spark/misc.rst index 3bc4f0fe2963..a3153cb9a2c9 100644 --- a/velox/docs/functions/spark/misc.rst +++ b/velox/docs/functions/spark/misc.rst @@ -13,9 +13,9 @@ Miscellaneous Functions The function relies on partition IDs, which are provided by the framework via the configuration 'spark.partition_id'. -.. spark:function:: raise_error(str) +.. spark:function:: raise_error(message) - Throws a runtime exception with the specified message ``str``. + Throws a user error with the specified message ``message``. .. spark:function:: spark_partition_id() -> integer diff --git a/velox/functions/sparksql/RaiseError.h b/velox/functions/sparksql/RaiseError.h index b46fac86d67f..301dd8585970 100644 --- a/velox/functions/sparksql/RaiseError.h +++ b/velox/functions/sparksql/RaiseError.h @@ -22,14 +22,13 @@ template struct RaiseErrorFunction { VELOX_DEFINE_FUNCTION_TYPES(T); - template FOLLY_ALWAYS_INLINE void callNullable( - UnknownValue& result, - const TInput* input) { + out_type& result, + const arg_type* input) { if (input) { - VELOX_FAIL(*input); + VELOX_USER_FAIL(*input); } - VELOX_FAIL(""); + VELOX_USER_FAIL(""); } }; } // namespace facebook::velox::functions::sparksql diff --git a/velox/functions/sparksql/tests/RaiseErrorTest.cpp b/velox/functions/sparksql/tests/RaiseErrorTest.cpp index 1e0ed3044f57..79214033fe2c 100644 --- a/velox/functions/sparksql/tests/RaiseErrorTest.cpp +++ b/velox/functions/sparksql/tests/RaiseErrorTest.cpp @@ -22,8 +22,8 @@ namespace { class RaiseErrorTest : public SparkFunctionBaseTest { protected: - void raiseError(const std::optional& errMsg) { - evaluateOnce("raise_error(c0)", errMsg); + void raiseError(const std::optional& message) { + evaluateOnce("raise_error(c0)", message); } }; From 9404101224fc48b3ec07bdf11f5e2fb702a5507b Mon Sep 17 00:00:00 2001 From: gaoyangxiaozhu Date: Wed, 19 Jun 2024 21:40:18 +0800 Subject: [PATCH 09/13] address comment --- velox/docs/functions/spark/misc.rst | 2 +- velox/expression/fuzzer/SparkExpressionFuzzerTest.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/velox/docs/functions/spark/misc.rst b/velox/docs/functions/spark/misc.rst index a3153cb9a2c9..52696c2657a5 100644 --- a/velox/docs/functions/spark/misc.rst +++ b/velox/docs/functions/spark/misc.rst @@ -15,7 +15,7 @@ Miscellaneous Functions .. spark:function:: raise_error(message) - Throws a user error with the specified message ``message``. + Throws a user error with the specified ``message``. .. spark:function:: spark_partition_id() -> integer diff --git a/velox/expression/fuzzer/SparkExpressionFuzzerTest.cpp b/velox/expression/fuzzer/SparkExpressionFuzzerTest.cpp index 450f72f0e4ad..ffba105e2e08 100644 --- a/velox/expression/fuzzer/SparkExpressionFuzzerTest.cpp +++ b/velox/expression/fuzzer/SparkExpressionFuzzerTest.cpp @@ -54,8 +54,7 @@ int main(int argc, char** argv) { "chr", "replace", "might_contain", - "unix_timestamp", - "raise_error"}; + "unix_timestamp"}; // Required by spark_partition_id function. std::unordered_map queryConfigs = { From 5dc24b00d5ac2539b67f08679eb88394fb411e1d Mon Sep 17 00:00:00 2001 From: gaoyangxiaozhu Date: Thu, 20 Jun 2024 20:18:26 +0800 Subject: [PATCH 10/13] address comment --- velox/functions/sparksql/tests/RaiseErrorTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/velox/functions/sparksql/tests/RaiseErrorTest.cpp b/velox/functions/sparksql/tests/RaiseErrorTest.cpp index 79214033fe2c..716428a8d962 100644 --- a/velox/functions/sparksql/tests/RaiseErrorTest.cpp +++ b/velox/functions/sparksql/tests/RaiseErrorTest.cpp @@ -28,9 +28,9 @@ class RaiseErrorTest : public SparkFunctionBaseTest { }; TEST_F(RaiseErrorTest, basic) { - VELOX_ASSERT_THROW(raiseError(""), ""); - VELOX_ASSERT_THROW(raiseError("0 > 1 is not true"), "0 > 1 is not true"); - VELOX_ASSERT_THROW(raiseError(std::nullopt), ""); + VELOX_ASSERT_USER_THROW(raiseError(""), ""); + VELOX_ASSERT_USER_THROW(raiseError("0 > 1 is not true"), "0 > 1 is not true"); + VELOX_ASSERT_USER_THROW(raiseError(std::nullopt), ""); } } // namespace } // namespace facebook::velox::functions::sparksql::test From 9e8848f111fa48bf32562c20a06d093fdb9e81fe Mon Sep 17 00:00:00 2001 From: gaoyangxiaozhu Date: Fri, 28 Jun 2024 16:13:03 +0800 Subject: [PATCH 11/13] update --- velox/functions/sparksql/RaiseError.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/velox/functions/sparksql/RaiseError.h b/velox/functions/sparksql/RaiseError.h index 301dd8585970..194ec23bc58d 100644 --- a/velox/functions/sparksql/RaiseError.h +++ b/velox/functions/sparksql/RaiseError.h @@ -22,13 +22,13 @@ template struct RaiseErrorFunction { VELOX_DEFINE_FUNCTION_TYPES(T); - FOLLY_ALWAYS_INLINE void callNullable( + FOLLY_ALWAYS_INLINE Status callNullable( out_type& result, const arg_type* input) { if (input) { - VELOX_USER_FAIL(*input); + return Status::UserError("{}", *input); } - VELOX_USER_FAIL(""); + return Status::UserError("{}", ""); } }; } // namespace facebook::velox::functions::sparksql From fbc38fda444d5e30734819ea08fb9fcb13cbfb8f Mon Sep 17 00:00:00 2001 From: gaoyangxiaozhu Date: Fri, 28 Jun 2024 16:16:22 +0800 Subject: [PATCH 12/13] format fix --- velox/functions/sparksql/RaiseError.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/velox/functions/sparksql/RaiseError.h b/velox/functions/sparksql/RaiseError.h index 194ec23bc58d..aab2207345cf 100644 --- a/velox/functions/sparksql/RaiseError.h +++ b/velox/functions/sparksql/RaiseError.h @@ -22,9 +22,8 @@ template struct RaiseErrorFunction { VELOX_DEFINE_FUNCTION_TYPES(T); - FOLLY_ALWAYS_INLINE Status callNullable( - out_type& result, - const arg_type* input) { + FOLLY_ALWAYS_INLINE Status + callNullable(out_type& result, const arg_type* input) { if (input) { return Status::UserError("{}", *input); } From bc6b38080935bac0f301e9acd1f1868bcd50aa81 Mon Sep 17 00:00:00 2001 From: gaoyangxiaozhu Date: Fri, 28 Jun 2024 19:00:38 +0800 Subject: [PATCH 13/13] address comment --- velox/docs/functions/spark/misc.rst | 1 + velox/functions/sparksql/RaiseError.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/velox/docs/functions/spark/misc.rst b/velox/docs/functions/spark/misc.rst index 52696c2657a5..0238d8018adc 100644 --- a/velox/docs/functions/spark/misc.rst +++ b/velox/docs/functions/spark/misc.rst @@ -16,6 +16,7 @@ Miscellaneous Functions .. spark:function:: raise_error(message) Throws a user error with the specified ``message``. + If ``message`` is NULL, throws a user error with empty message. .. spark:function:: spark_partition_id() -> integer diff --git a/velox/functions/sparksql/RaiseError.h b/velox/functions/sparksql/RaiseError.h index aab2207345cf..9b7e65b22584 100644 --- a/velox/functions/sparksql/RaiseError.h +++ b/velox/functions/sparksql/RaiseError.h @@ -27,7 +27,7 @@ struct RaiseErrorFunction { if (input) { return Status::UserError("{}", *input); } - return Status::UserError("{}", ""); + return Status::UserError(); } }; } // namespace facebook::velox::functions::sparksql