PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pgpa_output.c File Reference
#include "postgres.h"
#include "pgpa_output.h"
#include "pgpa_scan.h"
#include "nodes/parsenodes.h"
#include "parser/parsetree.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
Include dependency graph for pgpa_output.c:

Go to the source code of this file.

Data Structures

struct  pgpa_output_context
 

Typedefs

typedef struct pgpa_output_context pgpa_output_context
 

Functions

static void pgpa_output_unrolled_join (pgpa_output_context *context, pgpa_unrolled_join *join)
 
static void pgpa_output_join_member (pgpa_output_context *context, pgpa_join_member *member)
 
static void pgpa_output_scan_strategy (pgpa_output_context *context, pgpa_scan_strategy strategy, List *scans)
 
static void pgpa_output_relation_name (pgpa_output_context *context, Oid relid)
 
static void pgpa_output_query_feature (pgpa_output_context *context, pgpa_qf_type type, List *query_features)
 
static void pgpa_output_simple_strategy (pgpa_output_context *context, char *strategy, List *relid_sets)
 
static void pgpa_output_no_gather (pgpa_output_context *context, Bitmapset *relids)
 
static void pgpa_output_do_not_scan (pgpa_output_context *context, List *identifiers)
 
static void pgpa_output_relations (pgpa_output_context *context, StringInfo buf, Bitmapset *relids)
 
static charpgpa_cstring_join_strategy (pgpa_join_strategy strategy)
 
static charpgpa_cstring_scan_strategy (pgpa_scan_strategy strategy)
 
static charpgpa_cstring_query_feature_type (pgpa_qf_type type)
 
static void pgpa_maybe_linebreak (StringInfo buf, int wrap_column)
 
void pgpa_output_advice (StringInfo buf, pgpa_plan_walker_context *walker, pgpa_identifier *rt_identifiers)
 

Typedef Documentation

◆ pgpa_output_context

Function Documentation

◆ pgpa_cstring_join_strategy()

static char * pgpa_cstring_join_strategy ( pgpa_join_strategy  strategy)
static

Definition at line 470 of file pgpa_output.c.

471{
472 switch (strategy)
473 {
475 return "MERGE_JOIN_PLAIN";
477 return "MERGE_JOIN_MATERIALIZE";
479 return "NESTED_LOOP_PLAIN";
481 return "NESTED_LOOP_MATERIALIZE";
483 return "NESTED_LOOP_MEMOIZE";
484 case JSTRAT_HASH_JOIN:
485 return "HASH_JOIN";
486 }
487
489 return NULL;
490}
#define pg_unreachable()
Definition c.h:367
@ JSTRAT_MERGE_JOIN_PLAIN
Definition pgpa_join.h:29
@ JSTRAT_NESTED_LOOP_MATERIALIZE
Definition pgpa_join.h:32
@ JSTRAT_NESTED_LOOP_MEMOIZE
Definition pgpa_join.h:33
@ JSTRAT_HASH_JOIN
Definition pgpa_join.h:34
@ JSTRAT_NESTED_LOOP_PLAIN
Definition pgpa_join.h:31
@ JSTRAT_MERGE_JOIN_MATERIALIZE
Definition pgpa_join.h:30
static int fb(int x)

References fb(), JSTRAT_HASH_JOIN, JSTRAT_MERGE_JOIN_MATERIALIZE, JSTRAT_MERGE_JOIN_PLAIN, JSTRAT_NESTED_LOOP_MATERIALIZE, JSTRAT_NESTED_LOOP_MEMOIZE, JSTRAT_NESTED_LOOP_PLAIN, and pg_unreachable.

Referenced by pgpa_output_advice().

◆ pgpa_cstring_query_feature_type()

static char * pgpa_cstring_query_feature_type ( pgpa_qf_type  type)
static

Definition at line 526 of file pgpa_output.c.

