Skip to content

Spanner Commit Timestamp Sample #1425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion spanner/cloud-client/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
google-cloud-spanner==1.2.0
google-cloud-spanner==1.3.0
futures==3.2.0; python_version < "3"
161 changes: 160 additions & 1 deletion spanner/cloud-client/snippets.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,145 @@ def read_only_transaction(instance_id, database_id):
# [END spanner_read_only_transaction]


if __name__ == '__main__':
# [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)

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"""
])

print('Waiting for operation to complete...')
operation.result()

print('Created Performances table on database {} on instance {}'.format(
database_id, instance_id))
# [END spanner_create_table_with_timestamp_column]


# [START spanner_insert_data_with_timestamp_column]
def insert_data_with_timestamp(instance_id, database_id):
"""Inserts data with a COMMIT_TIMESTAMP field into a table. """

spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)

database = instance.database(database_id)

with database.batch() as batch:
batch.insert(
table='Performances',
columns=(
'SingerId', 'VenueId', 'EventDate',
'Revenue', 'LastUpdateTime',),
values=[
(1, 4, "2017-10-05", 11000, spanner.COMMIT_TIMESTAMP),
(1, 19, "2017-11-02", 15000, spanner.COMMIT_TIMESTAMP),
(2, 42, "2017-12-23", 7000, spanner.COMMIT_TIMESTAMP)])

print('Inserted data.')
# [END spanner_insert_data_with_timestamp_column]


# [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)

database = instance.database(database_id)

operation = database.update_ddl([
'ALTER TABLE Albums ADD COLUMN LastUpdateTime TIMESTAMP '
'OPTIONS(allow_commit_timestamp=true)'])

print('Waiting for operation to complete...')
operation.result()

print('Altered table "Albums" on database {} on instance {}.'.format(
database_id, instance_id))
# [END spanner_add_timestamp_column]


# [START spanner_update_data_with_timestamp_column]
def update_data_with_timestamp(instance_id, database_id):
"""Updates Performances tables in the database with the COMMIT_TIMESTAMP
column.

This updates the `MarketingBudget` column which must be created before
running this sample. You can add the column by running the `add_column`
sample or by running this DDL statement against your database:

ALTER TABLE Albums ADD COLUMN MarketingBudget INT64

In addition this update expects the LastUpdateTime column added by
applying this DDL statement against your database:

ALTER TABLE Albums ADD COLUMN LastUpdateTime TIMESTAMP
OPTIONS(allow_commit_timestamp=true)
"""
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)

database = instance.database(database_id)

with database.batch() as batch:
batch.update(
table='Albums',
columns=(
'SingerId', 'AlbumId', 'MarketingBudget', 'LastUpdateTime'),
values=[
(1, 4, 11000, spanner.COMMIT_TIMESTAMP),
(1, 19, 15000, spanner.COMMIT_TIMESTAMP),
(2, 42, 7000, spanner.COMMIT_TIMESTAMP)])

print('Updated data.')
# [END spanner_update_data_with_timestamp_column]


# [START spanner_query_data_with_timestamp_column]
def query_data_with_timestamp(instance_id, database_id):
"""Queries sample data from the database using SQL.

This updates the `LastUpdateTime` column which must be created before
running this sample. You can add the column by running the
`add_timestamp_column` sample or by running this DDL statement
against your database:

ALTER TABLE Performances ADD COLUMN LastUpdateTime TIMESTAMP
OPTIONS (allow_commit_timestamp=true)

"""
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)

database = instance.database(database_id)

with database.snapshot() as snapshot:
results = snapshot.execute_sql(
'SELECT SingerId, AlbumId, AlbumTitle FROM Albums '
'ORDER BY LastUpdateTime DESC')

for row in results:
print(u'SingerId: {}, AlbumId: {}, AlbumTitle: {}'.format(*row))
# [END spanner_query_data_with_timestamp_column]


if __name__ == '__main__': # noqa: C901
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
Expand Down Expand Up @@ -495,6 +633,17 @@ def read_only_transaction(instance_id, database_id):
subparsers.add_parser('add_storing_index', help=add_storing_index.__doc__)
subparsers.add_parser(
'read_data_with_storing_index', help=insert_data.__doc__)
subparsers.add_parser(
'create_table_with_timestamp',
help=create_table_with_timestamp.__doc__)
subparsers.add_parser(
'insert_data_with_timestamp', help=insert_data_with_timestamp.__doc__)
subparsers.add_parser(
'add_timestamp_column', help=add_timestamp_column.__doc__)
subparsers.add_parser(
'update_data_with_timestamp', help=update_data_with_timestamp.__doc__)
subparsers.add_parser(
'query_data_with_timestamp', help=query_data_with_timestamp.__doc__)

args = parser.parse_args()

Expand Down Expand Up @@ -530,3 +679,13 @@ def read_only_transaction(instance_id, database_id):
add_storing_index(args.instance_id, args.database_id)
elif args.command == 'read_data_with_storing_index':
read_data_with_storing_index(args.instance_id, args.database_id)
elif args.command == 'create_table_with_timestamp':
create_table_with_timestamp(args.instance_id, args.database_id)
elif args.command == 'insert_data_with_timestamp':
insert_data_with_timestamp(args.instance_id, args.database_id)
elif args.command == 'add_timestamp_column':
add_timestamp_column(args.instance_id, args.database_id)
elif args.command == 'update_data_with_timestamp':
update_data_with_timestamp(args.instance_id, args.database_id)
elif args.command == 'query_data_with_timestamp':
query_data_with_timestamp(args.instance_id, args.database_id)
54 changes: 54 additions & 0 deletions spanner/cloud-client/snippets_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,57 @@ def _():
out, _ = capsys.readouterr()

assert 'Forever Hold Your Peace' in out


def test_create_table_with_timestamp(temporary_database, capsys):
snippets.create_table_with_timestamp(
SPANNER_INSTANCE,
temporary_database.database_id)

out, _ = capsys.readouterr()

assert 'Performances' in out


def test_insert_data_with_timestamp(temporary_database, capsys):
snippets.insert_data_with_timestamp(
SPANNER_INSTANCE,
temporary_database.database_id)

out, _ = capsys.readouterr()

assert 'Inserted data.' in out


def test_add_timestamp_column(temporary_database, capsys):
snippets.add_timestamp_column(
SPANNER_INSTANCE,
temporary_database.database_id)

out, _ = capsys.readouterr()

assert 'Albums' in out


@pytest.mark.slow
def test_update_data_with_timestamp(temporary_database, capsys):
snippets.update_data_with_timestamp(
SPANNER_INSTANCE,
temporary_database.database_id)

out, _ = capsys.readouterr()

assert 'Updated data.' in out


@pytest.mark.slow
def test_query_data_with_timestamp(temporary_database, capsys):
@eventually_consistent.call
def _():
snippets.query_data_with_timestamp(
SPANNER_INSTANCE,
temporary_database.database_id)

out, _ = capsys.readouterr()

assert 'Go, Go, Go' in out