LCOV - code coverage report
Current view: top level - contrib/pg_plan_advice - pgpa_join.h (source / functions) Coverage Total Hit
Test: Code coverage Lines: 100.0 % 2 2
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 1 1
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 100.0 % 4 4

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * pgpa_join.h
       4                 :             :  *        analysis of joins in Plan trees
       5                 :             :  *
       6                 :             :  * Copyright (c) 2016-2025, PostgreSQL Global Development Group
       7                 :             :  *
       8                 :             :  *        contrib/pg_plan_advice/pgpa_join.h
       9                 :             :  *
      10                 :             :  *-------------------------------------------------------------------------
      11                 :             :  */
      12                 :             : #ifndef PGPA_JOIN_H
      13                 :             : #define PGPA_JOIN_H
      14                 :             : 
      15                 :             : #include "nodes/plannodes.h"
      16                 :             : 
      17                 :             : typedef struct pgpa_plan_walker_context pgpa_plan_walker_context;
      18                 :             : typedef struct pgpa_join_unroller pgpa_join_unroller;
      19                 :             : typedef struct pgpa_unrolled_join pgpa_unrolled_join;
      20                 :             : 
      21                 :             : /*
      22                 :             :  * Although there are three main join strategies, we try to classify things
      23                 :             :  * more precisely here: merge joins have the option of using materialization
      24                 :             :  * on the inner side, and nested loops can use either materialization or
      25                 :             :  * memoization.
      26                 :             :  */
      27                 :             : typedef enum
      28                 :             : {
      29                 :             :         JSTRAT_MERGE_JOIN_PLAIN = 0,
      30                 :             :         JSTRAT_MERGE_JOIN_MATERIALIZE,
      31                 :             :         JSTRAT_NESTED_LOOP_PLAIN,
      32                 :             :         JSTRAT_NESTED_LOOP_MATERIALIZE,
      33                 :             :         JSTRAT_NESTED_LOOP_MEMOIZE,
      34                 :             :         JSTRAT_HASH_JOIN
      35                 :             :         /* update NUM_PGPA_JOIN_STRATEGY if you add anything here */
      36                 :             : } pgpa_join_strategy;
      37                 :             : 
      38                 :             : #define NUM_PGPA_JOIN_STRATEGY          ((int) JSTRAT_HASH_JOIN + 1)
      39                 :             : 
      40                 :             : /*
      41                 :             :  * In an outer-deep join tree, every member of an unrolled join will be a scan,
      42                 :             :  * but join trees with other shapes can contain unrolled joins.
      43                 :             :  *
      44                 :             :  * The plan node we store here will be the inner or outer child of the join
      45                 :             :  * node, as appropriate, except that we look through subnodes that we regard as
      46                 :             :  * part of the join method itself. For instance, for a Nested Loop that
      47                 :             :  * materializes the inner input, we'll store the child of the Materialize node,
      48                 :             :  * not the Materialize node itself.
      49                 :             :  *
      50                 :             :  * If setrefs processing elided one or more nodes from the plan tree, then
      51                 :             :  * we'll store details about the topmost of those in elided_node; otherwise,
      52                 :             :  * it will be NULL.
      53                 :             :  *
      54                 :             :  * Exactly one of scan and unrolled_join will be non-NULL.
      55                 :             :  */
      56                 :             : typedef struct
      57                 :             : {
      58                 :             :         Plan       *plan;
      59                 :             :         ElidedNode *elided_node;
      60                 :             :         struct pgpa_scan *scan;
      61                 :             :         pgpa_unrolled_join *unrolled_join;
      62                 :             : } pgpa_join_member;
      63                 :             : 
      64                 :             : /*
      65                 :             :  * We convert outer-deep join trees to a flat structure; that is, ((A JOIN B)
      66                 :             :  * JOIN C) JOIN D gets converted to outer = A, inner = <B C D>.  When joins
      67                 :             :  * aren't outer-deep, substructure is required, e.g. (A JOIN B) JOIN (C JOIN D)
      68                 :             :  * is represented as outer = A, inner = <B X>, where X is a pgpa_unrolled_join
      69                 :             :  * covering C-D.
      70                 :             :  */
      71                 :             : struct pgpa_unrolled_join
      72                 :             : {
      73                 :             :         /* Outermost member; must not itself be an unrolled join. */
      74                 :             :         pgpa_join_member outer;
      75                 :             : 
      76                 :             :         /* Number of inner members. Length of the strategy and inner arrays. */
      77                 :             :         unsigned        ninner;
      78                 :             : 
      79                 :             :         /* Array of strategies, one per non-outermost member. */
      80                 :             :         pgpa_join_strategy *strategy;
      81                 :             : 
      82                 :             :         /* Array of members, excluding the outermost. Deepest first. */
      83                 :             :         pgpa_join_member *inner;
      84                 :             : };
      85                 :             : 
      86                 :             : /*
      87                 :             :  * Does this plan node inherit from Join?
      88                 :             :  */
      89                 :             : static inline bool
      90                 :      140223 : pgpa_is_join(Plan *plan)
      91                 :             : {
      92   [ +  +  +  + ]:      140223 :         return IsA(plan, NestLoop) || IsA(plan, MergeJoin) || IsA(plan, HashJoin);
      93                 :             : }
      94                 :             : 
      95                 :             : extern pgpa_join_unroller *pgpa_create_join_unroller(void);
      96                 :             : extern void pgpa_unroll_join(pgpa_plan_walker_context *walker,
      97                 :             :                                                          Plan *plan, bool beneath_any_gather,
      98                 :             :                                                          pgpa_join_unroller *join_unroller,
      99                 :             :                                                          pgpa_join_unroller **outer_join_unroller,
     100                 :             :                                                          pgpa_join_unroller **inner_join_unroller);
     101                 :             : extern pgpa_unrolled_join *pgpa_build_unrolled_join(pgpa_plan_walker_context *walker,
     102                 :             :                                                                                                         pgpa_join_unroller *join_unroller);
     103                 :             : extern void pgpa_destroy_join_unroller(pgpa_join_unroller *join_unroller);
     104                 :             : 
     105                 :             : #endif
        

Generated by: LCOV version 2.3.2-1