Skip to content

Commit a024483

Browse files
docs: add samples for PostgreSQL (#1700)
* docs: add samples for PostgreSQL * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * deps: remove specific Spanner version * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix: specify column names in query Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 3c55eb3 commit a024483

9 files changed

+623
-0
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,10 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/
264264
| Get Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/GetInstanceConfigSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/GetInstanceConfigSample.java) |
265265
| List Databases Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/ListDatabasesSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/ListDatabasesSample.java) |
266266
| List Instance Configs Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigsSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/ListInstanceConfigsSample.java) |
267+
| Pg Batch Dml Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/PgBatchDmlSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/PgBatchDmlSample.java) |
268+
| Pg Case Sensitivity Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/PgCaseSensitivitySample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/PgCaseSensitivitySample.java) |
269+
| Pg Interleaved Table Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/PgInterleavedTableSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/PgInterleavedTableSample.java) |
270+
| Pg Partitioned Dml Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/PgPartitionedDmlSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/PgPartitionedDmlSample.java) |
267271
| Query Information Schema Database Options Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QueryInformationSchemaDatabaseOptionsSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/QueryInformationSchemaDatabaseOptionsSample.java) |
268272
| Query With Json Parameter Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QueryWithJsonParameterSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/QueryWithJsonParameterSample.java) |
269273
| Query With Numeric Parameter Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QueryWithNumericParameterSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/QueryWithNumericParameterSample.java) |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright 2022 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.spanner;
18+
19+
// [START spanner_postgresql_batch_dml]
20+
21+
import com.google.cloud.spanner.DatabaseClient;
22+
import com.google.cloud.spanner.DatabaseId;
23+
import com.google.cloud.spanner.Spanner;
24+
import com.google.cloud.spanner.SpannerOptions;
25+
import com.google.cloud.spanner.Statement;
26+
import java.util.Arrays;
27+
28+
class PgBatchDmlSample {
29+
30+
static void batchDml() {
31+
// TODO(developer): Replace these variables before running the sample.
32+
String projectId = "my-project";
33+
String instanceId = "my-instance";
34+
String databaseId = "my-database";
35+
36+
batchDml(projectId, instanceId, databaseId);
37+
}
38+
39+
static void batchDml(String projectId, String instanceId, String databaseId) {
40+
try (Spanner spanner =
41+
SpannerOptions.newBuilder()
42+
.setProjectId(projectId)
43+
.build()
44+
.getService()) {
45+
DatabaseClient client =
46+
spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId));
47+
48+
// Spanner PostgreSQL supports BatchDML statements. This will batch multiple DML statements
49+
// into one request, which reduces the number of round trips that is needed for multiple DML
50+
// statements.
51+
long[] updateCounts =
52+
client
53+
.readWriteTransaction()
54+
.run(
55+
transaction ->
56+
transaction.batchUpdate(
57+
Arrays.asList(
58+
Statement.newBuilder(
59+
"INSERT INTO Singers (SingerId, FirstName, LastName) "
60+
+ "VALUES ($1, $2, $3)")
61+
// Use 'p1' to bind to the parameter with index 1 etc.
62+
.bind("p1")
63+
.to(1L)
64+
.bind("p2")
65+
.to("Alice")
66+
.bind("p3")
67+
.to("Henderson")
68+
.build(),
69+
Statement.newBuilder(
70+
"INSERT INTO Singers (SingerId, FirstName, LastName) "
71+
+ "VALUES ($1, $2, $3)")
72+
// Use 'p1' to bind to the parameter with index 1 etc.
73+
.bind("p1")
74+
.to(2L)
75+
.bind("p2")
76+
.to("Bruce")
77+
.bind("p3")
78+
.to("Allison")
79+
.build())));
80+
long totalUpdateCount = Arrays.stream(updateCounts).sum();
81+
System.out.printf("Inserted %d singers\n", totalUpdateCount);
82+
}
83+
}
84+
}
85+
// [END spanner_postgresql_batch_dml]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.spanner;
18+
19+
// [START spanner_postgresql_identifier_case_sensitivity]
20+
21+
import com.google.api.gax.longrunning.OperationFuture;
22+
import com.google.cloud.spanner.DatabaseAdminClient;
23+
import com.google.cloud.spanner.DatabaseClient;
24+
import com.google.cloud.spanner.DatabaseId;
25+
import com.google.cloud.spanner.Mutation;
26+
import com.google.cloud.spanner.ResultSet;
27+
import com.google.cloud.spanner.Spanner;
28+
import com.google.cloud.spanner.SpannerExceptionFactory;
29+
import com.google.cloud.spanner.SpannerOptions;
30+
import com.google.cloud.spanner.Statement;
31+
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
32+
import java.util.Collections;
33+
import java.util.concurrent.ExecutionException;
34+
35+
public class PgCaseSensitivitySample {
36+
37+
static void pgCaseSensitivity() {
38+
// TODO(developer): Replace these variables before running the sample.
39+
final String projectId = "my-project";
40+
final String instanceId = "my-instance";
41+
final String databaseId = "my-database";
42+
pgCaseSensitivity(projectId, instanceId, databaseId);
43+
}
44+
45+
static void pgCaseSensitivity(String projectId, String instanceId, String databaseId) {
46+
try (Spanner spanner =
47+
SpannerOptions.newBuilder()
48+
.setProjectId(projectId)
49+
.build()
50+
.getService()) {
51+
final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient();
52+
53+
// Spanner PostgreSQL follows the case sensitivity rules of PostgreSQL. This means that:
54+
// 1. Identifiers that are not double-quoted are folded to lower case.
55+
// 2. Identifiers that are double-quoted retain their case and are case-sensitive.
56+
// See https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
57+
// for more information.
58+
final OperationFuture<Void, UpdateDatabaseDdlMetadata> updateOperation =
59+
databaseAdminClient.updateDatabaseDdl(
60+
instanceId,
61+
databaseId,
62+
Collections.singleton(
63+
"CREATE TABLE Singers ("
64+
// SingerId will be folded to `singerid`.
65+
+ " SingerId bigint NOT NULL PRIMARY KEY,"
66+
// FirstName and LastName are double-quoted and will therefore retain their
67+
// mixed case and are case-sensitive. This means that any statement that
68+
// references any of these columns must use double quotes.
69+
+ " \"FirstName\" varchar(1024) NOT NULL,"
70+
+ " \"LastName\" varchar(1024) NOT NULL"
71+
+ ")"),
72+
null);
73+
updateOperation.get();
74+
75+
DatabaseClient client =
76+
spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId));
77+
78+
client.write(
79+
Collections.singleton(
80+
Mutation.newInsertBuilder("Singers")
81+
.set("singerid")
82+
.to(1L)
83+
// Column names in mutations are always case-insensitive, regardless whether the
84+
// columns were double-quoted or not during creation.
85+
.set("firstname")
86+
.to("Bruce")
87+
.set("lastname")
88+
.to("Allison")
89+
.build()));
90+
91+
try (ResultSet singers =
92+
client
93+
.singleUse()
94+
.executeQuery(
95+
Statement.of("SELECT SingerId, \"FirstName\", \"LastName\" FROM Singers"))) {
96+
while (singers.next()) {
97+
System.out.printf(
98+
"SingerId: %d, FirstName: %s, LastName: %s\n",
99+
// SingerId is automatically folded to lower case. Accessing the column by its name in
100+
// a result set must therefore use all lower-case letters.
101+
singers.getLong("singerid"),
102+
// FirstName and LastName were double-quoted during creation, and retain their mixed
103+
// case when returned in a result set.
104+
singers.getString("FirstName"),
105+
singers.getString("LastName"));
106+
}
107+
}
108+
109+
// Aliases are also identifiers, and specifying an alias in double quotes will make the alias
110+
// retain its case.
111+
try (ResultSet singers =
112+
client
113+
.singleUse()
114+
.executeQuery(
115+
Statement.of(
116+
"SELECT "
117+
+ "singerid AS \"SingerId\", "
118+
+ "concat(\"FirstName\", ' '::varchar, \"LastName\") AS \"FullName\" "
119+
+ "FROM Singers"))) {
120+
while (singers.next()) {
121+
System.out.printf(
122+
"SingerId: %d, FullName: %s\n",
123+
// The aliases are double-quoted and therefore retains their mixed case.
124+
singers.getLong("SingerId"), singers.getString("FullName"));
125+
}
126+
}
127+
128+
// DML statements must also follow the PostgreSQL case rules.
129+
client
130+
.readWriteTransaction()
131+
.run(
132+
transaction ->
133+
transaction.executeUpdate(
134+
Statement.newBuilder(
135+
"INSERT INTO Singers (SingerId, \"FirstName\", \"LastName\") "
136+
+ "VALUES ($1, $2, $3)")
137+
.bind("p1")
138+
.to(2L)
139+
.bind("p2")
140+
.to("Alice")
141+
.bind("p3")
142+
.to("Bruxelles")
143+
.build()));
144+
} catch (ExecutionException e) {
145+
// If the operation failed during execution, expose the cause.
146+
throw SpannerExceptionFactory.asSpannerException(e.getCause());
147+
} catch (InterruptedException e) {
148+
// Throw when a thread is waiting, sleeping, or otherwise occupied,
149+
// and the thread is interrupted, either before or during the activity.
150+
throw SpannerExceptionFactory.propagateInterrupt(e);
151+
}
152+
}
153+
}
154+
// [END spanner_postgresql_identifier_case_sensitivity]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.spanner;
18+
19+
// [START spanner_postgresql_interleaved_table]
20+
21+
import com.google.api.gax.longrunning.OperationFuture;
22+
import com.google.cloud.spanner.DatabaseAdminClient;
23+
import com.google.cloud.spanner.Spanner;
24+
import com.google.cloud.spanner.SpannerExceptionFactory;
25+
import com.google.cloud.spanner.SpannerOptions;
26+
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
27+
import java.util.Arrays;
28+
import java.util.concurrent.ExecutionException;
29+
30+
public class PgInterleavedTableSample {
31+
32+
static void pgInterleavedTable() {
33+
// TODO(developer): Replace these variables before running the sample.
34+
final String projectId = "my-project";
35+
final String instanceId = "my-instance";
36+
final String databaseId = "my-database";
37+
pgInterleavedTable(projectId, instanceId, databaseId);
38+
}
39+
40+
static void pgInterleavedTable(String projectId, String instanceId, String databaseId) {
41+
try (Spanner spanner =
42+
SpannerOptions.newBuilder()
43+
.setProjectId(projectId)
44+
.build()
45+
.getService()) {
46+
final DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient();
47+
48+
// The Spanner PostgreSQL dialect extends the PostgreSQL dialect with certain Spanner
49+
// specific features, such as interleaved tables.
50+
// See https://cloud.google.com/spanner/docs/postgresql/data-definition-language#create_table
51+
// for the full CREATE TABLE syntax.
52+
final OperationFuture<Void, UpdateDatabaseDdlMetadata> updateOperation =
53+
databaseAdminClient.updateDatabaseDdl(
54+
instanceId,
55+
databaseId,
56+
Arrays.asList(
57+
"CREATE TABLE Singers ("
58+
+ " SingerId bigint NOT NULL PRIMARY KEY,"
59+
+ " FirstName varchar(1024) NOT NULL,"
60+
+ " LastName varchar(1024) NOT NULL"
61+
+ ")",
62+
"CREATE TABLE Albums ("
63+
+ " SingerId bigint NOT NULL,"
64+
+ " AlbumId bigint NOT NULL,"
65+
+ " Title varchar(1024) NOT NULL,"
66+
+ " PRIMARY KEY (SingerId, AlbumId)"
67+
+ ") INTERLEAVE IN PARENT Singers ON DELETE CASCADE"),
68+
null);
69+
updateOperation.get();
70+
System.out.println("Created interleaved table hierarchy using PostgreSQL dialect");
71+
} catch (ExecutionException e) {
72+
// If the operation failed during execution, expose the cause.
73+
throw SpannerExceptionFactory.asSpannerException(e.getCause());
74+
} catch (InterruptedException e) {
75+
// Throw when a thread is waiting, sleeping, or otherwise occupied,
76+
// and the thread is interrupted, either before or during the activity.
77+
throw SpannerExceptionFactory.propagateInterrupt(e);
78+
}
79+
}
80+
}
81+
// [END spanner_postgresql_interleaved_table]

0 commit comments

Comments
 (0)