527{
528 switch (type)
529 {
530 case PGPAQF_GATHER:
531 return "GATHER";
533 return "GATHER_MERGE";
535 return "SEMIJOIN_NON_UNIQUE";
537 return "SEMIJOIN_UNIQUE";
538 }
539
540
542 return NULL;
543}
@ PGPAQF_GATHER
Definition pgpa_walker.h:45
@ PGPAQF_GATHER_MERGE
Definition pgpa_walker.h:46
@ PGPAQF_SEMIJOIN_UNIQUE
Definition pgpa_walker.h:48
@ PGPAQF_SEMIJOIN_NON_UNIQUE
Definition pgpa_walker.h:47
const char * type

References fb(), pg_unreachable, PGPAQF_GATHER, PGPAQF_GATHER_MERGE, PGPAQF_SEMIJOIN_NON_UNIQUE, PGPAQF_SEMIJOIN_UNIQUE, and type.

Referenced by pgpa_output_query_feature().

◆ pgpa_cstring_scan_strategy()

static char * pgpa_cstring_scan_strategy ( pgpa_scan_strategy  strategy)
static

Definition at line 496 of file pgpa_output.c.

497{
498 switch (strategy)
499 {
501 return "ORDINARY_SCAN";
502 case PGPA_SCAN_SEQ:
503 return "SEQ_SCAN";
505 return "BITMAP_HEAP_SCAN";
507 return "FOREIGN_JOIN";
508 case PGPA_SCAN_INDEX:
509 return "INDEX_SCAN";
511 return "INDEX_ONLY_SCAN";
513 return "PARTITIONWISE";
514 case PGPA_SCAN_TID:
515 return "TID_SCAN";
516 }
517
519 return NULL;
520}
@ PGPA_SCAN_SEQ
Definition pgpa_scan.h:58
@ PGPA_SCAN_INDEX
Definition pgpa_scan.h:61
@ PGPA_SCAN_INDEX_ONLY
Definition pgpa_scan.h:62
@ PGPA_SCAN_BITMAP_HEAP
Definition pgpa_scan.h:59
@ PGPA_SCAN_FOREIGN
Definition pgpa_scan.h:60
@ PGPA_SCAN_TID
Definition pgpa_scan.h:64
@ PGPA_SCAN_PARTITIONWISE
Definition pgpa_scan.h:63
@ PGPA_SCAN_ORDINARY
Definition pgpa_scan.h:57

References fb(), pg_unreachable, PGPA_SCAN_BITMAP_HEAP, PGPA_SCAN_FOREIGN, PGPA_SCAN_INDEX, PGPA_SCAN_INDEX_ONLY, PGPA_SCAN_ORDINARY, PGPA_SCAN_PARTITIONWISE, PGPA_SCAN_SEQ, and PGPA_SCAN_TID.

Referenced by pgpa_output_scan_strategy().

◆ pgpa_maybe_linebreak()

static void pgpa_maybe_linebreak ( StringInfo  buf,
int  wrap_column 
)
static

Definition at line 559 of file pgpa_output.c.

560{
561 char *trailing_nl;
562 int line_start;
563 int save_cursor;
564
565 /* If line wrapping is disabled, exit quickly. */
566 if (wrap_column <= 0)
567 return;
568
569 /*
570 * Set line_start to the byte offset within buf->data of the first
571 * character of the current line, where the current line means the last
572 * one in the buffer. Note that line_start could be the offset of the
573 * trailing '\0' if the last character in the buffer is a line break.
574 */
575 trailing_nl = strrchr(buf->data, '\n');
576 if (trailing_nl == NULL)
577 line_start = 0;
578 else
579 line_start = (trailing_nl - buf->data) + 1;
580
581 /*
582 * Remember that the current end of the buffer is a potential location to
583 * insert a line break on a future call to this function.
584 */
585 save_cursor = buf->cursor;
586 buf->cursor = buf->len;
587
588 /* If we haven't passed the wrap column, we don't need a newline. */
589 if (buf->len - line_start <= wrap_column)
590 return;
591
592 /*
593 * It only makes sense to insert a newline at a position later than the
594 * beginning of the current line.
595 */
596 if (save_cursor <= line_start)
597 return;
598
599 /* Insert a newline at the previous cursor location. */
601 memmove(&buf->data[save_cursor] + 1, &buf->data[save_cursor],
602 buf->len - save_cursor);
603 ++buf->cursor;
604 buf->data[++buf->len] = '\0';
605 buf->data[save_cursor] = '\n';
606}
static char buf[DEFAULT_XLOG_SEG_SIZE]
void enlargeStringInfo(StringInfo str, int needed)
Definition stringinfo.c:337

