Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -688,18 +688,19 @@ async def create(self):
"""
api = self._instance._client.database_admin_api
metadata = _metadata_with_prefix(self.name)
db_name = self.database_id
if "-" in db_name:
if self._database_dialect == DatabaseDialect.POSTGRESQL:
db_name = f'"{db_name}"'
else:
db_name = f"`{db_name}`"
database_id = str(self.database_id)
if self._database_dialect == DatabaseDialect.POSTGRESQL:
escaped = database_id.replace('"', '""')
quoted_database_id = f'"{escaped}"'
else:
escaped = database_id.replace("\\", "\\\\").replace("`", "\\`")
quoted_database_id = f"`{escaped}`"
if type(self._encryption_config) is dict:
self._encryption_config = EncryptionConfig(**self._encryption_config)

request = CreateDatabaseRequest(
parent=self._instance.name,
create_statement="CREATE DATABASE %s" % (db_name,),
create_statement=f"CREATE DATABASE {quoted_database_id}",
extra_statements=list(self._ddl_statements),
encryption_config=self._encryption_config,
database_dialect=self._database_dialect,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -599,17 +599,18 @@ def create(self):
:raises NotFound: if the instance owning the database does not exist"""
api = self._instance._client.database_admin_api
metadata = _metadata_with_prefix(self.name)
db_name = self.database_id
if "-" in db_name:
if self._database_dialect == DatabaseDialect.POSTGRESQL:
db_name = f'"{db_name}"'
else:
db_name = f"`{db_name}`"
database_id = str(self.database_id)
if self._database_dialect == DatabaseDialect.POSTGRESQL:
escaped = database_id.replace('"', '""')
quoted_database_id = f'"{escaped}"'
else:
escaped = database_id.replace("\\", "\\\\").replace("`", "\\`")
quoted_database_id = f"`{escaped}`"
if type(self._encryption_config) is dict:
self._encryption_config = EncryptionConfig(**self._encryption_config)
request = CreateDatabaseRequest(
parent=self._instance.name,
create_statement="CREATE DATABASE %s" % (db_name,),
create_statement=f"CREATE DATABASE {quoted_database_id}",
extra_statements=list(self._ddl_statements),
encryption_config=self._encryption_config,
database_dialect=self._database_dialect,
Expand Down
256 changes: 251 additions & 5 deletions packages/google-cloud-spanner/tests/unit/_async/test_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ async def test_create_grpc_error(self):

expected_request = CreateDatabaseRequest(
parent=self.INSTANCE_NAME,
create_statement="CREATE DATABASE {}".format(self.DATABASE_ID),
create_statement="CREATE DATABASE `{}`".format(self.DATABASE_ID),
extra_statements=[],
encryption_config=None,
)
Expand Down Expand Up @@ -834,7 +834,7 @@ async def test_create_instance_not_found(self):

expected_request = CreateDatabaseRequest(
parent=self.INSTANCE_NAME,
create_statement="CREATE DATABASE {}".format(self.DATABASE_ID),
create_statement="CREATE DATABASE `{}`".format(self.DATABASE_ID),
extra_statements=[],
encryption_config=None,
)
Expand Down Expand Up @@ -879,7 +879,7 @@ async def test_create_success(self):

expected_request = CreateDatabaseRequest(
parent=self.INSTANCE_NAME,
create_statement="CREATE DATABASE {}".format(self.DATABASE_ID),
create_statement="CREATE DATABASE `{}`".format(self.DATABASE_ID),
extra_statements=DDL_STATEMENTS,
encryption_config=encryption_config,
)
Expand Down Expand Up @@ -925,7 +925,7 @@ async def test_create_success_w_encryption_config_dict(self):
expected_encryption_config = EncryptionConfig(**encryption_config)
expected_request = CreateDatabaseRequest(
parent=self.INSTANCE_NAME,
create_statement="CREATE DATABASE {}".format(self.DATABASE_ID),
create_statement="CREATE DATABASE `{}`".format(self.DATABASE_ID),
extra_statements=DDL_STATEMENTS,
encryption_config=expected_encryption_config,
)
Expand Down Expand Up @@ -967,7 +967,7 @@ async def test_create_success_w_proto_descriptors(self):

expected_request = CreateDatabaseRequest(
parent=self.INSTANCE_NAME,
create_statement="CREATE DATABASE {}".format(self.DATABASE_ID),
create_statement="CREATE DATABASE `{}`".format(self.DATABASE_ID),
extra_statements=DDL_STATEMENTS,
proto_descriptors=proto_descriptors,
)
Expand All @@ -983,6 +983,252 @@ async def test_create_success_w_proto_descriptors(self):
],
)

