Skip to content

Commit

Permalink
feat: add support for Dataset.isCaseInsensitive
Browse files Browse the repository at this point in the history
This commit creates a property named is_case_insensitive (in dataset.py)
that allows the usage of the isCaseSensitive field in the Dataset REST
API.

Fixes: googleapis#1670
  • Loading branch information
joseignaciorc committed Oct 3, 2023
1 parent 514d3e1 commit a95a3c8
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 2 deletions.
20 changes: 20 additions & 0 deletions google/cloud/bigquery/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ class Dataset(object):
"default_table_expiration_ms": "defaultTableExpirationMs",
"friendly_name": "friendlyName",
"default_encryption_configuration": "defaultEncryptionConfiguration",
"is_case_insensitive": "isCaseInsensitive",
"storage_billing_model": "storageBillingModel",
}

Expand Down Expand Up @@ -764,6 +765,25 @@ def default_encryption_configuration(self, value):
api_repr = value.to_api_repr()
self._properties["defaultEncryptionConfiguration"] = api_repr

@property
def is_case_insensitive(self):
"""Optional[bool]: TRUE if the dataset and its table names are case-insensitive, otherwise FALSE.
By default, this is FALSE, which means the dataset and its table names are case-sensitive.
This field does not affect routine references.
Raises:
ValueError: for invalid value types.
"""
return self._properties.get("isCaseInsensitive") or False

@is_case_insensitive.setter
def is_case_insensitive(self, value):
if not isinstance(value, bool) and value is not None:
raise ValueError("Pass a boolean value, or None")
if value is None:
value = False
self._properties["isCaseInsensitive"] = value

@property
def storage_billing_model(self):
"""Union[str, None]: StorageBillingModel of the dataset as set by the user
Expand Down
60 changes: 58 additions & 2 deletions tests/system/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,17 @@ def test_create_dataset(self):
self.assertTrue(_dataset_exists(dataset))
self.assertEqual(dataset.dataset_id, DATASET_ID)
self.assertEqual(dataset.project, Config.CLIENT.project)
self.assertIs(dataset.is_case_insensitive, False)

def test_create_dataset_case_sensitive(self):
DATASET_ID = _make_dataset_id("create_cs_dataset")
dataset = self.temp_dataset(DATASET_ID, is_case_insensitive=False)
self.assertIs(dataset.is_case_insensitive, False)

def test_create_dataset_case_insensitive(self):
DATASET_ID = _make_dataset_id("create_ci_dataset")
dataset = self.temp_dataset(DATASET_ID, is_case_insensitive=True)
self.assertIs(dataset.is_case_insensitive, True)

def test_get_dataset(self):
dataset_id = _make_dataset_id("get_dataset")
Expand Down Expand Up @@ -271,16 +282,19 @@ def test_update_dataset(self):
self.assertIsNone(dataset.friendly_name)
self.assertIsNone(dataset.description)
self.assertEqual(dataset.labels, {})
self.assertIs(dataset.is_case_insensitive, False)

dataset.friendly_name = "Friendly"
dataset.description = "Description"
dataset.labels = {"priority": "high", "color": "blue"}
dataset.is_case_insensitive = True
ds2 = Config.CLIENT.update_dataset(
dataset, ("friendly_name", "description", "labels")
dataset, ("friendly_name", "description", "labels", "is_case_insensitive")
)
self.assertEqual(ds2.friendly_name, "Friendly")
self.assertEqual(ds2.description, "Description")
self.assertEqual(ds2.labels, {"priority": "high", "color": "blue"})
self.assertIs(ds2.is_case_insensitive, True)

ds2.labels = {
"color": "green", # change
Expand Down Expand Up @@ -335,6 +349,46 @@ def test_create_table(self):
self.assertTrue(_table_exists(table))
self.assertEqual(table.table_id, table_id)

def test_create_tables_in_case_insensitive_dataset(self):
ci_dataset = self.temp_dataset(
_make_dataset_id("create_table"), is_case_insensitive=True
)
table_arg = Table(ci_dataset.table("test_table2"), schema=SCHEMA)
tablemc_arg = Table(ci_dataset.table("Test_taBLe2"))

table = helpers.retry_403(Config.CLIENT.create_table)(table_arg)
self.to_delete.insert(0, table)

self.assertTrue(_table_exists(table_arg))
self.assertTrue(_table_exists(tablemc_arg))
self.assertIs(ci_dataset.is_case_insensitive, True)

def test_create_tables_in_case_sensitive_dataset(self):
ci_dataset = self.temp_dataset(
_make_dataset_id("create_table"), is_case_insensitive=False
)
table_arg = Table(ci_dataset.table("test_table3"), schema=SCHEMA)
tablemc_arg = Table(ci_dataset.table("Test_taBLe3"))

table = helpers.retry_403(Config.CLIENT.create_table)(table_arg)
self.to_delete.insert(0, table)

self.assertTrue(_table_exists(table_arg))
self.assertFalse(_table_exists(tablemc_arg))
self.assertIs(ci_dataset.is_case_insensitive, False)

def test_create_tables_in_default_sensitivity_dataset(self):
dataset = self.temp_dataset(_make_dataset_id("create_table"))
table_arg = Table(dataset.table("test_table4"), schema=SCHEMA)
tablemc_arg = Table(dataset.table("Test_taBLe4"))

table = helpers.retry_403(Config.CLIENT.create_table)(table_arg)
self.to_delete.insert(0, table)

self.assertTrue(_table_exists(table_arg))
self.assertFalse(_table_exists(tablemc_arg))
self.assertIs(dataset.is_case_insensitive, False)

def test_create_table_with_real_custom_policy(self):
from google.cloud.bigquery.schema import PolicyTagList

Expand Down Expand Up @@ -2286,12 +2340,14 @@ def test_nested_table_to_arrow(self):
self.assertTrue(pyarrow.types.is_list(record_col[1].type))
self.assertTrue(pyarrow.types.is_int64(record_col[1].type.value_type))

def temp_dataset(self, dataset_id, location=None):
def temp_dataset(self, dataset_id, location=None, is_case_insensitive=None):
project = Config.CLIENT.project
dataset_ref = bigquery.DatasetReference(project, dataset_id)
dataset = Dataset(dataset_ref)
if location:
dataset.location = location
if is_case_insensitive is not None:
dataset.is_case_insensitive = is_case_insensitive
dataset = helpers.retry_403(Config.CLIENT.create_dataset)(dataset)
self.to_delete.append(dataset)
return dataset
Expand Down

0 comments on commit a95a3c8

Please sign in to comment.