References buf, enlargeStringInfo(), and fb().

Referenced by pgpa_output_advice(), pgpa_output_do_not_scan(), pgpa_output_query_feature(), pgpa_output_relations(), pgpa_output_scan_strategy(), pgpa_output_simple_strategy(), and pgpa_output_unrolled_join().

◆ pgpa_output_advice()

void pgpa_output_advice ( StringInfo  buf,
pgpa_plan_walker_context walker,
pgpa_identifier rt_identifiers 
)

Definition at line 80 of file pgpa_output.c.

82{
83 Index rtable_length = list_length(walker->pstmt->rtable);
84 ListCell *lc;
85 pgpa_output_context context;
86
87 /* Basic initialization. */
88 memset(&context, 0, sizeof(pgpa_output_context));
89 context.buf = buf;
90
91 /*
92 * Convert identifiers to string form. Note that the loop variable here is
93 * not an RTI, because RTIs are 1-based. Some RTIs will have no
94 * identifier, either because the reloptkind is RTE_JOIN or because that
95 * portion of the query didn't make it into the final plan.
96 */
97 context.rid_strings = palloc0_array(const char *, rtable_length);
98 for (int i = 0; i < rtable_length; ++i)
99 if (rt_identifiers[i].alias_name != NULL)
101
102 /*
103 * If the user chooses to use EXPLAIN (PLAN_ADVICE) in an 80-column window
104 * from a psql client with default settings, psql will add one space to
105 * the left of the output and EXPLAIN will add two more to the left of the
106 * advice. Thus, lines of more than 77 characters will wrap. We set the
107 * wrap limit to 76 here so that the output won't reach all the way to the
108 * very last column of the terminal.
109 *
110 * Of course, this is fairly arbitrary set of assumptions, and one could
111 * well make an argument for a different wrap limit, or for a configurable
112 * one.
113 */
114 context.wrap_column = 76;
115
116 /*
117 * Each piece of JOIN_ORDER() advice fully describes the join order for a
118 * a single unrolled join. Merging is not permitted, because that would
119 * change the meaning, e.g. SEQ_SCAN(a b c d) means simply that sequential
120 * scans should be used for all of those relations, and is thus equivalent
121 * to SEQ_SCAN(a b) SEQ_SCAN(c d), but JOIN_ORDER(a b c d) means that "a"
122 * is the driving table which is then joined to "b" then "c" then "d",
123 * which is totally different from JOIN_ORDER(a b) and JOIN_ORDER(c d).
124 */
125 foreach(lc, walker->toplevel_unrolled_joins)
126 {
128
129 if (buf->len > 0)
131 appendStringInfo(context.buf, "JOIN_ORDER(");
133 appendStringInfoChar(context.buf, ')');
134 pgpa_maybe_linebreak(context.buf, context.wrap_column);
135 }
136
137 /* Emit join strategy advice. */
138 for (int s = 0; s < NUM_PGPA_JOIN_STRATEGY; ++s)
139 {
140 char *strategy = pgpa_cstring_join_strategy(s);
141
143 strategy,
144 walker->join_strategies[s]);
145 }
146
147 /*
148 * Emit scan strategy advice (but not for ordinary scans, which are
149 * definitionally uninteresting).
150 */
151 for (int c = 0; c < NUM_PGPA_SCAN_STRATEGY; ++c)
152 if (c != PGPA_SCAN_ORDINARY)
153 pgpa_output_scan_strategy(&context, c, walker->scans[c]);
154
155 /* Emit query feature advice. */
156 for (int t = 0; t < NUM_PGPA_QF_TYPES; ++t)
157 pgpa_output_query_feature(&context, t, walker->query_features[t]);
158
159 /* Emit NO_GATHER advice. */
160 pgpa_output_no_gather(&context, walker->no_gather_scans);
161
162 /* Emit DO_NOT_SCAN advice. */
163 pgpa_output_do_not_scan(&context, walker->do_not_scan_identifiers);
164}
unsigned int Index
Definition c.h:698
#define palloc0_array(type, count)
Definition fe_memutils.h:77
int i
Definition isn.c:77
#define lfirst(lc)
Definition pg_list.h:172
static int list_length(const List *l)
Definition pg_list.h:152
const char * pgpa_identifier_string(const pgpa_identifier *rid)
#define NUM_PGPA_JOIN_STRATEGY
Definition pgpa_join.h:38
static void pgpa_output_simple_strategy(pgpa_output_context *context, char *strategy, List *relid_sets)
static char * pgpa_cstring_join_strategy(pgpa_join_strategy strategy)
static void pgpa_output_no_gather(pgpa_output_context *context, Bitmapset *relids)
static void pgpa_maybe_linebreak(StringInfo buf, int wrap_column)
static void pgpa_output_unrolled_join(pgpa_output_context *context, pgpa_unrolled_join *join)
static void pgpa_output_scan_strategy(pgpa_output_context *context, pgpa_scan_strategy strategy, List *scans)
static void pgpa_output_query_feature(pgpa_output_context *context, pgpa_qf_type type, List *query_features)
static void pgpa_output_do_not_scan(pgpa_output_context *context, List *identifiers)
#define NUM_PGPA_SCAN_STRATEGY
Definition pgpa_scan.h:68
#define NUM_PGPA_QF_TYPES
Definition pgpa_walker.h:52
char * c
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242
const char ** rid_strings
Definition pgpa_output.c:36

