Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions bigquery/google/cloud/bigquery/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

"""Define API Jobs."""

import copy
import threading

import six
Expand Down Expand Up @@ -266,6 +267,11 @@ def ended(self):
if millis is not None:
return _datetime_from_microseconds(millis * 1000.0)

def _job_statistics(self):
"""Helper for job-type specific statistics-based properties."""
statistics = self._properties.get('statistics', {})
return statistics.get(self._JOB_TYPE, {})

@property
def error_result(self):
"""Error information about the job as a whole.
Expand Down Expand Up @@ -1278,6 +1284,20 @@ def from_api_repr(cls, resource, client):
job._set_properties(resource)
return job

@property
def query_plan(self):

This comment was marked as spam.

"""Return query plan from job statistics, if present.

See:
https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs#statistics.query.queryPlan

:rtype: list of dict
:returns: mappings describing the query plan, or an empty list
if the query has not yet completed.
"""
plan_entries = self._job_statistics().get('queryPlan', ())
return [copy.deepcopy(entry) for entry in plan_entries]

def query_results(self):
"""Construct a QueryResults instance, bound to this job.

Expand Down
33 changes: 33 additions & 0 deletions bigquery/tests/unit/test_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,39 @@ def test_cancelled(self):

self.assertTrue(job.cancelled())

def test_query_plan(self):
plan_entries = [{
'name': 'NAME',
'id': 1234,
'waitRatioAvg': 2.71828,
'waitRatioMax': 3.14159,
'readRatioAvg': 1.41421,
'readRatioMax': 1.73205,
'computeRatioAvg': 0.69315,
'computeRatioMax': 1.09861,
'writeRatioAvg': 3.32193,
'writeRatioMax': 2.30258,
'recordsRead': 100,

This comment was marked as spam.

'recordsWritten': 1,

This comment was marked as spam.

'status': 'STATUS',
'steps': [{
'kind': 'KIND',
'substeps': ['SUBSTEP1', 'SUBSTEP2'],
}],
}]
client = _Client(self.PROJECT)
job = self._make_one(self.JOB_NAME, self.QUERY, client)
self.assertEqual(job.query_plan, [])

statistics = job._properties['statistics'] = {}
self.assertEqual(job.query_plan, [])

query_stats = statistics['query'] = {}
self.assertEqual(job.query_plan, [])

query_stats['queryPlan'] = plan_entries
self.assertEqual(job.query_plan, plan_entries)

def test_query_results(self):
from google.cloud.bigquery.query import QueryResults

Expand Down