Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hQmzo-0006Ib-DJ for pgsql-hackers@arkaria.postgresql.org; Wed, 15 May 2019 06:02:33 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1hQmzn-0008DG-62 for pgsql-hackers@arkaria.postgresql.org; Wed, 15 May 2019 06:02:31 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hQmzm-0008D8-Jn for pgsql-hackers@lists.postgresql.org; Wed, 15 May 2019 06:02:30 +0000 Received: from xvm-110-146.dc2.ghst.net ([46.226.110.146] helo=fetter.org) by magus.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1hQmzZ-0003KS-6s for pgsql-hackers@postgresql.org; Wed, 15 May 2019 06:02:29 +0000 Received: by fetter.org (Postfix, from userid 1001) id 4585940D4E; Wed, 15 May 2019 08:02:15 +0200 (CEST) Date: Wed, 15 May 2019 08:02:14 +0200 From: David Fetter To: Tom Lane Cc: Stephen Frost , Andres Freund , PostgreSQL Development Subject: Re: New EXPLAIN option: ALL Message-ID: <20190515060214.GZ28936@fetter.org> References: <20190507073046.GI28936@fetter.org> <20190507154147.l32a3erg4mbycj7u@alap3.anarazel.de> <20190507163411.GM28936@fetter.org> <20190507164430.a7tig676hjzdnyyd@alap3.anarazel.de> <20190507212355.GQ28936@fetter.org> <20190507215449.3a4yb5kkoloq7yyw@alap3.anarazel.de> <4638.1557266803@sss.pgh.pa.us> <20190507221255.GO6197@tamriel.snowman.net> <5221.1557267912@sss.pgh.pa.us> <20190513055112.GA24409@fetter.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Ayym4vmyMU9P4uDb" Content-Disposition: inline In-Reply-To: <20190513055112.GA24409@fetter.org> User-Agent: Mutt/1.9.4 (2018-02-28) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --Ayym4vmyMU9P4uDb Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Mon, May 13, 2019 at 07:51:12AM +0200, David Fetter wrote: > On Tue, May 07, 2019 at 06:25:12PM -0400, Tom Lane wrote: > > Stephen Frost writes: > > > I'm generally in favor of doing something like what Tom is suggesting > > > with VERBOSE, but I also feel like it should be the default for formats > > > like JSON. If you're asking for the output in JSON, then we really > > > should include everything that a flag like VERBOSE would contain because > > > you're pretty clearly planning to copy/paste that output into something > > > else to read it anyway. > > > > Meh --- I don't especially care for non-orthogonal behaviors like that. > > If you wanted JSON but *not* all of the additional info, how would you > > specify that? (The implementation I had in mind would make VERBOSE OFF > > more or less a no-op, so that wouldn't get you there.) > > > > >> I do feel that it's a good idea to keep ANALYZE separate. "Execute > > >> the query or not" is a mighty fundamental thing. I've never liked > > >> that name for the option though --- maybe we could deprecate it > > >> in favor of EXECUTE? > > > > > Let's not fool ourselves by saying we'd 'deprecate' it because that > > > implies, at least to me, that there's some intention of later on > > > removing it > > > > True, the odds of ever actually removing it are small :-(. I meant > > mostly changing all of our docs to use the other spelling, except > > for some footnote. Maybe we could call ANALYZE a "legacy spelling" > > of EXECUTE. > > I tried changing it to EXEC (EXPLAIN EXECUTE is already a thing), but > got a giant flock of reduce-reduce conflicts along with a few > shift-reduce conflicts. > > How do I fix this? Fixed it. I hope the patch is a little easier to digest as now attached. Best, David. -- David Fetter http://fetter.org/ Phone: +1 415 235 3778 Remember to vote! Consider donating to Postgres: http://www.postgresql.org/about/donate --Ayym4vmyMU9P4uDb Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v4-0001-Changed-EXPLAIN-ANALYZE-to-EXPLAIN-EXEC.patch" From 92cb3f5da4157085933ea5c6dcb6f560fad66626 Mon Sep 17 00:00:00 2001 From: David Fetter Date: Tue, 14 May 2019 22:46:44 -0700 Subject: [PATCH v4 1/8] Changed EXPLAIN ANALYZE to EXPLAIN EXEC To: hackers MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------2.21.0" This is a multi-part message in MIME format. --------------2.21.0 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit - In passing, made some of the defaults for EXPLAIN more helpful diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index a6c6de78f1..95e8f20e5d 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -147,6 +147,7 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, const char *queryString, TupOutputState *tstate; List *rewritten; ListCell *lc; + bool buffers_set = false; bool timing_set = false; bool summary_set = false; @@ -155,14 +156,17 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, const char *queryString, { DefElem *opt = (DefElem *) lfirst(lc); - if (strcmp(opt->defname, "analyze") == 0) - es->analyze = defGetBoolean(opt); + if (strcmp(opt->defname, "exec") == 0) + es->exec = defGetBoolean(opt); else if (strcmp(opt->defname, "verbose") == 0) es->verbose = defGetBoolean(opt); else if (strcmp(opt->defname, "costs") == 0) es->costs = defGetBoolean(opt); else if (strcmp(opt->defname, "buffers") == 0) + { + buffers_set = true; es->buffers = defGetBoolean(opt); + } else if (strcmp(opt->defname, "settings") == 0) es->settings = defGetBoolean(opt); else if (strcmp(opt->defname, "timing") == 0) @@ -202,22 +206,21 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, const char *queryString, parser_errposition(pstate, opt->location))); } - if (es->buffers && !es->analyze) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("EXPLAIN option BUFFERS requires ANALYZE"))); + /* Turn buffers off automatically when exec isn't set */ + if (!es->exec) + es->buffers = false; /* if the timing was not set explicitly, set default value */ - es->timing = (timing_set) ? es->timing : es->analyze; + es->timing = (timing_set) ? es->timing : es->exec; - /* check that timing is used with EXPLAIN ANALYZE */ - if (es->timing && !es->analyze) + /* check that timing is used with EXPLAIN EXEC */ + if (es->timing && !es->exec) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("EXPLAIN option TIMING requires ANALYZE"))); + errmsg("EXPLAIN option TIMING requires EXEC"))); /* if the summary was not set explicitly, set default value */ - es->summary = (summary_set) ? es->summary : es->analyze; + es->summary = (summary_set) ? es->summary : es->exec; /* * Parse analysis was done already, but we still have to run the rule @@ -286,8 +289,11 @@ NewExplainState(void) { ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState)); - /* Set default options (most fields can be left as zeroes). */ + /* Set default options (fields can be left as zeroes). */ es->costs = true; + es->buffers = true; + es->settings = true; + es->timing = true; /* Prepare output buffer. */ es->str = makeStringInfo(); @@ -415,7 +421,7 @@ ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es, /* * Likewise for DECLARE CURSOR. * - * Notice that if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll + * Notice that if you say EXPLAIN EXEC DECLARE CURSOR then we'll * actually run the query. This is different from pre-8.3 behavior * but seems more useful than not running the query. No cursor will * be created, however. @@ -475,9 +481,9 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, Assert(plannedstmt->commandType != CMD_UTILITY); - if (es->analyze && es->timing) + if (es->exec && es->timing) instrument_option |= INSTRUMENT_TIMER; - else if (es->analyze) + else if (es->exec) instrument_option |= INSTRUMENT_ROWS; if (es->buffers) @@ -512,7 +518,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, dest, params, queryEnv, instrument_option); /* Select execution options */ - if (es->analyze) + if (es->exec) eflags = 0; /* default run-to-completion flags */ else eflags = EXEC_FLAG_EXPLAIN_ONLY; @@ -523,11 +529,11 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, ExecutorStart(queryDesc, eflags); /* Execute the plan for statistics if asked for */ - if (es->analyze) + if (es->exec) { ScanDirection dir; - /* EXPLAIN ANALYZE CREATE TABLE AS WITH NO DATA is weird */ + /* EXPLAIN EXEC CREATE TABLE AS WITH NO DATA is weird */ if (into && into->skipData) dir = NoMovementScanDirection; else @@ -556,7 +562,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, } /* Print info about runtime of triggers */ - if (es->analyze) + if (es->exec) ExplainPrintTriggers(es, queryDesc); /* @@ -581,7 +587,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, PopActiveSnapshot(); /* We need a CCI just in case query expanded to multiple plans */ - if (es->analyze) + if (es->exec) CommandCounterIncrement(); totaltime += elapsed_time(&starttime); @@ -592,7 +598,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, * user can set SUMMARY OFF to not have the timing information included in * the output). By default, ANALYZE sets SUMMARY to true. */ - if (es->summary && es->analyze) + if (es->summary && es->exec) ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3, es); @@ -834,7 +840,7 @@ ExplainPrintJIT(ExplainState *es, int jit_flags, "Expressions", jit_flags & PGJIT_EXPR ? "true" : "false", "Deforming", jit_flags & PGJIT_DEFORM ? "true" : "false"); - if (es->analyze && es->timing) + if (es->exec && es->timing) { appendStringInfoSpaces(es->str, es->indent * 2); appendStringInfo(es->str, @@ -860,7 +866,7 @@ ExplainPrintJIT(ExplainState *es, int jit_flags, ExplainPropertyBool("Deforming", jit_flags & PGJIT_DEFORM, es); ExplainCloseGroup("Options", "Options", true, es); - if (es->analyze && es->timing) + if (es->exec && es->timing) { ExplainOpenGroup("Timing", "Timing", true, es); @@ -1505,7 +1511,7 @@ ExplainNode(PlanState *planstate, List *ancestors, if (planstate->instrument) InstrEndLoop(planstate->instrument); - if (es->analyze && + if (es->exec && planstate->instrument && planstate->instrument->nloops > 0) { double nloops = planstate->instrument->nloops; @@ -1537,7 +1543,7 @@ ExplainNode(PlanState *planstate, List *ancestors, ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es); } } - else if (es->analyze) + else if (es->exec) { if (es->format == EXPLAIN_FORMAT_TEXT) appendStringInfoString(es->str, " (never executed)"); @@ -1606,7 +1612,7 @@ ExplainNode(PlanState *planstate, List *ancestors, if (plan->qual) show_instrumentation_count("Rows Removed by Filter", 1, planstate, es); - if (es->analyze) + if (es->exec) ExplainPropertyFloat("Heap Fetches", NULL, planstate->instrument->ntuples2, 0, es); break; @@ -1624,7 +1630,7 @@ ExplainNode(PlanState *planstate, List *ancestors, if (plan->qual) show_instrumentation_count("Rows Removed by Filter", 1, planstate, es); - if (es->analyze) + if (es->exec) show_tidbitmap_info((BitmapHeapScanState *) planstate, es); break; case T_SampleScan: @@ -1658,7 +1664,7 @@ ExplainNode(PlanState *planstate, List *ancestors, if (gather->initParam) show_eval_params(gather->initParam, es); - if (es->analyze) + if (es->exec) { int nworkers; @@ -1704,7 +1710,7 @@ ExplainNode(PlanState *planstate, List *ancestors, if (gm->initParam) show_eval_params(gm->initParam, es); - if (es->analyze) + if (es->exec) { int nworkers; @@ -1869,7 +1875,7 @@ ExplainNode(PlanState *planstate, List *ancestors, show_buffer_usage(es, &planstate->instrument->bufusage); /* Show worker detail */ - if (es->analyze && es->verbose && planstate->worker_instrument) + if (es->exec && es->verbose && planstate->worker_instrument) { WorkerInstrumentation *w = planstate->worker_instrument; bool opened_group = false; @@ -2531,12 +2537,12 @@ show_tablesample(TableSampleClause *tsc, PlanState *planstate, } /* - * If it's EXPLAIN ANALYZE, show tuplesort stats for a sort node + * If it's EXPLAIN EXEC, show tuplesort stats for a sort node */ static void show_sort_info(SortState *sortstate, ExplainState *es) { - if (!es->analyze) + if (!es->exec) return; if (sortstate->sort_Done && sortstate->tuplesortstate != NULL) @@ -2716,7 +2722,7 @@ show_hash_info(HashState *hashstate, ExplainState *es) } /* - * If it's EXPLAIN ANALYZE, show exact/lossy pages for a BitmapHeapScan node + * If it's EXPLAIN EXEC, show exact/lossy pages for a BitmapHeapScan node */ static void show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es) @@ -2744,7 +2750,7 @@ show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es) } /* - * If it's EXPLAIN ANALYZE, show instrumentation information for a plan node + * If it's EXPLAIN EXEC, show instrumentation information for a plan node * * "which" identifies which instrumentation counter to print */ @@ -2755,7 +2761,7 @@ show_instrumentation_count(const char *qlabel, int which, double nfiltered; double nloops; - if (!es->analyze || !planstate->instrument) + if (!es->exec || !planstate->instrument) return; if (which == 2) @@ -3283,8 +3289,8 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors, show_instrumentation_count("Rows Removed by Conflict Filter", 1, &mtstate->ps, es); } - /* EXPLAIN ANALYZE display of actual outcome for each tuple proposed */ - if (es->analyze && mtstate->ps.instrument) + /* EXPLAIN EXEC display of actual outcome for each tuple proposed */ + if (es->exec && mtstate->ps.instrument) { double total; double insert_path; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 3dc0e8a4fb..3a7d33502c 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -10632,7 +10632,7 @@ opt_vacuum_relation_list: /***************************************************************************** * * QUERY: - * EXPLAIN [ANALYZE] [VERBOSE] query + * EXPLAIN [EXEC] [VERBOSE] query * EXPLAIN ( options ) query * *****************************************************************************/ @@ -10645,11 +10645,11 @@ ExplainStmt: n->options = NIL; $$ = (Node *) n; } - | EXPLAIN analyze_keyword opt_verbose ExplainableStmt + | EXPLAIN exec_keyword opt_verbose ExplainableStmt { ExplainStmt *n = makeNode(ExplainStmt); n->query = $4; - n->options = list_make1(makeDefElem("analyze", NULL, @2)); + n->options = list_make1(makeDefElem("exec", NULL, @2)); if ($3) n->options = lappend(n->options, makeDefElem("verbose", NULL, @3)); @@ -10703,7 +10703,7 @@ explain_option_elem: explain_option_name: NonReservedWord { $$ = $1; } - | analyze_keyword { $$ = "analyze"; } + | exec_keyword { $$ = "exec"; } ; explain_option_arg: @@ -10712,6 +10712,11 @@ explain_option_arg: | /* EMPTY */ { $$ = NULL; } ; +exec_keyword: + ANALYZE /* Legacy */ {} + | ANALYSE /* British and legacy */ {} + ; + /***************************************************************************** * * QUERY: diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h index db48f29501..09cc806d7e 100644 --- a/src/include/commands/explain.h +++ b/src/include/commands/explain.h @@ -30,8 +30,8 @@ typedef struct ExplainState StringInfo str; /* output buffer */ /* options */ bool verbose; /* be verbose */ - bool analyze; /* print actual times */ bool costs; /* print estimated costs */ + bool exec; /* actually execute the query, measure it */ bool buffers; /* print buffer usage */ bool timing; /* print detailed node timing */ bool summary; /* print total planning and execution timing */ --------------2.21.0-- --Ayym4vmyMU9P4uDb Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v4-0002-Documentation.patch" From d4ee9af44e6f17e1ea505db78019a0280d655546 Mon Sep 17 00:00:00 2001 From: David Fetter Date: Tue, 14 May 2019 22:50:12 -0700 Subject: [PATCH v4 2/8] Documentation To: hackers MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------2.21.0" This is a multi-part message in MIME format. --------------2.21.0 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit diff --git a/doc/src/sgml/ref/explain.sgml b/doc/src/sgml/ref/explain.sgml index 385d10411f..63a3faede8 100644 --- a/doc/src/sgml/ref/explain.sgml +++ b/doc/src/sgml/ref/explain.sgml @@ -32,11 +32,11 @@ PostgreSQL documentation EXPLAIN [ ( option [, ...] ) ] statement -EXPLAIN [ ANALYZE ] [ VERBOSE ] statement +EXPLAIN [ EXEC ] [ VERBOSE ] statement where option can be one of: - ANALYZE [ boolean ] + EXEC [ boolean ] VERBOSE [ boolean ] COSTS [ boolean ] SETTINGS [ boolean ] @@ -76,36 +76,37 @@ EXPLAIN [ ANALYZE ] [ VERBOSE ] statement - The ANALYZE option causes the statement to be actually + The EXEC option causes the statement to be actually executed, not only planned. Then actual run time statistics are added to the display, including the total elapsed time expended within each plan node (in milliseconds) and the total number of rows it actually returned. This is useful for seeing whether the planner's estimates - are close to reality. + are close to reality. For historical reasons, ANALYZE and ANALYSE can be + used instead of EXEC. Keep in mind that the statement is actually executed when - the ANALYZE option is used. Although + the EXEC option is used. Although EXPLAIN will discard any output that a SELECT would return, other side effects of the statement will happen as usual. If you wish to use - EXPLAIN ANALYZE on an + EXPLAIN EXEC on an INSERT, UPDATE, DELETE, CREATE TABLE AS, or EXECUTE statement without letting the command affect your data, use this approach: BEGIN; -EXPLAIN ANALYZE ...; +EXPLAIN EXEC ...; ROLLBACK; - Only the ANALYZE and VERBOSE options + Only the EXEC and VERBOSE options can be specified, and only in that order, without surrounding the option list in parentheses. Prior to PostgreSQL 9.0, the unparenthesized syntax was the only one supported. It is expected that @@ -118,7 +119,7 @@ ROLLBACK; - ANALYZE + EXEC Carry out the command and show actual run times and other statistics. @@ -159,7 +160,7 @@ ROLLBACK; Include information on configuration parameters. Specifically, include options affecting query planning with value different from the built-in - default value. This parameter defaults to FALSE. + default value. This parameter defaults to TRUE. @@ -186,8 +187,8 @@ ROLLBACK; The number of blocks shown for an upper-level node includes those used by all its child nodes. In text format, only non-zero values are printed. This parameter may only be - used when ANALYZE is also enabled. It defaults to - FALSE. + used when EXEC is also enabled. It defaults to + TRUE. @@ -203,7 +204,7 @@ ROLLBACK; not exact times, are needed. Run time of the entire statement is always measured, even when node-level timing is turned off with this option. - This parameter may only be used when ANALYZE is also + This parameter may only be used when EXEC is also enabled. It defaults to TRUE. @@ -215,9 +216,9 @@ ROLLBACK; Include summary information (e.g., totaled timing information) after the query plan. Summary information is included by default when - ANALYZE is used but otherwise is not included by + EXEC is used but otherwise is not included by default, but can be enabled using this option. Planning time in - EXPLAIN EXECUTE includes the time required to fetch + EXPLAIN EXEC includes the time required to fetch the plan from the cache and the time required for re-planning, if necessary. @@ -295,8 +296,8 @@ ROLLBACK; In order to measure the run-time cost of each node in the execution plan, the current implementation of EXPLAIN - ANALYZE adds profiling overhead to query execution. - As a result, running EXPLAIN ANALYZE + EXEC adds profiling overhead to query execution. + As a result, running EXPLAIN EXEC on a query can sometimes take significantly longer than executing the query normally. The amount of overhead depends on the nature of the query, as well as the platform being used. The worst case occurs @@ -423,7 +424,7 @@ PREPARE query(int, int) AS SELECT sum(bar) FROM test WHERE id > $1 AND id < $2 GROUP BY foo; -EXPLAIN ANALYZE EXECUTE query(100, 200); +EXPLAIN EXEC EXECUTE query(100, 200); QUERY PLAN ------------------------------------------------------------------------------------------------------------------------ --------------2.21.0-- --Ayym4vmyMU9P4uDb Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v4-0003-psql-support.patch" From a53669452bca9099407c034b2e86151f9233993f Mon Sep 17 00:00:00 2001 From: David Fetter Date: Tue, 14 May 2019 22:50:46 -0700 Subject: [PATCH v4 3/8] psql support To: hackers MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------2.21.0" This is a multi-part message in MIME format. --------------2.21.0 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index e4c03de221..ac0673dafc 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -2848,11 +2848,11 @@ psql_completion(const char *text, int start, int end) /* * EXPLAIN [ ( option [, ...] ) ] statement - * EXPLAIN [ ANALYZE ] [ VERBOSE ] statement + * EXPLAIN [ EXEC ] [ VERBOSE ] statement */ else if (Matches("EXPLAIN")) COMPLETE_WITH("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", - "ANALYZE", "VERBOSE"); + "EXEC", "VERBOSE"); else if (HeadMatches("EXPLAIN", "(*") && !HeadMatches("EXPLAIN", "(*)")) { @@ -2862,19 +2862,23 @@ psql_completion(const char *text, int start, int end) * one word, so the above test is correct. */ if (ends_with(prev_wd, '(') || ends_with(prev_wd, ',')) - COMPLETE_WITH("ANALYZE", "VERBOSE", "COSTS", "BUFFERS", + COMPLETE_WITH("EXEC", "VERBOSE", "COSTS", "BUFFERS", "TIMING", "SUMMARY", "FORMAT"); - else if (TailMatches("ANALYZE|VERBOSE|COSTS|BUFFERS|TIMING|SUMMARY")) + else if (TailMatches("EXEC|VERBOSE|COSTS|BUFFERS|TIMING|SUMMARY")) COMPLETE_WITH("ON", "OFF"); else if (TailMatches("FORMAT")) COMPLETE_WITH("TEXT", "XML", "JSON", "YAML"); } - else if (Matches("EXPLAIN", "ANALYZE")) + else if (Matches("EXPLAIN", "EXEC") || + Matches("EXPLAIN", "ANALYZE") || + Matches("EXPLAIN", "ANALYSE")) COMPLETE_WITH("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", "VERBOSE"); else if (Matches("EXPLAIN", "(*)") || Matches("EXPLAIN", "VERBOSE") || - Matches("EXPLAIN", "ANALYZE", "VERBOSE")) + Matches("EXPLAIN", "EXEC", "VERBOSE") || + Matches("EXPLAIN", "ANALYZE", "VERBOSE") || + Matches("EXPLAIN", "ANALYSE", "VERBOSE")) COMPLETE_WITH("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE"); /* FETCH && MOVE */ --------------2.21.0-- --Ayym4vmyMU9P4uDb Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v4-0004-Changed-examples-in-the-documentation-to-use-EXEC.patch" From e9b4f35e0512129582b157ff5c94833519de120a Mon Sep 17 00:00:00 2001 From: David Fetter Date: Tue, 14 May 2019 22:51:24 -0700 Subject: [PATCH v4 4/8] Changed examples in the documentation to use EXEC To: hackers MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------2.21.0" This is a multi-part message in MIME format. --------------2.21.0 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit diff --git a/doc/src/sgml/auto-explain.sgml b/doc/src/sgml/auto-explain.sgml index 3d619d4a3d..3025a57232 100644 --- a/doc/src/sgml/auto-explain.sgml +++ b/doc/src/sgml/auto-explain.sgml @@ -65,14 +65,14 @@ LOAD 'auto_explain'; - auto_explain.log_analyze (boolean) + auto_explain.log_exec (boolean) - auto_explain.log_analyze configuration parameter + auto_explain.log_exec configuration parameter - auto_explain.log_analyze causes EXPLAIN ANALYZE + auto_explain.log_exec causes EXPLAIN EXEC output, rather than just EXPLAIN output, to be printed when an execution plan is logged. This parameter is off by default. Only superusers can change this setting. @@ -102,7 +102,7 @@ LOAD 'auto_explain'; usage statistics are printed when an execution plan is logged; it's equivalent to the BUFFERS option of EXPLAIN. This parameter has no effect - unless auto_explain.log_analyze is enabled. + unless auto_explain.log_exec is enabled. This parameter is off by default. Only superusers can change this setting. @@ -126,7 +126,7 @@ LOAD 'auto_explain'; parameter to off when only actual row counts, and not exact times, are needed. This parameter has no effect - unless auto_explain.log_analyze is enabled. + unless auto_explain.log_exec is enabled. This parameter is on by default. Only superusers can change this setting. @@ -145,7 +145,7 @@ LOAD 'auto_explain'; auto_explain.log_triggers causes trigger execution statistics to be included when an execution plan is logged. This parameter has no effect - unless auto_explain.log_analyze is enabled. + unless auto_explain.log_exec is enabled. This parameter is off by default. Only superusers can change this setting. @@ -283,7 +283,7 @@ auto_explain.log_min_duration = '3s' postgres=# LOAD 'auto_explain'; postgres=# SET auto_explain.log_min_duration = 0; -postgres=# SET auto_explain.log_analyze = true; +postgres=# SET auto_explain.log_exec = true; postgres=# SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; diff --git a/doc/src/sgml/bloom.sgml b/doc/src/sgml/bloom.sgml index 6eeaddee09..5b4ede2db1 100644 --- a/doc/src/sgml/bloom.sgml +++ b/doc/src/sgml/bloom.sgml @@ -129,7 +129,7 @@ CREATE INDEX A sequential scan over this large table takes a long time: -=# EXPLAIN ANALYZE SELECT * FROM tbloom WHERE i2 = 898732 AND i5 = 123451; +=# EXPLAIN EXEC SELECT * FROM tbloom WHERE i2 = 898732 AND i5 = 123451; QUERY PLAN ------------------------------------------------------------------------------------------------------------ Seq Scan on tbloom (cost=0.00..213694.08 rows=1 width=24) (actual time=1445.438..1445.438 rows=0 loops=1) @@ -145,7 +145,7 @@ CREATE INDEX So the planner will usually select an index scan if possible. With a btree index, we get results like this: -=# EXPLAIN ANALYZE SELECT * FROM tbloom WHERE i2 = 898732 AND i5 = 123451; +=# EXPLAIN EXEC SELECT * FROM tbloom WHERE i2 = 898732 AND i5 = 123451; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------- Index Only Scan using btreeidx on tbloom (cost=0.56..298311.96 rows=1 width=24) (actual time=445.709..445.709 rows=0 loops=1) @@ -160,7 +160,7 @@ CREATE INDEX Bloom is better than btree in handling this type of search: -=# EXPLAIN ANALYZE SELECT * FROM tbloom WHERE i2 = 898732 AND i5 = 123451; +=# EXPLAIN EXEC SELECT * FROM tbloom WHERE i2 = 898732 AND i5 = 123451; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on tbloom (cost=178435.39..178439.41 rows=1 width=24) (actual time=76.698..76.698 rows=0 loops=1) @@ -187,7 +187,7 @@ CREATE INDEX A better strategy for btree is to create a separate index on each column. Then the planner will choose something like this: -=# EXPLAIN ANALYZE SELECT * FROM tbloom WHERE i2 = 898732 AND i5 = 123451; +=# EXPLAIN EXEC SELECT * FROM tbloom WHERE i2 = 898732 AND i5 = 123451; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Bitmap Heap Scan on tbloom (cost=9.29..13.30 rows=1 width=24) (actual time=0.148..0.148 rows=0 loops=1) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 84341a30e5..41e9a64182 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -6441,7 +6441,7 @@ log_line_prefix = '%m [%p] %q%u@%d/%a ' UPDATE, DELETE, TRUNCATE, and COPY FROM. PREPARE, EXECUTE, and - EXPLAIN ANALYZE statements are also logged if their + EXPLAIN EXEC statements are also logged if their contained command is of an appropriate type. For clients using extended query protocol, logging occurs when an Execute message is received, and values of the Bind parameters are included diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index a0a7435a03..407f94dfbe 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -4498,7 +4498,7 @@ EXPLAIN SELECT count(*) FROM measurement WHERE logdate >= DATE '2008-01-01'; performed here for parameter values which are known during the initialization phase of execution. Partitions which are pruned during this stage will not show up in the query's - EXPLAIN or EXPLAIN ANALYZE. + EXPLAIN or EXPLAIN EXEC. It is possible to determine the number of partitions which were removed during this phase by observing the Subplans Removed property in the @@ -4518,7 +4518,7 @@ EXPLAIN SELECT count(*) FROM measurement WHERE logdate >= DATE '2008-01-01'; execution parameters being used by partition pruning changes. Determining if partitions were pruned during this phase requires careful inspection of the loops property in - the EXPLAIN ANALYZE output. Subplans + the EXPLAIN EXEC output. Subplans corresponding to different partitions may have different values for it depending on how many times each of them was pruned during execution. Some may be shown as (never executed) diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml index 27b94fb611..0f1e80b3b9 100644 --- a/doc/src/sgml/fdwhandler.sgml +++ b/doc/src/sgml/fdwhandler.sgml @@ -937,7 +937,7 @@ IterateDirectModify(ForeignScanState *node); Whether the query has the clause or not, the query's reported row count must be incremented by the FDW itself. When the query doesn't have the clause, the FDW must also increment the row count for the - ForeignScanState node in the EXPLAIN ANALYZE + ForeignScanState node in the EXPLAIN EXEC case. @@ -1123,7 +1123,7 @@ ExplainForeignScan(ForeignScanState *node, The flag fields in es can be used to determine what to print, and the state of the ForeignScanState node can be inspected to provide run-time statistics in the EXPLAIN - ANALYZE case. + EXEC case. @@ -1148,7 +1148,7 @@ ExplainForeignModify(ModifyTableState *mtstate, The flag fields in es can be used to determine what to print, and the state of the ModifyTableState node can be inspected to provide run-time statistics in the EXPLAIN - ANALYZE case. The first four arguments are the same as for + EXEC case. The first four arguments are the same as for BeginForeignModify. @@ -1172,7 +1172,7 @@ ExplainDirectModify(ForeignScanState *node, The flag fields in es can be used to determine what to print, and the state of the ForeignScanState node can be inspected to provide run-time statistics in the EXPLAIN - ANALYZE case. + EXEC case. diff --git a/doc/src/sgml/indices.sgml b/doc/src/sgml/indices.sgml index 95c0a1926c..decaaa6209 100644 --- a/doc/src/sgml/indices.sgml +++ b/doc/src/sgml/indices.sgml @@ -1498,7 +1498,7 @@ CREATE INDEX test1c_content_y_index ON test1c (content COLLATE "y"); possibilities: Either the system is right and using the index is indeed not appropriate, or the cost estimates of the query plans are not reflecting reality. So you should time your query with - and without indexes. The EXPLAIN ANALYZE + and without indexes. The EXPLAIN EXEC command can be useful here. diff --git a/doc/src/sgml/jit.sgml b/doc/src/sgml/jit.sgml index a21a07ef71..cb288d8b73 100644 --- a/doc/src/sgml/jit.sgml +++ b/doc/src/sgml/jit.sgml @@ -145,7 +145,7 @@ JIT is used or not. As an example, here is a query that is not using JIT: -=# EXPLAIN ANALYZE SELECT SUM(relpages) FROM pg_class; +=# EXPLAIN EXEC SELECT SUM(relpages) FROM pg_class; QUERY PLAN ------------------------------------------------------------------------------------------------------------- Aggregate (cost=16.27..16.29 rows=1 width=8) (actual time=0.303..0.303 rows=1 loops=1) @@ -161,7 +161,7 @@ =# SET jit_above_cost = 10; SET -=# EXPLAIN ANALYZE SELECT SUM(relpages) FROM pg_class; +=# EXPLAIN EXEC SELECT SUM(relpages) FROM pg_class; QUERY PLAN ------------------------------------------------------------------------------------------------------------- Aggregate (cost=16.27..16.29 rows=1 width=8) (actual time=6.049..6.049 rows=1 loops=1) diff --git a/doc/src/sgml/parallel.sgml b/doc/src/sgml/parallel.sgml index af5d48a5c7..b3e2285f05 100644 --- a/doc/src/sgml/parallel.sgml +++ b/doc/src/sgml/parallel.sgml @@ -442,7 +442,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%'; - When executing a parallel plan, you can use EXPLAIN (ANALYZE, + When executing a parallel plan, you can use EXPLAIN (EXEC, VERBOSE) to display per-worker statistics for each plan node. This may be useful in determining whether the work is being evenly distributed between all plan nodes and more generally in understanding the diff --git a/doc/src/sgml/perform.sgml b/doc/src/sgml/perform.sgml index a84be85159..3a890c5a71 100644 --- a/doc/src/sgml/perform.sgml +++ b/doc/src/sgml/perform.sgml @@ -533,25 +533,25 @@ WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2; which shows that the planner thinks that sorting onek by index-scanning is about 12% more expensive than sequential-scan-and-sort. Of course, the next question is whether it's right about that. - We can investigate that using EXPLAIN ANALYZE, as discussed + We can investigate that using EXPLAIN EXEC, as discussed below. - - <command>EXPLAIN ANALYZE</command> + + <command>EXPLAIN EXEC</command> It is possible to check the accuracy of the planner's estimates - by using EXPLAIN's ANALYZE option. With this + by using EXPLAIN's EXEC option. With this option, EXPLAIN actually executes the query, and then displays the true row counts and true run time accumulated within each plan node, along with the same estimates that a plain EXPLAIN shows. For example, we might get a result like this: -EXPLAIN ANALYZE SELECT * +EXPLAIN EXEC SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 10 AND t1.unique2 = t2.unique2; @@ -590,12 +590,12 @@ WHERE t1.unique1 < 10 AND t1.unique2 = t2.unique2; - In some cases EXPLAIN ANALYZE shows additional execution + In some cases EXPLAIN EXEC shows additional execution statistics beyond the plan node execution times and row counts. For example, Sort and Hash nodes provide extra information: -EXPLAIN ANALYZE SELECT * +EXPLAIN EXEC SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2 ORDER BY t1.fivethous; @@ -630,7 +630,7 @@ WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2 ORDER BY t1.fivethous; filter condition: -EXPLAIN ANALYZE SELECT * FROM tenk1 WHERE ten < 7; +EXPLAIN EXEC SELECT * FROM tenk1 WHERE ten < 7; QUERY PLAN --------------------------------------------------------------------------------------------------------- @@ -653,7 +653,7 @@ EXPLAIN ANALYZE SELECT * FROM tenk1 WHERE ten < 7; specific point: -EXPLAIN ANALYZE SELECT * FROM polygon_tbl WHERE f1 @> polygon '(0.5,2.0)'; +EXPLAIN EXEC SELECT * FROM polygon_tbl WHERE f1 @> polygon '(0.5,2.0)'; QUERY PLAN ------------------------------------------------------------------------------------------------------ @@ -672,7 +672,7 @@ EXPLAIN ANALYZE SELECT * FROM polygon_tbl WHERE f1 @> polygon '(0.5,2.0)'; SET enable_seqscan TO off; -EXPLAIN ANALYZE SELECT * FROM polygon_tbl WHERE f1 @> polygon '(0.5,2.0)'; +EXPLAIN EXEC SELECT * FROM polygon_tbl WHERE f1 @> polygon '(0.5,2.0)'; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------- @@ -695,7 +695,7 @@ EXPLAIN ANALYZE SELECT * FROM polygon_tbl WHERE f1 @> polygon '(0.5,2.0)'; ANALYZE to get even more run time statistics: -EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000; +EXPLAIN (EXEC, BUFFERS) SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- @@ -719,7 +719,7 @@ EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM tenk1 WHERE unique1 < 100 AND unique - Keep in mind that because EXPLAIN ANALYZE actually + Keep in mind that because EXPLAIN EXEC actually runs the query, any side-effects will happen as usual, even though whatever results the query might output are discarded in favor of printing the EXPLAIN data. If you want to analyze a @@ -729,7 +729,7 @@ EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM tenk1 WHERE unique1 < 100 AND unique BEGIN; -EXPLAIN ANALYZE UPDATE tenk1 SET hundred = hundred + 1 WHERE unique1 < 100; +EXPLAIN EXEC UPDATE tenk1 SET hundred = hundred + 1 WHERE unique1 < 100; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------- @@ -795,13 +795,13 @@ EXPLAIN UPDATE parent SET f2 = f2 + 1 WHERE f1 = 101; The Planning time shown by EXPLAIN - ANALYZE is the time it took to generate the query plan from the + EXEC is the time it took to generate the query plan from the parsed query and optimize it. It does not include parsing or rewriting. The Execution time shown by EXPLAIN - ANALYZE includes executor start-up and shut-down time, as well + EXEC includes executor start-up and shut-down time, as well as the time to run any triggers that are fired, but it does not include parsing, rewriting, or planning time. Time spent executing BEFORE triggers, if any, is included in @@ -812,7 +812,7 @@ EXPLAIN UPDATE parent SET f2 = f2 + 1 WHERE f1 = 101; (either BEFORE or AFTER) is also shown separately. Note that deferred constraint triggers will not be executed until end of transaction and are thus not considered at all by - EXPLAIN ANALYZE. + EXPLAIN EXEC. @@ -822,11 +822,11 @@ EXPLAIN UPDATE parent SET f2 = f2 + 1 WHERE f1 = 101; There are two significant ways in which run times measured by - EXPLAIN ANALYZE can deviate from normal execution of + EXPLAIN EXEC can deviate from normal execution of the same query. First, since no output rows are delivered to the client, network transmission costs and I/O conversion costs are not included. Second, the measurement overhead added by EXPLAIN - ANALYZE can be significant, especially on machines with slow + EXEC can be significant, especially on machines with slow gettimeofday() operating-system calls. You can use the tool to measure the overhead of timing on your system. @@ -853,7 +853,7 @@ EXPLAIN UPDATE parent SET f2 = f2 + 1 WHERE f1 = 101; effect. For example, in the LIMIT query we used before, -EXPLAIN ANALYZE SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2; +EXPLAIN EXEC SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------- @@ -883,7 +883,7 @@ EXPLAIN ANALYZE SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 of one child, with results like those mentioned for LIMIT. Also, if the outer (first) child contains rows with duplicate key values, the inner (second) child is backed up and rescanned for the portion of its - rows matching that key value. EXPLAIN ANALYZE counts these + rows matching that key value. EXPLAIN EXEC counts these repeated emissions of the same inner rows as if they were real additional rows. When there are many outer duplicates, the reported actual row count for the inner child plan node can be significantly larger than the number diff --git a/doc/src/sgml/planstats.sgml b/doc/src/sgml/planstats.sgml index 4b1d3f4952..3a4405c850 100644 --- a/doc/src/sgml/planstats.sgml +++ b/doc/src/sgml/planstats.sgml @@ -489,7 +489,7 @@ SELECT relpages, reltuples FROM pg_class WHERE relname = 't'; condition on the a column: -EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1; +EXPLAIN (EXEC, TIMING OFF) SELECT * FROM t WHERE a = 1; QUERY PLAN ------------------------------------------------------------------------------- Seq Scan on t (cost=0.00..170.00 rows=100 width=8) (actual rows=100 loops=1) @@ -506,7 +506,7 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1; condition on both columns, combining them with AND: -EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; +EXPLAIN (EXEC, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; QUERY PLAN ----------------------------------------------------------------------------- Seq Scan on t (cost=0.00..195.00 rows=1 width=8) (actual rows=100 loops=1) @@ -530,7 +530,7 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; CREATE STATISTICS stts (dependencies) ON a, b FROM t; ANALYZE t; -EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; +EXPLAIN (EXEC, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; QUERY PLAN ------------------------------------------------------------------------------- Seq Scan on t (cost=0.00..195.00 rows=100 width=8) (actual rows=100 loops=1) @@ -551,7 +551,7 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; estimated number of rows returned by the HashAggregate node) is very accurate: -EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a; +EXPLAIN (EXEC, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a; QUERY PLAN ----------------------------------------------------------------------------------------- HashAggregate (cost=195.00..196.00 rows=100 width=12) (actual rows=100 loops=1) @@ -562,7 +562,7 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a; groups in a query with two columns in GROUP BY, as in the following example, is off by an order of magnitude: -EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b; +EXPLAIN (EXEC, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b; QUERY PLAN -------------------------------------------------------------------------------------------- HashAggregate (cost=220.00..230.00 rows=1000 width=16) (actual rows=100 loops=1) @@ -575,7 +575,7 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b; DROP STATISTICS stts; CREATE STATISTICS stts (dependencies, ndistinct) ON a, b FROM t; ANALYZE t; -EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b; +EXPLAIN (EXEC, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b; QUERY PLAN -------------------------------------------------------------------------------------------- HashAggregate (cost=220.00..221.00 rows=100 width=16) (actual rows=100 loops=1) @@ -615,7 +615,7 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b; DROP STATISTICS stts; CREATE STATISTICS stts2 (mcv) ON a, b FROM t; ANALYZE t; -EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; +EXPLAIN (EXEC, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; QUERY PLAN ------------------------------------------------------------------------------- Seq Scan on t (cost=0.00..195.00 rows=100 width=8) (actual rows=100 loops=1) @@ -672,7 +672,7 @@ SELECT m.* FROM pg_statistic_ext, to decide which combinations are compatible. -EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 10; +EXPLAIN (EXEC, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 10; QUERY PLAN --------------------------------------------------------------------------- Seq Scan on t (cost=0.00..195.00 rows=1 width=8) (actual rows=0 loops=1) @@ -685,7 +685,7 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 10; example range query, presented earlier: -EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a <= 49 AND b > 49; +EXPLAIN (EXEC, TIMING OFF) SELECT * FROM t WHERE a <= 49 AND b > 49; QUERY PLAN --------------------------------------------------------------------------- Seq Scan on t (cost=0.00..195.00 rows=1 width=8) (actual rows=0 loops=1) diff --git a/doc/src/sgml/ref/create_statistics.sgml b/doc/src/sgml/ref/create_statistics.sgml index ae1d8024a4..18ca19fa8f 100644 --- a/doc/src/sgml/ref/create_statistics.sgml +++ b/doc/src/sgml/ref/create_statistics.sgml @@ -147,14 +147,14 @@ INSERT INTO t1 SELECT i/100, i/500 ANALYZE t1; -- the number of matching rows will be drastically underestimated: -EXPLAIN ANALYZE SELECT * FROM t1 WHERE (a = 1) AND (b = 0); +EXPLAIN EXEC SELECT * FROM t1 WHERE (a = 1) AND (b = 0); CREATE STATISTICS s1 (dependencies) ON a, b FROM t1; ANALYZE t1; -- now the row count estimate is more accurate: -EXPLAIN ANALYZE SELECT * FROM t1 WHERE (a = 1) AND (b = 0); +EXPLAIN EXEC SELECT * FROM t1 WHERE (a = 1) AND (b = 0); Without functional-dependency statistics, the planner would assume @@ -183,10 +183,10 @@ CREATE STATISTICS s2 (mcv) ON (a, b) FROM t2; ANALYZE t2; -- valid combination (found in MCV) -EXPLAIN ANALYZE SELECT * FROM t2 WHERE (a = 1) AND (b = 1); +EXPLAIN EXEC SELECT * FROM t2 WHERE (a = 1) AND (b = 1); -- invalid combination (not found in MCV) -EXPLAIN ANALYZE SELECT * FROM t2 WHERE (a = 1) AND (b = 2); +EXPLAIN EXEC SELECT * FROM t2 WHERE (a = 1) AND (b = 2); The MCV list gives the planner more detailed information about the diff --git a/doc/src/sgml/ref/pgtesttiming.sgml b/doc/src/sgml/ref/pgtesttiming.sgml index 545a934cf8..4470435dd2 100644 --- a/doc/src/sgml/ref/pgtesttiming.sgml +++ b/doc/src/sgml/ref/pgtesttiming.sgml @@ -30,7 +30,7 @@ pg_test_timing is a tool to measure the timing overhead on your system and confirm that the system time never moves backwards. Systems that are slow to collect timing data can give less accurate - EXPLAIN ANALYZE results. + EXPLAIN EXEC results. @@ -120,7 +120,7 @@ Histogram of timing durations: When the query executor is running a statement using - EXPLAIN ANALYZE, individual operations are timed as well + EXPLAIN EXEC, individual operations are timed as well as showing a summary. The overhead of your system can be checked by counting rows with the psql program: @@ -128,13 +128,13 @@ Histogram of timing durations: CREATE TABLE t AS SELECT * FROM generate_series(1,100000); \timing SELECT COUNT(*) FROM t; -EXPLAIN ANALYZE SELECT COUNT(*) FROM t; +EXPLAIN EXEC SELECT COUNT(*) FROM t; The i7-860 system measured runs the count query in 9.8 ms while - the EXPLAIN ANALYZE version takes 16.6 ms, each + the EXPLAIN EXEC version takes 16.6 ms, each processing just over 100,000 rows. That 6.8 ms difference means the timing overhead per row is 68 ns, about twice what pg_test_timing estimated it would be. Even that relatively small amount of overhead is making the fully @@ -169,12 +169,12 @@ Histogram of timing durations: - In this configuration, the sample EXPLAIN ANALYZE above + In this configuration, the sample EXPLAIN EXEC above takes 115.9 ms. That's 1061 ns of timing overhead, again a small multiple of what's measured directly by this utility. That much timing overhead means the actual query itself is only taking a tiny fraction of the accounted for time, most of it is being consumed in overhead instead. In - this configuration, any EXPLAIN ANALYZE totals involving + this configuration, any EXPLAIN EXEC totals involving many timed operations would be inflated significantly by timing overhead. diff --git a/doc/src/sgml/ref/set_transaction.sgml b/doc/src/sgml/ref/set_transaction.sgml index 43b1c6c892..cef790ecd7 100644 --- a/doc/src/sgml/ref/set_transaction.sgml +++ b/doc/src/sgml/ref/set_transaction.sgml @@ -133,7 +133,7 @@ SET SESSION CHARACTERISTICS AS TRANSACTION transa CREATE, ALTER, and DROP commands; COMMENT, GRANT, REVOKE, - TRUNCATE; and EXPLAIN ANALYZE + TRUNCATE; and EXPLAIN EXEC and EXECUTE if the command they would execute is among those listed. This is a high-level notion of read-only that does not prevent all writes to disk. diff --git a/doc/src/sgml/rules.sgml b/doc/src/sgml/rules.sgml index 4e20664ea1..499e6fcced 100644 --- a/doc/src/sgml/rules.sgml +++ b/doc/src/sgml/rules.sgml @@ -1030,7 +1030,7 @@ SELECT count(*) FROM words WHERE word = 'caterpiler'; (1 row) - With EXPLAIN ANALYZE, we see: + With EXPLAIN EXEC, we see: Aggregate (cost=21763.99..21764.00 rows=1 width=0) (actual time=188.180..188.181 rows=1 loops=1) --------------2.21.0-- --Ayym4vmyMU9P4uDb Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v4-0005-Changed-code-comments-to-reflect-the-new-default-.patch" From c808fa83c4682f1c352d7d96e3fb712f8a82fe41 Mon Sep 17 00:00:00 2001 From: David Fetter Date: Tue, 14 May 2019 22:53:19 -0700 Subject: [PATCH v4 5/8] Changed code comments to reflect the new default spelling To: hackers MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------2.21.0" This is a multi-part message in MIME format. --------------2.21.0 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 2beb378145..8c4320df58 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -2365,7 +2365,7 @@ FindTriggerIncompatibleWithInheritance(TriggerDesc *trigdesc) * trigdata: trigger descriptor. * tgindx: trigger's index in finfo and instr arrays. * finfo: array of cached trigger function call information. - * instr: optional array of EXPLAIN ANALYZE instrumentation state. + * instr: optional array of EXPLAIN EXEC instrumentation state. * per_tuple_context: memory context to execute the function in. * * Returns the tuple (or NULL) as returned by the function. @@ -2406,7 +2406,7 @@ ExecCallTriggerFunc(TriggerData *trigdata, Assert(finfo->fn_oid == trigdata->tg_trigger->tgfoid); /* - * If doing EXPLAIN ANALYZE, start charging time to this trigger. + * If doing EXPLAIN EXEC, start charging time to this trigger. */ if (instr) InstrStartNode(instr + tgindx); @@ -2455,7 +2455,7 @@ ExecCallTriggerFunc(TriggerData *trigdata, fcinfo->flinfo->fn_oid))); /* - * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count + * If doing EXPLAIN EXEC, stop charging time to this trigger, and count * one "tuple returned" (really the number of firings). */ if (instr) @@ -4171,7 +4171,7 @@ afterTriggerDeleteHeadEventChunk(AfterTriggersQueryData *qs) * rel: open relation for event. * trigdesc: working copy of rel's trigger info. * finfo: array of fmgr lookup cache entries (one per trigger in trigdesc). - * instr: array of EXPLAIN ANALYZE instrumentation nodes (one per trigger), + * instr: array of EXPLAIN EXEC instrumentation nodes (one per trigger), * or NULL if no instrumentation is wanted. * per_tuple_context: memory context to call trigger function in. * trig_tuple_slot1: scratch slot for tg_trigtuple (foreign tables only) @@ -4216,7 +4216,7 @@ AfterTriggerExecute(EState *estate, elog(ERROR, "could not find trigger %u", tgoid); /* - * If doing EXPLAIN ANALYZE, start charging time to this trigger. We want + * If doing EXPLAIN EXEC, start charging time to this trigger. We want * to include time spent re-fetching tuples in the trigger cost. */ if (instr) @@ -4359,7 +4359,7 @@ AfterTriggerExecute(EState *estate, ExecClearTuple(LocTriggerData.tg_newslot); /* - * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count + * If doing EXPLAIN EXEC, stop charging time to this trigger, and count * one "tuple returned" (really the number of firings). */ if (instr) diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index ed7c0606bf..cbbc7e087b 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -390,7 +390,7 @@ standard_ExecutorRun(QueryDesc *queryDesc, * * This routine must be called after the last ExecutorRun call. * It performs cleanup such as firing AFTER triggers. It is - * separate from ExecutorEnd because EXPLAIN ANALYZE needs to + * separate from ExecutorEnd because EXPLAIN EXEC needs to * include these actions in the total runtime. * * We provide a function hook variable that lets loadable plugins @@ -1365,7 +1365,7 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo, * on other relations, which will be processed in the context of the outer * query. For efficiency's sake, we want to have a ResultRelInfo for those * triggers too; that can avoid repeated re-opening of the relation. (It - * also provides a way for EXPLAIN ANALYZE to report the runtimes of such + * also provides a way for EXPLAIN EXEC to report the runtimes of such * triggers.) So we make additional ResultRelInfo's as needed, and save them * in es_trig_target_relations. */ diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index 3d4b01cb4d..adcccbbdcb 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -273,11 +273,11 @@ ExecParallelEstimate(PlanState *planstate, ExecParallelEstimateContext *e) e->pcxt); break; case T_HashState: - /* even when not parallel-aware, for EXPLAIN ANALYZE */ + /* even when not parallel-aware, for EXPLAIN EXEC */ ExecHashEstimate((HashState *) planstate, e->pcxt); break; case T_SortState: - /* even when not parallel-aware, for EXPLAIN ANALYZE */ + /* even when not parallel-aware, for EXPLAIN EXEC */ ExecSortEstimate((SortState *) planstate, e->pcxt); break; @@ -486,11 +486,11 @@ ExecParallelInitializeDSM(PlanState *planstate, d->pcxt); break; case T_HashState: - /* even when not parallel-aware, for EXPLAIN ANALYZE */ + /* even when not parallel-aware, for EXPLAIN EXEC */ ExecHashInitializeDSM((HashState *) planstate, d->pcxt); break; case T_SortState: - /* even when not parallel-aware, for EXPLAIN ANALYZE */ + /* even when not parallel-aware, for EXPLAIN EXEC */ ExecSortInitializeDSM((SortState *) planstate, d->pcxt); break; @@ -1294,11 +1294,11 @@ ExecParallelInitializeWorker(PlanState *planstate, ParallelWorkerContext *pwcxt) pwcxt); break; case T_HashState: - /* even when not parallel-aware, for EXPLAIN ANALYZE */ + /* even when not parallel-aware, for EXPLAIN EXEC */ ExecHashInitializeWorker((HashState *) planstate, pwcxt); break; case T_SortState: - /* even when not parallel-aware, for EXPLAIN ANALYZE */ + /* even when not parallel-aware, for EXPLAIN EXEC */ ExecSortInitializeWorker((SortState *) planstate, pwcxt); break; diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index 64eec91f8b..c6a2906db5 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -193,7 +193,7 @@ MultiExecPrivateHash(HashState *node) if (hashtable->nbuckets != hashtable->nbuckets_optimal) ExecHashIncreaseNumBuckets(hashtable); - /* Account for the buckets in spaceUsed (reported in EXPLAIN ANALYZE) */ + /* Account for the buckets in spaceUsed (reported in EXPLAIN EXEC) */ hashtable->spaceUsed += hashtable->nbuckets * sizeof(HashJoinTuple); if (hashtable->spaceUsed > hashtable->spacePeak) hashtable->spacePeak = hashtable->spaceUsed; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 92d0507949..cd5e834ae9 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -3215,19 +3215,19 @@ GetCommandLogLevel(Node *parsetree) case T_ExplainStmt: { ExplainStmt *stmt = (ExplainStmt *) parsetree; - bool analyze = false; + bool exec = false; ListCell *lc; - /* Look through an EXPLAIN ANALYZE to the contained stmt */ + /* Look through an EXPLAIN EXEC to the contained stmt */ foreach(lc, stmt->options) { DefElem *opt = (DefElem *) lfirst(lc); - if (strcmp(opt->defname, "analyze") == 0) - analyze = defGetBoolean(opt); + if (strcmp(opt->defname, "exec") == 0) + exec = defGetBoolean(opt); /* don't "break", as explain.c will use the last value */ } - if (analyze) + if (exec) return GetCommandLogLevel(stmt->query); /* Plain EXPLAIN isn't so interesting */ diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index eb4c8b5e79..72730fcfaf 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -52,7 +52,7 @@ * mean that the plan can't queue any AFTER triggers; just that the caller * is responsible for there being a trigger context for them to be queued in. */ -#define EXEC_FLAG_EXPLAIN_ONLY 0x0001 /* EXPLAIN, no ANALYZE */ +#define EXEC_FLAG_EXPLAIN_ONLY 0x0001 /* EXPLAIN, no EXEC */ #define EXEC_FLAG_REWIND 0x0002 /* need efficient rescan */ #define EXEC_FLAG_BACKWARD 0x0004 /* need backward scan */ #define EXEC_FLAG_MARK 0x0008 /* need mark/restore */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 4b1635eb8b..6a92fb1d6f 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -2189,7 +2189,7 @@ typedef struct GatherMergeState } GatherMergeState; /* ---------------- - * Values displayed by EXPLAIN ANALYZE + * Values displayed by EXPLAIN EXEC * ---------------- */ typedef struct HashInstrumentation --------------2.21.0-- --Ayym4vmyMU9P4uDb Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v4-0006-Mechanical-changes-to-regression-tests-and-their-.patch" From b04ca32d79ca18a7b68e04c12e2ae053351a2bbb Mon Sep 17 00:00:00 2001 From: David Fetter Date: Tue, 14 May 2019 22:54:15 -0700 Subject: [PATCH v4 6/8] Mechanical changes to regression tests and their output To: hackers MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------2.21.0" This is a multi-part message in MIME format. --------------2.21.0 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index 129c1e5075..4c06b8b507 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -795,7 +795,8 @@ explain (costs off) -> Limit -> Index Only Scan Backward using tenk1_unique1 on tenk1 Index Cond: ((unique1 IS NOT NULL) AND (unique1 > 42000)) -(5 rows) + Settings: max_parallel_workers_per_gather = '0' +(6 rows) select max(unique1) from tenk1 where unique1 > 42000; max @@ -2179,14 +2180,15 @@ ALTER TABLE tenk1 set (parallel_workers = 4); SET LOCAL parallel_setup_cost=0; SET LOCAL max_parallel_workers_per_gather=4; EXPLAIN (COSTS OFF) SELECT balk(hundred) FROM tenk1; - QUERY PLAN -------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 4 -> Partial Aggregate -> Parallel Index Only Scan using tenk1_hundred on tenk1 -(5 rows) + Settings: max_parallel_workers_per_gather = '4', parallel_setup_cost = '0' +(6 rows) SELECT balk(hundred) FROM tenk1; balk @@ -2206,14 +2208,15 @@ SET enable_indexonlyscan = off; -- sum(int8) covers int8_avg_combine EXPLAIN (COSTS OFF) SELECT variance(unique1::int4), sum(unique1::int8) FROM tenk1; - QUERY PLAN ----------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 4 -> Partial Aggregate -> Parallel Seq Scan on tenk1 -(5 rows) + Settings: enable_indexonlyscan = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(6 rows) SELECT variance(unique1::int4), sum(unique1::int8) FROM tenk1; variance | sum diff --git a/src/test/regress/expected/box.out b/src/test/regress/expected/box.out index 998b52223c..b3ee86063f 100644 --- a/src/test/regress/expected/box.out +++ b/src/test/regress/expected/box.out @@ -270,7 +270,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 << '(10,20),(30,40)'; ---------------------------------------------- Index Only Scan using box_spgist on box_temp Index Cond: (f1 << '(30,40),(10,20)'::box) -(2 rows) + Settings: enable_seqscan = 'off' +(3 rows) SELECT * FROM box_temp WHERE f1 &< '(10,4.333334),(5,100)'; f1 @@ -290,7 +291,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 &< '(10,4.333334),(5,100)'; ---------------------------------------------------- Index Only Scan using box_spgist on box_temp Index Cond: (f1 &< '(10,100),(5,4.333334)'::box) -(2 rows) + Settings: enable_seqscan = 'off' +(3 rows) SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)'; f1 @@ -319,7 +321,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 && '(15,20),(25,30)'; ---------------------------------------------- Index Only Scan using box_spgist on box_temp Index Cond: (f1 && '(25,30),(15,20)'::box) -(2 rows) + Settings: enable_seqscan = 'off' +(3 rows) SELECT * FROM box_temp WHERE f1 &> '(40,30),(45,50)'; f1 @@ -342,7 +345,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 &> '(40,30),(45,50)'; ---------------------------------------------- Index Only Scan using box_spgist on box_temp Index Cond: (f1 &> '(45,50),(40,30)'::box) -(2 rows) + Settings: enable_seqscan = 'off' +(3 rows) SELECT * FROM box_temp WHERE f1 >> '(30,40),(40,30)'; f1 @@ -364,7 +368,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 >> '(30,40),(40,30)'; ---------------------------------------------- Index Only Scan using box_spgist on box_temp Index Cond: (f1 >> '(40,40),(30,30)'::box) -(2 rows) + Settings: enable_seqscan = 'off' +(3 rows) SELECT * FROM box_temp WHERE f1 <<| '(10,4.33334),(5,100)'; f1 @@ -379,7 +384,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 <<| '(10,4.33334),(5,100)'; ---------------------------------------------------- Index Only Scan using box_spgist on box_temp Index Cond: (f1 <<| '(10,100),(5,4.33334)'::box) -(2 rows) + Settings: enable_seqscan = 'off' +(3 rows) SELECT * FROM box_temp WHERE f1 &<| '(10,4.3333334),(5,1)'; f1 @@ -394,7 +400,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 &<| '(10,4.3333334),(5,1)'; ---------------------------------------------------- Index Only Scan using box_spgist on box_temp Index Cond: (f1 &<| '(10,4.3333334),(5,1)'::box) -(2 rows) + Settings: enable_seqscan = 'off' +(3 rows) SELECT * FROM box_temp WHERE f1 |&> '(49.99,49.99),(49.99,49.99)'; f1 @@ -408,7 +415,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |&> '(49.99,49.99),(49.99,49 ----------------------------------------------------------- Index Only Scan using box_spgist on box_temp Index Cond: (f1 |&> '(49.99,49.99),(49.99,49.99)'::box) -(2 rows) + Settings: enable_seqscan = 'off' +(3 rows) SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)'; f1 @@ -431,7 +439,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 |>> '(37,38),(39,40)'; ----------------------------------------------- Index Only Scan using box_spgist on box_temp Index Cond: (f1 |>> '(39,40),(37,38)'::box) -(2 rows) + Settings: enable_seqscan = 'off' +(3 rows) SELECT * FROM box_temp WHERE f1 @> '(10,11),(15,16)'; f1 @@ -447,7 +456,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 @> '(10,11),(15,15)'; ---------------------------------------------- Index Only Scan using box_spgist on box_temp Index Cond: (f1 @> '(15,15),(10,11)'::box) -(2 rows) + Settings: enable_seqscan = 'off' +(3 rows) SELECT * FROM box_temp WHERE f1 <@ '(10,15),(30,35)'; f1 @@ -460,7 +470,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 <@ '(10,15),(30,35)'; ---------------------------------------------- Index Only Scan using box_spgist on box_temp Index Cond: (f1 <@ '(30,35),(10,15)'::box) -(2 rows) + Settings: enable_seqscan = 'off' +(3 rows) SELECT * FROM box_temp WHERE f1 ~= '(20,20),(40,40)'; f1 @@ -473,7 +484,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM box_temp WHERE f1 ~= '(20,20),(40,40)'; ---------------------------------------------- Index Only Scan using box_spgist on box_temp Index Cond: (f1 ~= '(40,40),(20,20)'::box) -(2 rows) + Settings: enable_seqscan = 'off' +(3 rows) RESET enable_seqscan; DROP INDEX box_spgist; diff --git a/src/test/regress/expected/btree_index.out b/src/test/regress/expected/btree_index.out index acab8e0b11..e7121823a2 100644 --- a/src/test/regress/expected/btree_index.out +++ b/src/test/regress/expected/btree_index.out @@ -112,7 +112,8 @@ select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1; Index Only Scan using pg_proc_proname_args_nsp_index on pg_proc Index Cond: ((proname >= 'RI_FKey'::text) AND (proname < 'RI_FKez'::text)) Filter: (proname ~~ 'RI\_FKey%del'::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1; proname @@ -131,7 +132,8 @@ select proname from pg_proc where proname ilike '00%foo' order by 1; Index Only Scan using pg_proc_proname_args_nsp_index on pg_proc Index Cond: ((proname >= '00'::text) AND (proname < '01'::text)) Filter: (proname ~~* '00%foo'::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) select proname from pg_proc where proname ilike '00%foo' order by 1; proname @@ -144,7 +146,8 @@ select proname from pg_proc where proname ilike 'ri%foo' order by 1; ----------------------------------------------------------------- Index Only Scan using pg_proc_proname_args_nsp_index on pg_proc Filter: (proname ~~* 'ri%foo'::text) -(2 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(3 rows) set enable_indexscan to false; set enable_bitmapscan to true; @@ -158,7 +161,8 @@ select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1; Filter: (proname ~~ 'RI\_FKey%del'::text) -> Bitmap Index Scan on pg_proc_proname_args_nsp_index Index Cond: ((proname >= 'RI_FKey'::text) AND (proname < 'RI_FKez'::text)) -(6 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(7 rows) select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1; proname @@ -180,7 +184,8 @@ select proname from pg_proc where proname ilike '00%foo' order by 1; Filter: (proname ~~* '00%foo'::text) -> Bitmap Index Scan on pg_proc_proname_args_nsp_index Index Cond: ((proname >= '00'::text) AND (proname < '01'::text)) -(6 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(7 rows) select proname from pg_proc where proname ilike '00%foo' order by 1; proname @@ -193,7 +198,8 @@ select proname from pg_proc where proname ilike 'ri%foo' order by 1; ----------------------------------------------------------------- Index Only Scan using pg_proc_proname_args_nsp_index on pg_proc Filter: (proname ~~* 'ri%foo'::text) -(2 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(3 rows) reset enable_seqscan; reset enable_indexscan; diff --git a/src/test/regress/expected/collate.out b/src/test/regress/expected/collate.out index 0dee7d783a..c3a390850b 100644 --- a/src/test/regress/expected/collate.out +++ b/src/test/regress/expected/collate.out @@ -626,7 +626,8 @@ EXPLAIN (COSTS OFF) Sort Sort Key: x COLLATE "C", y COLLATE "POSIX" -> Seq Scan on collate_test10 -(3 rows) + Settings: search_path = 'collate_tests' +(4 rows) EXPLAIN (COSTS OFF) SELECT * FROM collate_test10 ORDER BY x DESC, y COLLATE "C" ASC NULLS FIRST; @@ -635,7 +636,8 @@ EXPLAIN (COSTS OFF) Sort Sort Key: x COLLATE "C" DESC, y COLLATE "C" NULLS FIRST -> Seq Scan on collate_test10 -(3 rows) + Settings: search_path = 'collate_tests' +(4 rows) -- CREATE/DROP COLLATION CREATE COLLATION mycoll1 FROM "C"; diff --git a/src/test/regress/expected/create_am.out b/src/test/regress/expected/create_am.out index 352959b751..763ab8b2b6 100644 --- a/src/test/regress/expected/create_am.out +++ b/src/test/regress/expected/create_am.out @@ -54,7 +54,8 @@ SELECT * FROM fast_emp4000 Sort Key: ((home_base[0])[0]) -> Index Only Scan using grect2ind2 on fast_emp4000 Index Cond: (home_base @ '(2000,1000),(200,200)'::box) -(4 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(5 rows) SELECT * FROM fast_emp4000 WHERE home_base @ '(200,200),(2000,1000)'::box @@ -72,7 +73,8 @@ SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; Aggregate -> Index Only Scan using grect2ind2 on fast_emp4000 Index Cond: (home_base && '(1000,1000),(0,0)'::box) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; count @@ -82,12 +84,13 @@ SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; EXPLAIN (COSTS OFF) SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL; - QUERY PLAN --------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using grect2ind2 on fast_emp4000 Index Cond: (home_base IS NULL) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL; count diff --git a/src/test/regress/expected/create_function_3.out b/src/test/regress/expected/create_function_3.out index ba260df996..55832d399c 100644 --- a/src/test/regress/expected/create_function_3.out +++ b/src/test/regress/expected/create_function_3.out @@ -303,11 +303,12 @@ SELECT voidtest2(11,22); -- currently, we can inline voidtest2 but not voidtest1 EXPLAIN (verbose, costs off) SELECT voidtest2(11,22); - QUERY PLAN -------------------------- + QUERY PLAN +-------------------------------------------------- Result Output: voidtest1(33) -(2 rows) + Settings: search_path = 'temp_func_test, public' +(3 rows) CREATE TEMP TABLE sometable(f1 int); CREATE FUNCTION voidtest3(a int) RETURNS VOID LANGUAGE SQL AS diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out index c8bc6be061..e853c4ff82 100644 --- a/src/test/regress/expected/create_index.out +++ b/src/test/regress/expected/create_index.out @@ -267,7 +267,8 @@ SELECT * FROM fast_emp4000 Sort Key: ((home_base[0])[0]) -> Index Only Scan using grect2ind on fast_emp4000 Index Cond: (home_base @ '(2000,1000),(200,200)'::box) -(4 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(5 rows) SELECT * FROM fast_emp4000 WHERE home_base @ '(200,200),(2000,1000)'::box @@ -285,7 +286,8 @@ SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; Aggregate -> Index Only Scan using grect2ind on fast_emp4000 Index Cond: (home_base && '(1000,1000),(0,0)'::box) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; count @@ -295,12 +297,13 @@ SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; EXPLAIN (COSTS OFF) SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using grect2ind on fast_emp4000 Index Cond: (home_base IS NULL) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL; count @@ -311,13 +314,14 @@ SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL; EXPLAIN (COSTS OFF) SELECT * FROM polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::polygon ORDER BY (poly_center(f1))[0]; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Sort Sort Key: ((poly_center(f1))[0]) -> Index Scan using gpolygonind on polygon_tbl Index Cond: (f1 ~ '((1,1),(2,2),(2,1))'::polygon) -(4 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(5 rows) SELECT * FROM polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::polygon ORDER BY (poly_center(f1))[0]; @@ -329,13 +333,14 @@ SELECT * FROM polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::polygon EXPLAIN (COSTS OFF) SELECT * FROM circle_tbl WHERE f1 && circle(point(1,-2), 1) ORDER BY area(f1); - QUERY PLAN --------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Sort Sort Key: (area(f1)) -> Index Scan using gcircleind on circle_tbl Index Cond: (f1 && '<(1,-2),1>'::circle) -(4 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(5 rows) SELECT * FROM circle_tbl WHERE f1 && circle(point(1,-2), 1) ORDER BY area(f1); @@ -349,12 +354,13 @@ SELECT * FROM circle_tbl WHERE f1 && circle(point(1,-2), 1) EXPLAIN (COSTS OFF) SELECT count(*) FROM gpolygon_tbl WHERE f1 && '(1000,1000,0,0)'::polygon; - QUERY PLAN ------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Scan using ggpolygonind on gpolygon_tbl Index Cond: (f1 && '((1000,1000),(0,0))'::polygon) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM gpolygon_tbl WHERE f1 && '(1000,1000,0,0)'::polygon; count @@ -364,12 +370,13 @@ SELECT count(*) FROM gpolygon_tbl WHERE f1 && '(1000,1000,0,0)'::polygon; EXPLAIN (COSTS OFF) SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Scan using ggcircleind on gcircle_tbl Index Cond: (f1 && '<(500,500),500>'::circle) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle; count @@ -379,12 +386,13 @@ SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle; EXPLAIN (COSTS OFF) SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; - QUERY PLAN ----------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using gpointind on point_tbl Index Cond: (f1 <@ '(100,100),(0,0)'::box) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; count @@ -394,12 +402,13 @@ SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; - QUERY PLAN ----------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using gpointind on point_tbl Index Cond: (f1 <@ '(100,100),(0,0)'::box) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; count @@ -414,7 +423,8 @@ SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50, Aggregate -> Index Only Scan using gpointind on point_tbl Index Cond: (f1 <@ '((0,0),(0,100),(100,100),(50,50),(100,0),(0,0))'::polygon) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)'; count @@ -424,12 +434,13 @@ SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50, EXPLAIN (COSTS OFF) SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; - QUERY PLAN ----------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using gpointind on point_tbl Index Cond: (f1 <@ '<(50,50),50>'::circle) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; count @@ -439,12 +450,13 @@ SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; EXPLAIN (COSTS OFF) SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using gpointind on point_tbl p Index Cond: (f1 << '(0,0)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; count @@ -454,12 +466,13 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using gpointind on point_tbl p Index Cond: (f1 >> '(0,0)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; count @@ -469,12 +482,13 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using gpointind on point_tbl p Index Cond: (f1 <^ '(0,0)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; count @@ -484,12 +498,13 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using gpointind on point_tbl p Index Cond: (f1 >^ '(0,0)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; count @@ -499,12 +514,13 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using gpointind on point_tbl p Index Cond: (f1 ~= '(-5,-12)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; count @@ -514,11 +530,12 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; EXPLAIN (COSTS OFF) SELECT * FROM point_tbl ORDER BY f1 <-> '0,1'; - QUERY PLAN ----------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Only Scan using gpointind on point_tbl Order By: (f1 <-> '(0,1)'::point) -(2 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(3 rows) SELECT * FROM point_tbl ORDER BY f1 <-> '0,1'; f1 @@ -537,11 +554,12 @@ SELECT * FROM point_tbl ORDER BY f1 <-> '0,1'; EXPLAIN (COSTS OFF) SELECT * FROM point_tbl WHERE f1 IS NULL; - QUERY PLAN ----------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Only Scan using gpointind on point_tbl Index Cond: (f1 IS NULL) -(2 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(3 rows) SELECT * FROM point_tbl WHERE f1 IS NULL; f1 @@ -551,12 +569,13 @@ SELECT * FROM point_tbl WHERE f1 IS NULL; EXPLAIN (COSTS OFF) SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1'; - QUERY PLAN ----------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Only Scan using gpointind on point_tbl Index Cond: (f1 IS NOT NULL) Order By: (f1 <-> '(0,1)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1'; f1 @@ -574,12 +593,13 @@ SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1'; EXPLAIN (COSTS OFF) SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1'; - QUERY PLAN ------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Only Scan using gpointind on point_tbl Index Cond: (f1 <@ '(10,10),(-10,-10)'::box) Order By: (f1 <-> '(0,1)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1'; f1 @@ -593,12 +613,13 @@ SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0 EXPLAIN (COSTS OFF) SELECT * FROM gpolygon_tbl ORDER BY f1 <-> '(0,0)'::point LIMIT 10; - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Limit -> Index Scan using ggpolygonind on gpolygon_tbl Order By: (f1 <-> '(0,0)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT * FROM gpolygon_tbl ORDER BY f1 <-> '(0,0)'::point LIMIT 10; f1 @@ -617,12 +638,13 @@ SELECT * FROM gpolygon_tbl ORDER BY f1 <-> '(0,0)'::point LIMIT 10; EXPLAIN (COSTS OFF) SELECT circle_center(f1), round(radius(f1)) as radius FROM gcircle_tbl ORDER BY f1 <-> '(200,300)'::point LIMIT 10; - QUERY PLAN ---------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Limit -> Index Scan using ggcircleind on gcircle_tbl Order By: (f1 <-> '(200,300)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT circle_center(f1), round(radius(f1)) as radius FROM gcircle_tbl ORDER BY f1 <-> '(200,300)'::point LIMIT 10; circle_center | radius @@ -653,7 +675,8 @@ SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0 Recheck Cond: (f1 <@ '(10,10),(-10,-10)'::box) -> Bitmap Index Scan on gpointind Index Cond: (f1 <@ '(10,10),(-10,-10)'::box) -(6 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(7 rows) SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1'; f1 @@ -679,15 +702,16 @@ SET enable_bitmapscan = ON; CREATE INDEX intarrayidx ON array_index_op_test USING gin (i); explain (costs off) SELECT * FROM array_index_op_test WHERE i @> '{32}' ORDER BY seqno; - QUERY PLAN ----------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Sort Sort Key: seqno -> Bitmap Heap Scan on array_index_op_test Recheck Cond: (i @> '{32}'::integer[]) -> Bitmap Index Scan on intarrayidx Index Cond: (i @> '{32}'::integer[]) -(6 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(7 rows) SELECT * FROM array_index_op_test WHERE i @> '{32}' ORDER BY seqno; seqno | i | t @@ -933,7 +957,8 @@ SELECT * FROM array_index_op_test WHERE t @> '{AAAAAAAA72908}' ORDER BY seqno; Recheck Cond: (t @> '{AAAAAAAA72908}'::text[]) -> Bitmap Index Scan on textarrayidx Index Cond: (t @> '{AAAAAAAA72908}'::text[]) -(6 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(7 rows) SELECT * FROM array_index_op_test WHERE t @> '{AAAAAAAA72908}' ORDER BY seqno; seqno | i | t @@ -1849,7 +1874,8 @@ ORDER BY thousand; Sort Key: thousand -> Index Scan using tenk1_thous_tenthous on tenk1 Index Cond: ((thousand < 2) AND (tenthous = ANY ('{1001,3000}'::integer[]))) -(4 rows) + Settings: enable_indexonlyscan = 'off' +(5 rows) SELECT thousand, tenthous FROM tenk1 WHERE thousand < 2 AND tenthous IN (1001,3000) diff --git a/src/test/regress/expected/create_index_spgist.out b/src/test/regress/expected/create_index_spgist.out index 81b4a67c39..21246bcc42 100644 --- a/src/test/regress/expected/create_index_spgist.out +++ b/src/test/regress/expected/create_index_spgist.out @@ -179,12 +179,13 @@ SET enable_indexscan = ON; SET enable_bitmapscan = OFF; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p IS NULL; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_quad_ind on quad_point_tbl Index Cond: (p IS NULL) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM quad_point_tbl WHERE p IS NULL; count @@ -194,12 +195,13 @@ SELECT count(*) FROM quad_point_tbl WHERE p IS NULL; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p IS NOT NULL; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_quad_ind on quad_point_tbl Index Cond: (p IS NOT NULL) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM quad_point_tbl WHERE p IS NOT NULL; count @@ -209,11 +211,12 @@ SELECT count(*) FROM quad_point_tbl WHERE p IS NOT NULL; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_quad_ind on quad_point_tbl -(2 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(3 rows) SELECT count(*) FROM quad_point_tbl; count @@ -223,12 +226,13 @@ SELECT count(*) FROM quad_point_tbl; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_quad_ind on quad_point_tbl Index Cond: (p <@ '(1000,1000),(200,200)'::box) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; count @@ -238,12 +242,13 @@ SELECT count(*) FROM quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_quad_ind on quad_point_tbl Index Cond: (p <@ '(1000,1000),(200,200)'::box) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; count @@ -253,12 +258,13 @@ SELECT count(*) FROM quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p << '(5000, 4000)'; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_quad_ind on quad_point_tbl Index Cond: (p << '(5000,4000)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM quad_point_tbl WHERE p << '(5000, 4000)'; count @@ -268,12 +274,13 @@ SELECT count(*) FROM quad_point_tbl WHERE p << '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p >> '(5000, 4000)'; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_quad_ind on quad_point_tbl Index Cond: (p >> '(5000,4000)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM quad_point_tbl WHERE p >> '(5000, 4000)'; count @@ -283,12 +290,13 @@ SELECT count(*) FROM quad_point_tbl WHERE p >> '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p <^ '(5000, 4000)'; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_quad_ind on quad_point_tbl Index Cond: (p <^ '(5000,4000)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM quad_point_tbl WHERE p <^ '(5000, 4000)'; count @@ -298,12 +306,13 @@ SELECT count(*) FROM quad_point_tbl WHERE p <^ '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p >^ '(5000, 4000)'; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_quad_ind on quad_point_tbl Index Cond: (p >^ '(5000,4000)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM quad_point_tbl WHERE p >^ '(5000, 4000)'; count @@ -313,12 +322,13 @@ SELECT count(*) FROM quad_point_tbl WHERE p >^ '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p ~= '(4585, 365)'; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_quad_ind on quad_point_tbl Index Cond: (p ~= '(4585,365)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM quad_point_tbl WHERE p ~= '(4585, 365)'; count @@ -329,12 +339,13 @@ SELECT count(*) FROM quad_point_tbl WHERE p ~= '(4585, 365)'; EXPLAIN (COSTS OFF) SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p FROM quad_point_tbl; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- WindowAgg -> Index Only Scan using sp_quad_ind on quad_point_tbl Order By: (p <-> '(0,0)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) CREATE TEMP TABLE quad_point_tbl_ord_idx1 AS SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p @@ -349,13 +360,14 @@ WHERE seq.dist IS DISTINCT FROM idx.dist; EXPLAIN (COSTS OFF) SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p FROM quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- WindowAgg -> Index Only Scan using sp_quad_ind on quad_point_tbl Index Cond: (p <@ '(1000,1000),(200,200)'::box) Order By: (p <-> '(0,0)'::point) -(4 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(5 rows) CREATE TEMP TABLE quad_point_tbl_ord_idx2 AS SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p @@ -370,13 +382,14 @@ WHERE seq.dist IS DISTINCT FROM idx.dist; EXPLAIN (COSTS OFF) SELECT row_number() OVER (ORDER BY p <-> '333,400') n, p <-> '333,400' dist, p FROM quad_point_tbl WHERE p IS NOT NULL; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- WindowAgg -> Index Only Scan using sp_quad_ind on quad_point_tbl Index Cond: (p IS NOT NULL) Order By: (p <-> '(333,400)'::point) -(4 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(5 rows) CREATE TEMP TABLE quad_point_tbl_ord_idx3 AS SELECT row_number() OVER (ORDER BY p <-> '333,400') n, p <-> '333,400' dist, p @@ -390,12 +403,13 @@ WHERE seq.dist IS DISTINCT FROM idx.dist; EXPLAIN (COSTS OFF) SELECT count(*) FROM kd_point_tbl WHERE p <@ box '(200,200,1000,1000)'; - QUERY PLAN ---------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_kd_ind on kd_point_tbl Index Cond: (p <@ '(1000,1000),(200,200)'::box) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM kd_point_tbl WHERE p <@ box '(200,200,1000,1000)'; count @@ -405,12 +419,13 @@ SELECT count(*) FROM kd_point_tbl WHERE p <@ box '(200,200,1000,1000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM kd_point_tbl WHERE box '(200,200,1000,1000)' @> p; - QUERY PLAN ---------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_kd_ind on kd_point_tbl Index Cond: (p <@ '(1000,1000),(200,200)'::box) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM kd_point_tbl WHERE box '(200,200,1000,1000)' @> p; count @@ -420,12 +435,13 @@ SELECT count(*) FROM kd_point_tbl WHERE box '(200,200,1000,1000)' @> p; EXPLAIN (COSTS OFF) SELECT count(*) FROM kd_point_tbl WHERE p << '(5000, 4000)'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_kd_ind on kd_point_tbl Index Cond: (p << '(5000,4000)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM kd_point_tbl WHERE p << '(5000, 4000)'; count @@ -435,12 +451,13 @@ SELECT count(*) FROM kd_point_tbl WHERE p << '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM kd_point_tbl WHERE p >> '(5000, 4000)'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_kd_ind on kd_point_tbl Index Cond: (p >> '(5000,4000)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM kd_point_tbl WHERE p >> '(5000, 4000)'; count @@ -450,12 +467,13 @@ SELECT count(*) FROM kd_point_tbl WHERE p >> '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM kd_point_tbl WHERE p <^ '(5000, 4000)'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_kd_ind on kd_point_tbl Index Cond: (p <^ '(5000,4000)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM kd_point_tbl WHERE p <^ '(5000, 4000)'; count @@ -465,12 +483,13 @@ SELECT count(*) FROM kd_point_tbl WHERE p <^ '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM kd_point_tbl WHERE p >^ '(5000, 4000)'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_kd_ind on kd_point_tbl Index Cond: (p >^ '(5000,4000)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM kd_point_tbl WHERE p >^ '(5000, 4000)'; count @@ -480,12 +499,13 @@ SELECT count(*) FROM kd_point_tbl WHERE p >^ '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM kd_point_tbl WHERE p ~= '(4585, 365)'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_kd_ind on kd_point_tbl Index Cond: (p ~= '(4585,365)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM kd_point_tbl WHERE p ~= '(4585, 365)'; count @@ -496,12 +516,13 @@ SELECT count(*) FROM kd_point_tbl WHERE p ~= '(4585, 365)'; EXPLAIN (COSTS OFF) SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p FROM kd_point_tbl; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- WindowAgg -> Index Only Scan using sp_kd_ind on kd_point_tbl Order By: (p <-> '(0,0)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) CREATE TEMP TABLE kd_point_tbl_ord_idx1 AS SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p @@ -516,13 +537,14 @@ WHERE seq.dist IS DISTINCT FROM idx.dist; EXPLAIN (COSTS OFF) SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p FROM kd_point_tbl WHERE p <@ box '(200,200,1000,1000)'; - QUERY PLAN ---------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- WindowAgg -> Index Only Scan using sp_kd_ind on kd_point_tbl Index Cond: (p <@ '(1000,1000),(200,200)'::box) Order By: (p <-> '(0,0)'::point) -(4 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(5 rows) CREATE TEMP TABLE kd_point_tbl_ord_idx2 AS SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p @@ -537,13 +559,14 @@ WHERE seq.dist IS DISTINCT FROM idx.dist; EXPLAIN (COSTS OFF) SELECT row_number() OVER (ORDER BY p <-> '333,400') n, p <-> '333,400' dist, p FROM kd_point_tbl WHERE p IS NOT NULL; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- WindowAgg -> Index Only Scan using sp_kd_ind on kd_point_tbl Index Cond: (p IS NOT NULL) Order By: (p <-> '(333,400)'::point) -(4 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(5 rows) CREATE TEMP TABLE kd_point_tbl_ord_idx3 AS SELECT row_number() OVER (ORDER BY p <-> '333,400') n, p <-> '333,400' dist, p @@ -557,12 +580,13 @@ WHERE seq.dist IS DISTINCT FROM idx.dist; EXPLAIN (COSTS OFF) SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcdef'; - QUERY PLAN ------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t = 'P0123456789abcdef'::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcdef'; count @@ -572,12 +596,13 @@ SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcdef'; EXPLAIN (COSTS OFF) SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcde'; - QUERY PLAN ------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t = 'P0123456789abcde'::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcde'; count @@ -587,12 +612,13 @@ SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcde'; EXPLAIN (COSTS OFF) SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcdefF'; - QUERY PLAN ------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t = 'P0123456789abcdefF'::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcdefF'; count @@ -607,7 +633,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t < 'Aztec Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t < 'Aztec Ct '::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t < 'Aztec Ct '; count @@ -622,7 +649,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t ~<~ 'Aztec Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t ~<~ 'Aztec Ct '::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t ~<~ 'Aztec Ct '; count @@ -637,7 +665,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t <= 'Aztec Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t <= 'Aztec Ct '::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t <= 'Aztec Ct '; count @@ -652,7 +681,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t ~<=~ 'Aztec Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t ~<=~ 'Aztec Ct '::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t ~<=~ 'Aztec Ct '; count @@ -667,7 +697,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t = 'Aztec Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t = 'Aztec Ct '::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t = 'Aztec Ct '; count @@ -682,7 +713,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t = 'Worth Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t = 'Worth St '::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t = 'Worth St '; count @@ -697,7 +729,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t >= 'Worth Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t >= 'Worth St '::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t >= 'Worth St '; count @@ -712,7 +745,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t ~>=~ 'Worth Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t ~>=~ 'Worth St '::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t ~>=~ 'Worth St '; count @@ -727,7 +761,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t > 'Worth Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t > 'Worth St '::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t > 'Worth St '; count @@ -742,7 +777,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t ~>~ 'Worth Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t ~>~ 'Worth St '::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t ~>~ 'Worth St '; count @@ -752,12 +788,13 @@ SELECT count(*) FROM radix_text_tbl WHERE t ~>~ 'Worth EXPLAIN (COSTS OFF) SELECT count(*) FROM radix_text_tbl WHERE t ^@ 'Worth'; - QUERY PLAN ------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Only Scan using sp_radix_ind on radix_text_tbl Index Cond: (t ^@ 'Worth'::text) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM radix_text_tbl WHERE t ^@ 'Worth'; count @@ -771,14 +808,15 @@ SET enable_indexscan = OFF; SET enable_bitmapscan = ON; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p IS NULL; - QUERY PLAN ----------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on quad_point_tbl Recheck Cond: (p IS NULL) -> Bitmap Index Scan on sp_quad_ind Index Cond: (p IS NULL) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_point_tbl WHERE p IS NULL; count @@ -788,14 +826,15 @@ SELECT count(*) FROM quad_point_tbl WHERE p IS NULL; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p IS NOT NULL; - QUERY PLAN ----------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on quad_point_tbl Recheck Cond: (p IS NOT NULL) -> Bitmap Index Scan on sp_quad_ind Index Cond: (p IS NOT NULL) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_point_tbl WHERE p IS NOT NULL; count @@ -805,12 +844,13 @@ SELECT count(*) FROM quad_point_tbl WHERE p IS NOT NULL; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl; - QUERY PLAN ----------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on quad_point_tbl -> Bitmap Index Scan on sp_quad_ind -(3 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM quad_point_tbl; count @@ -827,7 +867,8 @@ SELECT count(*) FROM quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; Recheck Cond: (p <@ '(1000,1000),(200,200)'::box) -> Bitmap Index Scan on sp_quad_ind Index Cond: (p <@ '(1000,1000),(200,200)'::box) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; count @@ -844,7 +885,8 @@ SELECT count(*) FROM quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; Recheck Cond: ('(1000,1000),(200,200)'::box @> p) -> Bitmap Index Scan on sp_quad_ind Index Cond: (p <@ '(1000,1000),(200,200)'::box) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; count @@ -854,14 +896,15 @@ SELECT count(*) FROM quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p << '(5000, 4000)'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on quad_point_tbl Recheck Cond: (p << '(5000,4000)'::point) -> Bitmap Index Scan on sp_quad_ind Index Cond: (p << '(5000,4000)'::point) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_point_tbl WHERE p << '(5000, 4000)'; count @@ -871,14 +914,15 @@ SELECT count(*) FROM quad_point_tbl WHERE p << '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p >> '(5000, 4000)'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on quad_point_tbl Recheck Cond: (p >> '(5000,4000)'::point) -> Bitmap Index Scan on sp_quad_ind Index Cond: (p >> '(5000,4000)'::point) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_point_tbl WHERE p >> '(5000, 4000)'; count @@ -888,14 +932,15 @@ SELECT count(*) FROM quad_point_tbl WHERE p >> '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p <^ '(5000, 4000)'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on quad_point_tbl Recheck Cond: (p <^ '(5000,4000)'::point) -> Bitmap Index Scan on sp_quad_ind Index Cond: (p <^ '(5000,4000)'::point) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_point_tbl WHERE p <^ '(5000, 4000)'; count @@ -905,14 +950,15 @@ SELECT count(*) FROM quad_point_tbl WHERE p <^ '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p >^ '(5000, 4000)'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on quad_point_tbl Recheck Cond: (p >^ '(5000,4000)'::point) -> Bitmap Index Scan on sp_quad_ind Index Cond: (p >^ '(5000,4000)'::point) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_point_tbl WHERE p >^ '(5000, 4000)'; count @@ -922,14 +968,15 @@ SELECT count(*) FROM quad_point_tbl WHERE p >^ '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM quad_point_tbl WHERE p ~= '(4585, 365)'; - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on quad_point_tbl Recheck Cond: (p ~= '(4585,365)'::point) -> Bitmap Index Scan on sp_quad_ind Index Cond: (p ~= '(4585,365)'::point) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_point_tbl WHERE p ~= '(4585, 365)'; count @@ -946,7 +993,8 @@ SELECT count(*) FROM kd_point_tbl WHERE p <@ box '(200,200,1000,1000)'; Recheck Cond: (p <@ '(1000,1000),(200,200)'::box) -> Bitmap Index Scan on sp_kd_ind Index Cond: (p <@ '(1000,1000),(200,200)'::box) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM kd_point_tbl WHERE p <@ box '(200,200,1000,1000)'; count @@ -963,7 +1011,8 @@ SELECT count(*) FROM kd_point_tbl WHERE box '(200,200,1000,1000)' @> p; Recheck Cond: ('(1000,1000),(200,200)'::box @> p) -> Bitmap Index Scan on sp_kd_ind Index Cond: (p <@ '(1000,1000),(200,200)'::box) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM kd_point_tbl WHERE box '(200,200,1000,1000)' @> p; count @@ -973,14 +1022,15 @@ SELECT count(*) FROM kd_point_tbl WHERE box '(200,200,1000,1000)' @> p; EXPLAIN (COSTS OFF) SELECT count(*) FROM kd_point_tbl WHERE p << '(5000, 4000)'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on kd_point_tbl Recheck Cond: (p << '(5000,4000)'::point) -> Bitmap Index Scan on sp_kd_ind Index Cond: (p << '(5000,4000)'::point) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM kd_point_tbl WHERE p << '(5000, 4000)'; count @@ -990,14 +1040,15 @@ SELECT count(*) FROM kd_point_tbl WHERE p << '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM kd_point_tbl WHERE p >> '(5000, 4000)'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on kd_point_tbl Recheck Cond: (p >> '(5000,4000)'::point) -> Bitmap Index Scan on sp_kd_ind Index Cond: (p >> '(5000,4000)'::point) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM kd_point_tbl WHERE p >> '(5000, 4000)'; count @@ -1007,14 +1058,15 @@ SELECT count(*) FROM kd_point_tbl WHERE p >> '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM kd_point_tbl WHERE p <^ '(5000, 4000)'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on kd_point_tbl Recheck Cond: (p <^ '(5000,4000)'::point) -> Bitmap Index Scan on sp_kd_ind Index Cond: (p <^ '(5000,4000)'::point) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM kd_point_tbl WHERE p <^ '(5000, 4000)'; count @@ -1024,14 +1076,15 @@ SELECT count(*) FROM kd_point_tbl WHERE p <^ '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM kd_point_tbl WHERE p >^ '(5000, 4000)'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on kd_point_tbl Recheck Cond: (p >^ '(5000,4000)'::point) -> Bitmap Index Scan on sp_kd_ind Index Cond: (p >^ '(5000,4000)'::point) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM kd_point_tbl WHERE p >^ '(5000, 4000)'; count @@ -1041,14 +1094,15 @@ SELECT count(*) FROM kd_point_tbl WHERE p >^ '(5000, 4000)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM kd_point_tbl WHERE p ~= '(4585, 365)'; - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on kd_point_tbl Recheck Cond: (p ~= '(4585,365)'::point) -> Bitmap Index Scan on sp_kd_ind Index Cond: (p ~= '(4585,365)'::point) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM kd_point_tbl WHERE p ~= '(4585, 365)'; count @@ -1058,14 +1112,15 @@ SELECT count(*) FROM kd_point_tbl WHERE p ~= '(4585, 365)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcdef'; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on radix_text_tbl Recheck Cond: (t = 'P0123456789abcdef'::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t = 'P0123456789abcdef'::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcdef'; count @@ -1075,14 +1130,15 @@ SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcdef'; EXPLAIN (COSTS OFF) SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcde'; - QUERY PLAN ----------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on radix_text_tbl Recheck Cond: (t = 'P0123456789abcde'::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t = 'P0123456789abcde'::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcde'; count @@ -1099,7 +1155,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcdefF'; Recheck Cond: (t = 'P0123456789abcdefF'::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t = 'P0123456789abcdefF'::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t = 'P0123456789abcdefF'; count @@ -1116,7 +1173,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t < 'Aztec Recheck Cond: (t < 'Aztec Ct '::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t < 'Aztec Ct '::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t < 'Aztec Ct '; count @@ -1133,7 +1191,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t ~<~ 'Aztec Recheck Cond: (t ~<~ 'Aztec Ct '::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t ~<~ 'Aztec Ct '::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t ~<~ 'Aztec Ct '; count @@ -1150,7 +1209,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t <= 'Aztec Recheck Cond: (t <= 'Aztec Ct '::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t <= 'Aztec Ct '::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t <= 'Aztec Ct '; count @@ -1167,7 +1227,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t ~<=~ 'Aztec Recheck Cond: (t ~<=~ 'Aztec Ct '::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t ~<=~ 'Aztec Ct '::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t ~<=~ 'Aztec Ct '; count @@ -1184,7 +1245,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t = 'Aztec Recheck Cond: (t = 'Aztec Ct '::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t = 'Aztec Ct '::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t = 'Aztec Ct '; count @@ -1201,7 +1263,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t = 'Worth Recheck Cond: (t = 'Worth St '::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t = 'Worth St '::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t = 'Worth St '; count @@ -1218,7 +1281,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t >= 'Worth Recheck Cond: (t >= 'Worth St '::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t >= 'Worth St '::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t >= 'Worth St '; count @@ -1235,7 +1299,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t ~>=~ 'Worth Recheck Cond: (t ~>=~ 'Worth St '::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t ~>=~ 'Worth St '::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t ~>=~ 'Worth St '; count @@ -1252,7 +1317,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t > 'Worth Recheck Cond: (t > 'Worth St '::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t > 'Worth St '::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t > 'Worth St '; count @@ -1269,7 +1335,8 @@ SELECT count(*) FROM radix_text_tbl WHERE t ~>~ 'Worth Recheck Cond: (t ~>~ 'Worth St '::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t ~>~ 'Worth St '::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t ~>~ 'Worth St '; count @@ -1279,14 +1346,15 @@ SELECT count(*) FROM radix_text_tbl WHERE t ~>~ 'Worth EXPLAIN (COSTS OFF) SELECT count(*) FROM radix_text_tbl WHERE t ^@ 'Worth'; - QUERY PLAN ------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Aggregate -> Bitmap Heap Scan on radix_text_tbl Recheck Cond: (t ^@ 'Worth'::text) -> Bitmap Index Scan on sp_radix_ind Index Cond: (t ^@ 'Worth'::text) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM radix_text_tbl WHERE t ^@ 'Worth'; count diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out index e367ea2571..1ac8427c04 100644 --- a/src/test/regress/expected/create_view.out +++ b/src/test/regress/expected/create_view.out @@ -1602,7 +1602,8 @@ explain (costs off) select * from tt18v; Append -> Seq Scan on int8_tbl xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -> Seq Scan on int8_tbl xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_1 -(3 rows) + Settings: search_path = 'testviewschm2, public' +(4 rows) -- check display of ScalarArrayOp with a sub-select select 'foo'::text = any(array['abc','def','foo']::text[]); diff --git a/src/test/regress/expected/equivclass.out b/src/test/regress/expected/equivclass.out index c448d85dec..e15374d72b 100644 --- a/src/test/regress/expected/equivclass.out +++ b/src/test/regress/expected/equivclass.out @@ -104,38 +104,42 @@ set enable_mergejoin = off; -- explain (costs off) select * from ec0 where ff = f1 and f1 = '42'::int8; - QUERY PLAN ------------------------------------ + QUERY PLAN +------------------------------------------------------------- Index Scan using ec0_pkey on ec0 Index Cond: (ff = '42'::bigint) Filter: (f1 = '42'::bigint) -(3 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(4 rows) explain (costs off) select * from ec0 where ff = f1 and f1 = '42'::int8alias1; - QUERY PLAN ---------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Scan using ec0_pkey on ec0 Index Cond: (ff = '42'::int8alias1) Filter: (f1 = '42'::int8alias1) -(3 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(4 rows) explain (costs off) select * from ec1 where ff = f1 and f1 = '42'::int8alias1; - QUERY PLAN ---------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Scan using ec1_pkey on ec1 Index Cond: (ff = '42'::int8alias1) Filter: (f1 = '42'::int8alias1) -(3 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(4 rows) explain (costs off) select * from ec1 where ff = f1 and f1 = '42'::int8alias2; - QUERY PLAN ---------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Seq Scan on ec1 Filter: ((ff = f1) AND (f1 = '42'::int8alias2)) -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) explain (costs off) select * from ec1, ec2 where ff = x1 and ff = '42'::int8; @@ -146,52 +150,57 @@ explain (costs off) -> Index Scan using ec1_pkey on ec1 Index Cond: ((ff = '42'::bigint) AND (ff = '42'::bigint)) -> Seq Scan on ec2 -(5 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(6 rows) explain (costs off) select * from ec1, ec2 where ff = x1 and ff = '42'::int8alias1; - QUERY PLAN ---------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Nested Loop -> Index Scan using ec1_pkey on ec1 Index Cond: (ff = '42'::int8alias1) -> Seq Scan on ec2 Filter: (x1 = '42'::int8alias1) -(5 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(6 rows) explain (costs off) select * from ec1, ec2 where ff = x1 and '42'::int8 = x1; - QUERY PLAN ------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Nested Loop Join Filter: (ec1.ff = ec2.x1) -> Index Scan using ec1_pkey on ec1 Index Cond: (ff = '42'::bigint) -> Seq Scan on ec2 Filter: ('42'::bigint = x1) -(6 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(7 rows) explain (costs off) select * from ec1, ec2 where ff = x1 and x1 = '42'::int8alias1; - QUERY PLAN ---------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Nested Loop -> Index Scan using ec1_pkey on ec1 Index Cond: (ff = '42'::int8alias1) -> Seq Scan on ec2 Filter: (x1 = '42'::int8alias1) -(5 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(6 rows) explain (costs off) select * from ec1, ec2 where ff = x1 and x1 = '42'::int8alias2; - QUERY PLAN ------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Nested Loop -> Seq Scan on ec2 Filter: (x1 = '42'::int8alias2) -> Index Scan using ec1_pkey on ec1 Index Cond: (ff = ec2.x1) -(5 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(6 rows) create unique index ec1_expr1 on ec1((ff + 1)); create unique index ec1_expr2 on ec1((ff + 2 + 1)); @@ -206,8 +215,8 @@ explain (costs off) union all select ff + 4 as x from ec1) as ss1 where ss1.x = ec1.f1 and ec1.ff = 42::int8; - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Nested Loop -> Index Scan using ec1_pkey on ec1 Index Cond: (ff = '42'::bigint) @@ -218,7 +227,8 @@ explain (costs off) Index Cond: (((ff + 3) + 1) = ec1.f1) -> Index Scan using ec1_expr4 on ec1 ec1_3 Index Cond: ((ff + 4) = ec1.f1) -(10 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(11 rows) explain (costs off) select * from ec1, @@ -243,7 +253,8 @@ explain (costs off) Index Cond: (((ff + 3) + 1) = '42'::bigint) -> Index Scan using ec1_expr4 on ec1 ec1_3 Index Cond: ((ff + 4) = '42'::bigint) -(12 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(13 rows) explain (costs off) select * from ec1, @@ -280,7 +291,8 @@ explain (costs off) Index Cond: (((ff + 3) + 1) = (((ec1_1.ff + 2) + 1))) -> Index Scan using ec1_expr4 on ec1 ec1_6 Index Cond: ((ff + 4) = (((ec1_1.ff + 2) + 1))) -(18 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(19 rows) -- let's try that as a mergejoin set enable_mergejoin = on; @@ -321,7 +333,8 @@ explain (costs off) Sort Key: ec1.f1 USING < -> Index Scan using ec1_pkey on ec1 Index Cond: (ff = '42'::bigint) -(19 rows) + Settings: enable_hashjoin = 'off', enable_nestloop = 'off' +(20 rows) -- check partially indexed scan set enable_nestloop = on; @@ -336,8 +349,8 @@ explain (costs off) union all select ff + 4 as x from ec1) as ss1 where ss1.x = ec1.f1 and ec1.ff = 42::int8; - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------- Nested Loop -> Index Scan using ec1_pkey on ec1 Index Cond: (ff = '42'::bigint) @@ -348,7 +361,8 @@ explain (costs off) Filter: (((ff + 3) + 1) = ec1.f1) -> Index Scan using ec1_expr4 on ec1 ec1_3 Index Cond: ((ff + 4) = ec1.f1) -(10 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(11 rows) -- let's try that as a mergejoin set enable_mergejoin = on; @@ -362,8 +376,8 @@ explain (costs off) union all select ff + 4 as x from ec1) as ss1 where ss1.x = ec1.f1 and ec1.ff = 42::int8; - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------ Merge Join Merge Cond: ((((ec1_1.ff + 2) + 1)) = ec1.f1) -> Merge Append @@ -377,7 +391,8 @@ explain (costs off) Sort Key: ec1.f1 USING < -> Index Scan using ec1_pkey on ec1 Index Cond: (ff = '42'::bigint) -(13 rows) + Settings: enable_hashjoin = 'off', enable_nestloop = 'off' +(14 rows) -- check effects of row-level security set enable_nestloop = on; @@ -391,14 +406,15 @@ grant select on ec1 to regress_user_ectest; explain (costs off) select * from ec0 a, ec1 b where a.ff = b.ff and a.ff = 43::bigint::int8alias1; - QUERY PLAN ---------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Nested Loop -> Index Scan using ec0_pkey on ec0 a Index Cond: (ff = '43'::int8alias1) -> Index Scan using ec1_pkey on ec1 b Index Cond: (ff = '43'::int8alias1) -(5 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(6 rows) set session authorization regress_user_ectest; -- with RLS active, the non-leakproof a.ff = 43 clause is not treated @@ -407,15 +423,16 @@ set session authorization regress_user_ectest; explain (costs off) select * from ec0 a, ec1 b where a.ff = b.ff and a.ff = 43::bigint::int8alias1; - QUERY PLAN ---------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Nested Loop -> Index Scan using ec0_pkey on ec0 a Index Cond: (ff = '43'::int8alias1) -> Index Scan using ec1_pkey on ec1 b Index Cond: (ff = a.ff) Filter: (f1 < '5'::int8alias1) -(6 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(7 rows) reset session authorization; revoke select on ec0 from regress_user_ectest; @@ -428,14 +445,16 @@ explain (costs off) ------------------------------------------------------------- Seq Scan on tenk1 Filter: ((unique1 IS NOT NULL) AND (unique2 IS NOT NULL)) -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) -- this could be converted, but isn't at present explain (costs off) select * from tenk1 where unique1 = unique1 or unique2 = unique2; - QUERY PLAN --------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Seq Scan on tenk1 Filter: ((unique1 = unique1) OR (unique2 = unique2)) -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) diff --git a/src/test/regress/expected/fast_default.out b/src/test/regress/expected/fast_default.out index 10bc5ff757..261bd47805 100644 --- a/src/test/regress/expected/fast_default.out +++ b/src/test/regress/expected/fast_default.out @@ -302,7 +302,8 @@ SELECT c_bigint, c_text FROM T WHERE c_bigint = -1 LIMIT 1; -> Seq Scan on fast_default.t Output: c_bigint, c_text Filter: (t.c_bigint = '-1'::integer) -(5 rows) + Settings: search_path = 'fast_default' +(6 rows) SELECT c_bigint, c_text FROM T WHERE c_text = 'hello' LIMIT 1; c_bigint | c_text @@ -318,7 +319,8 @@ EXPLAIN (VERBOSE TRUE, COSTS FALSE) SELECT c_bigint, c_text FROM T WHERE c_text -> Seq Scan on fast_default.t Output: c_bigint, c_text Filter: (t.c_text = 'hello'::text) -(5 rows) + Settings: search_path = 'fast_default' +(6 rows) -- COALESCE SELECT COALESCE(c_bigint, pk), COALESCE(c_text, pk::text) @@ -372,7 +374,8 @@ SELECT * FROM T ORDER BY c_bigint, c_text, pk LIMIT 10; Sort Key: t.c_bigint, t.c_text, t.pk -> Seq Scan on fast_default.t Output: pk, c_bigint, c_text -(7 rows) + Settings: search_path = 'fast_default' +(8 rows) -- LIMIT SELECT * FROM T WHERE c_bigint > -1 ORDER BY c_bigint, c_text, pk LIMIT 10; @@ -402,7 +405,8 @@ SELECT * FROM T WHERE c_bigint > -1 ORDER BY c_bigint, c_text, pk LIMIT 10; -> Seq Scan on fast_default.t Output: pk, c_bigint, c_text Filter: (t.c_bigint > '-1'::integer) -(8 rows) + Settings: search_path = 'fast_default' +(9 rows) -- DELETE with RETURNING DELETE FROM T WHERE pk BETWEEN 10 AND 20 RETURNING *; @@ -432,7 +436,8 @@ DELETE FROM T WHERE pk BETWEEN 10 AND 20 RETURNING *; Recheck Cond: ((t.pk >= 10) AND (t.pk <= 20)) -> Bitmap Index Scan on t_pkey Index Cond: ((t.pk >= 10) AND (t.pk <= 20)) -(7 rows) + Settings: search_path = 'fast_default' +(8 rows) -- UPDATE UPDATE T SET c_text = '"' || c_text || '"' WHERE pk < 10; diff --git a/src/test/regress/expected/generated.out b/src/test/regress/expected/generated.out index d4ed3f7ae1..bb14be3b14 100644 --- a/src/test/regress/expected/generated.out +++ b/src/test/regress/expected/generated.out @@ -436,11 +436,12 @@ INSERT INTO gtest22c VALUES (1), (2), (3); SET enable_seqscan TO off; SET enable_bitmapscan TO off; EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b = 4; - QUERY PLAN ---------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Scan using gtest22c_b_idx on gtest22c Index Cond: (b = 4) -(2 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(3 rows) SELECT * FROM gtest22c WHERE b = 4; a | b @@ -449,11 +450,12 @@ SELECT * FROM gtest22c WHERE b = 4; (1 row) EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b * 3 = 6; - QUERY PLAN ------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Scan using gtest22c_expr_idx on gtest22c Index Cond: ((b * 3) = 6) -(2 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(3 rows) SELECT * FROM gtest22c WHERE b * 3 = 6; a | b @@ -462,11 +464,12 @@ SELECT * FROM gtest22c WHERE b * 3 = 6; (1 row) EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE a = 1 AND b > 0; - QUERY PLAN ------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Scan using gtest22c_pred_idx on gtest22c Index Cond: (a = 1) -(2 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(3 rows) SELECT * FROM gtest22c WHERE a = 1 AND b > 0; a | b diff --git a/src/test/regress/expected/gist.out b/src/test/regress/expected/gist.out index 0a43449f00..f716b4825e 100644 --- a/src/test/regress/expected/gist.out +++ b/src/test/regress/expected/gist.out @@ -51,11 +51,12 @@ create index gist_tbl_point_index on gist_tbl using gist (p); -- check that the planner chooses an index-only scan explain (costs off) select p from gist_tbl where p <@ box(point(0,0), point(0.5, 0.5)); - QUERY PLAN --------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Only Scan using gist_tbl_point_index on gist_tbl Index Cond: (p <@ '(0.5,0.5),(0,0)'::box) -(2 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(3 rows) -- execute the same select p from gist_tbl where p <@ box(point(0,0), point(0.5, 0.5)); @@ -78,12 +79,13 @@ select p from gist_tbl where p <@ box(point(0,0), point(0.5, 0.5)); explain (costs off) select p from gist_tbl where p <@ box(point(0,0), point(0.5, 0.5)) order by p <-> point(0.201, 0.201); - QUERY PLAN --------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Only Scan using gist_tbl_point_index on gist_tbl Index Cond: (p <@ '(0.5,0.5),(0,0)'::box) Order By: (p <-> '(0.201,0.201)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) select p from gist_tbl where p <@ box(point(0,0), point(0.5, 0.5)) order by p <-> point(0.201, 0.201); @@ -106,12 +108,13 @@ order by p <-> point(0.201, 0.201); explain (costs off) select p from gist_tbl where p <@ box(point(0,0), point(0.5, 0.5)) order by point(0.101, 0.101) <-> p; - QUERY PLAN --------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Only Scan using gist_tbl_point_index on gist_tbl Index Cond: (p <@ '(0.5,0.5),(0,0)'::box) Order By: (p <-> '(0.101,0.101)'::point) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) select p from gist_tbl where p <@ box(point(0,0), point(0.5, 0.5)) order by point(0.101, 0.101) <-> p; @@ -146,7 +149,8 @@ cross join lateral -> Index Only Scan using gist_tbl_point_index on gist_tbl Index Cond: (p <@ "*VALUES*".column1) Order By: (p <-> ("*VALUES*".column1)[0]) -(6 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(7 rows) select p from (values (box(point(0,0), point(0.5,0.5))), @@ -170,11 +174,12 @@ create index gist_tbl_box_index on gist_tbl using gist (b); -- check that the planner chooses an index-only scan explain (costs off) select b from gist_tbl where b <@ box(point(5,5), point(6,6)); - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Only Scan using gist_tbl_box_index on gist_tbl Index Cond: (b <@ '(6,6),(5,5)'::box) -(2 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(3 rows) -- execute the same select b from gist_tbl where b <@ box(point(5,5), point(6,6)); @@ -210,11 +215,12 @@ create index gist_tbl_multi_index on gist_tbl using gist (p, c); explain (costs off) select p, c from gist_tbl where p <@ box(point(5,5), point(6, 6)); - QUERY PLAN ---------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Index Scan using gist_tbl_multi_index on gist_tbl Index Cond: (p <@ '(6,6),(5,5)'::box) -(2 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(3 rows) -- execute the same select b, p from gist_tbl diff --git a/src/test/regress/expected/groupingsets.out b/src/test/regress/expected/groupingsets.out index 381ebce8a1..792ca82443 100644 --- a/src/test/regress/expected/groupingsets.out +++ b/src/test/regress/expected/groupingsets.out @@ -374,7 +374,8 @@ select g as alias1, g as alias2 -> Sort Sort Key: g -> Function Scan on generate_series g -(6 rows) + Settings: enable_hashagg = 'off' +(7 rows) select g as alias1, g as alias2 from generate_series(1,3) g @@ -467,7 +468,8 @@ explain (costs off) -> Limit -> Index Only Scan using tenk1_unique1 on tenk1 Index Cond: (unique1 IS NOT NULL) -(5 rows) + Settings: enable_hashagg = 'off' +(6 rows) -- Views with GROUPING SET queries CREATE VIEW gstest_view AS select a, b, grouping(a,b), sum(c), count(*), max(c) @@ -716,7 +718,8 @@ explain (costs off) -> Sort Sort Key: a -> Seq Scan on gstest2 -(7 rows) + Settings: enable_hashagg = 'off' +(8 rows) select v.c, (select count(*) from gstest2 group by () having v.c) from (values (false),(true)) v(c) order by v.c; @@ -741,7 +744,8 @@ explain (costs off) -> Result One-Time Filter: "*VALUES*".column1 -> Seq Scan on gstest2 -(10 rows) + Settings: enable_hashagg = 'off' +(11 rows) -- HAVING with GROUPING queries select ten, grouping(ten) from onek @@ -1481,8 +1485,8 @@ explain (costs off) count(hundred), count(thousand), count(twothousand), count(*) from tenk1 group by grouping sets (unique1,twothousand,thousand,hundred,ten,four,two); - QUERY PLAN -------------------------------- + QUERY PLAN +------------------------------------------------------- MixedAggregate Hash Key: two Hash Key: four @@ -1496,7 +1500,8 @@ explain (costs off) -> Sort Sort Key: unique1 -> Seq Scan on tenk1 -(13 rows) + Settings: enable_indexscan = 'off', work_mem = '64kB' +(14 rows) explain (costs off) select unique1, @@ -1504,8 +1509,8 @@ explain (costs off) count(hundred), count(thousand), count(twothousand), count(*) from tenk1 group by grouping sets (unique1,hundred,ten,four,two); - QUERY PLAN -------------------------------- + QUERY PLAN +------------------------------------------------------- MixedAggregate Hash Key: two Hash Key: four @@ -1515,7 +1520,8 @@ explain (costs off) -> Sort Sort Key: unique1 -> Seq Scan on tenk1 -(9 rows) + Settings: enable_indexscan = 'off', work_mem = '64kB' +(10 rows) set work_mem = '384kB'; explain (costs off) @@ -1524,8 +1530,8 @@ explain (costs off) count(hundred), count(thousand), count(twothousand), count(*) from tenk1 group by grouping sets (unique1,twothousand,thousand,hundred,ten,four,two); - QUERY PLAN -------------------------------- + QUERY PLAN +-------------------------------------------------------- MixedAggregate Hash Key: two Hash Key: four @@ -1538,7 +1544,8 @@ explain (costs off) -> Sort Sort Key: unique1 -> Seq Scan on tenk1 -(12 rows) + Settings: enable_indexscan = 'off', work_mem = '384kB' +(13 rows) -- check collation-sensitive matching between grouping expressions -- (similar to a check for aggregates, but there are additional code diff --git a/src/test/regress/expected/index_including.out b/src/test/regress/expected/index_including.out index 2405709f40..0b712c289c 100644 --- a/src/test/regress/expected/index_including.out +++ b/src/test/regress/expected/index_including.out @@ -154,7 +154,8 @@ select * from tbl where (c1,c2,c3) < (262,1,1) limit 1; -> Index Only Scan using covering on tbl Index Cond: (ROW(c1, c2) <= ROW(262, 1)) Filter: (ROW(c1, c2, c3) < ROW(262, 1, 1)) -(4 rows) + Settings: enable_seqscan = 'off' +(5 rows) select * from tbl where (c1,c2,c3) < (262,1,1) limit 1; c1 | c2 | c3 | c4 diff --git a/src/test/regress/expected/index_including_gist.out b/src/test/regress/expected/index_including_gist.out index ed9906da66..f013380ce9 100644 --- a/src/test/regress/expected/index_including_gist.out +++ b/src/test/regress/expected/index_including_gist.out @@ -29,7 +29,8 @@ EXPLAIN (costs off) SELECT * FROM tbl_gist where c4 <@ box(point(1,1),point(10, ------------------------------------------------ Index Only Scan using tbl_gist_idx on tbl_gist Index Cond: (c4 <@ '(10,10),(1,1)'::box) -(2 rows) + Settings: enable_bitmapscan = 'off' +(3 rows) SET enable_bitmapscan TO default; DROP TABLE tbl_gist; @@ -64,7 +65,8 @@ EXPLAIN (costs off) SELECT * FROM tbl_gist where c4 <@ box(point(1,1),point(10, ------------------------------------------------ Index Only Scan using tbl_gist_idx on tbl_gist Index Cond: (c4 <@ '(10,10),(1,1)'::box) -(2 rows) + Settings: enable_bitmapscan = 'off' +(3 rows) SET enable_bitmapscan TO default; DROP TABLE tbl_gist; diff --git a/src/test/regress/expected/inet.out b/src/test/regress/expected/inet.out index 24202376f1..58af8d5564 100644 --- a/src/test/regress/expected/inet.out +++ b/src/test/regress/expected/inet.out @@ -249,7 +249,8 @@ SELECT * FROM inet_tbl WHERE i<<'192.168.1.0/24'::cidr; Index Scan using inet_idx1 on inet_tbl Index Cond: ((i > '192.168.1.0/24'::inet) AND (i <= '192.168.1.255'::inet)) Filter: (i << '192.168.1.0/24'::inet) -(3 rows) + Settings: enable_seqscan = 'off' +(4 rows) SELECT * FROM inet_tbl WHERE i<<'192.168.1.0/24'::cidr; c | i @@ -266,7 +267,8 @@ SELECT * FROM inet_tbl WHERE i<<='192.168.1.0/24'::cidr; Index Scan using inet_idx1 on inet_tbl Index Cond: ((i >= '192.168.1.0/24'::inet) AND (i <= '192.168.1.255'::inet)) Filter: (i <<= '192.168.1.0/24'::inet) -(3 rows) + Settings: enable_seqscan = 'off' +(4 rows) SELECT * FROM inet_tbl WHERE i<<='192.168.1.0/24'::cidr; c | i @@ -286,7 +288,8 @@ SELECT * FROM inet_tbl WHERE '192.168.1.0/24'::cidr >>= i; Index Scan using inet_idx1 on inet_tbl Index Cond: ((i >= '192.168.1.0/24'::inet) AND (i <= '192.168.1.255'::inet)) Filter: ('192.168.1.0/24'::inet >>= i) -(3 rows) + Settings: enable_seqscan = 'off' +(4 rows) SELECT * FROM inet_tbl WHERE '192.168.1.0/24'::cidr >>= i; c | i @@ -306,7 +309,8 @@ SELECT * FROM inet_tbl WHERE '192.168.1.0/24'::cidr >> i; Index Scan using inet_idx1 on inet_tbl Index Cond: ((i > '192.168.1.0/24'::inet) AND (i <= '192.168.1.255'::inet)) Filter: ('192.168.1.0/24'::inet >> i) -(3 rows) + Settings: enable_seqscan = 'off' +(4 rows) SELECT * FROM inet_tbl WHERE '192.168.1.0/24'::cidr >> i; c | i @@ -454,7 +458,8 @@ SELECT i FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i; Sort Key: i -> Index Only Scan using inet_idx2 on inet_tbl Index Cond: (i << '192.168.1.0/24'::inet) -(4 rows) + Settings: enable_seqscan = 'off' +(5 rows) SELECT i FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i; i @@ -602,7 +607,8 @@ SELECT i FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i; Sort Key: i -> Index Only Scan using inet_idx3 on inet_tbl Index Cond: (i << '192.168.1.0/24'::inet) -(4 rows) + Settings: enable_seqscan = 'off' +(5 rows) SELECT i FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i; i diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out index c6abcfc3cb..a30ff26734 100644 --- a/src/test/regress/expected/inherit.out +++ b/src/test/regress/expected/inherit.out @@ -1411,7 +1411,8 @@ explain (verbose, costs off) select * from matest0 order by 1-id; Output: matest2.id, matest2.name -> Seq Scan on public.matest3 Output: matest3.id, matest3.name -(14 rows) + Settings: enable_indexscan = 'off' +(15 rows) select * from matest0 order by 1-id; id | name @@ -1438,7 +1439,8 @@ explain (verbose, costs off) select min(1-id) from matest0; Output: matest2.id -> Seq Scan on public.matest3 Output: matest3.id -(11 rows) + Settings: enable_indexscan = 'off' +(12 rows) select min(1-id) from matest0; min @@ -1465,7 +1467,8 @@ explain (verbose, costs off) select * from matest0 order by 1-id; Output: matest2.id, matest2.name, (1 - matest2.id) -> Index Scan using matest3i on public.matest3 Output: matest3.id, matest3.name, (1 - matest3.id) -(13 rows) + Settings: enable_parallel_append = 'off', enable_seqscan = 'off' +(14 rows) select * from matest0 order by 1-id; id | name @@ -1506,7 +1509,8 @@ explain (verbose, costs off) select min(1-id) from matest0; -> Index Scan using matest3i on public.matest3 Output: matest3.id, (1 - matest3.id) Index Cond: ((1 - matest3.id) IS NOT NULL) -(25 rows) + Settings: enable_parallel_append = 'off', enable_seqscan = 'off' +(26 rows) select min(1-id) from matest0; min @@ -1550,7 +1554,8 @@ order by t1.b limit 10; Filter: (c = d) -> Index Scan using matest1i on matest1 t2_1 Filter: (c = d) -(14 rows) + Settings: enable_nestloop = 'off' +(15 rows) reset enable_nestloop; drop table matest0 cascade; @@ -1575,7 +1580,8 @@ ORDER BY thousand, tenthous; -> Sort Sort Key: tenk1_1.thousand, tenk1_1.thousand -> Index Only Scan using tenk1_thous_tenthous on tenk1 tenk1_1 -(6 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(7 rows) explain (costs off) SELECT thousand, tenthous, thousand+tenthous AS x FROM tenk1 @@ -1590,7 +1596,8 @@ ORDER BY thousand, tenthous; -> Sort Sort Key: 42, 42 -> Index Only Scan using tenk1_hundred on tenk1 tenk1_1 -(6 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(7 rows) explain (costs off) SELECT thousand, tenthous FROM tenk1 @@ -1605,7 +1612,8 @@ ORDER BY thousand, tenthous; -> Sort Sort Key: tenk1_1.thousand, ((random())::integer) -> Index Only Scan using tenk1_thous_tenthous on tenk1 tenk1_1 -(6 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(7 rows) -- Check min/max aggregate optimization explain (costs off) @@ -1624,7 +1632,8 @@ SELECT min(x) FROM Index Cond: (unique1 IS NOT NULL) -> Index Only Scan using tenk1_unique2 on tenk1 b Index Cond: (unique2 IS NOT NULL) -(9 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(10 rows) explain (costs off) SELECT min(y) FROM @@ -1642,7 +1651,8 @@ SELECT min(y) FROM Index Cond: (unique1 IS NOT NULL) -> Index Only Scan using tenk1_unique2 on tenk1 b Index Cond: (unique2 IS NOT NULL) -(9 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(10 rows) -- XXX planner doesn't recognize that index on unique2 is sufficiently sorted explain (costs off) @@ -1659,7 +1669,8 @@ ORDER BY x, y; -> Sort Sort Key: b.unique2, b.unique2 -> Index Only Scan using tenk1_unique2 on tenk1 b -(6 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(7 rows) -- exercise rescan code path via a repeatedly-evaluated subquery explain (costs off) @@ -1684,7 +1695,8 @@ FROM generate_series(1, 3) g(i); -> Sort Sort Key: ((d_1.d + g.i)) -> Function Scan on generate_series d_1 -(11 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(12 rows) SELECT ARRAY(SELECT f.i FROM ( @@ -2236,7 +2248,8 @@ explain (costs off) select * from mcrparted where a = 10 order by a, abs(b), c; Index Cond: (a = 10) -> Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 Index Cond: (a = 10) -(5 rows) + Settings: enable_bitmapscan = 'off' +(6 rows) reset enable_bitmapscan; drop table mcrparted; diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out index f88f34550a..3f7b3fd441 100644 --- a/src/test/regress/expected/interval.out +++ b/src/test/regress/expected/interval.out @@ -257,7 +257,8 @@ SELECT f1 FROM INTERVAL_TBL_OF r1 ORDER BY f1; QUERY PLAN -------------------------------------------------------------------- Index Only Scan using interval_tbl_of_f1_idx on interval_tbl_of r1 -(1 row) + Settings: enable_seqscan = 'off' +(2 rows) SELECT f1 FROM INTERVAL_TBL_OF r1 ORDER BY f1; f1 diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 07e631d45e..a0b8181889 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -2496,7 +2496,8 @@ select count(*) from tenk1 a, tenk1 b -> Hash -> Seq Scan on tenk1 b Filter: ((fivethous % 10) < 10) -(7 rows) + Settings: enable_mergejoin = 'off', work_mem = '64kB' +(8 rows) select count(*) from tenk1 a, tenk1 b where a.hundred = b.thousand and (b.fivethous % 10) < 10; @@ -2715,7 +2716,8 @@ select a.idv, b.idv from tidv a, tidv b where a.idv = b.idv; -> Seq Scan on tidv a -> Index Only Scan using tidv_idv_idx on tidv b Index Cond: (idv = a.idv) -(4 rows) + Settings: enable_mergejoin = 'off' +(5 rows) rollback; -- @@ -4119,8 +4121,8 @@ explain (verbose, costs off) select a.q2, b.q1 from int8_tbl a left join int8_tbl b on a.q2 = coalesce(b.q1, 1) where coalesce(b.q1, 1) > 0; - QUERY PLAN ---------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ Merge Left Join Output: a.q2, b.q1 Merge Cond: (a.q2 = (COALESCE(b.q1, '1'::bigint))) @@ -4135,7 +4137,8 @@ explain (verbose, costs off) Sort Key: (COALESCE(b.q1, '1'::bigint)) -> Seq Scan on public.int8_tbl b Output: b.q1, COALESCE(b.q1, '1'::bigint) -(14 rows) + Settings: enable_hashjoin = 'off', enable_nestloop = 'off' +(15 rows) select a.q2, b.q1 from int8_tbl a left join int8_tbl b on a.q2 = coalesce(b.q1, 1) @@ -5970,14 +5973,15 @@ analyze j2; explain (costs off) select * from j1 inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2 where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1; - QUERY PLAN ------------------------------------------ + QUERY PLAN +--------------------------------------------------------------------------------- Merge Join Merge Cond: (j1.id1 = j2.id1) Join Filter: (j1.id2 = j2.id2) -> Index Scan using j1_id1_idx on j1 -> Index Scan using j2_id1_idx on j2 -(5 rows) + Settings: enable_hashjoin = 'off', enable_nestloop = 'off', enable_sort = 'off' +(6 rows) select * from j1 inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2 diff --git a/src/test/regress/expected/join_hash.out b/src/test/regress/expected/join_hash.out index 9eee39bdd3..9b1de7274f 100644 --- a/src/test/regress/expected/join_hash.out +++ b/src/test/regress/expected/join_hash.out @@ -4,7 +4,7 @@ begin; set local min_parallel_table_scan_size = 0; set local parallel_setup_cost = 0; --- Extract bucket and batch counts from an explain analyze plan. In +-- Extract bucket and batch counts from an explain exec plan. In -- general we can't make assertions about how many batches (or -- buckets) will be required because it can vary, but we can in some -- special cases and we can check for growth. @@ -39,7 +39,7 @@ declare hash_node json; begin for whole_plan in - execute 'explain (analyze, format ''json'') ' || query + execute 'explain (exec, format ''json'') ' || query loop hash_node := find_hash(json_extract_path(whole_plan, '0', 'Plan')); original := hash_node->>'Original Hash Batches'; @@ -87,15 +87,16 @@ set local max_parallel_workers_per_gather = 0; set local work_mem = '4MB'; explain (costs off) select count(*) from simple r join simple s using (id); - QUERY PLAN ----------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------- Aggregate -> Hash Join Hash Cond: (r.id = s.id) -> Seq Scan on simple r -> Hash -> Seq Scan on simple s -(6 rows) + Settings: max_parallel_workers_per_gather = '0', min_parallel_table_scan_size = '0', parallel_setup_cost = '0' +(7 rows) select count(*) from simple r join simple s using (id); count @@ -121,8 +122,8 @@ set local work_mem = '4MB'; set local enable_parallel_hash = off; explain (costs off) select count(*) from simple r join simple s using (id); - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 2 @@ -132,7 +133,8 @@ explain (costs off) -> Parallel Seq Scan on simple r -> Hash -> Seq Scan on simple s -(9 rows) + Settings: enable_parallel_hash = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0' +(10 rows) select count(*) from simple r join simple s using (id); count @@ -158,8 +160,8 @@ set local work_mem = '4MB'; set local enable_parallel_hash = on; explain (costs off) select count(*) from simple r join simple s using (id); - QUERY PLAN -------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 2 @@ -169,7 +171,8 @@ explain (costs off) -> Parallel Seq Scan on simple r -> Parallel Hash -> Parallel Seq Scan on simple s -(9 rows) + Settings: min_parallel_table_scan_size = '0', parallel_setup_cost = '0' +(10 rows) select count(*) from simple r join simple s using (id); count @@ -197,15 +200,16 @@ set local max_parallel_workers_per_gather = 0; set local work_mem = '128kB'; explain (costs off) select count(*) from simple r join simple s using (id); - QUERY PLAN ----------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------ Aggregate -> Hash Join Hash Cond: (r.id = s.id) -> Seq Scan on simple r -> Hash -> Seq Scan on simple s -(6 rows) + Settings: max_parallel_workers_per_gather = '0', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', work_mem = '128kB' +(7 rows) select count(*) from simple r join simple s using (id); count @@ -231,8 +235,8 @@ set local work_mem = '128kB'; set local enable_parallel_hash = off; explain (costs off) select count(*) from simple r join simple s using (id); - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 2 @@ -242,7 +246,8 @@ explain (costs off) -> Parallel Seq Scan on simple r -> Hash -> Seq Scan on simple s -(9 rows) + Settings: enable_parallel_hash = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', work_mem = '128kB' +(10 rows) select count(*) from simple r join simple s using (id); count @@ -268,8 +273,8 @@ set local work_mem = '192kB'; set local enable_parallel_hash = on; explain (costs off) select count(*) from simple r join simple s using (id); - QUERY PLAN -------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 2 @@ -279,7 +284,8 @@ explain (costs off) -> Parallel Seq Scan on simple r -> Parallel Hash -> Parallel Seq Scan on simple s -(9 rows) + Settings: min_parallel_table_scan_size = '0', parallel_setup_cost = '0', work_mem = '192kB' +(10 rows) select count(*) from simple r join simple s using (id); count @@ -308,15 +314,16 @@ set local max_parallel_workers_per_gather = 0; set local work_mem = '128kB'; explain (costs off) select count(*) FROM simple r JOIN bigger_than_it_looks s USING (id); - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------ Aggregate -> Hash Join Hash Cond: (r.id = s.id) -> Seq Scan on simple r -> Hash -> Seq Scan on bigger_than_it_looks s -(6 rows) + Settings: max_parallel_workers_per_gather = '0', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', work_mem = '128kB' +(7 rows) select count(*) FROM simple r JOIN bigger_than_it_looks s USING (id); count @@ -342,8 +349,8 @@ set local work_mem = '128kB'; set local enable_parallel_hash = off; explain (costs off) select count(*) from simple r join bigger_than_it_looks s using (id); - QUERY PLAN ------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 2 @@ -353,7 +360,8 @@ explain (costs off) -> Parallel Seq Scan on simple r -> Hash -> Seq Scan on bigger_than_it_looks s -(9 rows) + Settings: enable_parallel_hash = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', work_mem = '128kB' +(10 rows) select count(*) from simple r join bigger_than_it_looks s using (id); count @@ -379,8 +387,8 @@ set local work_mem = '192kB'; set local enable_parallel_hash = on; explain (costs off) select count(*) from simple r join bigger_than_it_looks s using (id); - QUERY PLAN ---------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------ Finalize Aggregate -> Gather Workers Planned: 1 @@ -390,7 +398,8 @@ explain (costs off) -> Parallel Seq Scan on simple r -> Parallel Hash -> Parallel Seq Scan on bigger_than_it_looks s -(9 rows) + Settings: max_parallel_workers_per_gather = '1', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', work_mem = '192kB' +(10 rows) select count(*) from simple r join bigger_than_it_looks s using (id); count @@ -420,15 +429,16 @@ set local max_parallel_workers_per_gather = 0; set local work_mem = '128kB'; explain (costs off) select count(*) from simple r join extremely_skewed s using (id); - QUERY PLAN --------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------ Aggregate -> Hash Join Hash Cond: (r.id = s.id) -> Seq Scan on simple r -> Hash -> Seq Scan on extremely_skewed s -(6 rows) + Settings: max_parallel_workers_per_gather = '0', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', work_mem = '128kB' +(7 rows) select count(*) from simple r join extremely_skewed s using (id); count @@ -453,8 +463,8 @@ set local work_mem = '128kB'; set local enable_parallel_hash = off; explain (costs off) select count(*) from simple r join extremely_skewed s using (id); - QUERY PLAN --------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- Aggregate -> Gather Workers Planned: 2 @@ -463,7 +473,8 @@ explain (costs off) -> Parallel Seq Scan on simple r -> Hash -> Seq Scan on extremely_skewed s -(8 rows) + Settings: enable_parallel_hash = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', work_mem = '128kB' +(9 rows) select count(*) from simple r join extremely_skewed s using (id); count @@ -488,8 +499,8 @@ set local work_mem = '128kB'; set local enable_parallel_hash = on; explain (costs off) select count(*) from simple r join extremely_skewed s using (id); - QUERY PLAN ------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------ Finalize Aggregate -> Gather Workers Planned: 1 @@ -499,7 +510,8 @@ explain (costs off) -> Parallel Seq Scan on simple r -> Parallel Hash -> Parallel Seq Scan on extremely_skewed s -(9 rows) + Settings: max_parallel_workers_per_gather = '1', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', work_mem = '128kB' +(10 rows) select count(*) from simple r join extremely_skewed s using (id); count @@ -518,7 +530,7 @@ $$); rollback to settings; -- A couple of other hash join tests unrelated to work_mem management. --- Check that EXPLAIN ANALYZE has data even if the leader doesn't participate +-- Check that EXPLAIN EXEC has data even if the leader doesn't participate savepoint settings; set local max_parallel_workers_per_gather = 2; set local work_mem = '4MB'; @@ -554,8 +566,8 @@ explain (costs off) select count(*) from join_foo left join (select b1.id, b1.t from join_bar b1 join join_bar b2 using (id)) ss on join_foo.id < ss.id + 1 and join_foo.id > ss.id - 1; - QUERY PLAN ------------------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Aggregate -> Nested Loop Left Join Join Filter: ((join_foo.id < (b1.id + 1)) AND (join_foo.id > (b1.id - 1))) @@ -567,7 +579,8 @@ explain (costs off) -> Parallel Seq Scan on join_bar b1 -> Hash -> Seq Scan on join_bar b2 -(11 rows) + Settings: enable_material = 'off', enable_mergejoin = 'off', enable_parallel_hash = 'off', min_parallel_table_scan_size = '0', parallel_leader_participation = 'off', parallel_setup_cost = '0', parallel_tuple_cost = '0', work_mem = '64kB' +(12 rows) select count(*) from join_foo left join (select b1.id, b1.t from join_bar b1 join join_bar b2 using (id)) ss @@ -605,8 +618,8 @@ explain (costs off) select count(*) from join_foo left join (select b1.id, b1.t from join_bar b1 join join_bar b2 using (id)) ss on join_foo.id < ss.id + 1 and join_foo.id > ss.id - 1; - QUERY PLAN ------------------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Aggregate -> Nested Loop Left Join Join Filter: ((join_foo.id < (b1.id + 1)) AND (join_foo.id > (b1.id - 1))) @@ -618,7 +631,8 @@ explain (costs off) -> Parallel Seq Scan on join_bar b1 -> Hash -> Seq Scan on join_bar b2 -(11 rows) + Settings: enable_material = 'off', enable_mergejoin = 'off', enable_parallel_hash = 'off', min_parallel_table_scan_size = '0', parallel_leader_participation = 'off', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(12 rows) select count(*) from join_foo left join (select b1.id, b1.t from join_bar b1 join join_bar b2 using (id)) ss @@ -656,8 +670,8 @@ explain (costs off) select count(*) from join_foo left join (select b1.id, b1.t from join_bar b1 join join_bar b2 using (id)) ss on join_foo.id < ss.id + 1 and join_foo.id > ss.id - 1; - QUERY PLAN ------------------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Aggregate -> Nested Loop Left Join Join Filter: ((join_foo.id < (b1.id + 1)) AND (join_foo.id > (b1.id - 1))) @@ -669,7 +683,8 @@ explain (costs off) -> Parallel Seq Scan on join_bar b1 -> Parallel Hash -> Parallel Seq Scan on join_bar b2 -(11 rows) + Settings: enable_material = 'off', enable_mergejoin = 'off', min_parallel_table_scan_size = '0', parallel_leader_participation = 'off', parallel_setup_cost = '0', parallel_tuple_cost = '0', work_mem = '64kB' +(12 rows) select count(*) from join_foo left join (select b1.id, b1.t from join_bar b1 join join_bar b2 using (id)) ss @@ -707,8 +722,8 @@ explain (costs off) select count(*) from join_foo left join (select b1.id, b1.t from join_bar b1 join join_bar b2 using (id)) ss on join_foo.id < ss.id + 1 and join_foo.id > ss.id - 1; - QUERY PLAN ------------------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Aggregate -> Nested Loop Left Join Join Filter: ((join_foo.id < (b1.id + 1)) AND (join_foo.id > (b1.id - 1))) @@ -720,7 +735,8 @@ explain (costs off) -> Parallel Seq Scan on join_bar b1 -> Parallel Hash -> Parallel Seq Scan on join_bar b2 -(11 rows) + Settings: enable_material = 'off', enable_mergejoin = 'off', min_parallel_table_scan_size = '0', parallel_leader_participation = 'off', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(12 rows) select count(*) from join_foo left join (select b1.id, b1.t from join_bar b1 join join_bar b2 using (id)) ss @@ -749,15 +765,16 @@ savepoint settings; set local max_parallel_workers_per_gather = 0; explain (costs off) select count(*) from simple r full outer join simple s using (id); - QUERY PLAN ----------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------- Aggregate -> Hash Full Join Hash Cond: (r.id = s.id) -> Seq Scan on simple r -> Hash -> Seq Scan on simple s -(6 rows) + Settings: max_parallel_workers_per_gather = '0', min_parallel_table_scan_size = '0', parallel_setup_cost = '0' +(7 rows) select count(*) from simple r full outer join simple s using (id); count @@ -771,15 +788,16 @@ savepoint settings; set local max_parallel_workers_per_gather = 2; explain (costs off) select count(*) from simple r full outer join simple s using (id); - QUERY PLAN ----------------------------------------- + QUERY PLAN +------------------------------------------------------------------------- Aggregate -> Hash Full Join Hash Cond: (r.id = s.id) -> Seq Scan on simple r -> Hash -> Seq Scan on simple s -(6 rows) + Settings: min_parallel_table_scan_size = '0', parallel_setup_cost = '0' +(7 rows) select count(*) from simple r full outer join simple s using (id); count @@ -794,15 +812,16 @@ savepoint settings; set local max_parallel_workers_per_gather = 0; explain (costs off) select count(*) from simple r full outer join simple s on (r.id = 0 - s.id); - QUERY PLAN ----------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------- Aggregate -> Hash Full Join Hash Cond: ((0 - s.id) = r.id) -> Seq Scan on simple s -> Hash -> Seq Scan on simple r -(6 rows) + Settings: max_parallel_workers_per_gather = '0', min_parallel_table_scan_size = '0', parallel_setup_cost = '0' +(7 rows) select count(*) from simple r full outer join simple s on (r.id = 0 - s.id); count @@ -816,15 +835,16 @@ savepoint settings; set local max_parallel_workers_per_gather = 2; explain (costs off) select count(*) from simple r full outer join simple s on (r.id = 0 - s.id); - QUERY PLAN ----------------------------------------- + QUERY PLAN +------------------------------------------------------------------------- Aggregate -> Hash Full Join Hash Cond: ((0 - s.id) = r.id) -> Seq Scan on simple s -> Hash -> Seq Scan on simple r -(6 rows) + Settings: min_parallel_table_scan_size = '0', parallel_setup_cost = '0' +(7 rows) select count(*) from simple r full outer join simple s on (r.id = 0 - s.id); count @@ -845,8 +865,8 @@ set work_mem = '128kB'; explain (costs off) select length(max(s.t)) from wide left join (select id, coalesce(t, '') || '' as t from wide) s using (id); - QUERY PLAN ----------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 2 @@ -856,7 +876,8 @@ explain (costs off) -> Parallel Seq Scan on wide -> Parallel Hash -> Parallel Seq Scan on wide wide_1 -(9 rows) + Settings: min_parallel_table_scan_size = '0', parallel_setup_cost = '0', work_mem = '128kB' +(10 rows) select length(max(s.t)) from wide left join (select id, coalesce(t, '') || '' as t from wide) s using (id); diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out index 1018303006..da4bfd2bdc 100644 --- a/src/test/regress/expected/jsonb.out +++ b/src/test/regress/expected/jsonb.out @@ -2923,7 +2923,8 @@ SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == null'; Recheck Cond: (j @@ '($."wait" == null)'::jsonpath) -> Bitmap Index Scan on jidx Index Cond: (j @@ '($."wait" == null)'::jsonpath) -(5 rows) + Settings: enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == null'; count @@ -3036,7 +3037,8 @@ SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)'; Recheck Cond: (j @? '$."wait"?(@ == null)'::jsonpath) -> Bitmap Index Scan on jidx Index Cond: (j @? '$."wait"?(@ == null)'::jsonpath) -(5 rows) + Settings: enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)'; count @@ -3341,7 +3343,8 @@ SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)'; Recheck Cond: (j @? '$."wait"?(@ == null)'::jsonpath) -> Bitmap Index Scan on jidx Index Cond: (j @? '$."wait"?(@ == null)'::jsonpath) -(5 rows) + Settings: enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)'; count diff --git a/src/test/regress/expected/partition_aggregate.out b/src/test/regress/expected/partition_aggregate.out index 10349ec29c..95ac71d77d 100644 --- a/src/test/regress/expected/partition_aggregate.out +++ b/src/test/regress/expected/partition_aggregate.out @@ -20,8 +20,8 @@ ANALYZE pagg_tab; -- When GROUP BY clause matches; full aggregation is performed for each partition. EXPLAIN (COSTS OFF) SELECT c, sum(a), avg(b), count(*), min(a), max(b) FROM pagg_tab GROUP BY c HAVING avg(d) < 15 ORDER BY 1, 2, 3; - QUERY PLAN ------------------------------------------------------------------------ + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_p1.c, (sum(pagg_tab_p1.a)), (avg(pagg_tab_p1.b)) -> Append @@ -37,7 +37,8 @@ SELECT c, sum(a), avg(b), count(*), min(a), max(b) FROM pagg_tab GROUP BY c HAVI Group Key: pagg_tab_p3.c Filter: (avg(pagg_tab_p3.d) < '15'::numeric) -> Seq Scan on pagg_tab_p3 -(15 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(16 rows) SELECT c, sum(a), avg(b), count(*), min(a), max(b) FROM pagg_tab GROUP BY c HAVING avg(d) < 15 ORDER BY 1, 2, 3; c | sum | avg | count | min | max @@ -53,8 +54,8 @@ SELECT c, sum(a), avg(b), count(*), min(a), max(b) FROM pagg_tab GROUP BY c HAVI -- When GROUP BY clause does not match; partial aggregation is performed for each partition. EXPLAIN (COSTS OFF) SELECT a, sum(b), avg(b), count(*), min(a), max(b) FROM pagg_tab GROUP BY a HAVING avg(d) < 15 ORDER BY 1, 2, 3; - QUERY PLAN ------------------------------------------------------------------------ + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_p1.a, (sum(pagg_tab_p1.b)), (avg(pagg_tab_p1.b)) -> Finalize HashAggregate @@ -70,7 +71,8 @@ SELECT a, sum(b), avg(b), count(*), min(a), max(b) FROM pagg_tab GROUP BY a HAVI -> Partial HashAggregate Group Key: pagg_tab_p3.a -> Seq Scan on pagg_tab_p3 -(15 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(16 rows) SELECT a, sum(b), avg(b), count(*), min(a), max(b) FROM pagg_tab GROUP BY a HAVING avg(d) < 15 ORDER BY 1, 2, 3; a | sum | avg | count | min | max @@ -90,8 +92,8 @@ SELECT a, sum(b), avg(b), count(*), min(a), max(b) FROM pagg_tab GROUP BY a HAVI -- Check with multiple columns in GROUP BY EXPLAIN (COSTS OFF) SELECT a, c, count(*) FROM pagg_tab GROUP BY a, c; - QUERY PLAN -------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Append -> HashAggregate Group Key: pagg_tab_p1.a, pagg_tab_p1.c @@ -102,13 +104,14 @@ SELECT a, c, count(*) FROM pagg_tab GROUP BY a, c; -> HashAggregate Group Key: pagg_tab_p3.a, pagg_tab_p3.c -> Seq Scan on pagg_tab_p3 -(10 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(11 rows) -- Check with multiple columns in GROUP BY, order in GROUP BY is reversed EXPLAIN (COSTS OFF) SELECT a, c, count(*) FROM pagg_tab GROUP BY c, a; - QUERY PLAN -------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Append -> HashAggregate Group Key: pagg_tab_p1.c, pagg_tab_p1.a @@ -119,13 +122,14 @@ SELECT a, c, count(*) FROM pagg_tab GROUP BY c, a; -> HashAggregate Group Key: pagg_tab_p3.c, pagg_tab_p3.a -> Seq Scan on pagg_tab_p3 -(10 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(11 rows) -- Check with multiple columns in GROUP BY, order in target-list is reversed EXPLAIN (COSTS OFF) SELECT c, a, count(*) FROM pagg_tab GROUP BY a, c; - QUERY PLAN -------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Append -> HashAggregate Group Key: pagg_tab_p1.a, pagg_tab_p1.c @@ -136,18 +140,20 @@ SELECT c, a, count(*) FROM pagg_tab GROUP BY a, c; -> HashAggregate Group Key: pagg_tab_p3.a, pagg_tab_p3.c -> Seq Scan on pagg_tab_p3 -(10 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(11 rows) -- Test when input relation for grouping is dummy EXPLAIN (COSTS OFF) SELECT c, sum(a) FROM pagg_tab WHERE 1 = 2 GROUP BY c; - QUERY PLAN --------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- HashAggregate Group Key: c -> Result One-Time Filter: false -(4 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(5 rows) SELECT c, sum(a) FROM pagg_tab WHERE 1 = 2 GROUP BY c; c | sum @@ -156,13 +162,14 @@ SELECT c, sum(a) FROM pagg_tab WHERE 1 = 2 GROUP BY c; EXPLAIN (COSTS OFF) SELECT c, sum(a) FROM pagg_tab WHERE c = 'x' GROUP BY c; - QUERY PLAN --------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- GroupAggregate Group Key: c -> Result One-Time Filter: false -(4 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(5 rows) SELECT c, sum(a) FROM pagg_tab WHERE c = 'x' GROUP BY c; c | sum @@ -174,8 +181,8 @@ SET enable_hashagg TO false; -- When GROUP BY clause matches full aggregation is performed for each partition. EXPLAIN (COSTS OFF) SELECT c, sum(a), avg(b), count(*) FROM pagg_tab GROUP BY 1 HAVING avg(d) < 15 ORDER BY 1, 2, 3; - QUERY PLAN ------------------------------------------------------------------------ + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_p1.c, (sum(pagg_tab_p1.a)), (avg(pagg_tab_p1.b)) -> Append @@ -197,7 +204,8 @@ SELECT c, sum(a), avg(b), count(*) FROM pagg_tab GROUP BY 1 HAVING avg(d) < 15 O -> Sort Sort Key: pagg_tab_p3.c -> Seq Scan on pagg_tab_p3 -(21 rows) + Settings: enable_hashagg = 'off', enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(22 rows) SELECT c, sum(a), avg(b), count(*) FROM pagg_tab GROUP BY 1 HAVING avg(d) < 15 ORDER BY 1, 2, 3; c | sum | avg | count @@ -213,8 +221,8 @@ SELECT c, sum(a), avg(b), count(*) FROM pagg_tab GROUP BY 1 HAVING avg(d) < 15 O -- When GROUP BY clause does not match; partial aggregation is performed for each partition. EXPLAIN (COSTS OFF) SELECT a, sum(b), avg(b), count(*) FROM pagg_tab GROUP BY 1 HAVING avg(d) < 15 ORDER BY 1, 2, 3; - QUERY PLAN ------------------------------------------------------------------------ + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_p1.a, (sum(pagg_tab_p1.b)), (avg(pagg_tab_p1.b)) -> Finalize GroupAggregate @@ -237,7 +245,8 @@ SELECT a, sum(b), avg(b), count(*) FROM pagg_tab GROUP BY 1 HAVING avg(d) < 15 O -> Sort Sort Key: pagg_tab_p3.a -> Seq Scan on pagg_tab_p3 -(22 rows) + Settings: enable_hashagg = 'off', enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(23 rows) SELECT a, sum(b), avg(b), count(*) FROM pagg_tab GROUP BY 1 HAVING avg(d) < 15 ORDER BY 1, 2, 3; a | sum | avg | count @@ -257,8 +266,8 @@ SELECT a, sum(b), avg(b), count(*) FROM pagg_tab GROUP BY 1 HAVING avg(d) < 15 O -- Test partitionwise grouping without any aggregates EXPLAIN (COSTS OFF) SELECT c FROM pagg_tab GROUP BY c ORDER BY 1; - QUERY PLAN -------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------- Merge Append Sort Key: pagg_tab_p1.c -> Group @@ -276,7 +285,8 @@ SELECT c FROM pagg_tab GROUP BY c ORDER BY 1; -> Sort Sort Key: pagg_tab_p3.c -> Seq Scan on pagg_tab_p3 -(17 rows) + Settings: enable_hashagg = 'off', enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(18 rows) SELECT c FROM pagg_tab GROUP BY c ORDER BY 1; c @@ -297,8 +307,8 @@ SELECT c FROM pagg_tab GROUP BY c ORDER BY 1; EXPLAIN (COSTS OFF) SELECT a FROM pagg_tab WHERE a < 3 GROUP BY a ORDER BY 1; - QUERY PLAN -------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------- Group Group Key: pagg_tab_p1.a -> Merge Append @@ -321,7 +331,8 @@ SELECT a FROM pagg_tab WHERE a < 3 GROUP BY a ORDER BY 1; Sort Key: pagg_tab_p3.a -> Seq Scan on pagg_tab_p3 Filter: (a < 3) -(22 rows) + Settings: enable_hashagg = 'off', enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(23 rows) SELECT a FROM pagg_tab WHERE a < 3 GROUP BY a ORDER BY 1; a @@ -335,8 +346,8 @@ RESET enable_hashagg; -- ROLLUP, partitionwise aggregation does not apply EXPLAIN (COSTS OFF) SELECT c, sum(a) FROM pagg_tab GROUP BY rollup(c) ORDER BY 1, 2; - QUERY PLAN -------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_p1.c, (sum(pagg_tab_p1.a)) -> MixedAggregate @@ -346,7 +357,8 @@ SELECT c, sum(a) FROM pagg_tab GROUP BY rollup(c) ORDER BY 1, 2; -> Seq Scan on pagg_tab_p1 -> Seq Scan on pagg_tab_p2 -> Seq Scan on pagg_tab_p3 -(9 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(10 rows) -- ORDERED SET within the aggregate. -- Full aggregation; since all the rows that belong to the same group come @@ -354,8 +366,8 @@ SELECT c, sum(a) FROM pagg_tab GROUP BY rollup(c) ORDER BY 1, 2; -- make any difference. EXPLAIN (COSTS OFF) SELECT c, sum(b order by a) FROM pagg_tab GROUP BY c ORDER BY 1, 2; - QUERY PLAN ------------------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_p1.c, (sum(pagg_tab_p1.b ORDER BY pagg_tab_p1.a)) -> Append @@ -374,15 +386,16 @@ SELECT c, sum(b order by a) FROM pagg_tab GROUP BY c ORDER BY 1, 2; -> Sort Sort Key: pagg_tab_p3.c -> Seq Scan on pagg_tab_p3 -(18 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(19 rows) -- Since GROUP BY clause does not match with PARTITION KEY; we need to do -- partial aggregation. However, ORDERED SET are not partial safe and thus -- partitionwise aggregation plan is not generated. EXPLAIN (COSTS OFF) SELECT a, sum(b order by a) FROM pagg_tab GROUP BY a ORDER BY 1, 2; - QUERY PLAN ------------------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_p1.a, (sum(pagg_tab_p1.b ORDER BY pagg_tab_p1.a)) -> GroupAggregate @@ -393,7 +406,8 @@ SELECT a, sum(b order by a) FROM pagg_tab GROUP BY a ORDER BY 1, 2; -> Seq Scan on pagg_tab_p1 -> Seq Scan on pagg_tab_p2 -> Seq Scan on pagg_tab_p3 -(10 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(11 rows) -- JOIN query CREATE TABLE pagg_tab1(x int, y int) PARTITION BY RANGE(x); @@ -411,8 +425,8 @@ ANALYZE pagg_tab2; -- When GROUP BY clause matches; full aggregation is performed for each partition. EXPLAIN (COSTS OFF) SELECT t1.x, sum(t1.y), count(*) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2.y GROUP BY t1.x ORDER BY 1, 2, 3; - QUERY PLAN -------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: t1.x, (sum(t1.y)), (count(*)) -> Append @@ -437,7 +451,8 @@ SELECT t1.x, sum(t1.y), count(*) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2 -> Seq Scan on pagg_tab2_p3 t2_2 -> Hash -> Seq Scan on pagg_tab1_p3 t1_2 -(24 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(25 rows) SELECT t1.x, sum(t1.y), count(*) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2.y GROUP BY t1.x ORDER BY 1, 2, 3; x | sum | count @@ -452,8 +467,8 @@ SELECT t1.x, sum(t1.y), count(*) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2 -- Check with whole-row reference; partitionwise aggregation does not apply EXPLAIN (COSTS OFF) SELECT t1.x, sum(t1.y), count(t1) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2.y GROUP BY t1.x ORDER BY 1, 2, 3; - QUERY PLAN -------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: t1.x, (sum(t1.y)), (count(((t1.*)::pagg_tab1))) -> HashAggregate @@ -469,7 +484,8 @@ SELECT t1.x, sum(t1.y), count(t1) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t -> Seq Scan on pagg_tab2_p1 t2 -> Seq Scan on pagg_tab2_p2 t2_1 -> Seq Scan on pagg_tab2_p3 t2_2 -(15 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(16 rows) SELECT t1.x, sum(t1.y), count(t1) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2.y GROUP BY t1.x ORDER BY 1, 2, 3; x | sum | count @@ -484,8 +500,8 @@ SELECT t1.x, sum(t1.y), count(t1) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t -- GROUP BY having other matching key EXPLAIN (COSTS OFF) SELECT t2.y, sum(t1.y), count(*) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2.y GROUP BY t2.y ORDER BY 1, 2, 3; - QUERY PLAN -------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: t2.y, (sum(t1.y)), (count(*)) -> Append @@ -510,15 +526,16 @@ SELECT t2.y, sum(t1.y), count(*) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2 -> Seq Scan on pagg_tab2_p3 t2_2 -> Hash -> Seq Scan on pagg_tab1_p3 t1_2 -(24 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(25 rows) -- When GROUP BY clause does not match; partial aggregation is performed for each partition. -- Also test GroupAggregate paths by disabling hash aggregates. SET enable_hashagg TO false; EXPLAIN (COSTS OFF) SELECT t1.y, sum(t1.x), count(*) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2.y GROUP BY t1.y HAVING avg(t1.x) > 10 ORDER BY 1, 2, 3; - QUERY PLAN -------------------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: t1.y, (sum(t1.x)), (count(*)) -> Finalize GroupAggregate @@ -553,7 +570,8 @@ SELECT t1.y, sum(t1.x), count(*) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2 -> Seq Scan on pagg_tab2_p3 t2_2 -> Hash -> Seq Scan on pagg_tab1_p3 t1_2 -(34 rows) + Settings: enable_hashagg = 'off', enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(35 rows) SELECT t1.y, sum(t1.x), count(*) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2.y GROUP BY t1.y HAVING avg(t1.x) > 10 ORDER BY 1, 2, 3; y | sum | count @@ -573,8 +591,8 @@ RESET enable_hashagg; -- GROUP BY is on nullable column EXPLAIN (COSTS OFF) SELECT b.y, sum(a.y) FROM pagg_tab1 a LEFT JOIN pagg_tab2 b ON a.x = b.y GROUP BY b.y ORDER BY 1 NULLS LAST; - QUERY PLAN ------------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Finalize GroupAggregate Group Key: b.y -> Sort @@ -601,7 +619,8 @@ SELECT b.y, sum(a.y) FROM pagg_tab1 a LEFT JOIN pagg_tab2 b ON a.x = b.y GROUP B -> Seq Scan on pagg_tab2_p3 b_2 -> Hash -> Seq Scan on pagg_tab1_p3 a_2 -(26 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(27 rows) SELECT b.y, sum(a.y) FROM pagg_tab1 a LEFT JOIN pagg_tab2 b ON a.x = b.y GROUP BY b.y ORDER BY 1 NULLS LAST; y | sum @@ -618,8 +637,8 @@ SELECT b.y, sum(a.y) FROM pagg_tab1 a LEFT JOIN pagg_tab2 b ON a.x = b.y GROUP B -- GROUP BY is on non-nullable column EXPLAIN (COSTS OFF) SELECT b.y, sum(a.y) FROM pagg_tab1 a RIGHT JOIN pagg_tab2 b ON a.x = b.y GROUP BY b.y ORDER BY 1 NULLS LAST; - QUERY PLAN ------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: b.y -> Append @@ -644,7 +663,8 @@ SELECT b.y, sum(a.y) FROM pagg_tab1 a RIGHT JOIN pagg_tab2 b ON a.x = b.y GROUP -> Seq Scan on pagg_tab2_p3 b_2 -> Hash -> Seq Scan on pagg_tab1_p3 a_2 -(24 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(25 rows) SELECT b.y, sum(a.y) FROM pagg_tab1 a RIGHT JOIN pagg_tab2 b ON a.x = b.y GROUP BY b.y ORDER BY 1 NULLS LAST; y | sum @@ -665,8 +685,8 @@ SELECT b.y, sum(a.y) FROM pagg_tab1 a RIGHT JOIN pagg_tab2 b ON a.x = b.y GROUP -- GROUP BY is on nullable column EXPLAIN (COSTS OFF) SELECT a.x, sum(b.x) FROM pagg_tab1 a FULL OUTER JOIN pagg_tab2 b ON a.x = b.y GROUP BY a.x ORDER BY 1 NULLS LAST; - QUERY PLAN ------------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Finalize GroupAggregate Group Key: a.x -> Sort @@ -693,7 +713,8 @@ SELECT a.x, sum(b.x) FROM pagg_tab1 a FULL OUTER JOIN pagg_tab2 b ON a.x = b.y G -> Seq Scan on pagg_tab2_p3 b_2 -> Hash -> Seq Scan on pagg_tab1_p3 a_2 -(26 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(27 rows) SELECT a.x, sum(b.x) FROM pagg_tab1 a FULL OUTER JOIN pagg_tab2 b ON a.x = b.y GROUP BY a.x ORDER BY 1 NULLS LAST; x | sum @@ -722,8 +743,8 @@ SELECT a.x, sum(b.x) FROM pagg_tab1 a FULL OUTER JOIN pagg_tab2 b ON a.x = b.y G -- But right now we are unable to do partitionwise join in this case. EXPLAIN (COSTS OFF) SELECT a.x, b.y, count(*) FROM (SELECT * FROM pagg_tab1 WHERE x < 20) a LEFT JOIN (SELECT * FROM pagg_tab2 WHERE y > 10) b ON a.x = b.y WHERE a.x > 5 or b.y < 20 GROUP BY a.x, b.y ORDER BY 1, 2; - QUERY PLAN ------------------------------------------------------------------------ + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab1_p1.x, pagg_tab2_p2.y -> HashAggregate @@ -742,7 +763,8 @@ SELECT a.x, b.y, count(*) FROM (SELECT * FROM pagg_tab1 WHERE x < 20) a LEFT JOI Filter: (y > 10) -> Seq Scan on pagg_tab2_p3 Filter: (y > 10) -(18 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(19 rows) SELECT a.x, b.y, count(*) FROM (SELECT * FROM pagg_tab1 WHERE x < 20) a LEFT JOIN (SELECT * FROM pagg_tab2 WHERE y > 10) b ON a.x = b.y WHERE a.x > 5 or b.y < 20 GROUP BY a.x, b.y ORDER BY 1, 2; x | y | count @@ -762,8 +784,8 @@ SELECT a.x, b.y, count(*) FROM (SELECT * FROM pagg_tab1 WHERE x < 20) a LEFT JOI -- But right now we are unable to do partitionwise join in this case. EXPLAIN (COSTS OFF) SELECT a.x, b.y, count(*) FROM (SELECT * FROM pagg_tab1 WHERE x < 20) a FULL JOIN (SELECT * FROM pagg_tab2 WHERE y > 10) b ON a.x = b.y WHERE a.x > 5 or b.y < 20 GROUP BY a.x, b.y ORDER BY 1, 2; - QUERY PLAN ------------------------------------------------------------------------ + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab1_p1.x, pagg_tab2_p2.y -> HashAggregate @@ -782,7 +804,8 @@ SELECT a.x, b.y, count(*) FROM (SELECT * FROM pagg_tab1 WHERE x < 20) a FULL JOI Filter: (y > 10) -> Seq Scan on pagg_tab2_p3 Filter: (y > 10) -(18 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(19 rows) SELECT a.x, b.y, count(*) FROM (SELECT * FROM pagg_tab1 WHERE x < 20) a FULL JOIN (SELECT * FROM pagg_tab2 WHERE y > 10) b ON a.x = b.y WHERE a.x > 5 or b.y < 20 GROUP BY a.x, b.y ORDER BY 1, 2; x | y | count @@ -800,15 +823,16 @@ SELECT a.x, b.y, count(*) FROM (SELECT * FROM pagg_tab1 WHERE x < 20) a FULL JOI -- Empty join relation because of empty outer side, no partitionwise agg plan EXPLAIN (COSTS OFF) SELECT a.x, a.y, count(*) FROM (SELECT * FROM pagg_tab1 WHERE x = 1 AND x = 2) a LEFT JOIN pagg_tab2 b ON a.x = b.y GROUP BY a.x, a.y ORDER BY 1, 2; - QUERY PLAN ---------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- GroupAggregate Group Key: pagg_tab1.x, pagg_tab1.y -> Sort Sort Key: pagg_tab1.y -> Result One-Time Filter: false -(6 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(7 rows) SELECT a.x, a.y, count(*) FROM (SELECT * FROM pagg_tab1 WHERE x = 1 AND x = 2) a LEFT JOIN pagg_tab2 b ON a.x = b.y GROUP BY a.x, a.y ORDER BY 1, 2; x | y | count @@ -825,8 +849,8 @@ ANALYZE pagg_tab_m; -- Partial aggregation as GROUP BY clause does not match with PARTITION KEY EXPLAIN (COSTS OFF) SELECT a, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY a HAVING avg(c) < 22 ORDER BY 1, 2, 3; - QUERY PLAN ------------------------------------------------------------------------------ + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_m_p1.a, (sum(pagg_tab_m_p1.b)), (avg(pagg_tab_m_p1.c)) -> Finalize HashAggregate @@ -842,7 +866,8 @@ SELECT a, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY a HAVING avg(c) < 22 -> Partial HashAggregate Group Key: pagg_tab_m_p3.a -> Seq Scan on pagg_tab_m_p3 -(15 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(16 rows) SELECT a, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY a HAVING avg(c) < 22 ORDER BY 1, 2, 3; a | sum | avg | count @@ -858,8 +883,8 @@ SELECT a, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY a HAVING avg(c) < 22 -- Full aggregation as GROUP BY clause matches with PARTITION KEY EXPLAIN (COSTS OFF) SELECT a, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY a, (a+b)/2 HAVING sum(b) < 50 ORDER BY 1, 2, 3; - QUERY PLAN -------------------------------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_m_p1.a, (sum(pagg_tab_m_p1.b)), (avg(pagg_tab_m_p1.c)) -> Append @@ -875,7 +900,8 @@ SELECT a, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY a, (a+b)/2 HAVING su Group Key: pagg_tab_m_p3.a, ((pagg_tab_m_p3.a + pagg_tab_m_p3.b) / 2) Filter: (sum(pagg_tab_m_p3.b) < 50) -> Seq Scan on pagg_tab_m_p3 -(15 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(16 rows) SELECT a, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY a, (a+b)/2 HAVING sum(b) < 50 ORDER BY 1, 2, 3; a | sum | avg | count @@ -891,8 +917,8 @@ SELECT a, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY a, (a+b)/2 HAVING su -- Full aggregation as PARTITION KEY is part of GROUP BY clause EXPLAIN (COSTS OFF) SELECT a, c, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY (a+b)/2, 2, 1 HAVING sum(b) = 50 AND avg(c) > 25 ORDER BY 1, 2, 3; - QUERY PLAN ------------------------------------------------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_m_p1.a, pagg_tab_m_p1.c, (sum(pagg_tab_m_p1.b)) -> Append @@ -908,7 +934,8 @@ SELECT a, c, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY (a+b)/2, 2, 1 HAV Group Key: ((pagg_tab_m_p3.a + pagg_tab_m_p3.b) / 2), pagg_tab_m_p3.c, pagg_tab_m_p3.a Filter: ((sum(pagg_tab_m_p3.b) = 50) AND (avg(pagg_tab_m_p3.c) > '25'::numeric)) -> Seq Scan on pagg_tab_m_p3 -(15 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', max_parallel_workers_per_gather = '0' +(16 rows) SELECT a, c, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY (a+b)/2, 2, 1 HAVING sum(b) = 50 AND avg(c) > 25 ORDER BY 1, 2, 3; a | c | sum | avg | count @@ -972,7 +999,8 @@ SELECT a, sum(b), array_agg(distinct c), count(*) FROM pagg_tab_ml GROUP BY a HA -> Sort Sort Key: pagg_tab_ml_p1.a -> Seq Scan on pagg_tab_ml_p1 -(27 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on' +(28 rows) SELECT a, sum(b), array_agg(distinct c), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER BY 1, 2, 3; a | sum | array_agg | count @@ -991,8 +1019,8 @@ SELECT a, sum(b), array_agg(distinct c), count(*) FROM pagg_tab_ml GROUP BY a HA -- Without ORDER BY clause, to test Gather at top-most path EXPLAIN (COSTS OFF) SELECT a, sum(b), array_agg(distinct c), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3; - QUERY PLAN ------------------------------------------------------------------ + QUERY PLAN +----------------------------------------------------------------------------------- Gather Workers Planned: 2 -> Parallel Append @@ -1018,15 +1046,16 @@ SELECT a, sum(b), array_agg(distinct c), count(*) FROM pagg_tab_ml GROUP BY a HA -> Sort Sort Key: pagg_tab_ml_p1.a -> Seq Scan on pagg_tab_ml_p1 -(25 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on' +(26 rows) -- Full aggregation at level 1 as GROUP BY clause matches with PARTITION KEY -- for level 1 only. For subpartitions, GROUP BY clause does not match with -- PARTITION KEY, thus we will have a partial aggregation for them. EXPLAIN (COSTS OFF) SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER BY 1, 2, 3; - QUERY PLAN -------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_ml_p1.a, (sum(pagg_tab_ml_p1.b)), (count(*)) -> Append @@ -1058,7 +1087,8 @@ SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER B -> Partial HashAggregate Group Key: pagg_tab_ml_p3_s2.a -> Seq Scan on pagg_tab_ml_p3_s2 -(31 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on' +(32 rows) SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER BY 1, 2, 3; a | sum | count @@ -1078,8 +1108,8 @@ SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER B -- PARTITION KEY EXPLAIN (COSTS OFF) SELECT b, sum(a), count(*) FROM pagg_tab_ml GROUP BY b ORDER BY 1, 2, 3; - QUERY PLAN -------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_ml_p1.b, (sum(pagg_tab_ml_p1.a)), (count(*)) -> Finalize GroupAggregate @@ -1102,7 +1132,8 @@ SELECT b, sum(a), count(*) FROM pagg_tab_ml GROUP BY b ORDER BY 1, 2, 3; -> Partial HashAggregate Group Key: pagg_tab_ml_p3_s2.b -> Seq Scan on pagg_tab_ml_p3_s2 -(22 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on' +(23 rows) SELECT b, sum(a), count(*) FROM pagg_tab_ml GROUP BY b HAVING avg(a) < 15 ORDER BY 1, 2, 3; b | sum | count @@ -1142,7 +1173,8 @@ SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a, b, c HAVING avg(b) > 7 O Group Key: pagg_tab_ml_p3_s2.a, pagg_tab_ml_p3_s2.b, pagg_tab_ml_p3_s2.c Filter: (avg(pagg_tab_ml_p3_s2.b) > '7'::numeric) -> Seq Scan on pagg_tab_ml_p3_s2 -(23 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on' +(24 rows) SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a, b, c HAVING avg(b) > 7 ORDER BY 1, 2, 3; a | sum | count @@ -1169,8 +1201,8 @@ SET parallel_setup_cost TO 0; -- PARTITION KEY, thus we will have a partial aggregation for them. EXPLAIN (COSTS OFF) SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER BY 1, 2, 3; - QUERY PLAN ----------------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_ml_p1.a, (sum(pagg_tab_ml_p1.b)), (count(*)) -> Append @@ -1212,7 +1244,8 @@ SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER B -> Partial HashAggregate Group Key: pagg_tab_ml_p3_s2.a -> Parallel Seq Scan on pagg_tab_ml_p3_s2 -(41 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', min_parallel_table_scan_size = '8kB', parallel_setup_cost = '0' +(42 rows) SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER BY 1, 2, 3; a | sum | count @@ -1232,8 +1265,8 @@ SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a HAVING avg(b) < 3 ORDER B -- PARTITION KEY EXPLAIN (COSTS OFF) SELECT b, sum(a), count(*) FROM pagg_tab_ml GROUP BY b ORDER BY 1, 2, 3; - QUERY PLAN ----------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_ml_p1.b, (sum(pagg_tab_ml_p1.a)), (count(*)) -> Finalize GroupAggregate @@ -1258,7 +1291,8 @@ SELECT b, sum(a), count(*) FROM pagg_tab_ml GROUP BY b ORDER BY 1, 2, 3; -> Partial HashAggregate Group Key: pagg_tab_ml_p3_s2.b -> Parallel Seq Scan on pagg_tab_ml_p3_s2 -(24 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', min_parallel_table_scan_size = '8kB', parallel_setup_cost = '0' +(25 rows) SELECT b, sum(a), count(*) FROM pagg_tab_ml GROUP BY b HAVING avg(a) < 15 ORDER BY 1, 2, 3; b | sum | count @@ -1273,8 +1307,8 @@ SELECT b, sum(a), count(*) FROM pagg_tab_ml GROUP BY b HAVING avg(a) < 15 ORDER -- Full aggregation at all levels as GROUP BY clause matches with PARTITION KEY EXPLAIN (COSTS OFF) SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a, b, c HAVING avg(b) > 7 ORDER BY 1, 2, 3; - QUERY PLAN ----------------------------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------- Gather Merge Workers Planned: 2 -> Sort @@ -1300,7 +1334,8 @@ SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a, b, c HAVING avg(b) > 7 O Group Key: pagg_tab_ml_p3_s2.a, pagg_tab_ml_p3_s2.b, pagg_tab_ml_p3_s2.c Filter: (avg(pagg_tab_ml_p3_s2.b) > '7'::numeric) -> Seq Scan on pagg_tab_ml_p3_s2 -(25 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', min_parallel_table_scan_size = '8kB', parallel_setup_cost = '0' +(26 rows) SELECT a, sum(b), count(*) FROM pagg_tab_ml GROUP BY a, b, c HAVING avg(b) > 7 ORDER BY 1, 2, 3; a | sum | count @@ -1337,8 +1372,8 @@ ANALYZE pagg_tab_para; -- When GROUP BY clause matches; full aggregation is performed for each partition. EXPLAIN (COSTS OFF) SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < 7 ORDER BY 1, 2, 3; - QUERY PLAN --------------------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_para_p1.x, (sum(pagg_tab_para_p1.y)), (avg(pagg_tab_para_p1.y)) -> Finalize GroupAggregate @@ -1358,7 +1393,8 @@ SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < -> Partial HashAggregate Group Key: pagg_tab_para_p3.x -> Parallel Seq Scan on pagg_tab_para_p3 -(19 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', min_parallel_table_scan_size = '8kB', parallel_setup_cost = '10' +(20 rows) SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < 7 ORDER BY 1, 2, 3; x | sum | avg | count @@ -1374,8 +1410,8 @@ SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < -- When GROUP BY clause does not match; partial aggregation is performed for each partition. EXPLAIN (COSTS OFF) SELECT y, sum(x), avg(x), count(*) FROM pagg_tab_para GROUP BY y HAVING avg(x) < 12 ORDER BY 1, 2, 3; - QUERY PLAN --------------------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_para_p1.y, (sum(pagg_tab_para_p1.x)), (avg(pagg_tab_para_p1.x)) -> Finalize GroupAggregate @@ -1395,7 +1431,8 @@ SELECT y, sum(x), avg(x), count(*) FROM pagg_tab_para GROUP BY y HAVING avg(x) < -> Partial HashAggregate Group Key: pagg_tab_para_p3.y -> Parallel Seq Scan on pagg_tab_para_p3 -(19 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', min_parallel_table_scan_size = '8kB', parallel_setup_cost = '10' +(20 rows) SELECT y, sum(x), avg(x), count(*) FROM pagg_tab_para GROUP BY y HAVING avg(x) < 12 ORDER BY 1, 2, 3; y | sum | avg | count @@ -1412,8 +1449,8 @@ ALTER TABLE pagg_tab_para_p3 SET (parallel_workers = 0); ANALYZE pagg_tab_para; EXPLAIN (COSTS OFF) SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < 7 ORDER BY 1, 2, 3; - QUERY PLAN --------------------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_para_p1.x, (sum(pagg_tab_para_p1.y)), (avg(pagg_tab_para_p1.y)) -> Finalize GroupAggregate @@ -1429,7 +1466,8 @@ SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < -> Seq Scan on pagg_tab_para_p1 -> Seq Scan on pagg_tab_para_p3 -> Parallel Seq Scan on pagg_tab_para_p2 -(15 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', min_parallel_table_scan_size = '8kB', parallel_setup_cost = '10' +(16 rows) SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < 7 ORDER BY 1, 2, 3; x | sum | avg | count @@ -1446,8 +1484,8 @@ ALTER TABLE pagg_tab_para_p2 SET (parallel_workers = 0); ANALYZE pagg_tab_para; EXPLAIN (COSTS OFF) SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < 7 ORDER BY 1, 2, 3; - QUERY PLAN --------------------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: pagg_tab_para_p1.x, (sum(pagg_tab_para_p1.y)), (avg(pagg_tab_para_p1.y)) -> Finalize GroupAggregate @@ -1463,7 +1501,8 @@ SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < -> Seq Scan on pagg_tab_para_p1 -> Seq Scan on pagg_tab_para_p2 -> Seq Scan on pagg_tab_para_p3 -(15 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on', min_parallel_table_scan_size = '8kB', parallel_setup_cost = '10' +(16 rows) SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < 7 ORDER BY 1, 2, 3; x | sum | avg | count @@ -1498,7 +1537,8 @@ SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < Group Key: pagg_tab_para_p3.x Filter: (avg(pagg_tab_para_p3.y) < '7'::numeric) -> Seq Scan on pagg_tab_para_p3 -(15 rows) + Settings: enable_partitionwise_aggregate = 'on', enable_partitionwise_join = 'on' +(16 rows) SELECT x, sum(y), avg(y), count(*) FROM pagg_tab_para GROUP BY x HAVING avg(y) < 7 ORDER BY 1, 2, 3; x | sum | avg | count diff --git a/src/test/regress/expected/partition_join.out b/src/test/regress/expected/partition_join.out index 1296edcdae..01a1444311 100644 --- a/src/test/regress/expected/partition_join.out +++ b/src/test/regress/expected/partition_join.out @@ -51,7 +51,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = -> Hash -> Seq Scan on prt1_p3 t1_2 Filter: (b = 0) -(21 rows) + Settings: enable_partitionwise_join = 'on' +(22 rows) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b; a | c | b | c @@ -83,7 +84,8 @@ SELECT t1, t2 FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.b = 0 ORDER Filter: (b = 0) -> Seq Scan on prt1_p3 t1_2 Filter: (b = 0) -(16 rows) + Settings: enable_partitionwise_join = 'on' +(17 rows) SELECT t1, t2 FROM prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b WHERE t1.b = 0 ORDER BY t1.a, t2.b; t1 | t2 @@ -127,7 +129,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHE Filter: (a = 0) -> Index Scan using iprt1_p3_a on prt1_p3 t1_2 Index Cond: (a = t2_2.b) -(20 rows) + Settings: enable_partitionwise_join = 'on' +(21 rows) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.a = 0 ORDER BY t1.a, t2.b; a | c | b | c @@ -174,7 +177,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM prt1 WHERE prt1.b = 0) -> Hash -> Seq Scan on prt2_p3 Filter: (a = 0) -(27 rows) + Settings: enable_partitionwise_join = 'on' +(28 rows) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 50 phv, * FROM prt1 WHERE prt1.b = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDER BY t1.a, t2.b; a | c | b | c @@ -197,7 +201,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a < -> Hash -> Seq Scan on prt1_p2 t1 Filter: ((a < 450) AND (b = 0)) -(9 rows) + Settings: enable_partitionwise_join = 'on' +(10 rows) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a < 450 AND t2.b > 250 AND t1.b = 0 ORDER BY t1.a, t2.b; a | c | b | c @@ -225,7 +230,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JO Filter: ((a < 450) AND (b = 0)) -> Seq Scan on prt1_p2 Filter: ((a < 450) AND (b = 0)) -(15 rows) + Settings: enable_partitionwise_join = 'on' +(16 rows) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0 ORDER BY t1.a, t2.b; a | c | b | c @@ -262,7 +268,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 FULL JO Filter: (b > 250) -> Seq Scan on prt2_p3 Filter: (b > 250) -(16 rows) + Settings: enable_partitionwise_join = 'on' +(17 rows) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 FULL JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0 OR t2.a = 0 ORDER BY t1.a, t2.b; a | c | b | c @@ -310,7 +317,8 @@ SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t2.b FROM prt2 t2 WHERE t2.a = 0) -> Materialize -> Seq Scan on prt2_p3 t2_2 Filter: (a = 0) -(24 rows) + Settings: enable_partitionwise_join = 'on' +(25 rows) SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t2.b FROM prt2 t2 WHERE t2.a = 0) AND t1.b = 0 ORDER BY t1.a; a | b | c @@ -343,7 +351,8 @@ SELECT sum(t1.a), avg(t1.a), sum(t1.b), avg(t1.b) FROM prt1 t1 WHERE NOT EXISTS -> Seq Scan on prt1_p3 t1_2 -> Hash -> Seq Scan on prt2_p3 t2_2 -(17 rows) + Settings: enable_partitionwise_join = 'on' +(18 rows) SELECT sum(t1.a), avg(t1.a), sum(t1.b), avg(t1.b) FROM prt1 t1 WHERE NOT EXISTS (SELECT 1 FROM prt2 t2 WHERE t1.a = t2.b); sum | avg | sum | avg @@ -385,7 +394,8 @@ SELECT * FROM prt1 t1 LEFT JOIN LATERAL Index Cond: (a = t1_2.a) -> Index Scan using iprt2_p3_b on prt2_p3 t3_2 Index Cond: (b = t2_2.a) -(27 rows) + Settings: enable_partitionwise_join = 'on' +(28 rows) SELECT * FROM prt1 t1 LEFT JOIN LATERAL (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.b) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss @@ -438,7 +448,8 @@ SELECT t1.a, ss.t2a, ss.t2c FROM prt1 t1 LEFT JOIN LATERAL -> Seq Scan on prt1_p3 t2_2 -> Hash -> Seq Scan on prt2_p3 t3_2 -(26 rows) + Settings: enable_partitionwise_join = 'on' +(27 rows) SELECT t1.a, ss.t2a, ss.t2c FROM prt1 t1 LEFT JOIN LATERAL (SELECT t2.a AS t2a, t3.a AS t3a, t2.b t2b, t2.c t2c, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss @@ -502,7 +513,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1, prt2_e t2 WHERE (t1.a + t1.b)/2 = -> Hash -> Seq Scan on prt1_e_p3 t1_2 Filter: (c = 0) -(21 rows) + Settings: enable_partitionwise_join = 'on' +(22 rows) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_e t1, prt2_e t2 WHERE (t1.a + t1.b)/2 = (t2.b + t2.a)/2 AND t1.c = 0 ORDER BY t1.a, t2.b; a | c | b | c @@ -553,7 +565,8 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t Filter: (b = 0) -> Index Scan using iprt1_e_p3_ab2 on prt1_e_p3 t3_2 Index Cond: (((a + b) / 2) = t2_2.b) -(33 rows) + Settings: enable_partitionwise_join = 'on' +(34 rows) SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.b = 0 ORDER BY t1.a, t2.b; a | c | b | c | ?column? | c @@ -601,7 +614,8 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 -> Hash -> Seq Scan on prt1_p3 t1_2 Filter: (b = 0) -(33 rows) + Settings: enable_partitionwise_join = 'on' +(34 rows) SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) LEFT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.b = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; a | c | b | c | ?column? | c @@ -654,7 +668,8 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 Filter: (c = 0) -> Index Scan using iprt2_p3_b on prt2_p3 t2_2 Index Cond: (b = t1_2.a) -(30 rows) + Settings: enable_partitionwise_join = 'on' +(31 rows) SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.c = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; a | c | b | c | ?column? | c @@ -721,7 +736,8 @@ SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * F -> Hash -> Seq Scan on prt1_e_p3 Filter: (c = 0) -(42 rows) + Settings: enable_partitionwise_join = 'on' +(43 rows) SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT 50 phv, * FROM prt1 WHERE prt1.b = 0) t1 FULL JOIN (SELECT 75 phv, * FROM prt2 WHERE prt2.a = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT 50 phv, * FROM prt1_e WHERE prt1_e.c = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDER BY t1.a, t2.b, t3.a + t3.b; a | phv | b | phv | ?column? | phv @@ -776,7 +792,8 @@ SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHER -> Index Scan using iprt1_p3_a on prt1_p3 t1_2 Index Cond: (a = ((t2_2.a + t2_2.b) / 2)) Filter: (b = 0) -(41 rows) + Settings: enable_partitionwise_join = 'on' +(42 rows) SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.a = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.b = 0 ORDER BY t1.a; a | b | c @@ -830,7 +847,8 @@ SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN ( -> Index Scan using iprt1_p3_a on prt1_p3 t1_2 Index Cond: (a = t1_5.b) Filter: (b = 0) -(39 rows) + Settings: enable_partitionwise_join = 'on' +(40 rows) SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.c = 0)) AND t1.b = 0 ORDER BY t1.a; a | b | c @@ -846,8 +864,8 @@ SET enable_hashjoin TO off; SET enable_nestloop TO off; EXPLAIN (COSTS OFF) SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.c = 0)) AND t1.b = 0 ORDER BY t1.a; - QUERY PLAN ----------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------- Merge Append Sort Key: t1.a -> Merge Semi Join @@ -895,7 +913,8 @@ SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN ( Sort Key: (((t1_8.a + t1_8.b) / 2)) -> Seq Scan on prt1_e_p3 t1_8 Filter: (c = 0) -(47 rows) + Settings: enable_hashjoin = 'off', enable_nestloop = 'off', enable_partitionwise_join = 'on' +(48 rows) SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.c = 0)) AND t1.b = 0 ORDER BY t1.a; a | b | c @@ -908,8 +927,8 @@ SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN ( EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.c = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; - QUERY PLAN ----------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------- Sort Sort Key: t1.a, t2.b, ((t3.a + t3.b)) -> Append @@ -961,7 +980,8 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 -> Sort Sort Key: t2_2.b -> Seq Scan on prt2_p3 t2_2 -(51 rows) + Settings: enable_hashjoin = 'off', enable_nestloop = 'off', enable_partitionwise_join = 'on' +(52 rows) SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.c = 0 ORDER BY t1.a, t2.b, t3.a + t3.b; a | c | b | c | ?column? | c @@ -984,8 +1004,8 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 -- This should generate a partitionwise join, but currently fails to EXPLAIN (COSTS OFF) SELECT t1.a, t2.b FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0 ORDER BY t1.a, t2.b; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +---------------------------------------------------------------------------------------------- Sort Sort Key: prt1_p1.a, prt2_p2.b -> Merge Left Join @@ -1004,7 +1024,8 @@ SELECT t1.a, t2.b FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JOIN (SELECT * Filter: (b > 250) -> Seq Scan on prt2_p3 Filter: (b > 250) -(18 rows) + Settings: enable_hashjoin = 'off', enable_nestloop = 'off', enable_partitionwise_join = 'on' +(19 rows) SELECT t1.a, t2.b FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0 ORDER BY t1.a, t2.b; a | b @@ -1024,8 +1045,8 @@ SELECT t1.a, t2.b FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFT JOIN (SELECT * -- partitionwise join does not apply EXPLAIN (COSTS OFF) SELECT t1.a, t2.b FROM prt1 t1, prt2 t2 WHERE t1::text = t2::text AND t1.a = t2.b ORDER BY t1.a; - QUERY PLAN ------------------------------------------------------------------------------------------ + QUERY PLAN +---------------------------------------------------------------------------------------------- Merge Join Merge Cond: ((t1.a = t2.b) AND (((((t1.*)::prt1))::text) = ((((t2.*)::prt2))::text))) -> Sort @@ -1042,7 +1063,8 @@ SELECT t1.a, t2.b FROM prt1 t1, prt2 t2 WHERE t1::text = t2::text AND t1.a = t2. -> Seq Scan on prt2_p1 t2 -> Seq Scan on prt2_p2 t2_1 -> Seq Scan on prt2_p3 t2_2 -(16 rows) + Settings: enable_hashjoin = 'off', enable_nestloop = 'off', enable_partitionwise_join = 'on' +(17 rows) SELECT t1.a, t2.b FROM prt1 t1, prt2 t2 WHERE t1::text = t2::text AND t1.a = t2.b ORDER BY t1.a; a | b @@ -1099,7 +1121,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_m WHERE prt1_m.c = 0) t1 -> Hash -> Seq Scan on prt2_m_p3 Filter: (c = 0) -(24 rows) + Settings: enable_partitionwise_join = 'on' +(25 rows) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_m WHERE prt1_m.c = 0) t1 FULL JOIN (SELECT * FROM prt2_m WHERE prt2_m.c = 0) t2 ON (t1.a = (t2.b + t2.a)/2 AND t2.b = (t1.a + t1.b)/2) ORDER BY t1.a, t2.b; a | c | b | c @@ -1183,7 +1206,8 @@ SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM plt1 t1, pl -> Seq Scan on plt2_p3 t2_2 -> Hash -> Seq Scan on plt1_e_p3 t3_2 -(32 rows) + Settings: enable_partitionwise_join = 'on' +(33 rows) SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM plt1 t1, plt2 t2, plt1_e t3 WHERE t1.b = t2.b AND t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c; avg | avg | avg | c | c | c @@ -1205,19 +1229,21 @@ SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM plt1 t1, pl -- joins where one of the relations is proven empty EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a = 1 AND t1.a = 2; - QUERY PLAN --------------------------- + QUERY PLAN +-------------------------------------------- Result One-Time Filter: false -(2 rows) + Settings: enable_partitionwise_join = 'on' +(3 rows) EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 LEFT JOIN prt2 t2 ON t1.a = t2.b; - QUERY PLAN --------------------------- + QUERY PLAN +-------------------------------------------- Result One-Time Filter: false -(2 rows) + Settings: enable_partitionwise_join = 'on' +(3 rows) EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b, prt1 t3 WHERE t2.b = t3.a; @@ -1244,7 +1270,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 -> Hash -> Result One-Time Filter: false -(21 rows) + Settings: enable_partitionwise_join = 'on' +(22 rows) EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 FULL JOIN prt2 t2 ON t1.a = t2.b WHERE t2.a = 0 ORDER BY t1.a, t2.b; @@ -1264,7 +1291,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1 AND a = 2) t1 -> Hash -> Result One-Time Filter: false -(14 rows) + Settings: enable_partitionwise_join = 'on' +(15 rows) -- -- tests for hash partitioned tables. @@ -1327,7 +1355,8 @@ SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM pht1 t1, ph -> Seq Scan on pht2_p3 t2_2 -> Hash -> Seq Scan on pht1_e_p3 t3_2 -(32 rows) + Settings: enable_partitionwise_join = 'on' +(33 rows) SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM pht1 t1, pht2 t2, pht1_e t3 WHERE t1.b = t2.b AND t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUP BY t1.c, t2.c, t3.c ORDER BY t1.c, t2.c, t3.c; avg | avg | avg | c | c | c @@ -1372,7 +1401,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = -> Hash -> Seq Scan on prt1_p3 t1_2 Filter: (b = 0) -(21 rows) + Settings: enable_partitionwise_join = 'on' +(22 rows) -- test default partition behavior for list ALTER TABLE plt1 DETACH PARTITION plt1_p3; @@ -1408,7 +1438,8 @@ SELECT avg(t1.a), avg(t2.b), t1.c, t2.c FROM plt1 t1 RIGHT JOIN plt2 t2 ON t1.c -> Hash -> Seq Scan on plt1_p3 t1_2 Filter: ((a % 25) = 0) -(23 rows) + Settings: enable_partitionwise_join = 'on' +(24 rows) -- -- multiple levels of partitioning @@ -1466,7 +1497,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1 -> Hash -> Seq Scan on prt1_l_p3_p1 t1_3 Filter: (b = 0) -(28 rows) + Settings: enable_partitionwise_join = 'on' +(29 rows) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b; a | c | b | c @@ -1511,7 +1543,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 LEFT JOIN prt2_l t2 ON t1.a = t2.b -> Hash -> Seq Scan on prt1_l_p3_p1 t1_3 Filter: (b = 0) -(29 rows) + Settings: enable_partitionwise_join = 'on' +(30 rows) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 LEFT JOIN prt2_l t2 ON t1.a = t2.b AND t1.c = t2.c WHERE t1.b = 0 ORDER BY t1.a, t2.b; a | c | b | c @@ -1564,7 +1597,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 RIGHT JOIN prt2_l t2 ON t1.a = t2.b -> Hash -> Seq Scan on prt2_l_p3_p1 t2_3 Filter: (a = 0) -(29 rows) + Settings: enable_partitionwise_join = 'on' +(30 rows) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 RIGHT JOIN prt2_l t2 ON t1.a = t2.b AND t1.c = t2.c WHERE t2.a = 0 ORDER BY t1.a, t2.b; a | c | b | c @@ -1615,7 +1649,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE prt1_l.b = 0) t1 -> Hash -> Seq Scan on prt2_l_p3_p1 Filter: (a = 0) -(31 rows) + Settings: enable_partitionwise_join = 'on' +(32 rows) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE prt1_l.b = 0) t1 FULL JOIN (SELECT * FROM prt2_l WHERE prt2_l.a = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c) ORDER BY t1.a, t2.b; a | c | b | c @@ -1689,7 +1724,8 @@ SELECT * FROM prt1_l t1 LEFT JOIN LATERAL Filter: ((t1_3.a = a) AND ((t1_3.c)::text = (c)::text)) -> Seq Scan on prt1_l_p3_p2 t2_4 Filter: ((t1_3.a = a) AND ((t1_3.c)::text = (c)::text)) -(44 rows) + Settings: enable_partitionwise_join = 'on' +(45 rows) SELECT * FROM prt1_l t1 LEFT JOIN LATERAL (SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.b AS t3b, least(t1.a,t2.a,t3.b) FROM prt1_l t2 JOIN prt2_l t3 ON (t2.a = t3.b AND t2.c = t3.c)) ss @@ -1726,7 +1762,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1 AND a = 2) -> Hash -> Result One-Time Filter: false -(11 rows) + Settings: enable_partitionwise_join = 'on' +(12 rows) -- Test case to verify proper handling of subqueries in a partitioned delete. -- The weird-looking lateral join is just there to force creation of a @@ -1769,7 +1806,8 @@ WHERE EXISTS ( -> Subquery Scan on ss_2 -> Limit -> Seq Scan on int8_tbl int8_tbl_2 -(28 rows) + Settings: enable_partitionwise_join = 'on' +(29 rows) -- -- negative testcases @@ -1812,7 +1850,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2 WHERE t1.a = t2.a; -> Seq Scan on prt4_n_p1 t2 -> Seq Scan on prt4_n_p2 t2_1 -> Seq Scan on prt4_n_p3 t2_2 -(11 rows) + Settings: enable_partitionwise_join = 'on' +(12 rows) EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2, prt2 t3 WHERE t1.a = t2.a and t1.a = t3.b; @@ -1841,7 +1880,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2, prt2 t3 WHERE t1.a = t2.a -> Seq Scan on prt1_p3 t1_2 -> Hash -> Seq Scan on prt2_p3 t3_2 -(23 rows) + Settings: enable_partitionwise_join = 'on' +(24 rows) -- partitionwise join can not be applied if there are no equi-join conditions -- between partition keys @@ -1861,7 +1901,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON (t1.a < t2.b); Index Cond: (b > t1.a) -> Index Scan using iprt2_p3_b on prt2_p3 t2_2 Index Cond: (b > t1.a) -(12 rows) + Settings: enable_partitionwise_join = 'on' +(13 rows) -- equi-join with join condition on partial keys does not qualify for -- partitionwise join @@ -1880,7 +1921,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1, prt2_m t2 WHERE t1.a = (t2.b + t2. -> Seq Scan on prt1_m_p1 t1 -> Seq Scan on prt1_m_p2 t1_1 -> Seq Scan on prt1_m_p3 t1_2 -(11 rows) + Settings: enable_partitionwise_join = 'on' +(12 rows) -- equi-join between out-of-order partition key columns does not qualify for -- partitionwise join @@ -1899,7 +1941,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.a = t2.b; -> Seq Scan on prt2_m_p1 t2 -> Seq Scan on prt2_m_p2 t2_1 -> Seq Scan on prt2_m_p3 t2_2 -(11 rows) + Settings: enable_partitionwise_join = 'on' +(12 rows) -- equi-join between non-key columns does not qualify for partitionwise join EXPLAIN (COSTS OFF) @@ -1917,7 +1960,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFT JOIN prt2_m t2 ON t1.c = t2.c; -> Seq Scan on prt2_m_p1 t2 -> Seq Scan on prt2_m_p2 t2_1 -> Seq Scan on prt2_m_p3 t2_2 -(11 rows) + Settings: enable_partitionwise_join = 'on' +(12 rows) -- partitionwise join can not be applied between tables with different -- partition lists @@ -1934,7 +1978,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 LEFT JOIN prt2_n t2 ON (t1.c = t2.c -> Append -> Seq Scan on prt1_n_p1 t1 -> Seq Scan on prt1_n_p2 t1_1 -(9 rows) + Settings: enable_partitionwise_join = 'on' +(10 rows) EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 JOIN prt2_n t2 ON (t1.c = t2.c) JOIN plt1 t3 ON (t1.c = t3.c); @@ -1956,7 +2001,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 JOIN prt2_n t2 ON (t1.c = t2.c) JOI -> Append -> Seq Scan on prt1_n_p1 t1 -> Seq Scan on prt1_n_p2 t1_1 -(16 rows) + Settings: enable_partitionwise_join = 'on' +(17 rows) -- partitionwise join can not be applied for a join between list and range -- partitioned table @@ -1974,7 +2020,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 FULL JOIN prt1 t2 ON (t1.c = t2.c); -> Append -> Seq Scan on prt1_n_p1 t1 -> Seq Scan on prt1_n_p2 t1_1 -(10 rows) + Settings: enable_partitionwise_join = 'on' +(11 rows) -- partitionwise join can not be applied if only one of joining table has -- default partition @@ -2001,5 +2048,6 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = Filter: (b = 0) -> Seq Scan on prt1_p3 t1_2 Filter: (b = 0) -(16 rows) + Settings: enable_partitionwise_join = 'on' +(17 rows) diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out index bd64bed8fc..a0eb3f62d5 100644 --- a/src/test/regress/expected/partition_prune.out +++ b/src/test/regress/expected/partition_prune.out @@ -1623,7 +1623,7 @@ create table ab_a3_b1 partition of ab_a3 for values in (1); create table ab_a3_b2 partition of ab_a3 for values in (2); create table ab_a3_b3 partition of ab_a3 for values in (3); -- Disallow index only scans as concurrent transactions may stop visibility --- bits being set causing "Heap Fetches" to be unstable in the EXPLAIN ANALYZE +-- bits being set causing "Heap Fetches" to be unstable in the EXPLAIN EXEC -- output. set enable_indexonlyscan = off; prepare ab_q1 (int, int, int) as @@ -1655,7 +1655,7 @@ execute ab_q1 (1, 8, 3); ---+--- (0 rows) -explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 2, 3); +explain (exec, costs off, summary off, timing off) execute ab_q1 (2, 2, 3); QUERY PLAN --------------------------------------------------------- Append (actual rows=0 loops=1) @@ -1666,9 +1666,10 @@ explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 2, 3); Filter: ((a >= $1) AND (a <= $2) AND (b <= $3)) -> Seq Scan on ab_a2_b3 (actual rows=0 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b <= $3)) -(8 rows) + Settings: enable_indexonlyscan = 'off' +(9 rows) -explain (analyze, costs off, summary off, timing off) execute ab_q1 (1, 2, 3); +explain (exec, costs off, summary off, timing off) execute ab_q1 (1, 2, 3); QUERY PLAN --------------------------------------------------------- Append (actual rows=0 loops=1) @@ -1685,7 +1686,8 @@ explain (analyze, costs off, summary off, timing off) execute ab_q1 (1, 2, 3); Filter: ((a >= $1) AND (a <= $2) AND (b <= $3)) -> Seq Scan on ab_a2_b3 (actual rows=0 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b <= $3)) -(14 rows) + Settings: enable_indexonlyscan = 'off' +(15 rows) deallocate ab_q1; -- Runtime pruning after optimizer pruning @@ -1718,7 +1720,7 @@ execute ab_q1 (1, 8); --- (0 rows) -explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 2); +explain (exec, costs off, summary off, timing off) execute ab_q1 (2, 2); QUERY PLAN ------------------------------------------------------- Append (actual rows=0 loops=1) @@ -1727,9 +1729,10 @@ explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 2); Filter: ((a >= $1) AND (a <= $2) AND (b < 3)) -> Seq Scan on ab_a2_b2 (actual rows=0 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b < 3)) -(6 rows) + Settings: enable_indexonlyscan = 'off' +(7 rows) -explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 4); +explain (exec, costs off, summary off, timing off) execute ab_q1 (2, 4); QUERY PLAN ------------------------------------------------------- Append (actual rows=0 loops=1) @@ -1742,7 +1745,8 @@ explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 4); Filter: ((a >= $1) AND (a <= $2) AND (b < 3)) -> Seq Scan on ab_a3_b2 (actual rows=0 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b < 3)) -(10 rows) + Settings: enable_indexonlyscan = 'off' +(11 rows) -- Ensure a mix of PARAM_EXTERN and PARAM_EXEC Params work together at -- different levels of partitioning. @@ -1773,7 +1777,7 @@ execute ab_q2 (1, 8); --- (0 rows) -explain (analyze, costs off, summary off, timing off) execute ab_q2 (2, 2); +explain (exec, costs off, summary off, timing off) execute ab_q2 (2, 2); QUERY PLAN -------------------------------------------------------- Append (actual rows=0 loops=1) @@ -1786,7 +1790,8 @@ explain (analyze, costs off, summary off, timing off) execute ab_q2 (2, 2); Filter: ((a >= $1) AND (a <= $2) AND (b < $0)) -> Seq Scan on ab_a2_b3 (never executed) Filter: ((a >= $1) AND (a <= $2) AND (b < $0)) -(10 rows) + Settings: enable_indexonlyscan = 'off' +(11 rows) -- As above, but swap the PARAM_EXEC Param to the first partition level prepare ab_q3 (int, int) as @@ -1816,7 +1821,7 @@ execute ab_q3 (1, 8); --- (0 rows) -explain (analyze, costs off, summary off, timing off) execute ab_q3 (2, 2); +explain (exec, costs off, summary off, timing off) execute ab_q3 (2, 2); QUERY PLAN -------------------------------------------------------- Append (actual rows=0 loops=1) @@ -1829,7 +1834,8 @@ explain (analyze, costs off, summary off, timing off) execute ab_q3 (2, 2); Filter: ((b >= $1) AND (b <= $2) AND (a < $0)) -> Seq Scan on ab_a3_b2 (never executed) Filter: ((b >= $1) AND (b <= $2) AND (a < $0)) -(10 rows) + Settings: enable_indexonlyscan = 'off' +(11 rows) -- Test a backwards Append scan create table list_part (a int) partition by list (a); @@ -1857,48 +1863,63 @@ begin; -- Test run-time pruning using stable functions create function list_part_fn(int) returns int as $$ begin return $1; end;$$ language plpgsql stable; -- Ensure pruning works using a stable function containing no Vars -explain (analyze, costs off, summary off, timing off) select * from list_part where a = list_part_fn(1); +explain (exec, costs off, summary off, timing off) select * from list_part where a = list_part_fn(1); QUERY PLAN ------------------------------------------------------ Append (actual rows=1 loops=1) + Buffers: shared hit=1 Subplans Removed: 3 -> Seq Scan on list_part1 (actual rows=1 loops=1) Filter: (a = list_part_fn(1)) -(4 rows) + Buffers: shared hit=1 + Settings: enable_indexonlyscan = 'off' +(7 rows) -- Ensure pruning does not take place when the function has a Var parameter -explain (analyze, costs off, summary off, timing off) select * from list_part where a = list_part_fn(a); +explain (exec, costs off, summary off, timing off) select * from list_part where a = list_part_fn(a); QUERY PLAN ------------------------------------------------------ Append (actual rows=4 loops=1) + Buffers: shared hit=4 -> Seq Scan on list_part1 (actual rows=1 loops=1) Filter: (a = list_part_fn(a)) + Buffers: shared hit=1 -> Seq Scan on list_part2 (actual rows=1 loops=1) Filter: (a = list_part_fn(a)) + Buffers: shared hit=1 -> Seq Scan on list_part3 (actual rows=1 loops=1) Filter: (a = list_part_fn(a)) + Buffers: shared hit=1 -> Seq Scan on list_part4 (actual rows=1 loops=1) Filter: (a = list_part_fn(a)) -(9 rows) + Buffers: shared hit=1 + Settings: enable_indexonlyscan = 'off' +(15 rows) -- Ensure pruning does not take place when the expression contains a Var. -explain (analyze, costs off, summary off, timing off) select * from list_part where a = list_part_fn(1) + a; +explain (exec, costs off, summary off, timing off) select * from list_part where a = list_part_fn(1) + a; QUERY PLAN ------------------------------------------------------ Append (actual rows=0 loops=1) + Buffers: shared hit=4 -> Seq Scan on list_part1 (actual rows=0 loops=1) Filter: (a = (list_part_fn(1) + a)) Rows Removed by Filter: 1 + Buffers: shared hit=1 -> Seq Scan on list_part2 (actual rows=0 loops=1) Filter: (a = (list_part_fn(1) + a)) Rows Removed by Filter: 1 + Buffers: shared hit=1 -> Seq Scan on list_part3 (actual rows=0 loops=1) Filter: (a = (list_part_fn(1) + a)) Rows Removed by Filter: 1 + Buffers: shared hit=1 -> Seq Scan on list_part4 (actual rows=0 loops=1) Filter: (a = (list_part_fn(1) + a)) Rows Removed by Filter: 1 -(13 rows) + Buffers: shared hit=1 + Settings: enable_indexonlyscan = 'off' +(19 rows) rollback; drop table list_part; @@ -1913,7 +1934,7 @@ declare ln text; begin for ln in - execute format('explain (analyze, costs off, summary off, timing off) %s', + execute format('explain (exec, costs off, summary off, timing off) %s', $1) loop if ln like '%Parallel%' then @@ -1963,8 +1984,8 @@ execute ab_q4 (1, 8); (1 row) select explain_parallel_append('execute ab_q4 (2, 2)'); - explain_parallel_append -------------------------------------------------------------------------------- + explain_parallel_append +---------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate (actual rows=1 loops=1) -> Gather (actual rows=3 loops=1) Workers Planned: 2 @@ -1978,7 +1999,8 @@ select explain_parallel_append('execute ab_q4 (2, 2)'); Filter: ((a >= $1) AND (a <= $2) AND (b < 4)) -> Parallel Seq Scan on ab_a2_b3 (actual rows=0 loops=N) Filter: ((a >= $1) AND (a <= $2) AND (b < 4)) -(13 rows) + Settings: enable_indexonlyscan = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(14 rows) -- Test run-time pruning with IN lists. prepare ab_q5 (int, int, int) as @@ -2016,8 +2038,8 @@ execute ab_q5 (1, 2, 3); (1 row) select explain_parallel_append('execute ab_q5 (1, 1, 1)'); - explain_parallel_append -------------------------------------------------------------------------------- + explain_parallel_append +---------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate (actual rows=1 loops=1) -> Gather (actual rows=3 loops=1) Workers Planned: 2 @@ -2031,11 +2053,12 @@ select explain_parallel_append('execute ab_q5 (1, 1, 1)'); Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3]))) -> Parallel Seq Scan on ab_a1_b3 (actual rows=0 loops=N) Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3]))) -(13 rows) + Settings: enable_indexonlyscan = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(14 rows) select explain_parallel_append('execute ab_q5 (2, 3, 3)'); - explain_parallel_append -------------------------------------------------------------------------------- + explain_parallel_append +---------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate (actual rows=1 loops=1) -> Gather (actual rows=3 loops=1) Workers Planned: 2 @@ -2055,13 +2078,14 @@ select explain_parallel_append('execute ab_q5 (2, 3, 3)'); Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3]))) -> Parallel Seq Scan on ab_a3_b3 (actual rows=0 loops=N) Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3]))) -(19 rows) + Settings: enable_indexonlyscan = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(20 rows) -- Try some params whose values do not belong to any partition. -- We'll still get a single subplan in this case, but it should not be scanned. select explain_parallel_append('execute ab_q5 (33, 44, 55)'); - explain_parallel_append -------------------------------------------------------------------------------- + explain_parallel_append +---------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate (actual rows=1 loops=1) -> Gather (actual rows=3 loops=1) Workers Planned: 2 @@ -2071,12 +2095,13 @@ select explain_parallel_append('execute ab_q5 (33, 44, 55)'); Subplans Removed: 8 -> Parallel Seq Scan on ab_a1_b1 (never executed) Filter: ((b < 4) AND (a = ANY (ARRAY[$1, $2, $3]))) -(9 rows) + Settings: enable_indexonlyscan = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(10 rows) -- Test Parallel Append with PARAM_EXEC Params select explain_parallel_append('select count(*) from ab where (a = (select 1) or a = (select 3)) and b = 2'); - explain_parallel_append -------------------------------------------------------------------------- + explain_parallel_append +---------------------------------------------------------------------------------------------------------------------------------- Aggregate (actual rows=1 loops=1) InitPlan 1 (returns $0) -> Result (actual rows=1 loops=1) @@ -2093,7 +2118,8 @@ select explain_parallel_append('select count(*) from ab where (a = (select 1) or Filter: ((b = 2) AND ((a = $0) OR (a = $1))) -> Parallel Seq Scan on ab_a3_b2 (actual rows=0 loops=N) Filter: ((b = 2) AND ((a = $0) OR (a = $1))) -(16 rows) + Settings: enable_indexonlyscan = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(17 rows) -- Test pruning during parallel nested loop query create table lprt_a (a int not null); @@ -2114,23 +2140,32 @@ create index ab_a3_b3_a_idx on ab_a3_b3 (a); set enable_hashjoin = 0; set enable_mergejoin = 0; select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a where a.a in(0, 0, 1)'); - explain_parallel_append ---------------------------------------------------------------------------------------------------- + explain_parallel_append +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate (actual rows=1 loops=1) + Buffers: shared hit=13 -> Gather (actual rows=2 loops=1) Workers Planned: 1 Workers Launched: 1 + Buffers: shared hit=13 -> Partial Aggregate (actual rows=1 loops=2) + Buffers: shared hit=13 -> Nested Loop (actual rows=0 loops=2) + Buffers: shared hit=13 -> Parallel Seq Scan on lprt_a a (actual rows=51 loops=N) Filter: (a = ANY ('{0,0,1}'::integer[])) + Buffers: shared hit=1 -> Append (actual rows=0 loops=102) + Buffers: shared hit=12 -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=0 loops=2) Index Cond: (a = a.a) + Buffers: shared hit=4 -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=0 loops=2) Index Cond: (a = a.a) + Buffers: shared hit=4 -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=0 loops=2) Index Cond: (a = a.a) + Buffers: shared hit=4 -> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed) Index Cond: (a = a.a) -> Index Scan using ab_a2_b2_a_idx on ab_a2_b2 (never executed) @@ -2143,28 +2178,38 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on Index Cond: (a = a.a) -> Index Scan using ab_a3_b3_a_idx on ab_a3_b3 (never executed) Index Cond: (a = a.a) -(27 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(37 rows) -- Ensure the same partitions are pruned when we make the nested loop -- parameter an Expr rather than a plain Param. select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a + 0 where a.a in(0, 0, 1)'); - explain_parallel_append ---------------------------------------------------------------------------------------------------- + explain_parallel_append +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate (actual rows=1 loops=1) + Buffers: shared hit=13 -> Gather (actual rows=2 loops=1) Workers Planned: 1 Workers Launched: 1 + Buffers: shared hit=13 -> Partial Aggregate (actual rows=1 loops=2) + Buffers: shared hit=13 -> Nested Loop (actual rows=0 loops=2) + Buffers: shared hit=13 -> Parallel Seq Scan on lprt_a a (actual rows=51 loops=N) Filter: (a = ANY ('{0,0,1}'::integer[])) + Buffers: shared hit=1 -> Append (actual rows=0 loops=102) + Buffers: shared hit=12 -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=0 loops=2) Index Cond: (a = (a.a + 0)) + Buffers: shared hit=4 -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=0 loops=2) Index Cond: (a = (a.a + 0)) + Buffers: shared hit=4 -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=0 loops=2) Index Cond: (a = (a.a + 0)) + Buffers: shared hit=4 -> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed) Index Cond: (a = (a.a + 0)) -> Index Scan using ab_a2_b2_a_idx on ab_a2_b2 (never executed) @@ -2177,27 +2222,37 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on Index Cond: (a = (a.a + 0)) -> Index Scan using ab_a3_b3_a_idx on ab_a3_b3 (never executed) Index Cond: (a = (a.a + 0)) -(27 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(37 rows) insert into lprt_a values(3),(3); select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a where a.a in(1, 0, 3)'); - explain_parallel_append ---------------------------------------------------------------------------------------------------- + explain_parallel_append +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate (actual rows=1 loops=1) + Buffers: shared hit=25 -> Gather (actual rows=2 loops=1) Workers Planned: 1 Workers Launched: 1 + Buffers: shared hit=25 -> Partial Aggregate (actual rows=1 loops=2) + Buffers: shared hit=25 -> Nested Loop (actual rows=0 loops=2) + Buffers: shared hit=25 -> Parallel Seq Scan on lprt_a a (actual rows=52 loops=N) Filter: (a = ANY ('{1,0,3}'::integer[])) + Buffers: shared hit=1 -> Append (actual rows=0 loops=104) + Buffers: shared hit=24 -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=0 loops=2) Index Cond: (a = a.a) + Buffers: shared hit=4 -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=0 loops=2) Index Cond: (a = a.a) + Buffers: shared hit=4 -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=0 loops=2) Index Cond: (a = a.a) + Buffers: shared hit=4 -> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed) Index Cond: (a = a.a) -> Index Scan using ab_a2_b2_a_idx on ab_a2_b2 (never executed) @@ -2206,31 +2261,44 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on Index Cond: (a = a.a) -> Index Scan using ab_a3_b1_a_idx on ab_a3_b1 (actual rows=0 loops=2) Index Cond: (a = a.a) + Buffers: shared hit=4 -> Index Scan using ab_a3_b2_a_idx on ab_a3_b2 (actual rows=0 loops=2) Index Cond: (a = a.a) + Buffers: shared hit=4 -> Index Scan using ab_a3_b3_a_idx on ab_a3_b3 (actual rows=0 loops=2) Index Cond: (a = a.a) -(27 rows) + Buffers: shared hit=4 + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(40 rows) select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a where a.a in(1, 0, 0)'); - explain_parallel_append ---------------------------------------------------------------------------------------------------- + explain_parallel_append +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate (actual rows=1 loops=1) + Buffers: shared hit=13 -> Gather (actual rows=2 loops=1) Workers Planned: 1 Workers Launched: 1 + Buffers: shared hit=13 -> Partial Aggregate (actual rows=1 loops=2) + Buffers: shared hit=13 -> Nested Loop (actual rows=0 loops=2) + Buffers: shared hit=13 -> Parallel Seq Scan on lprt_a a (actual rows=51 loops=N) Filter: (a = ANY ('{1,0,0}'::integer[])) Rows Removed by Filter: 1 + Buffers: shared hit=1 -> Append (actual rows=0 loops=102) + Buffers: shared hit=12 -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (actual rows=0 loops=2) Index Cond: (a = a.a) + Buffers: shared hit=4 -> Index Scan using ab_a1_b2_a_idx on ab_a1_b2 (actual rows=0 loops=2) Index Cond: (a = a.a) + Buffers: shared hit=4 -> Index Scan using ab_a1_b3_a_idx on ab_a1_b3 (actual rows=0 loops=2) Index Cond: (a = a.a) + Buffers: shared hit=4 -> Index Scan using ab_a2_b1_a_idx on ab_a2_b1 (never executed) Index Cond: (a = a.a) -> Index Scan using ab_a2_b2_a_idx on ab_a2_b2 (never executed) @@ -2243,21 +2311,27 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on Index Cond: (a = a.a) -> Index Scan using ab_a3_b3_a_idx on ab_a3_b3 (never executed) Index Cond: (a = a.a) -(28 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(38 rows) delete from lprt_a where a = 1; select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a where a.a in(1, 0, 0)'); - explain_parallel_append --------------------------------------------------------------------------------------------- + explain_parallel_append +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate (actual rows=1 loops=1) + Buffers: shared hit=1 -> Gather (actual rows=2 loops=1) Workers Planned: 1 Workers Launched: 1 + Buffers: shared hit=1 -> Partial Aggregate (actual rows=1 loops=2) + Buffers: shared hit=1 -> Nested Loop (actual rows=0 loops=2) + Buffers: shared hit=1 -> Parallel Seq Scan on lprt_a a (actual rows=50 loops=N) Filter: (a = ANY ('{1,0,0}'::integer[])) Rows Removed by Filter: 1 + Buffers: shared hit=1 -> Append (actual rows=0 loops=100) -> Index Scan using ab_a1_b1_a_idx on ab_a1_b1 (never executed) Index Cond: (a = a.a) @@ -2277,7 +2351,8 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on Index Cond: (a = a.a) -> Index Scan using ab_a3_b3_a_idx on ab_a3_b3 (never executed) Index Cond: (a = a.a) -(28 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(34 rows) reset enable_hashjoin; reset enable_mergejoin; @@ -2286,17 +2361,22 @@ reset parallel_tuple_cost; reset min_parallel_table_scan_size; reset max_parallel_workers_per_gather; -- Test run-time partition pruning with an initplan -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from ab where a = (select max(a) from lprt_a) and b = (select max(a)-1 from lprt_a); QUERY PLAN ------------------------------------------------------------------------- Append (actual rows=0 loops=1) + Buffers: shared hit=4 InitPlan 1 (returns $0) -> Aggregate (actual rows=1 loops=1) + Buffers: shared hit=1 -> Seq Scan on lprt_a (actual rows=102 loops=1) + Buffers: shared hit=1 InitPlan 2 (returns $1) -> Aggregate (actual rows=1 loops=1) + Buffers: shared hit=1 -> Seq Scan on lprt_a lprt_a_1 (actual rows=102 loops=1) + Buffers: shared hit=1 -> Bitmap Heap Scan on ab_a1_b1 (never executed) Recheck Cond: (a = $0) Filter: (b = $1) @@ -2335,29 +2415,36 @@ select * from ab where a = (select max(a) from lprt_a) and b = (select max(a)-1 -> Bitmap Heap Scan on ab_a3_b2 (actual rows=0 loops=1) Recheck Cond: (a = $0) Filter: (b = $1) + Buffers: shared hit=2 -> Bitmap Index Scan on ab_a3_b2_a_idx (actual rows=0 loops=1) Index Cond: (a = $0) + Buffers: shared hit=2 -> Bitmap Heap Scan on ab_a3_b3 (never executed) Recheck Cond: (a = $0) Filter: (b = $1) -> Bitmap Index Scan on ab_a3_b3_a_idx (never executed) Index Cond: (a = $0) -(52 rows) + Settings: enable_indexonlyscan = 'off' +(60 rows) -- Test run-time partition pruning with UNION ALL parents -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from (select * from ab where a = 1 union all select * from ab) ab where b = (select 1); QUERY PLAN ------------------------------------------------------------------------------- Append (actual rows=0 loops=1) + Buffers: shared hit=2 InitPlan 1 (returns $0) -> Result (actual rows=1 loops=1) -> Append (actual rows=0 loops=1) + Buffers: shared hit=2 -> Bitmap Heap Scan on ab_a1_b1 ab_a1_b1_1 (actual rows=0 loops=1) Recheck Cond: (a = 1) Filter: (b = $0) + Buffers: shared hit=2 -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1) Index Cond: (a = 1) + Buffers: shared hit=2 -> Bitmap Heap Scan on ab_a1_b2 ab_a1_b2_1 (never executed) Recheck Cond: (a = 1) Filter: (b = $0) @@ -2386,22 +2473,27 @@ select * from (select * from ab where a = 1 union all select * from ab) ab where Filter: (b = $0) -> Seq Scan on ab_a3_b3 (never executed) Filter: (b = $0) -(37 rows) + Settings: enable_indexonlyscan = 'off' +(42 rows) -- A case containing a UNION ALL with a non-partitioned child. -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from (select * from ab where a = 1 union all (values(10,5)) union all select * from ab) ab where b = (select 1); QUERY PLAN ------------------------------------------------------------------------------- Append (actual rows=0 loops=1) + Buffers: shared hit=2 InitPlan 1 (returns $0) -> Result (actual rows=1 loops=1) -> Append (actual rows=0 loops=1) + Buffers: shared hit=2 -> Bitmap Heap Scan on ab_a1_b1 ab_a1_b1_1 (actual rows=0 loops=1) Recheck Cond: (a = 1) Filter: (b = $0) + Buffers: shared hit=2 -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1) Index Cond: (a = 1) + Buffers: shared hit=2 -> Bitmap Heap Scan on ab_a1_b2 ab_a1_b2_1 (never executed) Recheck Cond: (a = 1) Filter: (b = $0) @@ -2432,7 +2524,8 @@ select * from (select * from ab where a = 1 union all (values(10,5)) union all s Filter: (b = $0) -> Seq Scan on ab_a3_b3 (never executed) Filter: (b = $0) -(39 rows) + Settings: enable_indexonlyscan = 'off' +(44 rows) -- Another UNION ALL test, but containing a mix of exec init and exec run-time pruning. create table xy_1 (x int, y int); @@ -2449,10 +2542,11 @@ union all select tableoid::regclass,a,b from ab ) ab where a = $1 and b = (select -10); -- Ensure the xy_1 subplan is not pruned. -explain (analyze, costs off, summary off, timing off) execute ab_q6(1); - QUERY PLAN --------------------------------------------------------- +explain (exec, costs off, summary off, timing off) execute ab_q6(1); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- Append (actual rows=0 loops=1) + Buffers: shared hit=1 InitPlan 1 (returns $0) -> Result (actual rows=1 loops=1) Subplans Removed: 12 @@ -2465,13 +2559,15 @@ explain (analyze, costs off, summary off, timing off) execute ab_q6(1); -> Seq Scan on xy_1 (actual rows=0 loops=1) Filter: ((x = $1) AND (y = $0)) Rows Removed by Filter: 1 + Buffers: shared hit=1 -> Seq Scan on ab_a1_b1 ab_a1_b1_1 (never executed) Filter: ((a = $1) AND (b = $0)) -> Seq Scan on ab_a1_b2 ab_a1_b2_1 (never executed) Filter: ((a = $1) AND (b = $0)) -> Seq Scan on ab_a1_b3 ab_a1_b3_1 (never executed) Filter: ((a = $1) AND (b = $0)) -(19 rows) + Settings: enable_bitmapscan = 'off', enable_indexonlyscan = 'off', enable_indexscan = 'off', plan_cache_mode = 'force_generic_plan' +(22 rows) -- Ensure we see just the xy_1 row. execute ab_q6(100); @@ -2491,7 +2587,7 @@ deallocate ab_q5; deallocate ab_q6; -- UPDATE on a partition subtree has been seen to have problems. insert into ab values (1,2); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) update ab_a1 set b = 3 from ab where ab.a = 1 and ab.a = ab_a1.a; QUERY PLAN ------------------------------------------------------------------------------------- @@ -2499,68 +2595,103 @@ update ab_a1 set b = 3 from ab where ab.a = 1 and ab.a = ab_a1.a; Update on ab_a1_b1 Update on ab_a1_b2 Update on ab_a1_b3 + Buffers: shared hit=25 dirtied=3 written=2 -> Nested Loop (actual rows=0 loops=1) + Buffers: shared hit=8 -> Append (actual rows=1 loops=1) + Buffers: shared hit=6 -> Bitmap Heap Scan on ab_a1_b1 ab_a1_b1_1 (actual rows=0 loops=1) Recheck Cond: (a = 1) + Buffers: shared hit=2 -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1) Index Cond: (a = 1) + Buffers: shared hit=2 -> Bitmap Heap Scan on ab_a1_b2 ab_a1_b2_1 (actual rows=1 loops=1) Recheck Cond: (a = 1) Heap Blocks: exact=1 + Buffers: shared hit=2 -> Bitmap Index Scan on ab_a1_b2_a_idx (actual rows=1 loops=1) Index Cond: (a = 1) + Buffers: shared hit=1 -> Bitmap Heap Scan on ab_a1_b3 ab_a1_b3_1 (actual rows=0 loops=1) Recheck Cond: (a = 1) + Buffers: shared hit=2 -> Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=0 loops=1) Index Cond: (a = 1) + Buffers: shared hit=2 -> Materialize (actual rows=0 loops=1) + Buffers: shared hit=2 -> Bitmap Heap Scan on ab_a1_b1 (actual rows=0 loops=1) Recheck Cond: (a = 1) + Buffers: shared hit=2 -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1) Index Cond: (a = 1) + Buffers: shared hit=2 -> Nested Loop (actual rows=1 loops=1) + Buffers: shared hit=8 -> Append (actual rows=1 loops=1) + Buffers: shared hit=6 -> Bitmap Heap Scan on ab_a1_b1 ab_a1_b1_1 (actual rows=0 loops=1) Recheck Cond: (a = 1) + Buffers: shared hit=2 -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1) Index Cond: (a = 1) + Buffers: shared hit=2 -> Bitmap Heap Scan on ab_a1_b2 ab_a1_b2_1 (actual rows=1 loops=1) Recheck Cond: (a = 1) Heap Blocks: exact=1 + Buffers: shared hit=2 -> Bitmap Index Scan on ab_a1_b2_a_idx (actual rows=1 loops=1) Index Cond: (a = 1) + Buffers: shared hit=1 -> Bitmap Heap Scan on ab_a1_b3 ab_a1_b3_1 (actual rows=0 loops=1) Recheck Cond: (a = 1) + Buffers: shared hit=2 -> Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1) Index Cond: (a = 1) + Buffers: shared hit=2 -> Materialize (actual rows=1 loops=1) + Buffers: shared hit=2 -> Bitmap Heap Scan on ab_a1_b2 (actual rows=1 loops=1) Recheck Cond: (a = 1) Heap Blocks: exact=1 + Buffers: shared hit=2 -> Bitmap Index Scan on ab_a1_b2_a_idx (actual rows=1 loops=1) Index Cond: (a = 1) + Buffers: shared hit=1 -> Nested Loop (actual rows=0 loops=1) + Buffers: shared hit=6 -> Append (actual rows=1 loops=1) + Buffers: shared hit=5 -> Bitmap Heap Scan on ab_a1_b1 ab_a1_b1_1 (actual rows=0 loops=1) Recheck Cond: (a = 1) + Buffers: shared hit=2 -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1) Index Cond: (a = 1) + Buffers: shared hit=2 -> Bitmap Heap Scan on ab_a1_b2 ab_a1_b2_1 (actual rows=1 loops=1) Recheck Cond: (a = 1) Heap Blocks: exact=1 + Buffers: shared hit=2 -> Bitmap Index Scan on ab_a1_b2_a_idx (actual rows=1 loops=1) Index Cond: (a = 1) + Buffers: shared hit=1 -> Bitmap Heap Scan on ab_a1_b3 ab_a1_b3_1 (actual rows=0 loops=1) Recheck Cond: (a = 1) + Buffers: shared hit=1 -> Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1) Index Cond: (a = 1) + Buffers: shared hit=1 -> Materialize (actual rows=0 loops=1) + Buffers: shared hit=1 -> Bitmap Heap Scan on ab_a1_b3 (actual rows=0 loops=1) Recheck Cond: (a = 1) + Buffers: shared hit=1 -> Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1) Index Cond: (a = 1) -(65 rows) + Buffers: shared hit=1 + Settings: enable_indexonlyscan = 'off' +(100 rows) table ab; a | b @@ -2571,7 +2702,7 @@ table ab; -- Test UPDATE where source relation has run-time pruning enabled truncate ab; insert into ab values (1, 1), (1, 2), (1, 3), (2, 1); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) update ab_a1 set b = 3 from ab_a2 where ab_a2.b = (select 1); QUERY PLAN ---------------------------------------------------------------------- @@ -2579,39 +2710,56 @@ update ab_a1 set b = 3 from ab_a2 where ab_a2.b = (select 1); Update on ab_a1_b1 Update on ab_a1_b2 Update on ab_a1_b3 + Buffers: shared hit=13 InitPlan 1 (returns $0) -> Result (actual rows=1 loops=1) -> Nested Loop (actual rows=1 loops=1) + Buffers: shared hit=2 -> Seq Scan on ab_a1_b1 (actual rows=1 loops=1) + Buffers: shared hit=1 -> Materialize (actual rows=1 loops=1) + Buffers: shared hit=1 -> Append (actual rows=1 loops=1) + Buffers: shared hit=1 -> Seq Scan on ab_a2_b1 (actual rows=1 loops=1) Filter: (b = $0) + Buffers: shared hit=1 -> Seq Scan on ab_a2_b2 (never executed) Filter: (b = $0) -> Seq Scan on ab_a2_b3 (never executed) Filter: (b = $0) -> Nested Loop (actual rows=1 loops=1) + Buffers: shared hit=2 -> Seq Scan on ab_a1_b2 (actual rows=1 loops=1) + Buffers: shared hit=1 -> Materialize (actual rows=1 loops=1) + Buffers: shared hit=1 -> Append (actual rows=1 loops=1) + Buffers: shared hit=1 -> Seq Scan on ab_a2_b1 (actual rows=1 loops=1) Filter: (b = $0) + Buffers: shared hit=1 -> Seq Scan on ab_a2_b2 (never executed) Filter: (b = $0) -> Seq Scan on ab_a2_b3 (never executed) Filter: (b = $0) -> Nested Loop (actual rows=1 loops=1) + Buffers: shared hit=2 -> Seq Scan on ab_a1_b3 (actual rows=1 loops=1) + Buffers: shared hit=1 -> Materialize (actual rows=1 loops=1) + Buffers: shared hit=1 -> Append (actual rows=1 loops=1) + Buffers: shared hit=1 -> Seq Scan on ab_a2_b1 (actual rows=1 loops=1) Filter: (b = $0) + Buffers: shared hit=1 -> Seq Scan on ab_a2_b2 (never executed) Filter: (b = $0) -> Seq Scan on ab_a2_b3 (never executed) Filter: (b = $0) -(36 rows) + Settings: enable_indexonlyscan = 'off' +(53 rows) select tableoid::regclass, * from ab; tableoid | a | b @@ -2643,17 +2791,22 @@ create index tprt6_idx on tprt_6 (col1); insert into tprt values (10), (20), (501), (502), (505), (1001), (4500); set enable_hashjoin = off; set enable_mergejoin = off; -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from tbl1 join tprt on tbl1.col1 > tprt.col1; - QUERY PLAN --------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------- Nested Loop (actual rows=6 loops=1) + Buffers: shared hit=7 -> Seq Scan on tbl1 (actual rows=2 loops=1) + Buffers: shared hit=1 -> Append (actual rows=3 loops=2) + Buffers: shared hit=6 -> Index Scan using tprt1_idx on tprt_1 (actual rows=2 loops=2) Index Cond: (col1 < tbl1.col1) + Buffers: shared hit=4 -> Index Scan using tprt2_idx on tprt_2 (actual rows=2 loops=1) Index Cond: (col1 < tbl1.col1) + Buffers: shared hit=2 -> Index Scan using tprt3_idx on tprt_3 (never executed) Index Cond: (col1 < tbl1.col1) -> Index Scan using tprt4_idx on tprt_4 (never executed) @@ -2662,19 +2815,24 @@ select * from tbl1 join tprt on tbl1.col1 > tprt.col1; Index Cond: (col1 < tbl1.col1) -> Index Scan using tprt6_idx on tprt_6 (never executed) Index Cond: (col1 < tbl1.col1) -(15 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(21 rows) -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from tbl1 join tprt on tbl1.col1 = tprt.col1; - QUERY PLAN --------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------- Nested Loop (actual rows=2 loops=1) + Buffers: shared hit=5 -> Seq Scan on tbl1 (actual rows=2 loops=1) + Buffers: shared hit=1 -> Append (actual rows=1 loops=2) + Buffers: shared hit=4 -> Index Scan using tprt1_idx on tprt_1 (never executed) Index Cond: (col1 = tbl1.col1) -> Index Scan using tprt2_idx on tprt_2 (actual rows=1 loops=2) Index Cond: (col1 = tbl1.col1) + Buffers: shared hit=4 -> Index Scan using tprt3_idx on tprt_3 (never executed) Index Cond: (col1 = tbl1.col1) -> Index Scan using tprt4_idx on tprt_4 (never executed) @@ -2683,7 +2841,8 @@ select * from tbl1 join tprt on tbl1.col1 = tprt.col1; Index Cond: (col1 = tbl1.col1) -> Index Scan using tprt6_idx on tprt_6 (never executed) Index Cond: (col1 = tbl1.col1) -(15 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(20 rows) select tbl1.col1, tprt.col1 from tbl1 inner join tprt on tbl1.col1 > tprt.col1 @@ -2709,47 +2868,60 @@ order by tbl1.col1, tprt.col1; -- Multiple partitions insert into tbl1 values (1001), (1010), (1011); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from tbl1 inner join tprt on tbl1.col1 > tprt.col1; - QUERY PLAN --------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------- Nested Loop (actual rows=23 loops=1) + Buffers: shared hit=23 -> Seq Scan on tbl1 (actual rows=5 loops=1) + Buffers: shared hit=1 -> Append (actual rows=5 loops=5) + Buffers: shared hit=22 -> Index Scan using tprt1_idx on tprt_1 (actual rows=2 loops=5) Index Cond: (col1 < tbl1.col1) + Buffers: shared hit=10 -> Index Scan using tprt2_idx on tprt_2 (actual rows=3 loops=4) Index Cond: (col1 < tbl1.col1) + Buffers: shared hit=8 -> Index Scan using tprt3_idx on tprt_3 (actual rows=1 loops=2) Index Cond: (col1 < tbl1.col1) + Buffers: shared hit=4 -> Index Scan using tprt4_idx on tprt_4 (never executed) Index Cond: (col1 < tbl1.col1) -> Index Scan using tprt5_idx on tprt_5 (never executed) Index Cond: (col1 < tbl1.col1) -> Index Scan using tprt6_idx on tprt_6 (never executed) Index Cond: (col1 < tbl1.col1) -(15 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(22 rows) -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from tbl1 inner join tprt on tbl1.col1 = tprt.col1; - QUERY PLAN --------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------- Nested Loop (actual rows=3 loops=1) + Buffers: shared hit=9 -> Seq Scan on tbl1 (actual rows=5 loops=1) + Buffers: shared hit=1 -> Append (actual rows=1 loops=5) + Buffers: shared hit=8 -> Index Scan using tprt1_idx on tprt_1 (never executed) Index Cond: (col1 = tbl1.col1) -> Index Scan using tprt2_idx on tprt_2 (actual rows=1 loops=2) Index Cond: (col1 = tbl1.col1) + Buffers: shared hit=4 -> Index Scan using tprt3_idx on tprt_3 (actual rows=0 loops=3) Index Cond: (col1 = tbl1.col1) + Buffers: shared hit=4 -> Index Scan using tprt4_idx on tprt_4 (never executed) Index Cond: (col1 = tbl1.col1) -> Index Scan using tprt5_idx on tprt_5 (never executed) Index Cond: (col1 = tbl1.col1) -> Index Scan using tprt6_idx on tprt_6 (never executed) Index Cond: (col1 = tbl1.col1) -(15 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(21 rows) select tbl1.col1, tprt.col1 from tbl1 inner join tprt on tbl1.col1 > tprt.col1 @@ -2794,13 +2966,16 @@ order by tbl1.col1, tprt.col1; -- Last partition delete from tbl1; insert into tbl1 values (4400); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from tbl1 join tprt on tbl1.col1 < tprt.col1; - QUERY PLAN --------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------- Nested Loop (actual rows=1 loops=1) + Buffers: shared hit=3 -> Seq Scan on tbl1 (actual rows=1 loops=1) + Buffers: shared hit=1 -> Append (actual rows=1 loops=1) + Buffers: shared hit=2 -> Index Scan using tprt1_idx on tprt_1 (never executed) Index Cond: (col1 > tbl1.col1) -> Index Scan using tprt2_idx on tprt_2 (never executed) @@ -2813,7 +2988,9 @@ select * from tbl1 join tprt on tbl1.col1 < tprt.col1; Index Cond: (col1 > tbl1.col1) -> Index Scan using tprt6_idx on tprt_6 (actual rows=1 loops=1) Index Cond: (col1 > tbl1.col1) -(15 rows) + Buffers: shared hit=2 + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(20 rows) select tbl1.col1, tprt.col1 from tbl1 inner join tprt on tbl1.col1 < tprt.col1 @@ -2826,12 +3003,14 @@ order by tbl1.col1, tprt.col1; -- No matching partition delete from tbl1; insert into tbl1 values (10000); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from tbl1 join tprt on tbl1.col1 = tprt.col1; - QUERY PLAN -------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------- Nested Loop (actual rows=0 loops=1) + Buffers: shared hit=1 -> Seq Scan on tbl1 (actual rows=1 loops=1) + Buffers: shared hit=1 -> Append (actual rows=0 loops=1) -> Index Scan using tprt1_idx on tprt_1 (never executed) Index Cond: (col1 = tbl1.col1) @@ -2845,7 +3024,8 @@ select * from tbl1 join tprt on tbl1.col1 = tprt.col1; Index Cond: (col1 = tbl1.col1) -> Index Scan using tprt6_idx on tprt_6 (never executed) Index Cond: (col1 = tbl1.col1) -(15 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(18 rows) select tbl1.col1, tprt.col1 from tbl1 inner join tprt on tbl1.col1 = tprt.col1 @@ -2893,12 +3073,13 @@ execute part_abc_q1 (1, 2, 3); (0 rows) -- Single partition should be scanned. -explain (analyze, costs off, summary off, timing off) execute part_abc_q1 (1, 2, 3); - QUERY PLAN -------------------------------------------------- +explain (exec, costs off, summary off, timing off) execute part_abc_q1 (1, 2, 3); + QUERY PLAN +------------------------------------------------------------------------------------------- Seq Scan on part_abc_p1 (actual rows=0 loops=1) Filter: ((a = $1) AND (b = $2) AND (c = $3)) -(2 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(3 rows) deallocate part_abc_q1; drop table part_abc; @@ -2943,34 +3124,37 @@ execute q1 (1,2); ---+--- (0 rows) -explain (analyze, costs off, summary off, timing off) execute q1 (1,1); - QUERY PLAN ------------------------------------------------------ +explain (exec, costs off, summary off, timing off) execute q1 (1,1); + QUERY PLAN +------------------------------------------------------------------------------------------- Append (actual rows=0 loops=1) Subplans Removed: 1 -> Seq Scan on listp_1_1 (actual rows=0 loops=1) Filter: (b = ANY (ARRAY[$1, $2])) -(4 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(5 rows) -explain (analyze, costs off, summary off, timing off) execute q1 (2,2); - QUERY PLAN ------------------------------------------------------ +explain (exec, costs off, summary off, timing off) execute q1 (2,2); + QUERY PLAN +------------------------------------------------------------------------------------------- Append (actual rows=0 loops=1) Subplans Removed: 1 -> Seq Scan on listp_2_1 (actual rows=0 loops=1) Filter: (b = ANY (ARRAY[$1, $2])) -(4 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(5 rows) -- Try with no matching partitions. One subplan should remain in this case, -- but it shouldn't be executed. -explain (analyze, costs off, summary off, timing off) execute q1 (0,0); - QUERY PLAN ----------------------------------------------- +explain (exec, costs off, summary off, timing off) execute q1 (0,0); + QUERY PLAN +------------------------------------------------------------------------------------------- Append (actual rows=0 loops=1) Subplans Removed: 1 -> Seq Scan on listp_1_1 (never executed) Filter: (b = ANY (ARRAY[$1, $2])) -(4 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(5 rows) deallocate q1; -- Test more complex cases where a not-equal condition further eliminates partitions. @@ -3001,31 +3185,33 @@ execute q1 (1,2,3,4); (0 rows) -- Both partitions allowed by IN clause, but one disallowed by <> clause -explain (analyze, costs off, summary off, timing off) execute q1 (1,2,2,0); - QUERY PLAN -------------------------------------------------------------------------- +explain (exec, costs off, summary off, timing off) execute q1 (1,2,2,0); + QUERY PLAN +------------------------------------------------------------------------------------------- Append (actual rows=0 loops=1) Subplans Removed: 1 -> Seq Scan on listp_1_1 (actual rows=0 loops=1) Filter: ((b = ANY (ARRAY[$1, $2])) AND ($3 <> b) AND ($4 <> b)) -(4 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(5 rows) -- Both partitions allowed by IN clause, then both excluded again by <> clauses. -- One subplan will remain in this case, but it should not be executed. -explain (analyze, costs off, summary off, timing off) execute q1 (1,2,2,1); - QUERY PLAN -------------------------------------------------------------------------- +explain (exec, costs off, summary off, timing off) execute q1 (1,2,2,1); + QUERY PLAN +------------------------------------------------------------------------------------------- Append (actual rows=0 loops=1) Subplans Removed: 1 -> Seq Scan on listp_1_1 (never executed) Filter: ((b = ANY (ARRAY[$1, $2])) AND ($3 <> b) AND ($4 <> b)) -(4 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(5 rows) -- Ensure Params that evaluate to NULL properly prune away all partitions -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from listp where a = (select null::int); - QUERY PLAN ----------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------- Append (actual rows=0 loops=1) InitPlan 1 (returns $0) -> Result (actual rows=1 loops=1) @@ -3033,7 +3219,8 @@ select * from listp where a = (select null::int); Filter: (a = $0) -> Seq Scan on listp_2_1 (never executed) Filter: (a = $0) -(7 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(8 rows) drop table listp; -- Ensure runtime pruning works with initplans params with boolean types @@ -3042,35 +3229,41 @@ insert into boolvalues values('t'),('f'); create table boolp (a bool) partition by list (a); create table boolp_t partition of boolp for values in('t'); create table boolp_f partition of boolp for values in('f'); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from boolp where a = (select value from boolvalues where value); - QUERY PLAN --------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------- Append (actual rows=0 loops=1) + Buffers: shared hit=1 InitPlan 1 (returns $0) -> Seq Scan on boolvalues (actual rows=1 loops=1) Filter: value Rows Removed by Filter: 1 + Buffers: shared hit=1 -> Seq Scan on boolp_f (never executed) Filter: (a = $0) -> Seq Scan on boolp_t (actual rows=0 loops=1) Filter: (a = $0) -(9 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(12 rows) -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from boolp where a = (select value from boolvalues where not value); - QUERY PLAN --------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------- Append (actual rows=0 loops=1) + Buffers: shared hit=1 InitPlan 1 (returns $0) -> Seq Scan on boolvalues (actual rows=1 loops=1) Filter: (NOT value) Rows Removed by Filter: 1 + Buffers: shared hit=1 -> Seq Scan on boolp_f (actual rows=0 loops=1) Filter: (a = $0) -> Seq Scan on boolp_t (never executed) Filter: (a = $0) -(9 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off' +(12 rows) drop table boolp; -- @@ -3128,19 +3321,23 @@ execute mt_q1(0); 25 (3 rows) -explain (analyze, costs off, summary off, timing off) execute mt_q1(15); - QUERY PLAN -------------------------------------------------------------------------------- +explain (exec, costs off, summary off, timing off) execute mt_q1(15); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------- Merge Append (actual rows=2 loops=1) Sort Key: ma_test_p2.b + Buffers: shared hit=4 Subplans Removed: 1 -> Index Scan using ma_test_p2_b_idx on ma_test_p2 (actual rows=1 loops=1) Filter: ((a >= $1) AND ((a % 10) = 5)) Rows Removed by Filter: 9 + Buffers: shared hit=2 -> Index Scan using ma_test_p3_b_idx on ma_test_p3 (actual rows=1 loops=1) Filter: ((a >= $1) AND ((a % 10) = 5)) Rows Removed by Filter: 9 -(9 rows) + Buffers: shared hit=2 + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off', enable_seqscan = 'off', enable_sort = 'off' +(13 rows) execute mt_q1(15); a @@ -3149,16 +3346,19 @@ execute mt_q1(15); 25 (2 rows) -explain (analyze, costs off, summary off, timing off) execute mt_q1(25); - QUERY PLAN -------------------------------------------------------------------------------- +explain (exec, costs off, summary off, timing off) execute mt_q1(25); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------- Merge Append (actual rows=1 loops=1) Sort Key: ma_test_p3.b + Buffers: shared hit=2 Subplans Removed: 2 -> Index Scan using ma_test_p3_b_idx on ma_test_p3 (actual rows=1 loops=1) Filter: ((a >= $1) AND ((a % 10) = 5)) Rows Removed by Filter: 9 -(6 rows) + Buffers: shared hit=2 + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off', enable_seqscan = 'off', enable_sort = 'off' +(9 rows) execute mt_q1(25); a @@ -3167,15 +3367,16 @@ execute mt_q1(25); (1 row) -- Ensure MergeAppend behaves correctly when no subplans match -explain (analyze, costs off, summary off, timing off) execute mt_q1(35); - QUERY PLAN ------------------------------------------------------------------------- +explain (exec, costs off, summary off, timing off) execute mt_q1(35); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------- Merge Append (actual rows=0 loops=1) Sort Key: ma_test_p1.b Subplans Removed: 2 -> Index Scan using ma_test_p1_b_idx on ma_test_p1 (never executed) Filter: ((a >= $1) AND ((a % 10) = 5)) -(5 rows) + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off', enable_seqscan = 'off', enable_sort = 'off' +(6 rows) execute mt_q1(35); a @@ -3184,24 +3385,31 @@ execute mt_q1(35); deallocate mt_q1; -- ensure initplan params properly prune partitions -explain (analyze, costs off, summary off, timing off) select * from ma_test where a >= (select min(b) from ma_test_p2) order by b; - QUERY PLAN ------------------------------------------------------------------------------------------------------------- +explain (exec, costs off, summary off, timing off) select * from ma_test where a >= (select min(b) from ma_test_p2) order by b; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------- Merge Append (actual rows=20 loops=1) Sort Key: ma_test_p1.b + Buffers: shared hit=6 InitPlan 2 (returns $1) -> Result (actual rows=1 loops=1) + Buffers: shared hit=2 InitPlan 1 (returns $0) -> Limit (actual rows=1 loops=1) + Buffers: shared hit=2 -> Index Scan using ma_test_p2_b_idx on ma_test_p2 ma_test_p2_1 (actual rows=1 loops=1) Index Cond: (b IS NOT NULL) + Buffers: shared hit=2 -> Index Scan using ma_test_p1_b_idx on ma_test_p1 (never executed) Filter: (a >= $1) -> Index Scan using ma_test_p2_b_idx on ma_test_p2 (actual rows=10 loops=1) Filter: (a >= $1) + Buffers: shared hit=2 -> Index Scan using ma_test_p3_b_idx on ma_test_p3 (actual rows=10 loops=1) Filter: (a >= $1) -(14 rows) + Buffers: shared hit=2 + Settings: enable_hashjoin = 'off', enable_indexonlyscan = 'off', enable_mergejoin = 'off', enable_seqscan = 'off', enable_sort = 'off' +(21 rows) reset enable_seqscan; reset enable_sort; @@ -3216,18 +3424,20 @@ create table pp_arrpart (a int[]) partition by list (a); create table pp_arrpart1 partition of pp_arrpart for values in ('{1}'); create table pp_arrpart2 partition of pp_arrpart for values in ('{2, 3}', '{4, 5}'); explain (costs off) select * from pp_arrpart where a = '{1}'; - QUERY PLAN ----------------------------------- + QUERY PLAN +------------------------------------------------------------- Seq Scan on pp_arrpart1 Filter: (a = '{1}'::integer[]) -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) explain (costs off) select * from pp_arrpart where a = '{1, 2}'; - QUERY PLAN --------------------------- + QUERY PLAN +------------------------------------------------------------- Result One-Time Filter: false -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) explain (costs off) select * from pp_arrpart where a in ('{4, 5}', '{1}'); QUERY PLAN @@ -3237,25 +3447,28 @@ explain (costs off) select * from pp_arrpart where a in ('{4, 5}', '{1}'); Filter: ((a = '{4,5}'::integer[]) OR (a = '{1}'::integer[])) -> Seq Scan on pp_arrpart2 Filter: ((a = '{4,5}'::integer[]) OR (a = '{1}'::integer[])) -(5 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(6 rows) explain (costs off) update pp_arrpart set a = a where a = '{1}'; - QUERY PLAN ----------------------------------------- + QUERY PLAN +------------------------------------------------------------- Update on pp_arrpart Update on pp_arrpart1 -> Seq Scan on pp_arrpart1 Filter: (a = '{1}'::integer[]) -(4 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(5 rows) explain (costs off) delete from pp_arrpart where a = '{1}'; - QUERY PLAN ----------------------------------------- + QUERY PLAN +------------------------------------------------------------- Delete on pp_arrpart Delete on pp_arrpart1 -> Seq Scan on pp_arrpart1 Filter: (a = '{1}'::integer[]) -(4 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(5 rows) drop table pp_arrpart; -- array type hash partition key @@ -3272,18 +3485,20 @@ select tableoid::regclass, * from pph_arrpart order by 1; (3 rows) explain (costs off) select * from pph_arrpart where a = '{1}'; - QUERY PLAN ----------------------------------- + QUERY PLAN +------------------------------------------------------------- Seq Scan on pph_arrpart2 Filter: (a = '{1}'::integer[]) -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) explain (costs off) select * from pph_arrpart where a = '{1, 2}'; - QUERY PLAN ------------------------------------- + QUERY PLAN +------------------------------------------------------------- Seq Scan on pph_arrpart1 Filter: (a = '{1,2}'::integer[]) -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) explain (costs off) select * from pph_arrpart where a in ('{4, 5}', '{1}'); QUERY PLAN @@ -3293,7 +3508,8 @@ explain (costs off) select * from pph_arrpart where a in ('{4, 5}', '{1}'); Filter: ((a = '{4,5}'::integer[]) OR (a = '{1}'::integer[])) -> Seq Scan on pph_arrpart2 Filter: ((a = '{4,5}'::integer[]) OR (a = '{1}'::integer[])) -(5 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(6 rows) drop table pph_arrpart; -- enum type list partition key @@ -3302,18 +3518,20 @@ create table pp_enumpart (a pp_colors) partition by list (a); create table pp_enumpart_green partition of pp_enumpart for values in ('green'); create table pp_enumpart_blue partition of pp_enumpart for values in ('blue'); explain (costs off) select * from pp_enumpart where a = 'blue'; - QUERY PLAN ------------------------------------ + QUERY PLAN +------------------------------------------------------------- Seq Scan on pp_enumpart_blue Filter: (a = 'blue'::pp_colors) -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) explain (costs off) select * from pp_enumpart where a = 'black'; - QUERY PLAN --------------------------- + QUERY PLAN +------------------------------------------------------------- Result One-Time Filter: false -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) drop table pp_enumpart; drop type pp_colors; @@ -3323,18 +3541,20 @@ create table pp_recpart (a pp_rectype) partition by list (a); create table pp_recpart_11 partition of pp_recpart for values in ('(1,1)'); create table pp_recpart_23 partition of pp_recpart for values in ('(2,3)'); explain (costs off) select * from pp_recpart where a = '(1,1)'::pp_rectype; - QUERY PLAN -------------------------------------- + QUERY PLAN +------------------------------------------------------------- Seq Scan on pp_recpart_11 Filter: (a = '(1,1)'::pp_rectype) -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) explain (costs off) select * from pp_recpart where a = '(1,2)'::pp_rectype; - QUERY PLAN --------------------------- + QUERY PLAN +------------------------------------------------------------- Result One-Time Filter: false -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) drop table pp_recpart; drop type pp_rectype; @@ -3343,18 +3563,20 @@ create table pp_intrangepart (a int4range) partition by list (a); create table pp_intrangepart12 partition of pp_intrangepart for values in ('[1,2]'); create table pp_intrangepart2inf partition of pp_intrangepart for values in ('[2,)'); explain (costs off) select * from pp_intrangepart where a = '[1,2]'::int4range; - QUERY PLAN ------------------------------------- + QUERY PLAN +------------------------------------------------------------- Seq Scan on pp_intrangepart12 Filter: (a = '[1,3)'::int4range) -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) explain (costs off) select * from pp_intrangepart where a = '(1,2)'::int4range; - QUERY PLAN --------------------------- + QUERY PLAN +------------------------------------------------------------- Result One-Time Filter: false -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) drop table pp_intrangepart; -- @@ -3364,45 +3586,49 @@ create table pp_lp (a int, value int) partition by list (a); create table pp_lp1 partition of pp_lp for values in(1); create table pp_lp2 partition of pp_lp for values in(2); explain (costs off) select * from pp_lp where a = 1; - QUERY PLAN --------------------- + QUERY PLAN +------------------------------------------------------------- Seq Scan on pp_lp1 Filter: (a = 1) -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) explain (costs off) update pp_lp set value = 10 where a = 1; - QUERY PLAN --------------------------- + QUERY PLAN +------------------------------------------------------------- Update on pp_lp Update on pp_lp1 -> Seq Scan on pp_lp1 Filter: (a = 1) -(4 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(5 rows) explain (costs off) delete from pp_lp where a = 1; - QUERY PLAN --------------------------- + QUERY PLAN +------------------------------------------------------------- Delete on pp_lp Delete on pp_lp1 -> Seq Scan on pp_lp1 Filter: (a = 1) -(4 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(5 rows) set enable_partition_pruning = off; set constraint_exclusion = 'partition'; -- this should not affect the result. explain (costs off) select * from pp_lp where a = 1; - QUERY PLAN --------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------- Append -> Seq Scan on pp_lp1 Filter: (a = 1) -> Seq Scan on pp_lp2 Filter: (a = 1) -(5 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(6 rows) explain (costs off) update pp_lp set value = 10 where a = 1; - QUERY PLAN --------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------- Update on pp_lp Update on pp_lp1 Update on pp_lp2 @@ -3410,11 +3636,12 @@ explain (costs off) update pp_lp set value = 10 where a = 1; Filter: (a = 1) -> Seq Scan on pp_lp2 Filter: (a = 1) -(7 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(8 rows) explain (costs off) delete from pp_lp where a = 1; - QUERY PLAN --------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------- Delete on pp_lp Delete on pp_lp1 Delete on pp_lp2 @@ -3422,22 +3649,24 @@ explain (costs off) delete from pp_lp where a = 1; Filter: (a = 1) -> Seq Scan on pp_lp2 Filter: (a = 1) -(7 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(8 rows) set constraint_exclusion = 'off'; -- this should not affect the result. explain (costs off) select * from pp_lp where a = 1; - QUERY PLAN --------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------- Append -> Seq Scan on pp_lp1 Filter: (a = 1) -> Seq Scan on pp_lp2 Filter: (a = 1) -(5 rows) + Settings: constraint_exclusion = 'off', enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(6 rows) explain (costs off) update pp_lp set value = 10 where a = 1; - QUERY PLAN --------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------- Update on pp_lp Update on pp_lp1 Update on pp_lp2 @@ -3445,11 +3674,12 @@ explain (costs off) update pp_lp set value = 10 where a = 1; Filter: (a = 1) -> Seq Scan on pp_lp2 Filter: (a = 1) -(7 rows) + Settings: constraint_exclusion = 'off', enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(8 rows) explain (costs off) delete from pp_lp where a = 1; - QUERY PLAN --------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------- Delete on pp_lp Delete on pp_lp1 Delete on pp_lp2 @@ -3457,7 +3687,8 @@ explain (costs off) delete from pp_lp where a = 1; Filter: (a = 1) -> Seq Scan on pp_lp2 Filter: (a = 1) -(7 rows) + Settings: constraint_exclusion = 'off', enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(8 rows) drop table pp_lp; -- Ensure enable_partition_prune does not affect non-partitioned tables. @@ -3471,18 +3702,19 @@ NOTICE: merging column "value" with inherited definition set constraint_exclusion = 'partition'; -- inh_lp2 should be removed in the following 3 cases. explain (costs off) select * from inh_lp where a = 1; - QUERY PLAN ---------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------- Append -> Seq Scan on inh_lp Filter: (a = 1) -> Seq Scan on inh_lp1 Filter: (a = 1) -(5 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(6 rows) explain (costs off) update inh_lp set value = 10 where a = 1; - QUERY PLAN ---------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------- Update on inh_lp Update on inh_lp Update on inh_lp1 @@ -3490,11 +3722,12 @@ explain (costs off) update inh_lp set value = 10 where a = 1; Filter: (a = 1) -> Seq Scan on inh_lp1 Filter: (a = 1) -(7 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(8 rows) explain (costs off) delete from inh_lp where a = 1; - QUERY PLAN ---------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------- Delete on inh_lp Delete on inh_lp Delete on inh_lp1 @@ -3502,17 +3735,19 @@ explain (costs off) delete from inh_lp where a = 1; Filter: (a = 1) -> Seq Scan on inh_lp1 Filter: (a = 1) -(7 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(8 rows) -- Ensure we don't exclude normal relations when we only expect to exclude -- inheritance children explain (costs off) update inh_lp1 set value = 10 where a = 2; - QUERY PLAN ---------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------- Update on inh_lp1 -> Seq Scan on inh_lp1 Filter: (a = 2) -(3 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(4 rows) drop table inh_lp cascade; NOTICE: drop cascades to 2 other objects @@ -3525,19 +3760,21 @@ create temp table pp_temp_parent (a int) partition by list (a); create temp table pp_temp_part_1 partition of pp_temp_parent for values in (1); create temp table pp_temp_part_def partition of pp_temp_parent default; explain (costs off) select * from pp_temp_parent where true; - QUERY PLAN ------------------------------------- + QUERY PLAN +------------------------------------------------------------- Append -> Seq Scan on pp_temp_part_1 -> Seq Scan on pp_temp_part_def -(3 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(4 rows) explain (costs off) select * from pp_temp_parent where a = 2; - QUERY PLAN ------------------------------- + QUERY PLAN +------------------------------------------------------------- Seq Scan on pp_temp_part_def Filter: (a = 2) -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(3 rows) drop table pp_temp_parent; -- Stress run-time partition pruning a bit more, per bug reports @@ -3562,8 +3799,8 @@ from ( select 1, 1, 1 ) s(a, b, c) where s.a = 1 and s.b = 1 and s.c = (select 1); - QUERY PLAN ----------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Append InitPlan 1 (returns $0) -> Result @@ -3573,7 +3810,8 @@ where s.a = 1 and s.b = 1 and s.c = (select 1); Filter: ((a = 1) AND (b = 1) AND (c = $0)) -> Result One-Time Filter: (1 = $0) -(9 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(10 rows) select * from ( @@ -3601,8 +3839,8 @@ from ( where s.a = $1 and s.b = $2 and s.c = (select 1); set plan_cache_mode to force_generic_plan; explain (costs off) execute q (1, 1); - QUERY PLAN ---------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------- Append InitPlan 1 (returns $0) -> Result @@ -3613,7 +3851,8 @@ explain (costs off) execute q (1, 1); Filter: ((a = $1) AND (b = $2) AND (c = $0)) -> Result One-Time Filter: ((1 = $1) AND (1 = $2) AND (1 = $0)) -(10 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off', plan_cache_mode = 'force_generic_plan' +(11 rows) execute q (1, 1); a | b | c @@ -3629,15 +3868,16 @@ create table listp (a int, b int) partition by list (a); create table listp1 partition of listp for values in(1); create table listp2 partition of listp for values in(2) partition by list(b); create table listp2_10 partition of listp2 for values in (10); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from listp where a = (select 2) and b <> 10; - QUERY PLAN --------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Seq Scan on listp1 (actual rows=0 loops=1) Filter: ((b <> 10) AND (a = $0)) InitPlan 1 (returns $0) -> Result (never executed) -(4 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off' +(5 rows) -- -- check that a partition directly accessed in a query is excluded with @@ -3648,36 +3888,40 @@ set enable_partition_pruning to off; -- setting constraint_exclusion to 'partition' disables exclusion set constraint_exclusion to 'partition'; explain (costs off) select * from listp1 where a = 2; - QUERY PLAN --------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------- Seq Scan on listp1 Filter: (a = 2) -(2 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(3 rows) explain (costs off) update listp1 set a = 1 where a = 2; - QUERY PLAN --------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------- Update on listp1 -> Seq Scan on listp1 Filter: (a = 2) -(3 rows) + Settings: enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(4 rows) -- constraint exclusion enabled set constraint_exclusion to 'on'; explain (costs off) select * from listp1 where a = 2; - QUERY PLAN --------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------- Result One-Time Filter: false -(2 rows) + Settings: constraint_exclusion = 'on', enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(3 rows) explain (costs off) update listp1 set a = 1 where a = 2; - QUERY PLAN --------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------- Update on listp1 -> Result One-Time Filter: false -(3 rows) + Settings: constraint_exclusion = 'on', enable_hashjoin = 'off', enable_mergejoin = 'off', enable_partition_pruning = 'off' +(4 rows) reset constraint_exclusion; reset enable_partition_pruning; diff --git a/src/test/regress/expected/plancache.out b/src/test/regress/expected/plancache.out index 7d289b8c5e..0dd5de5078 100644 --- a/src/test/regress/expected/plancache.out +++ b/src/test/regress/expected/plancache.out @@ -296,12 +296,13 @@ explain (costs off) execute test_mode_pp(2); -- force generic plan set plan_cache_mode to force_generic_plan; explain (costs off) execute test_mode_pp(2); - QUERY PLAN ------------------------------ + QUERY PLAN +-------------------------------------------------- Aggregate -> Seq Scan on test_mode Filter: (a = $1) -(3 rows) + Settings: plan_cache_mode = 'force_generic_plan' +(4 rows) -- get to generic plan by 5 executions set plan_cache_mode to auto; @@ -352,6 +353,7 @@ explain (costs off) execute test_mode_pp(2); Aggregate -> Index Only Scan using test_mode_a_idx on test_mode Index Cond: (a = 2) -(3 rows) + Settings: plan_cache_mode = 'force_custom_plan' +(4 rows) drop table test_mode; diff --git a/src/test/regress/expected/polygon.out b/src/test/regress/expected/polygon.out index f319239b2e..8d654c6289 100644 --- a/src/test/regress/expected/polygon.out +++ b/src/test/regress/expected/polygon.out @@ -82,7 +82,8 @@ SELECT count(*) FROM quad_poly_tbl WHERE p << polygon '((300,300),(400,600),(600 Recheck Cond: (p << '((300,300),(400,600),(600,500),(700,200))'::polygon) -> Bitmap Index Scan on quad_poly_tbl_idx Index Cond: (p << '((300,300),(400,600),(600,500),(700,200))'::polygon) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_poly_tbl WHERE p << polygon '((300,300),(400,600),(600,500),(700,200))'; count @@ -99,7 +100,8 @@ SELECT count(*) FROM quad_poly_tbl WHERE p &< polygon '((300,300),(400,600),(600 Recheck Cond: (p &< '((300,300),(400,600),(600,500),(700,200))'::polygon) -> Bitmap Index Scan on quad_poly_tbl_idx Index Cond: (p &< '((300,300),(400,600),(600,500),(700,200))'::polygon) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_poly_tbl WHERE p &< polygon '((300,300),(400,600),(600,500),(700,200))'; count @@ -116,7 +118,8 @@ SELECT count(*) FROM quad_poly_tbl WHERE p && polygon '((300,300),(400,600),(600 Recheck Cond: (p && '((300,300),(400,600),(600,500),(700,200))'::polygon) -> Bitmap Index Scan on quad_poly_tbl_idx Index Cond: (p && '((300,300),(400,600),(600,500),(700,200))'::polygon) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_poly_tbl WHERE p && polygon '((300,300),(400,600),(600,500),(700,200))'; count @@ -133,7 +136,8 @@ SELECT count(*) FROM quad_poly_tbl WHERE p &> polygon '((300,300),(400,600),(600 Recheck Cond: (p &> '((300,300),(400,600),(600,500),(700,200))'::polygon) -> Bitmap Index Scan on quad_poly_tbl_idx Index Cond: (p &> '((300,300),(400,600),(600,500),(700,200))'::polygon) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_poly_tbl WHERE p &> polygon '((300,300),(400,600),(600,500),(700,200))'; count @@ -150,7 +154,8 @@ SELECT count(*) FROM quad_poly_tbl WHERE p >> polygon '((300,300),(400,600),(600 Recheck Cond: (p >> '((300,300),(400,600),(600,500),(700,200))'::polygon) -> Bitmap Index Scan on quad_poly_tbl_idx Index Cond: (p >> '((300,300),(400,600),(600,500),(700,200))'::polygon) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_poly_tbl WHERE p >> polygon '((300,300),(400,600),(600,500),(700,200))'; count @@ -167,7 +172,8 @@ SELECT count(*) FROM quad_poly_tbl WHERE p <<| polygon '((300,300),(400,600),(60 Recheck Cond: (p <<| '((300,300),(400,600),(600,500),(700,200))'::polygon) -> Bitmap Index Scan on quad_poly_tbl_idx Index Cond: (p <<| '((300,300),(400,600),(600,500),(700,200))'::polygon) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_poly_tbl WHERE p <<| polygon '((300,300),(400,600),(600,500),(700,200))'; count @@ -184,7 +190,8 @@ SELECT count(*) FROM quad_poly_tbl WHERE p &<| polygon '((300,300),(400,600),(60 Recheck Cond: (p &<| '((300,300),(400,600),(600,500),(700,200))'::polygon) -> Bitmap Index Scan on quad_poly_tbl_idx Index Cond: (p &<| '((300,300),(400,600),(600,500),(700,200))'::polygon) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_poly_tbl WHERE p &<| polygon '((300,300),(400,600),(600,500),(700,200))'; count @@ -201,7 +208,8 @@ SELECT count(*) FROM quad_poly_tbl WHERE p |&> polygon '((300,300),(400,600),(60 Recheck Cond: (p |&> '((300,300),(400,600),(600,500),(700,200))'::polygon) -> Bitmap Index Scan on quad_poly_tbl_idx Index Cond: (p |&> '((300,300),(400,600),(600,500),(700,200))'::polygon) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_poly_tbl WHERE p |&> polygon '((300,300),(400,600),(600,500),(700,200))'; count @@ -218,7 +226,8 @@ SELECT count(*) FROM quad_poly_tbl WHERE p |>> polygon '((300,300),(400,600),(60 Recheck Cond: (p |>> '((300,300),(400,600),(600,500),(700,200))'::polygon) -> Bitmap Index Scan on quad_poly_tbl_idx Index Cond: (p |>> '((300,300),(400,600),(600,500),(700,200))'::polygon) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_poly_tbl WHERE p |>> polygon '((300,300),(400,600),(600,500),(700,200))'; count @@ -235,7 +244,8 @@ SELECT count(*) FROM quad_poly_tbl WHERE p <@ polygon '((300,300),(400,600),(600 Recheck Cond: (p <@ '((300,300),(400,600),(600,500),(700,200))'::polygon) -> Bitmap Index Scan on quad_poly_tbl_idx Index Cond: (p <@ '((300,300),(400,600),(600,500),(700,200))'::polygon) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_poly_tbl WHERE p <@ polygon '((300,300),(400,600),(600,500),(700,200))'; count @@ -252,7 +262,8 @@ SELECT count(*) FROM quad_poly_tbl WHERE p @> polygon '((340,550),(343,552),(341 Recheck Cond: (p @> '((340,550),(343,552),(341,553))'::polygon) -> Bitmap Index Scan on quad_poly_tbl_idx Index Cond: (p @> '((340,550),(343,552),(341,553))'::polygon) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_poly_tbl WHERE p @> polygon '((340,550),(343,552),(341,553))'; count @@ -269,7 +280,8 @@ SELECT count(*) FROM quad_poly_tbl WHERE p ~= polygon '((200, 300),(210, 310),(2 Recheck Cond: (p ~= '((200,300),(210,310),(230,290))'::polygon) -> Bitmap Index Scan on quad_poly_tbl_idx Index Cond: (p ~= '((200,300),(210,310),(230,290))'::polygon) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM quad_poly_tbl WHERE p ~= polygon '((200, 300),(210, 310),(230, 290))'; count @@ -289,7 +301,8 @@ FROM quad_poly_tbl WHERE p <@ polygon '((300,300),(400,600),(600,500),(700,200)) -> Index Scan using quad_poly_tbl_idx on quad_poly_tbl Index Cond: (p <@ '((300,300),(400,600),(600,500),(700,200))'::polygon) Order By: (p <-> '(123,456)'::point) -(4 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(5 rows) CREATE TEMP TABLE quad_poly_tbl_ord_idx2 AS SELECT rank() OVER (ORDER BY p <-> point '123,456') n, p <-> point '123,456' dist, id diff --git a/src/test/regress/expected/rangetypes.out b/src/test/regress/expected/rangetypes.out index accf1e0d9e..cb3f968dc5 100644 --- a/src/test/regress/expected/rangetypes.out +++ b/src/test/regress/expected/rangetypes.out @@ -1099,7 +1099,8 @@ select ir from test_range_spgist where ir -|- int4range(10,20) order by ir; Sort Key: ir -> Index Only Scan using test_range_spgist_idx on test_range_spgist Index Cond: (ir -|- '[10,20)'::int4range) -(4 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(5 rows) select ir from test_range_spgist where ir -|- int4range(10,20) order by ir; ir diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out index aa3b083ee3..6abd169172 100644 --- a/src/test/regress/expected/rowsecurity.out +++ b/src/test/regress/expected/rowsecurity.out @@ -272,7 +272,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle); InitPlan 1 (returns $0) -> Index Scan using uaccount_pkey on uaccount Index Cond: (pguser = CURRENT_USER) -(5 rows) + Settings: search_path = 'regress_rls_schema' +(6 rows) EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle); QUERY PLAN @@ -286,7 +287,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dt -> Hash -> Seq Scan on document Filter: ((dlevel <= $0) AND f_leak(dtitle)) -(9 rows) + Settings: search_path = 'regress_rls_schema' +(10 rows) -- viewpoint from regress_rls_dave SET SESSION AUTHORIZATION regress_rls_dave; @@ -336,7 +338,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle); InitPlan 1 (returns $0) -> Index Scan using uaccount_pkey on uaccount Index Cond: (pguser = CURRENT_USER) -(5 rows) + Settings: search_path = 'regress_rls_schema' +(6 rows) EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle); QUERY PLAN @@ -350,7 +353,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dt -> Hash -> Seq Scan on document Filter: ((cid <> 44) AND (cid <> 44) AND (cid < 50) AND (dlevel <= $0) AND f_leak(dtitle)) -(9 rows) + Settings: search_path = 'regress_rls_schema' +(10 rows) -- 44 would technically fail for both p2r and p1r, but we should get an error -- back from p1r for this because it sorts first @@ -427,7 +431,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle); --------------------------------------------------------- Seq Scan on document Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle); QUERY PLAN @@ -437,7 +442,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dt Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle)) -> Index Scan using category_pkey on category Index Cond: (cid = document.cid) -(5 rows) + Settings: search_path = 'regress_rls_schema' +(6 rows) -- interaction of FK/PK constraints SET SESSION AUTHORIZATION regress_rls_alice; @@ -659,8 +665,8 @@ SELECT * FROM t1; (5 rows) EXPLAIN (COSTS OFF) SELECT * FROM t1; - QUERY PLAN -------------------------------- + QUERY PLAN +---------------------------------------------- Append -> Seq Scan on t1 Filter: ((a % 2) = 0) @@ -668,7 +674,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1; Filter: ((a % 2) = 0) -> Seq Scan on t3 Filter: ((a % 2) = 0) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) SELECT * FROM t1 WHERE f_leak(b); NOTICE: f_leak => bbb @@ -695,7 +702,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b); Filter: (((a % 2) = 0) AND f_leak(b)) -> Seq Scan on t3 Filter: (((a % 2) = 0) AND f_leak(b)) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) -- reference to system column SELECT tableoid::regclass, * FROM t1; @@ -709,8 +717,8 @@ SELECT tableoid::regclass, * FROM t1; (5 rows) EXPLAIN (COSTS OFF) SELECT *, t1 FROM t1; - QUERY PLAN -------------------------------- + QUERY PLAN +---------------------------------------------- Append -> Seq Scan on t1 Filter: ((a % 2) = 0) @@ -718,7 +726,8 @@ EXPLAIN (COSTS OFF) SELECT *, t1 FROM t1; Filter: ((a % 2) = 0) -> Seq Scan on t3 Filter: ((a % 2) = 0) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) -- reference to whole-row reference SELECT *, t1 FROM t1; @@ -732,8 +741,8 @@ SELECT *, t1 FROM t1; (5 rows) EXPLAIN (COSTS OFF) SELECT *, t1 FROM t1; - QUERY PLAN -------------------------------- + QUERY PLAN +---------------------------------------------- Append -> Seq Scan on t1 Filter: ((a % 2) = 0) @@ -741,7 +750,8 @@ EXPLAIN (COSTS OFF) SELECT *, t1 FROM t1; Filter: ((a % 2) = 0) -> Seq Scan on t3 Filter: ((a % 2) = 0) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) -- for share/update lock SELECT * FROM t1 FOR SHARE; @@ -755,8 +765,8 @@ SELECT * FROM t1 FOR SHARE; (5 rows) EXPLAIN (COSTS OFF) SELECT * FROM t1 FOR SHARE; - QUERY PLAN -------------------------------------- + QUERY PLAN +---------------------------------------------- LockRows -> Append -> Seq Scan on t1 @@ -765,7 +775,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 FOR SHARE; Filter: ((a % 2) = 0) -> Seq Scan on t3 Filter: ((a % 2) = 0) -(8 rows) + Settings: search_path = 'regress_rls_schema' +(9 rows) SELECT * FROM t1 WHERE f_leak(b) FOR SHARE; NOTICE: f_leak => bbb @@ -793,7 +804,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b) FOR SHARE; Filter: (((a % 2) = 0) AND f_leak(b)) -> Seq Scan on t3 Filter: (((a % 2) = 0) AND f_leak(b)) -(8 rows) + Settings: search_path = 'regress_rls_schema' +(9 rows) -- union all query SELECT a, b, tableoid::regclass FROM t2 UNION ALL SELECT a, b, tableoid::regclass FROM t3; @@ -807,13 +819,14 @@ SELECT a, b, tableoid::regclass FROM t2 UNION ALL SELECT a, b, tableoid::regclas (5 rows) EXPLAIN (COSTS OFF) SELECT a, b, tableoid::regclass FROM t2 UNION ALL SELECT a, b, tableoid::regclass FROM t3; - QUERY PLAN -------------------------------- + QUERY PLAN +---------------------------------------------- Append -> Seq Scan on t2 Filter: ((a % 2) = 1) -> Seq Scan on t3 -(4 rows) + Settings: search_path = 'regress_rls_schema' +(5 rows) -- superuser is allowed to bypass RLS checks RESET SESSION AUTHORIZATION; @@ -846,8 +859,8 @@ NOTICE: f_leak => zzz (11 rows) EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b); - QUERY PLAN ---------------------------- + QUERY PLAN +---------------------------------------------- Append -> Seq Scan on t1 Filter: f_leak(b) @@ -855,7 +868,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b); Filter: f_leak(b) -> Seq Scan on t3 Filter: f_leak(b) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) -- non-superuser with bypass privilege can bypass RLS policy when disabled SET SESSION AUTHORIZATION regress_rls_exempt_user; @@ -888,8 +902,8 @@ NOTICE: f_leak => zzz (11 rows) EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b); - QUERY PLAN ---------------------------- + QUERY PLAN +---------------------------------------------- Append -> Seq Scan on t1 Filter: f_leak(b) @@ -897,7 +911,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b); Filter: f_leak(b) -> Seq Scan on t3 Filter: f_leak(b) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) -- -- Partitioned Tables @@ -997,7 +1012,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle); Filter: ((dlevel <= $0) AND f_leak(dtitle)) -> Seq Scan on part_document_nonfiction Filter: ((dlevel <= $0) AND f_leak(dtitle)) -(10 rows) + Settings: search_path = 'regress_rls_schema' +(11 rows) -- viewpoint from regress_rls_carol SET SESSION AUTHORIZATION regress_rls_carol; @@ -1039,7 +1055,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle); Filter: ((dlevel <= $0) AND f_leak(dtitle)) -> Seq Scan on part_document_nonfiction Filter: ((dlevel <= $0) AND f_leak(dtitle)) -(10 rows) + Settings: search_path = 'regress_rls_schema' +(11 rows) -- viewpoint from regress_rls_dave SET SESSION AUTHORIZATION regress_rls_dave; @@ -1064,7 +1081,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle); InitPlan 1 (returns $0) -> Index Scan using uaccount_pkey on uaccount Index Cond: (pguser = CURRENT_USER) -(5 rows) + Settings: search_path = 'regress_rls_schema' +(6 rows) -- pp1 ERROR INSERT INTO part_document VALUES (100, 11, 5, 'regress_rls_dave', 'testing pp1'); -- fail @@ -1142,7 +1160,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle); InitPlan 1 (returns $0) -> Index Scan using uaccount_pkey on uaccount Index Cond: (pguser = CURRENT_USER) -(5 rows) + Settings: search_path = 'regress_rls_schema' +(6 rows) -- viewpoint from regress_rls_carol SET SESSION AUTHORIZATION regress_rls_carol; @@ -1186,7 +1205,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle); Filter: ((dlevel <= $0) AND f_leak(dtitle)) -> Seq Scan on part_document_nonfiction Filter: ((dlevel <= $0) AND f_leak(dtitle)) -(10 rows) + Settings: search_path = 'regress_rls_schema' +(11 rows) -- only owner can change policies ALTER POLICY pp1 ON part_document USING (true); --fail @@ -1235,7 +1255,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle); Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle)) -> Seq Scan on part_document_nonfiction Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle)) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) -- database superuser does bypass RLS policy when enabled RESET SESSION AUTHORIZATION; @@ -1348,10 +1369,11 @@ HINT: Use DROP ... CASCADE to drop the dependent objects too. DROP TABLE dependee CASCADE; NOTICE: drop cascades to policy d1 on table dependent EXPLAIN (COSTS OFF) SELECT * FROM dependent; -- After drop, should be unqualified - QUERY PLAN ------------------------ + QUERY PLAN +---------------------------------------------- Seq Scan on dependent -(1 row) + Settings: search_path = 'regress_rls_schema' +(2 rows) ----- RECURSION ---- -- @@ -1444,7 +1466,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM only s1 WHERE f_leak(b); SubPlan 1 -> Seq Scan on s2 Filter: (((x % 2) = 0) AND (y ~~ '%2f%'::text)) -(5 rows) + Settings: search_path = 'regress_rls_schema' +(6 rows) SET SESSION AUTHORIZATION regress_rls_alice; ALTER POLICY p1 ON s1 USING (a in (select x from v2)); -- using VIEW in RLS policy @@ -1466,7 +1489,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM s1 WHERE f_leak(b); SubPlan 1 -> Seq Scan on s2 Filter: (((x % 2) = 0) AND (y ~~ '%af%'::text)) -(5 rows) + Settings: search_path = 'regress_rls_schema' +(6 rows) SELECT (SELECT x FROM s1 LIMIT 1) xx, * FROM s2 WHERE y like '%28%'; xx | x | y @@ -1488,7 +1512,8 @@ EXPLAIN (COSTS OFF) SELECT (SELECT x FROM s1 LIMIT 1) xx, * FROM s2 WHERE y like SubPlan 1 -> Seq Scan on s2 s2_1 Filter: (((x % 2) = 0) AND (y ~~ '%af%'::text)) -(9 rows) + Settings: search_path = 'regress_rls_schema' +(10 rows) SET SESSION AUTHORIZATION regress_rls_alice; ALTER POLICY p2 ON s2 USING (x in (select a from s1 where b like '%d2%')); @@ -1515,7 +1540,8 @@ EXPLAIN (COSTS OFF) EXECUTE p1(2); Filter: ((a <= 2) AND ((a % 2) = 0)) -> Seq Scan on t3 Filter: ((a <= 2) AND ((a % 2) = 0)) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) -- superuser is allowed to bypass RLS checks RESET SESSION AUTHORIZATION; @@ -1548,8 +1574,8 @@ NOTICE: f_leak => zzz (11 rows) EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b); - QUERY PLAN ---------------------------- + QUERY PLAN +---------------------------------------------- Append -> Seq Scan on t1 Filter: f_leak(b) @@ -1557,7 +1583,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b); Filter: f_leak(b) -> Seq Scan on t3 Filter: f_leak(b) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) -- plan cache should be invalidated EXECUTE p1(2); @@ -1572,8 +1599,8 @@ EXECUTE p1(2); (6 rows) EXPLAIN (COSTS OFF) EXECUTE p1(2); - QUERY PLAN --------------------------- + QUERY PLAN +---------------------------------------------- Append -> Seq Scan on t1 Filter: (a <= 2) @@ -1581,7 +1608,8 @@ EXPLAIN (COSTS OFF) EXECUTE p1(2); Filter: (a <= 2) -> Seq Scan on t3 Filter: (a <= 2) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) PREPARE p2(int) AS SELECT * FROM t1 WHERE a = $1; EXECUTE p2(2); @@ -1593,8 +1621,8 @@ EXECUTE p2(2); (3 rows) EXPLAIN (COSTS OFF) EXECUTE p2(2); - QUERY PLAN -------------------------- + QUERY PLAN +---------------------------------------------- Append -> Seq Scan on t1 Filter: (a = 2) @@ -1602,7 +1630,8 @@ EXPLAIN (COSTS OFF) EXECUTE p2(2); Filter: (a = 2) -> Seq Scan on t3 Filter: (a = 2) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) -- also, case when privilege switch from superuser SET SESSION AUTHORIZATION regress_rls_bob; @@ -1616,8 +1645,8 @@ EXECUTE p2(2); (3 rows) EXPLAIN (COSTS OFF) EXECUTE p2(2); - QUERY PLAN ---------------------------------------------- + QUERY PLAN +---------------------------------------------- Append -> Seq Scan on t1 Filter: ((a = 2) AND ((a % 2) = 0)) @@ -1625,7 +1654,8 @@ EXPLAIN (COSTS OFF) EXECUTE p2(2); Filter: ((a = 2) AND ((a % 2) = 0)) -> Seq Scan on t3 Filter: ((a = 2) AND ((a % 2) = 0)) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) -- -- UPDATE / DELETE and Row-level security @@ -1644,7 +1674,8 @@ EXPLAIN (COSTS OFF) UPDATE t1 SET b = b || b WHERE f_leak(b); Filter: (((a % 2) = 0) AND f_leak(b)) -> Seq Scan on t3 Filter: (((a % 2) = 0) AND f_leak(b)) -(10 rows) + Settings: search_path = 'regress_rls_schema' +(11 rows) UPDATE t1 SET b = b || b WHERE f_leak(b); NOTICE: f_leak => bbb @@ -1658,7 +1689,8 @@ EXPLAIN (COSTS OFF) UPDATE only t1 SET b = b || '_updt' WHERE f_leak(b); Update on t1 -> Seq Scan on t1 Filter: (((a % 2) = 0) AND f_leak(b)) -(3 rows) + Settings: search_path = 'regress_rls_schema' +(4 rows) UPDATE only t1 SET b = b || '_updt' WHERE f_leak(b); NOTICE: f_leak => bbbbbb @@ -1714,7 +1746,8 @@ WHERE t2.a = 3 and t3.a = 2 AND f_leak(t2.b) AND f_leak(t3.b); Filter: ((a = 3) AND ((a % 2) = 1) AND f_leak(b)) -> Seq Scan on t3 Filter: ((a = 2) AND f_leak(b)) -(6 rows) + Settings: search_path = 'regress_rls_schema' +(7 rows) UPDATE t2 SET b=t2.b FROM t3 WHERE t2.a = 3 and t3.a = 2 AND f_leak(t2.b) AND f_leak(t3.b); @@ -1743,7 +1776,8 @@ WHERE t1.a = 3 and t2.a = 3 AND f_leak(t1.b) AND f_leak(t2.b); Filter: ((a = 3) AND ((a % 2) = 0) AND f_leak(b)) -> Seq Scan on t2 Filter: ((a = 3) AND ((a % 2) = 1) AND f_leak(b)) -(19 rows) + Settings: search_path = 'regress_rls_schema' +(20 rows) UPDATE t1 SET b=t1.b FROM t2 WHERE t1.a = 3 and t2.a = 3 AND f_leak(t1.b) AND f_leak(t2.b); @@ -1762,7 +1796,8 @@ WHERE t1.a = 3 and t2.a = 3 AND f_leak(t1.b) AND f_leak(t2.b); Filter: ((a = 3) AND ((a % 2) = 0) AND f_leak(b)) -> Seq Scan on t3 Filter: ((a = 3) AND ((a % 2) = 0) AND f_leak(b)) -(11 rows) + Settings: search_path = 'regress_rls_schema' +(12 rows) UPDATE t2 SET b=t2.b FROM t1 WHERE t1.a = 3 and t2.a = 3 AND f_leak(t1.b) AND f_leak(t2.b); @@ -1780,7 +1815,8 @@ AND f_leak(t2_1.b) AND f_leak(t2_2.b) RETURNING *, t2_1, t2_2; Filter: ((a = 3) AND ((a % 2) = 1) AND f_leak(b)) -> Seq Scan on t2 t2_2 Filter: ((a = 3) AND ((a % 2) = 1) AND f_leak(b)) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) UPDATE t2 t2_1 SET b = t2_2.b FROM t2 t2_2 WHERE t2_1.a = 3 AND t2_2.a = t2_1.a AND t2_2.b = t2_1.b @@ -1834,7 +1870,8 @@ AND f_leak(t1_1.b) AND f_leak(t1_2.b) RETURNING *, t1_1, t1_2; Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) -> Seq Scan on t3 t1_2_2 Filter: ((a = 4) AND ((a % 2) = 0) AND f_leak(b)) -(37 rows) + Settings: search_path = 'regress_rls_schema' +(38 rows) UPDATE t1 t1_1 SET b = t1_2.b FROM t1 t1_2 WHERE t1_1.a = 4 AND t1_2.a = t1_1.a AND t1_2.b = t1_1.b @@ -1877,7 +1914,8 @@ EXPLAIN (COSTS OFF) DELETE FROM only t1 WHERE f_leak(b); Delete on t1 -> Seq Scan on t1 Filter: (((a % 2) = 0) AND f_leak(b)) -(3 rows) + Settings: search_path = 'regress_rls_schema' +(4 rows) EXPLAIN (COSTS OFF) DELETE FROM t1 WHERE f_leak(b); QUERY PLAN @@ -1892,7 +1930,8 @@ EXPLAIN (COSTS OFF) DELETE FROM t1 WHERE f_leak(b); Filter: (((a % 2) = 0) AND f_leak(b)) -> Seq Scan on t3 Filter: (((a % 2) = 0) AND f_leak(b)) -(10 rows) + Settings: search_path = 'regress_rls_schema' +(11 rows) DELETE FROM only t1 WHERE f_leak(b) RETURNING tableoid::regclass, *, t1; NOTICE: f_leak => bbbbbb_updt @@ -1928,13 +1967,14 @@ CREATE VIEW bv1 WITH (security_barrier) AS SELECT * FROM b1 WHERE a > 0 WITH CHE GRANT ALL ON bv1 TO regress_rls_carol; SET SESSION AUTHORIZATION regress_rls_carol; EXPLAIN (COSTS OFF) SELECT * FROM bv1 WHERE f_leak(b); - QUERY PLAN ---------------------------------------------- + QUERY PLAN +---------------------------------------------- Subquery Scan on bv1 Filter: f_leak(bv1.b) -> Seq Scan on b1 Filter: ((a > 0) AND ((a % 2) = 0)) -(4 rows) + Settings: search_path = 'regress_rls_schema' +(5 rows) SELECT * FROM bv1 WHERE f_leak(b); NOTICE: f_leak => c81e728d9d4c2f636f067f89cc14862c @@ -1962,7 +2002,8 @@ EXPLAIN (COSTS OFF) UPDATE bv1 SET b = 'yyy' WHERE a = 4 AND f_leak(b); Update on b1 -> Seq Scan on b1 Filter: ((a > 0) AND (a = 4) AND ((a % 2) = 0) AND f_leak(b)) -(3 rows) + Settings: search_path = 'regress_rls_schema' +(4 rows) UPDATE bv1 SET b = 'yyy' WHERE a = 4 AND f_leak(b); NOTICE: f_leak => a87ff679a2f3e71d9181a67b7542122c @@ -1972,7 +2013,8 @@ EXPLAIN (COSTS OFF) DELETE FROM bv1 WHERE a = 6 AND f_leak(b); Delete on b1 -> Seq Scan on b1 Filter: ((a > 0) AND (a = 6) AND ((a % 2) = 0) AND f_leak(b)) -(3 rows) + Settings: search_path = 'regress_rls_schema' +(4 rows) DELETE FROM bv1 WHERE a = 6 AND f_leak(b); NOTICE: f_leak => 1679091c5a880faf6fb5e6087eb1b2dc @@ -2163,19 +2205,21 @@ NOTICE: f_leak => dad (2 rows) EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b); - QUERY PLAN ------------------------------------------ + QUERY PLAN +---------------------------------------------- Seq Scan on z1 Filter: (((a % 2) = 0) AND f_leak(b)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) PREPARE plancache_test AS SELECT * FROM z1 WHERE f_leak(b); EXPLAIN (COSTS OFF) EXECUTE plancache_test; - QUERY PLAN ------------------------------------------ + QUERY PLAN +---------------------------------------------- Seq Scan on z1 Filter: (((a % 2) = 0) AND f_leak(b)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) PREPARE plancache_test2 AS WITH q AS MATERIALIZED (SELECT * FROM z1 WHERE f_leak(b)) SELECT * FROM q,z2; EXPLAIN (COSTS OFF) EXECUTE plancache_test2; @@ -2188,7 +2232,8 @@ EXPLAIN (COSTS OFF) EXECUTE plancache_test2; -> CTE Scan on q -> Materialize -> Seq Scan on z2 -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) PREPARE plancache_test3 AS WITH q AS MATERIALIZED (SELECT * FROM z2) SELECT * FROM q,z1 WHERE f_leak(z1.b); EXPLAIN (COSTS OFF) EXECUTE plancache_test3; @@ -2201,7 +2246,8 @@ EXPLAIN (COSTS OFF) EXECUTE plancache_test3; -> Materialize -> Seq Scan on z1 Filter: (((a % 2) = 0) AND f_leak(b)) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) SET ROLE regress_rls_group1; SELECT * FROM z1 WHERE f_leak(b); @@ -2214,18 +2260,20 @@ NOTICE: f_leak => dad (2 rows) EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b); - QUERY PLAN ------------------------------------------ + QUERY PLAN +---------------------------------------------- Seq Scan on z1 Filter: (((a % 2) = 0) AND f_leak(b)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) EXPLAIN (COSTS OFF) EXECUTE plancache_test; - QUERY PLAN ------------------------------------------ + QUERY PLAN +---------------------------------------------- Seq Scan on z1 Filter: (((a % 2) = 0) AND f_leak(b)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) EXPLAIN (COSTS OFF) EXECUTE plancache_test2; QUERY PLAN @@ -2237,7 +2285,8 @@ EXPLAIN (COSTS OFF) EXECUTE plancache_test2; -> CTE Scan on q -> Materialize -> Seq Scan on z2 -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) EXPLAIN (COSTS OFF) EXECUTE plancache_test3; QUERY PLAN @@ -2249,7 +2298,8 @@ EXPLAIN (COSTS OFF) EXECUTE plancache_test3; -> Materialize -> Seq Scan on z1 Filter: (((a % 2) = 0) AND f_leak(b)) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) SET SESSION AUTHORIZATION regress_rls_carol; SELECT * FROM z1 WHERE f_leak(b); @@ -2262,18 +2312,20 @@ NOTICE: f_leak => ccc (2 rows) EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b); - QUERY PLAN ------------------------------------------ + QUERY PLAN +---------------------------------------------- Seq Scan on z1 Filter: (((a % 2) = 1) AND f_leak(b)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) EXPLAIN (COSTS OFF) EXECUTE plancache_test; - QUERY PLAN ------------------------------------------ + QUERY PLAN +---------------------------------------------- Seq Scan on z1 Filter: (((a % 2) = 1) AND f_leak(b)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) EXPLAIN (COSTS OFF) EXECUTE plancache_test2; QUERY PLAN @@ -2285,7 +2337,8 @@ EXPLAIN (COSTS OFF) EXECUTE plancache_test2; -> CTE Scan on q -> Materialize -> Seq Scan on z2 -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) EXPLAIN (COSTS OFF) EXECUTE plancache_test3; QUERY PLAN @@ -2297,7 +2350,8 @@ EXPLAIN (COSTS OFF) EXECUTE plancache_test3; -> Materialize -> Seq Scan on z1 Filter: (((a % 2) = 1) AND f_leak(b)) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) SET ROLE regress_rls_group2; SELECT * FROM z1 WHERE f_leak(b); @@ -2310,18 +2364,20 @@ NOTICE: f_leak => ccc (2 rows) EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b); - QUERY PLAN ------------------------------------------ + QUERY PLAN +---------------------------------------------- Seq Scan on z1 Filter: (((a % 2) = 1) AND f_leak(b)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) EXPLAIN (COSTS OFF) EXECUTE plancache_test; - QUERY PLAN ------------------------------------------ + QUERY PLAN +---------------------------------------------- Seq Scan on z1 Filter: (((a % 2) = 1) AND f_leak(b)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) EXPLAIN (COSTS OFF) EXECUTE plancache_test2; QUERY PLAN @@ -2333,7 +2389,8 @@ EXPLAIN (COSTS OFF) EXECUTE plancache_test2; -> CTE Scan on q -> Materialize -> Seq Scan on z2 -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) EXPLAIN (COSTS OFF) EXECUTE plancache_test3; QUERY PLAN @@ -2345,7 +2402,8 @@ EXPLAIN (COSTS OFF) EXECUTE plancache_test3; -> Materialize -> Seq Scan on z1 Filter: (((a % 2) = 1) AND f_leak(b)) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) -- -- Views should follow policy for view owner. @@ -2370,11 +2428,12 @@ NOTICE: f_leak => dad (4 rows) EXPLAIN (COSTS OFF) SELECT * FROM rls_view; - QUERY PLAN ---------------------- + QUERY PLAN +---------------------------------------------- Seq Scan on z1 Filter: f_leak(b) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) -- Query as view/table owner. Should return all records. SET SESSION AUTHORIZATION regress_rls_alice; @@ -2392,11 +2451,12 @@ NOTICE: f_leak => dad (4 rows) EXPLAIN (COSTS OFF) SELECT * FROM rls_view; - QUERY PLAN ---------------------- + QUERY PLAN +---------------------------------------------- Seq Scan on z1 Filter: f_leak(b) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) DROP VIEW rls_view; -- View and Table owners are different. @@ -2416,11 +2476,12 @@ NOTICE: f_leak => dad (2 rows) EXPLAIN (COSTS OFF) SELECT * FROM rls_view; - QUERY PLAN ------------------------------------------ + QUERY PLAN +---------------------------------------------- Seq Scan on z1 Filter: (((a % 2) = 0) AND f_leak(b)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) -- Query as role that is not owner of table but is owner of view. -- Should return records based on view owner policies. @@ -2435,11 +2496,12 @@ NOTICE: f_leak => dad (2 rows) EXPLAIN (COSTS OFF) SELECT * FROM rls_view; - QUERY PLAN ------------------------------------------ + QUERY PLAN +---------------------------------------------- Seq Scan on z1 Filter: (((a % 2) = 0) AND f_leak(b)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) -- Query as role that is not the owner of the table or view without permissions. SET SESSION AUTHORIZATION regress_rls_carol; @@ -2460,11 +2522,12 @@ NOTICE: f_leak => dad (2 rows) EXPLAIN (COSTS OFF) SELECT * FROM rls_view; - QUERY PLAN ------------------------------------------ + QUERY PLAN +---------------------------------------------- Seq Scan on z1 Filter: (((a % 2) = 0) AND f_leak(b)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) SET SESSION AUTHORIZATION regress_rls_bob; DROP VIEW rls_view; @@ -2598,11 +2661,12 @@ SET SESSION AUTHORIZATION regress_rls_alice; CREATE VIEW rls_sbv WITH (security_barrier) AS SELECT * FROM y1 WHERE f_leak(b); EXPLAIN (COSTS OFF) SELECT * FROM rls_sbv WHERE (a = 1); - QUERY PLAN ------------------------------------ + QUERY PLAN +---------------------------------------------- Seq Scan on y1 Filter: (f_leak(b) AND (a = 1)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) DROP VIEW rls_sbv; -- Create view as role that does not own table. RLS should be applied. @@ -2614,7 +2678,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM rls_sbv WHERE (a = 1); ------------------------------------------------------------------ Seq Scan on y1 Filter: ((a = 1) AND ((a > 2) OR ((a % 2) = 0)) AND f_leak(b)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) DROP VIEW rls_sbv; -- @@ -2663,7 +2728,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM y2 WHERE f_leak(b); ----------------------------------------------------------------------------- Seq Scan on y2 Filter: ((((a % 4) = 0) OR ((a % 3) = 0) OR ((a % 2) = 0)) AND f_leak(b)) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) -- -- Qual push-down of leaky functions, when not referring to table @@ -2713,7 +2779,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM y2 WHERE f_leak('abc'); --------------------------------------------------------------------------------------- Seq Scan on y2 Filter: (f_leak('abc'::text) AND (((a % 4) = 0) OR ((a % 3) = 0) OR ((a % 2) = 0))) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) CREATE TABLE test_qual_pushdown ( abc text @@ -2736,7 +2803,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM y2 JOIN test_qual_pushdown ON (b = abc) WHERE -> Hash -> Seq Scan on y2 Filter: (((a % 4) = 0) OR ((a % 3) = 0) OR ((a % 2) = 0)) -(7 rows) + Settings: search_path = 'regress_rls_schema' +(8 rows) SELECT * FROM y2 JOIN test_qual_pushdown ON (b = abc) WHERE f_leak(b); NOTICE: f_leak => cfcd208495d565ef66e7dff9f98764da @@ -2766,7 +2834,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM y2 JOIN test_qual_pushdown ON (b = abc) WHERE -> Hash -> Seq Scan on y2 Filter: ((((a % 4) = 0) OR ((a % 3) = 0) OR ((a % 2) = 0)) AND f_leak(b)) -(6 rows) + Settings: search_path = 'regress_rls_schema' +(7 rows) DROP TABLE test_qual_pushdown; -- @@ -2787,31 +2856,34 @@ SET ROLE regress_rls_bob; PREPARE role_inval AS SELECT * FROM t1; -- Check plan EXPLAIN (COSTS OFF) EXECUTE role_inval; - QUERY PLAN -------------------------- + QUERY PLAN +---------------------------------------------- Seq Scan on t1 Filter: ((a % 2) = 0) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) -- Change to regress_rls_carol SET ROLE regress_rls_carol; -- Check plan- should be different EXPLAIN (COSTS OFF) EXECUTE role_inval; - QUERY PLAN -------------------------- + QUERY PLAN +---------------------------------------------- Seq Scan on t1 Filter: ((a % 4) = 0) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) -- Change back to regress_rls_bob SET ROLE regress_rls_bob; -- Check plan- should be back to original EXPLAIN (COSTS OFF) EXECUTE role_inval; - QUERY PLAN -------------------------- + QUERY PLAN +---------------------------------------------- Seq Scan on t1 Filter: ((a % 2) = 0) -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) -- -- CTE and RLS @@ -2859,7 +2931,8 @@ WITH cte1 AS MATERIALIZED (SELECT * FROM t1 WHERE f_leak(b)) SELECT * FROM cte1; CTE cte1 -> Seq Scan on t1 Filter: (((a % 2) = 0) AND f_leak(b)) -(4 rows) + Settings: search_path = 'regress_rls_schema' +(5 rows) WITH cte1 AS (UPDATE t1 SET a = a + 1 RETURNING *) SELECT * FROM cte1; --fail ERROR: new row violates row-level security policy for table "t1" @@ -2919,12 +2992,13 @@ SET SESSION AUTHORIZATION regress_rls_bob; CREATE TABLE t2 (a integer, b text); INSERT INTO t2 (SELECT * FROM t1); EXPLAIN (COSTS OFF) INSERT INTO t2 (SELECT * FROM t1); - QUERY PLAN -------------------------------- + QUERY PLAN +---------------------------------------------- Insert on t2 -> Seq Scan on t1 Filter: ((a % 2) = 0) -(3 rows) + Settings: search_path = 'regress_rls_schema' +(4 rows) SELECT * FROM t2; a | b @@ -2944,10 +3018,11 @@ SELECT * FROM t2; (12 rows) EXPLAIN (COSTS OFF) SELECT * FROM t2; - QUERY PLAN ----------------- + QUERY PLAN +---------------------------------------------- Seq Scan on t2 -(1 row) + Settings: search_path = 'regress_rls_schema' +(2 rows) CREATE TABLE t3 AS SELECT * FROM t1; SELECT * FROM t3; @@ -3079,10 +3154,11 @@ SELECT * FROM t1; (22 rows) EXPLAIN (COSTS OFF) SELECT * FROM t1; - QUERY PLAN ----------------- + QUERY PLAN +---------------------------------------------- Seq Scan on t1 -(1 row) + Settings: search_path = 'regress_rls_schema' +(2 rows) -- Check that default deny does not apply to table owner. SET SESSION AUTHORIZATION regress_rls_alice; @@ -3114,10 +3190,11 @@ SELECT * FROM t1; (22 rows) EXPLAIN (COSTS OFF) SELECT * FROM t1; - QUERY PLAN ----------------- + QUERY PLAN +---------------------------------------------- Seq Scan on t1 -(1 row) + Settings: search_path = 'regress_rls_schema' +(2 rows) -- Check that default deny applies to non-owner/non-superuser when RLS on. SET SESSION AUTHORIZATION regress_rls_bob; @@ -3128,11 +3205,12 @@ SELECT * FROM t1; (0 rows) EXPLAIN (COSTS OFF) SELECT * FROM t1; - QUERY PLAN --------------------------- + QUERY PLAN +---------------------------------------------- Result One-Time Filter: false -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) SET SESSION AUTHORIZATION regress_rls_bob; SELECT * FROM t1; @@ -3141,11 +3219,12 @@ SELECT * FROM t1; (0 rows) EXPLAIN (COSTS OFF) SELECT * FROM t1; - QUERY PLAN --------------------------- + QUERY PLAN +---------------------------------------------- Result One-Time Filter: false -(2 rows) + Settings: search_path = 'regress_rls_schema' +(3 rows) -- -- COPY TO/FROM @@ -3376,7 +3455,8 @@ EXPLAIN (COSTS OFF) UPDATE current_check SET payload = payload WHERE CURRENT OF -> Tid Scan on current_check TID Cond: CURRENT OF current_check_cursor Filter: ((currentid = 4) AND ((currentid % 2) = 0)) -(4 rows) + Settings: search_path = 'regress_rls_schema' +(5 rows) -- Similarly can only delete row 4 FETCH ABSOLUTE 1 FROM current_check_cursor; diff --git a/src/test/regress/expected/rowtypes.out b/src/test/regress/expected/rowtypes.out index ffccaa5c9d..3c39450839 100644 --- a/src/test/regress/expected/rowtypes.out +++ b/src/test/regress/expected/rowtypes.out @@ -406,7 +406,8 @@ select a,b from test_table where (a,b) > ('a','a') order by a,b; -------------------------------------------------------- Index Only Scan using test_table_a_b_idx on test_table Index Cond: (ROW(a, b) > ROW('a'::text, 'a'::text)) -(2 rows) + Settings: enable_sort = 'off' +(3 rows) select a,b from test_table where (a,b) > ('a','a') order by a,b; a | b diff --git a/src/test/regress/expected/select.out b/src/test/regress/expected/select.out index c441049f41..da4c1b8202 100644 --- a/src/test/regress/expected/select.out +++ b/src/test/regress/expected/select.out @@ -744,7 +744,8 @@ select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; Index Scan using onek2_u2_prtl on onek2 Index Cond: (unique2 = 11) Filter: (stringu1 = 'ATAAAA'::name) -(3 rows) + Settings: enable_sort = 'off' +(4 rows) select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 @@ -753,14 +754,16 @@ select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; (1 row) -- actually run the query with an analyze to use the partial index -explain (costs off, analyze on, timing off, summary off) +explain (costs off, exec on, timing off, summary off) select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; QUERY PLAN ----------------------------------------------------------------- Index Scan using onek2_u2_prtl on onek2 (actual rows=1 loops=1) Index Cond: (unique2 = 11) Filter: (stringu1 = 'ATAAAA'::name) -(3 rows) + Buffers: shared hit=2 + Settings: enable_sort = 'off' +(5 rows) explain (costs off) select unique2 from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; @@ -769,7 +772,8 @@ select unique2 from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; Index Scan using onek2_u2_prtl on onek2 Index Cond: (unique2 = 11) Filter: (stringu1 = 'ATAAAA'::name) -(3 rows) + Settings: enable_sort = 'off' +(4 rows) select unique2 from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; unique2 @@ -784,7 +788,8 @@ select * from onek2 where unique2 = 11 and stringu1 < 'B'; ----------------------------------------- Index Scan using onek2_u2_prtl on onek2 Index Cond: (unique2 = 11) -(2 rows) + Settings: enable_sort = 'off' +(3 rows) select * from onek2 where unique2 = 11 and stringu1 < 'B'; unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 @@ -798,7 +803,8 @@ select unique2 from onek2 where unique2 = 11 and stringu1 < 'B'; ---------------------------------------------- Index Only Scan using onek2_u2_prtl on onek2 Index Cond: (unique2 = 11) -(2 rows) + Settings: enable_sort = 'off' +(3 rows) select unique2 from onek2 where unique2 = 11 and stringu1 < 'B'; unique2 @@ -815,7 +821,8 @@ select unique2 from onek2 where unique2 = 11 and stringu1 < 'B' for update; -> Index Scan using onek2_u2_prtl on onek2 Index Cond: (unique2 = 11) Filter: (stringu1 < 'B'::name) -(4 rows) + Settings: enable_sort = 'off' +(5 rows) select unique2 from onek2 where unique2 = 11 and stringu1 < 'B' for update; unique2 @@ -830,7 +837,8 @@ select unique2 from onek2 where unique2 = 11 and stringu1 < 'C'; ------------------------------------------------------- Seq Scan on onek2 Filter: ((stringu1 < 'C'::name) AND (unique2 = 11)) -(2 rows) + Settings: enable_sort = 'off' +(3 rows) select unique2 from onek2 where unique2 = 11 and stringu1 < 'C'; unique2 @@ -848,7 +856,8 @@ select unique2 from onek2 where unique2 = 11 and stringu1 < 'B'; Recheck Cond: ((unique2 = 11) AND (stringu1 < 'B'::name)) -> Bitmap Index Scan on onek2_u2_prtl Index Cond: (unique2 = 11) -(4 rows) + Settings: enable_indexscan = 'off', enable_sort = 'off' +(5 rows) select unique2 from onek2 where unique2 = 11 and stringu1 < 'B'; unique2 @@ -871,30 +880,32 @@ select unique1, unique2 from onek2 Index Cond: (unique2 = 11) -> Bitmap Index Scan on onek2_u1_prtl Index Cond: (unique1 = 0) + Settings: enable_sort = 'off' +(9 rows) + +select unique1, unique2 from onek2 + where (unique2 = 11 or unique1 = 0) and stringu1 < 'B'; + unique1 | unique2 +---------+--------- + 494 | 11 + 0 | 998 +(2 rows) + +explain (costs off) +select unique1, unique2 from onek2 + where (unique2 = 11 and stringu1 < 'B') or unique1 = 0; + QUERY PLAN +-------------------------------------------------------------------------------- + Bitmap Heap Scan on onek2 + Recheck Cond: (((unique2 = 11) AND (stringu1 < 'B'::name)) OR (unique1 = 0)) + -> BitmapOr + -> Bitmap Index Scan on onek2_u2_prtl + Index Cond: (unique2 = 11) + -> Bitmap Index Scan on onek2_u1_prtl + Index Cond: (unique1 = 0) + Settings: enable_sort = 'off' (8 rows) -select unique1, unique2 from onek2 - where (unique2 = 11 or unique1 = 0) and stringu1 < 'B'; - unique1 | unique2 ----------+--------- - 494 | 11 - 0 | 998 -(2 rows) - -explain (costs off) -select unique1, unique2 from onek2 - where (unique2 = 11 and stringu1 < 'B') or unique1 = 0; - QUERY PLAN --------------------------------------------------------------------------------- - Bitmap Heap Scan on onek2 - Recheck Cond: (((unique2 = 11) AND (stringu1 < 'B'::name)) OR (unique1 = 0)) - -> BitmapOr - -> Bitmap Index Scan on onek2_u2_prtl - Index Cond: (unique2 = 11) - -> Bitmap Index Scan on onek2_u1_prtl - Index Cond: (unique1 = 0) -(7 rows) - select unique1, unique2 from onek2 where (unique2 = 11 and stringu1 < 'B') or unique1 = 0; unique1 | unique2 @@ -957,10 +968,11 @@ create table list_parted_tbl (a int,b int) partition by list (a); create table list_parted_tbl1 partition of list_parted_tbl for values in (1) partition by list(b); explain (costs off) select * from list_parted_tbl; - QUERY PLAN --------------------------- + QUERY PLAN +------------------------------- Result One-Time Filter: false -(2 rows) + Settings: enable_sort = 'off' +(3 rows) drop table list_parted_tbl; diff --git a/src/test/regress/expected/select_into.out b/src/test/regress/expected/select_into.out index f373fae679..3ddb485965 100644 --- a/src/test/regress/expected/select_into.out +++ b/src/test/regress/expected/select_into.out @@ -112,15 +112,21 @@ SELECT * FROM created_table; 4567890123456789 | -4567890123456789 (5 rows) --- Try EXPLAIN ANALYZE SELECT INTO and EXPLAIN ANALYZE CREATE TABLE AS +-- Try EXPLAIN EXEC SELECT INTO and EXPLAIN EXEC CREATE TABLE AS -- WITH NO DATA, but hide the outputs since they won't be stable. DO $$ BEGIN - EXECUTE 'EXPLAIN ANALYZE SELECT * INTO TABLE easi FROM int8_tbl'; - EXECUTE 'EXPLAIN ANALYZE CREATE TABLE easi2 AS SELECT * FROM int8_tbl WITH NO DATA'; + EXECUTE 'EXPLAIN EXEC SELECT * INTO TABLE easi FROM int8_tbl'; + EXECUTE 'EXPLAIN EXEC CREATE TABLE easi2 AS SELECT * FROM int8_tbl WITH NO DATA'; END$$; +ERROR: syntax error at or near "EXEC" +LINE 1: EXPLAIN EXEC SELECT * INTO TABLE easi FROM int8_tbl + ^ +QUERY: EXPLAIN EXEC SELECT * INTO TABLE easi FROM int8_tbl +CONTEXT: PL/pgSQL function inline_code_block line 3 at EXECUTE DROP TABLE created_table; DROP TABLE easi, easi2; +ERROR: table "easi" does not exist -- -- Disallowed uses of SELECT ... INTO. All should fail -- diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out index 0eca76cb41..5787360a23 100644 --- a/src/test/regress/expected/select_parallel.out +++ b/src/test/regress/expected/select_parallel.out @@ -14,8 +14,8 @@ set max_parallel_workers_per_gather=4; -- Parallel Append with partial-subplans explain (costs off) select round(avg(aa)), sum(aa) from a_star; - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 3 @@ -27,7 +27,8 @@ explain (costs off) -> Parallel Seq Scan on b_star -> Parallel Seq Scan on c_star -> Parallel Seq Scan on a_star -(11 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(12 rows) select round(avg(aa)), sum(aa) from a_star a1; round | sum @@ -40,8 +41,8 @@ alter table c_star set (parallel_workers = 0); alter table d_star set (parallel_workers = 0); explain (costs off) select round(avg(aa)), sum(aa) from a_star; - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 3 @@ -53,7 +54,8 @@ explain (costs off) -> Parallel Seq Scan on e_star -> Parallel Seq Scan on b_star -> Parallel Seq Scan on a_star -(11 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(12 rows) select round(avg(aa)), sum(aa) from a_star a2; round | sum @@ -68,8 +70,8 @@ alter table e_star set (parallel_workers = 0); alter table f_star set (parallel_workers = 0); explain (costs off) select round(avg(aa)), sum(aa) from a_star; - QUERY PLAN --------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 3 @@ -81,7 +83,8 @@ explain (costs off) -> Seq Scan on b_star -> Seq Scan on c_star -> Seq Scan on a_star -(11 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(12 rows) select round(avg(aa)), sum(aa) from a_star a3; round | sum @@ -99,8 +102,8 @@ alter table f_star reset (parallel_workers); set enable_parallel_append to off; explain (costs off) select round(avg(aa)), sum(aa) from a_star; - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 1 @@ -112,7 +115,8 @@ explain (costs off) -> Parallel Seq Scan on d_star -> Parallel Seq Scan on e_star -> Parallel Seq Scan on f_star -(11 rows) + Settings: enable_parallel_append = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(12 rows) select round(avg(aa)), sum(aa) from a_star a4; round | sum @@ -139,8 +143,8 @@ create table part_pa_test_p2 partition of part_pa_test for values from (0) to (m explain (costs off) select (select max((select pa1.b from part_pa_test pa1 where pa1.a = pa2.a))) from part_pa_test pa2; - QUERY PLAN --------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Aggregate -> Gather Workers Planned: 3 @@ -155,22 +159,24 @@ explain (costs off) Filter: (a = pa2.a) -> Seq Scan on part_pa_test_p2 pa1_1 Filter: (a = pa2.a) -(14 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(15 rows) drop table part_pa_test; -- test with leader participation disabled set parallel_leader_participation = off; explain (costs off) select count(*) from tenk1 where stringu1 = 'GRAAAA'; - QUERY PLAN ---------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 4 -> Partial Aggregate -> Parallel Seq Scan on tenk1 Filter: (stringu1 = 'GRAAAA'::name) -(6 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_leader_participation = 'off', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(7 rows) select count(*) from tenk1 where stringu1 = 'GRAAAA'; count @@ -183,15 +189,16 @@ select count(*) from tenk1 where stringu1 = 'GRAAAA'; set max_parallel_workers = 0; explain (costs off) select count(*) from tenk1 where stringu1 = 'GRAAAA'; - QUERY PLAN ---------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 4 -> Partial Aggregate -> Parallel Seq Scan on tenk1 Filter: (stringu1 = 'GRAAAA'::name) -(6 rows) + Settings: max_parallel_workers = '0', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_leader_participation = 'off', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(7 rows) select count(*) from tenk1 where stringu1 = 'GRAAAA'; count @@ -206,8 +213,8 @@ alter table tenk1 set (parallel_workers = 4); explain (verbose, costs off) select sp_parallel_restricted(unique1) from tenk1 where stringu1 = 'GRAAAA' order by 1; - QUERY PLAN ---------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Sort Output: (sp_parallel_restricted(unique1)) Sort Key: (sp_parallel_restricted(tenk1.unique1)) @@ -217,13 +224,14 @@ select sp_parallel_restricted(unique1) from tenk1 -> Parallel Seq Scan on public.tenk1 Output: unique1 Filter: (tenk1.stringu1 = 'GRAAAA'::name) -(9 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(10 rows) -- test parallel plan when group by expression is in target list. explain (costs off) select length(stringu1) from tenk1 group by length(stringu1); - QUERY PLAN ---------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Finalize HashAggregate Group Key: (length((stringu1)::text)) -> Gather @@ -231,7 +239,8 @@ explain (costs off) -> Partial HashAggregate Group Key: length((stringu1)::text) -> Parallel Seq Scan on tenk1 -(7 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(8 rows) select length(stringu1) from tenk1 group by length(stringu1); length @@ -241,8 +250,8 @@ select length(stringu1) from tenk1 group by length(stringu1); explain (costs off) select stringu1, count(*) from tenk1 group by stringu1 order by stringu1; - QUERY PLAN ----------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: stringu1 -> Finalize HashAggregate @@ -252,34 +261,37 @@ explain (costs off) -> Partial HashAggregate Group Key: stringu1 -> Parallel Seq Scan on tenk1 -(9 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(10 rows) -- test that parallel plan for aggregates is not selected when -- target list contains parallel restricted clause. explain (costs off) select sum(sp_parallel_restricted(unique1)) from tenk1 group by(sp_parallel_restricted(unique1)); - QUERY PLAN -------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- HashAggregate Group Key: sp_parallel_restricted(unique1) -> Gather Workers Planned: 4 -> Parallel Index Only Scan using tenk1_unique1 on tenk1 -(5 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(6 rows) -- test prepared statement prepare tenk1_count(integer) As select count((unique1)) from tenk1 where hundred > $1; explain (costs off) execute tenk1_count(1); - QUERY PLAN ----------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 4 -> Partial Aggregate -> Parallel Seq Scan on tenk1 Filter: (hundred > 1) -(6 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(7 rows) execute tenk1_count(1); count @@ -293,8 +305,8 @@ alter table tenk2 set (parallel_workers = 0); explain (costs off) select count(*) from tenk1 where (two, four) not in (select hundred, thousand from tenk2 where thousand > 100); - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 4 @@ -304,7 +316,8 @@ explain (costs off) SubPlan 1 -> Seq Scan on tenk2 Filter: (thousand > 100) -(9 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(10 rows) select count(*) from tenk1 where (two, four) not in (select hundred, thousand from tenk2 where thousand > 100); @@ -317,13 +330,14 @@ select count(*) from tenk1 where (two, four) not in explain (costs off) select * from tenk1 where (unique1 + random())::integer not in (select ten from tenk2); - QUERY PLAN ------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Seq Scan on tenk1 Filter: (NOT (hashed SubPlan 1)) SubPlan 1 -> Seq Scan on tenk2 -(4 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(5 rows) alter table tenk2 reset (parallel_workers); -- test parallel plan for a query containing initplan. @@ -334,8 +348,8 @@ alter table tenk2 set (parallel_workers = 2); explain (costs off) select count(*) from tenk1 where tenk1.unique1 = (Select max(tenk2.unique1) from tenk2); - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Aggregate InitPlan 1 (returns $2) -> Finalize Aggregate @@ -348,7 +362,8 @@ explain (costs off) Params Evaluated: $2 -> Parallel Seq Scan on tenk1 Filter: (unique1 = $2) -(12 rows) + Settings: enable_bitmapscan = 'off', enable_indexonlyscan = 'off', enable_indexscan = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(13 rows) select count(*) from tenk1 where tenk1.unique1 = (Select max(tenk2.unique1) from tenk2); @@ -366,15 +381,16 @@ set enable_seqscan to off; set enable_bitmapscan to off; explain (costs off) select count((unique1)) from tenk1 where hundred > 1; - QUERY PLAN --------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 4 -> Partial Aggregate -> Parallel Index Scan using tenk1_hundred on tenk1 Index Cond: (hundred > 1) -(6 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(7 rows) select count((unique1)) from tenk1 where hundred > 1; count @@ -385,15 +401,16 @@ select count((unique1)) from tenk1 where hundred > 1; -- test parallel index-only scans. explain (costs off) select count(*) from tenk1 where thousand > 95; - QUERY PLAN --------------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 4 -> Partial Aggregate -> Parallel Index Only Scan using tenk1_thous_tenthous on tenk1 Index Cond: (thousand > 95) -(6 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(7 rows) select count(*) from tenk1 where thousand > 95; count @@ -407,8 +424,8 @@ explain (costs off) select * from (select count(unique1) from tenk1 where hundred > 10) ss right join (values (1),(2),(3)) v(x) on true; - QUERY PLAN --------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nested Loop Left Join -> Values Scan on "*VALUES*" -> Finalize Aggregate @@ -417,7 +434,8 @@ select * from -> Partial Aggregate -> Parallel Index Scan using tenk1_hundred on tenk1 Index Cond: (hundred > 10) -(8 rows) + Settings: enable_bitmapscan = 'off', enable_material = 'off', enable_seqscan = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(9 rows) select * from (select count(unique1) from tenk1 where hundred > 10) ss @@ -433,8 +451,8 @@ explain (costs off) select * from (select count(*) from tenk1 where thousand > 99) ss right join (values (1),(2),(3)) v(x) on true; - QUERY PLAN --------------------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nested Loop Left Join -> Values Scan on "*VALUES*" -> Finalize Aggregate @@ -443,7 +461,8 @@ select * from -> Partial Aggregate -> Parallel Index Only Scan using tenk1_thous_tenthous on tenk1 Index Cond: (thousand > 99) -(8 rows) + Settings: enable_bitmapscan = 'off', enable_material = 'off', enable_seqscan = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(9 rows) select * from (select count(*) from tenk1 where thousand > 99) ss @@ -473,8 +492,8 @@ END $$; set work_mem='64kB'; --set small work mem to force lossy pages explain (costs off) select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0; - QUERY PLAN ------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Aggregate -> Nested Loop -> Seq Scan on tenk2 @@ -485,7 +504,8 @@ explain (costs off) Recheck Cond: (hundred > 1) -> Bitmap Index Scan on tenk1_hundred Index Cond: (hundred > 1) -(10 rows) + Settings: effective_io_concurrency = '50', enable_hashjoin = 'off', enable_indexscan = 'off', enable_material = 'off', enable_mergejoin = 'off', enable_seqscan = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0', work_mem = '64kB' +(11 rows) select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0; count @@ -505,23 +525,29 @@ select count(*) from bmscantest where a>1; -- test accumulation of stats for parallel nodes reset enable_seqscan; alter table tenk2 set (parallel_workers = 0); -explain (analyze, timing off, summary off, costs off) +explain (exec, timing off, summary off, costs off) select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0; - QUERY PLAN --------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Aggregate (actual rows=1 loops=1) + Buffers: shared hit=3795 -> Nested Loop (actual rows=98000 loops=1) + Buffers: shared hit=3795 -> Seq Scan on tenk2 (actual rows=10 loops=1) Filter: (thousand = 0) Rows Removed by Filter: 9990 + Buffers: shared hit=345 -> Gather (actual rows=9800 loops=10) Workers Planned: 4 Workers Launched: 4 + Buffers: shared hit=3450 -> Parallel Seq Scan on tenk1 (actual rows=1960 loops=50) Filter: (hundred > 1) Rows Removed by Filter: 40 -(11 rows) + Buffers: shared hit=3450 + Settings: effective_io_concurrency = '50', enable_hashjoin = 'off', enable_indexscan = 'off', enable_material = 'off', enable_mergejoin = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0', work_mem = '64kB' +(17 rows) alter table tenk2 reset (parallel_workers); reset work_mem; @@ -531,7 +557,7 @@ $$ declare ln text; begin for ln in - explain (analyze, timing off, summary off, costs off) + explain (exec, timing off, summary off, costs off) select * from (select ten from tenk1 where ten < 100 order by ten) ss right join (values (1),(2),(3)) v(x) on true @@ -542,13 +568,15 @@ begin end; $$; select * from explain_parallel_sort_stats(); - explain_parallel_sort_stats --------------------------------------------------------------------------- + explain_parallel_sort_stats +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nested Loop Left Join (actual rows=30000 loops=1) + Buffers: shared hit=1427 -> Values Scan on "*VALUES*" (actual rows=3 loops=1) -> Gather Merge (actual rows=10000 loops=3) Workers Planned: 4 Workers Launched: 4 + Buffers: shared hit=1231 -> Sort (actual rows=2000 loops=15) Sort Key: tenk1.ten Sort Method: quicksort Memory: xxx @@ -556,9 +584,12 @@ select * from explain_parallel_sort_stats(); Worker 1: Sort Method: quicksort Memory: xxx Worker 2: Sort Method: quicksort Memory: xxx Worker 3: Sort Method: quicksort Memory: xxx + Buffers: shared hit=1623 -> Parallel Seq Scan on tenk1 (actual rows=2000 loops=15) Filter: (ten < 100) -(14 rows) + Buffers: shared hit=1035 + Settings: effective_io_concurrency = '50', enable_hashjoin = 'off', enable_indexscan = 'off', enable_material = 'off', enable_mergejoin = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(19 rows) reset enable_indexscan; reset enable_hashjoin; @@ -572,8 +603,8 @@ set enable_hashjoin to off; set enable_nestloop to off; explain (costs off) select count(*) from tenk1, tenk2 where tenk1.unique1 = tenk2.unique1; - QUERY PLAN -------------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 4 @@ -582,7 +613,8 @@ explain (costs off) Merge Cond: (tenk1.unique1 = tenk2.unique1) -> Parallel Index Only Scan using tenk1_unique1 on tenk1 -> Index Only Scan using tenk2_unique1 on tenk2 -(8 rows) + Settings: enable_hashjoin = 'off', enable_nestloop = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(9 rows) select count(*) from tenk1, tenk2 where tenk1.unique1 = tenk2.unique1; count @@ -596,8 +628,8 @@ reset enable_nestloop; set enable_hashagg = false; explain (costs off) select count(*) from tenk1 group by twenty; - QUERY PLAN ----------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize GroupAggregate Group Key: twenty -> Gather Merge @@ -607,7 +639,8 @@ explain (costs off) -> Sort Sort Key: twenty -> Parallel Seq Scan on tenk1 -(9 rows) + Settings: enable_hashagg = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(10 rows) select count(*) from tenk1 group by twenty; count @@ -643,8 +676,8 @@ end; $$ language plpgsql PARALLEL SAFE; explain (costs off, verbose) select ten, sp_simple_func(ten) from tenk1 where ten < 100 order by ten; - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------- Gather Merge Output: ten, (sp_simple_func(ten)) Workers Planned: 4 @@ -656,14 +689,15 @@ explain (costs off, verbose) -> Parallel Seq Scan on public.tenk1 Output: ten Filter: (tenk1.ten < 100) -(11 rows) + Settings: enable_hashagg = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(12 rows) drop function sp_simple_func(integer); -- test handling of SRFs in targetlist (bug in 10.0) explain (costs off) select count(*), generate_series(1,2) from tenk1 group by twenty; - QUERY PLAN ----------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------- ProjectSet -> Finalize GroupAggregate Group Key: twenty @@ -674,7 +708,8 @@ explain (costs off) -> Sort Sort Key: twenty -> Parallel Seq Scan on tenk1 -(10 rows) + Settings: enable_hashagg = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(11 rows) select count(*), generate_series(1,2) from tenk1 group by twenty; count | generate_series @@ -725,8 +760,8 @@ select count(*), generate_series(1,2) from tenk1 group by twenty; set parallel_leader_participation = off; explain (costs off) select count(*) from tenk1 group by twenty; - QUERY PLAN ----------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Finalize GroupAggregate Group Key: twenty -> Gather Merge @@ -736,7 +771,8 @@ explain (costs off) -> Sort Sort Key: twenty -> Parallel Seq Scan on tenk1 -(9 rows) + Settings: enable_hashagg = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_leader_participation = 'off', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(10 rows) select count(*) from tenk1 group by twenty; count @@ -771,8 +807,8 @@ select * from (select string4, count(unique2) from tenk1 group by string4 order by string4) ss right join (values (1),(2),(3)) v(x) on true; - QUERY PLAN ----------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nested Loop Left Join -> Values Scan on "*VALUES*" -> Finalize GroupAggregate @@ -784,7 +820,8 @@ select * from -> Sort Sort Key: tenk1.string4 -> Parallel Seq Scan on tenk1 -(11 rows) + Settings: enable_hashagg = 'off', enable_material = 'off', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(12 rows) select * from (select string4, count(unique2) @@ -811,14 +848,15 @@ reset enable_hashagg; -- check parallelized int8 aggregate (bug #14897) explain (costs off) select avg(unique1::int8) from tenk1; - QUERY PLAN -------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate -> Gather Workers Planned: 4 -> Partial Aggregate -> Parallel Index Only Scan using tenk1_unique1 on tenk1 -(5 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(6 rows) select avg(unique1::int8) from tenk1; avg @@ -829,15 +867,16 @@ select avg(unique1::int8) from tenk1; -- gather merge test with a LIMIT explain (costs off) select fivethous from tenk1 order by fivethous limit 4; - QUERY PLAN ----------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Limit -> Gather Merge Workers Planned: 4 -> Sort Sort Key: fivethous -> Parallel Seq Scan on tenk1 -(6 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(7 rows) select fivethous from tenk1 order by fivethous limit 4; fivethous @@ -852,15 +891,16 @@ select fivethous from tenk1 order by fivethous limit 4; set max_parallel_workers = 0; explain (costs off) select string4 from tenk1 order by string4 limit 5; - QUERY PLAN ----------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit -> Gather Merge Workers Planned: 4 -> Sort Sort Key: string4 -> Parallel Seq Scan on tenk1 -(6 rows) + Settings: max_parallel_workers = '0', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(7 rows) select string4 from tenk1 order by string4 limit 5; string4 @@ -878,15 +918,16 @@ select string4 from tenk1 order by string4 limit 5; set parallel_leader_participation = off; explain (costs off) select string4 from tenk1 order by string4 limit 5; - QUERY PLAN ----------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit -> Gather Merge Workers Planned: 4 -> Sort Sort Key: string4 -> Parallel Seq Scan on tenk1 -(6 rows) + Settings: max_parallel_workers = '0', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_leader_participation = 'off', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(7 rows) select string4 from tenk1 order by string4 limit 5; string4 @@ -904,14 +945,15 @@ SAVEPOINT settings; SET LOCAL force_parallel_mode = 1; explain (costs off) select stringu1::int2 from tenk1 where unique1 = 1; - QUERY PLAN ------------------------------------------------ + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Gather Workers Planned: 1 Single Copy: true -> Index Scan using tenk1_unique1 on tenk1 Index Cond: (unique1 = 1) -(5 rows) + Settings: force_parallel_mode = 'on', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(6 rows) ROLLBACK TO SAVEPOINT settings; -- exercise record typmod remapping between backends @@ -962,8 +1004,8 @@ reset role; explain (costs off, verbose) select count(*) from tenk1 a where (unique1, two) in (select unique1, row_number() over() from tenk1 b); - QUERY PLAN ----------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Aggregate Output: count(*) -> Hash Semi Join @@ -982,14 +1024,15 @@ explain (costs off, verbose) Workers Planned: 4 -> Parallel Index Only Scan using tenk1_unique1 on public.tenk1 b Output: b.unique1 -(18 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(19 rows) -- LIMIT/OFFSET within sub-selects can't be pushed to workers. explain (costs off) select * from tenk1 a where two in (select two from tenk1 b where stringu1 like '%AAAA' limit 3); - QUERY PLAN ---------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Hash Semi Join Hash Cond: (a.two = b.two) -> Gather @@ -1001,19 +1044,23 @@ explain (costs off) Workers Planned: 4 -> Parallel Seq Scan on tenk1 b Filter: (stringu1 ~~ '%AAAA'::text) -(11 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(12 rows) -- to increase the parallel query test coverage SAVEPOINT settings; SET LOCAL force_parallel_mode = 1; -EXPLAIN (analyze, timing off, summary off, costs off) SELECT * FROM tenk1; - QUERY PLAN -------------------------------------------------------------- +EXPLAIN (exec, timing off, summary off, costs off) SELECT * FROM tenk1; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Gather (actual rows=10000 loops=1) Workers Planned: 4 Workers Launched: 4 + Buffers: shared hit=345 -> Parallel Seq Scan on tenk1 (actual rows=2000 loops=5) -(4 rows) + Buffers: shared hit=345 + Settings: force_parallel_mode = 'on', max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(7 rows) ROLLBACK TO SAVEPOINT settings; -- provoke error in worker @@ -1032,8 +1079,8 @@ EXPLAIN (COSTS OFF) SELECT unique1 FROM tenk1 WHERE fivethous = tenthous + 1 UNION ALL SELECT unique1 FROM tenk1 WHERE fivethous = tenthous + 1; - QUERY PLAN ----------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------- Gather Workers Planned: 4 -> Parallel Append @@ -1041,7 +1088,8 @@ SELECT unique1 FROM tenk1 WHERE fivethous = tenthous + 1; Filter: (fivethous = (tenthous + 1)) -> Parallel Seq Scan on tenk1 tenk1_1 Filter: (fivethous = (tenthous + 1)) -(7 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '10', parallel_tuple_cost = '0' +(8 rows) ROLLBACK TO SAVEPOINT settings; -- can't use multiple subqueries under a single Gather node due to initPlans @@ -1052,8 +1100,8 @@ UNION ALL SELECT unique1 FROM tenk1 WHERE fivethous = (SELECT unique2 FROM tenk1 WHERE fivethous = 1 LIMIT 1) ORDER BY 1; - QUERY PLAN --------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Sort Sort Key: tenk1.unique1 -> Append @@ -1079,7 +1127,8 @@ ORDER BY 1; Filter: (fivethous = 1) -> Parallel Seq Scan on tenk1 tenk1_1 Filter: (fivethous = $3) -(25 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(26 rows) -- test interaction with SRFs SELECT * FROM information_schema.foreign_data_wrapper_options @@ -1100,13 +1149,14 @@ CREATE TABLE fooarr(f1 text, f2 int[], f3 text); INSERT INTO fooarr VALUES('1', ARRAY[1,2], 'one'); PREPARE pstmt(text, int[]) AS SELECT * FROM fooarr WHERE f1 = $1 AND f2 = $2; EXPLAIN (COSTS OFF) EXECUTE pstmt('1', make_some_array(1,2)); - QUERY PLAN ------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Gather Workers Planned: 3 -> Parallel Seq Scan on fooarr Filter: ((f1 = '1'::text) AND (f2 = '{1,2}'::integer[])) -(4 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(5 rows) EXECUTE pstmt('1', make_some_array(1,2)); f1 | f2 | f3 @@ -1120,8 +1170,8 @@ CREATE VIEW tenk1_vw_sec WITH (security_barrier) AS SELECT * FROM tenk1; EXPLAIN (COSTS OFF) SELECT 1 FROM tenk1_vw_sec WHERE (SELECT sum(f1) FROM int4_tbl WHERE f1 < unique1) < 100; - QUERY PLAN -------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Subquery Scan on tenk1_vw_sec Filter: ((SubPlan 1) < 100) -> Gather @@ -1131,6 +1181,7 @@ SELECT 1 FROM tenk1_vw_sec -> Aggregate -> Seq Scan on int4_tbl Filter: (f1 < tenk1_vw_sec.unique1) -(9 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(10 rows) rollback; diff --git a/src/test/regress/expected/stats_ext.out b/src/test/regress/expected/stats_ext.out index 6dfca7a606..836ee928a0 100644 --- a/src/test/regress/expected/stats_ext.out +++ b/src/test/regress/expected/stats_ext.out @@ -12,7 +12,7 @@ declare first_row bool := true; begin for ln in - execute format('explain analyze %s', $1) + execute format('explain exec %s', $1) loop if first_row then first_row := false; @@ -167,35 +167,35 @@ INSERT INTO ndistinct (a, b, c, filler1) ANALYZE ndistinct; -- Group Aggregate, due to over-estimate of the number of groups SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b'); - estimated | actual ------------+-------- - 100 | 11 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY b, c'); - estimated | actual ------------+-------- - 100 | 11 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY b, c + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY b, c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c'); - estimated | actual ------------+-------- - 100 | 11 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c, d'); - estimated | actual ------------+-------- - 200 | 11 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c... + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c, d +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY b, c, d'); - estimated | actual ------------+-------- - 200 | 11 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY b, c, d + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY b, c, d +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- correct command CREATE STATISTICS s10 ON a, b, c FROM ndistinct; ANALYZE ndistinct; @@ -208,37 +208,37 @@ SELECT stxkind, stxndistinct -- Hash Aggregate, thanks to estimates improved by the statistic SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b'); - estimated | actual ------------+-------- - 11 | 11 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY b, c'); - estimated | actual ------------+-------- - 11 | 11 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY b, c + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY b, c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c'); - estimated | actual ------------+-------- - 11 | 11 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- last two plans keep using Group Aggregate, because 'd' is not covered -- by the statistic and while it's NULL-only we assume 200 values for it SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c, d'); - estimated | actual ------------+-------- - 200 | 11 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c... + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c, d +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY b, c, d'); - estimated | actual ------------+-------- - 200 | 11 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY b, c, d + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY b, c, d +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement TRUNCATE TABLE ndistinct; -- under-estimates when using only per-column statistics INSERT INTO ndistinct (a, b, c, filler1) @@ -255,35 +255,35 @@ SELECT stxkind, stxndistinct -- correct esimates SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b'); - estimated | actual ------------+-------- - 2550 | 2550 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c'); - estimated | actual ------------+-------- - 5000 | 5000 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c, d'); - estimated | actual ------------+-------- - 5000 | 5000 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c... + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c, d +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY b, c, d'); - estimated | actual ------------+-------- - 1632 | 1632 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY b, c, d + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY b, c, d +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, d'); - estimated | actual ------------+-------- - 500 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, d + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, d +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement DROP STATISTICS s10; SELECT stxkind, stxndistinct FROM pg_statistic_ext WHERE stxrelid = 'ndistinct'::regclass; @@ -293,35 +293,35 @@ SELECT stxkind, stxndistinct -- dropping the statistics results in under-estimates SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b'); - estimated | actual ------------+-------- - 500 | 2550 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c'); - estimated | actual ------------+-------- - 500 | 5000 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c, d'); - estimated | actual ------------+-------- - 500 | 5000 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c... + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, b, c, d +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY b, c, d'); - estimated | actual ------------+-------- - 500 | 1632 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY b, c, d + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY b, c, d +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, d'); - estimated | actual ------------+-------- - 500 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, d + ^ +QUERY: explain exec SELECT COUNT(*) FROM ndistinct GROUP BY a, d +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- functional dependencies tests CREATE TABLE functional_dependencies ( filler1 TEXT, @@ -339,32 +339,32 @@ INSERT INTO functional_dependencies (a, b, c, filler1) SELECT mod(i, 23), mod(i, 29), mod(i, 31), i FROM generate_series(1,5000) s(i); ANALYZE functional_dependencies; SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a = 1 AND b = ''1'''); - estimated | actual ------------+-------- - 8 | 8 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM functional_dependencies WHERE a =... + ^ +QUERY: explain exec SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a = 1 AND b = ''1'' AND c = 1'); - estimated | actual ------------+-------- - 1 | 1 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM functional_dependencies WHERE a =... + ^ +QUERY: explain exec SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' AND c = 1 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- create statistics CREATE STATISTICS func_deps_stat (dependencies) ON a, b, c FROM functional_dependencies; ANALYZE functional_dependencies; SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a = 1 AND b = ''1'''); - estimated | actual ------------+-------- - 8 | 8 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM functional_dependencies WHERE a =... + ^ +QUERY: explain exec SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a = 1 AND b = ''1'' AND c = 1'); - estimated | actual ------------+-------- - 1 | 1 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM functional_dependencies WHERE a =... + ^ +QUERY: explain exec SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' AND c = 1 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- a => b, a => c, b => c TRUNCATE functional_dependencies; DROP STATISTICS func_deps_stat; @@ -372,47 +372,47 @@ INSERT INTO functional_dependencies (a, b, c, filler1) SELECT mod(i,100), mod(i,50), mod(i,25), i FROM generate_series(1,5000) s(i); ANALYZE functional_dependencies; SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a = 1 AND b = ''1'''); - estimated | actual ------------+-------- - 1 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM functional_dependencies WHERE a =... + ^ +QUERY: explain exec SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a = 1 AND b = ''1'' AND c = 1'); - estimated | actual ------------+-------- - 1 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM functional_dependencies WHERE a =... + ^ +QUERY: explain exec SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' AND c = 1 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- create statistics CREATE STATISTICS func_deps_stat (dependencies) ON a, b, c FROM functional_dependencies; ANALYZE functional_dependencies; SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a = 1 AND b = ''1'''); - estimated | actual ------------+-------- - 50 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM functional_dependencies WHERE a =... + ^ +QUERY: explain exec SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a = 1 AND b = ''1'' AND c = 1'); - estimated | actual ------------+-------- - 50 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM functional_dependencies WHERE a =... + ^ +QUERY: explain exec SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' AND c = 1 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- check change of column type doesn't break it ALTER TABLE functional_dependencies ALTER COLUMN c TYPE numeric; SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a = 1 AND b = ''1'' AND c = 1'); - estimated | actual ------------+-------- - 50 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM functional_dependencies WHERE a =... + ^ +QUERY: explain exec SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' AND c = 1 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement ANALYZE functional_dependencies; SELECT * FROM check_estimated_rows('SELECT * FROM functional_dependencies WHERE a = 1 AND b = ''1'' AND c = 1'); - estimated | actual ------------+-------- - 50 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM functional_dependencies WHERE a =... + ^ +QUERY: explain exec SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' AND c = 1 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- MCV lists CREATE TABLE mcv_lists ( filler1 TEXT, @@ -428,32 +428,32 @@ INSERT INTO mcv_lists (a, b, c, filler1) SELECT mod(i,37), mod(i,41), mod(i,43), mod(i,47) FROM generate_series(1,5000) s(i); ANALYZE mcv_lists; SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b = ''1'''); - estimated | actual ------------+-------- - 3 | 4 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b = ''1'' AND c = 1'); - estimated | actual ------------+-------- - 1 | 1 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1'... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' AND c = 1 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- create statistics CREATE STATISTICS mcv_lists_stats (mcv) ON a, b, c FROM mcv_lists; ANALYZE mcv_lists; SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b = ''1'''); - estimated | actual ------------+-------- - 3 | 4 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b = ''1'' AND c = 1'); - estimated | actual ------------+-------- - 1 | 1 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1'... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' AND c = 1 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- 100 distinct combinations, all in the MCV list TRUNCATE mcv_lists; DROP STATISTICS mcv_lists_stats; @@ -461,80 +461,80 @@ INSERT INTO mcv_lists (a, b, c, filler1) SELECT mod(i,100), mod(i,50), mod(i,25), i FROM generate_series(1,5000) s(i); ANALYZE mcv_lists; SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b = ''1'''); - estimated | actual ------------+-------- - 1 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a < 1 AND b < ''1'''); - estimated | actual ------------+-------- - 1 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a < 1 AND b < '1' + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a < 1 AND b < '1' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a <= 0 AND b <= ''0'''); - estimated | actual ------------+-------- - 1 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a <= 0 AND b <= '... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a <= 0 AND b <= '0' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b = ''1'' AND c = 1'); - estimated | actual ------------+-------- - 1 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1'... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' AND c = 1 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a < 5 AND b < ''1'' AND c < 5'); - estimated | actual ------------+-------- - 1 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a < 5 AND b < '1'... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a < 5 AND b < '1' AND c < 5 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a <= 4 AND b <= ''0'' AND c <= 4'); - estimated | actual ------------+-------- - 1 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a <= 4 AND b <= '... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a <= 4 AND b <= '0' AND c <= 4 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- create statistics CREATE STATISTICS mcv_lists_stats (mcv) ON a, b, c FROM mcv_lists; ANALYZE mcv_lists; SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b = ''1'''); - estimated | actual ------------+-------- - 50 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a < 1 AND b < ''1'''); - estimated | actual ------------+-------- - 50 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a < 1 AND b < '1' + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a < 1 AND b < '1' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a <= 0 AND b <= ''0'''); - estimated | actual ------------+-------- - 50 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a <= 0 AND b <= '... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a <= 0 AND b <= '0' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b = ''1'' AND c = 1'); - estimated | actual ------------+-------- - 50 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1'... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' AND c = 1 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a < 5 AND b < ''1'' AND c < 5'); - estimated | actual ------------+-------- - 50 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a < 5 AND b < '1'... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a < 5 AND b < '1' AND c < 5 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a <= 4 AND b <= ''0'' AND c <= 4'); - estimated | actual ------------+-------- - 50 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a <= 4 AND b <= '... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a <= 4 AND b <= '0' AND c <= 4 +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- check change of unrelated column type does not reset the MCV statistics ALTER TABLE mcv_lists ALTER COLUMN d TYPE VARCHAR(64); SELECT stxmcv IS NOT NULL FROM pg_statistic_ext WHERE stxname = 'mcv_lists_stats'; @@ -546,18 +546,18 @@ SELECT stxmcv IS NOT NULL FROM pg_statistic_ext WHERE stxname = 'mcv_lists_stats -- check change of column type resets the MCV statistics ALTER TABLE mcv_lists ALTER COLUMN c TYPE numeric; SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b = ''1'''); - estimated | actual ------------+-------- - 1 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement ANALYZE mcv_lists; SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a = 1 AND b = ''1'''); - estimated | actual ------------+-------- - 50 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a = 1 AND b = '1' +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- 100 distinct combinations with NULL values, all in the MCV list TRUNCATE mcv_lists; DROP STATISTICS mcv_lists_stats; @@ -570,32 +570,32 @@ INSERT INTO mcv_lists (a, b, c, filler1) FROM generate_series(1,5000) s(i); ANALYZE mcv_lists; SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a IS NULL AND b IS NULL'); - estimated | actual ------------+-------- - 1 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a IS NULL AND b I... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a IS NULL AND b IS NULL +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a IS NULL AND b IS NULL AND c IS NULL'); - estimated | actual ------------+-------- - 1 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a IS NULL AND b I... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a IS NULL AND b IS NULL AND c IS NULL +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- create statistics CREATE STATISTICS mcv_lists_stats (mcv) ON a, b, c FROM mcv_lists; ANALYZE mcv_lists; SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a IS NULL AND b IS NULL'); - estimated | actual ------------+-------- - 50 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a IS NULL AND b I... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a IS NULL AND b IS NULL +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a IS NULL AND b IS NULL AND c IS NULL'); - estimated | actual ------------+-------- - 50 | 50 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists WHERE a IS NULL AND b I... + ^ +QUERY: explain exec SELECT * FROM mcv_lists WHERE a IS NULL AND b IS NULL AND c IS NULL +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement -- test pg_mcv_list_items with a very simple (single item) MCV list TRUNCATE mcv_lists; INSERT INTO mcv_lists (a, b, c) SELECT 1, 2, 3 FROM generate_series(1,1000) s(i); @@ -634,53 +634,53 @@ INSERT INTO mcv_lists_bool (a, b, c) FROM generate_series(1,10000) s(i); ANALYZE mcv_lists_bool; SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists_bool WHERE a AND b AND c'); - estimated | actual ------------+-------- - 156 | 1250 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists_bool WHERE a AND b AND ... + ^ +QUERY: explain exec SELECT * FROM mcv_lists_bool WHERE a AND b AND c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists_bool WHERE NOT a AND b AND c'); - estimated | actual ------------+-------- - 156 | 0 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists_bool WHERE NOT a AND b ... + ^ +QUERY: explain exec SELECT * FROM mcv_lists_bool WHERE NOT a AND b AND c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists_bool WHERE NOT a AND NOT b AND c'); - estimated | actual ------------+-------- - 469 | 0 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists_bool WHERE NOT a AND NO... + ^ +QUERY: explain exec SELECT * FROM mcv_lists_bool WHERE NOT a AND NOT b AND c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists_bool WHERE NOT a AND b AND NOT c'); - estimated | actual ------------+-------- - 1094 | 0 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists_bool WHERE NOT a AND b ... + ^ +QUERY: explain exec SELECT * FROM mcv_lists_bool WHERE NOT a AND b AND NOT c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement CREATE STATISTICS mcv_lists_bool_stats (mcv) ON a, b, c FROM mcv_lists_bool; ANALYZE mcv_lists_bool; SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists_bool WHERE a AND b AND c'); - estimated | actual ------------+-------- - 1250 | 1250 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists_bool WHERE a AND b AND ... + ^ +QUERY: explain exec SELECT * FROM mcv_lists_bool WHERE a AND b AND c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists_bool WHERE NOT a AND b AND c'); - estimated | actual ------------+-------- - 1 | 0 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists_bool WHERE NOT a AND b ... + ^ +QUERY: explain exec SELECT * FROM mcv_lists_bool WHERE NOT a AND b AND c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists_bool WHERE NOT a AND NOT b AND c'); - estimated | actual ------------+-------- - 1 | 0 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists_bool WHERE NOT a AND NO... + ^ +QUERY: explain exec SELECT * FROM mcv_lists_bool WHERE NOT a AND NOT b AND c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists_bool WHERE NOT a AND b AND NOT c'); - estimated | actual ------------+-------- - 1 | 0 -(1 row) - +ERROR: syntax error at or near "exec" +LINE 1: explain exec SELECT * FROM mcv_lists_bool WHERE NOT a AND b ... + ^ +QUERY: explain exec SELECT * FROM mcv_lists_bool WHERE NOT a AND b AND NOT c +CONTEXT: PL/pgSQL function check_estimated_rows(text) line 7 at FOR over EXECUTE statement diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out index 2d1963d12a..fcbffe71f5 100644 --- a/src/test/regress/expected/subselect.out +++ b/src/test/regress/expected/subselect.out @@ -1120,8 +1120,8 @@ drop function tattle(x int, y int); -- -- Test that LIMIT can be pushed to SORT through a subquery that just projects -- columns. We check for that having happened by looking to see if EXPLAIN --- ANALYZE shows that a top-N sort was used. We must suppress or filter away --- all the non-invariant parts of the EXPLAIN ANALYZE output. +-- EXEC shows that a top-N sort was used. We must suppress or filter away +-- all the non-invariant parts of the EXPLAIN EXEC output. -- create table sq_limit (pk int primary key, c1 int, c2 int); insert into sq_limit values @@ -1138,7 +1138,7 @@ $$ declare ln text; begin for ln in - explain (analyze, summary off, timing off, costs off) + explain (exec, summary off, timing off, costs off) select * from (select pk,c2 from sq_limit order by c1,pk) as x limit 3 loop ln := regexp_replace(ln, 'Memory: \S*', 'Memory: xxx'); @@ -1152,12 +1152,16 @@ select * from explain_sq_limit(); explain_sq_limit ---------------------------------------------------------------- Limit (actual rows=3 loops=1) + Buffers: shared hit=1 -> Subquery Scan on x (actual rows=3 loops=1) + Buffers: shared hit=1 -> Sort (actual rows=3 loops=1) Sort Key: sq_limit.c1, sq_limit.pk Sort Method: top-N heapsort Memory: xxx + Buffers: shared hit=1 -> Seq Scan on sq_limit (actual rows=8 loops=1) -(6 rows) + Buffers: shared hit=1 +(10 rows) select * from (select pk,c2 from sq_limit order by c1,pk) as x limit 3; pk | c2 diff --git a/src/test/regress/expected/tidscan.out b/src/test/regress/expected/tidscan.out index 9b5eb04bfd..b19516e39b 100644 --- a/src/test/regress/expected/tidscan.out +++ b/src/test/regress/expected/tidscan.out @@ -120,7 +120,8 @@ FROM tidscan t1 JOIN tidscan t2 ON t1.ctid = t2.ctid WHERE t1.id = 1; Filter: (id = 1) -> Tid Scan on tidscan t2 TID Cond: (ctid = t1.ctid) -(5 rows) + Settings: enable_hashjoin = 'off' +(6 rows) SELECT t1.ctid, t1.*, t2.ctid, t2.* FROM tidscan t1 JOIN tidscan t2 ON t1.ctid = t2.ctid WHERE t1.id = 1; @@ -139,7 +140,8 @@ FROM tidscan t1 LEFT JOIN tidscan t2 ON t1.ctid = t2.ctid WHERE t1.id = 1; Filter: (id = 1) -> Tid Scan on tidscan t2 TID Cond: (t1.ctid = ctid) -(5 rows) + Settings: enable_hashjoin = 'off' +(6 rows) SELECT t1.ctid, t1.*, t2.ctid, t2.* FROM tidscan t1 LEFT JOIN tidscan t2 ON t1.ctid = t2.ctid WHERE t1.id = 1; @@ -189,14 +191,16 @@ FETCH NEXT FROM c; (1 row) -- perform update -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (EXEC, COSTS OFF, SUMMARY OFF, TIMING OFF) UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; QUERY PLAN --------------------------------------------------- Update on tidscan (actual rows=1 loops=1) + Buffers: shared hit=3 -> Tid Scan on tidscan (actual rows=1 loops=1) TID Cond: CURRENT OF c -(3 rows) + Buffers: shared hit=2 +(5 rows) FETCH NEXT FROM c; ctid | id @@ -205,14 +209,16 @@ FETCH NEXT FROM c; (1 row) -- perform update -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (EXEC, COSTS OFF, SUMMARY OFF, TIMING OFF) UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; QUERY PLAN --------------------------------------------------- Update on tidscan (actual rows=1 loops=1) + Buffers: shared hit=3 -> Tid Scan on tidscan (actual rows=1 loops=1) TID Cond: CURRENT OF c -(3 rows) + Buffers: shared hit=2 +(5 rows) SELECT * FROM tidscan; id @@ -229,7 +235,7 @@ FETCH NEXT FROM c; (0 rows) -- should error out -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (EXEC, COSTS OFF, SUMMARY OFF, TIMING OFF) UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; ERROR: cursor "c" is not positioned on a row ROLLBACK; @@ -268,7 +274,8 @@ SELECT count(*) FROM tenk1 t1 JOIN tenk1 t2 ON t1.ctid = t2.ctid; -> Sort Sort Key: t2.ctid -> Seq Scan on tenk1 t2 -(9 rows) + Settings: enable_hashjoin = 'off' +(10 rows) SELECT count(*) FROM tenk1 t1 JOIN tenk1 t2 ON t1.ctid = t2.ctid; count diff --git a/src/test/regress/expected/tsearch.out b/src/test/regress/expected/tsearch.out index 6f61acc1ed..b61af4bed4 100644 --- a/src/test/regress/expected/tsearch.out +++ b/src/test/regress/expected/tsearch.out @@ -121,12 +121,13 @@ SET enable_seqscan=OFF; SET enable_indexscan=ON; SET enable_bitmapscan=OFF; explain (costs off) SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Aggregate -> Index Scan using wowidx on test_tsvector Index Cond: (a @@ '''wr'' | ''qh'''::tsquery) -(3 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(4 rows) SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh'; count @@ -198,7 +199,8 @@ explain (costs off) SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh'; Recheck Cond: (a @@ '''wr'' | ''qh'''::tsquery) -> Bitmap Index Scan on wowidx Index Cond: (a @@ '''wr'' | ''qh'''::tsquery) -(5 rows) + Settings: enable_indexscan = 'off', enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh'; count @@ -275,7 +277,8 @@ explain (costs off) SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh'; Recheck Cond: (a @@ '''wr'' | ''qh'''::tsquery) -> Bitmap Index Scan on wowidx Index Cond: (a @@ '''wr'' | ''qh'''::tsquery) -(5 rows) + Settings: enable_seqscan = 'off' +(6 rows) SELECT count(*) FROM test_tsvector WHERE a @@ 'wr|qh'; count diff --git a/src/test/regress/expected/union.out b/src/test/regress/expected/union.out index 7189f5bd3d..828563ad87 100644 --- a/src/test/regress/expected/union.out +++ b/src/test/regress/expected/union.out @@ -404,7 +404,8 @@ select count(*) from -> Seq Scan on tenk1 -> Subquery Scan on "*SELECT* 1" -> Index Only Scan using tenk1_unique1 on tenk1 tenk1_1 -(10 rows) + Settings: enable_hashagg = 'off' +(11 rows) select count(*) from ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss; @@ -426,7 +427,8 @@ select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; -> Subquery Scan on "*SELECT* 2" -> Index Only Scan using tenk1_unique2 on tenk1 tenk1_1 Filter: (unique2 <> 10) -(9 rows) + Settings: enable_hashagg = 'off' +(10 rows) select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; unique1 @@ -578,7 +580,8 @@ select from generate_series(1,5) union select from generate_series(1,3); -> Append -> Function Scan on generate_series -> Function Scan on generate_series generate_series_1 -(4 rows) + Settings: enable_sort = 'off' +(5 rows) explain (costs off) select from generate_series(1,5) intersect select from generate_series(1,3); @@ -590,7 +593,8 @@ select from generate_series(1,5) intersect select from generate_series(1,3); -> Function Scan on generate_series -> Subquery Scan on "*SELECT* 2" -> Function Scan on generate_series generate_series_1 -(6 rows) + Settings: enable_sort = 'off' +(7 rows) select from generate_series(1,5) union select from generate_series(1,3); -- @@ -627,7 +631,8 @@ select from generate_series(1,5) union select from generate_series(1,3); -> Append -> Function Scan on generate_series -> Function Scan on generate_series generate_series_1 -(4 rows) + Settings: enable_hashagg = 'off' +(5 rows) explain (costs off) select from generate_series(1,5) intersect select from generate_series(1,3); @@ -639,7 +644,8 @@ select from generate_series(1,5) intersect select from generate_series(1,3); -> Function Scan on generate_series -> Subquery Scan on "*SELECT* 2" -> Function Scan on generate_series generate_series_1 -(6 rows) + Settings: enable_hashagg = 'off' +(7 rows) select from generate_series(1,5) union select from generate_series(1,3); -- @@ -707,14 +713,15 @@ explain (costs off) UNION ALL SELECT * FROM t2) t WHERE ab = 'ab'; - QUERY PLAN ---------------------------------------------- + QUERY PLAN +------------------------------------------------------------- Append -> Index Scan using t1_ab_idx on t1 Index Cond: ((a || b) = 'ab'::text) -> Index Only Scan using t2_pkey on t2 Index Cond: (ab = 'ab'::text) -(5 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(6 rows) explain (costs off) SELECT * FROM @@ -722,8 +729,8 @@ explain (costs off) UNION SELECT * FROM t2) t WHERE ab = 'ab'; - QUERY PLAN ---------------------------------------------------- + QUERY PLAN +------------------------------------------------------------- HashAggregate Group Key: ((t1.a || t1.b)) -> Append @@ -731,7 +738,8 @@ explain (costs off) Index Cond: ((a || b) = 'ab'::text) -> Index Only Scan using t2_pkey on t2 Index Cond: (ab = 'ab'::text) -(7 rows) + Settings: enable_bitmapscan = 'off', enable_seqscan = 'off' +(8 rows) -- -- Test that ORDER BY for UNION ALL can be pushed down to inheritance @@ -751,8 +759,8 @@ explain (costs off) UNION ALL SELECT ab FROM t2) t ORDER BY 1 LIMIT 8; - QUERY PLAN ------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------- Limit -> Merge Append Sort Key: ((t1.a || t1.b)) @@ -760,7 +768,8 @@ explain (costs off) -> Index Scan using t1c_ab_idx on t1c -> Index Scan using t2_pkey on t2 -> Index Scan using t2c_pkey on t2c -(7 rows) + Settings: enable_bitmapscan = 'off', enable_indexonlyscan = 'off' +(8 rows) SELECT * FROM (SELECT a || b AS ab FROM t1 @@ -801,7 +810,8 @@ select event_id Sort Key: events_child.event_id -> Seq Scan on events_child -> Index Scan using other_events_pkey on other_events -(7 rows) + Settings: enable_indexonlyscan = 'off' +(8 rows) drop table events_child, events, other_events; reset enable_indexonlyscan; diff --git a/src/test/regress/expected/write_parallel.out b/src/test/regress/expected/write_parallel.out index 0c4da2591a..51e8380cdf 100644 --- a/src/test/regress/expected/write_parallel.out +++ b/src/test/regress/expected/write_parallel.out @@ -15,8 +15,8 @@ set max_parallel_workers_per_gather=4; -- explain (costs off) create table parallel_write as select length(stringu1) from tenk1 group by length(stringu1); - QUERY PLAN ---------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Finalize HashAggregate Group Key: (length((stringu1)::text)) -> Gather @@ -24,15 +24,16 @@ explain (costs off) create table parallel_write as -> Partial HashAggregate Group Key: length((stringu1)::text) -> Parallel Seq Scan on tenk1 -(7 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(8 rows) create table parallel_write as select length(stringu1) from tenk1 group by length(stringu1); drop table parallel_write; explain (costs off) select length(stringu1) into parallel_write from tenk1 group by length(stringu1); - QUERY PLAN ---------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Finalize HashAggregate Group Key: (length((stringu1)::text)) -> Gather @@ -40,15 +41,16 @@ explain (costs off) select length(stringu1) into parallel_write -> Partial HashAggregate Group Key: length((stringu1)::text) -> Parallel Seq Scan on tenk1 -(7 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(8 rows) select length(stringu1) into parallel_write from tenk1 group by length(stringu1); drop table parallel_write; explain (costs off) create materialized view parallel_mat_view as select length(stringu1) from tenk1 group by length(stringu1); - QUERY PLAN ---------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Finalize HashAggregate Group Key: (length((stringu1)::text)) -> Gather @@ -56,15 +58,16 @@ explain (costs off) create materialized view parallel_mat_view as -> Partial HashAggregate Group Key: length((stringu1)::text) -> Parallel Seq Scan on tenk1 -(7 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(8 rows) create materialized view parallel_mat_view as select length(stringu1) from tenk1 group by length(stringu1); drop materialized view parallel_mat_view; prepare prep_stmt as select length(stringu1) from tenk1 group by length(stringu1); explain (costs off) create table parallel_write as execute prep_stmt; - QUERY PLAN ---------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Finalize HashAggregate Group Key: (length((stringu1)::text)) -> Gather @@ -72,7 +75,8 @@ explain (costs off) create table parallel_write as execute prep_stmt; -> Partial HashAggregate Group Key: length((stringu1)::text) -> Parallel Seq Scan on tenk1 -(7 rows) + Settings: max_parallel_workers_per_gather = '4', min_parallel_table_scan_size = '0', parallel_setup_cost = '0', parallel_tuple_cost = '0' +(8 rows) create table parallel_write as execute prep_stmt; drop table parallel_write; diff --git a/src/test/regress/sql/join_hash.sql b/src/test/regress/sql/join_hash.sql index ae352e9b0b..b44d705d57 100644 --- a/src/test/regress/sql/join_hash.sql +++ b/src/test/regress/sql/join_hash.sql @@ -7,7 +7,7 @@ begin; set local min_parallel_table_scan_size = 0; set local parallel_setup_cost = 0; --- Extract bucket and batch counts from an explain analyze plan. In +-- Extract bucket and batch counts from an explain exec plan. In -- general we can't make assertions about how many batches (or -- buckets) will be required because it can vary, but we can in some -- special cases and we can check for growth. @@ -42,7 +42,7 @@ declare hash_node json; begin for whole_plan in - execute 'explain (analyze, format ''json'') ' || query + execute 'explain (exec, format ''json'') ' || query loop hash_node := find_hash(json_extract_path(whole_plan, '0', 'Plan')); original := hash_node->>'Original Hash Batches'; @@ -280,7 +280,7 @@ rollback to settings; -- A couple of other hash join tests unrelated to work_mem management. --- Check that EXPLAIN ANALYZE has data even if the leader doesn't participate +-- Check that EXPLAIN EXEC has data even if the leader doesn't participate savepoint settings; set local max_parallel_workers_per_gather = 2; set local work_mem = '4MB'; diff --git a/src/test/regress/sql/partition_prune.sql b/src/test/regress/sql/partition_prune.sql index 246c6274af..684aa3c464 100644 --- a/src/test/regress/sql/partition_prune.sql +++ b/src/test/regress/sql/partition_prune.sql @@ -327,7 +327,7 @@ create table ab_a3_b2 partition of ab_a3 for values in (2); create table ab_a3_b3 partition of ab_a3 for values in (3); -- Disallow index only scans as concurrent transactions may stop visibility --- bits being set causing "Heap Fetches" to be unstable in the EXPLAIN ANALYZE +-- bits being set causing "Heap Fetches" to be unstable in the EXPLAIN EXEC -- output. set enable_indexonlyscan = off; @@ -342,8 +342,8 @@ execute ab_q1 (1, 8, 3); execute ab_q1 (1, 8, 3); execute ab_q1 (1, 8, 3); -explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 2, 3); -explain (analyze, costs off, summary off, timing off) execute ab_q1 (1, 2, 3); +explain (exec, costs off, summary off, timing off) execute ab_q1 (2, 2, 3); +explain (exec, costs off, summary off, timing off) execute ab_q1 (1, 2, 3); deallocate ab_q1; @@ -359,8 +359,8 @@ execute ab_q1 (1, 8); execute ab_q1 (1, 8); execute ab_q1 (1, 8); -explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 2); -explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 4); +explain (exec, costs off, summary off, timing off) execute ab_q1 (2, 2); +explain (exec, costs off, summary off, timing off) execute ab_q1 (2, 4); -- Ensure a mix of PARAM_EXTERN and PARAM_EXEC Params work together at -- different levels of partitioning. @@ -373,7 +373,7 @@ execute ab_q2 (1, 8); execute ab_q2 (1, 8); execute ab_q2 (1, 8); -explain (analyze, costs off, summary off, timing off) execute ab_q2 (2, 2); +explain (exec, costs off, summary off, timing off) execute ab_q2 (2, 2); -- As above, but swap the PARAM_EXEC Param to the first partition level prepare ab_q3 (int, int) as @@ -385,7 +385,7 @@ execute ab_q3 (1, 8); execute ab_q3 (1, 8); execute ab_q3 (1, 8); -explain (analyze, costs off, summary off, timing off) execute ab_q3 (2, 2); +explain (exec, costs off, summary off, timing off) execute ab_q3 (2, 2); -- Test a backwards Append scan create table list_part (a int) partition by list (a); @@ -416,13 +416,13 @@ begin; create function list_part_fn(int) returns int as $$ begin return $1; end;$$ language plpgsql stable; -- Ensure pruning works using a stable function containing no Vars -explain (analyze, costs off, summary off, timing off) select * from list_part where a = list_part_fn(1); +explain (exec, costs off, summary off, timing off) select * from list_part where a = list_part_fn(1); -- Ensure pruning does not take place when the function has a Var parameter -explain (analyze, costs off, summary off, timing off) select * from list_part where a = list_part_fn(a); +explain (exec, costs off, summary off, timing off) select * from list_part where a = list_part_fn(a); -- Ensure pruning does not take place when the expression contains a Var. -explain (analyze, costs off, summary off, timing off) select * from list_part where a = list_part_fn(1) + a; +explain (exec, costs off, summary off, timing off) select * from list_part where a = list_part_fn(1) + a; rollback; @@ -440,7 +440,7 @@ declare ln text; begin for ln in - execute format('explain (analyze, costs off, summary off, timing off) %s', + execute format('explain (exec, costs off, summary off, timing off) %s', $1) loop if ln like '%Parallel%' then @@ -537,15 +537,15 @@ reset min_parallel_table_scan_size; reset max_parallel_workers_per_gather; -- Test run-time partition pruning with an initplan -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from ab where a = (select max(a) from lprt_a) and b = (select max(a)-1 from lprt_a); -- Test run-time partition pruning with UNION ALL parents -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from (select * from ab where a = 1 union all select * from ab) ab where b = (select 1); -- A case containing a UNION ALL with a non-partitioned child. -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from (select * from ab where a = 1 union all (values(10,5)) union all select * from ab) ab where b = (select 1); -- Another UNION ALL test, but containing a mix of exec init and exec run-time pruning. @@ -566,7 +566,7 @@ union all ) ab where a = $1 and b = (select -10); -- Ensure the xy_1 subplan is not pruned. -explain (analyze, costs off, summary off, timing off) execute ab_q6(1); +explain (exec, costs off, summary off, timing off) execute ab_q6(1); -- Ensure we see just the xy_1 row. execute ab_q6(100); @@ -584,14 +584,14 @@ deallocate ab_q6; -- UPDATE on a partition subtree has been seen to have problems. insert into ab values (1,2); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) update ab_a1 set b = 3 from ab where ab.a = 1 and ab.a = ab_a1.a; table ab; -- Test UPDATE where source relation has run-time pruning enabled truncate ab; insert into ab values (1, 1), (1, 2), (1, 3), (2, 1); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) update ab_a1 set b = 3 from ab_a2 where ab_a2.b = (select 1); select tableoid::regclass, * from ab; @@ -622,10 +622,10 @@ insert into tprt values (10), (20), (501), (502), (505), (1001), (4500); set enable_hashjoin = off; set enable_mergejoin = off; -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from tbl1 join tprt on tbl1.col1 > tprt.col1; -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from tbl1 join tprt on tbl1.col1 = tprt.col1; select tbl1.col1, tprt.col1 from tbl1 @@ -638,10 +638,10 @@ order by tbl1.col1, tprt.col1; -- Multiple partitions insert into tbl1 values (1001), (1010), (1011); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from tbl1 inner join tprt on tbl1.col1 > tprt.col1; -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from tbl1 inner join tprt on tbl1.col1 = tprt.col1; select tbl1.col1, tprt.col1 from tbl1 @@ -655,7 +655,7 @@ order by tbl1.col1, tprt.col1; -- Last partition delete from tbl1; insert into tbl1 values (4400); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from tbl1 join tprt on tbl1.col1 < tprt.col1; select tbl1.col1, tprt.col1 from tbl1 @@ -665,7 +665,7 @@ order by tbl1.col1, tprt.col1; -- No matching partition delete from tbl1; insert into tbl1 values (10000); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from tbl1 join tprt on tbl1.col1 = tprt.col1; select tbl1.col1, tprt.col1 from tbl1 @@ -696,7 +696,7 @@ execute part_abc_q1 (1, 2, 3); execute part_abc_q1 (1, 2, 3); -- Single partition should be scanned. -explain (analyze, costs off, summary off, timing off) execute part_abc_q1 (1, 2, 3); +explain (exec, costs off, summary off, timing off) execute part_abc_q1 (1, 2, 3); deallocate part_abc_q1; @@ -722,13 +722,13 @@ execute q1 (1,2); execute q1 (1,2); execute q1 (1,2); -explain (analyze, costs off, summary off, timing off) execute q1 (1,1); +explain (exec, costs off, summary off, timing off) execute q1 (1,1); -explain (analyze, costs off, summary off, timing off) execute q1 (2,2); +explain (exec, costs off, summary off, timing off) execute q1 (2,2); -- Try with no matching partitions. One subplan should remain in this case, -- but it shouldn't be executed. -explain (analyze, costs off, summary off, timing off) execute q1 (0,0); +explain (exec, costs off, summary off, timing off) execute q1 (0,0); deallocate q1; @@ -742,14 +742,14 @@ execute q1 (1,2,3,4); execute q1 (1,2,3,4); -- Both partitions allowed by IN clause, but one disallowed by <> clause -explain (analyze, costs off, summary off, timing off) execute q1 (1,2,2,0); +explain (exec, costs off, summary off, timing off) execute q1 (1,2,2,0); -- Both partitions allowed by IN clause, then both excluded again by <> clauses. -- One subplan will remain in this case, but it should not be executed. -explain (analyze, costs off, summary off, timing off) execute q1 (1,2,2,1); +explain (exec, costs off, summary off, timing off) execute q1 (1,2,2,1); -- Ensure Params that evaluate to NULL properly prune away all partitions -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from listp where a = (select null::int); drop table listp; @@ -762,10 +762,10 @@ create table boolp (a bool) partition by list (a); create table boolp_t partition of boolp for values in('t'); create table boolp_f partition of boolp for values in('f'); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from boolp where a = (select value from boolvalues where value); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from boolp where a = (select value from boolvalues where not value); drop table boolp; @@ -793,18 +793,18 @@ execute mt_q1(0); execute mt_q1(0); execute mt_q1(0); -explain (analyze, costs off, summary off, timing off) execute mt_q1(15); +explain (exec, costs off, summary off, timing off) execute mt_q1(15); execute mt_q1(15); -explain (analyze, costs off, summary off, timing off) execute mt_q1(25); +explain (exec, costs off, summary off, timing off) execute mt_q1(25); execute mt_q1(25); -- Ensure MergeAppend behaves correctly when no subplans match -explain (analyze, costs off, summary off, timing off) execute mt_q1(35); +explain (exec, costs off, summary off, timing off) execute mt_q1(35); execute mt_q1(35); deallocate mt_q1; -- ensure initplan params properly prune partitions -explain (analyze, costs off, summary off, timing off) select * from ma_test where a >= (select min(b) from ma_test_p2) order by b; +explain (exec, costs off, summary off, timing off) select * from ma_test where a >= (select min(b) from ma_test_p2) order by b; reset enable_seqscan; reset enable_sort; @@ -987,7 +987,7 @@ create table listp1 partition of listp for values in(1); create table listp2 partition of listp for values in(2) partition by list(b); create table listp2_10 partition of listp2 for values in (10); -explain (analyze, costs off, summary off, timing off) +explain (exec, costs off, summary off, timing off) select * from listp where a = (select 2) and b <> 10; -- diff --git a/src/test/regress/sql/select.sql b/src/test/regress/sql/select.sql index b5929b2eca..f573dfa921 100644 --- a/src/test/regress/sql/select.sql +++ b/src/test/regress/sql/select.sql @@ -196,7 +196,7 @@ explain (costs off) select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; -- actually run the query with an analyze to use the partial index -explain (costs off, analyze on, timing off, summary off) +explain (costs off, exec on, timing off, summary off) select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; explain (costs off) select unique2 from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; diff --git a/src/test/regress/sql/select_into.sql b/src/test/regress/sql/select_into.sql index a708fef0ea..bd2f918294 100644 --- a/src/test/regress/sql/select_into.sql +++ b/src/test/regress/sql/select_into.sql @@ -85,12 +85,12 @@ SELECT make_table(); SELECT * FROM created_table; --- Try EXPLAIN ANALYZE SELECT INTO and EXPLAIN ANALYZE CREATE TABLE AS +-- Try EXPLAIN EXEC SELECT INTO and EXPLAIN EXEC CREATE TABLE AS -- WITH NO DATA, but hide the outputs since they won't be stable. DO $$ BEGIN - EXECUTE 'EXPLAIN ANALYZE SELECT * INTO TABLE easi FROM int8_tbl'; - EXECUTE 'EXPLAIN ANALYZE CREATE TABLE easi2 AS SELECT * FROM int8_tbl WITH NO DATA'; + EXECUTE 'EXPLAIN EXEC SELECT * INTO TABLE easi FROM int8_tbl'; + EXECUTE 'EXPLAIN EXEC CREATE TABLE easi2 AS SELECT * FROM int8_tbl WITH NO DATA'; END$$; DROP TABLE created_table; diff --git a/src/test/regress/sql/select_parallel.sql b/src/test/regress/sql/select_parallel.sql index 03c056b8b7..de8ef80ecf 100644 --- a/src/test/regress/sql/select_parallel.sql +++ b/src/test/regress/sql/select_parallel.sql @@ -197,7 +197,7 @@ select count(*) from bmscantest where a>1; -- test accumulation of stats for parallel nodes reset enable_seqscan; alter table tenk2 set (parallel_workers = 0); -explain (analyze, timing off, summary off, costs off) +explain (exec, timing off, summary off, costs off) select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0; alter table tenk2 reset (parallel_workers); @@ -209,7 +209,7 @@ $$ declare ln text; begin for ln in - explain (analyze, timing off, summary off, costs off) + explain (exec, timing off, summary off, costs off) select * from (select ten from tenk1 where ten < 100 order by ten) ss right join (values (1),(2),(3)) v(x) on true @@ -376,7 +376,7 @@ explain (costs off) -- to increase the parallel query test coverage SAVEPOINT settings; SET LOCAL force_parallel_mode = 1; -EXPLAIN (analyze, timing off, summary off, costs off) SELECT * FROM tenk1; +EXPLAIN (exec, timing off, summary off, costs off) SELECT * FROM tenk1; ROLLBACK TO SAVEPOINT settings; -- provoke error in worker diff --git a/src/test/regress/sql/stats_ext.sql b/src/test/regress/sql/stats_ext.sql index c6a5776120..6492cd7c37 100644 --- a/src/test/regress/sql/stats_ext.sql +++ b/src/test/regress/sql/stats_ext.sql @@ -14,7 +14,7 @@ declare first_row bool := true; begin for ln in - execute format('explain analyze %s', $1) + execute format('explain exec %s', $1) loop if first_row then first_row := false; diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql index 99ca69791e..b1d89228d2 100644 --- a/src/test/regress/sql/subselect.sql +++ b/src/test/regress/sql/subselect.sql @@ -598,8 +598,8 @@ drop function tattle(x int, y int); -- -- Test that LIMIT can be pushed to SORT through a subquery that just projects -- columns. We check for that having happened by looking to see if EXPLAIN --- ANALYZE shows that a top-N sort was used. We must suppress or filter away --- all the non-invariant parts of the EXPLAIN ANALYZE output. +-- EXEC shows that a top-N sort was used. We must suppress or filter away +-- all the non-invariant parts of the EXPLAIN EXEC output. -- create table sq_limit (pk int primary key, c1 int, c2 int); insert into sq_limit values @@ -617,7 +617,7 @@ $$ declare ln text; begin for ln in - explain (analyze, summary off, timing off, costs off) + explain (exec, summary off, timing off, costs off) select * from (select pk,c2 from sq_limit order by c1,pk) as x limit 3 loop ln := regexp_replace(ln, 'Memory: \S*', 'Memory: xxx'); diff --git a/src/test/regress/sql/tidscan.sql b/src/test/regress/sql/tidscan.sql index ef05c09842..65e222681e 100644 --- a/src/test/regress/sql/tidscan.sql +++ b/src/test/regress/sql/tidscan.sql @@ -68,17 +68,17 @@ DECLARE c CURSOR FOR SELECT ctid, * FROM tidscan; FETCH NEXT FROM c; -- skip one row FETCH NEXT FROM c; -- perform update -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (EXEC, COSTS OFF, SUMMARY OFF, TIMING OFF) UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; FETCH NEXT FROM c; -- perform update -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (EXEC, COSTS OFF, SUMMARY OFF, TIMING OFF) UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; SELECT * FROM tidscan; -- position cursor past any rows FETCH NEXT FROM c; -- should error out -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (EXEC, COSTS OFF, SUMMARY OFF, TIMING OFF) UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; ROLLBACK; --------------2.21.0-- --Ayym4vmyMU9P4uDb Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v4-0007-Propagate-changes-to-auto_explain.patch" From 36c2806daa4fe325dc552e41b30d26ece609fe9f Mon Sep 17 00:00:00 2001 From: David Fetter Date: Tue, 14 May 2019 22:55:18 -0700 Subject: [PATCH v4 7/8] Propagate changes to auto_explain To: hackers MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------2.21.0" This is a multi-part message in MIME format. --------------2.21.0 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit diff --git a/contrib/auto_explain/auto_explain.c b/contrib/auto_explain/auto_explain.c index edc50f9368..1aeda40ea1 100644 --- a/contrib/auto_explain/auto_explain.c +++ b/contrib/auto_explain/auto_explain.c @@ -23,7 +23,7 @@ PG_MODULE_MAGIC; /* GUC variables */ static int auto_explain_log_min_duration = -1; /* msec or -1 */ -static bool auto_explain_log_analyze = false; +static bool auto_explain_log_exec = false; static bool auto_explain_log_verbose = false; static bool auto_explain_log_buffers = false; static bool auto_explain_log_triggers = false; @@ -102,10 +102,10 @@ _PG_init(void) NULL, NULL); - DefineCustomBoolVariable("auto_explain.log_analyze", - "Use EXPLAIN ANALYZE for plan logging.", + DefineCustomBoolVariable("auto_explain.log_exec", + "Use EXPLAIN EXEC for plan logging.", NULL, - &auto_explain_log_analyze, + &auto_explain_log_exec, false, PGC_SUSET, 0, @@ -148,7 +148,7 @@ _PG_init(void) DefineCustomBoolVariable("auto_explain.log_triggers", "Include trigger statistics in plans.", - "This has no effect unless log_analyze is also set.", + "This has no effect unless log_exec is also set.", &auto_explain_log_triggers, false, PGC_SUSET, @@ -258,8 +258,8 @@ explain_ExecutorStart(QueryDesc *queryDesc, int eflags) if (auto_explain_enabled() && current_query_sampled) { - /* Enable per-node instrumentation iff log_analyze is required. */ - if (auto_explain_log_analyze && (eflags & EXEC_FLAG_EXPLAIN_ONLY) == 0) + /* Enable per-node instrumentation iff log_exec is required. */ + if (auto_explain_log_exec && (eflags & EXEC_FLAG_EXPLAIN_ONLY) == 0) { if (auto_explain_log_timing) queryDesc->instrument_options |= INSTRUMENT_TIMER; @@ -362,18 +362,18 @@ explain_ExecutorEnd(QueryDesc *queryDesc) { ExplainState *es = NewExplainState(); - es->analyze = (queryDesc->instrument_options && auto_explain_log_analyze); + es->exec = (queryDesc->instrument_options && auto_explain_log_exec); es->verbose = auto_explain_log_verbose; - es->buffers = (es->analyze && auto_explain_log_buffers); - es->timing = (es->analyze && auto_explain_log_timing); - es->summary = es->analyze; + es->buffers = (es->exec && auto_explain_log_buffers); + es->timing = (es->exec && auto_explain_log_timing); + es->summary = es->exec; es->format = auto_explain_log_format; es->settings = auto_explain_log_settings; ExplainBeginOutput(es); ExplainQueryText(es, queryDesc); ExplainPrintPlan(es, queryDesc); - if (es->analyze && auto_explain_log_triggers) + if (es->exec && auto_explain_log_triggers) ExplainPrintTriggers(es, queryDesc); if (es->costs) ExplainPrintJITSummary(es, queryDesc); --------------2.21.0-- --Ayym4vmyMU9P4uDb Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v4-0008-Mechanical-changes-in-file_fdw-and-postgres_fdw.patch" From 17b46b340cd8eb7a0c5df80f2ffc6450701d1c29 Mon Sep 17 00:00:00 2001 From: David Fetter Date: Tue, 14 May 2019 22:56:29 -0700 Subject: [PATCH v4 8/8] Mechanical changes in file_fdw and postgres_fdw To: hackers MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------2.21.0" This is a multi-part message in MIME format. --------------2.21.0 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c index 85534a3a76..58e88c9957 100644 --- a/contrib/file_fdw/file_fdw.c +++ b/contrib/file_fdw/file_fdw.c @@ -661,7 +661,7 @@ fileBeginForeignScan(ForeignScanState *node, int eflags) FileFdwExecutionState *festate; /* - * Do nothing in EXPLAIN (no ANALYZE) case. node->fdw_state stays NULL. + * Do nothing in EXPLAIN (no EXEC) case. node->fdw_state stays NULL. */ if (eflags & EXEC_FLAG_EXPLAIN_ONLY) return; diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index 2b6d885efe..7e739f56a9 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -1413,7 +1413,7 @@ postgresBeginForeignScan(ForeignScanState *node, int eflags) int numParams; /* - * Do nothing in EXPLAIN (no ANALYZE) case. node->fdw_state stays NULL. + * Do nothing in EXPLAIN (no EXEC) case. node->fdw_state stays NULL. */ if (eflags & EXEC_FLAG_EXPLAIN_ONLY) return; @@ -1804,7 +1804,7 @@ postgresBeginForeignModify(ModifyTableState *mtstate, RangeTblEntry *rte; /* - * Do nothing in EXPLAIN (no ANALYZE) case. resultRelInfo->ri_FdwState + * Do nothing in EXPLAIN (no EXEC) case. resultRelInfo->ri_FdwState * stays NULL. */ if (eflags & EXEC_FLAG_EXPLAIN_ONLY) @@ -2345,7 +2345,7 @@ postgresBeginDirectModify(ForeignScanState *node, int eflags) int numParams; /* - * Do nothing in EXPLAIN (no ANALYZE) case. node->fdw_state stays NULL. + * Do nothing in EXPLAIN (no EXEC) case. node->fdw_state stays NULL. */ if (eflags & EXEC_FLAG_EXPLAIN_ONLY) return; @@ -2477,7 +2477,7 @@ postgresIterateDirectModify(ForeignScanState *node) if (dmstate->set_processed) estate->es_processed += dmstate->num_tuples; - /* Increment the tuple count for EXPLAIN ANALYZE if necessary. */ + /* Increment the tuple count for EXPLAIN EXEC if necessary. */ if (instr) instr->tuplecount += dmstate->num_tuples; --------------2.21.0-- --Ayym4vmyMU9P4uDb--