|
22 | 22 |
|
23 | 23 | import com.apple.foundationdb.record.PlanHashable;
|
24 | 24 | import com.apple.foundationdb.record.provider.foundationdb.FDBRecordStoreBase;
|
| 25 | +import com.apple.foundationdb.relational.api.Continuation; |
25 | 26 | import com.apple.foundationdb.relational.api.Options;
|
26 | 27 | import com.apple.foundationdb.relational.api.RelationalConnection;
|
27 | 28 | import com.apple.foundationdb.relational.api.RelationalDriver;
|
| 29 | +import com.apple.foundationdb.relational.api.RelationalPreparedStatement; |
28 | 30 | import com.apple.foundationdb.relational.api.RelationalResultSet;
|
29 | 31 | import com.apple.foundationdb.relational.recordlayer.query.AstNormalizer;
|
30 | 32 | import com.apple.foundationdb.relational.recordlayer.query.PlanContext;
|
31 | 33 | import com.apple.foundationdb.relational.recordlayer.query.PlanGenerator;
|
32 | 34 | import com.apple.foundationdb.relational.utils.SimpleDatabaseRule;
|
33 | 35 | import com.apple.foundationdb.relational.utils.TestSchemas;
|
34 |
| - |
35 | 36 | import org.apache.logging.log4j.Level;
|
36 | 37 | import org.assertj.core.api.Assertions;
|
37 | 38 | import org.junit.Assert;
|
38 | 39 | import org.junit.jupiter.api.Order;
|
39 | 40 | import org.junit.jupiter.api.Test;
|
40 | 41 | import org.junit.jupiter.api.extension.RegisterExtension;
|
| 42 | +import org.junit.jupiter.params.ParameterizedTest; |
| 43 | +import org.junit.jupiter.params.provider.ValueSource; |
41 | 44 |
|
42 | 45 | import java.sql.DriverManager;
|
43 | 46 | import java.sql.PreparedStatement;
|
44 | 47 | import java.sql.ResultSet;
|
| 48 | +import java.sql.SQLException; |
45 | 49 | import java.sql.Statement;
|
46 | 50 | import java.util.List;
|
47 | 51 |
|
@@ -169,6 +173,115 @@ void testRelationalConnectionOptionExplicitlyDisabled() throws Exception {
|
169 | 173 | }
|
170 | 174 | }
|
171 | 175 |
|
| 176 | + @Test |
| 177 | + void testRelationalConnectionSetLogOnThenOff() throws Exception { |
| 178 | + final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); |
| 179 | + try (RelationalConnection conn = driver.connect(database.getConnectionUri(), Options.NONE)) { |
| 180 | + conn.setSchema(database.getSchemaName()); |
| 181 | + try (Statement stmt = conn.createStatement()) { |
| 182 | + try (ResultSet rs = stmt.executeQuery("select name from restaurant")) { |
| 183 | + rs.next(); |
| 184 | + } |
| 185 | + Assertions.assertThat(logAppender.getLogEvents()).isEmpty(); |
| 186 | + } |
| 187 | + // set logging to true |
| 188 | + conn.setOption(Options.Name.LOG_QUERY, true); |
| 189 | + try (PreparedStatement ps = conn.prepareStatement("SELECT name from restaurant where rest_no = ?")) { |
| 190 | + ps.setLong(1, 0); |
| 191 | + try (ResultSet rs = ps.executeQuery()) { |
| 192 | + rs.next(); |
| 193 | + } |
| 194 | + Assertions.assertThat(logAppender.getLastLogEventMessage()).contains("query=\"SELECT 'NAME' from 'RESTAURANT' where 'REST_NO' = ?\""); |
| 195 | + Assertions.assertThat(logAppender.getLogEvents()).hasSize(1); |
| 196 | + } |
| 197 | + logAppender.getLogEvents().clear(); |
| 198 | + // ... and then explicitly to false |
| 199 | + conn.setOption(Options.Name.LOG_QUERY, false); |
| 200 | + try (Statement stmt = conn.createStatement()) { |
| 201 | + try (ResultSet rs = stmt.executeQuery("select name from restaurant")) { |
| 202 | + rs.next(); |
| 203 | + } |
| 204 | + Assertions.assertThat(logAppender.getLogEvents()).isEmpty(); |
| 205 | + } |
| 206 | + } |
| 207 | + } |
| 208 | + |
| 209 | + @Test |
| 210 | + void testRelationalConnectionSetLogIsOverriddenByQueryOption() throws Exception { |
| 211 | + final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); |
| 212 | + try (RelationalConnection conn = driver.connect(database.getConnectionUri(), Options.NONE)) { |
| 213 | + conn.setSchema(database.getSchemaName()); |
| 214 | + conn.setOption(Options.Name.LOG_QUERY, false); |
| 215 | + try (PreparedStatement ps = conn.prepareStatement("SELECT name from restaurant where rest_no = ? OPTIONS(LOG QUERY)")) { |
| 216 | + ps.setLong(1, 0); |
| 217 | + try (ResultSet rs = ps.executeQuery()) { |
| 218 | + rs.next(); |
| 219 | + } |
| 220 | + Assertions.assertThat(logAppender.getLastLogEventMessage()).contains("query=\"SELECT 'NAME' from 'RESTAURANT' where 'REST_NO' = ?\""); |
| 221 | + Assertions.assertThat(logAppender.getLogEvents()).hasSize(1); |
| 222 | + } |
| 223 | + } |
| 224 | + } |
| 225 | + |
| 226 | + @Test |
| 227 | + void testRelationalConnectionSetLogIsOverriddenByExecuteContinuationQueryOption() throws Exception { |
| 228 | + insertRows(); |
| 229 | + final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); |
| 230 | + try (RelationalConnection conn = driver.connect(database.getConnectionUri(), Options.NONE)) { |
| 231 | + Continuation continuation; |
| 232 | + conn.setSchema(database.getSchemaName()); |
| 233 | + try (RelationalPreparedStatement ps = conn.prepareStatement("SELECT name from restaurant")) { |
| 234 | + ps.setMaxRows(1); |
| 235 | + try (RelationalResultSet rs = ps.executeQuery()) { |
| 236 | + rs.next(); |
| 237 | + continuation = rs.getContinuation(); |
| 238 | + } |
| 239 | + Assertions.assertThat(logAppender.getLogEvents()).isEmpty(); |
| 240 | + } |
| 241 | + conn.setOption(Options.Name.LOG_QUERY, false); |
| 242 | + try (RelationalPreparedStatement ps = conn.prepareStatement("EXECUTE CONTINUATION ?continuation OPTIONS(LOG QUERY)")) { |
| 243 | + ps.setBytes("continuation", continuation.serialize()); |
| 244 | + try (RelationalResultSet rs = ps.executeQuery()) { |
| 245 | + rs.next(); |
| 246 | + } |
| 247 | + Assertions.assertThat(logAppender.getLogEvents()).isNotEmpty(); |
| 248 | + Assertions.assertThat(logAppender.getLastLogEventMessage()).contains("plan=\"COVERING(RECORD_TYPE_COVERING <,> -> [NAME: VALUE[0], REST_NO: KEY[0]]) | MAP (_.NAME AS NAME)\""); |
| 249 | + } |
| 250 | + } |
| 251 | + } |
| 252 | + |
| 253 | + @ParameterizedTest |
| 254 | + @ValueSource(booleans = {true, false}) |
| 255 | + void testRelationalConnectionSetLogWithExecuteContinuation(boolean setLogging) throws Exception { |
| 256 | + insertRows(); |
| 257 | + final var driver = (RelationalDriver) DriverManager.getDriver(database.getConnectionUri().toString()); |
| 258 | + try (RelationalConnection conn = driver.connect(database.getConnectionUri(), Options.NONE)) { |
| 259 | + Continuation continuation; |
| 260 | + conn.setSchema(database.getSchemaName()); |
| 261 | + try (RelationalPreparedStatement ps = conn.prepareStatement("SELECT name from restaurant")) { |
| 262 | + ps.setMaxRows(1); |
| 263 | + try (RelationalResultSet rs = ps.executeQuery()) { |
| 264 | + rs.next(); |
| 265 | + continuation = rs.getContinuation(); |
| 266 | + } |
| 267 | + Assertions.assertThat(logAppender.getLogEvents()).isEmpty(); |
| 268 | + } |
| 269 | + conn.setOption(Options.Name.LOG_QUERY, setLogging); |
| 270 | + try (RelationalPreparedStatement ps = conn.prepareStatement("EXECUTE CONTINUATION ?continuation")) { |
| 271 | + ps.setBytes("continuation", continuation.serialize()); |
| 272 | + try (RelationalResultSet rs = ps.executeQuery()) { |
| 273 | + rs.next(); |
| 274 | + } |
| 275 | + if (!setLogging) { |
| 276 | + Assertions.assertThat(logAppender.getLogEvents()).isEmpty(); |
| 277 | + } else { |
| 278 | + Assertions.assertThat(logAppender.getLogEvents()).isNotEmpty(); |
| 279 | + Assertions.assertThat(logAppender.getLastLogEventMessage()).contains("plan=\"COVERING(RECORD_TYPE_COVERING <,> -> [NAME: VALUE[0], REST_NO: KEY[0]]) | MAP (_.NAME AS NAME)\""); |
| 280 | + } |
| 281 | + } |
| 282 | + } |
| 283 | + } |
| 284 | + |
172 | 285 | @Test
|
173 | 286 | void testLogQueryBecauseLoggerIsSetToDebug() throws Exception {
|
174 | 287 | try (LogAppenderRule debugRule = LogAppenderRule.of("DebugLogAppender", PlanGenerator.class, Level.DEBUG)) {
|
@@ -272,4 +385,10 @@ void testLogDelete() throws Exception {
|
272 | 385 | statement.executeUpdate("DELETE FROM RESTAURANT WHERE rest_no = 54 OPTIONS (LOG QUERY)");
|
273 | 386 | Assertions.assertThat(logAppender.getLastLogEventMessage()).contains("query=\"DELETE FROM 'RESTAURANT' WHERE 'REST_NO' = ?\"");
|
274 | 387 | }
|
| 388 | + |
| 389 | + // insert to the table and closes the running statement. |
| 390 | + private void insertRows() throws SQLException { |
| 391 | + statement.executeUpdate("INSERT INTO RESTAURANT(REST_NO) VALUES (1), (2), (3)"); |
| 392 | + statement.close(); |
| 393 | + } |
275 | 394 | }
|
0 commit comments