PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pgpa_trove.c File Reference
#include "postgres.h"
#include "pgpa_trove.h"
#include "common/hashfn_unstable.h"
#include "lib/simplehash.h"
Include dependency graph for pgpa_trove.c:

Go to the source code of this file.

Data Structures

struct  pgpa_trove_slice
 
struct  pgpa_trove
 
struct  pgpa_trove_entry_key
 
struct  pgpa_trove_entry_element
 

Macros

#define SH_PREFIX   pgpa_trove_entry
 
#define SH_ELEMENT_TYPE   pgpa_trove_entry_element
 
#define SH_KEY_TYPE   pgpa_trove_entry_key
 
#define SH_KEY   key
 
#define SH_HASH_KEY(tb, key)   pgpa_trove_entry_hash_key(key)
 
#define SH_EQUAL(tb, a, b)   pgpa_trove_entry_compare_key(a, b)
 
#define SH_SCOPE   static inline
 
#define SH_DECLARE
 
#define SH_DEFINE
 

Typedefs

typedef struct pgpa_trove_slice pgpa_trove_slice
 

Functions

static uint32 pgpa_trove_entry_hash_key (pgpa_trove_entry_key key)
 
static bool pgpa_trove_entry_compare_key (pgpa_trove_entry_key a, pgpa_trove_entry_key b)
 
static void pgpa_init_trove_slice (pgpa_trove_slice *tslice)
 
static void pgpa_trove_add_to_slice (pgpa_trove_slice *tslice, pgpa_advice_tag_type tag, pgpa_advice_target *target)
 
static void pgpa_trove_add_to_hash (pgpa_trove_entry_hash *hash, pgpa_advice_target *target, int index)
 
static Bitmapsetpgpa_trove_slice_lookup (pgpa_trove_slice *tslice, pgpa_identifier *rid)
 
pgpa_trovepgpa_build_trove (List *advice_items)
 
void pgpa_trove_lookup (pgpa_trove *trove, pgpa_trove_lookup_type type, int nrids, pgpa_identifier *rids, pgpa_trove_result *result)
 
void pgpa_trove_lookup_all (pgpa_trove *trove, pgpa_trove_lookup_type type, pgpa_trove_entry **entries, int *nentries)
 
charpgpa_cstring_trove_entry (pgpa_trove_entry *entry)
 
void pgpa_trove_set_flags (pgpa_trove_entry *entries, Bitmapset *indexes, int flags)
 
void pgpa_trove_append_flags (StringInfo buf, int flags)
 

Macro Definition Documentation

◆ SH_DECLARE

#define SH_DECLARE

Definition at line 111 of file pgpa_trove.c.

◆ SH_DEFINE

#define SH_DEFINE

Definition at line 112 of file pgpa_trove.c.

◆ SH_ELEMENT_TYPE

#define SH_ELEMENT_TYPE   pgpa_trove_entry_element

Definition at line 105 of file pgpa_trove.c.

◆ SH_EQUAL

#define SH_EQUAL (   tb,
  a,
  b 
)    pgpa_trove_entry_compare_key(a, b)

Definition at line 109 of file pgpa_trove.c.

◆ SH_HASH_KEY

#define SH_HASH_KEY (   tb,
  key 
)    pgpa_trove_entry_hash_key(key)

Definition at line 108 of file pgpa_trove.c.

◆ SH_KEY

#define SH_KEY   key

Definition at line 107 of file pgpa_trove.c.

◆ SH_KEY_TYPE

#define SH_KEY_TYPE   pgpa_trove_entry_key

Definition at line 106 of file pgpa_trove.c.

◆ SH_PREFIX

#define SH_PREFIX   pgpa_trove_entry

Definition at line 104 of file pgpa_trove.c.

◆ SH_SCOPE

#define SH_SCOPE   static inline

Definition at line 110 of file pgpa_trove.c.

Typedef Documentation

◆ pgpa_trove_slice

Function Documentation

◆ pgpa_build_trove()

pgpa_trove * pgpa_build_trove ( List advice_items)

Definition at line 132 of file pgpa_trove.c.

