From 24e40a776c978297700c882a07b52d3486ffdbac Mon Sep 17 00:00:00 2001 From: Jisha Abubaker Date: Mon, 11 Jun 2018 21:19:38 -0700 Subject: [PATCH 1/6] Adding Spanner STRUCT param samples --- spanner/cloud-client/snippets.py | 173 ++++++++++++++++++++++++++ spanner/cloud-client/snippets_test.py | 56 +++++++++ 2 files changed, 229 insertions(+) diff --git a/spanner/cloud-client/snippets.py b/spanner/cloud-client/snippets.py index e6a6f37cfcd..998cabf0824 100644 --- a/spanner/cloud-client/snippets.py +++ b/spanner/cloud-client/snippets.py @@ -23,6 +23,7 @@ import argparse from google.cloud import spanner +from google.cloud.spanner_v1 import param_types # [START spanner_create_database] @@ -597,6 +598,161 @@ def query_data_with_timestamp(instance_id, database_id): print(u'SingerId: {}, AlbumId: {}, AlbumTitle: {}'.format(*row)) # [END spanner_query_data_with_timestamp_column] +# [START spanner_write_data_for_struct_queries] +def write_struct_data(instance_id, database_id): + """Inserts sample data that can be used to test STRUCT parameters in queries. + """ + spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + database = instance.database(database_id) + + with database.batch() as batch: + batch.insert( + table='Singers', + columns=('SingerId', 'FirstName', 'LastName',), + values=[ + (6, u'Elena', u'Campbell'), + (7, u'Gabriel', u'Wright'), + (8, u'Benjamin', u'Martinez'), + (9, u'Hannah', u'Harris')]) + + print 'Inserted sample data for STRUCT queries' +# [END spanner_write_data_for_struct_queries] + +def query_with_struct(instance_id, database_id): + """ + Query a table using STRUCT parameters. + """ + # [START spanner_create_struct_with_data] + record_type = param_types.Struct([ + param_types.StructField('FirstName', param_types.STRING), + param_types.StructField('LastName', param_types.STRING) + ]) + record_value = ('Elena', 'Campbell') + # [END spanner_create_struct_with_data] + + # [START spanner_query_data_with_struct] + 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 FROM Singers WHERE " + "(FirstName, LastName) = @name", + params={'name': record_value}, + param_types={'name': record_type}) + + for row in results: + print(u'SingerId: {}'.format(*row)) + # [END spanner_query_data_with_struct] + +def query_with_array_of_struct(instance_id, database_id): + """ + Query a table using an array of STRUCT parameters. + """ + # [START spanner_create_user_defined_struct] + name_type = param_types.Struct([ + param_types.StructField('FirstName', param_types.STRING), + param_types.StructField('LastName', param_types.STRING) + ]) + # [END spanner_create_user_defined_struct] + + # [START spanner_create_array_of_struct_with_data] + band_members = [("Elena", "Campbell"), + ("Gabriel", "Wright"), + ("Benjamin", "Martinez")] + # [END spanner_create_array_of_struct_with_data] + + # [START spanner_query_data_with_array_of_struct] + 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 FROM Singers WHERE " + "STRUCT" + "(FirstName, LastName) IN UNNEST(@names)", + params={'names': band_members}, + param_types={'names': param_types.Array(name_type)}) + + for row in results: + print(u'SingerId: {}'.format(*row)) + # [END spanner_query_data_with_array_of_struct] + + +# [START spanner_field_access_on_struct_parameters] +def query_struct_field(instance_id, database_id): + """ + Query a table using field access on a STRUCT parameter. + """ + spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + database = instance.database(database_id) + + name_type = param_types.Struct([ + param_types.StructField('FirstName', param_types.STRING), + param_types.StructField('LastName', param_types.STRING) + ]) + + with database.snapshot() as snapshot: + results = snapshot.execute_sql( + "SELECT SingerId FROM Singers " + "WHERE FirstName = @name.FirstName", + params={'name': ("Elena", "Campbell")}, + param_types={'name': name_type}) + + for row in results: + print(u'SingerId: {}'.format(*row)) +# [START spanner_field_access_on_struct_parameters] + + +# [START spanner_field_access_on_nested_struct_parameters] +def query_nested_struct_field(instance_id, database_id): + """ + Query a table using nested field access on a STRUCT parameter. + """ + spanner_client = spanner.Client() + instance = spanner_client.instance(instance_id) + database = instance.database(database_id) + + song_info_type = param_types.Struct([ + param_types.StructField('SongName', param_types.STRING), + param_types.StructField( + 'ArtistNames', param_types.Array( + param_types.Struct([ + param_types.StructField( + 'FirstName', param_types.STRING), + param_types.StructField( + 'LastName', param_types.STRING) + ]) + ) + ) + ]) + + song_info = ('Imagination', [('Elena', 'Campbell'), ('Hannah', 'Harris')]) + + with database.snapshot() as snapshot: + results = snapshot.execute_sql( + "SELECT SingerId, @song_info.SongName " + "FROM Singers WHERE " + "STRUCT" + "(FirstName, LastName) " + "IN UNNEST(@song_info.ArtistNames)", + params={ + 'song_info': song_info + }, + param_types={ + 'song_info': song_info_type + } + ) + + for row in results: + print(u'SingerId: {} SongName: {}'.format(*row)) +# [END spanner_field_access_on_nested_struct_parameters] + if __name__ == '__main__': # noqa: C901 parser = argparse.ArgumentParser( @@ -644,6 +800,13 @@ def query_data_with_timestamp(instance_id, database_id): 'update_data_with_timestamp', help=update_data_with_timestamp.__doc__) subparsers.add_parser( 'query_data_with_timestamp', help=query_data_with_timestamp.__doc__) + subparsers.add_parser('write_struct_data', help=write_struct_data.__doc__) + subparsers.add_parser('query_with_struct', help=query_with_struct.__doc__) + subparsers.add_parser( + 'query_with_array_of_struct', help=query_with_array_of_struct.__doc__) + subparsers.add_parser('query_struct_field', help=query_struct_field.__doc__) + subparsers.add_parser( + 'query_nested_struct_field', help=query_nested_struct_field.__doc__) args = parser.parse_args() @@ -689,3 +852,13 @@ def query_data_with_timestamp(instance_id, database_id): 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) + elif args.command == 'write_struct_data': + write_struct_data(args.instance_id, args.database_id) + elif args.command == 'query_with_struct': + query_with_struct(args.instance_id, args.database_id) + elif args.command == 'query_with_array_of_struct': + query_with_array_of_struct(args.instance_id, args.database_id) + elif args.command == 'query_struct_field': + query_struct_field(args.instance_id, args.database_id) + elif args.command == 'query_nested_struct_field': + query_nested_struct_field(args.instance_id, args.database_id) diff --git a/spanner/cloud-client/snippets_test.py b/spanner/cloud-client/snippets_test.py index bdedd70fe65..a0c8405a962 100644 --- a/spanner/cloud-client/snippets_test.py +++ b/spanner/cloud-client/snippets_test.py @@ -234,3 +234,59 @@ def _(): out, _ = capsys.readouterr() assert 'Go, Go, Go' in out + +@pytest.mark.slow +def test_query_data_with_struct(temporary_database, capsys): + @eventually_consistent.call + def _(): + snippets.write_struct_data( + SPANNER_INSTANCE, + temporary_database.database_id) + snippets.query_with_struct( + SPANNER_INSTANCE, + temporary_database.database_id) + out, _ = capsys.readouterr() + + assert 'SingerId: 6' in out + +@pytest.mark.slow +def test_query_data_with_array_struct(temporary_database, capsys): + @eventually_consistent.call + def _(): + snippets.write_struct_data( + SPANNER_INSTANCE, + temporary_database.database_id) + snippets.query_with_array_of_struct( + SPANNER_INSTANCE, + temporary_database.database_id) + out, _ = capsys.readouterr() + + assert 'SingerId: 6\nSingerId: 7' in out + +@pytest.mark.slow +def test_query_data_with_field_struct(temporary_database, capsys): + @eventually_consistent.call + def _(): + snippets.write_struct_data( + SPANNER_INSTANCE, + temporary_database.database_id) + snippets.query_struct_field( + SPANNER_INSTANCE, + temporary_database.database_id) + out, _ = capsys.readouterr() + + assert 'SingerId: 6' in out + +@pytest.mark.slow +def test_query_data_with_nested_field_struct(temporary_database, capsys): + @eventually_consistent.call + def _(): + snippets.write_struct_data( + SPANNER_INSTANCE, + temporary_database.database_id) + snippets.query_nested_struct_field( + SPANNER_INSTANCE, + temporary_database.database_id) + out, _ = capsys.readouterr() + + assert 'SingerId: 6 SongName: Imagination\nSingerId: 9 SongName: Imagination' in out From 4b178d11159d12ed9736429e29fe8ee6c463ac71 Mon Sep 17 00:00:00 2001 From: Jisha Abubaker Date: Mon, 11 Jun 2018 21:27:43 -0700 Subject: [PATCH 2/6] lint fixes --- spanner/cloud-client/snippets.py | 6 +++++- spanner/cloud-client/snippets_test.py | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/spanner/cloud-client/snippets.py b/spanner/cloud-client/snippets.py index 998cabf0824..9056d6968f2 100644 --- a/spanner/cloud-client/snippets.py +++ b/spanner/cloud-client/snippets.py @@ -598,6 +598,7 @@ def query_data_with_timestamp(instance_id, database_id): print(u'SingerId: {}, AlbumId: {}, AlbumTitle: {}'.format(*row)) # [END spanner_query_data_with_timestamp_column] + # [START spanner_write_data_for_struct_queries] def write_struct_data(instance_id, database_id): """Inserts sample data that can be used to test STRUCT parameters in queries. @@ -619,6 +620,7 @@ def write_struct_data(instance_id, database_id): print 'Inserted sample data for STRUCT queries' # [END spanner_write_data_for_struct_queries] + def query_with_struct(instance_id, database_id): """ Query a table using STRUCT parameters. @@ -648,6 +650,7 @@ def query_with_struct(instance_id, database_id): print(u'SingerId: {}'.format(*row)) # [END spanner_query_data_with_struct] + def query_with_array_of_struct(instance_id, database_id): """ Query a table using an array of STRUCT parameters. @@ -804,7 +807,8 @@ def query_nested_struct_field(instance_id, database_id): subparsers.add_parser('query_with_struct', help=query_with_struct.__doc__) subparsers.add_parser( 'query_with_array_of_struct', help=query_with_array_of_struct.__doc__) - subparsers.add_parser('query_struct_field', help=query_struct_field.__doc__) + subparsers.add_parser( + 'query_struct_field', help=query_struct_field.__doc__) subparsers.add_parser( 'query_nested_struct_field', help=query_nested_struct_field.__doc__) diff --git a/spanner/cloud-client/snippets_test.py b/spanner/cloud-client/snippets_test.py index a0c8405a962..d82af92c71c 100644 --- a/spanner/cloud-client/snippets_test.py +++ b/spanner/cloud-client/snippets_test.py @@ -235,6 +235,7 @@ def _(): assert 'Go, Go, Go' in out + @pytest.mark.slow def test_query_data_with_struct(temporary_database, capsys): @eventually_consistent.call @@ -249,6 +250,7 @@ def _(): assert 'SingerId: 6' in out + @pytest.mark.slow def test_query_data_with_array_struct(temporary_database, capsys): @eventually_consistent.call @@ -263,6 +265,7 @@ def _(): assert 'SingerId: 6\nSingerId: 7' in out + @pytest.mark.slow def test_query_data_with_field_struct(temporary_database, capsys): @eventually_consistent.call @@ -277,6 +280,7 @@ def _(): assert 'SingerId: 6' in out + @pytest.mark.slow def test_query_data_with_nested_field_struct(temporary_database, capsys): @eventually_consistent.call @@ -289,4 +293,6 @@ def _(): temporary_database.database_id) out, _ = capsys.readouterr() - assert 'SingerId: 6 SongName: Imagination\nSingerId: 9 SongName: Imagination' in out + assert 'SingerId: 6 SongName: Imagination' in out + assert 'SingerId: 9 SongName: Imagination' in out + From 9443b05c42e322c08c4b149e3c11338bc5ed0ba2 Mon Sep 17 00:00:00 2001 From: Jisha Abubaker Date: Mon, 11 Jun 2018 21:36:41 -0700 Subject: [PATCH 3/6] lint fixes --- spanner/cloud-client/snippets_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/spanner/cloud-client/snippets_test.py b/spanner/cloud-client/snippets_test.py index d82af92c71c..01c3b1da84d 100644 --- a/spanner/cloud-client/snippets_test.py +++ b/spanner/cloud-client/snippets_test.py @@ -295,4 +295,3 @@ def _(): assert 'SingerId: 6 SongName: Imagination' in out assert 'SingerId: 9 SongName: Imagination' in out - From e1c1ee4f8384e01af1ce9749c00f5de8212c4895 Mon Sep 17 00:00:00 2001 From: Jisha Abubaker Date: Mon, 11 Jun 2018 21:53:42 -0700 Subject: [PATCH 4/6] lint fixes --- spanner/cloud-client/snippets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/cloud-client/snippets.py b/spanner/cloud-client/snippets.py index 9056d6968f2..203ad428664 100644 --- a/spanner/cloud-client/snippets.py +++ b/spanner/cloud-client/snippets.py @@ -617,7 +617,7 @@ def write_struct_data(instance_id, database_id): (8, u'Benjamin', u'Martinez'), (9, u'Hannah', u'Harris')]) - print 'Inserted sample data for STRUCT queries' + print('Inserted sample data for STRUCT queries') # [END spanner_write_data_for_struct_queries] From c5260ee4e1c06d3a7584bb4dadd030cfd15c1cbe Mon Sep 17 00:00:00 2001 From: Jisha Abubaker Date: Wed, 13 Jun 2018 08:21:30 -0700 Subject: [PATCH 5/6] fixing formatting issues --- spanner/cloud-client/snippets.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spanner/cloud-client/snippets.py b/spanner/cloud-client/snippets.py index 203ad428664..5f3e473b188 100644 --- a/spanner/cloud-client/snippets.py +++ b/spanner/cloud-client/snippets.py @@ -647,7 +647,7 @@ def query_with_struct(instance_id, database_id): param_types={'name': record_type}) for row in results: - print(u'SingerId: {}'.format(*row)) + print(u'SingerId: {}'.format(*row)) # [END spanner_query_data_with_struct] @@ -658,8 +658,7 @@ def query_with_array_of_struct(instance_id, database_id): # [START spanner_create_user_defined_struct] name_type = param_types.Struct([ param_types.StructField('FirstName', param_types.STRING), - param_types.StructField('LastName', param_types.STRING) - ]) + param_types.StructField('LastName', param_types.STRING)]) # [END spanner_create_user_defined_struct] # [START spanner_create_array_of_struct_with_data] From 3b943511e29af9ac8995680f00c4ae0ec75f36dc Mon Sep 17 00:00:00 2001 From: Jisha Abubaker Date: Wed, 13 Jun 2018 08:33:07 -0700 Subject: [PATCH 6/6] doc string formats --- spanner/cloud-client/snippets.py | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/spanner/cloud-client/snippets.py b/spanner/cloud-client/snippets.py index 5f3e473b188..eec778985de 100644 --- a/spanner/cloud-client/snippets.py +++ b/spanner/cloud-client/snippets.py @@ -515,8 +515,7 @@ 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. + """ Adds a new TIMESTAMP column to the Albums table in the example database. """ spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) @@ -601,7 +600,8 @@ def query_data_with_timestamp(instance_id, database_id): # [START spanner_write_data_for_struct_queries] def write_struct_data(instance_id, database_id): - """Inserts sample data that can be used to test STRUCT parameters in queries. + """Inserts sample data that can be used to test STRUCT parameters + in queries. """ spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) @@ -622,9 +622,7 @@ def write_struct_data(instance_id, database_id): def query_with_struct(instance_id, database_id): - """ - Query a table using STRUCT parameters. - """ + """Query a table using STRUCT parameters. """ # [START spanner_create_struct_with_data] record_type = param_types.Struct([ param_types.StructField('FirstName', param_types.STRING), @@ -652,9 +650,7 @@ def query_with_struct(instance_id, database_id): def query_with_array_of_struct(instance_id, database_id): - """ - Query a table using an array of STRUCT parameters. - """ + """Query a table using an array of STRUCT parameters. """ # [START spanner_create_user_defined_struct] name_type = param_types.Struct([ param_types.StructField('FirstName', param_types.STRING), @@ -687,9 +683,7 @@ def query_with_array_of_struct(instance_id, database_id): # [START spanner_field_access_on_struct_parameters] def query_struct_field(instance_id, database_id): - """ - Query a table using field access on a STRUCT parameter. - """ + """Query a table using field access on a STRUCT parameter. """ spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) @@ -713,9 +707,7 @@ def query_struct_field(instance_id, database_id): # [START spanner_field_access_on_nested_struct_parameters] def query_nested_struct_field(instance_id, database_id): - """ - Query a table using nested field access on a STRUCT parameter. - """ + """Query a table using nested field access on a STRUCT parameter. """ spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id)