Repository: googleapis/python-bigquery
Pull request #2145 (2025-03-12 22:39:56)

feat: add preview support for incremental results
This PR adds a new property to JobConfig to enable incremental results, a preview feature.  It also plumbs this through to the faster query path via a QueryRequest to jobs.query.

internal: b/390240540

Linchin: Will this feature affect how we fetch query results? If not, the PR LGTM.
shollyman: > Will this feature affect how we fetch query results? If not, the PR LGTM.

It doesn't alter row iteration/retrieval.

Patch:
diff --git a/google/cloud/bigquery/_job_helpers.py b/google/cloud/bigquery/_job_helpers.py
index a8373c35..9193f818 100644
--- a/google/cloud/bigquery/_job_helpers.py
+++ b/google/cloud/bigquery/_job_helpers.py
@@ -564,6 +564,7 @@ def _supported_by_jobs_query(request_body: Dict[str, Any]) -> bool:
         "maximumBytesBilled",
         "requestId",
         "createSession",
+        "writeIncrementalResults",
     }
 
     unsupported_keys = request_keys - keys_allowlist
diff --git a/google/cloud/bigquery/job/query.py b/google/cloud/bigquery/job/query.py
index a27c1053..f14039bc 100644
--- a/google/cloud/bigquery/job/query.py
+++ b/google/cloud/bigquery/job/query.py
@@ -674,6 +674,21 @@ class QueryJobConfig(_JobConfig):
     def write_disposition(self, value):
         self._set_sub_prop("writeDisposition", value)
 
+    @property
+    def write_incremental_results(self) -> Optional[bool]:
+        """This is only supported for a SELECT query using a temporary table.
+
+        If set, the query is allowed to write results incrementally to the temporary result
+        table. This may incur a performance penalty. This option cannot be used with Legacy SQL.
+
+        This feature is not generally available.
+        """
+        return self._get_sub_prop("writeIncrementalResults")
+
+    @write_incremental_results.setter
+    def write_incremental_results(self, value):
+        self._set_sub_prop("writeIncrementalResults", value)
+
     @property
     def table_definitions(self):
         """Dict[str, google.cloud.bigquery.external_config.ExternalConfig]:


Test patch:
diff --git a/tests/unit/job/test_query_config.py b/tests/unit/job/test_query_config.py
index 7818236f..e0878d06 100644
--- a/tests/unit/job/test_query_config.py
+++ b/tests/unit/job/test_query_config.py
@@ -167,6 +167,11 @@ class TestQueryJobConfig(_Base):
         self.assertEqual(config.connection_properties[1].key, "time_zone")
         self.assertEqual(config.connection_properties[1].value, "America/Chicago")
 
+    def test_incremental_results(self):
+        config = self._get_target_class()()
+        config.write_incremental_results = True
+        self.assertEqual(config.write_incremental_results, True)
+
     def test_create_session(self):
         config = self._get_target_class()()
         self.assertIsNone(config.create_session)
diff --git a/tests/unit/test__job_helpers.py b/tests/unit/test__job_helpers.py
index 96914d9f..4fa093c6 100644
--- a/tests/unit/test__job_helpers.py
+++ b/tests/unit/test__job_helpers.py
@@ -194,6 +194,13 @@ def make_query_response(
             make_query_request({"maximumBytesBilled": "987654"}),
             id="job_config-with-maximum_bytes_billed",
         ),
+        pytest.param(
+            job_query.QueryJobConfig(
+                write_incremental_results=True,
+            ),
+            make_query_request({"writeIncrementalResults": True}),
+            id="job_config-with-incremental-results",
+        ),
     ),
 )
 def test__to_query_request(job_config, expected):
@@ -1141,6 +1148,11 @@ def test_make_job_id_w_job_id_overrides_prefix():
             False,
             id="priority=BATCH",
         ),
+        pytest.param(
+            job_query.QueryJobConfig(write_incremental_results=True),
+            True,
+            id="write_incremental_results",
+        ),
     ),
 )
 def test_supported_by_jobs_query_from_queryjobconfig(