133{
135
137 pgpa_init_trove_slice(&trove->rel);
139
141 {
142 switch (item->tag)
143 {
145 {
146 pgpa_advice_target *target;
147
148 /*
149 * For most advice types, each element in the top-level
150 * list is a separate target, but it's most convenient to
151 * regard the entirety of a JOIN_ORDER specification as a
152 * single target. Since it wasn't represented that way
153 * during parsing, build a surrogate object now.
154 */
157 target->children = item->targets;
158
160 item->tag, target);
161 }
162 break;
163
169
170 /*
171 * Scan advice.
172 */
173 foreach_ptr(pgpa_advice_target, target, item->targets)
174 {
175 /*
176 * For now, all of our scan types target single relations,
177 * but in the future this might not be true, e.g. a custom
178 * scan could replace a join.
179 */
180 Assert(target->ttype == PGPA_TARGET_IDENTIFIER);
182 item->tag, target);
183 }
184 break;
185
195
196 /*
197 * Join strategy advice.
198 */
199 foreach_ptr(pgpa_advice_target, target, item->targets)
200 {
202 item->tag, target);
203 }
204 break;
205
207 case PGPA_TAG_GATHER:
210
211 /*
212 * Advice about a RelOptInfo relevant to both scans and joins.
213 */
214 foreach_ptr(pgpa_advice_target, target, item->targets)
215 {
217 item->tag, target);
218 }
219 break;
220 }
221 }
222
223 return trove;
224}
#define Assert(condition)
Definition c.h:927
#define palloc_object(type)
Definition fe_memutils.h:74
#define palloc0_object(type)
Definition fe_memutils.h:75
#define foreach_ptr(type, var, lst)
Definition pg_list.h:469
@ PGPA_TAG_INDEX_SCAN
Definition pgpa_ast.h:88
@ PGPA_TAG_NESTED_LOOP_MATERIALIZE
Definition pgpa_ast.h:92
@ PGPA_TAG_MERGE_JOIN_PLAIN
Definition pgpa_ast.h:91
@ PGPA_TAG_GATHER_MERGE
Definition pgpa_ast.h:85
@ PGPA_TAG_GATHER
Definition pgpa_ast.h:84
@ PGPA_TAG_NESTED_LOOP_MEMOIZE
Definition pgpa_ast.h:93
@ PGPA_TAG_SEMIJOIN_NON_UNIQUE
Definition pgpa_ast.h:97
@ PGPA_TAG_BITMAP_HEAP_SCAN
Definition pgpa_ast.h:82
@ PGPA_TAG_PARTITIONWISE
Definition pgpa_ast.h:96
@ PGPA_TAG_NO_GATHER
Definition pgpa_ast.h:95
@ PGPA_TAG_INDEX_ONLY_SCAN
Definition pgpa_ast.h:87
@ PGPA_TAG_SEQ_SCAN
Definition pgpa_ast.h:99
@ PGPA_TAG_HASH_JOIN
Definition pgpa_ast.h:86
@ PGPA_TAG_SEMIJOIN_UNIQUE
Definition pgpa_ast.h:98
@ PGPA_TAG_JOIN_ORDER
Definition pgpa_ast.h:89
@ PGPA_TAG_TID_SCAN
Definition pgpa_ast.h:100
@ PGPA_TAG_FOREIGN_JOIN
Definition pgpa_ast.h:83
@ PGPA_TAG_NESTED_LOOP_PLAIN
Definition pgpa_ast.h:94
@ PGPA_TAG_MERGE_JOIN_MATERIALIZE
Definition pgpa_ast.h:90
@ PGPA_TARGET_IDENTIFIER
Definition pgpa_ast.h:27
@ PGPA_TARGET_ORDERED_LIST
Definition pgpa_ast.h:28
static void pgpa_init_trove_slice(pgpa_trove_slice *tslice)
Definition pgpa_trove.c:431
static void pgpa_trove_add_to_slice(pgpa_trove_slice *tslice, pgpa_advice_tag_type tag, pgpa_advice_target *target)
Definition pgpa_trove.c:366
static int fb(int x)
pgpa_target_type ttype
Definition pgpa_ast.h:49
pgpa_trove_slice rel
Definition pgpa_trove.c:53
pgpa_trove_slice join
Definition pgpa_trove.c:52
pgpa_trove_slice scan
Definition pgpa_trove.c:54

