diff --git a/samples/samples/admin/backup_snippet.py b/samples/samples/archived/backup_snippet.py similarity index 58% rename from samples/samples/admin/backup_snippet.py rename to samples/samples/archived/backup_snippet.py index 0a7260d115..f31cbc1f2c 100644 --- a/samples/samples/admin/backup_snippet.py +++ b/samples/samples/archived/backup_snippet.py @@ -14,48 +14,104 @@ """This application demonstrates how to create and restore from backups using Cloud Spanner. + For more information, see the README.rst under /spanner. """ import time from datetime import datetime, timedelta -from google.api_core import protobuf_helpers from google.cloud import spanner -from google.cloud.exceptions import NotFound + + +# [START spanner_cancel_backup_create] +def cancel_backup(instance_id, database_id, backup_id): + spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + database = instance.database(database_id) + + expire_time = datetime.utcnow() + timedelta(days=30) + + # Create a backup. + backup = instance.backup(backup_id, database=database, expire_time=expire_time) + operation = backup.create() + + # Cancel backup creation. + operation.cancel() + + # Cancel operations are best effort so either it will complete or + # be cancelled. + while not operation.done(): + time.sleep(300) # 5 mins + + # Deal with resource if the operation succeeded. + if backup.exists(): + print("Backup was created before the cancel completed.") + backup.delete() + print("Backup deleted.") + else: + print("Backup creation was successfully cancelled.") + + +# [END spanner_cancel_backup_create] + + +# [START spanner_copy_backup] +def copy_backup(instance_id, backup_id, source_backup_path): + """Copies a backup.""" + spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + + # Create a backup object and wait for copy backup operation to complete. + expire_time = datetime.utcnow() + timedelta(days=14) + copy_backup = instance.copy_backup( + backup_id=backup_id, source_backup=source_backup_path, expire_time=expire_time + ) + operation = copy_backup.create() + + # Wait for copy backup operation to complete. + operation.result(2100) + + # Verify that the copy backup is ready. + copy_backup.reload() + assert copy_backup.is_ready() is True + + print( + "Backup {} of size {} bytes was created at {} with version time {}".format( + copy_backup.name, + copy_backup.size_bytes, + copy_backup.create_time, + copy_backup.version_time, + ) + ) + + +# [END spanner_copy_backup] # [START spanner_create_backup] def create_backup(instance_id, database_id, backup_id, version_time): """Creates a backup for a database.""" - - from google.cloud.spanner_admin_database_v1.types import backup as backup_pb - spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) # Create a backup expire_time = datetime.utcnow() + timedelta(days=14) - - request = backup_pb.CreateBackupRequest( - parent=instance.name, - backup_id=backup_id, - backup=backup_pb.Backup( - database=database.name, - expire_time=expire_time, - version_time=version_time, - ), + backup = instance.backup( + backup_id, database=database, expire_time=expire_time, version_time=version_time ) - - operation = spanner_client.database_admin_api.create_backup(request) + operation = backup.create() # Wait for backup operation to complete. - backup = operation.result(2100) + operation.result(2100) # Verify that the backup is ready. - assert backup.state == backup_pb.Backup.State.READY + backup.reload() + assert backup.is_ready() is True + # Get the name, create time and backup size. + backup.reload() print( "Backup {} of size {} bytes was created at {} for version of database at {}".format( backup.name, backup.size_bytes, backup.create_time, backup.version_time @@ -71,10 +127,8 @@ def create_backup_with_encryption_key( instance_id, database_id, backup_id, kms_key_name ): """Creates a backup for a database using a Customer Managed Encryption Key (CMEK).""" - - from google.cloud.spanner_admin_database_v1.types import backup as backup_pb - - from google.cloud.spanner_admin_database_v1 import CreateBackupEncryptionConfig + from google.cloud.spanner_admin_database_v1 import \ + CreateBackupEncryptionConfig spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) @@ -86,24 +140,23 @@ def create_backup_with_encryption_key( "encryption_type": CreateBackupEncryptionConfig.EncryptionType.CUSTOMER_MANAGED_ENCRYPTION, "kms_key_name": kms_key_name, } - request = backup_pb.CreateBackupRequest( - parent=instance.name, - backup_id=backup_id, - backup=backup_pb.Backup( - database=database.name, - expire_time=expire_time, - ), + backup = instance.backup( + backup_id, + database=database, + expire_time=expire_time, encryption_config=encryption_config, ) - operation = spanner_client.database_admin_api.create_backup(request) + operation = backup.create() # Wait for backup operation to complete. - backup = operation.result(2100) + operation.result(2100) # Verify that the backup is ready. - assert backup.state == backup_pb.Backup.State.READY + backup.reload() + assert backup.is_ready() is True # Get the name, create time, backup size and encryption key. + backup.reload() print( "Backup {} of size {} bytes was created at {} using encryption key {}".format( backup.name, backup.size_bytes, backup.create_time, kms_key_name @@ -114,139 +167,75 @@ def create_backup_with_encryption_key( # [END spanner_create_backup_with_encryption_key] -# [START spanner_restore_backup] -def restore_database(instance_id, new_database_id, backup_id): - """Restores a database from a backup.""" - from google.cloud.spanner_admin_database_v1 import RestoreDatabaseRequest - - spanner_client = spanner.Client() - instance = spanner_client.instance(instance_id) - - # Start restoring an existing backup to a new database. - request = RestoreDatabaseRequest( - parent=instance.name, - database_id=new_database_id, - backup="{}/backups/{}".format(instance.name, backup_id), - ) - operation = spanner_client.database_admin_api.restore_database(request) - - # Wait for restore operation to complete. - db = operation.result(1600) - - # Newly created database has restore information. - restore_info = db.restore_info - print( - "Database {} restored to {} from backup {} with version time {}.".format( - restore_info.backup_info.source_database, - new_database_id, - restore_info.backup_info.backup, - restore_info.backup_info.version_time, - ) - ) - - -# [END spanner_restore_backup] - - -# [START spanner_restore_backup_with_encryption_key] -def restore_database_with_encryption_key( - instance_id, new_database_id, backup_id, kms_key_name +# [START spanner_create_database_with_version_retention_period] +def create_database_with_version_retention_period( + instance_id, database_id, retention_period ): - """Restores a database from a backup using a Customer Managed Encryption Key (CMEK).""" - from google.cloud.spanner_admin_database_v1 import ( - RestoreDatabaseEncryptionConfig, - RestoreDatabaseRequest, - ) - + """Creates a database with a version retention period.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) + ddl_statements = [ + "CREATE TABLE Singers (" + + " SingerId INT64 NOT NULL," + + " FirstName STRING(1024)," + + " LastName STRING(1024)," + + " SingerInfo BYTES(MAX)" + + ") PRIMARY KEY (SingerId)", + "CREATE TABLE Albums (" + + " SingerId INT64 NOT NULL," + + " AlbumId INT64 NOT NULL," + + " AlbumTitle STRING(MAX)" + + ") PRIMARY KEY (SingerId, AlbumId)," + + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE", + "ALTER DATABASE `{}`" + " SET OPTIONS (version_retention_period = '{}')".format( + database_id, retention_period + ), + ] + db = instance.database(database_id, ddl_statements) + operation = db.create() - # Start restoring an existing backup to a new database. - encryption_config = { - "encryption_type": RestoreDatabaseEncryptionConfig.EncryptionType.CUSTOMER_MANAGED_ENCRYPTION, - "kms_key_name": kms_key_name, - } - - request = RestoreDatabaseRequest( - parent=instance.name, - database_id=new_database_id, - backup="{}/backups/{}".format(instance.name, backup_id), - encryption_config=encryption_config, - ) - operation = spanner_client.database_admin_api.restore_database(request) + operation.result(30) - # Wait for restore operation to complete. - db = operation.result(1600) + db.reload() - # Newly created database has restore information. - restore_info = db.restore_info print( - "Database {} restored to {} from backup {} with using encryption key {}.".format( - restore_info.backup_info.source_database, - new_database_id, - restore_info.backup_info.backup, - db.encryption_config.kms_key_name, + "Database {} created with version retention period {} and earliest version time {}".format( + db.database_id, db.version_retention_period, db.earliest_version_time ) ) + db.drop() -# [END spanner_restore_backup_with_encryption_key] +# [END spanner_create_database_with_version_retention_period] -# [START spanner_cancel_backup_create] -def cancel_backup(instance_id, database_id, backup_id): - from google.cloud.spanner_admin_database_v1.types import backup as backup_pb +# [START spanner_delete_backup] +def delete_backup(instance_id, backup_id): spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - database = instance.database(database_id) - - expire_time = datetime.utcnow() + timedelta(days=30) + backup = instance.backup(backup_id) + backup.reload() - # Create a backup. - request = backup_pb.CreateBackupRequest( - parent=instance.name, - backup_id=backup_id, - backup=backup_pb.Backup( - database=database.name, - expire_time=expire_time, - ), - ) - - operation = spanner_client.database_admin_api.create_backup(request) - # Cancel backup creation. - operation.cancel() + # Wait for databases that reference this backup to finish optimizing. + while backup.referencing_databases: + time.sleep(30) + backup.reload() - # Cancel operations are best effort so either it will complete or - # be cancelled. - while not operation.done(): - time.sleep(300) # 5 mins + # Delete the backup. + backup.delete() - try: - spanner_client.database_admin_api.get_backup( - backup_pb.GetBackupRequest( - name="{}/backups/{}".format(instance.name, backup_id) - ) - ) - except NotFound: - print("Backup creation was successfully cancelled.") - return - print("Backup was created before the cancel completed.") - spanner_client.database_admin_api.delete_backup( - backup_pb.DeleteBackupRequest( - name="{}/backups/{}".format(instance.name, backup_id) - ) - ) - print("Backup deleted.") + # Verify that the backup is deleted. + assert backup.exists() is False + print("Backup {} has been deleted.".format(backup.name)) -# [END spanner_cancel_backup_create] +# [END spanner_delete_backup] # [START spanner_list_backup_operations] def list_backup_operations(instance_id, database_id, backup_id): - from google.cloud.spanner_admin_database_v1.types import backup as backup_pb - spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) @@ -256,14 +245,9 @@ def list_backup_operations(instance_id, database_id, backup_id): "google.spanner.admin.database.v1.CreateBackupMetadata) " "AND (metadata.database:{})" ).format(database_id) - request = backup_pb.ListBackupOperationsRequest( - parent=instance.name, filter=filter_ - ) - operations = spanner_client.database_admin_api.list_backup_operations(request) + operations = instance.list_backup_operations(filter_=filter_) for op in operations: - metadata = protobuf_helpers.from_any_pb( - backup_pb.CreateBackupMetadata, op.metadata - ) + metadata = op.metadata print( "Backup {} on database {}: {}% complete.".format( metadata.name, metadata.database, metadata.progress.progress_percent @@ -275,14 +259,9 @@ def list_backup_operations(instance_id, database_id, backup_id): "(metadata.@type:type.googleapis.com/google.spanner.admin.database.v1.CopyBackupMetadata) " "AND (metadata.source_backup:{})" ).format(backup_id) - request = backup_pb.ListBackupOperationsRequest( - parent=instance.name, filter=filter_ - ) - operations = spanner_client.database_admin_api.list_backup_operations(request) + operations = instance.list_backup_operations(filter_=filter_) for op in operations: - metadata = protobuf_helpers.from_any_pb( - backup_pb.CopyBackupMetadata, op.metadata - ) + metadata = op.metadata print( "Backup {} on source backup {}: {}% complete.".format( metadata.name, @@ -295,66 +274,24 @@ def list_backup_operations(instance_id, database_id, backup_id): # [END spanner_list_backup_operations] -# [START spanner_list_database_operations] -def list_database_operations(instance_id): - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - - spanner_client = spanner.Client() - instance = spanner_client.instance(instance_id) - - # List the progress of restore. - filter_ = ( - "(metadata.@type:type.googleapis.com/" - "google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata)" - ) - request = spanner_database_admin.ListDatabaseOperationsRequest( - parent=instance.name, filter=filter_ - ) - operations = spanner_client.database_admin_api.list_database_operations(request) - for op in operations: - metadata = protobuf_helpers.from_any_pb( - spanner_database_admin.OptimizeRestoredDatabaseMetadata, op.metadata - ) - print( - "Database {} restored from backup is {}% optimized.".format( - metadata.name, metadata.progress.progress_percent - ) - ) - - -# [END spanner_list_database_operations] - - # [START spanner_list_backups] def list_backups(instance_id, database_id, backup_id): - from google.cloud.spanner_admin_database_v1.types import backup as backup_pb - spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) # List all backups. print("All backups:") - request = backup_pb.ListBackupsRequest(parent=instance.name, filter="") - operations = spanner_client.database_admin_api.list_backups(request) - for backup in operations: + for backup in instance.list_backups(): print(backup.name) # List all backups that contain a name. print('All backups with backup name containing "{}":'.format(backup_id)) - request = backup_pb.ListBackupsRequest( - parent=instance.name, filter="name:{}".format(backup_id) - ) - operations = spanner_client.database_admin_api.list_backups(request) - for backup in operations: + for backup in instance.list_backups(filter_="name:{}".format(backup_id)): print(backup.name) # List all backups for a database that contains a name. print('All backups with database name containing "{}":'.format(database_id)) - request = backup_pb.ListBackupsRequest( - parent=instance.name, filter="database:{}".format(database_id) - ) - operations = spanner_client.database_admin_api.list_backups(request) - for backup in operations: + for backup in instance.list_backups(filter_="database:{}".format(database_id)): print(backup.name) # List all backups that expire before a timestamp. @@ -364,21 +301,14 @@ def list_backups(instance_id, database_id, backup_id): *expire_time.timetuple() ) ) - request = backup_pb.ListBackupsRequest( - parent=instance.name, - filter='expire_time < "{}-{}-{}T{}:{}:{}Z"'.format(*expire_time.timetuple()), - ) - operations = spanner_client.database_admin_api.list_backups(request) - for backup in operations: + for backup in instance.list_backups( + filter_='expire_time < "{}-{}-{}T{}:{}:{}Z"'.format(*expire_time.timetuple()) + ): print(backup.name) # List all backups with a size greater than some bytes. print("All backups with backup size more than 100 bytes:") - request = backup_pb.ListBackupsRequest( - parent=instance.name, filter="size_bytes > 100" - ) - operations = spanner_client.database_admin_api.list_backups(request) - for backup in operations: + for backup in instance.list_backups(filter_="size_bytes > 100"): print(backup.name) # List backups that were created after a timestamp that are also ready. @@ -388,23 +318,18 @@ def list_backups(instance_id, database_id, backup_id): *create_time.timetuple() ) ) - request = backup_pb.ListBackupsRequest( - parent=instance.name, - filter='create_time >= "{}-{}-{}T{}:{}:{}Z" AND state:READY'.format( + for backup in instance.list_backups( + filter_='create_time >= "{}-{}-{}T{}:{}:{}Z" AND state:READY'.format( *create_time.timetuple() - ), - ) - operations = spanner_client.database_admin_api.list_backups(request) - for backup in operations: + ) + ): print(backup.name) print("All backups with pagination") # If there are multiple pages, additional ``ListBackup`` # requests will be made as needed while iterating. paged_backups = set() - request = backup_pb.ListBackupsRequest(parent=instance.name, page_size=2) - operations = spanner_client.database_admin_api.list_backups(request) - for backup in operations: + for backup in instance.list_backups(page_size=2): paged_backups.add(backup.name) for backup in paged_backups: print(backup) @@ -413,163 +338,117 @@ def list_backups(instance_id, database_id, backup_id): # [END spanner_list_backups] -# [START spanner_delete_backup] -def delete_backup(instance_id, backup_id): - from google.cloud.spanner_admin_database_v1.types import backup as backup_pb - +# [START spanner_list_database_operations] +def list_database_operations(instance_id): spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - backup = spanner_client.database_admin_api.get_backup( - backup_pb.GetBackupRequest( - name="{}/backups/{}".format(instance.name, backup_id) - ) - ) - # Wait for databases that reference this backup to finish optimizing. - while backup.referencing_databases: - time.sleep(30) - backup = spanner_client.database_admin_api.get_backup( - backup_pb.GetBackupRequest( - name="{}/backups/{}".format(instance.name, backup_id) - ) - ) - - # Delete the backup. - spanner_client.database_admin_api.delete_backup( - backup_pb.DeleteBackupRequest(name=backup.name) + # List the progress of restore. + filter_ = ( + "(metadata.@type:type.googleapis.com/" + "google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata)" ) - - # Verify that the backup is deleted. - try: - backup = spanner_client.database_admin_api.get_backup( - backup_pb.GetBackupRequest(name=backup.name) + operations = instance.list_database_operations(filter_=filter_) + for op in operations: + print( + "Database {} restored from backup is {}% optimized.".format( + op.metadata.name, op.metadata.progress.progress_percent + ) ) - except NotFound: - print("Backup {} has been deleted.".format(backup.name)) - return - -# [END spanner_delete_backup] +# [END spanner_list_database_operations] -# [START spanner_update_backup] -def update_backup(instance_id, backup_id): - from google.cloud.spanner_admin_database_v1.types import backup as backup_pb +# [START spanner_restore_backup] +def restore_database(instance_id, new_database_id, backup_id): + """Restores a database from a backup.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) + # Create a backup on database_id. - backup = spanner_client.database_admin_api.get_backup( - backup_pb.GetBackupRequest( - name="{}/backups/{}".format(instance.name, backup_id) - ) - ) + # Start restoring an existing backup to a new database. + backup = instance.backup(backup_id) + new_database = instance.database(new_database_id) + operation = new_database.restore(backup) - # Expire time must be within 366 days of the create time of the backup. - old_expire_time = backup.expire_time - # New expire time should be less than the max expire time - new_expire_time = min(backup.max_expire_time, old_expire_time + timedelta(days=30)) - spanner_client.database_admin_api.update_backup( - backup_pb.UpdateBackupRequest( - backup=backup_pb.Backup(name=backup.name, expire_time=new_expire_time), - update_mask={"paths": ["expire_time"]}, - ) - ) + # Wait for restore operation to complete. + operation.result(1600) + + # Newly created database has restore information. + new_database.reload() + restore_info = new_database.restore_info print( - "Backup {} expire time was updated from {} to {}.".format( - backup.name, old_expire_time, new_expire_time + "Database {} restored to {} from backup {} with version time {}.".format( + restore_info.backup_info.source_database, + new_database_id, + restore_info.backup_info.backup, + restore_info.backup_info.version_time, ) ) -# [END spanner_update_backup] +# [END spanner_restore_backup] -# [START spanner_create_database_with_version_retention_period] -def create_database_with_version_retention_period( - instance_id, database_id, retention_period +# [START spanner_restore_backup_with_encryption_key] +def restore_database_with_encryption_key( + instance_id, new_database_id, backup_id, kms_key_name ): - """Creates a database with a version retention period.""" - - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin + """Restores a database from a backup using a Customer Managed Encryption Key (CMEK).""" + from google.cloud.spanner_admin_database_v1 import \ + RestoreDatabaseEncryptionConfig spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - ddl_statements = [ - "CREATE TABLE Singers (" - + " SingerId INT64 NOT NULL," - + " FirstName STRING(1024)," - + " LastName STRING(1024)," - + " SingerInfo BYTES(MAX)" - + ") PRIMARY KEY (SingerId)", - "CREATE TABLE Albums (" - + " SingerId INT64 NOT NULL," - + " AlbumId INT64 NOT NULL," - + " AlbumTitle STRING(MAX)" - + ") PRIMARY KEY (SingerId, AlbumId)," - + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE", - "ALTER DATABASE `{}`" - " SET OPTIONS (version_retention_period = '{}')".format( - database_id, retention_period - ), - ] - operation = spanner_client.database_admin_api.create_database( - request=spanner_database_admin.CreateDatabaseRequest( - parent=instance.name, - create_statement="CREATE DATABASE `{}`".format(database_id), - extra_statements=ddl_statements, - ) + + # Start restoring an existing backup to a new database. + backup = instance.backup(backup_id) + encryption_config = { + "encryption_type": RestoreDatabaseEncryptionConfig.EncryptionType.CUSTOMER_MANAGED_ENCRYPTION, + "kms_key_name": kms_key_name, + } + new_database = instance.database( + new_database_id, encryption_config=encryption_config ) + operation = new_database.restore(backup) + + # Wait for restore operation to complete. + operation.result(1600) - db = operation.result(30) + # Newly created database has restore information. + new_database.reload() + restore_info = new_database.restore_info print( - "Database {} created with version retention period {} and earliest version time {}".format( - db.name, db.version_retention_period, db.earliest_version_time + "Database {} restored to {} from backup {} with using encryption key {}.".format( + restore_info.backup_info.source_database, + new_database_id, + restore_info.backup_info.backup, + new_database.encryption_config.kms_key_name, ) ) - spanner_client.database_admin_api.drop_database( - spanner_database_admin.DropDatabaseRequest(database=db.name) - ) - - -# [END spanner_create_database_with_version_retention_period] - -# [START spanner_copy_backup] -def copy_backup(instance_id, backup_id, source_backup_path): - """Copies a backup.""" +# [END spanner_restore_backup_with_encryption_key] - from google.cloud.spanner_admin_database_v1.types import backup as backup_pb +# [START spanner_update_backup] +def update_backup(instance_id, backup_id): spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) + backup = instance.backup(backup_id) + backup.reload() - # Create a backup object and wait for copy backup operation to complete. - expire_time = datetime.utcnow() + timedelta(days=14) - request = backup_pb.CopyBackupRequest( - parent=instance.name, - backup_id=backup_id, - source_backup=source_backup_path, - expire_time=expire_time, - ) - - operation = spanner_client.database_admin_api.copy_backup(request) - - # Wait for backup operation to complete. - copy_backup = operation.result(2100) - - # Verify that the copy backup is ready. - assert copy_backup.state == backup_pb.Backup.State.READY - + # Expire time must be within 366 days of the create time of the backup. + old_expire_time = backup.expire_time + # New expire time should be less than the max expire time + new_expire_time = min(backup.max_expire_time, old_expire_time + timedelta(days=30)) + backup.update_expire_time(new_expire_time) print( - "Backup {} of size {} bytes was created at {} with version time {}".format( - copy_backup.name, - copy_backup.size_bytes, - copy_backup.create_time, - copy_backup.version_time, + "Backup {} expire time was updated from {} to {}.".format( + backup.name, old_expire_time, new_expire_time ) ) -# [END spanner_copy_backup] +# [END spanner_update_backup] diff --git a/samples/samples/admin/backup_snippet_test.py b/samples/samples/archived/backup_snippet_test.py similarity index 100% rename from samples/samples/admin/backup_snippet_test.py rename to samples/samples/archived/backup_snippet_test.py diff --git a/samples/samples/admin/pg_samples.py b/samples/samples/archived/pg_samples.py similarity index 78% rename from samples/samples/admin/pg_samples.py rename to samples/samples/archived/pg_samples.py index 4da2cafc33..2d0dd0e5a9 100644 --- a/samples/samples/admin/pg_samples.py +++ b/samples/samples/archived/pg_samples.py @@ -18,122 +18,22 @@ Spanner PostgreSql dialect. For more information, see the README.rst under /spanner. """ -from google.cloud import spanner +from google.cloud import spanner, spanner_admin_database_v1 from google.cloud.spanner_admin_database_v1.types.common import DatabaseDialect OPERATION_TIMEOUT_SECONDS = 240 -# [START spanner_postgresql_create_database] -def create_database(instance_id, database_id): - """Creates a PostgreSql database and tables for sample data.""" - - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - - spanner_client = spanner.Client() - instance = spanner_client.instance(instance_id) - - request = spanner_database_admin.CreateDatabaseRequest( - parent=instance.name, - create_statement=f'CREATE DATABASE "{database_id}"', - database_dialect=DatabaseDialect.POSTGRESQL, - ) - - operation = spanner_client.database_admin_api.create_database(request=request) - - print("Waiting for operation to complete...") - database = operation.result(OPERATION_TIMEOUT_SECONDS) - - create_table_using_ddl(database.name) - print("Created database {} on instance {}".format(database_id, instance_id)) - - -def create_table_using_ddl(database_name): - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - - spanner_client = spanner.Client() - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database_name, - statements=[ - """CREATE TABLE Singers ( - SingerId bigint NOT NULL, - FirstName character varying(1024), - LastName character varying(1024), - SingerInfo bytea, - FullName character varying(2048) - GENERATED ALWAYS AS (FirstName || ' ' || LastName) STORED, - PRIMARY KEY (SingerId) - )""", - """CREATE TABLE Albums ( - SingerId bigint NOT NULL, - AlbumId bigint NOT NULL, - AlbumTitle character varying(1024), - PRIMARY KEY (SingerId, AlbumId) - ) INTERLEAVE IN PARENT Singers ON DELETE CASCADE""", - ], - ) - operation = spanner_client.database_admin_api.update_database_ddl(request) - operation.result(OPERATION_TIMEOUT_SECONDS) - - -# [END spanner_postgresql_create_database] - - -def create_table_with_datatypes(instance_id, database_id): - """Creates a table with supported datatypes.""" - # [START spanner_postgresql_create_table_with_datatypes] - # instance_id = "your-spanner-instance" - # database_id = "your-spanner-db-id" - - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - - spanner_client = spanner.Client() - instance = spanner_client.instance(instance_id) - database = instance.database(database_id) - - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - """CREATE TABLE Venues ( - VenueId BIGINT NOT NULL, - VenueName character varying(100), - VenueInfo BYTEA, - Capacity BIGINT, - OutdoorVenue BOOL, - PopularityScore FLOAT8, - Revenue NUMERIC, - LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL, - PRIMARY KEY (VenueId))""" - ], - ) - operation = spanner_client.database_admin_api.update_database_ddl(request) - - print("Waiting for operation to complete...") - operation.result(OPERATION_TIMEOUT_SECONDS) - - print( - "Created Venues table on database {} on instance {}".format( - database_id, instance_id - ) - ) - # [END spanner_postgresql_create_table_with_datatypes] - - # [START spanner_postgresql_add_column] def add_column(instance_id, database_id): """Adds a new column to the Albums table in the example database.""" - - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=["ALTER TABLE Albums ADD COLUMN MarketingBudget BIGINT"], + operation = database.update_ddl( + ["ALTER TABLE Albums ADD COLUMN MarketingBudget BIGINT"] ) - operation = spanner_client.database_admin_api.update_database_ddl(request) print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -164,19 +64,14 @@ def add_jsonb_column(instance_id, database_id): # instance_id = "your-spanner-instance" # database_id = "your-spanner-db-id" - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=["ALTER TABLE Venues ADD COLUMN VenueDetails JSONB"], + operation = database.update_ddl( + ["ALTER TABLE Venues ADD COLUMN VenueDetails JSONB"] ) - operation = spanner_client.database_admin_api.update_database_ddl(request) - print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -190,46 +85,103 @@ def add_jsonb_column(instance_id, database_id): # [END spanner_postgresql_jsonb_add_column] -# [START spanner_postgresql_create_storing_index] -def add_storing_index(instance_id, database_id): - """Adds an storing index to the example database.""" +# [START spanner_postgresql_alter_sequence] +def alter_sequence(instance_id, database_id): + """Alters the Sequence and insert data""" + spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + database = instance.database(database_id) + + operation = database.update_ddl(["ALTER SEQUENCE Seq SKIP RANGE 1000 5000000"]) + + print("Waiting for operation to complete...") + operation.result(OPERATION_TIMEOUT_SECONDS) + + print( + "Altered Seq sequence to skip an inclusive range between 1000 and 5000000 on database {} on instance {}".format( + database_id, instance_id + ) + ) + + def insert_customers(transaction): + results = transaction.execute_sql( + "INSERT INTO Customers (CustomerName) VALUES " + "('Lea'), " + "('Cataline'), " + "('Smith') " + "RETURNING CustomerId" + ) + for result in results: + print("Inserted customer record with Customer Id: {}".format(*result)) + print( + "Number of customer records inserted is {}".format( + results.stats.row_count_exact + ) + ) + + database.run_in_transaction(insert_customers) + + +# [END spanner_postgresql_alter_sequence] - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +# [START spanner_postgresql_create_database] +def create_database(instance_id, database_id): + """Creates a PostgreSql database and tables for sample data.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle)" - "INCLUDE (MarketingBudget)" - ], + database = instance.database( + database_id, + database_dialect=DatabaseDialect.POSTGRESQL, ) - operation = spanner_client.database_admin_api.update_database_ddl(request) + operation = database.create() print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) - print("Added the AlbumsByAlbumTitle2 index.") + create_table_using_ddl(database.name) + print("Created database {} on instance {}".format(database_id, instance_id)) -# [END spanner_postgresql_create_storing_index] +def create_table_using_ddl(database_name): + spanner_client = spanner.Client() + request = spanner_admin_database_v1.UpdateDatabaseDdlRequest( + database=database_name, + statements=[ + """CREATE TABLE Singers ( + SingerId bigint NOT NULL, + FirstName character varying(1024), + LastName character varying(1024), + SingerInfo bytea, + FullName character varying(2048) + GENERATED ALWAYS AS (FirstName || ' ' || LastName) STORED, + PRIMARY KEY (SingerId) + )""", + """CREATE TABLE Albums ( + SingerId bigint NOT NULL, + AlbumId bigint NOT NULL, + AlbumTitle character varying(1024), + PRIMARY KEY (SingerId, AlbumId) + ) INTERLEAVE IN PARENT Singers ON DELETE CASCADE""", + ], + ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + operation.result(OPERATION_TIMEOUT_SECONDS) + + +# [END spanner_postgresql_create_database] # [START spanner_postgresql_create_sequence] def create_sequence(instance_id, database_id): """Creates the Sequence and insert data""" - - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( + request = spanner_admin_database_v1.UpdateDatabaseDdlRequest( database=database.name, statements=[ "CREATE SEQUENCE Seq BIT_REVERSED_POSITIVE", @@ -272,68 +224,78 @@ def insert_customers(transaction): # [END spanner_postgresql_create_sequence] -# [START spanner_postgresql_alter_sequence] -def alter_sequence(instance_id, database_id): - """Alters the Sequence and insert data""" +# [START spanner_postgresql_create_storing_index] +def add_storing_index(instance_id, database_id): + """Adds an storing index to the example database.""" + spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + database = instance.database(database_id) + + operation = database.update_ddl( + [ + "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle)" + "INCLUDE (MarketingBudget)" + ] + ) - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin + print("Waiting for operation to complete...") + operation.result(OPERATION_TIMEOUT_SECONDS) + print("Added the AlbumsByAlbumTitle2 index.") + + +# [END spanner_postgresql_create_storing_index] + + +# [START spanner_postgresql_drop_sequence] +def drop_sequence(instance_id, database_id): + """Drops the Sequence""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=["ALTER SEQUENCE Seq SKIP RANGE 1000 5000000"], + operation = database.update_ddl( + [ + "ALTER TABLE Customers ALTER COLUMN CustomerId DROP DEFAULT", + "DROP SEQUENCE Seq", + ] ) - operation = spanner_client.database_admin_api.update_database_ddl(request) print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) print( - "Altered Seq sequence to skip an inclusive range between 1000 and 5000000 on database {} on instance {}".format( + "Altered Customers table to drop DEFAULT from CustomerId column and dropped the Seq sequence on database {} on instance {}".format( database_id, instance_id ) ) - def insert_customers(transaction): - results = transaction.execute_sql( - "INSERT INTO Customers (CustomerName) VALUES " - "('Lea'), " - "('Cataline'), " - "('Smith') " - "RETURNING CustomerId" - ) - for result in results: - print("Inserted customer record with Customer Id: {}".format(*result)) - print( - "Number of customer records inserted is {}".format( - results.stats.row_count_exact - ) - ) - - database.run_in_transaction(insert_customers) +# [END spanner_postgresql_drop_sequence] -# [END spanner_postgresql_alter_sequence] - - -# [START spanner_postgresql_drop_sequence] -def drop_sequence(instance_id, database_id): - """Drops the Sequence""" - - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +def create_table_with_datatypes(instance_id, database_id): + """Creates a table with supported datatypes.""" + # [START spanner_postgresql_create_table_with_datatypes] + # instance_id = "your-spanner-instance" + # database_id = "your-spanner-db-id" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( + request = spanner_admin_database_v1.UpdateDatabaseDdlRequest( database=database.name, statements=[ - "ALTER TABLE Customers ALTER COLUMN CustomerId DROP DEFAULT", - "DROP SEQUENCE Seq", + """CREATE TABLE Venues ( + VenueId BIGINT NOT NULL, + VenueName character varying(100), + VenueInfo BYTEA, + Capacity BIGINT, + OutdoorVenue BOOL, + PopularityScore FLOAT8, + Revenue NUMERIC, + LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL, + PRIMARY KEY (VenueId))""" ], ) operation = spanner_client.database_admin_api.update_database_ddl(request) @@ -342,10 +304,8 @@ def drop_sequence(instance_id, database_id): operation.result(OPERATION_TIMEOUT_SECONDS) print( - "Altered Customers table to drop DEFAULT from CustomerId column and dropped the Seq sequence on database {} on instance {}".format( + "Created Venues table on database {} on instance {}".format( database_id, instance_id ) ) - - -# [END spanner_postgresql_drop_sequence] + # [END spanner_postgresql_create_table_with_datatypes] diff --git a/samples/samples/admin/pg_samples_test.py b/samples/samples/archived/pg_samples_test.py similarity index 100% rename from samples/samples/admin/pg_samples_test.py rename to samples/samples/archived/pg_samples_test.py diff --git a/samples/samples/admin/samples.py b/samples/samples/archived/samples.py similarity index 66% rename from samples/samples/admin/samples.py rename to samples/samples/archived/samples.py index a4119f602f..0f930d4a35 100644 --- a/samples/samples/admin/samples.py +++ b/samples/samples/archived/samples.py @@ -16,609 +16,449 @@ """This application demonstrates how to do basic operations using Cloud Spanner. + For more information, see the README.rst under /spanner. """ import time from google.cloud import spanner +from google.iam.v1 import policy_pb2 +from google.type import expr_pb2 OPERATION_TIMEOUT_SECONDS = 240 -# [START spanner_create_instance] -def create_instance(instance_id): - """Creates an instance.""" - from google.cloud.spanner_admin_instance_v1.types import spanner_instance_admin - +def add_and_drop_database_roles(instance_id, database_id): + """Showcases how to manage a user defined database role.""" + # [START spanner_add_and_drop_database_role] + # instance_id = "your-spanner-instance" + # database_id = "your-spanner-db-id" spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + database = instance.database(database_id) + role_parent = "new_parent" + role_child = "new_child" - config_name = "{}/instanceConfigs/regional-us-central1".format( - spanner_client.project_name - ) - - operation = spanner_client.instance_admin_api.create_instance( - parent=spanner_client.project_name, - instance_id=instance_id, - instance=spanner_instance_admin.Instance( - config=config_name, - display_name="This is a display name.", - node_count=1, - labels={ - "cloud_spanner_samples": "true", - "sample_name": "snippets-create_instance-explicit", - "created": str(int(time.time())), - }, - ), + operation = database.update_ddl( + [ + "CREATE ROLE {}".format(role_parent), + "GRANT SELECT ON TABLE Singers TO ROLE {}".format(role_parent), + "CREATE ROLE {}".format(role_child), + "GRANT ROLE {} TO ROLE {}".format(role_parent, role_child), + ] ) - - print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) - - print("Created instance {}".format(instance_id)) - - -# [END spanner_create_instance] - - -# [START spanner_create_instance_with_processing_units] -def create_instance_with_processing_units(instance_id, processing_units): - """Creates an instance.""" - from google.cloud.spanner_admin_instance_v1.types import spanner_instance_admin - - spanner_client = spanner.Client() - - config_name = "{}/instanceConfigs/regional-us-central1".format( - spanner_client.project_name - ) - - request = spanner_instance_admin.CreateInstanceRequest( - parent=spanner_client.project_name, - instance_id=instance_id, - instance=spanner_instance_admin.Instance( - config=config_name, - display_name="This is a display name.", - processing_units=processing_units, - labels={ - "cloud_spanner_samples": "true", - "sample_name": "snippets-create_instance_with_processing_units", - "created": str(int(time.time())), - }, - ), - ) - - operation = spanner_client.instance_admin_api.create_instance(request=request) - - print("Waiting for operation to complete...") - instance = operation.result(OPERATION_TIMEOUT_SECONDS) - print( - "Created instance {} with {} processing units".format( - instance_id, instance.processing_units - ) + "Created roles {} and {} and granted privileges".format(role_parent, role_child) ) + operation = database.update_ddl( + [ + "REVOKE ROLE {} FROM ROLE {}".format(role_parent, role_child), + "DROP ROLE {}".format(role_child), + ] + ) + operation.result(OPERATION_TIMEOUT_SECONDS) + print("Revoked privileges and dropped role {}".format(role_child)) -# [END spanner_create_instance_with_processing_units] - + # [END spanner_add_and_drop_database_role] -# [START spanner_create_database] -def create_database(instance_id, database_id): - """Creates a database and tables for sample data.""" - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +# [START spanner_add_column] +def add_column(instance_id, database_id): + """Adds a new column to the Albums table in the example database.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) + database = instance.database(database_id) - request = spanner_database_admin.CreateDatabaseRequest( - parent=instance.name, - create_statement=f"CREATE DATABASE `{database_id}`", - extra_statements=[ - """CREATE TABLE Singers ( - SingerId INT64 NOT NULL, - FirstName STRING(1024), - LastName STRING(1024), - SingerInfo BYTES(MAX), - FullName STRING(2048) AS ( - ARRAY_TO_STRING([FirstName, LastName], " ") - ) STORED - ) PRIMARY KEY (SingerId)""", - """CREATE TABLE Albums ( - SingerId INT64 NOT NULL, - AlbumId INT64 NOT NULL, - AlbumTitle STRING(MAX) - ) PRIMARY KEY (SingerId, AlbumId), - INTERLEAVE IN PARENT Singers ON DELETE CASCADE""", - ], + operation = database.update_ddl( + ["ALTER TABLE Albums ADD COLUMN MarketingBudget INT64"] ) - operation = spanner_client.database_admin_api.create_database(request=request) - print("Waiting for operation to complete...") - database = operation.result(OPERATION_TIMEOUT_SECONDS) - - print("Created database {} on instance {}".format(database.name, instance.name)) - - -# [START spanner_update_database] -def update_database(instance_id, database_id): - """Updates the drop protection setting for a database.""" - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - - spanner_client = spanner.Client() - instance = spanner_client.instance(instance_id) - - request = spanner_database_admin.UpdateDatabaseRequest( - database=spanner_database_admin.Database( - name="{}/databases/{}".format(instance.name, database_id), - enable_drop_protection=True, - ), - update_mask={"paths": ["enable_drop_protection"]}, - ) - operation = spanner_client.database_admin_api.update_database(request=request) - print( - "Waiting for update operation for {}/databases/{} to complete...".format( - instance.name, database_id - ) - ) operation.result(OPERATION_TIMEOUT_SECONDS) - print("Updated database {}/databases/{}.".format(instance.name, database_id)) - + print("Added the MarketingBudget column.") -# [END spanner_update_database] -# [END spanner_create_database] +# [END spanner_add_column] -# [START spanner_create_database_with_default_leader] -def create_database_with_default_leader(instance_id, database_id, default_leader): - """Creates a database with tables with a default leader.""" - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - +# [START spanner_add_json_column] +def add_json_column(instance_id, database_id): + """Adds a new JSON column to the Venues table in the example database.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - operation = spanner_client.database_admin_api.create_database( - request=spanner_database_admin.CreateDatabaseRequest( - parent=instance.name, - create_statement=f"CREATE DATABASE `{database_id}`", - extra_statements=[ - """CREATE TABLE Singers ( - SingerId INT64 NOT NULL, - FirstName STRING(1024), - LastName STRING(1024), - SingerInfo BYTES(MAX) - ) PRIMARY KEY (SingerId)""", - """CREATE TABLE Albums ( - SingerId INT64 NOT NULL, - AlbumId INT64 NOT NULL, - AlbumTitle STRING(MAX) - ) PRIMARY KEY (SingerId, AlbumId), - INTERLEAVE IN PARENT Singers ON DELETE CASCADE""", - "ALTER DATABASE {}" - " SET OPTIONS (default_leader = '{}')".format( - database_id, default_leader - ), - ], - ) - ) + database = instance.database(database_id) + + operation = database.update_ddl(["ALTER TABLE Venues ADD COLUMN VenueDetails JSON"]) print("Waiting for operation to complete...") - database = operation.result(OPERATION_TIMEOUT_SECONDS) + operation.result(OPERATION_TIMEOUT_SECONDS) print( - "Database {} created with default leader {}".format( - database.name, database.default_leader + 'Altered table "Venues" on database {} on instance {}.'.format( + database_id, instance_id ) ) -# [END spanner_create_database_with_default_leader] +# [END spanner_add_json_column] -# [START spanner_update_database_with_default_leader] -def update_database_with_default_leader(instance_id, database_id, default_leader): - """Updates a database with tables with a default leader.""" - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - +# [START spanner_add_numeric_column] +def add_numeric_column(instance_id, database_id): + """Adds a new NUMERIC column to the Venues table in the example database.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) + database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - "ALTER DATABASE {}" - " SET OPTIONS (default_leader = '{}')".format(database_id, default_leader) - ], - ) - operation = spanner_client.database_admin_api.update_database_ddl(request) + operation = database.update_ddl(["ALTER TABLE Venues ADD COLUMN Revenue NUMERIC"]) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) print( - "Database {} updated with default leader {}".format(database_id, default_leader) + 'Altered table "Venues" on database {} on instance {}.'.format( + database_id, instance_id + ) ) -# [END spanner_update_database_with_default_leader] - +# [END spanner_add_numeric_column] -# [START spanner_create_database_with_encryption_key] -def create_database_with_encryption_key(instance_id, database_id, kms_key_name): - """Creates a database with tables using a Customer Managed Encryption Key (CMEK).""" - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - from google.cloud.spanner_admin_database_v1 import EncryptionConfig +# [START spanner_add_timestamp_column] +def add_timestamp_column(instance_id, database_id): + """Adds a new TIMESTAMP column to the Albums table in the example database.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - request = spanner_database_admin.CreateDatabaseRequest( - parent=instance.name, - create_statement=f"CREATE DATABASE `{database_id}`", - extra_statements=[ - """CREATE TABLE Singers ( - SingerId INT64 NOT NULL, - FirstName STRING(1024), - LastName STRING(1024), - SingerInfo BYTES(MAX) - ) PRIMARY KEY (SingerId)""", - """CREATE TABLE Albums ( - SingerId INT64 NOT NULL, - AlbumId INT64 NOT NULL, - AlbumTitle STRING(MAX) - ) PRIMARY KEY (SingerId, AlbumId), - INTERLEAVE IN PARENT Singers ON DELETE CASCADE""", - ], - encryption_config=EncryptionConfig(kms_key_name=kms_key_name), - ) + database = instance.database(database_id) - operation = spanner_client.database_admin_api.create_database(request=request) + operation = database.update_ddl( + [ + "ALTER TABLE Albums ADD COLUMN LastUpdateTime TIMESTAMP " + "OPTIONS(allow_commit_timestamp=true)" + ] + ) print("Waiting for operation to complete...") - database = operation.result(OPERATION_TIMEOUT_SECONDS) + operation.result(OPERATION_TIMEOUT_SECONDS) print( - "Database {} created with encryption key {}".format( - database.name, database.encryption_config.kms_key_name + 'Altered table "Albums" on database {} on instance {}.'.format( + database_id, instance_id ) ) -# [END spanner_create_database_with_encryption_key] - - -def add_and_drop_database_roles(instance_id, database_id): - """Showcases how to manage a user defined database role.""" - # [START spanner_add_and_drop_database_role] - # instance_id = "your-spanner-instance" - # database_id = "your-spanner-db-id" +# [END spanner_add_timestamp_column] - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +# [START spanner_alter_sequence] +def alter_sequence(instance_id, database_id): + """Alters the Sequence and insert data""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - role_parent = "new_parent" - role_child = "new_child" - - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - "CREATE ROLE {}".format(role_parent), - "GRANT SELECT ON TABLE Singers TO ROLE {}".format(role_parent), - "CREATE ROLE {}".format(role_child), - "GRANT ROLE {} TO ROLE {}".format(role_parent, role_child), - ], + operation = database.update_ddl( + [ + "ALTER SEQUENCE Seq SET OPTIONS (skip_range_min = 1000, skip_range_max = 5000000)" + ] ) - operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) - print( - "Created roles {} and {} and granted privileges".format(role_parent, role_child) - ) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - "REVOKE ROLE {} FROM ROLE {}".format(role_parent, role_child), - "DROP ROLE {}".format(role_child), - ], + print( + "Altered Seq sequence to skip an inclusive range between 1000 and 5000000 on database {} on instance {}".format( + database_id, instance_id + ) ) - operation = spanner_client.database_admin_api.update_database_ddl(request) - operation.result(OPERATION_TIMEOUT_SECONDS) - print("Revoked privileges and dropped role {}".format(role_child)) + def insert_customers(transaction): + results = transaction.execute_sql( + "INSERT INTO Customers (CustomerName) VALUES " + "('Lea'), " + "('Cataline'), " + "('Smith') " + "THEN RETURN CustomerId" + ) + for result in results: + print("Inserted customer record with Customer Id: {}".format(*result)) + print( + "Number of customer records inserted is {}".format( + results.stats.row_count_exact + ) + ) - # [END spanner_add_and_drop_database_role] + database.run_in_transaction(insert_customers) -def create_table_with_datatypes(instance_id, database_id): - """Creates a table with supported datatypes.""" - # [START spanner_create_table_with_datatypes] - # instance_id = "your-spanner-instance" - # database_id = "your-spanner-db-id" +# [END spanner_alter_sequence] - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +# [START spanner_alter_table_with_foreign_key_delete_cascade] +def alter_table_with_foreign_key_delete_cascade(instance_id, database_id): + """Alters a table with foreign key delete cascade action""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - """CREATE TABLE Venues ( - VenueId INT64 NOT NULL, - VenueName STRING(100), - VenueInfo BYTES(MAX), - Capacity INT64, - AvailableDates ARRAY, - LastContactDate DATE, - OutdoorVenue BOOL, - PopularityScore FLOAT64, - LastUpdateTime TIMESTAMP NOT NULL - OPTIONS(allow_commit_timestamp=true) - ) PRIMARY KEY (VenueId)""" - ], + operation = database.update_ddl( + [ + """ALTER TABLE ShoppingCarts + ADD CONSTRAINT FKShoppingCartsCustomerName + FOREIGN KEY (CustomerName) + REFERENCES Customers(CustomerName) + ON DELETE CASCADE""" + ] ) - operation = spanner_client.database_admin_api.update_database_ddl(request) print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) print( - "Created Venues table on database {} on instance {}".format( + """Altered ShoppingCarts table with FKShoppingCartsCustomerName + foreign key constraint on database {} on instance {}""".format( database_id, instance_id ) ) - # [END spanner_create_table_with_datatypes] -# [START spanner_add_json_column] -def add_json_column(instance_id, database_id): - """Adds a new JSON column to the Venues table in the example database.""" - # instance_id = "your-spanner-instance" - # database_id = "your-spanner-db-id" +# [END spanner_alter_table_with_foreign_key_delete_cascade] - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +# [START spanner_create_database] +def create_database(instance_id, database_id): + """Creates a database and tables for sample data.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=["ALTER TABLE Venues ADD COLUMN VenueDetails JSON"], + database = instance.database( + database_id, + ddl_statements=[ + """CREATE TABLE Singers ( + SingerId INT64 NOT NULL, + FirstName STRING(1024), + LastName STRING(1024), + SingerInfo BYTES(MAX), + FullName STRING(2048) AS ( + ARRAY_TO_STRING([FirstName, LastName], " ") + ) STORED + ) PRIMARY KEY (SingerId)""", + """CREATE TABLE Albums ( + SingerId INT64 NOT NULL, + AlbumId INT64 NOT NULL, + AlbumTitle STRING(MAX) + ) PRIMARY KEY (SingerId, AlbumId), + INTERLEAVE IN PARENT Singers ON DELETE CASCADE""", + ], ) - operation = spanner_client.database_admin_api.update_database_ddl(request) + operation = database.create() print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) - print( - 'Altered table "Venues" on database {} on instance {}.'.format( - database_id, instance_id - ) - ) - - -# [END spanner_add_json_column] + print("Created database {} on instance {}".format(database_id, instance_id)) -# [START spanner_add_numeric_column] -def add_numeric_column(instance_id, database_id): - """Adds a new NUMERIC column to the Venues table in the example database.""" +# [END spanner_create_database] - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +# [START spanner_create_database_with_default_leader] +def create_database_with_default_leader(instance_id, database_id, default_leader): + """Creates a database with tables with a default leader.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=["ALTER TABLE Venues ADD COLUMN Revenue NUMERIC"], + database = instance.database( + database_id, + ddl_statements=[ + """CREATE TABLE Singers ( + SingerId INT64 NOT NULL, + FirstName STRING(1024), + LastName STRING(1024), + SingerInfo BYTES(MAX) + ) PRIMARY KEY (SingerId)""", + """CREATE TABLE Albums ( + SingerId INT64 NOT NULL, + AlbumId INT64 NOT NULL, + AlbumTitle STRING(MAX) + ) PRIMARY KEY (SingerId, AlbumId), + INTERLEAVE IN PARENT Singers ON DELETE CASCADE""", + "ALTER DATABASE {}" + " SET OPTIONS (default_leader = '{}')".format(database_id, default_leader), + ], ) - - operation = spanner_client.database_admin_api.update_database_ddl(request) + operation = database.create() print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) + database.reload() + print( - 'Altered table "Venues" on database {} on instance {}.'.format( - database_id, instance_id + "Database {} created with default leader {}".format( + database.name, database.default_leader ) ) -# [END spanner_add_numeric_column] - - -# [START spanner_create_table_with_timestamp_column] -def create_table_with_timestamp(instance_id, database_id): - """Creates a table with a COMMIT_TIMESTAMP column.""" +# [END spanner_create_database_with_default_leader] - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +# [START spanner_create_database_with_encryption_key] +def create_database_with_encryption_key(instance_id, database_id, kms_key_name): + """Creates a database with tables using a Customer Managed Encryption Key (CMEK).""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - """CREATE TABLE Performances ( + database = instance.database( + database_id, + ddl_statements=[ + """CREATE TABLE Singers ( SingerId INT64 NOT NULL, - VenueId INT64 NOT NULL, - EventDate Date, - Revenue INT64, - LastUpdateTime TIMESTAMP NOT NULL - OPTIONS(allow_commit_timestamp=true) - ) PRIMARY KEY (SingerId, VenueId, EventDate), - INTERLEAVE IN PARENT Singers ON DELETE CASCADE""" + FirstName STRING(1024), + LastName STRING(1024), + SingerInfo BYTES(MAX) + ) PRIMARY KEY (SingerId)""", + """CREATE TABLE Albums ( + SingerId INT64 NOT NULL, + AlbumId INT64 NOT NULL, + AlbumTitle STRING(MAX) + ) PRIMARY KEY (SingerId, AlbumId), + INTERLEAVE IN PARENT Singers ON DELETE CASCADE""", ], + encryption_config={"kms_key_name": kms_key_name}, ) - operation = spanner_client.database_admin_api.update_database_ddl(request) + operation = database.create() print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) print( - "Created Performances table on database {} on instance {}".format( - database_id, instance_id + "Database {} created with encryption key {}".format( + database.name, database.encryption_config.kms_key_name ) ) -# [END spanner_create_table_with_timestamp_column] - - -# [START spanner_create_table_with_foreign_key_delete_cascade] -def create_table_with_foreign_key_delete_cascade(instance_id, database_id): - """Creates a table with foreign key delete cascade action""" +# [END spanner_create_database_with_encryption_key] - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +# [START spanner_create_index] +def add_index(instance_id, database_id): + """Adds a simple index to the example database.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - """CREATE TABLE Customers ( - CustomerId INT64 NOT NULL, - CustomerName STRING(62) NOT NULL, - ) PRIMARY KEY (CustomerId) - """, - """ - CREATE TABLE ShoppingCarts ( - CartId INT64 NOT NULL, - CustomerId INT64 NOT NULL, - CustomerName STRING(62) NOT NULL, - CONSTRAINT FKShoppingCartsCustomerId FOREIGN KEY (CustomerId) - REFERENCES Customers (CustomerId) ON DELETE CASCADE - ) PRIMARY KEY (CartId) - """, - ], + operation = database.update_ddl( + ["CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"] ) - operation = spanner_client.database_admin_api.update_database_ddl(request) - print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) - print( - """Created Customers and ShoppingCarts table with FKShoppingCartsCustomerId - foreign key constraint on database {} on instance {}""".format( - database_id, instance_id - ) - ) - - -# [END spanner_create_table_with_foreign_key_delete_cascade] + print("Added the AlbumsByAlbumTitle index.") -# [START spanner_alter_table_with_foreign_key_delete_cascade] -def alter_table_with_foreign_key_delete_cascade(instance_id, database_id): - """Alters a table with foreign key delete cascade action""" +# [END spanner_create_index] - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +# [START spanner_create_instance] +def create_instance(instance_id): + """Creates an instance.""" spanner_client = spanner.Client() - instance = spanner_client.instance(instance_id) - database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - """ALTER TABLE ShoppingCarts - ADD CONSTRAINT FKShoppingCartsCustomerName - FOREIGN KEY (CustomerName) - REFERENCES Customers(CustomerName) - ON DELETE CASCADE""" - ], + config_name = "{}/instanceConfigs/regional-us-central1".format( + spanner_client.project_name ) - operation = spanner_client.database_admin_api.update_database_ddl(request) + instance = spanner_client.instance( + instance_id, + configuration_name=config_name, + display_name="This is a display name.", + node_count=1, + labels={ + "cloud_spanner_samples": "true", + "sample_name": "snippets-create_instance-explicit", + "created": str(int(time.time())), + }, + ) + + operation = instance.create() print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) - print( - """Altered ShoppingCarts table with FKShoppingCartsCustomerName - foreign key constraint on database {} on instance {}""".format( - database_id, instance_id - ) - ) - - -# [END spanner_alter_table_with_foreign_key_delete_cascade] + print("Created instance {}".format(instance_id)) -# [START spanner_drop_foreign_key_constraint_delete_cascade] -def drop_foreign_key_constraint_delete_cascade(instance_id, database_id): - """Alter table to drop foreign key delete cascade action""" +# [END spanner_create_instance] - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - spanner_client = spanner.Client() - instance = spanner_client.instance(instance_id) - database = instance.database(database_id) +# [START spanner_create_instance_with_processing_units] +def create_instance_with_processing_units(instance_id, processing_units): + """Creates an instance.""" + spanner_client = spanner.Client() - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - """ALTER TABLE ShoppingCarts - DROP CONSTRAINT FKShoppingCartsCustomerName""" - ], + config_name = "{}/instanceConfigs/regional-us-central1".format( + spanner_client.project_name + ) + + instance = spanner_client.instance( + instance_id, + configuration_name=config_name, + display_name="This is a display name.", + processing_units=processing_units, + labels={ + "cloud_spanner_samples": "true", + "sample_name": "snippets-create_instance_with_processing_units", + "created": str(int(time.time())), + }, ) - operation = spanner_client.database_admin_api.update_database_ddl(request) + operation = instance.create() print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) print( - """Altered ShoppingCarts table to drop FKShoppingCartsCustomerName - foreign key constraint on database {} on instance {}""".format( - database_id, instance_id + "Created instance {} with {} processing units".format( + instance_id, instance.processing_units ) ) -# [END spanner_drop_foreign_key_constraint_delete_cascade] +# [END spanner_create_instance_with_processing_units] # [START spanner_create_sequence] def create_sequence(instance_id, database_id): """Creates the Sequence and insert data""" - - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ + operation = database.update_ddl( + [ "CREATE SEQUENCE Seq OPTIONS (sequence_kind = 'bit_reversed_positive')", """CREATE TABLE Customers ( CustomerId INT64 DEFAULT (GET_NEXT_SEQUENCE_VALUE(Sequence Seq)), CustomerName STRING(1024) ) PRIMARY KEY (CustomerId)""", - ], + ] ) - operation = spanner_client.database_admin_api.update_database_ddl(request) - print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -650,203 +490,194 @@ def insert_customers(transaction): # [END spanner_create_sequence] -# [START spanner_alter_sequence] -def alter_sequence(instance_id, database_id): - """Alters the Sequence and insert data""" - - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - +# [START spanner_create_storing_index] +def add_storing_index(instance_id, database_id): + """Adds an storing index to the example database.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - "ALTER SEQUENCE Seq SET OPTIONS (skip_range_min = 1000, skip_range_max = 5000000)", - ], + operation = database.update_ddl( + [ + "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle)" + "STORING (MarketingBudget)" + ] ) - operation = spanner_client.database_admin_api.update_database_ddl(request) - print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) - print( - "Altered Seq sequence to skip an inclusive range between 1000 and 5000000 on database {} on instance {}".format( - database_id, instance_id - ) - ) - - def insert_customers(transaction): - results = transaction.execute_sql( - "INSERT INTO Customers (CustomerName) VALUES " - "('Lea'), " - "('Cataline'), " - "('Smith') " - "THEN RETURN CustomerId" - ) - for result in results: - print("Inserted customer record with Customer Id: {}".format(*result)) - print( - "Number of customer records inserted is {}".format( - results.stats.row_count_exact - ) - ) - - database.run_in_transaction(insert_customers) - - -# [END spanner_alter_sequence] + print("Added the AlbumsByAlbumTitle2 index.") -# [START spanner_drop_sequence] -def drop_sequence(instance_id, database_id): - """Drops the Sequence""" +# [END spanner_create_storing_index] - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +def create_table_with_datatypes(instance_id, database_id): + """Creates a table with supported datatypes.""" + # [START spanner_create_table_with_datatypes] + # instance_id = "your-spanner-instance" + # database_id = "your-spanner-db-id" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - "ALTER TABLE Customers ALTER COLUMN CustomerId DROP DEFAULT", - "DROP SEQUENCE Seq", - ], + operation = database.update_ddl( + [ + """CREATE TABLE Venues ( + VenueId INT64 NOT NULL, + VenueName STRING(100), + VenueInfo BYTES(MAX), + Capacity INT64, + AvailableDates ARRAY, + LastContactDate DATE, + OutdoorVenue BOOL, + PopularityScore FLOAT64, + LastUpdateTime TIMESTAMP NOT NULL + OPTIONS(allow_commit_timestamp=true) + ) PRIMARY KEY (VenueId)""" + ] ) - operation = spanner_client.database_admin_api.update_database_ddl(request) - print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) print( - "Altered Customers table to drop DEFAULT from CustomerId column and dropped the Seq sequence on database {} on instance {}".format( + "Created Venues table on database {} on instance {}".format( database_id, instance_id ) ) + # [END spanner_create_table_with_datatypes] -# [END spanner_drop_sequence] - - -# [START spanner_add_column] -def add_column(instance_id, database_id): - """Adds a new column to the Albums table in the example database.""" - - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin - +# [START spanner_create_table_with_foreign_key_delete_cascade] +def create_table_with_foreign_key_delete_cascade(instance_id, database_id): + """Creates a table with foreign key delete cascade action""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - "ALTER TABLE Albums ADD COLUMN MarketingBudget INT64", - ], + operation = database.update_ddl( + [ + """CREATE TABLE Customers ( + CustomerId INT64 NOT NULL, + CustomerName STRING(62) NOT NULL, + ) PRIMARY KEY (CustomerId) + """, + """ + CREATE TABLE ShoppingCarts ( + CartId INT64 NOT NULL, + CustomerId INT64 NOT NULL, + CustomerName STRING(62) NOT NULL, + CONSTRAINT FKShoppingCartsCustomerId FOREIGN KEY (CustomerId) + REFERENCES Customers (CustomerId) ON DELETE CASCADE + ) PRIMARY KEY (CartId) + """, + ] ) - operation = spanner_client.database_admin_api.update_database_ddl(request) - print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) - print("Added the MarketingBudget column.") + print( + """Created Customers and ShoppingCarts table with FKShoppingCartsCustomerId + foreign key constraint on database {} on instance {}""".format( + database_id, instance_id + ) + ) -# [END spanner_add_column] +# [END spanner_create_table_with_foreign_key_delete_cascade] -# [START spanner_add_timestamp_column] -def add_timestamp_column(instance_id, database_id): - """Adds a new TIMESTAMP column to the Albums table in the example database.""" - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +# [START spanner_create_table_with_timestamp_column] +def create_table_with_timestamp(instance_id, database_id): + """Creates a table with a COMMIT_TIMESTAMP column.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - "ALTER TABLE Albums ADD COLUMN LastUpdateTime TIMESTAMP " - "OPTIONS(allow_commit_timestamp=true)" - ], + operation = database.update_ddl( + [ + """CREATE TABLE Performances ( + SingerId INT64 NOT NULL, + VenueId INT64 NOT NULL, + EventDate Date, + Revenue INT64, + LastUpdateTime TIMESTAMP NOT NULL + OPTIONS(allow_commit_timestamp=true) + ) PRIMARY KEY (SingerId, VenueId, EventDate), + INTERLEAVE IN PARENT Singers ON DELETE CASCADE""" + ] ) - operation = spanner_client.database_admin_api.update_database_ddl(request) - print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) print( - 'Altered table "Albums" on database {} on instance {}.'.format( + "Created Performances table on database {} on instance {}".format( database_id, instance_id ) ) -# [END spanner_add_timestamp_column] - - -# [START spanner_create_index] -def add_index(instance_id, database_id): - """Adds a simple index to the example database.""" +# [END spanner_create_table_with_timestamp_column] - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +# [START spanner_drop_foreign_key_constraint_delete_cascade] +def drop_foreign_key_constraint_delete_cascade(instance_id, database_id): + """Alter table to drop foreign key delete cascade action""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=["CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"], + operation = database.update_ddl( + [ + """ALTER TABLE ShoppingCarts + DROP CONSTRAINT FKShoppingCartsCustomerName""" + ] ) - operation = spanner_client.database_admin_api.update_database_ddl(request) - print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) - print("Added the AlbumsByAlbumTitle index.") - - -# [END spanner_create_index] + print( + """Altered ShoppingCarts table to drop FKShoppingCartsCustomerName + foreign key constraint on database {} on instance {}""".format( + database_id, instance_id + ) + ) -# [START spanner_create_storing_index] -def add_storing_index(instance_id, database_id): - """Adds an storing index to the example database.""" +# [END spanner_drop_foreign_key_constraint_delete_cascade] - from google.cloud.spanner_admin_database_v1.types import spanner_database_admin +# [START spanner_drop_sequence] +def drop_sequence(instance_id, database_id): + """Drops the Sequence""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_database_admin.UpdateDatabaseDdlRequest( - database=database.name, - statements=[ - "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle)" - "STORING (MarketingBudget)" - ], + operation = database.update_ddl( + [ + "ALTER TABLE Customers ALTER COLUMN CustomerId DROP DEFAULT", + "DROP SEQUENCE Seq", + ] ) - operation = spanner_client.database_admin_api.update_database_ddl(request) - print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) - print("Added the AlbumsByAlbumTitle2 index.") + print( + "Altered Customers table to drop DEFAULT from CustomerId column and dropped the Seq sequence on database {} on instance {}".format( + database_id, instance_id + ) + ) -# [END spanner_create_storing_index] +# [END spanner_drop_sequence] def enable_fine_grained_access( @@ -863,12 +694,6 @@ def enable_fine_grained_access( # iam_member = "user:alice@example.com" # database_role = "new_parent" # title = "condition title" - - from google.type import expr_pb2 - from google.iam.v1 import iam_policy_pb2 - from google.iam.v1 import options_pb2 - from google.iam.v1 import policy_pb2 - spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) @@ -877,11 +702,7 @@ def enable_fine_grained_access( # that you specified, or it might use a lower policy version. For example, if you # specify version 3, but the policy has no conditional role bindings, the response # uses version 1. Valid values are 0, 1, and 3. - request = iam_policy_pb2.GetIamPolicyRequest( - resource=database.name, - options=options_pb2.GetPolicyOptions(requested_policy_version=3), - ) - policy = spanner_client.database_admin_api.get_iam_policy(request=request) + policy = database.get_iam_policy(3) if policy.version < 3: policy.version = 3 @@ -896,14 +717,108 @@ def enable_fine_grained_access( policy.version = 3 policy.bindings.append(new_binding) - set_request = iam_policy_pb2.SetIamPolicyRequest( - resource=database.name, - policy=policy, - ) - spanner_client.database_admin_api.set_iam_policy(set_request) + database.set_iam_policy(policy) - new_policy = spanner_client.database_admin_api.get_iam_policy(request=request) + new_policy = database.get_iam_policy(3) print( f"Enabled fine-grained access in IAM. New policy has version {new_policy.version}" ) # [END spanner_enable_fine_grained_access] + + +def list_database_roles(instance_id, database_id): + """Showcases how to list Database Roles.""" + # [START spanner_list_database_roles] + # instance_id = "your-spanner-instance" + # database_id = "your-spanner-db-id" + spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + database = instance.database(database_id) + + # List database roles. + print("Database Roles are:") + for role in database.list_database_roles(): + print(role.name.split("/")[-1]) + # [END spanner_list_database_roles] + + +# [START spanner_list_databases] +def list_databases(instance_id): + """Lists databases and their leader options.""" + spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + + databases = list(instance.list_databases()) + for database in databases: + print( + "Database {} has default leader {}".format( + database.name, database.default_leader + ) + ) + + +# [END spanner_list_databases] + + +# [START spanner_list_instance_configs] +def list_instance_config(): + """Lists the available instance configurations.""" + spanner_client = spanner.Client() + configs = spanner_client.list_instance_configs() + for config in configs: + print( + "Available leader options for instance config {}: {}".format( + config.name, config.leader_options + ) + ) + + +# [END spanner_list_instance_configs] + + +# [START spanner_update_database] +def update_database(instance_id, database_id): + """Updates the drop protection setting for a database.""" + spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + + db = instance.database(database_id) + db.enable_drop_protection = True + + operation = db.update(["enable_drop_protection"]) + + print("Waiting for update operation for {} to complete...".format(db.name)) + operation.result(OPERATION_TIMEOUT_SECONDS) + + print("Updated database {}.".format(db.name)) + + +# [END spanner_update_database] + + +# [START spanner_update_database_with_default_leader] +def update_database_with_default_leader(instance_id, database_id, default_leader): + """Updates a database with tables with a default leader.""" + spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + + database = instance.database(database_id) + + operation = database.update_ddl( + [ + "ALTER DATABASE {}" + " SET OPTIONS (default_leader = '{}')".format(database_id, default_leader) + ] + ) + operation.result(OPERATION_TIMEOUT_SECONDS) + + database.reload() + + print( + "Database {} updated with default leader {}".format( + database.name, database.default_leader + ) + ) + + +# [END spanner_update_database_with_default_leader] diff --git a/samples/samples/admin/samples_test.py b/samples/samples/archived/samples_test.py similarity index 95% rename from samples/samples/admin/samples_test.py rename to samples/samples/archived/samples_test.py index 959c2f48fc..6435dc5311 100644 --- a/samples/samples/admin/samples_test.py +++ b/samples/samples/archived/samples_test.py @@ -206,6 +206,12 @@ def test_update_database(capsys, instance_id, sample_database): op.result() +def test_list_databases(capsys, instance_id): + samples.list_databases(instance_id) + out, _ = capsys.readouterr() + assert "has default leader" in out + + @pytest.mark.dependency( name="add_and_drop_database_roles", depends=["create_table_with_datatypes"] ) @@ -216,6 +222,19 @@ def test_add_and_drop_database_roles(capsys, instance_id, sample_database): assert "Revoked privileges and dropped role new_child" in out +@pytest.mark.dependency(depends=["add_and_drop_database_roles"]) +def test_list_database_roles(capsys, instance_id, sample_database): + samples.list_database_roles(instance_id, sample_database.database_id) + out, _ = capsys.readouterr() + assert "new_parent" in out + + +def test_list_instance_config(capsys): + samples.list_instance_config() + out, _ = capsys.readouterr() + assert "regional-us-central1" in out + + @pytest.mark.dependency(name="create_table_with_datatypes") def test_create_table_with_datatypes(capsys, instance_id, sample_database): samples.create_table_with_datatypes(instance_id, sample_database.database_id) diff --git a/samples/samples/autocommit_test.py b/samples/samples/autocommit_test.py index 8150058f1c..a22f74e6b4 100644 --- a/samples/samples/autocommit_test.py +++ b/samples/samples/autocommit_test.py @@ -4,8 +4,8 @@ # license that can be found in the LICENSE file or at # https://developers.google.com/open-source/licenses/bsd -from google.api_core.exceptions import Aborted import pytest +from google.api_core.exceptions import Aborted from test_utils.retry import RetryErrors import autocommit diff --git a/samples/samples/backup_sample.py b/samples/samples/backup_sample.py index 01d3e4bf60..d72dde87a6 100644 --- a/samples/samples/backup_sample.py +++ b/samples/samples/backup_sample.py @@ -19,35 +19,46 @@ """ import argparse -from datetime import datetime, timedelta import time +from datetime import datetime, timedelta +from google.api_core import protobuf_helpers from google.cloud import spanner +from google.cloud.exceptions import NotFound # [START spanner_create_backup] def create_backup(instance_id, database_id, backup_id, version_time): """Creates a backup for a database.""" + + from google.cloud.spanner_admin_database_v1.types import \ + backup as backup_pb + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) # Create a backup expire_time = datetime.utcnow() + timedelta(days=14) - backup = instance.backup( - backup_id, database=database, expire_time=expire_time, version_time=version_time + + request = backup_pb.CreateBackupRequest( + parent=instance.name, + backup_id=backup_id, + backup=backup_pb.Backup( + database=database.name, + expire_time=expire_time, + version_time=version_time, + ), ) - operation = backup.create() + + operation = spanner_client.database_admin_api.create_backup(request) # Wait for backup operation to complete. - operation.result(2100) + backup = operation.result(2100) # Verify that the backup is ready. - backup.reload() - assert backup.is_ready() is True + assert backup.state == backup_pb.Backup.State.READY - # Get the name, create time and backup size. - backup.reload() print( "Backup {} of size {} bytes was created at {} for version of database at {}".format( backup.name, backup.size_bytes, backup.create_time, backup.version_time @@ -57,12 +68,17 @@ def create_backup(instance_id, database_id, backup_id, version_time): # [END spanner_create_backup] + # [START spanner_create_backup_with_encryption_key] def create_backup_with_encryption_key( instance_id, database_id, backup_id, kms_key_name ): """Creates a backup for a database using a Customer Managed Encryption Key (CMEK).""" - from google.cloud.spanner_admin_database_v1 import CreateBackupEncryptionConfig + + from google.cloud.spanner_admin_database_v1 import \ + CreateBackupEncryptionConfig + from google.cloud.spanner_admin_database_v1.types import \ + backup as backup_pb spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) @@ -74,23 +90,24 @@ def create_backup_with_encryption_key( "encryption_type": CreateBackupEncryptionConfig.EncryptionType.CUSTOMER_MANAGED_ENCRYPTION, "kms_key_name": kms_key_name, } - backup = instance.backup( - backup_id, - database=database, - expire_time=expire_time, + request = backup_pb.CreateBackupRequest( + parent=instance.name, + backup_id=backup_id, + backup=backup_pb.Backup( + database=database.name, + expire_time=expire_time, + ), encryption_config=encryption_config, ) - operation = backup.create() + operation = spanner_client.database_admin_api.create_backup(request) # Wait for backup operation to complete. - operation.result(2100) + backup = operation.result(2100) # Verify that the backup is ready. - backup.reload() - assert backup.is_ready() is True + assert backup.state == backup_pb.Backup.State.READY # Get the name, create time, backup size and encryption key. - backup.reload() print( "Backup {} of size {} bytes was created at {} using encryption key {}".format( backup.name, backup.size_bytes, backup.create_time, kms_key_name @@ -104,21 +121,24 @@ def create_backup_with_encryption_key( # [START spanner_restore_backup] def restore_database(instance_id, new_database_id, backup_id): """Restores a database from a backup.""" + from google.cloud.spanner_admin_database_v1 import RestoreDatabaseRequest + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - # Create a backup on database_id. # Start restoring an existing backup to a new database. - backup = instance.backup(backup_id) - new_database = instance.database(new_database_id) - operation = new_database.restore(backup) + request = RestoreDatabaseRequest( + parent=instance.name, + database_id=new_database_id, + backup="{}/backups/{}".format(instance.name, backup_id), + ) + operation = spanner_client.database_admin_api.restore_database(request) # Wait for restore operation to complete. - operation.result(1600) + db = operation.result(1600) # Newly created database has restore information. - new_database.reload() - restore_info = new_database.restore_info + restore_info = db.restore_info print( "Database {} restored to {} from backup {} with version time {}.".format( restore_info.backup_info.source_database, @@ -137,34 +157,37 @@ def restore_database_with_encryption_key( instance_id, new_database_id, backup_id, kms_key_name ): """Restores a database from a backup using a Customer Managed Encryption Key (CMEK).""" - from google.cloud.spanner_admin_database_v1 import RestoreDatabaseEncryptionConfig + from google.cloud.spanner_admin_database_v1 import ( + RestoreDatabaseEncryptionConfig, RestoreDatabaseRequest) spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) # Start restoring an existing backup to a new database. - backup = instance.backup(backup_id) encryption_config = { "encryption_type": RestoreDatabaseEncryptionConfig.EncryptionType.CUSTOMER_MANAGED_ENCRYPTION, "kms_key_name": kms_key_name, } - new_database = instance.database( - new_database_id, encryption_config=encryption_config + + request = RestoreDatabaseRequest( + parent=instance.name, + database_id=new_database_id, + backup="{}/backups/{}".format(instance.name, backup_id), + encryption_config=encryption_config, ) - operation = new_database.restore(backup) + operation = spanner_client.database_admin_api.restore_database(request) # Wait for restore operation to complete. - operation.result(1600) + db = operation.result(1600) # Newly created database has restore information. - new_database.reload() - restore_info = new_database.restore_info + restore_info = db.restore_info print( "Database {} restored to {} from backup {} with using encryption key {}.".format( restore_info.backup_info.source_database, new_database_id, restore_info.backup_info.backup, - new_database.encryption_config.kms_key_name, + db.encryption_config.kms_key_name, ) ) @@ -174,6 +197,9 @@ def restore_database_with_encryption_key( # [START spanner_cancel_backup_create] def cancel_backup(instance_id, database_id, backup_id): + from google.cloud.spanner_admin_database_v1.types import \ + backup as backup_pb + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) @@ -181,9 +207,16 @@ def cancel_backup(instance_id, database_id, backup_id): expire_time = datetime.utcnow() + timedelta(days=30) # Create a backup. - backup = instance.backup(backup_id, database=database, expire_time=expire_time) - operation = backup.create() + request = backup_pb.CreateBackupRequest( + parent=instance.name, + backup_id=backup_id, + backup=backup_pb.Backup( + database=database.name, + expire_time=expire_time, + ), + ) + operation = spanner_client.database_admin_api.create_backup(request) # Cancel backup creation. operation.cancel() @@ -192,13 +225,22 @@ def cancel_backup(instance_id, database_id, backup_id): while not operation.done(): time.sleep(300) # 5 mins - # Deal with resource if the operation succeeded. - if backup.exists(): - print("Backup was created before the cancel completed.") - backup.delete() - print("Backup deleted.") - else: + try: + spanner_client.database_admin_api.get_backup( + backup_pb.GetBackupRequest( + name="{}/backups/{}".format(instance.name, backup_id) + ) + ) + except NotFound: print("Backup creation was successfully cancelled.") + return + print("Backup was created before the cancel completed.") + spanner_client.database_admin_api.delete_backup( + backup_pb.DeleteBackupRequest( + name="{}/backups/{}".format(instance.name, backup_id) + ) + ) + print("Backup deleted.") # [END spanner_cancel_backup_create] @@ -206,6 +248,9 @@ def cancel_backup(instance_id, database_id, backup_id): # [START spanner_list_backup_operations] def list_backup_operations(instance_id, database_id, backup_id): + from google.cloud.spanner_admin_database_v1.types import \ + backup as backup_pb + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) @@ -215,9 +260,14 @@ def list_backup_operations(instance_id, database_id, backup_id): "google.spanner.admin.database.v1.CreateBackupMetadata) " "AND (metadata.database:{})" ).format(database_id) - operations = instance.list_backup_operations(filter_=filter_) + request = backup_pb.ListBackupOperationsRequest( + parent=instance.name, filter=filter_ + ) + operations = spanner_client.database_admin_api.list_backup_operations(request) for op in operations: - metadata = op.metadata + metadata = protobuf_helpers.from_any_pb( + backup_pb.CreateBackupMetadata, op.metadata + ) print( "Backup {} on database {}: {}% complete.".format( metadata.name, metadata.database, metadata.progress.progress_percent @@ -229,9 +279,14 @@ def list_backup_operations(instance_id, database_id, backup_id): "(metadata.@type:type.googleapis.com/google.spanner.admin.database.v1.CopyBackupMetadata) " "AND (metadata.source_backup:{})" ).format(backup_id) - operations = instance.list_backup_operations(filter_=filter_) + request = backup_pb.ListBackupOperationsRequest( + parent=instance.name, filter=filter_ + ) + operations = spanner_client.database_admin_api.list_backup_operations(request) for op in operations: - metadata = op.metadata + metadata = protobuf_helpers.from_any_pb( + backup_pb.CopyBackupMetadata, op.metadata + ) print( "Backup {} on source backup {}: {}% complete.".format( metadata.name, @@ -246,6 +301,9 @@ def list_backup_operations(instance_id, database_id, backup_id): # [START spanner_list_database_operations] def list_database_operations(instance_id): + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) @@ -254,11 +312,17 @@ def list_database_operations(instance_id): "(metadata.@type:type.googleapis.com/" "google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata)" ) - operations = instance.list_database_operations(filter_=filter_) + request = spanner_database_admin.ListDatabaseOperationsRequest( + parent=instance.name, filter=filter_ + ) + operations = spanner_client.database_admin_api.list_database_operations(request) for op in operations: + metadata = protobuf_helpers.from_any_pb( + spanner_database_admin.OptimizeRestoredDatabaseMetadata, op.metadata + ) print( "Database {} restored from backup is {}% optimized.".format( - op.metadata.name, op.metadata.progress.progress_percent + metadata.name, metadata.progress.progress_percent ) ) @@ -268,22 +332,35 @@ def list_database_operations(instance_id): # [START spanner_list_backups] def list_backups(instance_id, database_id, backup_id): + from google.cloud.spanner_admin_database_v1.types import \ + backup as backup_pb + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) # List all backups. print("All backups:") - for backup in instance.list_backups(): + request = backup_pb.ListBackupsRequest(parent=instance.name, filter="") + operations = spanner_client.database_admin_api.list_backups(request) + for backup in operations: print(backup.name) # List all backups that contain a name. print('All backups with backup name containing "{}":'.format(backup_id)) - for backup in instance.list_backups(filter_="name:{}".format(backup_id)): + request = backup_pb.ListBackupsRequest( + parent=instance.name, filter="name:{}".format(backup_id) + ) + operations = spanner_client.database_admin_api.list_backups(request) + for backup in operations: print(backup.name) # List all backups for a database that contains a name. print('All backups with database name containing "{}":'.format(database_id)) - for backup in instance.list_backups(filter_="database:{}".format(database_id)): + request = backup_pb.ListBackupsRequest( + parent=instance.name, filter="database:{}".format(database_id) + ) + operations = spanner_client.database_admin_api.list_backups(request) + for backup in operations: print(backup.name) # List all backups that expire before a timestamp. @@ -293,14 +370,21 @@ def list_backups(instance_id, database_id, backup_id): *expire_time.timetuple() ) ) - for backup in instance.list_backups( - filter_='expire_time < "{}-{}-{}T{}:{}:{}Z"'.format(*expire_time.timetuple()) - ): + request = backup_pb.ListBackupsRequest( + parent=instance.name, + filter='expire_time < "{}-{}-{}T{}:{}:{}Z"'.format(*expire_time.timetuple()), + ) + operations = spanner_client.database_admin_api.list_backups(request) + for backup in operations: print(backup.name) # List all backups with a size greater than some bytes. print("All backups with backup size more than 100 bytes:") - for backup in instance.list_backups(filter_="size_bytes > 100"): + request = backup_pb.ListBackupsRequest( + parent=instance.name, filter="size_bytes > 100" + ) + operations = spanner_client.database_admin_api.list_backups(request) + for backup in operations: print(backup.name) # List backups that were created after a timestamp that are also ready. @@ -310,18 +394,23 @@ def list_backups(instance_id, database_id, backup_id): *create_time.timetuple() ) ) - for backup in instance.list_backups( - filter_='create_time >= "{}-{}-{}T{}:{}:{}Z" AND state:READY'.format( + request = backup_pb.ListBackupsRequest( + parent=instance.name, + filter='create_time >= "{}-{}-{}T{}:{}:{}Z" AND state:READY'.format( *create_time.timetuple() - ) - ): + ), + ) + operations = spanner_client.database_admin_api.list_backups(request) + for backup in operations: print(backup.name) print("All backups with pagination") # If there are multiple pages, additional ``ListBackup`` # requests will be made as needed while iterating. paged_backups = set() - for backup in instance.list_backups(page_size=2): + request = backup_pb.ListBackupsRequest(parent=instance.name, page_size=2) + operations = spanner_client.database_admin_api.list_backups(request) + for backup in operations: paged_backups.add(backup.name) for backup in paged_backups: print(backup) @@ -332,22 +421,39 @@ def list_backups(instance_id, database_id, backup_id): # [START spanner_delete_backup] def delete_backup(instance_id, backup_id): + from google.cloud.spanner_admin_database_v1.types import \ + backup as backup_pb + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - backup = instance.backup(backup_id) - backup.reload() + backup = spanner_client.database_admin_api.get_backup( + backup_pb.GetBackupRequest( + name="{}/backups/{}".format(instance.name, backup_id) + ) + ) # Wait for databases that reference this backup to finish optimizing. while backup.referencing_databases: time.sleep(30) - backup.reload() + backup = spanner_client.database_admin_api.get_backup( + backup_pb.GetBackupRequest( + name="{}/backups/{}".format(instance.name, backup_id) + ) + ) # Delete the backup. - backup.delete() + spanner_client.database_admin_api.delete_backup( + backup_pb.DeleteBackupRequest(name=backup.name) + ) # Verify that the backup is deleted. - assert backup.exists() is False - print("Backup {} has been deleted.".format(backup.name)) + try: + backup = spanner_client.database_admin_api.get_backup( + backup_pb.GetBackupRequest(name=backup.name) + ) + except NotFound: + print("Backup {} has been deleted.".format(backup.name)) + return # [END spanner_delete_backup] @@ -355,16 +461,28 @@ def delete_backup(instance_id, backup_id): # [START spanner_update_backup] def update_backup(instance_id, backup_id): + from google.cloud.spanner_admin_database_v1.types import \ + backup as backup_pb + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - backup = instance.backup(backup_id) - backup.reload() + + backup = spanner_client.database_admin_api.get_backup( + backup_pb.GetBackupRequest( + name="{}/backups/{}".format(instance.name, backup_id) + ) + ) # Expire time must be within 366 days of the create time of the backup. old_expire_time = backup.expire_time # New expire time should be less than the max expire time new_expire_time = min(backup.max_expire_time, old_expire_time + timedelta(days=30)) - backup.update_expire_time(new_expire_time) + spanner_client.database_admin_api.update_backup( + backup_pb.UpdateBackupRequest( + backup=backup_pb.Backup(name=backup.name, expire_time=new_expire_time), + update_mask={"paths": ["expire_time"]}, + ) + ) print( "Backup {} expire time was updated from {} to {}.".format( backup.name, old_expire_time, new_expire_time @@ -380,6 +498,10 @@ def create_database_with_version_retention_period( instance_id, database_id, retention_period ): """Creates a database with a version retention period.""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) ddl_statements = [ @@ -400,20 +522,24 @@ def create_database_with_version_retention_period( database_id, retention_period ), ] - db = instance.database(database_id, ddl_statements) - operation = db.create() - - operation.result(30) - - db.reload() + operation = spanner_client.database_admin_api.create_database( + request=spanner_database_admin.CreateDatabaseRequest( + parent=instance.name, + create_statement="CREATE DATABASE `{}`".format(database_id), + extra_statements=ddl_statements, + ) + ) + db = operation.result(30) print( "Database {} created with version retention period {} and earliest version time {}".format( - db.database_id, db.version_retention_period, db.earliest_version_time + db.name, db.version_retention_period, db.earliest_version_time ) ) - db.drop() + spanner_client.database_admin_api.drop_database( + spanner_database_admin.DropDatabaseRequest(database=db.name) + ) # [END spanner_create_database_with_version_retention_period] @@ -422,22 +548,29 @@ def create_database_with_version_retention_period( # [START spanner_copy_backup] def copy_backup(instance_id, backup_id, source_backup_path): """Copies a backup.""" + + from google.cloud.spanner_admin_database_v1.types import \ + backup as backup_pb + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) # Create a backup object and wait for copy backup operation to complete. expire_time = datetime.utcnow() + timedelta(days=14) - copy_backup = instance.copy_backup( - backup_id=backup_id, source_backup=source_backup_path, expire_time=expire_time + request = backup_pb.CopyBackupRequest( + parent=instance.name, + backup_id=backup_id, + source_backup=source_backup_path, + expire_time=expire_time, ) - operation = copy_backup.create() - # Wait for copy backup operation to complete. - operation.result(2100) + operation = spanner_client.database_admin_api.copy_backup(request) + + # Wait for backup operation to complete. + copy_backup = operation.result(2100) # Verify that the copy backup is ready. - copy_backup.reload() - assert copy_backup.is_ready() is True + assert copy_backup.state == backup_pb.Backup.State.READY print( "Backup {} of size {} bytes was created at {} with version time {}".format( diff --git a/samples/samples/backup_sample_test.py b/samples/samples/backup_sample_test.py index 5f094e7a77..6d656c5545 100644 --- a/samples/samples/backup_sample_test.py +++ b/samples/samples/backup_sample_test.py @@ -13,8 +13,8 @@ # limitations under the License. import uuid -from google.api_core.exceptions import DeadlineExceeded import pytest +from google.api_core.exceptions import DeadlineExceeded from test_utils.retry import RetryErrors import backup_sample diff --git a/samples/samples/conftest.py b/samples/samples/conftest.py index 5b1af63876..9f0b7d12a0 100644 --- a/samples/samples/conftest.py +++ b/samples/samples/conftest.py @@ -16,15 +16,11 @@ import time import uuid +import pytest from google.api_core import exceptions - from google.cloud import spanner_admin_database_v1 from google.cloud.spanner_admin_database_v1.types.common import DatabaseDialect -from google.cloud.spanner_v1 import backup -from google.cloud.spanner_v1 import client -from google.cloud.spanner_v1 import database -from google.cloud.spanner_v1 import instance -import pytest +from google.cloud.spanner_v1 import backup, client, database, instance from test_utils import retry INSTANCE_CREATION_TIMEOUT = 560 # seconds diff --git a/samples/samples/pg_snippets.py b/samples/samples/pg_snippets.py index 51ddec6906..fe5ebab02c 100644 --- a/samples/samples/pg_snippets.py +++ b/samples/samples/pg_snippets.py @@ -68,26 +68,34 @@ def create_instance(instance_id): # [START spanner_postgresql_create_database] def create_database(instance_id, database_id): """Creates a PostgreSql database and tables for sample data.""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - database = instance.database( - database_id, + request = spanner_database_admin.CreateDatabaseRequest( + parent=instance.name, + create_statement=f'CREATE DATABASE "{database_id}"', database_dialect=DatabaseDialect.POSTGRESQL, ) - operation = database.create() + operation = spanner_client.database_admin_api.create_database(request=request) print("Waiting for operation to complete...") - operation.result(OPERATION_TIMEOUT_SECONDS) + database = operation.result(OPERATION_TIMEOUT_SECONDS) create_table_using_ddl(database.name) print("Created database {} on instance {}".format(database_id, instance_id)) def create_table_using_ddl(database_name): + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() - request = spanner_admin_database_v1.UpdateDatabaseDdlRequest( + request = spanner_database_admin.UpdateDatabaseDdlRequest( database=database_name, statements=[ """CREATE TABLE Singers ( @@ -231,13 +239,19 @@ def read_data(instance_id, database_id): # [START spanner_postgresql_add_column] def add_column(instance_id, database_id): """Adds a new column to the Albums table in the example database.""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - ["ALTER TABLE Albums ADD COLUMN MarketingBudget BIGINT"] + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=["ALTER TABLE Albums ADD COLUMN MarketingBudget BIGINT"], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -390,6 +404,7 @@ def add_index(instance_id, database_id): # [END spanner_postgresql_create_index] + # [START spanner_postgresql_read_data_with_index] def read_data_with_index(instance_id, database_id): """Reads sample data from the database using an index. @@ -424,17 +439,24 @@ def read_data_with_index(instance_id, database_id): # [START spanner_postgresql_create_storing_index] def add_storing_index(instance_id, database_id): """Adds an storing index to the example database.""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle)" "INCLUDE (MarketingBudget)" - ] + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -1066,11 +1088,15 @@ def create_table_with_datatypes(instance_id, database_id): # [START spanner_postgresql_create_table_with_datatypes] # instance_id = "your-spanner-instance" # database_id = "your-spanner-db-id" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_admin_database_v1.UpdateDatabaseDdlRequest( + request = spanner_database_admin.UpdateDatabaseDdlRequest( database=database.name, statements=[ """CREATE TABLE Venues ( @@ -1447,14 +1473,20 @@ def add_jsonb_column(instance_id, database_id): # instance_id = "your-spanner-instance" # database_id = "your-spanner-db-id" + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - ["ALTER TABLE Venues ADD COLUMN VenueDetails JSONB"] + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=["ALTER TABLE Venues ADD COLUMN VenueDetails JSONB"], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -1524,6 +1556,7 @@ def update_data_with_jsonb(instance_id, database_id): # [END spanner_postgresql_jsonb_update_data] + # [START spanner_postgresql_jsonb_query_parameter] def query_data_with_jsonb_parameter(instance_id, database_id): """Queries sample data using SQL with a JSONB parameter.""" @@ -1555,11 +1588,15 @@ def query_data_with_jsonb_parameter(instance_id, database_id): # [START spanner_postgresql_create_sequence] def create_sequence(instance_id, database_id): """Creates the Sequence and insert data""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - request = spanner_admin_database_v1.UpdateDatabaseDdlRequest( + request = spanner_database_admin.UpdateDatabaseDdlRequest( database=database.name, statements=[ "CREATE SEQUENCE Seq BIT_REVERSED_POSITIVE", @@ -1601,14 +1638,23 @@ def insert_customers(transaction): # [END spanner_postgresql_create_sequence] + # [START spanner_postgresql_alter_sequence] def alter_sequence(instance_id, database_id): """Alters the Sequence and insert data""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl(["ALTER SEQUENCE Seq SKIP RANGE 1000 5000000"]) + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=["ALTER SEQUENCE Seq SKIP RANGE 1000 5000000"], + ) + operation = spanner_client.database_admin_api.update_database_ddl(request) print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -1640,19 +1686,26 @@ def insert_customers(transaction): # [END spanner_postgresql_alter_sequence] + # [START spanner_postgresql_drop_sequence] def drop_sequence(instance_id, database_id): """Drops the Sequence""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ "ALTER TABLE Customers ALTER COLUMN CustomerId DROP DEFAULT", "DROP SEQUENCE Seq", - ] + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) diff --git a/samples/samples/pg_snippets_test.py b/samples/samples/pg_snippets_test.py index d4f08499d2..1b5d2971c1 100644 --- a/samples/samples/pg_snippets_test.py +++ b/samples/samples/pg_snippets_test.py @@ -15,9 +15,9 @@ import time import uuid +import pytest from google.api_core import exceptions from google.cloud.spanner_admin_database_v1.types.common import DatabaseDialect -import pytest from test_utils.retry import RetryErrors import pg_snippets as snippets diff --git a/samples/samples/quickstart.py b/samples/samples/quickstart.py index aa330dd3ca..f2d355d931 100644 --- a/samples/samples/quickstart.py +++ b/samples/samples/quickstart.py @@ -25,7 +25,6 @@ def run_quickstart(instance_id, database_id): # # Your Cloud Spanner database ID. # database_id = "my-database-id" - # Instantiate a client. spanner_client = spanner.Client() diff --git a/samples/samples/snippets.py b/samples/samples/snippets.py index 3ffd579f4a..3cef929309 100644 --- a/samples/samples/snippets.py +++ b/samples/samples/snippets.py @@ -30,10 +30,7 @@ from google.cloud import spanner from google.cloud.spanner_admin_instance_v1.types import spanner_instance_admin -from google.cloud.spanner_v1 import param_types -from google.cloud.spanner_v1 import DirectedReadOptions -from google.type import expr_pb2 -from google.iam.v1 import policy_pb2 +from google.cloud.spanner_v1 import DirectedReadOptions, param_types from google.cloud.spanner_v1.data_types import JsonObject from google.protobuf import field_mask_pb2 # type: ignore @@ -43,26 +40,30 @@ # [START spanner_create_instance] def create_instance(instance_id): """Creates an instance.""" + from google.cloud.spanner_admin_instance_v1.types import \ + spanner_instance_admin + spanner_client = spanner.Client() config_name = "{}/instanceConfigs/regional-us-central1".format( spanner_client.project_name ) - instance = spanner_client.instance( - instance_id, - configuration_name=config_name, - display_name="This is a display name.", - node_count=1, - labels={ - "cloud_spanner_samples": "true", - "sample_name": "snippets-create_instance-explicit", - "created": str(int(time.time())), - }, + operation = spanner_client.instance_admin_api.create_instance( + parent=spanner_client.project_name, + instance_id=instance_id, + instance=spanner_instance_admin.Instance( + config=config_name, + display_name="This is a display name.", + node_count=1, + labels={ + "cloud_spanner_samples": "true", + "sample_name": "snippets-create_instance-explicit", + "created": str(int(time.time())), + }, + ), ) - operation = instance.create() - print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -75,28 +76,34 @@ def create_instance(instance_id): # [START spanner_create_instance_with_processing_units] def create_instance_with_processing_units(instance_id, processing_units): """Creates an instance.""" + from google.cloud.spanner_admin_instance_v1.types import \ + spanner_instance_admin + spanner_client = spanner.Client() config_name = "{}/instanceConfigs/regional-us-central1".format( spanner_client.project_name ) - instance = spanner_client.instance( - instance_id, - configuration_name=config_name, - display_name="This is a display name.", - processing_units=processing_units, - labels={ - "cloud_spanner_samples": "true", - "sample_name": "snippets-create_instance_with_processing_units", - "created": str(int(time.time())), - }, + request = spanner_instance_admin.CreateInstanceRequest( + parent=spanner_client.project_name, + instance_id=instance_id, + instance=spanner_instance_admin.Instance( + config=config_name, + display_name="This is a display name.", + processing_units=processing_units, + labels={ + "cloud_spanner_samples": "true", + "sample_name": "snippets-create_instance_with_processing_units", + "created": str(int(time.time())), + }, + ), ) - operation = instance.create() + operation = spanner_client.instance_admin_api.create_instance(request=request) print("Waiting for operation to complete...") - operation.result(OPERATION_TIMEOUT_SECONDS) + instance = operation.result(OPERATION_TIMEOUT_SECONDS) print( "Created instance {} with {} processing units".format( @@ -129,9 +136,17 @@ def get_instance_config(instance_config): # [START spanner_list_instance_configs] def list_instance_config(): """Lists the available instance configurations.""" + from google.cloud.spanner_admin_instance_v1.types import \ + spanner_instance_admin + spanner_client = spanner.Client() - configs = spanner_client.list_instance_configs() - for config in configs: + + request = spanner_instance_admin.ListInstanceConfigsRequest( + parent=spanner_client.project_name + ) + for config in spanner_client.instance_admin_api.list_instance_configs( + request=request + ): print( "Available leader options for instance config {}: {}".format( config.name, config.leader_options @@ -145,11 +160,15 @@ def list_instance_config(): # [START spanner_list_databases] def list_databases(instance_id): """Lists databases and their leader options.""" + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - databases = list(instance.list_databases()) - for database in databases: + request = spanner_database_admin.ListDatabasesRequest(parent=instance.name) + + for database in spanner_client.database_admin_api.list_databases(request=request): print( "Database {} has default leader {}".format( database.name, database.default_leader @@ -163,12 +182,16 @@ def list_databases(instance_id): # [START spanner_create_database] def create_database(instance_id, database_id): """Creates a database and tables for sample data.""" + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - database = instance.database( - database_id, - ddl_statements=[ + request = spanner_database_admin.CreateDatabaseRequest( + parent=instance.name, + create_statement=f"CREATE DATABASE `{database_id}`", + extra_statements=[ """CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), @@ -187,12 +210,12 @@ def create_database(instance_id, database_id): ], ) - operation = database.create() + operation = spanner_client.database_admin_api.create_database(request=request) print("Waiting for operation to complete...") - operation.result(OPERATION_TIMEOUT_SECONDS) + database = operation.result(OPERATION_TIMEOUT_SECONDS) - print("Created database {} on instance {}".format(database_id, instance_id)) + print("Created database {} on instance {}".format(database.name, instance.name)) # [END spanner_create_database] @@ -201,18 +224,28 @@ def create_database(instance_id, database_id): # [START spanner_update_database] def update_database(instance_id, database_id): """Updates the drop protection setting for a database.""" + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - db = instance.database(database_id) - db.enable_drop_protection = True - - operation = db.update(["enable_drop_protection"]) - - print("Waiting for update operation for {} to complete...".format(db.name)) + request = spanner_database_admin.UpdateDatabaseRequest( + database=spanner_database_admin.Database( + name="{}/databases/{}".format(instance.name, database_id), + enable_drop_protection=True, + ), + update_mask={"paths": ["enable_drop_protection"]}, + ) + operation = spanner_client.database_admin_api.update_database(request=request) + print( + "Waiting for update operation for {}/databases/{} to complete...".format( + instance.name, database_id + ) + ) operation.result(OPERATION_TIMEOUT_SECONDS) - print("Updated database {}.".format(db.name)) + print("Updated database {}/databases/{}.".format(instance.name, database_id)) # [END spanner_update_database] @@ -221,12 +254,17 @@ def update_database(instance_id, database_id): # [START spanner_create_database_with_encryption_key] def create_database_with_encryption_key(instance_id, database_id, kms_key_name): """Creates a database with tables using a Customer Managed Encryption Key (CMEK).""" + from google.cloud.spanner_admin_database_v1 import EncryptionConfig + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - database = instance.database( - database_id, - ddl_statements=[ + request = spanner_database_admin.CreateDatabaseRequest( + parent=instance.name, + create_statement=f"CREATE DATABASE `{database_id}`", + extra_statements=[ """CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), @@ -240,13 +278,13 @@ def create_database_with_encryption_key(instance_id, database_id, kms_key_name): ) PRIMARY KEY (SingerId, AlbumId), INTERLEAVE IN PARENT Singers ON DELETE CASCADE""", ], - encryption_config={"kms_key_name": kms_key_name}, + encryption_config=EncryptionConfig(kms_key_name=kms_key_name), ) - operation = database.create() + operation = spanner_client.database_admin_api.create_database(request=request) print("Waiting for operation to complete...") - operation.result(OPERATION_TIMEOUT_SECONDS) + database = operation.result(OPERATION_TIMEOUT_SECONDS) print( "Database {} created with encryption key {}".format( @@ -261,34 +299,39 @@ def create_database_with_encryption_key(instance_id, database_id, kms_key_name): # [START spanner_create_database_with_default_leader] def create_database_with_default_leader(instance_id, database_id, default_leader): """Creates a database with tables with a default leader.""" - spanner_client = spanner.Client() - instance = spanner_client.instance(instance_id) - - database = instance.database( - database_id, - ddl_statements=[ - """CREATE TABLE Singers ( - SingerId INT64 NOT NULL, - FirstName STRING(1024), - LastName STRING(1024), - SingerInfo BYTES(MAX) - ) PRIMARY KEY (SingerId)""", - """CREATE TABLE Albums ( - SingerId INT64 NOT NULL, - AlbumId INT64 NOT NULL, - AlbumTitle STRING(MAX) - ) PRIMARY KEY (SingerId, AlbumId), - INTERLEAVE IN PARENT Singers ON DELETE CASCADE""", - "ALTER DATABASE {}" - " SET OPTIONS (default_leader = '{}')".format(database_id, default_leader), - ], + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + + spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + + operation = spanner_client.database_admin_api.create_database( + request=spanner_database_admin.CreateDatabaseRequest( + parent=instance.name, + create_statement=f"CREATE DATABASE `{database_id}`", + extra_statements=[ + """CREATE TABLE Singers ( + SingerId INT64 NOT NULL, + FirstName STRING(1024), + LastName STRING(1024), + SingerInfo BYTES(MAX) + ) PRIMARY KEY (SingerId)""", + """CREATE TABLE Albums ( + SingerId INT64 NOT NULL, + AlbumId INT64 NOT NULL, + AlbumTitle STRING(MAX) + ) PRIMARY KEY (SingerId, AlbumId), + INTERLEAVE IN PARENT Singers ON DELETE CASCADE""", + "ALTER DATABASE {}" + " SET OPTIONS (default_leader = '{}')".format( + database_id, default_leader + ), + ], + ) ) - operation = database.create() print("Waiting for operation to complete...") - operation.result(OPERATION_TIMEOUT_SECONDS) - - database.reload() + database = operation.result(OPERATION_TIMEOUT_SECONDS) print( "Database {} created with default leader {}".format( @@ -303,25 +346,26 @@ def create_database_with_default_leader(instance_id, database_id, default_leader # [START spanner_update_database_with_default_leader] def update_database_with_default_leader(instance_id, database_id, default_leader): """Updates a database with tables with a default leader.""" + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - database = instance.database(database_id) - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ "ALTER DATABASE {}" " SET OPTIONS (default_leader = '{}')".format(database_id, default_leader) - ] + ], ) - operation.result(OPERATION_TIMEOUT_SECONDS) + operation = spanner_client.database_admin_api.update_database_ddl(request) - database.reload() + operation.result(OPERATION_TIMEOUT_SECONDS) print( - "Database {} updated with default leader {}".format( - database.name, database.default_leader - ) + "Database {} updated with default leader {}".format(database_id, default_leader) ) @@ -590,14 +634,21 @@ def query_data_with_new_column(instance_id, database_id): # [START spanner_create_index] def add_index(instance_id, database_id): """Adds a simple index to the example database.""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - ["CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"] + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=["CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -686,17 +737,24 @@ def read_data_with_index(instance_id, database_id): # [START spanner_create_storing_index] def add_storing_index(instance_id, database_id): """Adds an storing index to the example database.""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle)" "STORING (MarketingBudget)" - ] + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -742,17 +800,25 @@ def read_data_with_storing_index(instance_id, database_id): # [START spanner_add_column] def add_column(instance_id, database_id): """Adds a new column to the Albums table in the example database.""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - ["ALTER TABLE Albums ADD COLUMN MarketingBudget INT64"] + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ + "ALTER TABLE Albums ADD COLUMN MarketingBudget INT64", + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) - print("Added the MarketingBudget column.") @@ -897,12 +963,16 @@ def read_only_transaction(instance_id, database_id): def create_table_with_timestamp(instance_id, database_id): """Creates a table with a COMMIT_TIMESTAMP column.""" + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ """CREATE TABLE Performances ( SingerId INT64 NOT NULL, VenueId INT64 NOT NULL, @@ -912,9 +982,11 @@ def create_table_with_timestamp(instance_id, database_id): OPTIONS(allow_commit_timestamp=true) ) PRIMARY KEY (SingerId, VenueId, EventDate), INTERLEAVE IN PARENT Singers ON DELETE CASCADE""" - ] + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -957,18 +1029,25 @@ def insert_data_with_timestamp(instance_id, database_id): # [START spanner_add_timestamp_column] def add_timestamp_column(instance_id, database_id): """Adds a new TIMESTAMP column to the Albums table in the example database.""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ "ALTER TABLE Albums ADD COLUMN LastUpdateTime TIMESTAMP " "OPTIONS(allow_commit_timestamp=true)" - ] + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -1054,12 +1133,20 @@ def query_data_with_timestamp(instance_id, database_id): # [START spanner_add_numeric_column] def add_numeric_column(instance_id, database_id): """Adds a new NUMERIC column to the Venues table in the example database.""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - database = instance.database(database_id) - operation = database.update_ddl(["ALTER TABLE Venues ADD COLUMN Revenue NUMERIC"]) + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=["ALTER TABLE Venues ADD COLUMN Revenue NUMERIC"], + ) + + operation = spanner_client.database_admin_api.update_database_ddl(request) print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -1111,12 +1198,22 @@ def update_data_with_numeric(instance_id, database_id): # [START spanner_add_json_column] def add_json_column(instance_id, database_id): """Adds a new JSON column to the Venues table in the example database.""" + # instance_id = "your-spanner-instance" + # database_id = "your-spanner-db-id" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) - database = instance.database(database_id) - operation = database.update_ddl(["ALTER TABLE Venues ADD COLUMN VenueDetails JSON"]) + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=["ALTER TABLE Venues ADD COLUMN VenueDetails JSON"], + ) + + operation = spanner_client.database_admin_api.update_database_ddl(request) print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -1374,6 +1471,7 @@ def insert_singers(transaction): # [START spanner_get_commit_stats] def log_commit_stats(instance_id, database_id): """Inserts sample data using DML and displays the commit statistics.""" + # By default, commit statistics are logged via stdout at level Info. # This sample uses a custom logger to access the commit statistics. class CommitStatsSampleLogger(logging.Logger): @@ -1812,12 +1910,17 @@ def create_table_with_datatypes(instance_id, database_id): # [START spanner_create_table_with_datatypes] # instance_id = "your-spanner-instance" # database_id = "your-spanner-db-id" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ """CREATE TABLE Venues ( VenueId INT64 NOT NULL, VenueName STRING(100), @@ -1830,8 +1933,9 @@ def create_table_with_datatypes(instance_id, database_id): LastUpdateTime TIMESTAMP NOT NULL OPTIONS(allow_commit_timestamp=true) ) PRIMARY KEY (VenueId)""" - ] + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -2333,6 +2437,7 @@ def create_instance_config(user_config_name, base_config_id): # [END spanner_create_instance_config] + # [START spanner_update_instance_config] def update_instance_config(user_config_name): """Updates the user-managed instance configuration.""" @@ -2357,6 +2462,7 @@ def update_instance_config(user_config_name): # [END spanner_update_instance_config] + # [START spanner_delete_instance_config] def delete_instance_config(user_config_id): """Deleted the user-managed instance configuration.""" @@ -2398,31 +2504,42 @@ def add_and_drop_database_roles(instance_id, database_id): # [START spanner_add_and_drop_database_role] # instance_id = "your-spanner-instance" # database_id = "your-spanner-db-id" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) + role_parent = "new_parent" role_child = "new_child" - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ "CREATE ROLE {}".format(role_parent), "GRANT SELECT ON TABLE Singers TO ROLE {}".format(role_parent), "CREATE ROLE {}".format(role_child), "GRANT ROLE {} TO ROLE {}".format(role_parent, role_child), - ] + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + operation.result(OPERATION_TIMEOUT_SECONDS) print( "Created roles {} and {} and granted privileges".format(role_parent, role_child) ) - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ "REVOKE ROLE {} FROM ROLE {}".format(role_parent, role_child), "DROP ROLE {}".format(role_child), - ] + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + operation.result(OPERATION_TIMEOUT_SECONDS) print("Revoked privileges and dropped role {}".format(role_child)) @@ -2452,13 +2569,17 @@ def list_database_roles(instance_id, database_id): # [START spanner_list_database_roles] # instance_id = "your-spanner-instance" # database_id = "your-spanner-db-id" + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) + request = spanner_database_admin.ListDatabaseRolesRequest(parent=database.name) # List database roles. print("Database Roles are:") - for role in database.list_database_roles(): + for role in spanner_client.database_admin_api.list_database_roles(request): print(role.name.split("/")[-1]) # [END spanner_list_database_roles] @@ -2477,6 +2598,10 @@ def enable_fine_grained_access( # iam_member = "user:alice@example.com" # database_role = "new_parent" # title = "condition title" + + from google.iam.v1 import iam_policy_pb2, options_pb2, policy_pb2 + from google.type import expr_pb2 + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) @@ -2485,7 +2610,11 @@ def enable_fine_grained_access( # that you specified, or it might use a lower policy version. For example, if you # specify version 3, but the policy has no conditional role bindings, the response # uses version 1. Valid values are 0, 1, and 3. - policy = database.get_iam_policy(3) + request = iam_policy_pb2.GetIamPolicyRequest( + resource=database.name, + options=options_pb2.GetPolicyOptions(requested_policy_version=3), + ) + policy = spanner_client.database_admin_api.get_iam_policy(request=request) if policy.version < 3: policy.version = 3 @@ -2500,9 +2629,13 @@ def enable_fine_grained_access( policy.version = 3 policy.bindings.append(new_binding) - database.set_iam_policy(policy) + set_request = iam_policy_pb2.SetIamPolicyRequest( + resource=database.name, + policy=policy, + ) + spanner_client.database_admin_api.set_iam_policy(set_request) - new_policy = database.get_iam_policy(3) + new_policy = spanner_client.database_admin_api.get_iam_policy(request=request) print( f"Enabled fine-grained access in IAM. New policy has version {new_policy.version}" ) @@ -2512,12 +2645,17 @@ def enable_fine_grained_access( # [START spanner_create_table_with_foreign_key_delete_cascade] def create_table_with_foreign_key_delete_cascade(instance_id, database_id): """Creates a table with foreign key delete cascade action""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ """CREATE TABLE Customers ( CustomerId INT64 NOT NULL, CustomerName STRING(62) NOT NULL, @@ -2532,9 +2670,11 @@ def create_table_with_foreign_key_delete_cascade(instance_id, database_id): REFERENCES Customers (CustomerId) ON DELETE CASCADE ) PRIMARY KEY (CartId) """, - ] + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -2552,20 +2692,27 @@ def create_table_with_foreign_key_delete_cascade(instance_id, database_id): # [START spanner_alter_table_with_foreign_key_delete_cascade] def alter_table_with_foreign_key_delete_cascade(instance_id, database_id): """Alters a table with foreign key delete cascade action""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ """ALTER TABLE ShoppingCarts ADD CONSTRAINT FKShoppingCartsCustomerName FOREIGN KEY (CustomerName) REFERENCES Customers(CustomerName) ON DELETE CASCADE""" - ] + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -2583,17 +2730,24 @@ def alter_table_with_foreign_key_delete_cascade(instance_id, database_id): # [START spanner_drop_foreign_key_constraint_delete_cascade] def drop_foreign_key_constraint_delete_cascade(instance_id, database_id): """Alter table to drop foreign key delete cascade action""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ """ALTER TABLE ShoppingCarts DROP CONSTRAINT FKShoppingCartsCustomerName""" - ] + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -2611,20 +2765,27 @@ def drop_foreign_key_constraint_delete_cascade(instance_id, database_id): # [START spanner_create_sequence] def create_sequence(instance_id, database_id): """Creates the Sequence and insert data""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ "CREATE SEQUENCE Seq OPTIONS (sequence_kind = 'bit_reversed_positive')", """CREATE TABLE Customers ( CustomerId INT64 DEFAULT (GET_NEXT_SEQUENCE_VALUE(Sequence Seq)), CustomerName STRING(1024) ) PRIMARY KEY (CustomerId)""", - ] + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -2655,19 +2816,27 @@ def insert_customers(transaction): # [END spanner_create_sequence] + # [START spanner_alter_sequence] def alter_sequence(instance_id, database_id): """Alters the Sequence and insert data""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - [ - "ALTER SEQUENCE Seq SET OPTIONS (skip_range_min = 1000, skip_range_max = 5000000)" - ] + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ + "ALTER SEQUENCE Seq SET OPTIONS (skip_range_min = 1000, skip_range_max = 5000000)", + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) @@ -2698,20 +2867,28 @@ def insert_customers(transaction): # [END spanner_alter_sequence] + # [START spanner_drop_sequence] def drop_sequence(instance_id, database_id): """Drops the Sequence""" + + from google.cloud.spanner_admin_database_v1.types import \ + spanner_database_admin + spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) - operation = database.update_ddl( - [ + request = spanner_database_admin.UpdateDatabaseDdlRequest( + database=database.name, + statements=[ "ALTER TABLE Customers ALTER COLUMN CustomerId DROP DEFAULT", "DROP SEQUENCE Seq", - ] + ], ) + operation = spanner_client.database_admin_api.update_database_ddl(request) + print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) diff --git a/samples/samples/snippets_test.py b/samples/samples/snippets_test.py index a49a4ee480..6942f8fa79 100644 --- a/samples/samples/snippets_test.py +++ b/samples/samples/snippets_test.py @@ -15,10 +15,10 @@ import time import uuid +import pytest from google.api_core import exceptions from google.cloud import spanner from google.cloud.spanner_admin_database_v1.types.common import DatabaseDialect -import pytest from test_utils.retry import RetryErrors import snippets