From 529627b208c0a3b490b53d7676755e0c185a7451 Mon Sep 17 00:00:00 2001 From: mtimm_01 Date: Wed, 14 Jan 2015 15:48:29 +0100 Subject: [PATCH] Clean Patch v.7.1 --- src/backend/commands/explain.c | 110 ++++++++++++++++++++---- src/test/regress/expected/aggregates.out | 2 +- src/test/regress/expected/equivclass.out | 4 +- src/test/regress/expected/explain_sortorder.out | 16 ++++ src/test/regress/parallel_schedule | 9 +- src/test/regress/serial_schedule | 3 +- src/test/regress/sql/explain_sortorder.sql | 12 +++ 7 files changed, 133 insertions(+), 23 deletions(-) create mode 100644 src/test/regress/expected/explain_sortorder.out create mode 100644 src/test/regress/sql/explain_sortorder.sql diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 8a0be5d..833084c 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -3,7 +3,7 @@ * explain.c * Explain query execution plans * - * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * * IDENTIFICATION @@ -14,6 +14,9 @@ #include "postgres.h" #include "access/xact.h" +#include "access/htup_details.h" +#include "catalog/pg_collation.h" +#include "catalog/pg_operator.h" #include "catalog/pg_type.h" #include "commands/createas.h" #include "commands/defrem.h" @@ -30,8 +33,11 @@ #include "utils/rel.h" #include "utils/ruleutils.h" #include "utils/snapmgr.h" +#include "utils/syscache.h" #include "utils/tuplesort.h" +#include "utils/typcache.h" #include "utils/xml.h" +#include "nodes/nodeFuncs.h" /* Hook for plugins to get control in ExplainOneQuery() */ @@ -84,6 +90,7 @@ static void show_group_keys(GroupState *gstate, List *ancestors, static void show_sort_group_keys(PlanState *planstate, const char *qlabel, int nkeys, AttrNumber *keycols, List *ancestors, ExplainState *es); +static char *get_sortorder_by_keyno(SortState *sortstate, ExplainState *es, int keyno); static void show_sort_info(SortState *sortstate, ExplainState *es); static void show_hash_info(HashState *hashstate, ExplainState *es); static void show_tidbitmap_info(BitmapHeapScanState *planstate, @@ -116,7 +123,6 @@ static void ExplainYAMLLineStarting(ExplainState *es); static void escape_yaml(StringInfo buf, const char *str); - /* * ExplainQuery - * execute an EXPLAIN command @@ -1844,12 +1850,12 @@ show_sort_group_keys(PlanState *planstate, const char *qlabel, int nkeys, AttrNumber *keycols, List *ancestors, ExplainState *es) { - Plan *plan = planstate->plan; - List *context; - List *result = NIL; - bool useprefix; - int keyno; - char *exprstr; + Plan *plan = planstate->plan; + List *context; + List *result = NIL; + bool useprefix; + int keyno; + char *exprstr; if (nkeys <= 0) return; @@ -1863,23 +1869,95 @@ show_sort_group_keys(PlanState *planstate, const char *qlabel, for (keyno = 0; keyno < nkeys; keyno++) { - /* find key expression in tlist */ - AttrNumber keyresno = keycols[keyno]; - TargetEntry *target = get_tle_by_resno(plan->targetlist, - keyresno); - + /* find key ekeynoxpression in tlist */ + AttrNumber keyresno = keycols[keyno]; + TargetEntry *target = get_tle_by_resno(plan->targetlist, keyresno); + char *sortorder; + StringInfo element_concat_sortorder; + + if (nodeTag(plan) == T_Sort) { + sortorder = get_sortorder_by_keyno((SortState *) planstate, es, keyno); + } else { + sortorder = ""; + } if (!target) elog(ERROR, "no tlist entry for key %d", keyresno); /* Deparse the expression, showing any top-level cast */ - exprstr = deparse_expression((Node *) target->expr, context, - useprefix, true); - result = lappend(result, exprstr); + exprstr = deparse_expression((Node *) target->expr, context, useprefix, true); + element_concat_sortorder = makeStringInfo(); + appendStringInfoString(element_concat_sortorder, exprstr); + appendStringInfoString(element_concat_sortorder, sortorder); + result = lappend(result, element_concat_sortorder->data); } ExplainPropertyList(qlabel, result, es); } /* + * In verbose mode, additional information about the collation, sort order + * and NULLS FIRST/LAST is printed + */ +static char * +get_sortorder_by_keyno(SortState *sortstate, ExplainState *es, int keyno) +{ + Sort *plan; + Plan *planstatePlan; + Oid sortcoltype; + TypeCacheEntry *typentry; + HeapTuple opertup; + Form_pg_operator operform; + char *oprname; + StringInfo sortorderInformation; + Oid collId; + Oid operId; + AttrNumber keyresno; + TargetEntry *target; + + plan = (Sort *) sortstate->ss.ps.plan; + planstatePlan = (Plan *) sortstate->ss.ps.plan; + collId = plan->collations[keyno]; + operId = plan->sortOperators[keyno]; + keyresno = plan->sortColIdx[keyno]; + target = get_tle_by_resno(planstatePlan->targetlist, keyresno); + sortcoltype = exprType((const Node *) target->expr); + typentry = lookup_type_cache(sortcoltype, TYPECACHE_LT_OPR | TYPECACHE_GT_OPR); + sortorderInformation = makeStringInfo(); + + if (OidIsValid(collId) && collId != DEFAULT_COLLATION_OID) + { + char *collname; + char *localeptr; + + collname = get_collation_name(collId); + localeptr = setlocale(LC_COLLATE, NULL); + + appendStringInfo(sortorderInformation, " COLLATE '%s'", collname); + /* for those who use COLLATE although their default is already the wanted */ + if (strcmp(collname, localeptr) == 0) + { + appendStringInfo(sortorderInformation, " (%s is LC_COLLATE)", collname); + } + } + if (operId == typentry->gt_opr) + { + appendStringInfoString(sortorderInformation, " DESC"); + } + else if (operId != typentry->lt_opr) + { + opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operId)); + operform = (Form_pg_operator) GETSTRUCT (opertup); + oprname = NameStr(operform->oprname); + appendStringInfo(sortorderInformation, " USING %s", oprname); + ReleaseSysCache(opertup); + } + if (plan->nullsFirst[keyno]) + { + appendStringInfoString(sortorderInformation, " NULLS FIRST"); + } + return sortorderInformation->data; +} + +/* * If it's EXPLAIN ANALYZE, show tuplesort stats for a sort node */ static void diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index 40f5398..ca8aec8 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -735,7 +735,7 @@ explain (costs off) QUERY PLAN --------------------------------------------------------------------- Sort - Sort Key: (generate_series(1, 3)) + Sort Key: (generate_series(1, 3)) DESC NULLS FIRST InitPlan 1 (returns $0) -> Limit -> Index Only Scan Backward using tenk1_unique2 on tenk1 diff --git a/src/test/regress/expected/equivclass.out b/src/test/regress/expected/equivclass.out index b312292..dfae84e 100644 --- a/src/test/regress/expected/equivclass.out +++ b/src/test/regress/expected/equivclass.out @@ -319,7 +319,7 @@ explain (costs off) -> Index Scan using ec1_expr4 on ec1 ec1_3 -> Materialize -> Sort - Sort Key: ec1.f1 + Sort Key: ec1.f1 USING < -> Index Scan using ec1_pkey on ec1 Index Cond: (ff = 42::bigint) (20 rows) @@ -376,7 +376,7 @@ explain (costs off) -> Index Scan using ec1_expr4 on ec1 ec1_3 -> Materialize -> Sort - Sort Key: ec1.f1 + Sort Key: ec1.f1 USING < -> Index Scan using ec1_pkey on ec1 Index Cond: (ff = 42::bigint) (14 rows) diff --git a/src/test/regress/expected/explain_sortorder.out b/src/test/regress/expected/explain_sortorder.out new file mode 100644 index 0000000..abd8130 --- /dev/null +++ b/src/test/regress/expected/explain_sortorder.out @@ -0,0 +1,16 @@ +-- +-- Test explain feature: sort order +-- +CREATE TABLE sortordertest (n1 char(1), n2 int4); +-- Insert values by which should be ordered +INSERT INTO sortordertest(n1, n2) VALUES ('d', 5), ('b', 3), ('a', 1), ('e', 2), ('c', 4); +-- Display sort order when explain analyze and verbose are true. +EXPLAIN (COSTS OFF) SELECT * FROM sortordertest ORDER BY n1 COLLATE "C" DESC, n2; + QUERY PLAN +------------------------------------------------- + Sort + Sort Key: n1 COLLATE 'C' DESC NULLS FIRST, n2 + -> Seq Scan on sortordertest +(3 rows) + +DROP TABLE sortordertest; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index e0ae2f2..3cf63ff 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -59,7 +59,7 @@ test: create_index create_view # ---------- # Another group of parallel tests # ---------- -test: create_aggregate create_function_3 create_cast constraints triggers inherit create_table_like typed_table vacuum drop_if_exists updatable_views +test: create_aggregate create_function_3 create_cast constraints triggers inherit create_table_like typed_table vacuum drop_if_exists updatable_views explain_sortorder # ---------- # sanity_check does a vacuum, affecting the sort order of SELECT * @@ -78,12 +78,15 @@ ignore: random # ---------- # Another group of parallel tests # ---------- -test: select_into select_distinct select_distinct_on select_implicit select_having subselect union case join aggregates transactions random portals arrays btree_index hash_index update namespace prepared_xacts delete +test: select_into select_distinct select_distinct_on select_implicit select_having subselect union case join aggregates transactions random portals arrays btree_index hash_index update delete namespace prepared_xacts # ---------- # Another group of parallel tests # ---------- -test: brin gin gist spgist privileges security_label collate matview lock replica_identity rowsecurity object_address +test: brin gin gist spgist privileges security_label collate matview lock replica_identity object_address + +# rowsecurity creates an event trigger, so don't run it in parallel +test: rowsecurity # ---------- # Another group of parallel tests diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 7f762bd..dc242f1 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -71,6 +71,7 @@ test: typed_table test: vacuum test: drop_if_exists test: updatable_views +test: explain_sortorder test: sanity_check test: errors test: select @@ -105,8 +106,8 @@ test: collate test: matview test: lock test: replica_identity -test: rowsecurity test: object_address +test: rowsecurity test: alter_generic test: misc test: psql diff --git a/src/test/regress/sql/explain_sortorder.sql b/src/test/regress/sql/explain_sortorder.sql new file mode 100644 index 0000000..555d22f --- /dev/null +++ b/src/test/regress/sql/explain_sortorder.sql @@ -0,0 +1,12 @@ +-- +-- Test explain feature: sort order +-- +CREATE TABLE sortordertest (n1 char(1), n2 int4); + +-- Insert values by which should be ordered +INSERT INTO sortordertest(n1, n2) VALUES ('d', 5), ('b', 3), ('a', 1), ('e', 2), ('c', 4); + +-- Display sort order when explain analyze and verbose are true. +EXPLAIN (COSTS OFF) SELECT * FROM sortordertest ORDER BY n1 COLLATE "C" DESC, n2; + +DROP TABLE sortordertest; -- 1.9.1