References Assert, pgpa_advice_target::children, fb(), foreach_ptr, pgpa_trove::join, palloc0_object, palloc_object, pgpa_init_trove_slice(), PGPA_TAG_BITMAP_HEAP_SCAN, PGPA_TAG_FOREIGN_JOIN, PGPA_TAG_GATHER, PGPA_TAG_GATHER_MERGE, PGPA_TAG_HASH_JOIN, PGPA_TAG_INDEX_ONLY_SCAN, PGPA_TAG_INDEX_SCAN, PGPA_TAG_JOIN_ORDER, PGPA_TAG_MERGE_JOIN_MATERIALIZE, PGPA_TAG_MERGE_JOIN_PLAIN, PGPA_TAG_NESTED_LOOP_MATERIALIZE, PGPA_TAG_NESTED_LOOP_MEMOIZE, PGPA_TAG_NESTED_LOOP_PLAIN, PGPA_TAG_NO_GATHER, PGPA_TAG_PARTITIONWISE, PGPA_TAG_SEMIJOIN_NON_UNIQUE, PGPA_TAG_SEMIJOIN_UNIQUE, PGPA_TAG_SEQ_SCAN, PGPA_TAG_TID_SCAN, PGPA_TARGET_IDENTIFIER, PGPA_TARGET_ORDERED_LIST, pgpa_trove_add_to_slice(), pgpa_trove::rel, pgpa_trove::scan, and pgpa_advice_target::ttype.

Referenced by pgpa_planner_setup().

◆ pgpa_cstring_trove_entry()

char * pgpa_cstring_trove_entry ( pgpa_trove_entry entry)

Definition at line 295 of file pgpa_trove.c.

296{
298
301
302 /* JOIN_ORDER tags are transformed by pgpa_build_trove; undo that here */
303 if (entry->tag != PGPA_TAG_JOIN_ORDER)
305 else
307
309
310 if (entry->target->itarget != NULL)
311 {
314 }
315
316 if (entry->tag != PGPA_TAG_JOIN_ORDER)
318
319 return buf.data;
320}
static char buf[DEFAULT_XLOG_SEG_SIZE]
char * pgpa_cstring_advice_tag(pgpa_advice_tag_type advice_tag)
Definition pgpa_ast.c:29
void pgpa_format_advice_target(StringInfo str, pgpa_advice_target *target)
Definition pgpa_ast.c:164
void pgpa_format_index_target(StringInfo str, pgpa_index_target *itarget)
Definition pgpa_ast.c:200
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
pgpa_index_target * itarget
Definition pgpa_ast.h:64
pgpa_advice_target * target
Definition pgpa_trove.h:59
pgpa_advice_tag_type tag
Definition pgpa_trove.h:58

References appendStringInfo(), appendStringInfoChar(), Assert, buf, fb(), initStringInfo(), pgpa_advice_target::itarget, pgpa_cstring_advice_tag(), pgpa_format_advice_target(), pgpa_format_index_target(), PGPA_TAG_JOIN_ORDER, PGPA_TARGET_ORDERED_LIST, pgpa_trove_entry::tag, pgpa_trove_entry::target, and pgpa_advice_target::ttype.

Referenced by pgpa_planner_append_feedback().

◆ pgpa_init_trove_slice()

static void pgpa_init_trove_slice ( pgpa_trove_slice tslice)
static

Definition at line 431 of file pgpa_trove.c.

432{
433 /*
434 * In an ideal world, we'll make tslice->nallocated big enough that the
435 * array and hash table will be large enough to contain the number of
436 * advice items in this trove slice, but a generous default value is not
437 * good for performance, because pgpa_init_trove_slice() has to zero an
438 * amount of memory proportional to tslice->nallocated. Hence, we keep the
439 * starting value quite small, on the theory that advice strings will
440 * often be relatively short.
441 */
442 tslice->nallocated = 16;
443 tslice->nused = 0;
444 tslice->entries = palloc_array(pgpa_trove_entry, tslice->nallocated);
446 tslice->nallocated, NULL);
447}
#define palloc_array(type, count)
Definition fe_memutils.h:76
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
Definition pgpa_trove.h:57

