Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 067cacd

Browse files
committed
Add new scalar statistics properties to 'QueryJob' (googleapis#3800)
* Add 'QueryJob.total_bytes_processed' property. * Add 'QueryJob.total_bytes_billed' property. * Add 'QueryJob.billing_tier' property. * Add 'QueryJob.cache_hit' property. * Add 'QueryJob.num_dml_affected_rows' property. * Add 'QueryJob.statement_type' property.
1 parent 029082f commit 067cacd

File tree

2 files changed

+176
-0
lines changed

2 files changed

+176
-0
lines changed

bigquery/google/cloud/bigquery/job.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,6 +1300,93 @@ def query_plan(self):
13001300
plan_entries = self._job_statistics().get('queryPlan', ())
13011301
return [QueryPlanEntry.from_api_repr(entry) for entry in plan_entries]
13021302

1303+
@property
1304+
def total_bytes_processed(self):
1305+
"""Return total bytes processed from job statistics, if present.
1306+
1307+
See:
1308+
https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs#statistics.query.totalBytesProcessed
1309+
1310+
:rtype: int or None
1311+
:returns: total bytes processed by the job, or None if job is not
1312+
yet complete.
1313+
"""
1314+
result = self._job_statistics().get('totalBytesProcessed')
1315+
if result is not None:
1316+
result = int(result)
1317+
return result
1318+
1319+
@property
1320+
def total_bytes_billed(self):
1321+
"""Return total bytes billed from job statistics, if present.
1322+
1323+
See:
1324+
https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs#statistics.query.totalBytesBilled
1325+
1326+
:rtype: int or None
1327+
:returns: total bytes processed by the job, or None if job is not
1328+
yet complete.
1329+
"""
1330+
result = self._job_statistics().get('totalBytesBilled')
1331+
if result is not None:
1332+
result = int(result)
1333+
return result
1334+
1335+
@property
1336+
def billing_tier(self):
1337+
"""Return billing tier from job statistics, if present.
1338+
1339+
See:
1340+
https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs#statistics.query.billingTier
1341+
1342+
:rtype: int or None
1343+
:returns: billing tier used by the job, or None if job is not
1344+
yet complete.
1345+
"""
1346+
return self._job_statistics().get('billingTier')
1347+
1348+
@property
1349+
def cache_hit(self):
1350+
"""Return billing tier from job statistics, if present.
1351+
1352+
See:
1353+
https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs#statistics.query.cacheHit
1354+
1355+
:rtype: bool or None
1356+
:returns: whether the query results were returned from cache, or None
1357+
if job is not yet complete.
1358+
"""
1359+
return self._job_statistics().get('cacheHit')
1360+
1361+
@property
1362+
def num_dml_affected_rows(self):
1363+
"""Return total bytes billed from job statistics, if present.
1364+
1365+
See:
1366+
https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs#statistics.query.numDmlAffectedRows
1367+
1368+
:rtype: int or None
1369+
:returns: number of DML rows affectd by the job, or None if job is not
1370+
yet complete.
1371+
"""
1372+
result = self._job_statistics().get('numDmlAffectedRows')
1373+
if result is not None:
1374+
result = int(result)
1375+
return result
1376+
1377+
@property
1378+
def statement_type(self):
1379+
"""Return statement type from job statistics, if present.
1380+
1381+
See:
1382+
https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs#statistics.query.statementType
1383+
1384+
:rtype: str or None
1385+
:returns: type of statement used by the job, or None if job is not
1386+
yet complete.
1387+
"""
1388+
return self._job_statistics().get('statementType')
1389+
13031390
def query_results(self):
13041391
"""Construct a QueryResults instance, bound to this job.
13051392

bigquery/tests/unit/test_job.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,95 @@ def test_query_plan(self):
17441744
self.assertEqual(f_step.kind, e_step['kind'])
17451745
self.assertEqual(f_step.substeps, e_step['substeps'])
17461746

1747+
def test_total_bytes_processed(self):
1748+
total_bytes = 1234
1749+
client = _Client(self.PROJECT)
1750+
job = self._make_one(self.JOB_NAME, self.QUERY, client)
1751+
self.assertIsNone(job.total_bytes_processed)
1752+
1753+
statistics = job._properties['statistics'] = {}
1754+
self.assertIsNone(job.total_bytes_processed)
1755+
1756+
query_stats = statistics['query'] = {}
1757+
self.assertIsNone(job.total_bytes_processed)
1758+
1759+
query_stats['totalBytesProcessed'] = str(total_bytes)
1760+
self.assertEqual(job.total_bytes_processed, total_bytes)
1761+
1762+
def test_total_bytes_billed(self):
1763+
total_bytes = 1234
1764+
client = _Client(self.PROJECT)
1765+
job = self._make_one(self.JOB_NAME, self.QUERY, client)
1766+
self.assertIsNone(job.total_bytes_billed)
1767+
1768+
statistics = job._properties['statistics'] = {}
1769+
self.assertIsNone(job.total_bytes_billed)
1770+
1771+
query_stats = statistics['query'] = {}
1772+
self.assertIsNone(job.total_bytes_billed)
1773+
1774+
query_stats['totalBytesBilled'] = str(total_bytes)
1775+
self.assertEqual(job.total_bytes_billed, total_bytes)
1776+
1777+
def test_billing_tier(self):
1778+
billing_tier = 1
1779+
client = _Client(self.PROJECT)
1780+
job = self._make_one(self.JOB_NAME, self.QUERY, client)
1781+
self.assertIsNone(job.billing_tier)
1782+
1783+
statistics = job._properties['statistics'] = {}
1784+
self.assertIsNone(job.billing_tier)
1785+
1786+
query_stats = statistics['query'] = {}
1787+
self.assertIsNone(job.billing_tier)
1788+
1789+
query_stats['billingTier'] = billing_tier
1790+
self.assertEqual(job.billing_tier, billing_tier)
1791+
1792+
def test_cache_hit(self):
1793+
client = _Client(self.PROJECT)
1794+
job = self._make_one(self.JOB_NAME, self.QUERY, client)
1795+
self.assertIsNone(job.cache_hit)
1796+
1797+
statistics = job._properties['statistics'] = {}
1798+
self.assertIsNone(job.cache_hit)
1799+
1800+
query_stats = statistics['query'] = {}
1801+
self.assertIsNone(job.cache_hit)
1802+
1803+
query_stats['cacheHit'] = True
1804+
self.assertTrue(job.cache_hit)
1805+
1806+
def test_num_dml_affected_rows(self):
1807+
num_rows = 1234
1808+
client = _Client(self.PROJECT)
1809+
job = self._make_one(self.JOB_NAME, self.QUERY, client)
1810+
self.assertIsNone(job.num_dml_affected_rows)
1811+
1812+
statistics = job._properties['statistics'] = {}
1813+
self.assertIsNone(job.num_dml_affected_rows)
1814+
1815+
query_stats = statistics['query'] = {}
1816+
self.assertIsNone(job.num_dml_affected_rows)
1817+
1818+
query_stats['numDmlAffectedRows'] = str(num_rows)
1819+
self.assertEqual(job.num_dml_affected_rows, num_rows)
1820+
1821+
def test_statement_type(self):
1822+
statement_type = 'SELECT'
1823+
client = _Client(self.PROJECT)
1824+
job = self._make_one(self.JOB_NAME, self.QUERY, client)
1825+
self.assertIsNone(job.statement_type)
1826+
1827+
statistics = job._properties['statistics'] = {}
1828+
self.assertIsNone(job.statement_type)
1829+
1830+
query_stats = statistics['query'] = {}
1831+
self.assertIsNone(job.statement_type)
1832+
1833+
query_stats['statementType'] = statement_type
1834+
self.assertEqual(job.statement_type, statement_type)
1835+
17471836
def test_query_results(self):
17481837
from google.cloud.bigquery.query import QueryResults
17491838

0 commit comments

Comments
 (0)