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

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


The following commit(s) were added to refs/heads/master by this push:
     new 9b2d7a4cd17b [SPARK-54532][PYTHON] Add support for sqlstate for 
PySparkException
9b2d7a4cd17b is described below

commit 9b2d7a4cd17bd2854439f9680095b47222b04452
Author: Tian Gao <[email protected]>
AuthorDate: Thu Nov 27 16:57:04 2025 +0900

    [SPARK-54532][PYTHON] Add support for sqlstate for PySparkException
    
    ### What changes were proposed in this pull request?
    
    Allow `PySparkException` to get `sqlstate` from the json file.
    
    ### Why are the changes needed?
    
    It's useful for python client to throw exceptions with sqlstate.
    
    ### Does this PR introduce _any_ user-facing change?
    
    For this specific PR no. It's an infra to have more sqlstate in the future.
    
    ### How was this patch tested?
    
    A feature test is added. However, we don't have any sqlstate assigned to 
python exceptions now - so we can't test the positive case. The future PRs will 
add more sqlstate and we can test then.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    No
    
    Closes #53241 from gaogaotiantian/support-sqlstate.
    
    Authored-by: Tian Gao <[email protected]>
    Signed-off-by: Hyukjin Kwon <[email protected]>
---
 python/pyspark/errors/exceptions/base.py   |  4 ++--
 python/pyspark/errors/tests/test_errors.py | 12 +++++++++++-
 python/pyspark/errors/utils.py             | 18 ++++++++++++++++++
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/python/pyspark/errors/exceptions/base.py 
b/python/pyspark/errors/exceptions/base.py
index 84da3c345e92..157997da8d70 100644
--- a/python/pyspark/errors/exceptions/base.py
+++ b/python/pyspark/errors/exceptions/base.py
@@ -110,7 +110,7 @@ class PySparkException(Exception):
         """
         Returns an SQLSTATE as a string.
 
-        Errors generated in Python have no SQLSTATE, so it always returns None.
+        If the errorClass has no corresponding SQLSTATE, it returns None.
 
         .. versionadded:: 3.4.0
 
@@ -121,7 +121,7 @@ class PySparkException(Exception):
         :meth:`PySparkException.getMessageParameters`
         :meth:`PySparkException.getQueryContext`
         """
-        return None
+        return self._error_reader.get_sqlstate(self._errorClass)
 
     def getMessage(self) -> str:
         """
diff --git a/python/pyspark/errors/tests/test_errors.py 
b/python/pyspark/errors/tests/test_errors.py
index d0565a40d222..d87b284d4fd2 100644
--- a/python/pyspark/errors/tests/test_errors.py
+++ b/python/pyspark/errors/tests/test_errors.py
@@ -19,7 +19,7 @@
 import json
 import unittest
 
-from pyspark.errors import PySparkValueError
+from pyspark.errors import PySparkRuntimeError, PySparkValueError
 from pyspark.errors.error_classes import ERROR_CLASSES_JSON
 from pyspark.errors.utils import ErrorClassesReader
 
@@ -108,6 +108,16 @@ class ErrorsTest(unittest.TestCase):
         subclass_map = 
error_reader.error_info_map["TEST_ERROR_WITH_SUB_CLASS"]["sub_class"]
         self.assertEqual(breaking_change_info2, 
subclass_map["SUBCLASS"]["breaking_change_info"])
 
+    def test_sqlstate(self):
+        error = PySparkRuntimeError(errorClass="APPLICATION_NAME_NOT_SET", 
messageParameters={})
+        self.assertIsNone(error.getSqlState())
+
+        error = PySparkRuntimeError(
+            
errorClass="SESSION_MUTATION_IN_DECLARATIVE_PIPELINE.SET_RUNTIME_CONF",
+            messageParameters={"method": "set"},
+        )
+        self.assertIsNone(error.getSqlState())
+
 
 if __name__ == "__main__":
     import unittest
diff --git a/python/pyspark/errors/utils.py b/python/pyspark/errors/utils.py
index 43bd871c564d..b5c361702ae0 100644
--- a/python/pyspark/errors/utils.py
+++ b/python/pyspark/errors/utils.py
@@ -95,6 +95,24 @@ class ErrorClassesReader:
     def __init__(self) -> None:
         self.error_info_map = ERROR_CLASSES_MAP
 
+    def get_sqlstate(self, errorClass: Optional[str]) -> Optional[str]:
+        """
+        Returns the SQL state for the given error class.
+        """
+        if errorClass is None:
+            return None
+
+        error_classes = errorClass.split(".")
+        try:
+            if len(error_classes) == 1:
+                return self.error_info_map[errorClass]["sqlState"]
+            else:
+                return 
self.error_info_map[error_classes[0]]["sub_class"][error_classes[1]][
+                    "sqlState"
+                ]
+        except KeyError:
+            return None
+
     def get_error_message(self, errorClass: str, messageParameters: Dict[str, 
str]) -> str:
         """
         Returns the completed error message by applying message parameters to 
the message template.


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to