References CurrentMemoryContext, fb(), and palloc_array.

Referenced by pgpa_build_trove().

◆ pgpa_trove_add_to_hash()

static void pgpa_trove_add_to_hash ( pgpa_trove_entry_hash hash,
pgpa_advice_target target,
int  index 
)
static

Definition at line 396 of file pgpa_trove.c.

398{
401 bool found;
402
403 /* For non-identifiers, add entries for all descendants. */
404 if (target->ttype != PGPA_TARGET_IDENTIFIER)
405 {
407 {
409 }
410 return;
411 }
412
413 /* Sanity checks. */
414 Assert(target->rid.occurrence > 0);
415 Assert(target->rid.alias_name != NULL);
416
417 /* Add an entry for this relation identifier. */
418 key.alias_name = target->rid.alias_name;
419 key.partition_name = target->rid.partrel;
420 key.plan_name = target->rid.plan_name;
421 element = pgpa_trove_entry_insert(hash, key, &found);
422 if (!found)
423 element->indexes = NULL;
424 element->indexes = bms_add_member(element->indexes, index);
425}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
static void pgpa_trove_add_to_hash(pgpa_trove_entry_hash *hash, pgpa_advice_target *target, int index)
Definition pgpa_trove.c:396
static chr element(struct vars *v, const chr *startp, const chr *endp)
static unsigned hash(unsigned *uv, int n)
Definition rege_dfa.c:715
Definition type.h:96
pgpa_identifier rid
Definition pgpa_ast.h:58
const char * alias_name
const char * partrel
const char * plan_name
Definition pgpa_trove.c:81
Definition pgpa_trove.c:74

References pgpa_identifier::alias_name, Assert, bms_add_member(), pgpa_advice_target::children, element(), fb(), foreach_ptr, hash(), pgpa_identifier::occurrence, pgpa_identifier::partrel, PGPA_TARGET_IDENTIFIER, pgpa_trove_add_to_hash(), pgpa_identifier::plan_name, pgpa_advice_target::rid, and pgpa_advice_target::ttype.

Referenced by pgpa_trove_add_to_hash(), and pgpa_trove_add_to_slice().

◆ pgpa_trove_add_to_slice()

static void pgpa_trove_add_to_slice ( pgpa_trove_slice tslice,
pgpa_advice_tag_type  tag,
pgpa_advice_target target 
)
static

Definition at line 366 of file pgpa_trove.c.

