|
36 | 36 | import com.google.cloud.spanner.testing.EmulatorSpannerHelper;
|
37 | 37 | import com.google.common.base.Strings;
|
38 | 38 | import com.google.common.io.BaseEncoding;
|
| 39 | +import com.google.common.io.CharStreams; |
39 | 40 | import java.io.IOException;
|
40 | 41 | import java.io.InputStream;
|
41 | 42 | import java.io.StringReader;
|
@@ -263,6 +264,24 @@ private void setPreparedStatement(Connection connection, PreparedStatement ps, D
|
263 | 264 | ps.setArray(6, connection.createArrayOf("INT64", this.ticketPrices));
|
264 | 265 | }
|
265 | 266 | }
|
| 267 | + |
| 268 | + private void assertEqualsFields(Connection connection, ResultSet rs, Dialect dialect) |
| 269 | + throws SQLException { |
| 270 | + assertEquals(rs.getLong(1), this.venueId); |
| 271 | + assertEquals(rs.getLong(2), this.singerId); |
| 272 | + if (dialect == Dialect.POSTGRESQL) { |
| 273 | + assertEquals(rs.getString(3), this.concertDate.toString()); |
| 274 | + assertEquals(rs.getString(4), this.beginTime.toString()); |
| 275 | + assertEquals(rs.getString(5), this.endTime.toString()); |
| 276 | + } else { |
| 277 | + assertEquals(rs.getDate(3), this.concertDate); |
| 278 | + assertEquals(rs.getTimestamp(4), this.beginTime); |
| 279 | + assertEquals(rs.getTimestamp(5), this.endTime); |
| 280 | + assertArrayEquals( |
| 281 | + (Object[]) rs.getArray(6).getArray(), |
| 282 | + (Object[]) connection.createArrayOf("INT64", this.ticketPrices).getArray()); |
| 283 | + } |
| 284 | + } |
266 | 285 | }
|
267 | 286 |
|
268 | 287 | private static Date parseDate(String value) {
|
@@ -333,6 +352,34 @@ private String getConcertsInsertQuery(Dialect dialect) {
|
333 | 352 | return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?);";
|
334 | 353 | }
|
335 | 354 |
|
| 355 | + private String getConcertsInsertReturningQuery(Dialect dialect) { |
| 356 | + if (dialect == Dialect.POSTGRESQL) { |
| 357 | + return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime) VALUES (?,?,?,?,?) RETURNING *;"; |
| 358 | + } |
| 359 | + return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?) THEN RETURN *;"; |
| 360 | + } |
| 361 | + |
| 362 | + private String getSingersInsertReturningQuery(Dialect dialect) { |
| 363 | + if (dialect == Dialect.POSTGRESQL) { |
| 364 | + return "INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) values (?,?,?,?,?) RETURNING *"; |
| 365 | + } |
| 366 | + return "INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) values (?,?,?,?,?) THEN RETURN *"; |
| 367 | + } |
| 368 | + |
| 369 | + private String getAlbumsInsertReturningQuery(Dialect dialect) { |
| 370 | + if (dialect == Dialect.POSTGRESQL) { |
| 371 | + return "INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (?,?,?,?) RETURNING *"; |
| 372 | + } |
| 373 | + return "INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (?,?,?,?) THEN RETURN *"; |
| 374 | + } |
| 375 | + |
| 376 | + private String getSongsInsertReturningQuery(Dialect dialect) { |
| 377 | + if (dialect == Dialect.POSTGRESQL) { |
| 378 | + return "INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (?,?,?,?,?,?) RETURNING *;"; |
| 379 | + } |
| 380 | + return "INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (?,?,?,?,?,?) THEN RETURN *;"; |
| 381 | + } |
| 382 | + |
336 | 383 | private int getConcertExpectedParamCount(Dialect dialect) {
|
337 | 384 | if (dialect == Dialect.POSTGRESQL) {
|
338 | 385 | return 5;
|
@@ -1150,6 +1197,103 @@ private void assertDefaultParameterMetaData(ParameterMetaData pmd, int expectedP
|
1150 | 1197 | }
|
1151 | 1198 | }
|
1152 | 1199 |
|
| 1200 | + @Test |
| 1201 | + public void test12_InsertReturningTestData() throws SQLException { |
| 1202 | + assumeFalse( |
| 1203 | + "Emulator does not support DML with returning clause", |
| 1204 | + EmulatorSpannerHelper.isUsingEmulator()); |
| 1205 | + try (Connection connection = createConnection(env, database)) { |
| 1206 | + connection.setAutoCommit(false); |
| 1207 | + // Delete existing rows from tables populated by other tests, |
| 1208 | + // so that this test can populate rows from scratch. |
| 1209 | + Statement deleteStatements = connection.createStatement(); |
| 1210 | + deleteStatements.addBatch("DELETE FROM Concerts WHERE TRUE"); |
| 1211 | + deleteStatements.addBatch("DELETE FROM Songs WHERE TRUE"); |
| 1212 | + deleteStatements.addBatch("DELETE FROM Albums WHERE TRUE"); |
| 1213 | + deleteStatements.addBatch("DELETE FROM Singers WHERE TRUE"); |
| 1214 | + deleteStatements.executeBatch(); |
| 1215 | + try (PreparedStatement ps = |
| 1216 | + connection.prepareStatement(getSingersInsertReturningQuery(dialect.dialect))) { |
| 1217 | + assertDefaultParameterMetaData(ps.getParameterMetaData(), 5); |
| 1218 | + for (Singer singer : createSingers()) { |
| 1219 | + singer.setPreparedStatement(ps, getDialect()); |
| 1220 | + assertInsertSingerParameterMetadata(ps.getParameterMetaData()); |
| 1221 | + ps.addBatch(); |
| 1222 | + // check that adding the current params to a batch will not reset the metadata |
| 1223 | + assertInsertSingerParameterMetadata(ps.getParameterMetaData()); |
| 1224 | + } |
| 1225 | + int[] results = ps.executeBatch(); |
| 1226 | + for (int res : results) { |
| 1227 | + assertEquals(1, res); |
| 1228 | + } |
| 1229 | + } |
| 1230 | + try (PreparedStatement ps = |
| 1231 | + connection.prepareStatement(getAlbumsInsertReturningQuery(dialect.dialect))) { |
| 1232 | + assertDefaultParameterMetaData(ps.getParameterMetaData(), 4); |
| 1233 | + for (Album album : createAlbums()) { |
| 1234 | + ps.setLong(1, album.singerId); |
| 1235 | + ps.setLong(2, album.albumId); |
| 1236 | + ps.setString(3, album.albumTitle); |
| 1237 | + ps.setLong(4, album.marketingBudget); |
| 1238 | + assertInsertAlbumParameterMetadata(ps.getParameterMetaData()); |
| 1239 | + try (ResultSet rs = ps.executeQuery()) { |
| 1240 | + rs.next(); |
| 1241 | + assertEquals(rs.getLong(1), album.singerId); |
| 1242 | + assertEquals(rs.getLong(2), album.albumId); |
| 1243 | + assertEquals(rs.getString(3), album.albumTitle); |
| 1244 | + assertEquals(rs.getLong(4), album.marketingBudget); |
| 1245 | + } |
| 1246 | + // check that calling executeQuery will not reset the metadata |
| 1247 | + assertInsertAlbumParameterMetadata(ps.getParameterMetaData()); |
| 1248 | + } |
| 1249 | + } |
| 1250 | + try (PreparedStatement ps = |
| 1251 | + connection.prepareStatement(getSongsInsertReturningQuery(dialect.dialect))) { |
| 1252 | + assertDefaultParameterMetaData(ps.getParameterMetaData(), 6); |
| 1253 | + for (Song song : createSongs()) { |
| 1254 | + ps.setByte(1, (byte) song.singerId); |
| 1255 | + ps.setInt(2, (int) song.albumId); |
| 1256 | + ps.setShort(3, (short) song.songId); |
| 1257 | + ps.setNString(4, song.songName); |
| 1258 | + ps.setLong(5, song.duration); |
| 1259 | + ps.setCharacterStream(6, new StringReader(song.songGenre)); |
| 1260 | + assertInsertSongParameterMetadata(ps.getParameterMetaData()); |
| 1261 | + try (ResultSet rs = ps.executeQuery()) { |
| 1262 | + rs.next(); |
| 1263 | + assertEquals(rs.getByte(1), (byte) song.singerId); |
| 1264 | + assertEquals(rs.getInt(2), (int) song.albumId); |
| 1265 | + assertEquals(rs.getShort(3), (short) song.songId); |
| 1266 | + assertEquals(rs.getNString(4), song.songName); |
| 1267 | + assertEquals(rs.getLong(5), song.duration); |
| 1268 | + assertEquals( |
| 1269 | + CharStreams.toString(rs.getCharacterStream(6)), |
| 1270 | + CharStreams.toString(new StringReader(song.songGenre))); |
| 1271 | + } |
| 1272 | + // check that calling executeQuery will not reset the metadata |
| 1273 | + assertInsertSongParameterMetadata(ps.getParameterMetaData()); |
| 1274 | + } |
| 1275 | + } catch (IOException e) { |
| 1276 | + // ignore exception. |
| 1277 | + } |
| 1278 | + try (PreparedStatement ps = |
| 1279 | + connection.prepareStatement(getConcertsInsertReturningQuery(dialect.dialect))) { |
| 1280 | + assertDefaultParameterMetaData( |
| 1281 | + ps.getParameterMetaData(), getConcertExpectedParamCount(dialect.dialect)); |
| 1282 | + for (Concert concert : createConcerts()) { |
| 1283 | + concert.setPreparedStatement(connection, ps, getDialect()); |
| 1284 | + assertInsertConcertParameterMetadata(ps.getParameterMetaData()); |
| 1285 | + try (ResultSet rs = ps.executeQuery()) { |
| 1286 | + rs.next(); |
| 1287 | + concert.assertEqualsFields(connection, rs, dialect.dialect); |
| 1288 | + } |
| 1289 | + // check that calling executeQuery will not reset the meta data |
| 1290 | + assertInsertConcertParameterMetadata(ps.getParameterMetaData()); |
| 1291 | + } |
| 1292 | + } |
| 1293 | + connection.commit(); |
| 1294 | + } |
| 1295 | + } |
| 1296 | + |
1153 | 1297 | private List<String> readValuesFromFile(String filename) {
|
1154 | 1298 | StringBuilder builder = new StringBuilder();
|
1155 | 1299 | try (InputStream stream = ITJdbcPreparedStatementTest.class.getResourceAsStream(filename)) {
|
|
0 commit comments