From efe4bc5e5755f7564a3a1cd35706cece6890ecb1 Mon Sep 17 00:00:00 2001 From: yaojiejia Date: Sat, 24 May 2025 17:07:32 -0400 Subject: [PATCH 1/5] Add support for Explain Analyze for Postgres v13 --- src/sqlancer/postgres/gen/PostgresExplainGenerator.java | 2 +- src/sqlancer/postgres/gen/PostgresSetGenerator.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sqlancer/postgres/gen/PostgresExplainGenerator.java b/src/sqlancer/postgres/gen/PostgresExplainGenerator.java index d3039394b..6f965db06 100644 --- a/src/sqlancer/postgres/gen/PostgresExplainGenerator.java +++ b/src/sqlancer/postgres/gen/PostgresExplainGenerator.java @@ -8,7 +8,7 @@ private PostgresExplainGenerator() { public static String explain(String selectStr) throws Exception { StringBuilder sb = new StringBuilder(); - sb.append("EXPLAIN (FORMAT JSON) "); + sb.append("EXPLAIN (ANALYZE, FORMAT JSON) "); sb.append(selectStr); return sb.toString(); } diff --git a/src/sqlancer/postgres/gen/PostgresSetGenerator.java b/src/sqlancer/postgres/gen/PostgresSetGenerator.java index 440172c4b..38318b26b 100644 --- a/src/sqlancer/postgres/gen/PostgresSetGenerator.java +++ b/src/sqlancer/postgres/gen/PostgresSetGenerator.java @@ -112,7 +112,7 @@ private enum ConfigurationOption { JIT("jit", (r) -> Randomly.fromOptions(1, 0)), JOIN_COLLAPSE_LIMIT("join_collapse_limit", (r) -> r.getInteger(1, Integer.MAX_VALUE)), PARALLEL_LEADER_PARTICIPATION("parallel_leader_participation", (r) -> Randomly.fromOptions(1, 0)), - FORCE_PARALLEL_MODE("force_parallel_mode", (r) -> Randomly.fromOptions("off", "on", "regress")), + // FORCE_PARALLEL_MODE("force_parallel_mode", (r) -> Randomly.fromOptions("off", "on", "regress")), PLAN_CACHE_MODE("plan_cache_mode", (r) -> Randomly.fromOptions("auto", "force_generic_plan", "force_custom_plan")); From 8860d9291837a34226287e8cfadcd9582b62f98b Mon Sep 17 00:00:00 2001 From: yaojiejia Date: Mon, 23 Jun 2025 21:28:14 -0400 Subject: [PATCH 2/5] Add seperate method for EXPLAIN --- src/sqlancer/postgres/PostgresProvider.java | 4 ++ .../gen/PostgresExplainGenerator.java | 58 ++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/sqlancer/postgres/PostgresProvider.java b/src/sqlancer/postgres/PostgresProvider.java index 2b2cb8585..4ddb2d1c7 100644 --- a/src/sqlancer/postgres/PostgresProvider.java +++ b/src/sqlancer/postgres/PostgresProvider.java @@ -125,6 +125,7 @@ public enum Action implements AbstractAction { LISTEN((g) -> PostgresNotifyGenerator.createListen()), // UNLISTEN((g) -> PostgresNotifyGenerator.createUnlisten()), // CREATE_SEQUENCE(PostgresSequenceGenerator::createSequence), // + EXPLAIN(PostgresExplainGenerator::create), // CREATE_VIEW(PostgresViewGenerator::create); private final SQLQueryProvider sqlQueryProvider; @@ -192,6 +193,9 @@ protected static int mapActions(PostgresGlobalState globalState, Action a) { case INSERT: nrPerformed = r.getInteger(0, globalState.getOptions().getMaxNumberInserts()); break; + case EXPLAIN: + nrPerformed = r.getInteger(0, 1); + break; default: throw new AssertionError(a); } diff --git a/src/sqlancer/postgres/gen/PostgresExplainGenerator.java b/src/sqlancer/postgres/gen/PostgresExplainGenerator.java index 6f965db06..e60f62198 100644 --- a/src/sqlancer/postgres/gen/PostgresExplainGenerator.java +++ b/src/sqlancer/postgres/gen/PostgresExplainGenerator.java @@ -1,5 +1,14 @@ package sqlancer.postgres.gen; +import sqlancer.Randomly; +import sqlancer.common.query.SQLQueryAdapter; +import sqlancer.postgres.PostgresGlobalState; +import sqlancer.postgres.PostgresSchema; +import sqlancer.postgres.ast.PostgresSelect; +import sqlancer.postgres.PostgresSchema.PostgresDataType; +import sqlancer.postgres.PostgresSchema.PostgresTables; +import java.util.Arrays; + public final class PostgresExplainGenerator { private PostgresExplainGenerator() { @@ -8,9 +17,56 @@ private PostgresExplainGenerator() { public static String explain(String selectStr) throws Exception { StringBuilder sb = new StringBuilder(); - sb.append("EXPLAIN (ANALYZE, FORMAT JSON) "); + sb.append("EXPLAIN (FORMAT JSON) "); sb.append(selectStr); return sb.toString(); } + + public static String explainGeneral(String selectStr) throws Exception { + StringBuilder sb = new StringBuilder(); + sb.append("EXPLAIN "); + + // Add various EXPLAIN options randomly + if (Randomly.getBoolean()) { + sb.append("(ANALYZE) "); + } + if (Randomly.getBoolean()) { + sb.append("(FORMAT "); + sb.append(Randomly.fromOptions("TEXT", "XML", "JSON", "YAML")); + sb.append(") "); + } + if (Randomly.getBoolean()) { + sb.append("(VERBOSE) "); + } + if (Randomly.getBoolean()) { + sb.append("(COSTS) "); + } + if (Randomly.getBoolean()) { + sb.append("(BUFFERS) "); + } + if (Randomly.getBoolean()) { + sb.append("(TIMING) "); + } + if (Randomly.getBoolean()) { + sb.append("(SUMMARY) "); + } + + sb.append(selectStr); + return sb.toString(); + } + + public static SQLQueryAdapter create(PostgresGlobalState globalState) throws Exception { + PostgresSchema.PostgresTable table = globalState.getSchema().getRandomTable(t -> !t.isView()); + PostgresExpressionGenerator gen = new PostgresExpressionGenerator(globalState); + gen.setTablesAndColumns(new PostgresTables(Arrays.asList(table))); + PostgresSelect select = gen.generateSelect(); + select.setFromList(gen.getTableRefs()); + select.setFetchColumns(gen.generateFetchColumns(false)); + if (Randomly.getBoolean()) { + select.setWhereClause(gen.generateExpression(PostgresDataType.BOOLEAN)); + } + return new SQLQueryAdapter(explainGeneral(select.asString())); + } + } From 5903b1c251a0005337c159679c02f4dc7b7e0351 Mon Sep 17 00:00:00 2001 From: yaojiejia Date: Sun, 13 Jul 2025 15:35:10 -0400 Subject: [PATCH 3/5] Add explain generator in postgresprovider --- src/sqlancer/postgres/gen/PostgresAlterTableGenerator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sqlancer/postgres/gen/PostgresAlterTableGenerator.java b/src/sqlancer/postgres/gen/PostgresAlterTableGenerator.java index f12927e90..c8ce1b475 100644 --- a/src/sqlancer/postgres/gen/PostgresAlterTableGenerator.java +++ b/src/sqlancer/postgres/gen/PostgresAlterTableGenerator.java @@ -298,6 +298,7 @@ public SQLQueryAdapter generate() { errors.add("contains null values"); errors.add("insufficient columns in PRIMARY KEY constraint definition"); errors.add("which is part of the partition key"); + errors.add("ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned tables"); break; case VALIDATE_CONSTRAINT: sb.append("VALIDATE CONSTRAINT asdf"); From 81f14c9ffa0514728076b5e5ccf220b4a6a36fd1 Mon Sep 17 00:00:00 2001 From: yaojiejia Date: Sun, 13 Jul 2025 15:40:29 -0400 Subject: [PATCH 4/5] Reformat the code --- .../postgres/gen/PostgresExplainGenerator.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sqlancer/postgres/gen/PostgresExplainGenerator.java b/src/sqlancer/postgres/gen/PostgresExplainGenerator.java index e60f62198..effca95b5 100644 --- a/src/sqlancer/postgres/gen/PostgresExplainGenerator.java +++ b/src/sqlancer/postgres/gen/PostgresExplainGenerator.java @@ -1,13 +1,14 @@ package sqlancer.postgres.gen; +import java.util.Arrays; + import sqlancer.Randomly; import sqlancer.common.query.SQLQueryAdapter; import sqlancer.postgres.PostgresGlobalState; import sqlancer.postgres.PostgresSchema; -import sqlancer.postgres.ast.PostgresSelect; import sqlancer.postgres.PostgresSchema.PostgresDataType; import sqlancer.postgres.PostgresSchema.PostgresTables; -import java.util.Arrays; +import sqlancer.postgres.ast.PostgresSelect; public final class PostgresExplainGenerator { @@ -22,11 +23,10 @@ public static String explain(String selectStr) throws Exception { return sb.toString(); } - public static String explainGeneral(String selectStr) throws Exception { StringBuilder sb = new StringBuilder(); sb.append("EXPLAIN "); - + // Add various EXPLAIN options randomly if (Randomly.getBoolean()) { sb.append("(ANALYZE) "); @@ -51,7 +51,7 @@ public static String explainGeneral(String selectStr) throws Exception { if (Randomly.getBoolean()) { sb.append("(SUMMARY) "); } - + sb.append(selectStr); return sb.toString(); } From c294642ec940f1b6f7804b282e5def4ba9223da2 Mon Sep 17 00:00:00 2001 From: yaojiejia Date: Sun, 24 Aug 2025 20:45:19 -0400 Subject: [PATCH 5/5] Uncommenting force parallel mode --- src/sqlancer/postgres/gen/PostgresSetGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sqlancer/postgres/gen/PostgresSetGenerator.java b/src/sqlancer/postgres/gen/PostgresSetGenerator.java index 38318b26b..440172c4b 100644 --- a/src/sqlancer/postgres/gen/PostgresSetGenerator.java +++ b/src/sqlancer/postgres/gen/PostgresSetGenerator.java @@ -112,7 +112,7 @@ private enum ConfigurationOption { JIT("jit", (r) -> Randomly.fromOptions(1, 0)), JOIN_COLLAPSE_LIMIT("join_collapse_limit", (r) -> r.getInteger(1, Integer.MAX_VALUE)), PARALLEL_LEADER_PARTICIPATION("parallel_leader_participation", (r) -> Randomly.fromOptions(1, 0)), - // FORCE_PARALLEL_MODE("force_parallel_mode", (r) -> Randomly.fromOptions("off", "on", "regress")), + FORCE_PARALLEL_MODE("force_parallel_mode", (r) -> Randomly.fromOptions("off", "on", "regress")), PLAN_CACHE_MODE("plan_cache_mode", (r) -> Randomly.fromOptions("auto", "force_generic_plan", "force_custom_plan"));