From b93305ecebe04174839393938800bdeceba3f172 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Thu, 3 Jul 2025 15:00:55 -0400 Subject: [PATCH] remove old file --- contrib/pg_plan_advice/create_advice.c | 461 ------------------------- 1 file changed, 461 deletions(-) delete mode 100644 contrib/pg_plan_advice/create_advice.c diff --git a/contrib/pg_plan_advice/create_advice.c b/contrib/pg_plan_advice/create_advice.c deleted file mode 100644 index bb44d09856..0000000000 --- a/contrib/pg_plan_advice/create_advice.c +++ /dev/null @@ -1,461 +0,0 @@ -/*------------------------------------------------------------------------- - * - * create_advice.c - * generate advice from a finished plan that can be fed back into - * future planning cycles if desired - * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group - * - * contrib/pg_plan_advice/pg_plan_advice.c - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "commands/explain.h" -#include "parser/parsetree.h" -#include "pg_plan_advice.h" -#include "utils/builtins.h" -#include "utils/lsyscache.h" - -typedef enum -{ - JOIN_NONE, - JOIN_FOREIGN, - JOIN_MERGEJOIN_PLAIN, - JOIN_MERGEJOIN_MATERIALIZE, - JOIN_NESTLOOP_PLAIN, - JOIN_NESTLOOP_MATERIALIZE, - JOIN_NESTLOOP_MEMOIZE, - JOIN_HASHJOIN, - JOIN_PARTITIONWISE -} join_strategy; - -typedef struct -{ - PlannedStmt *stmt; - int rtable_length; - SubPlanRTInfo **rtable_subplans; - char **rtable_names; - Plan **rtable_scans; - bool *rtable_drivingjoin; - join_strategy *rtable_joinstrat; - List *all_join_orders; -} advice_context; - -typedef struct -{ - bool inner_side; - join_strategy jstrat; - Node *join_order; -} join_traversal; - -static void scan_plan_tree(advice_context *context, Plan *plan, - join_traversal *jtraversal); -static void scan_plan_tree_list(advice_context *context, List *list); - -static void -init_advice_context(advice_context *context, PlannedStmt *stmt) -{ - int rtable_length = list_length(stmt->rtable); - - context->stmt = stmt; - context->rtable_length = list_length(stmt->rtable); - context->rtable_subplans = palloc0_array(SubPlanRTInfo *, rtable_length); - context->rtable_names = palloc0_array(char *, rtable_length); - context->rtable_scans = palloc0_array(Plan *, rtable_length); - context->rtable_drivingjoin = palloc0_array(bool, rtable_length); - context->rtable_joinstrat = palloc0_array(join_strategy, rtable_length); - context->all_join_orders = NIL; -} - -static void -generate_relation_identifiers(advice_context *context) -{ - PlannedStmt *stmt = context->stmt; - Index rti; - Index *topparent; - - topparent = CreateParentRelationMap(stmt->rtable, stmt->appendRelations); - - /* Main loop over the entire flattened range table. */ - for (rti = 1; rti <= context->rtable_length; ++rti) - { - const char *result; - - result = MakeRelationIdentifier(stmt->rtable, - topparent, - stmt->subrtinfos, - rti); - - /* Save the name we just generated. */ - context->rtable_names[rti - 1] = unconstify(char *, result); - } -} - -static void -scan_plan_tree(advice_context *context, Plan *plan, join_traversal *jtraversal) -{ - Node *join_order = NULL; - Index rti; - - if (IsA(plan, NestLoop) || IsA(plan, HashJoin) || IsA(plan, MergeJoin)) - { - join_traversal outer_join_traversal; - join_traversal inner_join_traversal; - - /* - * The outermost table in a set of joins needs no join strategy advice; - * in the case of a bushy join, the outermost table of each clump - * needs join strategy advice to indicate how the clump as a whole - * should be joined. - */ - outer_join_traversal.inner_side = false; - outer_join_traversal.jstrat = JOIN_NONE; - outer_join_traversal.join_order = NULL; - if (jtraversal != NULL) - outer_join_traversal.jstrat = jtraversal->jstrat; - else - outer_join_traversal.jstrat = JOIN_NONE; - outer_join_traversal.join_order = NULL; - scan_plan_tree(context, plan->lefttree, &outer_join_traversal); - - /* - * Any table on the inner side of a join needs join strategy advice. - */ - inner_join_traversal.inner_side = true; - inner_join_traversal.join_order = NULL; - if (IsA(plan, MergeJoin)) - { - if (IsA(plan->righttree, Material)) - inner_join_traversal.jstrat = JOIN_MERGEJOIN_MATERIALIZE; - else - inner_join_traversal.jstrat = JOIN_MERGEJOIN_PLAIN; - } - else if (IsA(plan, NestLoop)) - { - if (IsA(plan->righttree, Material)) - inner_join_traversal.jstrat = JOIN_NESTLOOP_MATERIALIZE; - else if (IsA(plan->righttree, Memoize)) - inner_join_traversal.jstrat = JOIN_NESTLOOP_MEMOIZE; - else - inner_join_traversal.jstrat = JOIN_NESTLOOP_PLAIN; - } - else if (IsA(plan, HashJoin)) - inner_join_traversal.jstrat = JOIN_HASHJOIN; - else - elog(ERROR, "unknown node type: %d", nodeTag(plan)); - scan_plan_tree(context, plan->righttree, &inner_join_traversal); - - /* - * We assume that left-deep (or outer-deep) join trees are the norm; - * hence JOIN(JOIN(A,B),C) is represented as (A B C), whereas - * JOIN(A,JOIN(B,C)) is represnted as (A (B C)). - */ - if (IsA(outer_join_traversal.join_order, List)) - join_order = (Node *) - lappend((List *) outer_join_traversal.join_order, - inner_join_traversal.join_order); - else - join_order = (Node *) - list_make2(outer_join_traversal.join_order, - inner_join_traversal.join_order); - } - else if (jtraversal != NULL && !jtraversal->inner_side && - IsA(plan, Sort)) - { - Assert(plan->lefttree != NULL && plan->righttree == NULL); - scan_plan_tree(context, plan->lefttree, jtraversal); - } - else if (jtraversal != NULL && jtraversal->inner_side && - (IsA(plan, Material) || IsA(plan, Memoize) || IsA(plan, Hash) || - IsA(plan, Sort))) - { - Assert(plan->lefttree != NULL && plan->righttree == NULL); - scan_plan_tree(context, plan->lefttree, jtraversal); - } - else - { - if (plan->lefttree != NULL) - scan_plan_tree(context, plan->lefttree, NULL); - if (plan->righttree != NULL) - scan_plan_tree(context, plan->righttree, NULL); - - if (jtraversal != NULL) - join_order = (Node *) plan; - } - - if (join_order != NULL) - { - if (jtraversal == NULL) - context->all_join_orders = lappend(context->all_join_orders, - join_order); - else - { - Assert(jtraversal->join_order == NULL); - jtraversal->join_order = join_order; - } - } - - /* recurse into any special children */ - switch (nodeTag(plan)) - { - case T_Append: - scan_plan_tree_list(context, ((Append *) plan)->appendplans); - break; - case T_MergeAppend: - scan_plan_tree_list(context, ((MergeAppend *) plan)->mergeplans); - break; - case T_BitmapAnd: - scan_plan_tree_list(context, ((BitmapAnd *) plan)->bitmapplans); - break; - case T_BitmapOr: - scan_plan_tree_list(context, ((BitmapOr *) plan)->bitmapplans); - break; - case T_SubqueryScan: - scan_plan_tree(context, ((SubqueryScan *) plan)->subplan, NULL); - break; - case T_CustomScan: - scan_plan_tree_list(context, ((CustomScan *) plan)->custom_plans); - break; - default: - break; - } - - rti = GetScannedRTI(context->stmt, plan); - if (rti != 0) - { - if (context->rtable_scans[rti - 1] != NULL) - elog(ERROR, "rti %d is duplicated", rti); - context->rtable_scans[rti - 1] = plan; - if (jtraversal != NULL) - { - context->rtable_drivingjoin[rti - 1] = !jtraversal->inner_side; - context->rtable_joinstrat[rti - 1] = jtraversal->jstrat; - } - } -} - -static void -scan_plan_tree_list(advice_context *context, List *list) -{ - ListCell *lc; - - foreach(lc, list) - { - scan_plan_tree(context, lfirst(lc), NULL); - } -} - -static void -join_method_dump(StringInfo result, advice_context *context) -{ - Index rti; - - for (rti = 1; rti <= context->rtable_length; ++rti) - { - char *name = context->rtable_names[rti - 1]; - bool drivingjoin = context->rtable_drivingjoin[rti - 1]; - join_strategy jstrat = context->rtable_joinstrat[rti - 1]; - char *jstrat_name = NULL; - - switch (jstrat) - { - case JOIN_NONE: - break; - case JOIN_FOREIGN: - jstrat_name = drivingjoin ? "BUSHY_FOREIGN_JOIN" : "FOREIGN_JOIN"; - break; - case JOIN_MERGEJOIN_PLAIN: - jstrat_name = drivingjoin ? "BUSHY_MERGE_JOIN" : "MERGE_JOIN"; - break; - case JOIN_MERGEJOIN_MATERIALIZE: - jstrat_name = drivingjoin ? "BUSHY_MERGE_JOIN_MATERIALIZE" : "MERGE_JOIN_MATERIALIZE"; - break; - case JOIN_NESTLOOP_PLAIN: - jstrat_name = drivingjoin ? "BUSHY_NESTED_LOOP" : "NESTED_LOOP"; - break; - case JOIN_NESTLOOP_MATERIALIZE: - jstrat_name = drivingjoin ? "BUSHY_NESTED_LOOP_MATERIALIZE" : "NESTED_LOOP_MATERIALIZE"; - break; - case JOIN_NESTLOOP_MEMOIZE: - jstrat_name = drivingjoin ? "BUSHY_NESTED_LOOP_MEMOIZE" : "NESTED_LOOP_MEMOIZE"; - break; - case JOIN_HASHJOIN: - jstrat_name = drivingjoin ? "BUSHY_HASH_JOIN" : "HASH_JOIN"; - break; - case JOIN_PARTITIONWISE: - jstrat_name = drivingjoin ? "BUSHY_PARTITIONWISE" : "PARTITIONWISE"; - break; - } - - if (name == NULL) - name = "???"; - if (jstrat_name != NULL) - appendStringInfo(result, "%s(%s)\n", jstrat_name, name); - } -} - -static void -scan_method_dump(StringInfo result, advice_context *context) -{ - Index rti; - - for (rti = 1; rti <= context->rtable_length; ++rti) - { - char *name = context->rtable_names[rti - 1]; - Plan *plan = context->rtable_scans[rti - 1]; - char *scan_name = NULL; - Oid index_oid = InvalidOid; - - /* - * Convert the node tag of the scan to a string. We can ignore scan - * types for which there is no alternative, e.g. SubqueryScan, - * FunctionScan, ValuesScan. - */ - if (plan != NULL) - { - switch (nodeTag(plan)) - { - case T_SeqScan: - scan_name = "SEQ_SCAN"; - break; - case T_IndexScan: - scan_name = "INDEX_SCAN"; - index_oid = ((IndexScan *) plan)->indexid; - break; - case T_IndexOnlyScan: - scan_name = "INDEX_ONLY_SCAN"; - index_oid = ((IndexOnlyScan *) plan)->indexid; - break; - case T_BitmapHeapScan: - scan_name = "BITMAP_HEAP_SCAN"; - break; - case T_TidScan: - scan_name = "TID_SCAN"; - break; - case T_TidRangeScan: - scan_name = "TID_RANGE_SCAN"; - break; - case T_CustomScan: - scan_name = "CUSTOM_SCAN"; - break; - default: - break; - } - } - - if (name == NULL) - name = "???"; - if (OidIsValid(index_oid)) - { - char *indnsp; - char *indrel; - - indnsp = get_namespace_name_or_temp(get_rel_namespace(index_oid)); - indrel = get_rel_name(index_oid); - appendStringInfo(result, "%s(%s, %s.%s)\n", scan_name, name, - quote_identifier(indnsp), quote_identifier(indrel)); - } - else if (scan_name != NULL) - appendStringInfo(result, "%s(%s)\n", scan_name, name); - } -} - -static void -join_order_dump_recursive(StringInfo result, advice_context *context, Node *n) -{ - if (IsA(n, List)) - { - ListCell *lc; - bool first = true; - - appendStringInfoString(result, "("); - foreach(lc, (List *) n) - { - if (first) - first = false; - else - appendStringInfoString(result, " "); - join_order_dump_recursive(result, context, (Node *) lfirst(lc)); - } - appendStringInfoString(result, ")"); - } - else - { - Index rti = GetScannedRTI(context->stmt, (Plan *) n); - - if (rti != 0) - appendStringInfoString(result, context->rtable_names[rti - 1]); - else - appendStringInfo(result, "?[rti=%d,nodetag=%d]", (int) rti, - (int) nodeTag(n)); - } -} - -static void -join_order_dump(StringInfo result, advice_context *context) -{ - ListCell *lc; - - foreach(lc, context->all_join_orders) - { - List *l = lfirst_node(List, lc); - ListCell *lc2; - bool first = true; - - appendStringInfoString(result, "JOIN_ORDER("); - foreach(lc2, l) - { - if (first) - first = false; - else - appendStringInfoString(result, " "); - join_order_dump_recursive(result, context, (Node *) lfirst(lc2)); - } - appendStringInfoString(result, ")\n"); - } -} - -/* - * Generate advice from a PlannedStmt, and append it to the buffer provided. - * - * Returns false if the PlannedStmt has no plan tree, otherwise true. - */ -bool -append_advice_from_plan(StringInfo buf, PlannedStmt *stmt) -{ - advice_context context; - ListCell *lc; - - /* If this is a utility statement, there's no useful work to be done. */ - if (stmt->planTree == NULL) - return false; - - /* Initialization steps. */ - init_advice_context(&context, stmt); - generate_relation_identifiers(&context); - - /* First, scan the main plan tree. */ - scan_plan_tree(&context, stmt->planTree, NULL); - - /* - * Now, scan the list of InitPlans and SubPlans, which, confusingly, - * are collectively known as subplans. Some subplans may have been elided - * during planning, so skip any NULL entries in the array. - */ - foreach(lc, stmt->subplans) - { - Plan *plan = lfirst(lc); - - if (plan != NULL) - scan_plan_tree(&context, plan, NULL); - } - - /* Finally, append advice to the output buffer. */ - join_order_dump(buf, &context); - join_method_dump(buf, &context); - scan_method_dump(buf, &context); - - return true; -} -- 2.39.5