Skip to content

Commit

Permalink
Adding support for Standard SQL views
Browse files Browse the repository at this point in the history
Change-Id: I61d80c7359663f441006ac39f0b3826f7079bf0c
  • Loading branch information
Jens Larsson committed Dec 22, 2016
1 parent 455eaf6 commit d80b2a0
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 4 deletions.
50 changes: 49 additions & 1 deletion bigquery/google/cloud/bigquery/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,43 @@ def view_query(self, value):
"""
if not isinstance(value, six.string_types):
raise ValueError("Pass a string")
self._properties['view'] = {'query': value}
if 'view' in self._properties:
self._properties['view']['query'] = value
else:
self._properties['view'] = {
'query': value,
'useLegacySql': True
}

@property
def view_use_legacy_sql(self):
"""Boolean value definin SQL dialect of a view.
:rtype: bool, or ``NoneType``
:returns: boolean indicating whether the view uses standard
or legacy SQL
"""
view = self._properties.get('view')
if view is not None:
return view.get('useLegacySql', True)

@view_use_legacy_sql.setter
def view_use_legacy_sql(self, value):
"""Update SQL dialect for view
:type value: bool
:param value: Whether to use legacy SQL
:raises: ValueError for invalid value types.
"""
if not isinstance(value, bool):
raise ValueError("Pass a boolean value")
if 'view' in self._properties:
self._properties['view']['useLegacySql'] = value
else:
self._properties['view'] = {
'useLegacySql': value
}

@view_query.deleter
def view_query(self):
Expand Down Expand Up @@ -469,6 +505,8 @@ def _build_resource(self):
if self.view_query is not None:
view = resource['view'] = {}
view['query'] = self.view_query
if self.view_use_legacy_sql is not None:
view['useLegacySql'] = self.view_use_legacy_sql
elif self._schema:
resource['schema'] = {
'fields': _build_schema_resource(self._schema)
Expand Down Expand Up @@ -544,6 +582,7 @@ def patch(self,
location=_MARKER,
expires=_MARKER,
view_query=_MARKER,
view_use_legacy_sql=_MARKER,
schema=_MARKER):
"""API call: update individual table properties via a PATCH request
Expand Down Expand Up @@ -571,6 +610,9 @@ def patch(self,
:type view_query: str
:param view_query: SQL query defining the table as a view
:type view_use_legacy_sql: str
:param view_use_legacy_sql: Boolean indicating view_query dialect
:type schema: list of :class:`SchemaField`
:param schema: fields describing the schema
Expand Down Expand Up @@ -601,6 +643,12 @@ def patch(self,
else:
partial['view'] = {'query': view_query}

if view_use_legacy_sql is not _MARKER:
if 'view' in partial:
partial['view']['useLegacySql'] = view_use_legacy_sql
else:
partial['view'] = {'useLegacySql': view_use_legacy_sql}

if schema is not _MARKER:
if schema is None:
partial['schema'] = None
Expand Down
29 changes: 26 additions & 3 deletions bigquery/unit_tests/test_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,10 @@ def _verifyResourceProperties(self, table, resource):

if 'view' in resource:
self.assertEqual(table.view_query, resource['view']['query'])
self.assertEqual(table.view_use_legacy_sql, resource['view']['useLegacySql'])
else:
self.assertIsNone(table.view_query)
self.assertIsNone(table.view_use_legacy_sql)

if 'schema' in resource:
self._verifySchema(table.schema, resource)
Expand Down Expand Up @@ -159,6 +161,7 @@ def test_ctor(self):
self.assertIsNone(table.friendly_name)
self.assertIsNone(table.location)
self.assertIsNone(table.view_query)
self.assertIsNone(table.view_use_legacy_sql)

def test_ctor_w_schema(self):
from google.cloud.bigquery.table import SchemaField
Expand Down Expand Up @@ -354,6 +357,20 @@ def test_view_query_deleter(self):
del table.view_query
self.assertIsNone(table.view_query)

def test_view_use_legacy_sql_setter_bad_value(self):
client = _Client(self.PROJECT)
dataset = _Dataset(client)
table = self._make_one(self.TABLE_NAME, dataset)
with self.assertRaises(ValueError):
table.use_legacy_sql = 12345

def test_view_use_legacy_sql_setter(self):
client = _Client(self.PROJECT)
dataset = _Dataset(client)
table = self._make_one(self.TABLE_NAME, dataset)
table.use_legacy_sql = False
self.assertFalse(table.use_legacy_sql)

def test_from_api_repr_missing_identity(self):
self._setUpConstants()
client = _Client(self.PROJECT)
Expand Down Expand Up @@ -637,6 +654,7 @@ def test_create_w_alternate_client(self):
DESCRIPTION = 'DESCRIPTION'
TITLE = 'TITLE'
QUERY = 'select fullname, age from person_ages'
LEGACY_SQL = False
RESOURCE = self._makeResource()
RESOURCE['description'] = DESCRIPTION
RESOURCE['friendlyName'] = TITLE
Expand All @@ -645,6 +663,7 @@ def test_create_w_alternate_client(self):
RESOURCE['expirationTime'] = _millis(self.EXP_TIME)
RESOURCE['view'] = {}
RESOURCE['view']['query'] = QUERY
RESOURCE['view']['useLegacySql'] = LEGACY_SQL
RESOURCE['type'] = 'VIEW'
conn1 = _Connection()
client1 = _Client(project=self.PROJECT, connection=conn1)
Expand Down Expand Up @@ -673,7 +692,10 @@ def test_create_w_alternate_client(self):
'tableId': self.TABLE_NAME},
'description': DESCRIPTION,
'friendlyName': TITLE,
'view': {'query': QUERY},
'view': {
'query': QUERY,
'useLegacySql': LEGACY_SQL
},
}
self.assertEqual(req['data'], SENT)
self._verifyResourceProperties(table, RESOURCE)
Expand Down Expand Up @@ -943,13 +965,14 @@ def test_update_w_alternate_client(self):
DEF_TABLE_EXP = 12345
LOCATION = 'EU'
QUERY = 'select fullname, age from person_ages'
LEGACY_SQL = False
RESOURCE = self._makeResource()
RESOURCE['defaultTableExpirationMs'] = 12345
RESOURCE['location'] = LOCATION
self.EXP_TIME = datetime.datetime(2015, 8, 1, 23, 59, 59,
tzinfo=UTC)
RESOURCE['expirationTime'] = _millis(self.EXP_TIME)
RESOURCE['view'] = {'query': QUERY}
RESOURCE['view'] = {'query': QUERY, 'useLegacySql': LEGACY_SQL}
RESOURCE['type'] = 'VIEW'
conn1 = _Connection()
client1 = _Client(project=self.PROJECT, connection=conn1)
Expand All @@ -976,7 +999,7 @@ def test_update_w_alternate_client(self):
'tableId': self.TABLE_NAME},
'expirationTime': _millis(self.EXP_TIME),
'location': 'EU',
'view': {'query': QUERY},
'view': {'query': QUERY, 'useLegacySql': LEGACY_SQL},
}
self.assertEqual(req['data'], SENT)
self._verifyResourceProperties(table, RESOURCE)
Expand Down

0 comments on commit d80b2a0

Please sign in to comment.