References appendStringInfo(), appendStringInfoChar(), pgpa_output_context::buf, buf, fb(), i, lfirst, list_length(), NUM_PGPA_JOIN_STRATEGY, NUM_PGPA_QF_TYPES, NUM_PGPA_SCAN_STRATEGY, palloc0_array, pgpa_cstring_join_strategy(), pgpa_identifier_string(), pgpa_maybe_linebreak(), pgpa_output_do_not_scan(), pgpa_output_no_gather(), pgpa_output_query_feature(), pgpa_output_scan_strategy(), pgpa_output_simple_strategy(), pgpa_output_unrolled_join(), PGPA_SCAN_ORDINARY, pgpa_output_context::rid_strings, and pgpa_output_context::wrap_column.

Referenced by pgpa_planner_shutdown().

◆ pgpa_output_do_not_scan()

static void pgpa_output_do_not_scan ( pgpa_output_context context,
List identifiers 
)
static

Definition at line 408 of file pgpa_output.c.

409{
410 bool first = true;
411
412 if (identifiers == NIL)
413 return;
414 if (context->buf->len > 0)
415 appendStringInfoChar(context->buf, '\n');
416 appendStringInfoString(context->buf, "DO_NOT_SCAN(");
417
418 foreach_ptr(pgpa_identifier, rid, identifiers)
419 {
420 if (first)
421 first = false;
422 else
423 {
424 pgpa_maybe_linebreak(context->buf, context->wrap_column);
425 appendStringInfoChar(context->buf, ' ');
426 }
428 }
429
430 appendStringInfoChar(context->buf, ')');
431}
#define NIL
Definition pg_list.h:68
#define foreach_ptr(type, var, lst)
Definition pg_list.h:501
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230