@CrossSync.pytest
async def test_create_reserved_keyword_googlesql(self):
from google.cloud.spanner_admin_database_v1 import CreateDatabaseRequest

client = _Client()
api = client.database_admin_api = self._make_database_admin_api()
api.create_database.return_value = None
instance = _Instance(self.INSTANCE_NAME, client=client)
pool = _Pool()
database = await self._make_one("default", instance, pool=pool)

await database.create()

expected_request = CreateDatabaseRequest(
parent=self.INSTANCE_NAME,
create_statement="CREATE DATABASE `default`",
extra_statements=[],
encryption_config=None,
)
api.create_database.assert_called_once_with(
request=expected_request,
metadata=[
("google-cloud-resource-prefix", database.name),
(
"x-goog-spanner-request-id",
f"1.{REQ_RAND_PROCESS_ID}.{database._nth_client_id}.{database._channel_id}.1.1",
),
],
)

@CrossSync.pytest
async def test_create_reserved_keyword_postgresql(self):
from google.cloud.spanner_admin_database_v1 import CreateDatabaseRequest
from google.cloud.spanner_admin_database_v1.types import DatabaseDialect

client = _Client()
api = client.database_admin_api = self._make_database_admin_api()
api.create_database.return_value = None
instance = _Instance(self.INSTANCE_NAME, client=client)
pool = _Pool()
database = await self._make_one(
"default",
instance,
pool=pool,
database_dialect=DatabaseDialect.POSTGRESQL,
)

await database.create()

expected_request = CreateDatabaseRequest(
parent=self.INSTANCE_NAME,
create_statement='CREATE DATABASE "default"',
extra_statements=[],
encryption_config=None,
database_dialect=DatabaseDialect.POSTGRESQL,
)
api.create_database.assert_called_once_with(
request=expected_request,
metadata=[
("google-cloud-resource-prefix", database.name),
(
"x-goog-spanner-request-id",
f"1.{REQ_RAND_PROCESS_ID}.{database._nth_client_id}.{database._channel_id}.1.1",
),
],
)

@CrossSync.pytest
async def test_create_hyphen_postgresql(self):
from google.cloud.spanner_admin_database_v1 import CreateDatabaseRequest
from google.cloud.spanner_admin_database_v1.types import DatabaseDialect

DATABASE_ID_HYPHEN = "database-id"
client = _Client()
api = client.database_admin_api = self._make_database_admin_api()
api.create_database.return_value = None
instance = _Instance(self.INSTANCE_NAME, client=client)
pool = _Pool()
database = await self._make_one(
DATABASE_ID_HYPHEN,
instance,
pool=pool,
database_dialect=DatabaseDialect.POSTGRESQL,
)

await database.create()

expected_request = CreateDatabaseRequest(
parent=self.INSTANCE_NAME,
create_statement=f'CREATE DATABASE "{DATABASE_ID_HYPHEN}"',
extra_statements=[],
encryption_config=None,
database_dialect=DatabaseDialect.POSTGRESQL,
)
api.create_database.assert_called_once_with(
request=expected_request,
metadata=[
("google-cloud-resource-prefix", database.name),
(
"x-goog-spanner-request-id",
f"1.{REQ_RAND_PROCESS_ID}.{database._nth_client_id}.{database._channel_id}.1.1",
),
],
)

@CrossSync.pytest
async def test_create_delimiters_escaped_googlesql(self):
from google.cloud.spanner_admin_database_v1 import CreateDatabaseRequest

client = _Client()
api = client.database_admin_api = self._make_database_admin_api()
api.create_database.return_value = None
instance = _Instance(self.INSTANCE_NAME, client=client)
pool = _Pool()
database = await self._make_one("db`name\\", instance, pool=pool)