369{
370 pgpa_trove_entry *entry;
371
372 if (tslice->nused >= tslice->nallocated)
373 {
374 int new_allocated;
375
376 new_allocated = tslice->nallocated * 2;
377 tslice->entries = repalloc_array(tslice->entries, pgpa_trove_entry,
379 tslice->nallocated = new_allocated;
380 }
381
382 entry = &tslice->entries[tslice->nused];
383 entry->tag = tag;
384 entry->target = target;
385 entry->flags = 0;
386
387 pgpa_trove_add_to_hash(tslice->hash, target, tslice->nused);
388
389 tslice->nused++;
390}
#define repalloc_array(pointer, type, count)
Definition fe_memutils.h:78
int flags
Definition pgpa_trove.h:60

References fb(), pgpa_trove_entry::flags, pgpa_trove_add_to_hash(), repalloc_array, pgpa_trove_entry::tag, and pgpa_trove_entry::target.

Referenced by pgpa_build_trove().

◆ pgpa_trove_append_flags()

void pgpa_trove_append_flags ( StringInfo  buf,
int  flags 
)

Definition at line 343 of file pgpa_trove.c.

344{
345 if ((flags & PGPA_TE_MATCH_FULL) != 0)
346 {
347 Assert((flags & PGPA_TE_MATCH_PARTIAL) != 0);
348 appendStringInfo(buf, "matched");
349 }
350 else if ((flags & PGPA_TE_MATCH_PARTIAL) != 0)
351 appendStringInfo(buf, "partially matched");
352 else
353 appendStringInfo(buf, "not matched");
354 if ((flags & PGPA_TE_INAPPLICABLE) != 0)
355 appendStringInfo(buf, ", inapplicable");
356 if ((flags & PGPA_TE_CONFLICTING) != 0)
357 appendStringInfo(buf, ", conflicting");
358 if ((flags & PGPA_TE_FAILED) != 0)
359 appendStringInfo(buf, ", failed");
360}
#define PGPA_TE_INAPPLICABLE
Definition pgpa_trove.h:48
#define PGPA_TE_MATCH_FULL
Definition pgpa_trove.h:47
#define PGPA_TE_MATCH_PARTIAL
Definition pgpa_trove.h:46
#define PGPA_TE_CONFLICTING
Definition pgpa_trove.h:49
#define PGPA_TE_FAILED
Definition pgpa_trove.h:50

References appendStringInfo(), Assert, buf, PGPA_TE_CONFLICTING, PGPA_TE_FAILED, PGPA_TE_INAPPLICABLE, PGPA_TE_MATCH_FULL, and PGPA_TE_MATCH_PARTIAL.

Referenced by pg_plan_advice_explain_feedback(), and pgpa_planner_feedback_warning().

◆ pgpa_trove_entry_compare_key()

static bool pgpa_trove_entry_compare_key ( pgpa_trove_entry_key  a,
pgpa_trove_entry_key  b 
)
inlinestatic

Definition at line 90 of file pgpa_trove.c.

91{
92 if (strcmp(a.alias_name, b.alias_name) != 0)
93 return false;
94
95 if (!strings_equal_or_both_null(a.partition_name, b.partition_name))
96 return false;
97
98 if (!strings_equal_or_both_null(a.plan_name, b.plan_name))
99 return false;
100
101 return true;
102}
int b
Definition isn.c:74
int a
Definition isn.c:73
static bool strings_equal_or_both_null(const char *a, const char *b)

References a, b, fb(), and strings_equal_or_both_null().

◆ pgpa_trove_entry_hash_key()

static uint32 pgpa_trove_entry_hash_key ( pgpa_trove_entry_key  key)
static

Definition at line 454 of file pgpa_trove.c.

455{
457 int sp_len;
458
459 fasthash_init(&hs, 0);
460
461 /* alias_name may not be NULL */
462 sp_len = fasthash_accum_cstring(&hs, key.alias_name);
463
464 /* partition_name and plan_name, however, can be NULL */
465 if (key.partition_name != NULL)
466 sp_len += fasthash_accum_cstring(&hs, key.partition_name);
467 if (key.plan_name != NULL)
468 sp_len += fasthash_accum_cstring(&hs, key.plan_name);
469
470 /*
471 * hashfn_unstable.h recommends using string length as tweak. It's not
472 * clear to me what to do if there are multiple strings, so for now I'm
473 * just using the total of all of the lengths.
474 */
475 return fasthash_final32(&hs, sp_len);
476}
static size_t fasthash_accum_cstring(fasthash_state *hs, const char *str)
static uint32 fasthash_final32(fasthash_state *hs, uint64 tweak)
static void fasthash_init(fasthash_state *hs, uint64 seed)

References fasthash_accum_cstring(), fasthash_final32(), fasthash_init(), and fb().

◆ pgpa_trove_lookup()

void pgpa_trove_lookup ( pgpa_trove trove,
pgpa_trove_lookup_type  type,
int  nrids,
pgpa_identifier rids,
pgpa_trove_result result 
)

Definition at line 233 of file pgpa_trove.c.

235{
237 Bitmapset *indexes;
238
239 Assert(nrids > 0);
240
242 tslice = &trove->scan;
243 else if (type == PGPA_TROVE_LOOKUP_JOIN)
244 tslice = &trove->join;
245 else
246 tslice = &trove->rel;
247
248 indexes = pgpa_trove_slice_lookup(tslice, &rids[0]);
249 for (int i = 1; i < nrids; ++i)
250 {
252
253 /*
254 * If the caller is asking about two relations that aren't part of the
255 * same subquery, they've messed up.
256 */
257 Assert(strings_equal_or_both_null(rids[0].plan_name,
258 rids[i].plan_name));
259
261 indexes = bms_union(indexes, other_indexes);
262 }
263
264 result->entries = tslice->entries;
265 result->indexes = indexes;
266}
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:251
int i
Definition isn.c:77
static Bitmapset * pgpa_trove_slice_lookup(pgpa_trove_slice *tslice, pgpa_identifier *rid)
Definition pgpa_trove.c:482
@ PGPA_TROVE_LOOKUP_SCAN
Definition pgpa_trove.h:85
@ PGPA_TROVE_LOOKUP_JOIN
Definition pgpa_trove.h:83
pgpa_trove_entry * entries
Definition pgpa_trove.h:95
Bitmapset * indexes
Definition pgpa_trove.h:96
const char * type

References Assert, bms_union(), pgpa_trove_result::entries, fb(), i, pgpa_trove_result::indexes, pgpa_trove::join, PGPA_TROVE_LOOKUP_JOIN, PGPA_TROVE_LOOKUP_SCAN, pgpa_trove_slice_lookup(), pgpa_trove::rel, pgpa_trove::scan, strings_equal_or_both_null(), and type.

Referenced by pgpa_build_simple_rel(), and pgpa_get_join_state().

◆ pgpa_trove_lookup_all()

void pgpa_trove_lookup_all ( pgpa_trove trove,
pgpa_trove_lookup_type  type,
pgpa_trove_entry **  entries,
int nentries 
)

Definition at line 275 of file pgpa_trove.c.

277{
279
281 tslice = &trove->scan;
282 else if (type == PGPA_TROVE_LOOKUP_JOIN)
283 tslice = &trove->join;
284 else
285 tslice = &trove->rel;
286
287 *entries = tslice->entries;
288 *nentries = tslice->nused;
289}

References fb(), pgpa_trove::join, PGPA_TROVE_LOOKUP_JOIN, PGPA_TROVE_LOOKUP_SCAN, pgpa_trove::rel, pgpa_trove::scan, and type.

Referenced by pgpa_planner_append_feedback().

◆ pgpa_trove_set_flags()

void pgpa_trove_set_flags ( pgpa_trove_entry entries,
Bitmapset indexes,
int  flags 
)

Definition at line 326 of file pgpa_trove.c.

327{
328 int i = -1;
329
330 while ((i = bms_next_member(indexes, i)) >= 0)
331 {
332 pgpa_trove_entry *entry = &entries[i];
333
334 entry->flags |= flags;
335 }
336}
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1290

References bms_next_member(), pgpa_trove_entry::flags, and i.

Referenced by pgpa_planner_apply_join_path_advice(), pgpa_planner_apply_joinrel_advice(), and pgpa_planner_apply_scan_advice().

◆ pgpa_trove_slice_lookup()

static Bitmapset * pgpa_trove_slice_lookup ( pgpa_trove_slice tslice,
pgpa_identifier rid 
)
static

Definition at line 482 of file pgpa_trove.c.

483{
486 Bitmapset *result = NULL;
487
488 Assert(rid->occurrence >= 1);
489
490 key.alias_name = rid->alias_name;
491 key.partition_name = rid->partrel;
492 key.plan_name = rid->plan_name;
493
495
496 if (element != NULL)
497 {
498 int i = -1;
499
500 while ((i = bms_next_member(element->indexes, i)) >= 0)
501 {
502 pgpa_trove_entry *entry = &tslice->entries[i];
503
504 /*
505 * We know that this target or one of its descendants matches the
506 * identifier on the three key fields above, but we don't know
507 * which descendant or whether the occurrence and schema also
508 * match.
509 */
510 if (pgpa_identifier_matches_target(rid, entry->target))
511 result = bms_add_member(result, i);
512 }
513 }
514
515 return result;
516}
bool pgpa_identifier_matches_target(pgpa_identifier *rid, pgpa_advice_target *target)
Definition pgpa_ast.c:229

References pgpa_identifier::alias_name, Assert, bms_add_member(), bms_next_member(), element(), fb(), i, pgpa_identifier::occurrence, pgpa_identifier::partrel, pgpa_identifier_matches_target(), pgpa_identifier::plan_name, and pgpa_trove_entry::target.

Referenced by pgpa_trove_lookup().