References appendStringInfoChar(), appendStringInfoString(), pgpa_output_context::buf, foreach_ptr, StringInfoData::len, NIL, pgpa_identifier_string(), pgpa_maybe_linebreak(), and pgpa_output_context::wrap_column.

Referenced by pgpa_output_advice().

◆ pgpa_output_join_member()

static void pgpa_output_join_member ( pgpa_output_context context,
pgpa_join_member member 
)
static

Definition at line 190 of file pgpa_output.c.

192{
193 if (member->unrolled_join != NULL)
194 {
195 appendStringInfoChar(context->buf, '(');
197 appendStringInfoChar(context->buf, ')');
198 }
199 else
200 {
201 pgpa_scan *scan = member->scan;
202
203 Assert(scan != NULL);
204 if (bms_membership(scan->relids) == BMS_SINGLETON)
205 pgpa_output_relations(context, context->buf, scan->relids);
206 else
207 {
208 appendStringInfoChar(context->buf, '{');
209 pgpa_output_relations(context, context->buf, scan->relids);
210 appendStringInfoChar(context->buf, '}');
211 }
212 }
213}
BMS_Membership bms_membership(const Bitmapset *a)
Definition bitmapset.c:765
@ BMS_SINGLETON
Definition bitmapset.h:72
#define Assert(condition)
Definition c.h:943
static void pgpa_output_relations(pgpa_output_context *context, StringInfo buf, Bitmapset *relids)
struct pgpa_scan * scan
Definition pgpa_join.h:60
pgpa_unrolled_join * unrolled_join
Definition pgpa_join.h:61
Bitmapset * relids
Definition pgpa_scan.h:77

References appendStringInfoChar(), Assert, bms_membership(), BMS_SINGLETON, pgpa_output_context::buf, fb(), pgpa_output_relations(), pgpa_output_unrolled_join(), pgpa_scan::relids, pgpa_join_member::scan, and pgpa_join_member::unrolled_join.

Referenced by pgpa_output_unrolled_join().

◆ pgpa_output_no_gather()

static void pgpa_output_no_gather ( pgpa_output_context context,
Bitmapset relids 
)
static

Definition at line 392 of file pgpa_output.c.

393{
394 if (relids == NULL)
395 return;
396 if (context->buf->len > 0)
397 appendStringInfoChar(context->buf, '\n');
398 appendStringInfoString(context->buf, "NO_GATHER(");
399 pgpa_output_relations(context, context->buf, relids);
400 appendStringInfoChar(context->buf, ')');
401}

References appendStringInfoChar(), appendStringInfoString(), pgpa_output_context::buf, fb(), StringInfoData::len, and pgpa_output_relations().

Referenced by pgpa_output_advice().

◆ pgpa_output_query_feature()

static void pgpa_output_query_feature ( pgpa_output_context context,
pgpa_qf_type  type,
List query_features 
)
static

Definition at line 300 of file pgpa_output.c.

