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

eladkal pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 201a9c5af96 Add `accept_none` to `SQLTableCheckOperator` (#63210)
201a9c5af96 is described below

commit 201a9c5af968867958cc66719334c1cfd68380ee
Author: Jake McGrath <[email protected]>
AuthorDate: Mon Apr 13 15:09:11 2026 -0400

    Add `accept_none` to `SQLTableCheckOperator` (#63210)
    
    * issue-30082: Adding accept_none to SQLTableCheckOperator
    
    * Update 
providers/common/sql/src/airflow/providers/common/sql/operators/sql.py
    
    Co-authored-by: Elad Kalif <[email protected]>
    
    * fix static checks
    
    ---------
    
    Co-authored-by: Elad Kalif <[email protected]>
---
 .../sql/src/airflow/providers/common/sql/operators/sql.py | 13 +++++++++++++
 .../sql/tests/unit/common/sql/operators/test_sql.py       | 15 +++++++++++++++
 2 files changed, 28 insertions(+)

diff --git 
a/providers/common/sql/src/airflow/providers/common/sql/operators/sql.py 
b/providers/common/sql/src/airflow/providers/common/sql/operators/sql.py
index 7d8e65df73b..285b4657be6 100644
--- a/providers/common/sql/src/airflow/providers/common/sql/operators/sql.py
+++ b/providers/common/sql/src/airflow/providers/common/sql/operators/sql.py
@@ -714,6 +714,7 @@ class SQLTableCheckOperator(BaseSQLOperator):
 
     :param conn_id: the connection ID used to connect to the database
     :param database: name of database which overwrite the defined one in 
connection
+    :param accept_none: If True, an empty table (row count=0) will not trigger 
a failure.
 
     .. seealso::
         For more information on how to use this operator, take a look at the 
guide:
@@ -738,6 +739,7 @@ class SQLTableCheckOperator(BaseSQLOperator):
         partition_clause: str | None = None,
         conn_id: str | None = None,
         database: str | None = None,
+        accept_none: bool = False,
         **kwargs,
     ):
         super().__init__(conn_id=conn_id, database=database, **kwargs)
@@ -745,6 +747,7 @@ class SQLTableCheckOperator(BaseSQLOperator):
         self.table = table
         self.checks = checks
         self.partition_clause = _initialize_partition_clause(partition_clause)
+        self.accept_none = accept_none
         self.sql = f"SELECT check_name, check_result FROM 
({self._generate_sql_query()}) AS check_table"
 
     def execute(self, context: Context):
@@ -752,6 +755,16 @@ class SQLTableCheckOperator(BaseSQLOperator):
         records = hook.get_records(self.sql)
 
         if not records:
+            # accept_none prevents an error from being thrown if there are no 
records in the table
+            if self.accept_none:
+                self.log.warning(
+                    "No records found for table: %s, but accept_none=True, "
+                    "therefore, no tests are being marked as failed.",
+                    self.table,
+                )
+                return
+
+            # Otherwise, we'll raise an exception
             self._raise_exception(f"The following query returned zero rows: 
{self.sql}")
 
         self.log.info("Record:\n%s", records)
diff --git a/providers/common/sql/tests/unit/common/sql/operators/test_sql.py 
b/providers/common/sql/tests/unit/common/sql/operators/test_sql.py
index abe38efbdb9..08becbc12e1 100644
--- a/providers/common/sql/tests/unit/common/sql/operators/test_sql.py
+++ b/providers/common/sql/tests/unit/common/sql/operators/test_sql.py
@@ -605,6 +605,21 @@ class TestTableCheckOperator:
         finally:
             hook.run(["DROP TABLE employees"])
 
+    def test_sql_check_accept_none_true(self, monkeypatch):
+        """Validate that empty table does not fail when accept_none=True."""
+        records = []
+        operator = self._construct_operator(monkeypatch, self.checks, records)
+        operator.accept_none = True
+        operator.execute(context=MagicMock())
+
+    def test_sql_check_accept_none_false(self, monkeypatch):
+        """Validate that empty table throws an exception when 
accept_none=False."""
+        records = []
+        operator = self._construct_operator(monkeypatch, self.checks, records)
+        operator.accept_none = False  # This is default, technically
+        with pytest.raises(AirflowException):
+            operator.execute(context=MagicMock())
+
     def test_pass_all_checks_check(self, monkeypatch):
         records = [("row_count_check", 1), ("column_sum_check", "y")]
         operator = self._construct_operator(monkeypatch, self.checks, records)

Reply via email to