MCPcopy Create free account
hub / github.com/apache/cloudberry / create_unique_path

Function create_unique_path

src/backend/optimizer/util/pathnode.c:2334–2632  ·  view source on GitHub ↗

* create_unique_path * Creates a path representing elimination of distinct rows from the * input data. Distinct-ness is defined according to the needs of the * semijoin represented by sjinfo. If it is not possible to identify * how to make the data unique, NULL is returned. * * If used at all, this is likely to be called repeatedly on the same rel; * and the input subpath should a

Source from the content-addressed store, hash-verified

2332 * for the rel). So we cache the result.
2333 */
2334UniquePath *
2335create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
2336 SpecialJoinInfo *sjinfo)
2337{
2338 UniquePath *pathnode;
2339 Path sort_path; /* dummy for result of cost_sort */
2340 Path agg_path; /* dummy for result of cost_agg */
2341 MemoryContext oldcontext;
2342 int numCols;
2343 CdbPathLocus locus;
2344 bool add_motion = false;
2345 double numsegments;
2346
2347 /* Caller made a mistake if subpath isn't cheapest_total ... */
2348 Assert(subpath == rel->cheapest_total_path);
2349 Assert(subpath->parent == rel);
2350 /* ... or if SpecialJoinInfo is the wrong one */
2351 Assert(sjinfo->jointype == JOIN_SEMI);
2352 Assert(bms_equal(rel->relids, sjinfo->syn_righthand));
2353
2354 /* If result already cached, return it */
2355 if (rel->cheapest_unique_path)
2356 return (UniquePath *) rel->cheapest_unique_path;
2357
2358 /* If it's not possible to unique-ify, return NULL */
2359 if (!(sjinfo->semi_can_btree || sjinfo->semi_can_hash))
2360 return NULL;
2361
2362 /*
2363 * When called during GEQO join planning, we are in a short-lived memory
2364 * context. We must make sure that the path and any subsidiary data
2365 * structures created for a baserel survive the GEQO cycle, else the
2366 * baserel is trashed for future GEQO cycles. On the other hand, when we
2367 * are creating those for a joinrel during GEQO, we don't want them to
2368 * clutter the main planning context. Upshot is that the best solution is
2369 * to explicitly allocate memory in the same context the given RelOptInfo
2370 * is in.
2371 */
2372 oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(rel));
2373
2374 /* Repartition first if duplicates might be on different QEs. */
2375 if (!CdbPathLocus_IsBottleneck(subpath->locus) &&
2376 !cdbpathlocus_is_hashed_on_exprs(subpath->locus, sjinfo->semi_rhs_exprs, false))
2377 {
2378 int numsegments = CdbPathLocus_NumSegments(subpath->locus);
2379
2380 List *opfamilies = NIL;
2381 List *sortrefs = NIL;
2382 ListCell *lc;
2383
2384 foreach(lc, sjinfo->semi_rhs_exprs)
2385 {
2386 Node *expr = lfirst(lc);
2387 Oid opfamily;
2388
2389 opfamily = cdb_default_distribution_opfamily_for_type(exprType(expr));
2390 opfamilies = lappend_oid(opfamilies, opfamily);
2391 sortrefs = lappend_int(sortrefs, 0);

Callers 6

join_is_legalFunction · 0.85
sort_inner_and_outerFunction · 0.85
match_unsorted_outerFunction · 0.85
hash_inner_and_outerFunction · 0.85

Calls 15

bms_equalFunction · 0.85
MemoryContextSwitchToFunction · 0.85
GetMemoryChunkContextFunction · 0.85
exprTypeFunction · 0.85
lappend_oidFunction · 0.85
lappend_intFunction · 0.85
cdbpathlocus_from_exprsFunction · 0.85
clamp_row_estFunction · 0.85

Tested by

no test coverage detected