302{
303 bool first = true;
304
305 if (query_features == NIL)
306 return;
307
308 if (context->buf->len > 0)
309 appendStringInfoChar(context->buf, '\n');
310 appendStringInfo(context->buf, "%s(",
312
313 foreach_ptr(pgpa_query_feature, qf, query_features)
314 {
315 if (first)
316 first = false;
317 else
318 {
319 pgpa_maybe_linebreak(context->buf, context->wrap_column);
320 appendStringInfoChar(context->buf, ' ');
321 }
322
323 if (bms_membership(qf->relids) == BMS_SINGLETON)
324 pgpa_output_relations(context, context->buf, qf->relids);
325 else
326 {
327 appendStringInfoChar(context->buf, '(');
328 pgpa_output_relations(context, context->buf, qf->relids);
329 appendStringInfoChar(context->buf, ')');
330 }
331 }
332
333 appendStringInfoChar(context->buf, ')');
334 pgpa_maybe_linebreak(context->buf, context->wrap_column);
335}
static char * pgpa_cstring_query_feature_type(pgpa_qf_type type)

References appendStringInfo(), appendStringInfoChar(), bms_membership(), BMS_SINGLETON, pgpa_output_context::buf, fb(), foreach_ptr, StringInfoData::len, NIL, pgpa_cstring_query_feature_type(), pgpa_maybe_linebreak(), pgpa_output_relations(), type, and pgpa_output_context::wrap_column.

Referenced by pgpa_output_advice().

◆ pgpa_output_relation_name()

static void pgpa_output_relation_name ( pgpa_output_context context,
Oid  relid 
)
static

Definition at line 283 of file pgpa_output.c.

284{
286 char *relnamespace = get_namespace_name_or_temp(nspoid);
287 char *relname = get_rel_name(relid);
288
289 appendStringInfoString(context->buf, quote_identifier(relnamespace));
290 appendStringInfoChar(context->buf, '.');
292}
char * get_rel_name(Oid relid)
Definition lsyscache.c:2148
Oid get_rel_namespace(Oid relid)
Definition lsyscache.c:2172
char * get_namespace_name_or_temp(Oid nspid)
Definition lsyscache.c:3612
NameData relname
Definition pg_class.h:40
unsigned int Oid
const char * quote_identifier(const char *ident)

References appendStringInfoChar(), appendStringInfoString(), pgpa_output_context::buf, fb(), get_namespace_name_or_temp(), get_rel_name(), get_rel_namespace(), quote_identifier(), and relname.

Referenced by pgpa_output_scan_strategy().

◆ pgpa_output_relations()

static void pgpa_output_relations ( pgpa_output_context context,
StringInfo  buf,
Bitmapset relids 
)
static

Definition at line 440 of file pgpa_output.c.

442{
443 int rti = -1;
444 bool first = true;
445
446 while ((rti = bms_next_member(relids, rti)) >= 0)
447 {
448 const char *rid_string = context->rid_strings[rti - 1];
449
450 if (rid_string == NULL)
451 elog(ERROR, "no identifier for RTI %d", rti);
452
453 if (first)
454 {
455 first = false;
457 }
458 else
459 {
462 }
463 }
464}
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1290
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:227

References appendStringInfo(), appendStringInfoString(), bms_next_member(), buf, elog, ERROR, fb(), pgpa_maybe_linebreak(), pgpa_output_context::rid_strings, and pgpa_output_context::wrap_column.

Referenced by pgpa_output_join_member(), pgpa_output_no_gather(), pgpa_output_query_feature(), pgpa_output_scan_strategy(), and pgpa_output_simple_strategy().

◆ pgpa_output_scan_strategy()

static void pgpa_output_scan_strategy ( pgpa_output_context context,
pgpa_scan_strategy  strategy,
List scans 
)
static

Definition at line 221 of file pgpa_output.c.

224{
225 bool first = true;
226
227 if (scans == NIL)
228 return;
229
230 if (context->buf->len > 0)
231 appendStringInfoChar(context->buf, '\n');
232 appendStringInfo(context->buf, "%s(",
234
235 foreach_ptr(pgpa_scan, scan, scans)
236 {
237 Plan *plan = scan->plan;
238
239 if (first)
240 first = false;
241 else
242 {
243 pgpa_maybe_linebreak(context->buf, context->wrap_column);
244 appendStringInfoChar(context->buf, ' ');
245 }
246
247 /* Output the relation identifiers. */
248 if (bms_membership(scan->relids) == BMS_SINGLETON)
249 pgpa_output_relations(context, context->buf, scan->relids);
250 else
251 {
252 appendStringInfoChar(context->buf, '(');
253 pgpa_output_relations(context, context->buf, scan->relids);
254 appendStringInfoChar(context->buf, ')');
255 }
256
257 /* For index or index-only scans, output index information. */
258 if (strategy == PGPA_SCAN_INDEX)
259 {
261 pgpa_maybe_linebreak(context->buf, context->wrap_column);
262 appendStringInfoChar(context->buf, ' ');
263 pgpa_output_relation_name(context, ((IndexScan *) plan)->indexid);
264 }
265 else if (strategy == PGPA_SCAN_INDEX_ONLY)
266 {
268 pgpa_maybe_linebreak(context->buf, context->wrap_column);
269 appendStringInfoChar(context->buf, ' ');
271 ((IndexOnlyScan *) plan)->indexid);
272 }
273 }
274
275 appendStringInfoChar(context->buf, ')');
276 pgpa_maybe_linebreak(context->buf, context->wrap_column);
277}
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define plan(x)
Definition pg_regress.c:164
static void pgpa_output_relation_name(pgpa_output_context *context, Oid relid)
static char * pgpa_cstring_scan_strategy(pgpa_scan_strategy strategy)

References appendStringInfo(), appendStringInfoChar(), Assert, bms_membership(), BMS_SINGLETON, pgpa_output_context::buf, foreach_ptr, IsA, StringInfoData::len, NIL, pgpa_cstring_scan_strategy(), pgpa_maybe_linebreak(), pgpa_output_relation_name(), pgpa_output_relations(), PGPA_SCAN_INDEX, PGPA_SCAN_INDEX_ONLY, plan, and pgpa_output_context::wrap_column.

Referenced by pgpa_output_advice().

◆ pgpa_output_simple_strategy()

static void pgpa_output_simple_strategy ( pgpa_output_context context,
char strategy,
List relid_sets 
)
static

Definition at line 351 of file pgpa_output.c.

353{
354 bool first = true;
355
356 if (relid_sets == NIL)
357 return;
358
359 if (context->buf->len > 0)
360 appendStringInfoChar(context->buf, '\n');
361 appendStringInfo(context->buf, "%s(", strategy);
362
364 {
365 if (first)
366 first = false;
367 else
368 {
369 pgpa_maybe_linebreak(context->buf, context->wrap_column);
370 appendStringInfoChar(context->buf, ' ');
371 }
372
373 if (bms_membership(relids) == BMS_SINGLETON)
374 pgpa_output_relations(context, context->buf, relids);
375 else
376 {
377 appendStringInfoChar(context->buf, '(');
378 pgpa_output_relations(context, context->buf, relids);
379 appendStringInfoChar(context->buf, ')');
380 }
381 }
382
383 appendStringInfoChar(context->buf, ')');
384 pgpa_maybe_linebreak(context->buf, context->wrap_column);
385}
#define foreach_node(type, var, lst)
Definition pg_list.h:528

References appendStringInfo(), appendStringInfoChar(), bms_membership(), BMS_SINGLETON, pgpa_output_context::buf, fb(), foreach_node, StringInfoData::len, NIL, pgpa_maybe_linebreak(), pgpa_output_relations(), and pgpa_output_context::wrap_column.

Referenced by pgpa_output_advice().

◆ pgpa_output_unrolled_join()

static void pgpa_output_unrolled_join ( pgpa_output_context context,
pgpa_unrolled_join join 
)
static

Definition at line 171 of file pgpa_output.c.

173{
174 pgpa_output_join_member(context, &join->outer);
175
176 for (int k = 0; k < join->ninner; ++k)
177 {
178 pgpa_join_member *member = &join->inner[k];
179
180 pgpa_maybe_linebreak(context->buf, context->wrap_column);
181 appendStringInfoChar(context->buf, ' ');
182 pgpa_output_join_member(context, member);
183 }
184}
static void pgpa_output_join_member(pgpa_output_context *context, pgpa_join_member *member)
pgpa_join_member * inner
Definition pgpa_join.h:83
pgpa_join_member outer
Definition pgpa_join.h:74

References appendStringInfoChar(), pgpa_output_context::buf, pgpa_unrolled_join::inner, pgpa_unrolled_join::ninner, pgpa_unrolled_join::outer, pgpa_maybe_linebreak(), pgpa_output_join_member(), and pgpa_output_context::wrap_column.

Referenced by pgpa_output_advice(), and pgpa_output_join_member().