Skip to content

Commit 996239c

Browse files
authored
Merge pull request #3610 from ebean-orm/feature/configure-explain
Add support to configure EXPLAIN options for query plan capture
2 parents 792d52b + caf2772 commit 996239c

File tree

4 files changed

+39
-6
lines changed

4 files changed

+39
-6
lines changed

ebean-api/src/main/java/io/ebean/DatabaseBuilder.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,6 +2019,11 @@ default DatabaseBuilder queryPlanTTLSeconds(int queryPlanTTLSeconds) {
20192019
@Deprecated
20202020
DatabaseBuilder setQueryPlanTTLSeconds(int queryPlanTTLSeconds);
20212021

2022+
/**
2023+
* Set the EXPLAIN (with options) to use for query plan capture.
2024+
*/
2025+
DatabaseBuilder queryPlanExplain(String queryPlanExplain);
2026+
20222027
/**
20232028
* Create a new PlatformConfig based of the one held but with overridden properties by reading
20242029
* properties with the given path and prefix.
@@ -3044,6 +3049,11 @@ interface Settings extends DatabaseBuilder {
30443049
*/
30453050
int getQueryPlanTTLSeconds();
30463051

3052+
/**
3053+
* Return the EXPLAIN (with options) to use for capturing query plans.
3054+
*/
3055+
String getQueryPlanExplain();
3056+
30473057
/**
30483058
* Return mapping locations to search for xml mapping via class path search.
30493059
*/

ebean-api/src/main/java/io/ebean/config/DatabaseConfig.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
481481
* Time to live for query plans - defaults to 5 minutes.
482482
*/
483483
private int queryPlanTTLSeconds = 60 * 5;
484+
private String queryPlanExplain;
484485

485486
/**
486487
* Set to true to globally disable L2 caching (typically for performance testing).
@@ -2151,6 +2152,7 @@ protected void loadSettings(PropertiesWrapper p) {
21512152
queryPlanCapturePeriodSecs = p.getLong("queryPlan.capturePeriodSecs", queryPlanCapturePeriodSecs);
21522153
queryPlanCaptureMaxTimeMillis = p.getLong("queryPlan.captureMaxTimeMillis", queryPlanCaptureMaxTimeMillis);
21532154
queryPlanCaptureMaxCount = p.getInt("queryPlan.captureMaxCount", queryPlanCaptureMaxCount);
2155+
queryPlanExplain = p.get("queryPlan.explain", queryPlanExplain);
21542156
docStoreOnly = p.getBoolean("docStoreOnly", docStoreOnly);
21552157
disableL2Cache = p.getBoolean("disableL2Cache", disableL2Cache);
21562158
localOnlyL2Cache = p.getBoolean("localOnlyL2Cache", localOnlyL2Cache);
@@ -2402,6 +2404,17 @@ public int getQueryPlanTTLSeconds() {
24022404
return queryPlanTTLSeconds;
24032405
}
24042406

2407+
@Override
2408+
public String getQueryPlanExplain() {
2409+
return queryPlanExplain;
2410+
}
2411+
2412+
@Override
2413+
public DatabaseBuilder queryPlanExplain(String queryPlanExplain) {
2414+
this.queryPlanExplain = queryPlanExplain;
2415+
return this;
2416+
}
2417+
24052418
@Override
24062419
public DatabaseConfig setQueryPlanTTLSeconds(int queryPlanTTLSeconds) {
24072420
this.queryPlanTTLSeconds = queryPlanTTLSeconds;

ebean-api/src/test/java/io/ebean/config/DatabaseConfigTest.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ void testLoadWithProperties() {
8484
props.setProperty("queryPlan.capturePeriodSecs", "42");
8585
props.setProperty("queryPlan.captureMaxTimeMillis", "560");
8686
props.setProperty("queryPlan.captureMaxCount", "7");
87+
props.setProperty("queryPlan.explain", "explain (verbose)");
8788

8889
config.loadFromProperties(props);
8990

@@ -129,15 +130,18 @@ void testLoadWithProperties() {
129130
assertEquals(42, settings.getQueryPlanCapturePeriodSecs());
130131
assertEquals(560, settings.getQueryPlanCaptureMaxTimeMillis());
131132
assertEquals(7, settings.getQueryPlanCaptureMaxCount());
133+
assertEquals("explain (verbose)", settings.getQueryPlanExplain());
132134

133135
assertThat(settings.getMappingLocations()).containsExactly("classpath:/foo","bar");
134136

135137
config.persistBatch(PersistBatch.NONE)
136138
.persistBatchOnCascade(PersistBatch.NONE)
137139
.lengthCheck(LengthCheck.ON)
138-
.lengthCheck(LengthCheck.UTF8);
140+
.lengthCheck(LengthCheck.UTF8)
141+
.queryPlanExplain("explain (buffers)");
139142

140143

144+
assertThat(config.settings().getQueryPlanExplain()).isEqualTo("explain (buffers)");
141145
Properties props1 = new Properties();
142146
props1.setProperty("ebean.persistBatch", "ALL");
143147
props1.setProperty("ebean.persistBatchOnCascade", "ALL");
@@ -182,6 +186,7 @@ void test_defaults() {
182186
assertEquals(600, config.getQueryPlanCapturePeriodSecs());
183187
assertEquals(10000L, config.getQueryPlanCaptureMaxTimeMillis());
184188
assertEquals(10, config.getQueryPlanCaptureMaxCount());
189+
assertThat(config.getQueryPlanExplain()).isNull();
185190
assertThat(config.getLengthCheck()).isEqualTo(LengthCheck.OFF);
186191
assertTrue(config.isIncludeLabelInSql());
187192

ebean-core/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -585,27 +585,32 @@ public QueryPlanManager initQueryPlanManager(TransactionManager transactionManag
585585
return QueryPlanManager.NOOP;
586586
}
587587
long threshold = config.getQueryPlanThresholdMicros();
588-
return new CQueryPlanManager(transactionManager, threshold, queryPlanLogger(databasePlatform.platform()), extraMetrics);
588+
return new CQueryPlanManager(transactionManager, threshold, queryPlanLogger(databasePlatform.platform(), config), extraMetrics);
589589
}
590590

591591
/**
592592
* Returns the logger to log query plans for the given platform.
593593
*/
594-
QueryPlanLogger queryPlanLogger(Platform platform) {
594+
QueryPlanLogger queryPlanLogger(Platform platform, DatabaseBuilder.Settings config) {
595595
switch (platform.base()) {
596596
case SQLSERVER:
597597
return new QueryPlanLoggerSqlServer();
598598
case ORACLE:
599599
return new QueryPlanLoggerOracle();
600600
case POSTGRES:
601-
return new QueryPlanLoggerExplain("explain (analyze, buffers) ");
601+
return new QueryPlanLoggerExplain(explain(config, "explain (analyze, costs, verbose, buffers) "));
602602
case YUGABYTE:
603-
return new QueryPlanLoggerExplain("explain (analyze, buffers, dist) ");
603+
return new QueryPlanLoggerExplain(explain(config,"explain (analyze, buffers, dist) "));
604604
default:
605-
return new QueryPlanLoggerExplain("explain ");
605+
return new QueryPlanLoggerExplain(explain(config,"explain "));
606606
}
607607
}
608608

609+
private static String explain(DatabaseBuilder.Settings config, String defaultExplain) {
610+
String explain = config.getQueryPlanExplain();
611+
return explain == null ? defaultExplain : explain + ' ';
612+
}
613+
609614
/**
610615
* Return the DDL generator.
611616
*/

0 commit comments

Comments
 (0)