|
16 | 16 |
|
17 | 17 | package com.example.spanner.jdbc;
|
18 | 18 |
|
| 19 | +import com.example.spanner.jdbc.SingerProto.Genre; |
| 20 | +import com.example.spanner.jdbc.SingerProto.SingerInfo; |
19 | 21 | import com.google.api.gax.core.NoCredentialsProvider;
|
20 | 22 | import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
|
21 | 23 | import com.google.cloud.spanner.DatabaseId;
|
|
29 | 31 | import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient;
|
30 | 32 | import com.google.cloud.spanner.admin.database.v1.DatabaseAdminSettings;
|
31 | 33 | import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection;
|
| 34 | +import com.google.cloud.spanner.jdbc.ProtoEnumType; |
| 35 | +import com.google.cloud.spanner.jdbc.ProtoMessageType; |
32 | 36 | import com.google.common.base.Strings;
|
33 | 37 | import com.google.common.collect.ImmutableList;
|
34 | 38 | import com.google.spanner.admin.database.v1.CreateDatabaseRequest;
|
35 | 39 | import com.google.spanner.admin.database.v1.DatabaseDialect;
|
36 | 40 | import com.google.spanner.admin.instance.v1.InstanceName;
|
37 | 41 | import com.google.spanner.v1.DatabaseName;
|
38 | 42 | import io.grpc.ManagedChannelBuilder;
|
| 43 | +import java.io.IOException; |
| 44 | +import java.io.InputStream; |
39 | 45 | import java.sql.Connection;
|
40 | 46 | import java.sql.DriverManager;
|
41 | 47 | import java.sql.PreparedStatement;
|
@@ -1576,6 +1582,98 @@ static void arrayOfStructAsQueryParameter(
|
1576 | 1582 | }
|
1577 | 1583 | }
|
1578 | 1584 |
|
| 1585 | + static void protoColumns( |
| 1586 | + final String project, |
| 1587 | + final String instance, |
| 1588 | + final String database, |
| 1589 | + final Properties properties) throws SQLException, IOException { |
| 1590 | + try (Connection connection = |
| 1591 | + DriverManager.getConnection( |
| 1592 | + String.format( |
| 1593 | + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", |
| 1594 | + project, instance, database), |
| 1595 | + properties)) { |
| 1596 | + // Create a PROTO BUNDLE and a table. |
| 1597 | + try (Statement statement = connection.createStatement(); |
| 1598 | + InputStream protoDescriptors = JdbcSample.class.getClassLoader() |
| 1599 | + .getResourceAsStream("com/example/spanner/jdbc/descriptors.pb")) { |
| 1600 | + if (protoDescriptors == null) { |
| 1601 | + throw new IllegalArgumentException("proto descriptors not found"); |
| 1602 | + } |
| 1603 | + |
| 1604 | + // Unwrap the CloudSpannerJdbcConnection interface to set the proto |
| 1605 | + // descriptors that should be used for the next DDL statements. |
| 1606 | + connection |
| 1607 | + .unwrap(CloudSpannerJdbcConnection.class) |
| 1608 | + .setProtoDescriptors(protoDescriptors); |
| 1609 | + // Execute the DDL statements as one batch. |
| 1610 | + // This will reduce execution time compared to executing each statement |
| 1611 | + // sequentially. |
| 1612 | + statement.addBatch("CREATE PROTO BUNDLE (\n" |
| 1613 | + + "examples.spanner.music.SingerInfo,\n" |
| 1614 | + + "examples.spanner.music.Genre,\n" |
| 1615 | + + ")"); |
| 1616 | + statement.addBatch("CREATE TABLE SingersWithProto (\n" |
| 1617 | + + " SingerId INT64 NOT NULL,\n" |
| 1618 | + + " SingerInfo examples.spanner.music.SingerInfo,\n" |
| 1619 | + + " SingerGenre examples.spanner.music.Genre,\n" |
| 1620 | + + ") PRIMARY KEY (SingerId)"); |
| 1621 | + statement.executeBatch(); |
| 1622 | + } |
| 1623 | + |
| 1624 | + // Insert a couple of rows using a prepared statement. |
| 1625 | + try (PreparedStatement statement = connection.prepareStatement( |
| 1626 | + "INSERT INTO SingersWithProto " |
| 1627 | + + "(SingerId, SingerInfo, SingerGenre) " |
| 1628 | + + "VALUES (?, ?, ?)")) { |
| 1629 | + int param = 0; |
| 1630 | + statement.setLong(++param, 1L); |
| 1631 | + statement.setObject(++param, |
| 1632 | + SingerInfo.newBuilder() |
| 1633 | + .setGenre(Genre.ROCK) |
| 1634 | + .setBirthDate("1998-07-04") |
| 1635 | + .setSingerId(1L) |
| 1636 | + .setNationality("ES") |
| 1637 | + .build(), ProtoMessageType.VENDOR_TYPE_NUMBER); |
| 1638 | + statement.setObject(++param, Genre.ROCK, |
| 1639 | + ProtoEnumType.VENDOR_TYPE_NUMBER); |
| 1640 | + statement.addBatch(); |
| 1641 | + |
| 1642 | + param = 0; |
| 1643 | + statement.setLong(++param, 2L); |
| 1644 | + statement.setObject(++param, |
| 1645 | + SingerInfo.newBuilder() |
| 1646 | + .setGenre(Genre.POP) |
| 1647 | + .setBirthDate("2001-12-03") |
| 1648 | + .setSingerId(2L) |
| 1649 | + .setNationality("FO") |
| 1650 | + .build(), ProtoMessageType.VENDOR_TYPE_NUMBER); |
| 1651 | + statement.setObject(++param, Genre.POP, |
| 1652 | + ProtoEnumType.VENDOR_TYPE_NUMBER); |
| 1653 | + statement.addBatch(); |
| 1654 | + |
| 1655 | + int[] updateCounts = statement.executeBatch(); |
| 1656 | + System.out.printf("Inserted %d singers\n", |
| 1657 | + Arrays.stream(updateCounts).sum()); |
| 1658 | + } |
| 1659 | + |
| 1660 | + // Read the inserted rows. |
| 1661 | + try (ResultSet resultSet = connection.createStatement() |
| 1662 | + .executeQuery("SELECT * FROM SingersWithProto")) { |
| 1663 | + while (resultSet.next()) { |
| 1664 | + long singerId = resultSet.getLong("SingerId"); |
| 1665 | + // Proto messages and proto enums can be retrieved with the |
| 1666 | + // ResultSet#getObject(int, Class) method. |
| 1667 | + // The Spanner JDBC driver automatically deserializes |
| 1668 | + // and converts the column to the Java class representation. |
| 1669 | + SingerInfo info = resultSet.getObject("SingerInfo", SingerInfo.class); |
| 1670 | + Genre genre = resultSet.getObject("SingerGenre", Genre.class); |
| 1671 | + System.out.printf("%d:\n%s\n%s\n", singerId, info, genre); |
| 1672 | + } |
| 1673 | + } |
| 1674 | + } |
| 1675 | + } |
| 1676 | + |
1579 | 1677 | /** The expected number of command line arguments. */
|
1580 | 1678 | private static final int NUM_EXPECTED_ARGS = 3;
|
1581 | 1679 |
|
@@ -1761,6 +1859,13 @@ static boolean runGoogleSQLSample(
|
1761 | 1859 | database.getDatabase(),
|
1762 | 1860 | createProperties());
|
1763 | 1861 | return true;
|
| 1862 | + case "protocolumns": |
| 1863 | + protoColumns( |
| 1864 | + database.getInstanceId().getProject(), |
| 1865 | + database.getInstanceId().getInstance(), |
| 1866 | + database.getDatabase(), |
| 1867 | + createProperties()); |
| 1868 | + return true; |
1764 | 1869 | default:
|
1765 | 1870 | return false;
|
1766 | 1871 | }
|
|
0 commit comments