await database.create()

expected_request = CreateDatabaseRequest(
parent=self.INSTANCE_NAME,
create_statement="CREATE DATABASE `db\\`name\\\\`",
extra_statements=[],
encryption_config=None,
)
api.create_database.assert_called_once_with(
request=expected_request,
metadata=[
("google-cloud-resource-prefix", database.name),
(
"x-goog-spanner-request-id",
f"1.{REQ_RAND_PROCESS_ID}.{database._nth_client_id}.{database._channel_id}.1.1",
),
],
)

@CrossSync.pytest
async def test_create_delimiters_escaped_postgresql(self):
from google.cloud.spanner_admin_database_v1 import CreateDatabaseRequest
from google.cloud.spanner_admin_database_v1.types import DatabaseDialect

client = _Client()
api = client.database_admin_api = self._make_database_admin_api()
api.create_database.return_value = None
instance = _Instance(self.INSTANCE_NAME, client=client)
pool = _Pool()
database = await self._make_one(
'db"name',
instance,
pool=pool,
database_dialect=DatabaseDialect.POSTGRESQL,
)

await database.create()

expected_request = CreateDatabaseRequest(
parent=self.INSTANCE_NAME,
create_statement='CREATE DATABASE "db""name"',
extra_statements=[],
encryption_config=None,
database_dialect=DatabaseDialect.POSTGRESQL,
)
api.create_database.assert_called_once_with(
request=expected_request,
metadata=[
("google-cloud-resource-prefix", database.name),
(
"x-goog-spanner-request-id",
f"1.{REQ_RAND_PROCESS_ID}.{database._nth_client_id}.{database._channel_id}.1.1",
),
],
)

@CrossSync.pytest
async def test_create_explicit_googlesql(self):
from google.cloud.spanner_admin_database_v1 import CreateDatabaseRequest
from google.cloud.spanner_admin_database_v1.types import DatabaseDialect

client = _Client()
api = client.database_admin_api = self._make_database_admin_api()
api.create_database.return_value = None
instance = _Instance(self.INSTANCE_NAME, client=client)
pool = _Pool()
database = await self._make_one(
self.DATABASE_ID,
instance,
pool=pool,
database_dialect=DatabaseDialect.GOOGLE_STANDARD_SQL,
)

await database.create()

expected_request = CreateDatabaseRequest(
parent=self.INSTANCE_NAME,
create_statement=f"CREATE DATABASE `{self.DATABASE_ID}`",
extra_statements=[],
encryption_config=None,
database_dialect=DatabaseDialect.GOOGLE_STANDARD_SQL,
)
api.create_database.assert_called_once_with(
request=expected_request,
metadata=[
("google-cloud-resource-prefix", database.name),
(
"x-goog-spanner-request-id",
f"1.{REQ_RAND_PROCESS_ID}.{database._nth_client_id}.{database._channel_id}.1.1",
),
],
)

@CrossSync.pytest
async def test_create_standard_postgresql(self):
from google.cloud.spanner_admin_database_v1 import CreateDatabaseRequest
from google.cloud.spanner_admin_database_v1.types import DatabaseDialect

client = _Client()
api = client.database_admin_api = self._make_database_admin_api()
api.create_database.return_value = None
instance = _Instance(self.INSTANCE_NAME, client=client)
pool = _Pool()
database = await self._make_one(
"standard_db",
instance,
pool=pool,
database_dialect=DatabaseDialect.POSTGRESQL,
)

await database.create()

expected_request = CreateDatabaseRequest(
parent=self.INSTANCE_NAME,
create_statement='CREATE DATABASE "standard_db"',
extra_statements=[],
encryption_config=None,
database_dialect=DatabaseDialect.POSTGRESQL,
)
api.create_database.assert_called_once_with(
request=expected_request,
metadata=[
("google-cloud-resource-prefix", database.name),
(
"x-goog-spanner-request-id",
f"1.{REQ_RAND_PROCESS_ID}.{database._nth_client_id}.{database._channel_id}.1.1",
),
],
)

@CrossSync.pytest
async def test_exists_grpc_error(self):
from google.api_core.exceptions import Unknown
Expand Down
Loading
Loading