File tree Expand file tree Collapse file tree 8 files changed +47
-0
lines changed
Expand file tree Collapse file tree 8 files changed +47
-0
lines changed Original file line number Diff line number Diff line change @@ -560,6 +560,7 @@ def do_query():
560560 num_dml_affected_rows = query_results .num_dml_affected_rows ,
561561 query = query ,
562562 total_bytes_processed = query_results .total_bytes_processed ,
563+ slot_millis = query_results .slot_millis ,
563564 )
564565
565566 if job_retry is not None :
Original file line number Diff line number Diff line change @@ -4144,6 +4144,7 @@ def _list_rows_from_query_results(
41444144 num_dml_affected_rows : Optional [int ] = None ,
41454145 query : Optional [str ] = None ,
41464146 total_bytes_processed : Optional [int ] = None ,
4147+ slot_millis : Optional [int ] = None ,
41474148 ) -> RowIterator :
41484149 """List the rows of a completed query.
41494150 See
@@ -4195,6 +4196,8 @@ def _list_rows_from_query_results(
41954196 The query text used.
41964197 total_bytes_processed (Optional[int]):
41974198 total bytes processed from job statistics, if present.
4199+ slot_millis (Optional[int]):
4200+ Number of slot ms the user is actually billed for.
41984201
41994202 Returns:
42004203 google.cloud.bigquery.table.RowIterator:
@@ -4234,6 +4237,7 @@ def _list_rows_from_query_results(
42344237 num_dml_affected_rows = num_dml_affected_rows ,
42354238 query = query ,
42364239 total_bytes_processed = total_bytes_processed ,
4240+ slot_millis = slot_millis ,
42374241 )
42384242 return row_iterator
42394243
Original file line number Diff line number Diff line change @@ -1766,6 +1766,7 @@ def is_job_done():
17661766 num_dml_affected_rows = self ._query_results .num_dml_affected_rows ,
17671767 query = self .query ,
17681768 total_bytes_processed = self .total_bytes_processed ,
1769+ slot_millis = self .slot_millis ,
17691770 ** list_rows_kwargs ,
17701771 )
17711772 rows ._preserve_order = _contains_order_by (self .query )
Original file line number Diff line number Diff line change @@ -1282,6 +1282,20 @@ def total_bytes_processed(self):
12821282 if total_bytes_processed is not None :
12831283 return int (total_bytes_processed )
12841284
1285+ @property
1286+ def slot_millis (self ):
1287+ """Total number of slot ms the user is actually billed for.
1288+
1289+ See:
1290+ https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query#body.QueryResponse.FIELDS.slot_millis
1291+
1292+ Returns:
1293+ Optional[int]: Count generated on the server (None until set by the server).
1294+ """
1295+ slot_millis = self ._properties .get ("totalSlotMs" )
1296+ if slot_millis is not None :
1297+ return int (slot_millis )
1298+
12851299 @property
12861300 def num_dml_affected_rows (self ):
12871301 """Total number of rows affected by a DML query.
Original file line number Diff line number Diff line change @@ -1812,6 +1812,7 @@ def __init__(
18121812 num_dml_affected_rows : Optional [int ] = None ,
18131813 query : Optional [str ] = None ,
18141814 total_bytes_processed : Optional [int ] = None ,
1815+ slot_millis : Optional [int ] = None ,
18151816 ):
18161817 super (RowIterator , self ).__init__ (
18171818 client ,
@@ -1841,6 +1842,7 @@ def __init__(
18411842 self ._num_dml_affected_rows = num_dml_affected_rows
18421843 self ._query = query
18431844 self ._total_bytes_processed = total_bytes_processed
1845+ self ._slot_millis = slot_millis
18441846
18451847 @property
18461848 def _billing_project (self ) -> Optional [str ]:
@@ -1898,6 +1900,11 @@ def total_bytes_processed(self) -> Optional[int]:
18981900 """total bytes processed from job statistics, if present."""
18991901 return self ._total_bytes_processed
19001902
1903+ @property
1904+ def slot_millis (self ) -> Optional [int ]:
1905+ """Number of slot ms the user is actually billed for."""
1906+ return self ._slot_millis
1907+
19011908 def _is_almost_completely_cached (self ):
19021909 """Check if all results are completely cached.
19031910
Original file line number Diff line number Diff line change @@ -888,6 +888,7 @@ def test_result_reloads_job_state_until_done(self):
888888 job_resource = self ._make_resource (started = True , location = "EU" )
889889 job_resource_done = self ._make_resource (started = True , ended = True , location = "EU" )
890890 job_resource_done ["statistics" ]["query" ]["totalBytesProcessed" ] = str (1234 )
891+ job_resource_done ["statistics" ]["query" ]["totalSlotMs" ] = str (5678 )
891892 job_resource_done ["configuration" ]["query" ]["destinationTable" ] = {
892893 "projectId" : "dest-project" ,
893894 "datasetId" : "dest_dataset" ,
@@ -969,6 +970,7 @@ def test_result_reloads_job_state_until_done(self):
969970 self .assertEqual (result .total_rows , 1 )
970971 self .assertEqual (result .query , job .query )
971972 self .assertEqual (result .total_bytes_processed , 1234 )
973+ self .assertEqual (result .slot_millis , 5678 )
972974
973975 query_results_path = f"/projects/{ self .PROJECT } /queries/{ self .JOB_ID } "
974976 query_results_call = mock .call (
Original file line number Diff line number Diff line change @@ -5718,6 +5718,7 @@ def test_query_and_wait_defaults(self):
57185718 "rows" : [{"f" : [{"v" : "5552452" }]}],
57195719 "queryId" : "job_abcDEF_" ,
57205720 "totalBytesProcessed" : 1234 ,
5721+ "totalSlotMs" : 5678 ,
57215722 }
57225723 creds = _make_credentials ()
57235724 http = object ()
@@ -5735,6 +5736,7 @@ def test_query_and_wait_defaults(self):
57355736 self .assertIsNone (rows .location )
57365737 self .assertEqual (rows .query , query )
57375738 self .assertEqual (rows .total_bytes_processed , 1234 )
5739+ self .assertEqual (rows .slot_millis , 5678 )
57385740
57395741 # Verify the request we send is to jobs.query.
57405742 conn .api_request .assert_called_once ()
Original file line number Diff line number Diff line change @@ -2000,6 +2000,22 @@ def test_total_bytes_processed_present_string(self):
20002000 query = self ._make_one (resource )
20012001 self .assertEqual (query .total_bytes_processed , 123456 )
20022002
2003+ def test_slot_millis_missing (self ):
2004+ query = self ._make_one (self ._make_resource ())
2005+ self .assertIsNone (query .slot_millis )
2006+
2007+ def test_slot_millis_present_integer (self ):
2008+ resource = self ._make_resource ()
2009+ resource ["totalSlotMs" ] = 123456
2010+ query = self ._make_one (resource )
2011+ self .assertEqual (query .slot_millis , 123456 )
2012+
2013+ def test_slot_millis_present_string (self ):
2014+ resource = self ._make_resource ()
2015+ resource ["totalSlotMs" ] = "123456"
2016+ query = self ._make_one (resource )
2017+ self .assertEqual (query .slot_millis , 123456 )
2018+
20032019 def test_num_dml_affected_rows_missing (self ):
20042020 query = self ._make_one (self ._make_resource ())
20052021 self .assertIsNone (query .num_dml_affected_rows )
You can’t perform that action at this time.
0 commit comments