Skip to content

Commit 2a9182e

Browse files
committed
fix header and add more test
1 parent 59918ef commit 2a9182e

File tree

6 files changed

+438
-37
lines changed

6 files changed

+438
-37
lines changed

samples/generated/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2021 Google LLC All rights reserved.
1+
# Copyright 2024 Google LLC All rights reserved.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

samples/generated/noxfile.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2019 Google LLC
1+
# Copyright 2024 Google LLC
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -160,6 +160,7 @@ def blacken(session: nox.sessions.Session) -> None:
160160
# format = isort + black
161161
#
162162

163+
163164
@nox.session
164165
def format(session: nox.sessions.Session) -> None:
165166
"""
@@ -187,7 +188,9 @@ def _session_tests(
187188
session: nox.sessions.Session, post_install: Callable = None
188189
) -> None:
189190
# check for presence of tests
190-
test_list = glob.glob("**/*_test.py", recursive=True) + glob.glob("**/test_*.py", recursive=True)
191+
test_list = glob.glob("**/*_test.py", recursive=True) + glob.glob(
192+
"**/test_*.py", recursive=True
193+
)
191194
test_list.extend(glob.glob("**/tests", recursive=True))
192195

193196
if len(test_list) == 0:
@@ -209,9 +212,7 @@ def _session_tests(
209212

210213
if os.path.exists("requirements-test.txt"):
211214
if os.path.exists("constraints-test.txt"):
212-
session.install(
213-
"-r", "requirements-test.txt", "-c", "constraints-test.txt"
214-
)
215+
session.install("-r", "requirements-test.txt", "-c", "constraints-test.txt")
215216
else:
216217
session.install("-r", "requirements-test.txt")
217218
with open("requirements-test.txt") as rtfile:
@@ -224,9 +225,9 @@ def _session_tests(
224225
post_install(session)
225226

226227
if "pytest-parallel" in packages:
227-
concurrent_args.extend(['--workers', 'auto', '--tests-per-worker', 'auto'])
228+
concurrent_args.extend(["--workers", "auto", "--tests-per-worker", "auto"])
228229
elif "pytest-xdist" in packages:
229-
concurrent_args.extend(['-n', 'auto'])
230+
concurrent_args.extend(["-n", "auto"])
230231

231232
session.run(
232233
"pytest",
@@ -256,7 +257,7 @@ def py(session: nox.sessions.Session) -> None:
256257

257258

258259
def _get_repo_root() -> Optional[str]:
259-
""" Returns the root folder of the project. """
260+
"""Returns the root folder of the project."""
260261
# Get root of this repository. Assume we don't have directories nested deeper than 10 items.
261262
p = Path(os.getcwd())
262263
for i in range(10):

samples/generated/pg_snippet_test.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Copyright 2024 Google, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import uuid
16+
17+
from google.api_core import exceptions
18+
from google.cloud.spanner_admin_database_v1.types.common import DatabaseDialect
19+
import pytest
20+
from test_utils.retry import RetryErrors
21+
22+
import pg_snippets as snippets
23+
24+
CREATE_TABLE_SINGERS = """\
25+
CREATE TABLE Singers (
26+
SingerId BIGINT NOT NULL,
27+
FirstName CHARACTER VARYING(1024),
28+
LastName CHARACTER VARYING(1024),
29+
SingerInfo BYTEA,
30+
FullName CHARACTER VARYING(2048)
31+
GENERATED ALWAYS AS (FirstName || ' ' || LastName) STORED,
32+
PRIMARY KEY (SingerId)
33+
)
34+
"""
35+
36+
CREATE_TABLE_ALBUMS = """\
37+
CREATE TABLE Albums (
38+
SingerId BIGINT NOT NULL,
39+
AlbumId BIGINT NOT NULL,
40+
AlbumTitle CHARACTER VARYING(1024),
41+
PRIMARY KEY (SingerId, AlbumId)
42+
) INTERLEAVE IN PARENT Singers ON DELETE CASCADE
43+
"""
44+
45+
retry_429 = RetryErrors(exceptions.ResourceExhausted, delay=15)
46+
47+
48+
@pytest.fixture(scope="module")
49+
def sample_name():
50+
return "pg_snippets"
51+
52+
53+
@pytest.fixture(scope="module")
54+
def database_dialect():
55+
"""Spanner dialect to be used for this sample.
56+
57+
The dialect is used to initialize the dialect for the database.
58+
It can either be GoogleStandardSql or PostgreSql.
59+
"""
60+
return DatabaseDialect.POSTGRESQL
61+
62+
63+
@pytest.fixture(scope="module")
64+
def create_instance_id():
65+
"""Id for the low-cost instance."""
66+
return f"create-instance-{uuid.uuid4().hex[:10]}"
67+
68+
69+
@pytest.fixture(scope="module")
70+
def lci_instance_id():
71+
"""Id for the low-cost instance."""
72+
return f"lci-instance-{uuid.uuid4().hex[:10]}"
73+
74+
75+
@pytest.fixture(scope="module")
76+
def database_id():
77+
return f"test-db-{uuid.uuid4().hex[:10]}"
78+
79+
80+
@pytest.fixture(scope="module")
81+
def create_database_id():
82+
return f"create-db-{uuid.uuid4().hex[:10]}"
83+
84+
85+
@pytest.fixture(scope="module")
86+
def cmek_database_id():
87+
return f"cmek-db-{uuid.uuid4().hex[:10]}"
88+
89+
90+
@pytest.fixture(scope="module")
91+
def default_leader_database_id():
92+
return f"leader_db_{uuid.uuid4().hex[:10]}"
93+
94+
95+
@pytest.fixture(scope="module")
96+
def database_ddl():
97+
"""Sequence of DDL statements used to set up the database.
98+
99+
Sample testcase modules can override as needed.
100+
"""
101+
return [CREATE_TABLE_SINGERS, CREATE_TABLE_ALBUMS]
102+
103+
104+
@pytest.fixture(scope="module")
105+
def default_leader():
106+
"""Default leader for multi-region instances."""
107+
return "us-east4"
108+
109+
110+
@pytest.mark.dependency(name="create_table_with_datatypes")
111+
def test_create_table_with_datatypes(capsys, instance_id, sample_database):
112+
snippets.create_table_with_datatypes(instance_id, sample_database.database_id)
113+
out, _ = capsys.readouterr()
114+
assert "Created Venues table on database" in out
115+
116+
117+
@pytest.mark.dependency(
118+
name="insert_datatypes_data",
119+
depends=["create_table_with_datatypes"],
120+
)
121+
def test_insert_datatypes_data(capsys, instance_id, sample_database):
122+
snippets.insert_datatypes_data(instance_id, sample_database.database_id)
123+
out, _ = capsys.readouterr()
124+
assert "Inserted data." in out
125+
126+
127+
@pytest.mark.dependency(name="add_jsonb_column", depends=["insert_datatypes_data"])
128+
def test_add_jsonb_column(capsys, instance_id, sample_database):
129+
snippets.add_jsonb_column(instance_id, sample_database.database_id)
130+
out, _ = capsys.readouterr()
131+
assert "Waiting for operation to complete..." in out
132+
assert 'Altered table "Venues" on database ' in out

samples/generated/pg_snippets.py

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright 2024 Google, Inc.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
"""This application demonstrates how to do basic operations using Cloud
18+
Spanner PostgreSql dialect.
19+
20+
For more information, see the README.rst under /spanner.
21+
"""
22+
import base64
23+
import decimal
24+
25+
from google.cloud import spanner, spanner_admin_database_v1
26+
27+
OPERATION_TIMEOUT_SECONDS = 240
28+
29+
30+
def create_table_with_datatypes(instance_id, database_id):
31+
"""Creates a table with supported datatypes."""
32+
# [START spanner_postgresql_create_table_with_datatypes]
33+
# instance_id = "your-spanner-instance"
34+
# database_id = "your-spanner-db-id"
35+
spanner_client = spanner.Client()
36+
instance = spanner_client.instance(instance_id)
37+
database = instance.database(database_id)
38+
39+
request = spanner_admin_database_v1.UpdateDatabaseDdlRequest(
40+
database=database.name,
41+
statements=[
42+
"""CREATE TABLE Venues (
43+
VenueId BIGINT NOT NULL,
44+
VenueName character varying(100),
45+
VenueInfo BYTEA,
46+
Capacity BIGINT,
47+
OutdoorVenue BOOL,
48+
PopularityScore FLOAT8,
49+
Revenue NUMERIC,
50+
LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL,
51+
PRIMARY KEY (VenueId))"""
52+
],
53+
)
54+
operation = spanner_client.database_admin_api.update_database_ddl(request)
55+
56+
print("Waiting for operation to complete...")
57+
operation.result(OPERATION_TIMEOUT_SECONDS)
58+
59+
print(
60+
"Created Venues table on database {} on instance {}".format(
61+
database_id, instance_id
62+
)
63+
)
64+
# [END spanner_postgresql_create_table_with_datatypes]
65+
66+
67+
# [START spanner_postgresql_jsonb_add_column]
68+
def add_jsonb_column(instance_id, database_id):
69+
"""
70+
Alters Venues tables in the database adding a JSONB column.
71+
You can create the table by running the `create_table_with_datatypes`
72+
sample or by running this DDL statement against your database:
73+
CREATE TABLE Venues (
74+
VenueId BIGINT NOT NULL,
75+
VenueName character varying(100),
76+
VenueInfo BYTEA,
77+
Capacity BIGINT,
78+
OutdoorVenue BOOL,
79+
PopularityScore FLOAT8,
80+
Revenue NUMERIC,
81+
LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL,
82+
PRIMARY KEY (VenueId))
83+
"""
84+
# instance_id = "your-spanner-instance"
85+
# database_id = "your-spanner-db-id"
86+
87+
spanner_client = spanner.Client()
88+
instance = spanner_client.instance(instance_id)
89+
database = instance.database(database_id)
90+
91+
request = spanner_admin_database_v1.UpdateDatabaseDdlRequest(
92+
database=database.name,
93+
statements=["ALTER TABLE Venues ADD COLUMN VenueDetails JSONB"],
94+
)
95+
96+
operation = spanner_client.database_admin_api.update_database_ddl(request)
97+
98+
print("Waiting for operation to complete...")
99+
operation.result(OPERATION_TIMEOUT_SECONDS)
100+
101+
print(
102+
'Altered table "Venues" on database {} on instance {}.'.format(
103+
database_id, instance_id
104+
)
105+
)
106+
107+
108+
# [END spanner_postgresql_jsonb_add_column]
109+
110+
111+
def insert_datatypes_data(instance_id, database_id):
112+
"""Inserts data with supported datatypes into a table."""
113+
# [START spanner_postgresql_insert_datatypes_data]
114+
# instance_id = "your-spanner-instance"
115+
# database_id = "your-spanner-db-id"
116+
spanner_client = spanner.Client()
117+
instance = spanner_client.instance(instance_id)
118+
database = instance.database(database_id)
119+
120+
exampleBytes1 = base64.b64encode("Hello World 1".encode())
121+
exampleBytes2 = base64.b64encode("Hello World 2".encode())
122+
exampleBytes3 = base64.b64encode("Hello World 3".encode())
123+
with database.batch() as batch:
124+
batch.insert(
125+
table="Venues",
126+
columns=(
127+
"VenueId",
128+
"VenueName",
129+
"VenueInfo",
130+
"Capacity",
131+
"OutdoorVenue",
132+
"PopularityScore",
133+
"Revenue",
134+
"LastUpdateTime",
135+
),
136+
values=[
137+
(
138+
4,
139+
"Venue 4",
140+
exampleBytes1,
141+
1800,
142+
False,
143+
0.85543,
144+
decimal.Decimal("215100.10"),
145+
spanner.COMMIT_TIMESTAMP,
146+
),
147+
(
148+
19,
149+
"Venue 19",
150+
exampleBytes2,
151+
6300,
152+
True,
153+
0.98716,
154+
decimal.Decimal("1200100.00"),
155+
spanner.COMMIT_TIMESTAMP,
156+
),
157+
(
158+
42,
159+
"Venue 42",
160+
exampleBytes3,
161+
3000,
162+
False,
163+
0.72598,
164+
decimal.Decimal("390650.99"),
165+
spanner.COMMIT_TIMESTAMP,
166+
),
167+
],
168+
)
169+
170+
print("Inserted data.")
171+
# [END spanner_postgresql_insert_datatypes_data]

0 commit comments

Comments
 (0)