1 /*-------------------------------------------------------------------------
2  *
3  * partbounds.c
4  *		Support routines for manipulating partition bounds
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *		  src/backend/partitioning/partbounds.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 
15 #include "postgres.h"
16 
17 #include "access/relation.h"
18 #include "access/table.h"
19 #include "access/tableam.h"
20 #include "catalog/partition.h"
21 #include "catalog/pg_inherits.h"
22 #include "catalog/pg_type.h"
23 #include "commands/tablecmds.h"
24 #include "common/hashfn.h"
25 #include "executor/executor.h"
26 #include "miscadmin.h"
27 #include "nodes/makefuncs.h"
28 #include "nodes/nodeFuncs.h"
29 #include "nodes/pathnodes.h"
30 #include "parser/parse_coerce.h"
31 #include "partitioning/partbounds.h"
32 #include "partitioning/partdesc.h"
33 #include "partitioning/partprune.h"
34 #include "utils/builtins.h"
35 #include "utils/datum.h"
36 #include "utils/fmgroids.h"
downcase_truncate_identifier(const char * ident,int len,bool warn)37 #include "utils/lsyscache.h"
38 #include "utils/partcache.h"
39 #include "utils/ruleutils.h"
40 #include "utils/snapmgr.h"
41 #include "utils/syscache.h"
42 
43 /*
44  * When qsort'ing partition bounds after reading from the catalog, each bound
45  * is represented with one of the following structs.
46  */
47 
48 /* One bound of a hash partition */
49 typedef struct PartitionHashBound
50 {
51 	int			modulus;
52 	int			remainder;
53 	int			index;
54 } PartitionHashBound;
55 
56 /* One value coming from some (index'th) list partition */
57 typedef struct PartitionListValue
58 {
59 	int			index;
60 	Datum		value;
61 } PartitionListValue;
62 
63 /* One bound of a range partition */
64 typedef struct PartitionRangeBound
65 {
66 	int			index;
67 	Datum	   *datums;			/* range bound datums */
68 	PartitionRangeDatumKind *kind;	/* the kind of each datum */
69 	bool		lower;			/* this is the lower (vs upper) bound */
70 } PartitionRangeBound;
71 
72 /*
73  * Mapping from partitions of a joining relation to partitions of a join
74  * relation being computed (a.k.a merged partitions)
75  */
76 typedef struct PartitionMap
77 {
78 	int			nparts;			/* number of partitions */
79 	int		   *merged_indexes; /* indexes of merged partitions */
80 	bool	   *merged;			/* flags to indicate whether partitions are
81 								 * merged with non-dummy partitions */
82 	bool		did_remapping;	/* did we re-map partitions? */
83 	int		   *old_indexes;	/* old indexes of merged partitions if
84 								 * did_remapping */
85 } PartitionMap;
86 
87 /* Macro for comparing two range bounds */
88 #define compare_range_bounds(partnatts, partsupfunc, partcollations, \
89 							 bound1, bound2) \
90 	(partition_rbound_cmp(partnatts, partsupfunc, partcollations, \
91 						  (bound1)->datums, (bound1)->kind, (bound1)->lower, \
92 						  bound2))
truncate_identifier(char * ident,int len,bool warn)93 
94 static int32 qsort_partition_hbound_cmp(const void *a, const void *b);
95 static int32 qsort_partition_list_value_cmp(const void *a, const void *b,
96 											void *arg);
97 static int32 qsort_partition_rbound_cmp(const void *a, const void *b,
98 										void *arg);
99 static PartitionBoundInfo create_hash_bounds(PartitionBoundSpec **boundspecs,
100 											 int nparts, PartitionKey key, int **mapping);
101 static PartitionBoundInfo create_list_bounds(PartitionBoundSpec **boundspecs,
102 											 int nparts, PartitionKey key, int **mapping);
103 static PartitionBoundInfo create_range_bounds(PartitionBoundSpec **boundspecs,
104 											  int nparts, PartitionKey key, int **mapping);
105 static PartitionBoundInfo merge_list_bounds(FmgrInfo *partsupfunc,
106 											Oid *collations,
107 											RelOptInfo *outer_rel,
108 											RelOptInfo *inner_rel,
109 											JoinType jointype,
110 											List **outer_parts,
111 											List **inner_parts);
112 static PartitionBoundInfo merge_range_bounds(int partnatts,
113 											 FmgrInfo *partsupfuncs,
114 											 Oid *partcollations,
115 											 RelOptInfo *outer_rel,
116 											 RelOptInfo *inner_rel,
scanner_isspace(char ch)117 											 JoinType jointype,
118 											 List **outer_parts,
119 											 List **inner_parts);
120 static void init_partition_map(RelOptInfo *rel, PartitionMap *map);
121 static void free_partition_map(PartitionMap *map);
122 static bool is_dummy_partition(RelOptInfo *rel, int part_index);
123 static int	merge_matching_partitions(PartitionMap *outer_map,
124 									  PartitionMap *inner_map,
125 									  int outer_part,
126 									  int inner_part,
127 									  int *next_index);
128 static int	process_outer_partition(PartitionMap *outer_map,
129 									PartitionMap *inner_map,
130 									bool outer_has_default,
131 									bool inner_has_default,
132 									int outer_index,
133 									int inner_default,
134 									JoinType jointype,
135 									int *next_index,
136 									int *default_index);
137 static int	process_inner_partition(PartitionMap *outer_map,
138 									PartitionMap *inner_map,
139 									bool outer_has_default,
140 									bool inner_has_default,
141 									int inner_index,
142 									int outer_default,
143 									JoinType jointype,
144 									int *next_index,
145 									int *default_index);
146 static void merge_null_partitions(PartitionMap *outer_map,
147 								  PartitionMap *inner_map,
148 								  bool outer_has_null,
149 								  bool inner_has_null,
150 								  int outer_null,
151 								  int inner_null,
152 								  JoinType jointype,
153 								  int *next_index,
154 								  int *null_index);
155 static void merge_default_partitions(PartitionMap *outer_map,
156 									 PartitionMap *inner_map,
157 									 bool outer_has_default,
158 									 bool inner_has_default,
159 									 int outer_default,
160 									 int inner_default,
161 									 JoinType jointype,
162 									 int *next_index,
163 									 int *default_index);
164 static int	merge_partition_with_dummy(PartitionMap *map, int index,
165 									   int *next_index);
166 static void fix_merged_indexes(PartitionMap *outer_map,
167 							   PartitionMap *inner_map,
168 							   int nmerged, List *merged_indexes);
169 static void generate_matching_part_pairs(RelOptInfo *outer_rel,
170 										 RelOptInfo *inner_rel,
171 										 PartitionMap *outer_map,
172 										 PartitionMap *inner_map,
173 										 int nmerged,
174 										 List **outer_parts,
175 										 List **inner_parts);
176 static PartitionBoundInfo build_merged_partition_bounds(char strategy,
177 														List *merged_datums,
178 														List *merged_kinds,
179 														List *merged_indexes,
180 														int null_index,
181 														int default_index);
182 static int	get_range_partition(RelOptInfo *rel,
183 								PartitionBoundInfo bi,
184 								int *lb_pos,
185 								PartitionRangeBound *lb,
186 								PartitionRangeBound *ub);
187 static int	get_range_partition_internal(PartitionBoundInfo bi,
188 										 int *lb_pos,
189 										 PartitionRangeBound *lb,
190 										 PartitionRangeBound *ub);
191 static bool compare_range_partitions(int partnatts, FmgrInfo *partsupfuncs,
192 									 Oid *partcollations,
193 									 PartitionRangeBound *outer_lb,
194 									 PartitionRangeBound *outer_ub,
195 									 PartitionRangeBound *inner_lb,
196 									 PartitionRangeBound *inner_ub,
197 									 int *lb_cmpval, int *ub_cmpval);
198 static void get_merged_range_bounds(int partnatts, FmgrInfo *partsupfuncs,
199 									Oid *partcollations, JoinType jointype,
200 									PartitionRangeBound *outer_lb,
201 									PartitionRangeBound *outer_ub,
202 									PartitionRangeBound *inner_lb,
203 									PartitionRangeBound *inner_ub,
204 									int lb_cmpval, int ub_cmpval,
205 									PartitionRangeBound *merged_lb,
206 									PartitionRangeBound *merged_ub);
207 static void add_merged_range_bounds(int partnatts, FmgrInfo *partsupfuncs,
208 									Oid *partcollations,
209 									PartitionRangeBound *merged_lb,
210 									PartitionRangeBound *merged_ub,
211 									int merged_index,
212 									List **merged_datums,
213 									List **merged_kinds,
214 									List **merged_indexes);
215 static PartitionRangeBound *make_one_partition_rbound(PartitionKey key, int index,
216 													  List *datums, bool lower);
217 static int32 partition_hbound_cmp(int modulus1, int remainder1, int modulus2,
218 								  int remainder2);
219 static int32 partition_rbound_cmp(int partnatts, FmgrInfo *partsupfunc,
220 								  Oid *partcollation, Datum *datums1,
221 								  PartitionRangeDatumKind *kind1, bool lower1,
222 								  PartitionRangeBound *b2);
223 static int	partition_range_bsearch(int partnatts, FmgrInfo *partsupfunc,
224 									Oid *partcollation,
225 									PartitionBoundInfo boundinfo,
226 									PartitionRangeBound *probe, int32 *cmpval);
227 static Expr *make_partition_op_expr(PartitionKey key, int keynum,
228 									uint16 strategy, Expr *arg1, Expr *arg2);
229 static Oid	get_partition_operator(PartitionKey key, int col,
230 								   StrategyNumber strategy, bool *need_relabel);
231 static List *get_qual_for_hash(Relation parent, PartitionBoundSpec *spec);
232 static List *get_qual_for_list(Relation parent, PartitionBoundSpec *spec);
233 static List *get_qual_for_range(Relation parent, PartitionBoundSpec *spec,
234 								bool for_default);
235 static void get_range_key_properties(PartitionKey key, int keynum,
236 									 PartitionRangeDatum *ldatum,
237 									 PartitionRangeDatum *udatum,
238 									 ListCell **partexprs_item,
239 									 Expr **keyCol,
240 									 Const **lower_val, Const **upper_val);
241 static List *get_range_nulltest(PartitionKey key);
242 
243 /*
244  * get_qual_from_partbound
245  *		Given a parser node for partition bound, return the list of executable
246  *		expressions as partition constraint
247  */
248 List *
249 get_qual_from_partbound(Relation rel, Relation parent,
250 						PartitionBoundSpec *spec)
251 {
252 	PartitionKey key = RelationGetPartitionKey(parent);
253 	List	   *my_qual = NIL;
254 
255 	Assert(key != NULL);
256 
257 	switch (key->strategy)
258 	{
259 		case PARTITION_STRATEGY_HASH:
260 			Assert(spec->strategy == PARTITION_STRATEGY_HASH);
261 			my_qual = get_qual_for_hash(parent, spec);
262 			break;
263 
264 		case PARTITION_STRATEGY_LIST:
265 			Assert(spec->strategy == PARTITION_STRATEGY_LIST);
266 			my_qual = get_qual_for_list(parent, spec);
267 			break;
268 
269 		case PARTITION_STRATEGY_RANGE:
270 			Assert(spec->strategy == PARTITION_STRATEGY_RANGE);
271 			my_qual = get_qual_for_range(parent, spec, false);
272 			break;
273 
274 		default:
275 			elog(ERROR, "unexpected partition strategy: %d",
276 				 (int) key->strategy);
277 	}
278 
279 	return my_qual;
280 }
281 
282 /*
283  *	partition_bounds_create
284  *		Build a PartitionBoundInfo struct from a list of PartitionBoundSpec
285  *		nodes
286  *
287  * This function creates a PartitionBoundInfo and fills the values of its
288  * various members based on the input list.  Importantly, 'datums' array will
289  * contain Datum representation of individual bounds (possibly after
290  * de-duplication as in case of range bounds), sorted in a canonical order
291  * defined by qsort_partition_* functions of respective partitioning methods.
292  * 'indexes' array will contain as many elements as there are bounds (specific
293  * exceptions to this rule are listed in the function body), which represent
294  * the 0-based canonical positions of partitions.
295  *
296  * Upon return from this function, *mapping is set to an array of
297  * list_length(boundspecs) elements, each of which maps the original index of
298  * a partition to its canonical index.
299  *
300  * Note: The objects returned by this function are wholly allocated in the
301  * current memory context.
302  */
303 PartitionBoundInfo
304 partition_bounds_create(PartitionBoundSpec **boundspecs, int nparts,
305 						PartitionKey key, int **mapping)
306 {
307 	int			i;
308 
309 	Assert(nparts > 0);
310 
311 	/*
312 	 * For each partitioning method, we first convert the partition bounds
313 	 * from their parser node representation to the internal representation,
314 	 * along with any additional preprocessing (such as de-duplicating range
315 	 * bounds).  Resulting bound datums are then added to the 'datums' array
316 	 * in PartitionBoundInfo.  For each datum added, an integer indicating the
317 	 * canonical partition index is added to the 'indexes' array.
318 	 *
319 	 * For each bound, we remember its partition's position (0-based) in the
320 	 * original list to later map it to the canonical index.
321 	 */
322 
323 	/*
324 	 * Initialize mapping array with invalid values, this is filled within
325 	 * each sub-routine below depending on the bound type.
326 	 */
327 	*mapping = (int *) palloc(sizeof(int) * nparts);
328 	for (i = 0; i < nparts; i++)
329 		(*mapping)[i] = -1;
330 
331 	switch (key->strategy)
332 	{
333 		case PARTITION_STRATEGY_HASH:
334 			return create_hash_bounds(boundspecs, nparts, key, mapping);
335 
336 		case PARTITION_STRATEGY_LIST:
337 			return create_list_bounds(boundspecs, nparts, key, mapping);
338 
339 		case PARTITION_STRATEGY_RANGE:
340 			return create_range_bounds(boundspecs, nparts, key, mapping);
341 
342 		default:
343 			elog(ERROR, "unexpected partition strategy: %d",
344 				 (int) key->strategy);
345 			break;
346 	}
347 
348 	Assert(false);
349 	return NULL;				/* keep compiler quiet */
350 }
351 
352 /*
353  * create_hash_bounds
354  *		Create a PartitionBoundInfo for a hash partitioned table
355  */
356 static PartitionBoundInfo
357 create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
358 				   PartitionKey key, int **mapping)
359 {
360 	PartitionBoundInfo boundinfo;
361 	PartitionHashBound **hbounds = NULL;
362 	int			i;
363 	int			ndatums = 0;
364 	int			greatest_modulus;
365 
366 	boundinfo = (PartitionBoundInfoData *)
367 		palloc0(sizeof(PartitionBoundInfoData));
368 	boundinfo->strategy = key->strategy;
369 	/* No special hash partitions. */
370 	boundinfo->null_index = -1;
371 	boundinfo->default_index = -1;
372 
373 	ndatums = nparts;
374 	hbounds = (PartitionHashBound **)
375 		palloc(nparts * sizeof(PartitionHashBound *));
376 
377 	/* Convert from node to the internal representation */
378 	for (i = 0; i < nparts; i++)
379 	{
380 		PartitionBoundSpec *spec = boundspecs[i];
381 
382 		if (spec->strategy != PARTITION_STRATEGY_HASH)
383 			elog(ERROR, "invalid strategy in partition bound spec");
384 
385 		hbounds[i] = (PartitionHashBound *) palloc(sizeof(PartitionHashBound));
386 		hbounds[i]->modulus = spec->modulus;
387 		hbounds[i]->remainder = spec->remainder;
388 		hbounds[i]->index = i;
389 	}
390 
391 	/* Sort all the bounds in ascending order */
392 	qsort(hbounds, nparts, sizeof(PartitionHashBound *),
393 		  qsort_partition_hbound_cmp);
394 
395 	/* After sorting, moduli are now stored in ascending order. */
396 	greatest_modulus = hbounds[ndatums - 1]->modulus;
397 
398 	boundinfo->ndatums = ndatums;
399 	boundinfo->datums = (Datum **) palloc0(ndatums * sizeof(Datum *));
400 	boundinfo->nindexes = greatest_modulus;
401 	boundinfo->indexes = (int *) palloc(greatest_modulus * sizeof(int));
402 	for (i = 0; i < greatest_modulus; i++)
403 		boundinfo->indexes[i] = -1;
404 
405 	/*
406 	 * For hash partitioning, there are as many datums (modulus and remainder
407 	 * pairs) as there are partitions.  Indexes are simply values ranging from
408 	 * 0 to (nparts - 1).
409 	 */
410 	for (i = 0; i < nparts; i++)
411 	{
412 		int			modulus = hbounds[i]->modulus;
413 		int			remainder = hbounds[i]->remainder;
414 
415 		boundinfo->datums[i] = (Datum *) palloc(2 * sizeof(Datum));
416 		boundinfo->datums[i][0] = Int32GetDatum(modulus);
417 		boundinfo->datums[i][1] = Int32GetDatum(remainder);
418 
419 		while (remainder < greatest_modulus)
420 		{
421 			/* overlap? */
422 			Assert(boundinfo->indexes[remainder] == -1);
423 			boundinfo->indexes[remainder] = i;
424 			remainder += modulus;
425 		}
426 
427 		(*mapping)[hbounds[i]->index] = i;
428 		pfree(hbounds[i]);
429 	}
430 	pfree(hbounds);
431 
432 	return boundinfo;
433 }
434 
435 /*
436  * create_list_bounds
437  *		Create a PartitionBoundInfo for a list partitioned table
438  */
439 static PartitionBoundInfo
440 create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
441 				   PartitionKey key, int **mapping)
442 {
443 	PartitionBoundInfo boundinfo;
444 	PartitionListValue **all_values = NULL;
445 	ListCell   *cell;
446 	int			i = 0;
447 	int			ndatums = 0;
448 	int			next_index = 0;
449 	int			default_index = -1;
450 	int			null_index = -1;
451 	List	   *non_null_values = NIL;
452 
453 	boundinfo = (PartitionBoundInfoData *)
454 		palloc0(sizeof(PartitionBoundInfoData));
455 	boundinfo->strategy = key->strategy;
456 	/* Will be set correctly below. */
457 	boundinfo->null_index = -1;
458 	boundinfo->default_index = -1;
459 
460 	/* Create a unified list of non-null values across all partitions. */
461 	for (i = 0; i < nparts; i++)
462 	{
463 		PartitionBoundSpec *spec = boundspecs[i];
464 		ListCell   *c;
465 
466 		if (spec->strategy != PARTITION_STRATEGY_LIST)
467 			elog(ERROR, "invalid strategy in partition bound spec");
468 
469 		/*
470 		 * Note the index of the partition bound spec for the default
471 		 * partition.  There's no datum to add to the list on non-null datums
472 		 * for this partition.
473 		 */
474 		if (spec->is_default)
475 		{
476 			default_index = i;
477 			continue;
478 		}
479 
480 		foreach(c, spec->listdatums)
481 		{
482 			Const	   *val = castNode(Const, lfirst(c));
483 			PartitionListValue *list_value = NULL;
484 
485 			if (!val->constisnull)
486 			{
487 				list_value = (PartitionListValue *)
488 					palloc0(sizeof(PartitionListValue));
489 				list_value->index = i;
490 				list_value->value = val->constvalue;
491 			}
492 			else
493 			{
494 				/*
495 				 * Never put a null into the values array; save the index of
496 				 * the partition that stores nulls, instead.
497 				 */
498 				if (null_index != -1)
499 					elog(ERROR, "found null more than once");
500 				null_index = i;
501 			}
502 
503 			if (list_value)
504 				non_null_values = lappend(non_null_values, list_value);
505 		}
506 	}
507 
508 	ndatums = list_length(non_null_values);
509 
510 	/*
511 	 * Collect all list values in one array. Alongside the value, we also save
512 	 * the index of partition the value comes from.
513 	 */
514 	all_values = (PartitionListValue **)
515 		palloc(ndatums * sizeof(PartitionListValue *));
516 	i = 0;
517 	foreach(cell, non_null_values)
518 	{
519 		PartitionListValue *src = lfirst(cell);
520 
521 		all_values[i] = (PartitionListValue *)
522 			palloc(sizeof(PartitionListValue));
523 		all_values[i]->value = src->value;
524 		all_values[i]->index = src->index;
525 		i++;
526 	}
527 
528 	qsort_arg(all_values, ndatums, sizeof(PartitionListValue *),
529 			  qsort_partition_list_value_cmp, (void *) key);
530 
531 	boundinfo->ndatums = ndatums;
532 	boundinfo->datums = (Datum **) palloc0(ndatums * sizeof(Datum *));
533 	boundinfo->nindexes = ndatums;
534 	boundinfo->indexes = (int *) palloc(ndatums * sizeof(int));
535 
536 	/*
537 	 * Copy values.  Canonical indexes are values ranging from 0 to (nparts -
538 	 * 1) assigned to each partition such that all datums of a given partition
539 	 * receive the same value. The value for a given partition is the index of
540 	 * that partition's smallest datum in the all_values[] array.
541 	 */
542 	for (i = 0; i < ndatums; i++)
543 	{
544 		int			orig_index = all_values[i]->index;
545 
546 		boundinfo->datums[i] = (Datum *) palloc(sizeof(Datum));
547 		boundinfo->datums[i][0] = datumCopy(all_values[i]->value,
548 											key->parttypbyval[0],
549 											key->parttyplen[0]);
550 
551 		/* If the old index has no mapping, assign one */
552 		if ((*mapping)[orig_index] == -1)
553 			(*mapping)[orig_index] = next_index++;
554 
555 		boundinfo->indexes[i] = (*mapping)[orig_index];
556 	}
557 
558 	/*
559 	 * Set the canonical value for null_index, if any.
560 	 *
561 	 * It is possible that the null-accepting partition has not been assigned
562 	 * an index yet, which could happen if such partition accepts only null
563 	 * and hence not handled in the above loop which only looked at non-null
564 	 * values.
565 	 */
566 	if (null_index != -1)
567 	{
568 		Assert(null_index >= 0);
569 		if ((*mapping)[null_index] == -1)
570 			(*mapping)[null_index] = next_index++;
571 		boundinfo->null_index = (*mapping)[null_index];
572 	}
573 
574 	/* Set the canonical value for default_index, if any. */
575 	if (default_index != -1)
576 	{
577 		/*
578 		 * The default partition accepts any value not specified in the lists
579 		 * of other partitions, hence it should not get mapped index while
580 		 * assigning those for non-null datums.
581 		 */
582 		Assert(default_index >= 0);
583 		Assert((*mapping)[default_index] == -1);
584 		(*mapping)[default_index] = next_index++;
585 		boundinfo->default_index = (*mapping)[default_index];
586 	}
587 
588 	/* All partitions must now have been assigned canonical indexes. */
589 	Assert(next_index == nparts);
590 	return boundinfo;
591 }
592 
593 /*
594  * create_range_bounds
595  *		Create a PartitionBoundInfo for a range partitioned table
596  */
597 static PartitionBoundInfo
598 create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
599 					PartitionKey key, int **mapping)
600 {
601 	PartitionBoundInfo boundinfo;
602 	PartitionRangeBound **rbounds = NULL;
603 	PartitionRangeBound **all_bounds,
604 			   *prev;
605 	int			i,
606 				k;
607 	int			ndatums = 0;
608 	int			default_index = -1;
609 	int			next_index = 0;
610 
611 	boundinfo = (PartitionBoundInfoData *)
612 		palloc0(sizeof(PartitionBoundInfoData));
613 	boundinfo->strategy = key->strategy;
614 	/* There is no special null-accepting range partition. */
615 	boundinfo->null_index = -1;
616 	/* Will be set correctly below. */
617 	boundinfo->default_index = -1;
618 
619 	all_bounds = (PartitionRangeBound **)
620 		palloc0(2 * nparts * sizeof(PartitionRangeBound *));
621 
622 	/* Create a unified list of range bounds across all the partitions. */
623 	ndatums = 0;
624 	for (i = 0; i < nparts; i++)
625 	{
626 		PartitionBoundSpec *spec = boundspecs[i];
627 		PartitionRangeBound *lower,
628 				   *upper;
629 
630 		if (spec->strategy != PARTITION_STRATEGY_RANGE)
631 			elog(ERROR, "invalid strategy in partition bound spec");
632 
633 		/*
634 		 * Note the index of the partition bound spec for the default
635 		 * partition.  There's no datum to add to the all_bounds array for
636 		 * this partition.
637 		 */
638 		if (spec->is_default)
639 		{
640 			default_index = i;
641 			continue;
642 		}
643 
644 		lower = make_one_partition_rbound(key, i, spec->lowerdatums, true);
645 		upper = make_one_partition_rbound(key, i, spec->upperdatums, false);
646 		all_bounds[ndatums++] = lower;
647 		all_bounds[ndatums++] = upper;
648 	}
649 
650 	Assert(ndatums == nparts * 2 ||
651 		   (default_index != -1 && ndatums == (nparts - 1) * 2));
652 
653 	/* Sort all the bounds in ascending order */
654 	qsort_arg(all_bounds, ndatums,
655 			  sizeof(PartitionRangeBound *),
656 			  qsort_partition_rbound_cmp,
657 			  (void *) key);
658 
659 	/* Save distinct bounds from all_bounds into rbounds. */
660 	rbounds = (PartitionRangeBound **)
661 		palloc(ndatums * sizeof(PartitionRangeBound *));
662 	k = 0;
663 	prev = NULL;
664 	for (i = 0; i < ndatums; i++)
665 	{
666 		PartitionRangeBound *cur = all_bounds[i];
667 		bool		is_distinct = false;
668 		int			j;
669 
670 		/* Is the current bound distinct from the previous one? */
671 		for (j = 0; j < key->partnatts; j++)
672 		{
673 			Datum		cmpval;
674 
675 			if (prev == NULL || cur->kind[j] != prev->kind[j])
676 			{
677 				is_distinct = true;
678 				break;
679 			}
680 
681 			/*
682 			 * If the bounds are both MINVALUE or MAXVALUE, stop now and treat
683 			 * them as equal, since any values after this point must be
684 			 * ignored.
685 			 */
686 			if (cur->kind[j] != PARTITION_RANGE_DATUM_VALUE)
687 				break;
688 
689 			cmpval = FunctionCall2Coll(&key->partsupfunc[j],
690 									   key->partcollation[j],
691 									   cur->datums[j],
692 									   prev->datums[j]);
693 			if (DatumGetInt32(cmpval) != 0)
694 			{
695 				is_distinct = true;
696 				break;
697 			}
698 		}
699 
700 		/*
701 		 * Only if the bound is distinct save it into a temporary array, i.e,
702 		 * rbounds which is later copied into boundinfo datums array.
703 		 */
704 		if (is_distinct)
705 			rbounds[k++] = all_bounds[i];
706 
707 		prev = cur;
708 	}
709 
710 	/* Update ndatums to hold the count of distinct datums. */
711 	ndatums = k;
712 
713 	/*
714 	 * Add datums to boundinfo.  Canonical indexes are values ranging from 0
715 	 * to nparts - 1, assigned in that order to each partition's upper bound.
716 	 * For 'datums' elements that are lower bounds, there is -1 in the
717 	 * 'indexes' array to signify that no partition exists for the values less
718 	 * than such a bound and greater than or equal to the previous upper
719 	 * bound.
720 	 */
721 	boundinfo->ndatums = ndatums;
722 	boundinfo->datums = (Datum **) palloc0(ndatums * sizeof(Datum *));
723 	boundinfo->kind = (PartitionRangeDatumKind **)
724 		palloc(ndatums *
725 			   sizeof(PartitionRangeDatumKind *));
726 
727 	/*
728 	 * For range partitioning, an additional value of -1 is stored as the last
729 	 * element of the indexes[] array.
730 	 */
731 	boundinfo->nindexes = ndatums + 1;
732 	boundinfo->indexes = (int *) palloc((ndatums + 1) * sizeof(int));
733 
734 	for (i = 0; i < ndatums; i++)
735 	{
736 		int			j;
737 
738 		boundinfo->datums[i] = (Datum *) palloc(key->partnatts *
739 												sizeof(Datum));
740 		boundinfo->kind[i] = (PartitionRangeDatumKind *)
741 			palloc(key->partnatts *
742 				   sizeof(PartitionRangeDatumKind));
743 		for (j = 0; j < key->partnatts; j++)
744 		{
745 			if (rbounds[i]->kind[j] == PARTITION_RANGE_DATUM_VALUE)
746 				boundinfo->datums[i][j] =
747 					datumCopy(rbounds[i]->datums[j],
748 							  key->parttypbyval[j],
749 							  key->parttyplen[j]);
750 			boundinfo->kind[i][j] = rbounds[i]->kind[j];
751 		}
752 
753 		/*
754 		 * There is no mapping for invalid indexes.
755 		 *
756 		 * Any lower bounds in the rbounds array have invalid indexes
757 		 * assigned, because the values between the previous bound (if there
758 		 * is one) and this (lower) bound are not part of the range of any
759 		 * existing partition.
760 		 */
761 		if (rbounds[i]->lower)
762 			boundinfo->indexes[i] = -1;
763 		else
764 		{
765 			int			orig_index = rbounds[i]->index;
766 
767 			/* If the old index has no mapping, assign one */
768 			if ((*mapping)[orig_index] == -1)
769 				(*mapping)[orig_index] = next_index++;
770 
771 			boundinfo->indexes[i] = (*mapping)[orig_index];
772 		}
773 	}
774 
775 	/* Set the canonical value for default_index, if any. */
776 	if (default_index != -1)
777 	{
778 		Assert(default_index >= 0 && (*mapping)[default_index] == -1);
779 		(*mapping)[default_index] = next_index++;
780 		boundinfo->default_index = (*mapping)[default_index];
781 	}
782 
783 	/* The extra -1 element. */
784 	Assert(i == ndatums);
785 	boundinfo->indexes[i] = -1;
786 
787 	/* All partitions must now have been assigned canonical indexes. */
788 	Assert(next_index == nparts);
789 	return boundinfo;
790 }
791 
792 /*
793  * Are two partition bound collections logically equal?
794  *
795  * Used in the keep logic of relcache.c (ie, in RelationClearRelation()).
796  * This is also useful when b1 and b2 are bound collections of two separate
797  * relations, respectively, because PartitionBoundInfo is a canonical
798  * representation of partition bounds.
799  */
800 bool
801 partition_bounds_equal(int partnatts, int16 *parttyplen, bool *parttypbyval,
802 					   PartitionBoundInfo b1, PartitionBoundInfo b2)
803 {
804 	int			i;
805 
806 	if (b1->strategy != b2->strategy)
807 		return false;
808 
809 	if (b1->ndatums != b2->ndatums)
810 		return false;
811 
812 	if (b1->nindexes != b2->nindexes)
813 		return false;
814 
815 	if (b1->null_index != b2->null_index)
816 		return false;
817 
818 	if (b1->default_index != b2->default_index)
819 		return false;
820 
821 	/* For all partition strategies, the indexes[] arrays have to match */
822 	for (i = 0; i < b1->nindexes; i++)
823 	{
824 		if (b1->indexes[i] != b2->indexes[i])
825 			return false;
826 	}
827 
828 	/* Finally, compare the datums[] arrays */
829 	if (b1->strategy == PARTITION_STRATEGY_HASH)
830 	{
831 		/*
832 		 * We arrange the partitions in the ascending order of their moduli
833 		 * and remainders.  Also every modulus is factor of next larger
834 		 * modulus.  Therefore we can safely store index of a given partition
835 		 * in indexes array at remainder of that partition.  Also entries at
836 		 * (remainder + N * modulus) positions in indexes array are all same
837 		 * for (modulus, remainder) specification for any partition.  Thus the
838 		 * datums arrays from the given bounds are the same, if and only if
839 		 * their indexes arrays are the same.  So, it suffices to compare the
840 		 * indexes arrays.
841 		 *
842 		 * Nonetheless make sure that the bounds are indeed the same when the
843 		 * indexes match.  Hash partition bound stores modulus and remainder
844 		 * at b1->datums[i][0] and b1->datums[i][1] position respectively.
845 		 */
846 #ifdef USE_ASSERT_CHECKING
847 		for (i = 0; i < b1->ndatums; i++)
848 			Assert((b1->datums[i][0] == b2->datums[i][0] &&
849 					b1->datums[i][1] == b2->datums[i][1]));
850 #endif
851 	}
852 	else
853 	{
854 		for (i = 0; i < b1->ndatums; i++)
855 		{
856 			int			j;
857 
858 			for (j = 0; j < partnatts; j++)
859 			{
860 				/* For range partitions, the bounds might not be finite. */
861 				if (b1->kind != NULL)
862 				{
863 					/* The different kinds of bound all differ from each other */
864 					if (b1->kind[i][j] != b2->kind[i][j])
865 						return false;
866 
867 					/*
868 					 * Non-finite bounds are equal without further
869 					 * examination.
870 					 */
871 					if (b1->kind[i][j] != PARTITION_RANGE_DATUM_VALUE)
872 						continue;
873 				}
874 
875 				/*
876 				 * Compare the actual values. Note that it would be both
877 				 * incorrect and unsafe to invoke the comparison operator
878 				 * derived from the partitioning specification here.  It would
879 				 * be incorrect because we want the relcache entry to be
880 				 * updated for ANY change to the partition bounds, not just
881 				 * those that the partitioning operator thinks are
882 				 * significant.  It would be unsafe because we might reach
883 				 * this code in the context of an aborted transaction, and an
884 				 * arbitrary partitioning operator might not be safe in that
885 				 * context.  datumIsEqual() should be simple enough to be
886 				 * safe.
887 				 */
888 				if (!datumIsEqual(b1->datums[i][j], b2->datums[i][j],
889 								  parttypbyval[j], parttyplen[j]))
890 					return false;
891 			}
892 		}
893 	}
894 	return true;
895 }
896 
897 /*
898  * Return a copy of given PartitionBoundInfo structure. The data types of bounds
899  * are described by given partition key specification.
900  *
901  * Note: it's important that this function and its callees not do any catalog
902  * access, nor anything else that would result in allocating memory other than
903  * the returned data structure.  Since this is called in a long-lived context,
904  * that would result in unwanted memory leaks.
905  */
906 PartitionBoundInfo
907 partition_bounds_copy(PartitionBoundInfo src,
908 					  PartitionKey key)
909 {
910 	PartitionBoundInfo dest;
911 	int			i;
912 	int			ndatums;
913 	int			nindexes;
914 	int			partnatts;
915 	bool		hash_part;
916 	int			natts;
917 
918 	dest = (PartitionBoundInfo) palloc(sizeof(PartitionBoundInfoData));
919 
920 	dest->strategy = src->strategy;
921 	ndatums = dest->ndatums = src->ndatums;
922 	nindexes = dest->nindexes = src->nindexes;
923 	partnatts = key->partnatts;
924 
925 	/* List partitioned tables have only a single partition key. */
926 	Assert(key->strategy != PARTITION_STRATEGY_LIST || partnatts == 1);
927 
928 	dest->datums = (Datum **) palloc(sizeof(Datum *) * ndatums);
929 
930 	if (src->kind != NULL)
931 	{
932 		dest->kind = (PartitionRangeDatumKind **) palloc(ndatums *
933 														 sizeof(PartitionRangeDatumKind *));
934 		for (i = 0; i < ndatums; i++)
935 		{
936 			dest->kind[i] = (PartitionRangeDatumKind *) palloc(partnatts *
937 															   sizeof(PartitionRangeDatumKind));
938 
939 			memcpy(dest->kind[i], src->kind[i],
940 				   sizeof(PartitionRangeDatumKind) * key->partnatts);
941 		}
942 	}
943 	else
944 		dest->kind = NULL;
945 
946 	/*
947 	 * For hash partitioning, datums array will have two elements - modulus
948 	 * and remainder.
949 	 */
950 	hash_part = (key->strategy == PARTITION_STRATEGY_HASH);
951 	natts = hash_part ? 2 : partnatts;
952 
953 	for (i = 0; i < ndatums; i++)
954 	{
955 		int			j;
956 
957 		dest->datums[i] = (Datum *) palloc(sizeof(Datum) * natts);
958 
959 		for (j = 0; j < natts; j++)
960 		{
961 			bool		byval;
962 			int			typlen;
963 
964 			if (hash_part)
965 			{
966 				typlen = sizeof(int32); /* Always int4 */
967 				byval = true;	/* int4 is pass-by-value */
968 			}
969 			else
970 			{
971 				byval = key->parttypbyval[j];
972 				typlen = key->parttyplen[j];
973 			}
974 
975 			if (dest->kind == NULL ||
976 				dest->kind[i][j] == PARTITION_RANGE_DATUM_VALUE)
977 				dest->datums[i][j] = datumCopy(src->datums[i][j],
978 											   byval, typlen);
979 		}
980 	}
981 
982 	dest->indexes = (int *) palloc(sizeof(int) * nindexes);
983 	memcpy(dest->indexes, src->indexes, sizeof(int) * nindexes);
984 
985 	dest->null_index = src->null_index;
986 	dest->default_index = src->default_index;
987 
988 	return dest;
989 }
990 
991 /*
992  * partition_bounds_merge
993  *		Check to see whether every partition of 'outer_rel' matches/overlaps
994  *		one partition of 'inner_rel' at most, and vice versa; and if so, build
995  *		and return the partition bounds for a join relation between the rels,
996  *		generating two lists of the matching/overlapping partitions, which are
997  *		returned to *outer_parts and *inner_parts respectively.
998  *
999  * The lists contain the same number of partitions, and the partitions at the
1000  * same positions in the lists indicate join pairs used for partitioned join.
1001  * If a partition on one side matches/overlaps multiple partitions on the other
1002  * side, this function returns NULL, setting *outer_parts and *inner_parts to
1003  * NIL.
1004  */
1005 PartitionBoundInfo
1006 partition_bounds_merge(int partnatts,
1007 					   FmgrInfo *partsupfunc, Oid *partcollation,
1008 					   RelOptInfo *outer_rel, RelOptInfo *inner_rel,
1009 					   JoinType jointype,
1010 					   List **outer_parts, List **inner_parts)
1011 {
1012 	/*
1013 	 * Currently, this function is called only from try_partitionwise_join(),
1014 	 * so the join type should be INNER, LEFT, FULL, SEMI, or ANTI.
1015 	 */
1016 	Assert(jointype == JOIN_INNER || jointype == JOIN_LEFT ||
1017 		   jointype == JOIN_FULL || jointype == JOIN_SEMI ||
1018 		   jointype == JOIN_ANTI);
1019 
1020 	/* The partitioning strategies should be the same. */
1021 	Assert(outer_rel->boundinfo->strategy == inner_rel->boundinfo->strategy);
1022 
1023 	*outer_parts = *inner_parts = NIL;
1024 	switch (outer_rel->boundinfo->strategy)
1025 	{
1026 		case PARTITION_STRATEGY_HASH:
1027 
1028 			/*
1029 			 * For hash partitioned tables, we currently support partitioned
1030 			 * join only when they have exactly the same partition bounds.
1031 			 *
1032 			 * XXX: it might be possible to relax the restriction to support
1033 			 * cases where hash partitioned tables have missing partitions
1034 			 * and/or different moduli, but it's not clear if it would be
1035 			 * useful to support the former case since it's unusual to have
1036 			 * missing partitions.  On the other hand, it would be useful to
1037 			 * support the latter case, but in that case, there is a high
1038 			 * probability that a partition on one side will match multiple
1039 			 * partitions on the other side, which is the scenario the current
1040 			 * implementation of partitioned join can't handle.
1041 			 */
1042 			return NULL;
1043 
1044 		case PARTITION_STRATEGY_LIST:
1045 			return merge_list_bounds(partsupfunc,
1046 									 partcollation,
1047 									 outer_rel,
1048 									 inner_rel,
1049 									 jointype,
1050 									 outer_parts,
1051 									 inner_parts);
1052 
1053 		case PARTITION_STRATEGY_RANGE:
1054 			return merge_range_bounds(partnatts,
1055 									  partsupfunc,
1056 									  partcollation,
1057 									  outer_rel,
1058 									  inner_rel,
1059 									  jointype,
1060 									  outer_parts,
1061 									  inner_parts);
1062 
1063 		default:
1064 			elog(ERROR, "unexpected partition strategy: %d",
1065 				 (int) outer_rel->boundinfo->strategy);
1066 			return NULL;		/* keep compiler quiet */
1067 	}
1068 }
1069 
1070 /*
1071  * merge_list_bounds
1072  *		Create the partition bounds for a join relation between list
1073  *		partitioned tables, if possible
1074  *
1075  * In this function we try to find sets of matching partitions from both sides
1076  * by comparing list values stored in their partition bounds.  Since the list
1077  * values appear in the ascending order, an algorithm similar to merge join is
1078  * used for that.  If a partition on one side doesn't have a matching
1079  * partition on the other side, the algorithm tries to match it with the
1080  * default partition on the other side if any; if not, the algorithm tries to
1081  * match it with a dummy partition on the other side if it's on the
1082  * non-nullable side of an outer join.  Also, if both sides have the default
1083  * partitions, the algorithm tries to match them with each other.  We give up
1084  * if the algorithm finds a partition matching multiple partitions on the
1085  * other side, which is the scenario the current implementation of partitioned
1086  * join can't handle.
1087  */
1088 static PartitionBoundInfo
1089 merge_list_bounds(FmgrInfo *partsupfunc, Oid *partcollation,
1090 				  RelOptInfo *outer_rel, RelOptInfo *inner_rel,
1091 				  JoinType jointype,
1092 				  List **outer_parts, List **inner_parts)
1093 {
1094 	PartitionBoundInfo merged_bounds = NULL;
1095 	PartitionBoundInfo outer_bi = outer_rel->boundinfo;
1096 	PartitionBoundInfo inner_bi = inner_rel->boundinfo;
1097 	bool		outer_has_default = partition_bound_has_default(outer_bi);
1098 	bool		inner_has_default = partition_bound_has_default(inner_bi);
1099 	int			outer_default = outer_bi->default_index;
1100 	int			inner_default = inner_bi->default_index;
1101 	bool		outer_has_null = partition_bound_accepts_nulls(outer_bi);
1102 	bool		inner_has_null = partition_bound_accepts_nulls(inner_bi);
1103 	PartitionMap outer_map;
1104 	PartitionMap inner_map;
1105 	int			outer_pos;
1106 	int			inner_pos;
1107 	int			next_index = 0;
1108 	int			null_index = -1;
1109 	int			default_index = -1;
1110 	List	   *merged_datums = NIL;
1111 	List	   *merged_indexes = NIL;
1112 
1113 	Assert(*outer_parts == NIL);
1114 	Assert(*inner_parts == NIL);
1115 	Assert(outer_bi->strategy == inner_bi->strategy &&
1116 		   outer_bi->strategy == PARTITION_STRATEGY_LIST);
1117 	/* List partitioning doesn't require kinds. */
1118 	Assert(!outer_bi->kind && !inner_bi->kind);
1119 
1120 	init_partition_map(outer_rel, &outer_map);
1121 	init_partition_map(inner_rel, &inner_map);
1122 
1123 	/*
1124 	 * If the default partitions (if any) have been proven empty, deem them
1125 	 * non-existent.
1126 	 */
1127 	if (outer_has_default && is_dummy_partition(outer_rel, outer_default))
1128 		outer_has_default = false;
1129 	if (inner_has_default && is_dummy_partition(inner_rel, inner_default))
1130 		inner_has_default = false;
1131 
1132 	/*
1133 	 * Merge partitions from both sides.  In each iteration we compare a pair
1134 	 * of list values, one from each side, and decide whether the
1135 	 * corresponding partitions match or not.  If the two values match
1136 	 * exactly, move to the next pair of list values, otherwise move to the
1137 	 * next list value on the side with a smaller list value.
1138 	 */
1139 	outer_pos = inner_pos = 0;
1140 	while (outer_pos < outer_bi->ndatums || inner_pos < inner_bi->ndatums)
1141 	{
1142 		int			outer_index = -1;
1143 		int			inner_index = -1;
1144 		Datum	   *outer_datums;
1145 		Datum	   *inner_datums;
1146 		int			cmpval;
1147 		Datum	   *merged_datum = NULL;
1148 		int			merged_index = -1;
1149 
1150 		if (outer_pos < outer_bi->ndatums)
1151 		{
1152 			/*
1153 			 * If the partition on the outer side has been proven empty,
1154 			 * ignore it and move to the next datum on the outer side.
1155 			 */
1156 			outer_index = outer_bi->indexes[outer_pos];
1157 			if (is_dummy_partition(outer_rel, outer_index))
1158 			{
1159 				outer_pos++;
1160 				continue;
1161 			}
1162 		}
1163 		if (inner_pos < inner_bi->ndatums)
1164 		{
1165 			/*
1166 			 * If the partition on the inner side has been proven empty,
1167 			 * ignore it and move to the next datum on the inner side.
1168 			 */
1169 			inner_index = inner_bi->indexes[inner_pos];
1170 			if (is_dummy_partition(inner_rel, inner_index))
1171 			{
1172 				inner_pos++;
1173 				continue;
1174 			}
1175 		}
1176 
1177 		/* Get the list values. */
1178 		outer_datums = outer_pos < outer_bi->ndatums ?
1179 			outer_bi->datums[outer_pos] : NULL;
1180 		inner_datums = inner_pos < inner_bi->ndatums ?
1181 			inner_bi->datums[inner_pos] : NULL;
1182 
1183 		/*
1184 		 * We run this loop till both sides finish.  This allows us to avoid
1185 		 * duplicating code to handle the remaining values on the side which
1186 		 * finishes later.  For that we set the comparison parameter cmpval in
1187 		 * such a way that it appears as if the side which finishes earlier
1188 		 * has an extra value higher than any other value on the unfinished
1189 		 * side. That way we advance the values on the unfinished side till
1190 		 * all of its values are exhausted.
1191 		 */
1192 		if (outer_pos >= outer_bi->ndatums)
1193 			cmpval = 1;
1194 		else if (inner_pos >= inner_bi->ndatums)
1195 			cmpval = -1;
1196 		else
1197 		{
1198 			Assert(outer_datums != NULL && inner_datums != NULL);
1199 			cmpval = DatumGetInt32(FunctionCall2Coll(&partsupfunc[0],
1200 													 partcollation[0],
1201 													 outer_datums[0],
1202 													 inner_datums[0]));
1203 		}
1204 
1205 		if (cmpval == 0)
1206 		{
1207 			/* Two list values match exactly. */
1208 			Assert(outer_pos < outer_bi->ndatums);
1209 			Assert(inner_pos < inner_bi->ndatums);
1210 			Assert(outer_index >= 0);
1211 			Assert(inner_index >= 0);
1212 
1213 			/*
1214 			 * Try merging both partitions.  If successful, add the list value
1215 			 * and index of the merged partition below.
1216 			 */
1217 			merged_index = merge_matching_partitions(&outer_map, &inner_map,
1218 													 outer_index, inner_index,
1219 													 &next_index);
1220 			if (merged_index == -1)
1221 				goto cleanup;
1222 
1223 			merged_datum = outer_datums;
1224 
1225 			/* Move to the next pair of list values. */
1226 			outer_pos++;
1227 			inner_pos++;
1228 		}
1229 		else if (cmpval < 0)
1230 		{
1231 			/* A list value missing from the inner side. */
1232 			Assert(outer_pos < outer_bi->ndatums);
1233 
1234 			/*
1235 			 * If the inner side has the default partition, or this is an
1236 			 * outer join, try to assign a merged partition to the outer
1237 			 * partition (see process_outer_partition()).  Otherwise, the
1238 			 * outer partition will not contribute to the result.
1239 			 */
1240 			if (inner_has_default || IS_OUTER_JOIN(jointype))
1241 			{
1242 				/* Get the outer partition. */
1243 				outer_index = outer_bi->indexes[outer_pos];
1244 				Assert(outer_index >= 0);
1245 				merged_index = process_outer_partition(&outer_map,
1246 													   &inner_map,
1247 													   outer_has_default,
1248 													   inner_has_default,
1249 													   outer_index,
1250 													   inner_default,
1251 													   jointype,
1252 													   &next_index,
1253 													   &default_index);
1254 				if (merged_index == -1)
1255 					goto cleanup;
1256 				merged_datum = outer_datums;
1257 			}
1258 
1259 			/* Move to the next list value on the outer side. */
1260 			outer_pos++;
1261 		}
1262 		else
1263 		{
1264 			/* A list value missing from the outer side. */
1265 			Assert(cmpval > 0);
1266 			Assert(inner_pos < inner_bi->ndatums);
1267 
1268 			/*
1269 			 * If the outer side has the default partition, or this is a FULL
1270 			 * join, try to assign a merged partition to the inner partition
1271 			 * (see process_inner_partition()).  Otherwise, the inner
1272 			 * partition will not contribute to the result.
1273 			 */
1274 			if (outer_has_default || jointype == JOIN_FULL)
1275 			{
1276 				/* Get the inner partition. */
1277 				inner_index = inner_bi->indexes[inner_pos];
1278 				Assert(inner_index >= 0);
1279 				merged_index = process_inner_partition(&outer_map,
1280 													   &inner_map,
1281 													   outer_has_default,
1282 													   inner_has_default,
1283 													   inner_index,
1284 													   outer_default,
1285 													   jointype,
1286 													   &next_index,
1287 													   &default_index);
1288 				if (merged_index == -1)
1289 					goto cleanup;
1290 				merged_datum = inner_datums;
1291 			}
1292 
1293 			/* Move to the next list value on the inner side. */
1294 			inner_pos++;
1295 		}
1296 
1297 		/*
1298 		 * If we assigned a merged partition, add the list value and index of
1299 		 * the merged partition if appropriate.
1300 		 */
1301 		if (merged_index >= 0 && merged_index != default_index)
1302 		{
1303 			merged_datums = lappend(merged_datums, merged_datum);
1304 			merged_indexes = lappend_int(merged_indexes, merged_index);
1305 		}
1306 	}
1307 
1308 	/*
1309 	 * If the NULL partitions (if any) have been proven empty, deem them
1310 	 * non-existent.
1311 	 */
1312 	if (outer_has_null &&
1313 		is_dummy_partition(outer_rel, outer_bi->null_index))
1314 		outer_has_null = false;
1315 	if (inner_has_null &&
1316 		is_dummy_partition(inner_rel, inner_bi->null_index))
1317 		inner_has_null = false;
1318 
1319 	/* Merge the NULL partitions if any. */
1320 	if (outer_has_null || inner_has_null)
1321 		merge_null_partitions(&outer_map, &inner_map,
1322 							  outer_has_null, inner_has_null,
1323 							  outer_bi->null_index, inner_bi->null_index,
1324 							  jointype, &next_index, &null_index);
1325 	else
1326 		Assert(null_index == -1);
1327 
1328 	/* Merge the default partitions if any. */
1329 	if (outer_has_default || inner_has_default)
1330 		merge_default_partitions(&outer_map, &inner_map,
1331 								 outer_has_default, inner_has_default,
1332 								 outer_default, inner_default,
1333 								 jointype, &next_index, &default_index);
1334 	else
1335 		Assert(default_index == -1);
1336 
1337 	/* If we have merged partitions, create the partition bounds. */
1338 	if (next_index > 0)
1339 	{
1340 		/* Fix the merged_indexes list if necessary. */
1341 		if (outer_map.did_remapping || inner_map.did_remapping)
1342 		{
1343 			Assert(jointype == JOIN_FULL);
1344 			fix_merged_indexes(&outer_map, &inner_map,
1345 							   next_index, merged_indexes);
1346 		}
1347 
1348 		/* Use maps to match partitions from inputs. */
1349 		generate_matching_part_pairs(outer_rel, inner_rel,
1350 									 &outer_map, &inner_map,
1351 									 next_index,
1352 									 outer_parts, inner_parts);
1353 		Assert(*outer_parts != NIL);
1354 		Assert(*inner_parts != NIL);
1355 		Assert(list_length(*outer_parts) == list_length(*inner_parts));
1356 		Assert(list_length(*outer_parts) <= next_index);
1357 
1358 		/* Make a PartitionBoundInfo struct to return. */
1359 		merged_bounds = build_merged_partition_bounds(outer_bi->strategy,
1360 													  merged_datums,
1361 													  NIL,
1362 													  merged_indexes,
1363 													  null_index,
1364 													  default_index);
1365 		Assert(merged_bounds);
1366 	}
1367 
1368 cleanup:
1369 	/* Free local memory before returning. */
1370 	list_free(merged_datums);
1371 	list_free(merged_indexes);
1372 	free_partition_map(&outer_map);
1373 	free_partition_map(&inner_map);
1374 
1375 	return merged_bounds;
1376 }
1377 
1378 /*
1379  * merge_range_bounds
1380  *		Create the partition bounds for a join relation between range
1381  *		partitioned tables, if possible
1382  *
1383  * In this function we try to find sets of overlapping partitions from both
1384  * sides by comparing ranges stored in their partition bounds.  Since the
1385  * ranges appear in the ascending order, an algorithm similar to merge join is
1386  * used for that.  If a partition on one side doesn't have an overlapping
1387  * partition on the other side, the algorithm tries to match it with the
1388  * default partition on the other side if any; if not, the algorithm tries to
1389  * match it with a dummy partition on the other side if it's on the
1390  * non-nullable side of an outer join.  Also, if both sides have the default
1391  * partitions, the algorithm tries to match them with each other.  We give up
1392  * if the algorithm finds a partition overlapping multiple partitions on the
1393  * other side, which is the scenario the current implementation of partitioned
1394  * join can't handle.
1395  */
1396 static PartitionBoundInfo
1397 merge_range_bounds(int partnatts, FmgrInfo *partsupfuncs,
1398 				   Oid *partcollations,
1399 				   RelOptInfo *outer_rel, RelOptInfo *inner_rel,
1400 				   JoinType jointype,
1401 				   List **outer_parts, List **inner_parts)
1402 {
1403 	PartitionBoundInfo merged_bounds = NULL;
1404 	PartitionBoundInfo outer_bi = outer_rel->boundinfo;
1405 	PartitionBoundInfo inner_bi = inner_rel->boundinfo;
1406 	bool		outer_has_default = partition_bound_has_default(outer_bi);
1407 	bool		inner_has_default = partition_bound_has_default(inner_bi);
1408 	int			outer_default = outer_bi->default_index;
1409 	int			inner_default = inner_bi->default_index;
1410 	PartitionMap outer_map;
1411 	PartitionMap inner_map;
1412 	int			outer_index;
1413 	int			inner_index;
1414 	int			outer_lb_pos;
1415 	int			inner_lb_pos;
1416 	PartitionRangeBound outer_lb;
1417 	PartitionRangeBound outer_ub;
1418 	PartitionRangeBound inner_lb;
1419 	PartitionRangeBound inner_ub;
1420 	int			next_index = 0;
1421 	int			default_index = -1;
1422 	List	   *merged_datums = NIL;
1423 	List	   *merged_kinds = NIL;
1424 	List	   *merged_indexes = NIL;
1425 
1426 	Assert(*outer_parts == NIL);
1427 	Assert(*inner_parts == NIL);
1428 	Assert(outer_bi->strategy == inner_bi->strategy &&
1429 		   outer_bi->strategy == PARTITION_STRATEGY_RANGE);
1430 
1431 	init_partition_map(outer_rel, &outer_map);
1432 	init_partition_map(inner_rel, &inner_map);
1433 
1434 	/*
1435 	 * If the default partitions (if any) have been proven empty, deem them
1436 	 * non-existent.
1437 	 */
1438 	if (outer_has_default && is_dummy_partition(outer_rel, outer_default))
1439 		outer_has_default = false;
1440 	if (inner_has_default && is_dummy_partition(inner_rel, inner_default))
1441 		inner_has_default = false;
1442 
1443 	/*
1444 	 * Merge partitions from both sides.  In each iteration we compare a pair
1445 	 * of ranges, one from each side, and decide whether the corresponding
1446 	 * partitions match or not.  If the two ranges overlap, move to the next
1447 	 * pair of ranges, otherwise move to the next range on the side with a
1448 	 * lower range.  outer_lb_pos/inner_lb_pos keep track of the positions of
1449 	 * lower bounds in the datums arrays in the outer/inner
1450 	 * PartitionBoundInfos respectively.
1451 	 */
1452 	outer_lb_pos = inner_lb_pos = 0;
1453 	outer_index = get_range_partition(outer_rel, outer_bi, &outer_lb_pos,
1454 									  &outer_lb, &outer_ub);
1455 	inner_index = get_range_partition(inner_rel, inner_bi, &inner_lb_pos,
1456 									  &inner_lb, &inner_ub);
1457 	while (outer_index >= 0 || inner_index >= 0)
1458 	{
1459 		bool		overlap;
1460 		int			ub_cmpval;
1461 		int			lb_cmpval;
1462 		PartitionRangeBound merged_lb = {-1, NULL, NULL, true};
1463 		PartitionRangeBound merged_ub = {-1, NULL, NULL, false};
1464 		int			merged_index = -1;
1465 
1466 		/*
1467 		 * We run this loop till both sides finish.  This allows us to avoid
1468 		 * duplicating code to handle the remaining ranges on the side which
1469 		 * finishes later.  For that we set the comparison parameter cmpval in
1470 		 * such a way that it appears as if the side which finishes earlier
1471 		 * has an extra range higher than any other range on the unfinished
1472 		 * side. That way we advance the ranges on the unfinished side till
1473 		 * all of its ranges are exhausted.
1474 		 */
1475 		if (outer_index == -1)
1476 		{
1477 			overlap = false;
1478 			lb_cmpval = 1;
1479 			ub_cmpval = 1;
1480 		}
1481 		else if (inner_index == -1)
1482 		{
1483 			overlap = false;
1484 			lb_cmpval = -1;
1485 			ub_cmpval = -1;
1486 		}
1487 		else
1488 			overlap = compare_range_partitions(partnatts, partsupfuncs,
1489 											   partcollations,
1490 											   &outer_lb, &outer_ub,
1491 											   &inner_lb, &inner_ub,
1492 											   &lb_cmpval, &ub_cmpval);
1493 
1494 		if (overlap)
1495 		{
1496 			/* Two ranges overlap; form a join pair. */
1497 
1498 			PartitionRangeBound save_outer_ub;
1499 			PartitionRangeBound save_inner_ub;
1500 
1501 			/* Both partitions should not have been merged yet. */
1502 			Assert(outer_index >= 0);
1503 			Assert(outer_map.merged_indexes[outer_index] == -1 &&
1504 				   outer_map.merged[outer_index] == false);
1505 			Assert(inner_index >= 0);
1506 			Assert(inner_map.merged_indexes[inner_index] == -1 &&
1507 				   inner_map.merged[inner_index] == false);
1508 
1509 			/*
1510 			 * Get the index of the merged partition.  Both partitions aren't
1511 			 * merged yet, so the partitions should be merged successfully.
1512 			 */
1513 			merged_index = merge_matching_partitions(&outer_map, &inner_map,
1514 													 outer_index, inner_index,
1515 													 &next_index);
1516 			Assert(merged_index >= 0);
1517 
1518 			/* Get the range bounds of the merged partition. */
1519 			get_merged_range_bounds(partnatts, partsupfuncs,
1520 									partcollations, jointype,
1521 									&outer_lb, &outer_ub,
1522 									&inner_lb, &inner_ub,
1523 									lb_cmpval, ub_cmpval,
1524 									&merged_lb, &merged_ub);
1525 
1526 			/* Save the upper bounds of both partitions for use below. */
1527 			save_outer_ub = outer_ub;
1528 			save_inner_ub = inner_ub;
1529 
1530 			/* Move to the next pair of ranges. */
1531 			outer_index = get_range_partition(outer_rel, outer_bi, &outer_lb_pos,
1532 											  &outer_lb, &outer_ub);
1533 			inner_index = get_range_partition(inner_rel, inner_bi, &inner_lb_pos,
1534 											  &inner_lb, &inner_ub);
1535 
1536 			/*
1537 			 * If the range of a partition on one side overlaps the range of
1538 			 * the next partition on the other side, that will cause the
1539 			 * partition on one side to match at least two partitions on the
1540 			 * other side, which is the case that we currently don't support
1541 			 * partitioned join for; give up.
1542 			 */
1543 			if (ub_cmpval > 0 && inner_index >= 0 &&
1544 				compare_range_bounds(partnatts, partsupfuncs, partcollations,
1545 									 &save_outer_ub, &inner_lb) > 0)
1546 				goto cleanup;
1547 			if (ub_cmpval < 0 && outer_index >= 0 &&
1548 				compare_range_bounds(partnatts, partsupfuncs, partcollations,
1549 									 &outer_lb, &save_inner_ub) < 0)
1550 				goto cleanup;
1551 
1552 			/*
1553 			 * A row from a non-overlapping portion (if any) of a partition on
1554 			 * one side might find its join partner in the default partition
1555 			 * (if any) on the other side, causing the same situation as
1556 			 * above; give up in that case.
1557 			 */
1558 			if ((outer_has_default && (lb_cmpval > 0 || ub_cmpval < 0)) ||
1559 				(inner_has_default && (lb_cmpval < 0 || ub_cmpval > 0)))
1560 				goto cleanup;
1561 		}
1562 		else if (ub_cmpval < 0)
1563 		{
1564 			/* A non-overlapping outer range. */
1565 
1566 			/* The outer partition should not have been merged yet. */
1567 			Assert(outer_index >= 0);
1568 			Assert(outer_map.merged_indexes[outer_index] == -1 &&
1569 				   outer_map.merged[outer_index] == false);
1570 
1571 			/*
1572 			 * If the inner side has the default partition, or this is an
1573 			 * outer join, try to assign a merged partition to the outer
1574 			 * partition (see process_outer_partition()).  Otherwise, the
1575 			 * outer partition will not contribute to the result.
1576 			 */
1577 			if (inner_has_default || IS_OUTER_JOIN(jointype))
1578 			{
1579 				merged_index = process_outer_partition(&outer_map,
1580 													   &inner_map,
1581 													   outer_has_default,
1582 													   inner_has_default,
1583 													   outer_index,
1584 													   inner_default,
1585 													   jointype,
1586 													   &next_index,
1587 													   &default_index);
1588 				if (merged_index == -1)
1589 					goto cleanup;
1590 				merged_lb = outer_lb;
1591 				merged_ub = outer_ub;
1592 			}
1593 
1594 			/* Move to the next range on the outer side. */
1595 			outer_index = get_range_partition(outer_rel, outer_bi, &outer_lb_pos,
1596 											  &outer_lb, &outer_ub);
1597 		}
1598 		else
1599 		{
1600 			/* A non-overlapping inner range. */
1601 			Assert(ub_cmpval > 0);
1602 
1603 			/* The inner partition should not have been merged yet. */
1604 			Assert(inner_index >= 0);
1605 			Assert(inner_map.merged_indexes[inner_index] == -1 &&
1606 				   inner_map.merged[inner_index] == false);
1607 
1608 			/*
1609 			 * If the outer side has the default partition, or this is a FULL
1610 			 * join, try to assign a merged partition to the inner partition
1611 			 * (see process_inner_partition()).  Otherwise, the inner
1612 			 * partition will not contribute to the result.
1613 			 */
1614 			if (outer_has_default || jointype == JOIN_FULL)
1615 			{
1616 				merged_index = process_inner_partition(&outer_map,
1617 													   &inner_map,
1618 													   outer_has_default,
1619 													   inner_has_default,
1620 													   inner_index,
1621 													   outer_default,
1622 													   jointype,
1623 													   &next_index,
1624 													   &default_index);
1625 				if (merged_index == -1)
1626 					goto cleanup;
1627 				merged_lb = inner_lb;
1628 				merged_ub = inner_ub;
1629 			}
1630 
1631 			/* Move to the next range on the inner side. */
1632 			inner_index = get_range_partition(inner_rel, inner_bi, &inner_lb_pos,
1633 											  &inner_lb, &inner_ub);
1634 		}
1635 
1636 		/*
1637 		 * If we assigned a merged partition, add the range bounds and index
1638 		 * of the merged partition if appropriate.
1639 		 */
1640 		if (merged_index >= 0 && merged_index != default_index)
1641 			add_merged_range_bounds(partnatts, partsupfuncs, partcollations,
1642 									&merged_lb, &merged_ub, merged_index,
1643 									&merged_datums, &merged_kinds,
1644 									&merged_indexes);
1645 	}
1646 
1647 	/* Merge the default partitions if any. */
1648 	if (outer_has_default || inner_has_default)
1649 		merge_default_partitions(&outer_map, &inner_map,
1650 								 outer_has_default, inner_has_default,
1651 								 outer_default, inner_default,
1652 								 jointype, &next_index, &default_index);
1653 	else
1654 		Assert(default_index == -1);
1655 
1656 	/* If we have merged partitions, create the partition bounds. */
1657 	if (next_index > 0)
1658 	{
1659 		/*
1660 		 * Unlike the case of list partitioning, we wouldn't have re-merged
1661 		 * partitions, so did_remapping should be left alone.
1662 		 */
1663 		Assert(!outer_map.did_remapping);
1664 		Assert(!inner_map.did_remapping);
1665 
1666 		/* Use maps to match partitions from inputs. */
1667 		generate_matching_part_pairs(outer_rel, inner_rel,
1668 									 &outer_map, &inner_map,
1669 									 next_index,
1670 									 outer_parts, inner_parts);
1671 		Assert(*outer_parts != NIL);
1672 		Assert(*inner_parts != NIL);
1673 		Assert(list_length(*outer_parts) == list_length(*inner_parts));
1674 		Assert(list_length(*outer_parts) == next_index);
1675 
1676 		/* Make a PartitionBoundInfo struct to return. */
1677 		merged_bounds = build_merged_partition_bounds(outer_bi->strategy,
1678 													  merged_datums,
1679 													  merged_kinds,
1680 													  merged_indexes,
1681 													  -1,
1682 													  default_index);
1683 		Assert(merged_bounds);
1684 	}
1685 
1686 cleanup:
1687 	/* Free local memory before returning. */
1688 	list_free(merged_datums);
1689 	list_free(merged_kinds);
1690 	list_free(merged_indexes);
1691 	free_partition_map(&outer_map);
1692 	free_partition_map(&inner_map);
1693 
1694 	return merged_bounds;
1695 }
1696 
1697 /*
1698  * init_partition_map
1699  *		Initialize a PartitionMap struct for given relation
1700  */
1701 static void
1702 init_partition_map(RelOptInfo *rel, PartitionMap *map)
1703 {
1704 	int			nparts = rel->nparts;
1705 	int			i;
1706 
1707 	map->nparts = nparts;
1708 	map->merged_indexes = (int *) palloc(sizeof(int) * nparts);
1709 	map->merged = (bool *) palloc(sizeof(bool) * nparts);
1710 	map->did_remapping = false;
1711 	map->old_indexes = (int *) palloc(sizeof(int) * nparts);
1712 	for (i = 0; i < nparts; i++)
1713 	{
1714 		map->merged_indexes[i] = map->old_indexes[i] = -1;
1715 		map->merged[i] = false;
1716 	}
1717 }
1718 
1719 /*
1720  * free_partition_map
1721  */
1722 static void
1723 free_partition_map(PartitionMap *map)
1724 {
1725 	pfree(map->merged_indexes);
1726 	pfree(map->merged);
1727 	pfree(map->old_indexes);
1728 }
1729 
1730 /*
1731  * is_dummy_partition --- has partition been proven empty?
1732  */
1733 static bool
1734 is_dummy_partition(RelOptInfo *rel, int part_index)
1735 {
1736 	RelOptInfo *part_rel;
1737 
1738 	Assert(part_index >= 0);
1739 	part_rel = rel->part_rels[part_index];
1740 	if (part_rel == NULL || IS_DUMMY_REL(part_rel))
1741 		return true;
1742 	return false;
1743 }
1744 
1745 /*
1746  * merge_matching_partitions
1747  *		Try to merge given outer/inner partitions, and return the index of a
1748  *		merged partition produced from them if successful, -1 otherwise
1749  *
1750  * If the merged partition is newly created, *next_index is incremented.
1751  */
1752 static int
1753 merge_matching_partitions(PartitionMap *outer_map, PartitionMap *inner_map,
1754 						  int outer_index, int inner_index, int *next_index)
1755 {
1756 	int			outer_merged_index;
1757 	int			inner_merged_index;
1758 	bool		outer_merged;
1759 	bool		inner_merged;
1760 
1761 	Assert(outer_index >= 0 && outer_index < outer_map->nparts);
1762 	outer_merged_index = outer_map->merged_indexes[outer_index];
1763 	outer_merged = outer_map->merged[outer_index];
1764 	Assert(inner_index >= 0 && inner_index < inner_map->nparts);
1765 	inner_merged_index = inner_map->merged_indexes[inner_index];
1766 	inner_merged = inner_map->merged[inner_index];
1767 
1768 	/*
1769 	 * Handle cases where we have already assigned a merged partition to each
1770 	 * of the given partitions.
1771 	 */
1772 	if (outer_merged_index >= 0 && inner_merged_index >= 0)
1773 	{
1774 		/*
1775 		 * If the merged partitions are the same, no need to do anything;
1776 		 * return the index of the merged partitions.  Otherwise, if each of
1777 		 * the given partitions has been merged with a dummy partition on the
1778 		 * other side, re-map them to either of the two merged partitions.
1779 		 * Otherwise, they can't be merged, so return -1.
1780 		 */
1781 		if (outer_merged_index == inner_merged_index)
1782 		{
1783 			Assert(outer_merged);
1784 			Assert(inner_merged);
1785 			return outer_merged_index;
1786 		}
1787 		if (!outer_merged && !inner_merged)
1788 		{
1789 			/*
1790 			 * This can only happen for a list-partitioning case.  We re-map
1791 			 * them to the merged partition with the smaller of the two merged
1792 			 * indexes to preserve the property that the canonical order of
1793 			 * list partitions is determined by the indexes assigned to the
1794 			 * smallest list value of each partition.
1795 			 */
1796 			if (outer_merged_index < inner_merged_index)
1797 			{
1798 				outer_map->merged[outer_index] = true;
1799 				inner_map->merged_indexes[inner_index] = outer_merged_index;
1800 				inner_map->merged[inner_index] = true;
1801 				inner_map->did_remapping = true;
1802 				inner_map->old_indexes[inner_index] = inner_merged_index;
1803 				return outer_merged_index;
1804 			}
1805 			else
1806 			{
1807 				inner_map->merged[inner_index] = true;
1808 				outer_map->merged_indexes[outer_index] = inner_merged_index;
1809 				outer_map->merged[outer_index] = true;
1810 				outer_map->did_remapping = true;
1811 				outer_map->old_indexes[outer_index] = outer_merged_index;
1812 				return inner_merged_index;
1813 			}
1814 		}
1815 		return -1;
1816 	}
1817 
1818 	/* At least one of the given partitions should not have yet been merged. */
1819 	Assert(outer_merged_index == -1 || inner_merged_index == -1);
1820 
1821 	/*
1822 	 * If neither of them has been merged, merge them.  Otherwise, if one has
1823 	 * been merged with a dummy partition on the other side (and the other
1824 	 * hasn't yet been merged with anything), re-merge them.  Otherwise, they
1825 	 * can't be merged, so return -1.
1826 	 */
1827 	if (outer_merged_index == -1 && inner_merged_index == -1)
1828 	{
1829 		int			merged_index = *next_index;
1830 
1831 		Assert(!outer_merged);
1832 		Assert(!inner_merged);
1833 		outer_map->merged_indexes[outer_index] = merged_index;
1834 		outer_map->merged[outer_index] = true;
1835 		inner_map->merged_indexes[inner_index] = merged_index;
1836 		inner_map->merged[inner_index] = true;
1837 		*next_index = *next_index + 1;
1838 		return merged_index;
1839 	}
1840 	if (outer_merged_index >= 0 && !outer_map->merged[outer_index])
1841 	{
1842 		Assert(inner_merged_index == -1);
1843 		Assert(!inner_merged);
1844 		inner_map->merged_indexes[inner_index] = outer_merged_index;
1845 		inner_map->merged[inner_index] = true;
1846 		outer_map->merged[outer_index] = true;
1847 		return outer_merged_index;
1848 	}
1849 	if (inner_merged_index >= 0 && !inner_map->merged[inner_index])
1850 	{
1851 		Assert(outer_merged_index == -1);
1852 		Assert(!outer_merged);
1853 		outer_map->merged_indexes[outer_index] = inner_merged_index;
1854 		outer_map->merged[outer_index] = true;
1855 		inner_map->merged[inner_index] = true;
1856 		return inner_merged_index;
1857 	}
1858 	return -1;
1859 }
1860 
1861 /*
1862  * process_outer_partition
1863  *		Try to assign given outer partition a merged partition, and return the
1864  *		index of the merged partition if successful, -1 otherwise
1865  *
1866  * If the partition is newly created, *next_index is incremented.  Also, if it
1867  * is the default partition of the join relation, *default_index is set to the
1868  * index if not already done.
1869  */
1870 static int
1871 process_outer_partition(PartitionMap *outer_map,
1872 						PartitionMap *inner_map,
1873 						bool outer_has_default,
1874 						bool inner_has_default,
1875 						int outer_index,
1876 						int inner_default,
1877 						JoinType jointype,
1878 						int *next_index,
1879 						int *default_index)
1880 {
1881 	int			merged_index = -1;
1882 
1883 	Assert(outer_index >= 0);
1884 
1885 	/*
1886 	 * If the inner side has the default partition, a row from the outer
1887 	 * partition might find its join partner in the default partition; try
1888 	 * merging the outer partition with the default partition.  Otherwise,
1889 	 * this should be an outer join, in which case the outer partition has to
1890 	 * be scanned all the way anyway; merge the outer partition with a dummy
1891 	 * partition on the other side.
1892 	 */
1893 	if (inner_has_default)
1894 	{
1895 		Assert(inner_default >= 0);
1896 
1897 		/*
1898 		 * If the outer side has the default partition as well, the default
1899 		 * partition on the inner side will have two matching partitions on
1900 		 * the other side: the outer partition and the default partition on
1901 		 * the outer side.  Partitionwise join doesn't handle this scenario
1902 		 * yet.
1903 		 */
1904 		if (outer_has_default)
1905 			return -1;
1906 
1907 		merged_index = merge_matching_partitions(outer_map, inner_map,
1908 												 outer_index, inner_default,
1909 												 next_index);
1910 		if (merged_index == -1)
1911 			return -1;
1912 
1913 		/*
1914 		 * If this is a FULL join, the default partition on the inner side has
1915 		 * to be scanned all the way anyway, so the resulting partition will
1916 		 * contain all key values from the default partition, which any other
1917 		 * partition of the join relation will not contain.  Thus the
1918 		 * resulting partition will act as the default partition of the join
1919 		 * relation; record the index in *default_index if not already done.
1920 		 */
1921 		if (jointype == JOIN_FULL)
1922 		{
1923 			if (*default_index == -1)
1924 				*default_index = merged_index;
1925 			else
1926 				Assert(*default_index == merged_index);
1927 		}
1928 	}
1929 	else
1930 	{
1931 		Assert(IS_OUTER_JOIN(jointype));
1932 		Assert(jointype != JOIN_RIGHT);
1933 
1934 		/* If we have already assigned a partition, no need to do anything. */
1935 		merged_index = outer_map->merged_indexes[outer_index];
1936 		if (merged_index == -1)
1937 			merged_index = merge_partition_with_dummy(outer_map, outer_index,
1938 													  next_index);
1939 	}
1940 	return merged_index;
1941 }
1942 
1943 /*
1944  * process_inner_partition
1945  *		Try to assign given inner partition a merged partition, and return the
1946  *		index of the merged partition if successful, -1 otherwise
1947  *
1948  * If the partition is newly created, *next_index is incremented.  Also, if it
1949  * is the default partition of the join relation, *default_index is set to the
1950  * index if not already done.
1951  */
1952 static int
1953 process_inner_partition(PartitionMap *outer_map,
1954 						PartitionMap *inner_map,
1955 						bool outer_has_default,
1956 						bool inner_has_default,
1957 						int inner_index,
1958 						int outer_default,
1959 						JoinType jointype,
1960 						int *next_index,
1961 						int *default_index)
1962 {
1963 	int			merged_index = -1;
1964 
1965 	Assert(inner_index >= 0);
1966 
1967 	/*
1968 	 * If the outer side has the default partition, a row from the inner
1969 	 * partition might find its join partner in the default partition; try
1970 	 * merging the inner partition with the default partition.  Otherwise,
1971 	 * this should be a FULL join, in which case the inner partition has to be
1972 	 * scanned all the way anyway; merge the inner partition with a dummy
1973 	 * partition on the other side.
1974 	 */
1975 	if (outer_has_default)
1976 	{
1977 		Assert(outer_default >= 0);
1978 
1979 		/*
1980 		 * If the inner side has the default partition as well, the default
1981 		 * partition on the outer side will have two matching partitions on
1982 		 * the other side: the inner partition and the default partition on
1983 		 * the inner side.  Partitionwise join doesn't handle this scenario
1984 		 * yet.
1985 		 */
1986 		if (inner_has_default)
1987 			return -1;
1988 
1989 		merged_index = merge_matching_partitions(outer_map, inner_map,
1990 												 outer_default, inner_index,
1991 												 next_index);
1992 		if (merged_index == -1)
1993 			return -1;
1994 
1995 		/*
1996 		 * If this is an outer join, the default partition on the outer side
1997 		 * has to be scanned all the way anyway, so the resulting partition
1998 		 * will contain all key values from the default partition, which any
1999 		 * other partition of the join relation will not contain.  Thus the
2000 		 * resulting partition will act as the default partition of the join
2001 		 * relation; record the index in *default_index if not already done.
2002 		 */
2003 		if (IS_OUTER_JOIN(jointype))
2004 		{
2005 			Assert(jointype != JOIN_RIGHT);
2006 			if (*default_index == -1)
2007 				*default_index = merged_index;
2008 			else
2009 				Assert(*default_index == merged_index);
2010 		}
2011 	}
2012 	else
2013 	{
2014 		Assert(jointype == JOIN_FULL);
2015 
2016 		/* If we have already assigned a partition, no need to do anything. */
2017 		merged_index = inner_map->merged_indexes[inner_index];
2018 		if (merged_index == -1)
2019 			merged_index = merge_partition_with_dummy(inner_map, inner_index,
2020 													  next_index);
2021 	}
2022 	return merged_index;
2023 }
2024 
2025 /*
2026  * merge_null_partitions
2027  *		Merge the NULL partitions from a join's outer and inner sides.
2028  *
2029  * If the merged partition produced from them is the NULL partition of the join
2030  * relation, *null_index is set to the index of the merged partition.
2031  *
2032  * Note: We assume here that the join clause for a partitioned join is strict
2033  * because have_partkey_equi_join() requires that the corresponding operator
2034  * be mergejoinable, and we currently assume that mergejoinable operators are
2035  * strict (see MJEvalOuterValues()/MJEvalInnerValues()).
2036  */
2037 static void
2038 merge_null_partitions(PartitionMap *outer_map,
2039 					  PartitionMap *inner_map,
2040 					  bool outer_has_null,
2041 					  bool inner_has_null,
2042 					  int outer_null,
2043 					  int inner_null,
2044 					  JoinType jointype,
2045 					  int *next_index,
2046 					  int *null_index)
2047 {
2048 	bool		consider_outer_null = false;
2049 	bool		consider_inner_null = false;
2050 
2051 	Assert(outer_has_null || inner_has_null);
2052 	Assert(*null_index == -1);
2053 
2054 	/*
2055 	 * Check whether the NULL partitions have already been merged and if so,
2056 	 * set the consider_outer_null/consider_inner_null flags.
2057 	 */
2058 	if (outer_has_null)
2059 	{
2060 		Assert(outer_null >= 0 && outer_null < outer_map->nparts);
2061 		if (outer_map->merged_indexes[outer_null] == -1)
2062 			consider_outer_null = true;
2063 	}
2064 	if (inner_has_null)
2065 	{
2066 		Assert(inner_null >= 0 && inner_null < inner_map->nparts);
2067 		if (inner_map->merged_indexes[inner_null] == -1)
2068 			consider_inner_null = true;
2069 	}
2070 
2071 	/* If both flags are set false, we don't need to do anything. */
2072 	if (!consider_outer_null && !consider_inner_null)
2073 		return;
2074 
2075 	if (consider_outer_null && !consider_inner_null)
2076 	{
2077 		Assert(outer_has_null);
2078 
2079 		/*
2080 		 * If this is an outer join, the NULL partition on the outer side has
2081 		 * to be scanned all the way anyway; merge the NULL partition with a
2082 		 * dummy partition on the other side.  In that case
2083 		 * consider_outer_null means that the NULL partition only contains
2084 		 * NULL values as the key values, so the merged partition will do so;
2085 		 * treat it as the NULL partition of the join relation.
2086 		 */
2087 		if (IS_OUTER_JOIN(jointype))
2088 		{
2089 			Assert(jointype != JOIN_RIGHT);
2090 			*null_index = merge_partition_with_dummy(outer_map, outer_null,
2091 													 next_index);
2092 		}
2093 	}
2094 	else if (!consider_outer_null && consider_inner_null)
2095 	{
2096 		Assert(inner_has_null);
2097 
2098 		/*
2099 		 * If this is a FULL join, the NULL partition on the inner side has to
2100 		 * be scanned all the way anyway; merge the NULL partition with a
2101 		 * dummy partition on the other side.  In that case
2102 		 * consider_inner_null means that the NULL partition only contains
2103 		 * NULL values as the key values, so the merged partition will do so;
2104 		 * treat it as the NULL partition of the join relation.
2105 		 */
2106 		if (jointype == JOIN_FULL)
2107 			*null_index = merge_partition_with_dummy(inner_map, inner_null,
2108 													 next_index);
2109 	}
2110 	else
2111 	{
2112 		Assert(consider_outer_null && consider_inner_null);
2113 		Assert(outer_has_null);
2114 		Assert(inner_has_null);
2115 
2116 		/*
2117 		 * If this is an outer join, the NULL partition on the outer side (and
2118 		 * that on the inner side if this is a FULL join) have to be scanned
2119 		 * all the way anyway, so merge them.  Note that each of the NULL
2120 		 * partitions isn't merged yet, so they should be merged successfully.
2121 		 * Like the above, each of the NULL partitions only contains NULL
2122 		 * values as the key values, so the merged partition will do so; treat
2123 		 * it as the NULL partition of the join relation.
2124 		 *
2125 		 * Note: if this an INNER/SEMI join, the join clause will never be
2126 		 * satisfied by two NULL values (see comments above), so both the NULL
2127 		 * partitions can be eliminated.
2128 		 */
2129 		if (IS_OUTER_JOIN(jointype))
2130 		{
2131 			Assert(jointype != JOIN_RIGHT);
2132 			*null_index = merge_matching_partitions(outer_map, inner_map,
2133 													outer_null, inner_null,
2134 													next_index);
2135 			Assert(*null_index >= 0);
2136 		}
2137 	}
2138 }
2139 
2140 /*
2141  * merge_default_partitions
2142  *		Merge the default partitions from a join's outer and inner sides.
2143  *
2144  * If the merged partition produced from them is the default partition of the
2145  * join relation, *default_index is set to the index of the merged partition.
2146  */
2147 static void
2148 merge_default_partitions(PartitionMap *outer_map,
2149 						 PartitionMap *inner_map,
2150 						 bool outer_has_default,
2151 						 bool inner_has_default,
2152 						 int outer_default,
2153 						 int inner_default,
2154 						 JoinType jointype,
2155 						 int *next_index,
2156 						 int *default_index)
2157 {
2158 	int			outer_merged_index = -1;
2159 	int			inner_merged_index = -1;
2160 
2161 	Assert(outer_has_default || inner_has_default);
2162 
2163 	/* Get the merged partition indexes for the default partitions. */
2164 	if (outer_has_default)
2165 	{
2166 		Assert(outer_default >= 0 && outer_default < outer_map->nparts);
2167 		outer_merged_index = outer_map->merged_indexes[outer_default];
2168 	}
2169 	if (inner_has_default)
2170 	{
2171 		Assert(inner_default >= 0 && inner_default < inner_map->nparts);
2172 		inner_merged_index = inner_map->merged_indexes[inner_default];
2173 	}
2174 
2175 	if (outer_has_default && !inner_has_default)
2176 	{
2177 		/*
2178 		 * If this is an outer join, the default partition on the outer side
2179 		 * has to be scanned all the way anyway; if we have not yet assigned a
2180 		 * partition, merge the default partition with a dummy partition on
2181 		 * the other side.  The merged partition will act as the default
2182 		 * partition of the join relation (see comments in
2183 		 * process_inner_partition()).
2184 		 */
2185 		if (IS_OUTER_JOIN(jointype))
2186 		{
2187 			Assert(jointype != JOIN_RIGHT);
2188 			if (outer_merged_index == -1)
2189 			{
2190 				Assert(*default_index == -1);
2191 				*default_index = merge_partition_with_dummy(outer_map,
2192 															outer_default,
2193 															next_index);
2194 			}
2195 			else
2196 				Assert(*default_index == outer_merged_index);
2197 		}
2198 		else
2199 			Assert(*default_index == -1);
2200 	}
2201 	else if (!outer_has_default && inner_has_default)
2202 	{
2203 		/*
2204 		 * If this is a FULL join, the default partition on the inner side has
2205 		 * to be scanned all the way anyway; if we have not yet assigned a
2206 		 * partition, merge the default partition with a dummy partition on
2207 		 * the other side.  The merged partition will act as the default
2208 		 * partition of the join relation (see comments in
2209 		 * process_outer_partition()).
2210 		 */
2211 		if (jointype == JOIN_FULL)
2212 		{
2213 			if (inner_merged_index == -1)
2214 			{
2215 				Assert(*default_index == -1);
2216 				*default_index = merge_partition_with_dummy(inner_map,
2217 															inner_default,
2218 															next_index);
2219 			}
2220 			else
2221 				Assert(*default_index == inner_merged_index);
2222 		}
2223 		else
2224 			Assert(*default_index == -1);
2225 	}
2226 	else
2227 	{
2228 		Assert(outer_has_default && inner_has_default);
2229 
2230 		/*
2231 		 * The default partitions have to be joined with each other, so merge
2232 		 * them.  Note that each of the default partitions isn't merged yet
2233 		 * (see, process_outer_partition()/process_innerer_partition()), so
2234 		 * they should be merged successfully.  The merged partition will act
2235 		 * as the default partition of the join relation.
2236 		 */
2237 		Assert(outer_merged_index == -1);
2238 		Assert(inner_merged_index == -1);
2239 		Assert(*default_index == -1);
2240 		*default_index = merge_matching_partitions(outer_map,
2241 												   inner_map,
2242 												   outer_default,
2243 												   inner_default,
2244 												   next_index);
2245 		Assert(*default_index >= 0);
2246 	}
2247 }
2248 
2249 /*
2250  * merge_partition_with_dummy
2251  *		Assign given partition a new partition of a join relation
2252  *
2253  * Note: The caller assumes that the given partition doesn't have a non-dummy
2254  * matching partition on the other side, but if the given partition finds the
2255  * matching partition later, we will adjust the assignment.
2256  */
2257 static int
2258 merge_partition_with_dummy(PartitionMap *map, int index, int *next_index)
2259 {
2260 	int			merged_index = *next_index;
2261 
2262 	Assert(index >= 0 && index < map->nparts);
2263 	Assert(map->merged_indexes[index] == -1);
2264 	Assert(!map->merged[index]);
2265 	map->merged_indexes[index] = merged_index;
2266 	/* Leave the merged flag alone! */
2267 	*next_index = *next_index + 1;
2268 	return merged_index;
2269 }
2270 
2271 /*
2272  * fix_merged_indexes
2273  *		Adjust merged indexes of re-merged partitions
2274  */
2275 static void
2276 fix_merged_indexes(PartitionMap *outer_map, PartitionMap *inner_map,
2277 				   int nmerged, List *merged_indexes)
2278 {
2279 	int		   *new_indexes;
2280 	int			merged_index;
2281 	int			i;
2282 	ListCell   *lc;
2283 
2284 	Assert(nmerged > 0);
2285 
2286 	new_indexes = (int *) palloc(sizeof(int) * nmerged);
2287 	for (i = 0; i < nmerged; i++)
2288 		new_indexes[i] = -1;
2289 
2290 	/* Build the mapping of old merged indexes to new merged indexes. */
2291 	if (outer_map->did_remapping)
2292 	{
2293 		for (i = 0; i < outer_map->nparts; i++)
2294 		{
2295 			merged_index = outer_map->old_indexes[i];
2296 			if (merged_index >= 0)
2297 				new_indexes[merged_index] = outer_map->merged_indexes[i];
2298 		}
2299 	}
2300 	if (inner_map->did_remapping)
2301 	{
2302 		for (i = 0; i < inner_map->nparts; i++)
2303 		{
2304 			merged_index = inner_map->old_indexes[i];
2305 			if (merged_index >= 0)
2306 				new_indexes[merged_index] = inner_map->merged_indexes[i];
2307 		}
2308 	}
2309 
2310 	/* Fix the merged_indexes list using the mapping. */
2311 	foreach(lc, merged_indexes)
2312 	{
2313 		merged_index = lfirst_int(lc);
2314 		Assert(merged_index >= 0);
2315 		if (new_indexes[merged_index] >= 0)
2316 			lfirst_int(lc) = new_indexes[merged_index];
2317 	}
2318 
2319 	pfree(new_indexes);
2320 }
2321 
2322 /*
2323  * generate_matching_part_pairs
2324  *		Generate a pair of lists of partitions that produce merged partitions
2325  *
2326  * The lists of partitions are built in the order of merged partition indexes,
2327  * and returned in *outer_parts and *inner_parts.
2328  */
2329 static void
2330 generate_matching_part_pairs(RelOptInfo *outer_rel, RelOptInfo *inner_rel,
2331 							 PartitionMap *outer_map, PartitionMap *inner_map,
2332 							 int nmerged,
2333 							 List **outer_parts, List **inner_parts)
2334 {
2335 	int			outer_nparts = outer_map->nparts;
2336 	int			inner_nparts = inner_map->nparts;
2337 	int		   *outer_indexes;
2338 	int		   *inner_indexes;
2339 	int			max_nparts;
2340 	int			i;
2341 
2342 	Assert(nmerged > 0);
2343 	Assert(*outer_parts == NIL);
2344 	Assert(*inner_parts == NIL);
2345 
2346 	outer_indexes = (int *) palloc(sizeof(int) * nmerged);
2347 	inner_indexes = (int *) palloc(sizeof(int) * nmerged);
2348 	for (i = 0; i < nmerged; i++)
2349 		outer_indexes[i] = inner_indexes[i] = -1;
2350 
2351 	/* Set pairs of matching partitions. */
2352 	Assert(outer_nparts == outer_rel->nparts);
2353 	Assert(inner_nparts == inner_rel->nparts);
2354 	max_nparts = Max(outer_nparts, inner_nparts);
2355 	for (i = 0; i < max_nparts; i++)
2356 	{
2357 		if (i < outer_nparts)
2358 		{
2359 			int			merged_index = outer_map->merged_indexes[i];
2360 
2361 			if (merged_index >= 0)
2362 			{
2363 				Assert(merged_index < nmerged);
2364 				outer_indexes[merged_index] = i;
2365 			}
2366 		}
2367 		if (i < inner_nparts)
2368 		{
2369 			int			merged_index = inner_map->merged_indexes[i];
2370 
2371 			if (merged_index >= 0)
2372 			{
2373 				Assert(merged_index < nmerged);
2374 				inner_indexes[merged_index] = i;
2375 			}
2376 		}
2377 	}
2378 
2379 	/* Build the list pairs. */
2380 	for (i = 0; i < nmerged; i++)
2381 	{
2382 		int			outer_index = outer_indexes[i];
2383 		int			inner_index = inner_indexes[i];
2384 
2385 		/*
2386 		 * If both partitions are dummy, it means the merged partition that
2387 		 * had been assigned to the outer/inner partition was removed when
2388 		 * re-merging the outer/inner partition in
2389 		 * merge_matching_partitions(); ignore the merged partition.
2390 		 */
2391 		if (outer_index == -1 && inner_index == -1)
2392 			continue;
2393 
2394 		*outer_parts = lappend(*outer_parts, outer_index >= 0 ?
2395 							   outer_rel->part_rels[outer_index] : NULL);
2396 		*inner_parts = lappend(*inner_parts, inner_index >= 0 ?
2397 							   inner_rel->part_rels[inner_index] : NULL);
2398 	}
2399 
2400 	pfree(outer_indexes);
2401 	pfree(inner_indexes);
2402 }
2403 
2404 /*
2405  * build_merged_partition_bounds
2406  *		Create a PartitionBoundInfo struct from merged partition bounds
2407  */
2408 static PartitionBoundInfo
2409 build_merged_partition_bounds(char strategy, List *merged_datums,
2410 							  List *merged_kinds, List *merged_indexes,
2411 							  int null_index, int default_index)
2412 {
2413 	PartitionBoundInfo merged_bounds;
2414 	int			ndatums = list_length(merged_datums);
2415 	int			pos;
2416 	ListCell   *lc;
2417 
2418 	merged_bounds = (PartitionBoundInfo) palloc(sizeof(PartitionBoundInfoData));
2419 	merged_bounds->strategy = strategy;
2420 	merged_bounds->ndatums = ndatums;
2421 
2422 	merged_bounds->datums = (Datum **) palloc(sizeof(Datum *) * ndatums);
2423 	pos = 0;
2424 	foreach(lc, merged_datums)
2425 		merged_bounds->datums[pos++] = (Datum *) lfirst(lc);
2426 
2427 	if (strategy == PARTITION_STRATEGY_RANGE)
2428 	{
2429 		Assert(list_length(merged_kinds) == ndatums);
2430 		merged_bounds->kind = (PartitionRangeDatumKind **)
2431 			palloc(sizeof(PartitionRangeDatumKind *) * ndatums);
2432 		pos = 0;
2433 		foreach(lc, merged_kinds)
2434 			merged_bounds->kind[pos++] = (PartitionRangeDatumKind *) lfirst(lc);
2435 
2436 		/* There are ndatums+1 indexes in the case of range partitioning. */
2437 		merged_indexes = lappend_int(merged_indexes, -1);
2438 		ndatums++;
2439 	}
2440 	else
2441 	{
2442 		Assert(strategy == PARTITION_STRATEGY_LIST);
2443 		Assert(merged_kinds == NIL);
2444 		merged_bounds->kind = NULL;
2445 	}
2446 
2447 	Assert(list_length(merged_indexes) == ndatums);
2448 	merged_bounds->nindexes = ndatums;
2449 	merged_bounds->indexes = (int *) palloc(sizeof(int) * ndatums);
2450 	pos = 0;
2451 	foreach(lc, merged_indexes)
2452 		merged_bounds->indexes[pos++] = lfirst_int(lc);
2453 
2454 	merged_bounds->null_index = null_index;
2455 	merged_bounds->default_index = default_index;
2456 
2457 	return merged_bounds;
2458 }
2459 
2460 /*
2461  * get_range_partition
2462  *		Get the next non-dummy partition of a range-partitioned relation,
2463  *		returning the index of that partition
2464  *
2465  * *lb and *ub are set to the lower and upper bounds of that partition
2466  * respectively, and *lb_pos is advanced to the next lower bound, if any.
2467  */
2468 static int
2469 get_range_partition(RelOptInfo *rel,
2470 					PartitionBoundInfo bi,
2471 					int *lb_pos,
2472 					PartitionRangeBound *lb,
2473 					PartitionRangeBound *ub)
2474 {
2475 	int			part_index;
2476 
2477 	Assert(bi->strategy == PARTITION_STRATEGY_RANGE);
2478 
2479 	do
2480 	{
2481 		part_index = get_range_partition_internal(bi, lb_pos, lb, ub);
2482 		if (part_index == -1)
2483 			return -1;
2484 	} while (is_dummy_partition(rel, part_index));
2485 
2486 	return part_index;
2487 }
2488 
2489 static int
2490 get_range_partition_internal(PartitionBoundInfo bi,
2491 							 int *lb_pos,
2492 							 PartitionRangeBound *lb,
2493 							 PartitionRangeBound *ub)
2494 {
2495 	/* Return the index as -1 if we've exhausted all lower bounds. */
2496 	if (*lb_pos >= bi->ndatums)
2497 		return -1;
2498 
2499 	/* A lower bound should have at least one more bound after it. */
2500 	Assert(*lb_pos + 1 < bi->ndatums);
2501 
2502 	/* Set the lower bound. */
2503 	lb->index = bi->indexes[*lb_pos];
2504 	lb->datums = bi->datums[*lb_pos];
2505 	lb->kind = bi->kind[*lb_pos];
2506 	lb->lower = true;
2507 	/* Set the upper bound. */
2508 	ub->index = bi->indexes[*lb_pos + 1];
2509 	ub->datums = bi->datums[*lb_pos + 1];
2510 	ub->kind = bi->kind[*lb_pos + 1];
2511 	ub->lower = false;
2512 
2513 	/* The index assigned to an upper bound should be valid. */
2514 	Assert(ub->index >= 0);
2515 
2516 	/*
2517 	 * Advance the position to the next lower bound.  If there are no bounds
2518 	 * left beyond the upper bound, we have reached the last lower bound.
2519 	 */
2520 	if (*lb_pos + 2 >= bi->ndatums)
2521 		*lb_pos = bi->ndatums;
2522 	else
2523 	{
2524 		/*
2525 		 * If the index assigned to the bound next to the upper bound isn't
2526 		 * valid, that is the next lower bound; else, the upper bound is also
2527 		 * the lower bound of the next range partition.
2528 		 */
2529 		if (bi->indexes[*lb_pos + 2] < 0)
2530 			*lb_pos = *lb_pos + 2;
2531 		else
2532 			*lb_pos = *lb_pos + 1;
2533 	}
2534 
2535 	return ub->index;
2536 }
2537 
2538 /*
2539  * compare_range_partitions
2540  *		Compare the bounds of two range partitions, and return true if the
2541  *		two partitions overlap, false otherwise
2542  *
2543  * *lb_cmpval is set to -1, 0, or 1 if the outer partition's lower bound is
2544  * lower than, equal to, or higher than the inner partition's lower bound
2545  * respectively.  Likewise, *ub_cmpval is set to -1, 0, or 1 if the outer
2546  * partition's upper bound is lower than, equal to, or higher than the inner
2547  * partition's upper bound respectively.
2548  */
2549 static bool
2550 compare_range_partitions(int partnatts, FmgrInfo *partsupfuncs,
2551 						 Oid *partcollations,
2552 						 PartitionRangeBound *outer_lb,
2553 						 PartitionRangeBound *outer_ub,
2554 						 PartitionRangeBound *inner_lb,
2555 						 PartitionRangeBound *inner_ub,
2556 						 int *lb_cmpval, int *ub_cmpval)
2557 {
2558 	/*
2559 	 * Check if the outer partition's upper bound is lower than the inner
2560 	 * partition's lower bound; if so the partitions aren't overlapping.
2561 	 */
2562 	if (compare_range_bounds(partnatts, partsupfuncs, partcollations,
2563 							 outer_ub, inner_lb) < 0)
2564 	{
2565 		*lb_cmpval = -1;
2566 		*ub_cmpval = -1;
2567 		return false;
2568 	}
2569 
2570 	/*
2571 	 * Check if the outer partition's lower bound is higher than the inner
2572 	 * partition's upper bound; if so the partitions aren't overlapping.
2573 	 */
2574 	if (compare_range_bounds(partnatts, partsupfuncs, partcollations,
2575 							 outer_lb, inner_ub) > 0)
2576 	{
2577 		*lb_cmpval = 1;
2578 		*ub_cmpval = 1;
2579 		return false;
2580 	}
2581 
2582 	/* All other cases indicate overlapping partitions. */
2583 	*lb_cmpval = compare_range_bounds(partnatts, partsupfuncs, partcollations,
2584 									  outer_lb, inner_lb);
2585 	*ub_cmpval = compare_range_bounds(partnatts, partsupfuncs, partcollations,
2586 									  outer_ub, inner_ub);
2587 	return true;
2588 }
2589 
2590 /*
2591  * get_merged_range_bounds
2592  *		Given the bounds of range partitions to be joined, determine the bounds
2593  *		of a merged partition produced from the range partitions
2594  *
2595  * *merged_lb and *merged_ub are set to the lower and upper bounds of the
2596  * merged partition.
2597  */
2598 static void
2599 get_merged_range_bounds(int partnatts, FmgrInfo *partsupfuncs,
2600 						Oid *partcollations, JoinType jointype,
2601 						PartitionRangeBound *outer_lb,
2602 						PartitionRangeBound *outer_ub,
2603 						PartitionRangeBound *inner_lb,
2604 						PartitionRangeBound *inner_ub,
2605 						int lb_cmpval, int ub_cmpval,
2606 						PartitionRangeBound *merged_lb,
2607 						PartitionRangeBound *merged_ub)
2608 {
2609 	Assert(compare_range_bounds(partnatts, partsupfuncs, partcollations,
2610 								outer_lb, inner_lb) == lb_cmpval);
2611 	Assert(compare_range_bounds(partnatts, partsupfuncs, partcollations,
2612 								outer_ub, inner_ub) == ub_cmpval);
2613 
2614 	switch (jointype)
2615 	{
2616 		case JOIN_INNER:
2617 		case JOIN_SEMI:
2618 
2619 			/*
2620 			 * An INNER/SEMI join will have the rows that fit both sides, so
2621 			 * the lower bound of the merged partition will be the higher of
2622 			 * the two lower bounds, and the upper bound of the merged
2623 			 * partition will be the lower of the two upper bounds.
2624 			 */
2625 			*merged_lb = (lb_cmpval > 0) ? *outer_lb : *inner_lb;
2626 			*merged_ub = (ub_cmpval < 0) ? *outer_ub : *inner_ub;
2627 			break;
2628 
2629 		case JOIN_LEFT:
2630 		case JOIN_ANTI:
2631 
2632 			/*
2633 			 * A LEFT/ANTI join will have all the rows from the outer side, so
2634 			 * the bounds of the merged partition will be the same as the
2635 			 * outer bounds.
2636 			 */
2637 			*merged_lb = *outer_lb;
2638 			*merged_ub = *outer_ub;
2639 			break;
2640 
2641 		case JOIN_FULL:
2642 
2643 			/*
2644 			 * A FULL join will have all the rows from both sides, so the
2645 			 * lower bound of the merged partition will be the lower of the
2646 			 * two lower bounds, and the upper bound of the merged partition
2647 			 * will be the higher of the two upper bounds.
2648 			 */
2649 			*merged_lb = (lb_cmpval < 0) ? *outer_lb : *inner_lb;
2650 			*merged_ub = (ub_cmpval > 0) ? *outer_ub : *inner_ub;
2651 			break;
2652 
2653 		default:
2654 			elog(ERROR, "unrecognized join type: %d", (int) jointype);
2655 	}
2656 }
2657 
2658 /*
2659  * add_merged_range_bounds
2660  *		Add the bounds of a merged partition to the lists of range bounds
2661  */
2662 static void
2663 add_merged_range_bounds(int partnatts, FmgrInfo *partsupfuncs,
2664 						Oid *partcollations,
2665 						PartitionRangeBound *merged_lb,
2666 						PartitionRangeBound *merged_ub,
2667 						int merged_index,
2668 						List **merged_datums,
2669 						List **merged_kinds,
2670 						List **merged_indexes)
2671 {
2672 	int			cmpval;
2673 
2674 	if (!*merged_datums)
2675 	{
2676 		/* First merged partition */
2677 		Assert(!*merged_kinds);
2678 		Assert(!*merged_indexes);
2679 		cmpval = 1;
2680 	}
2681 	else
2682 	{
2683 		PartitionRangeBound prev_ub;
2684 
2685 		Assert(*merged_datums);
2686 		Assert(*merged_kinds);
2687 		Assert(*merged_indexes);
2688 
2689 		/* Get the last upper bound. */
2690 		prev_ub.index = llast_int(*merged_indexes);
2691 		prev_ub.datums = (Datum *) llast(*merged_datums);
2692 		prev_ub.kind = (PartitionRangeDatumKind *) llast(*merged_kinds);
2693 		prev_ub.lower = false;
2694 
2695 		/*
2696 		 * We pass lower1 = false to partition_rbound_cmp() to prevent it from
2697 		 * considering the last upper bound to be smaller than the lower bound
2698 		 * of the merged partition when the values of the two range bounds
2699 		 * compare equal.
2700 		 */
2701 		cmpval = partition_rbound_cmp(partnatts, partsupfuncs, partcollations,
2702 									  merged_lb->datums, merged_lb->kind,
2703 									  false, &prev_ub);
2704 		Assert(cmpval >= 0);
2705 	}
2706 
2707 	/*
2708 	 * If the lower bound is higher than the last upper bound, add the lower
2709 	 * bound with the index as -1 indicating that that is a lower bound; else,
2710 	 * the last upper bound will be reused as the lower bound of the merged
2711 	 * partition, so skip this.
2712 	 */
2713 	if (cmpval > 0)
2714 	{
2715 		*merged_datums = lappend(*merged_datums, merged_lb->datums);
2716 		*merged_kinds = lappend(*merged_kinds, merged_lb->kind);
2717 		*merged_indexes = lappend_int(*merged_indexes, -1);
2718 	}
2719 
2720 	/* Add the upper bound and index of the merged partition. */
2721 	*merged_datums = lappend(*merged_datums, merged_ub->datums);
2722 	*merged_kinds = lappend(*merged_kinds, merged_ub->kind);
2723 	*merged_indexes = lappend_int(*merged_indexes, merged_index);
2724 }
2725 
2726 /*
2727  * partitions_are_ordered
2728  *		Determine whether the partitions described by 'boundinfo' are ordered,
2729  *		that is partitions appearing earlier in the PartitionDesc sequence
2730  *		contain partition keys strictly less than those appearing later.
2731  *		Also, if NULL values are possible, they must come in the last
2732  *		partition defined in the PartitionDesc.
2733  *
2734  * If out of order, or there is insufficient info to know the order,
2735  * then we return false.
2736  */
2737 bool
2738 partitions_are_ordered(PartitionBoundInfo boundinfo, int nparts)
2739 {
2740 	Assert(boundinfo != NULL);
2741 
2742 	switch (boundinfo->strategy)
2743 	{
2744 		case PARTITION_STRATEGY_RANGE:
2745 
2746 			/*
2747 			 * RANGE-type partitioning guarantees that the partitions can be
2748 			 * scanned in the order that they're defined in the PartitionDesc
2749 			 * to provide sequential, non-overlapping ranges of tuples.
2750 			 * However, if a DEFAULT partition exists then it doesn't work, as
2751 			 * that could contain tuples from either below or above the
2752 			 * defined range, or tuples belonging to gaps between partitions.
2753 			 */
2754 			if (!partition_bound_has_default(boundinfo))
2755 				return true;
2756 			break;
2757 
2758 		case PARTITION_STRATEGY_LIST:
2759 
2760 			/*
2761 			 * LIST partitioning can also guarantee ordering, but only if the
2762 			 * partitions don't accept interleaved values.  We could likely
2763 			 * check for this by looping over the PartitionBound's indexes
2764 			 * array to check that the indexes are in order.  For now, let's
2765 			 * just keep it simple and just accept LIST partitioning when
2766 			 * there's no DEFAULT partition, exactly one value per partition,
2767 			 * and optionally a NULL partition that does not accept any other
2768 			 * values.  Such a NULL partition will come last in the
2769 			 * PartitionDesc, and the other partitions will be properly
2770 			 * ordered.  This is a cheap test to make as it does not require
2771 			 * any per-partition processing.  Maybe we'd like to handle more
2772 			 * complex cases in the future.
2773 			 */
2774 			if (partition_bound_has_default(boundinfo))
2775 				return false;
2776 
2777 			if (boundinfo->ndatums + partition_bound_accepts_nulls(boundinfo)
2778 				== nparts)
2779 				return true;
2780 			break;
2781 
2782 		default:
2783 			/* HASH, or some other strategy */
2784 			break;
2785 	}
2786 
2787 	return false;
2788 }
2789 
2790 /*
2791  * check_new_partition_bound
2792  *
2793  * Checks if the new partition's bound overlaps any of the existing partitions
2794  * of parent.  Also performs additional checks as necessary per strategy.
2795  */
2796 void
2797 check_new_partition_bound(char *relname, Relation parent,
2798 						  PartitionBoundSpec *spec, ParseState *pstate)
2799 {
2800 	PartitionKey key = RelationGetPartitionKey(parent);
2801 	PartitionDesc partdesc = RelationGetPartitionDesc(parent, false);
2802 	PartitionBoundInfo boundinfo = partdesc->boundinfo;
2803 	int			with = -1;
2804 	bool		overlap = false;
2805 	int			overlap_location = -1;
2806 
2807 	if (spec->is_default)
2808 	{
2809 		/*
2810 		 * The default partition bound never conflicts with any other
2811 		 * partition's; if that's what we're attaching, the only possible
2812 		 * problem is that one already exists, so check for that and we're
2813 		 * done.
2814 		 */
2815 		if (boundinfo == NULL || !partition_bound_has_default(boundinfo))
2816 			return;
2817 
2818 		/* Default partition already exists, error out. */
2819 		ereport(ERROR,
2820 				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2821 				 errmsg("partition \"%s\" conflicts with existing default partition \"%s\"",
2822 						relname, get_rel_name(partdesc->oids[boundinfo->default_index])),
2823 				 parser_errposition(pstate, spec->location)));
2824 	}
2825 
2826 	switch (key->strategy)
2827 	{
2828 		case PARTITION_STRATEGY_HASH:
2829 			{
2830 				Assert(spec->strategy == PARTITION_STRATEGY_HASH);
2831 				Assert(spec->remainder >= 0 && spec->remainder < spec->modulus);
2832 
2833 				if (partdesc->nparts > 0)
2834 				{
2835 					int			greatest_modulus;
2836 					int			remainder;
2837 					int			offset;
2838 
2839 					/*
2840 					 * Check rule that every modulus must be a factor of the
2841 					 * next larger modulus.  (For example, if you have a bunch
2842 					 * of partitions that all have modulus 5, you can add a
2843 					 * new partition with modulus 10 or a new partition with
2844 					 * modulus 15, but you cannot add both a partition with
2845 					 * modulus 10 and a partition with modulus 15, because 10
2846 					 * is not a factor of 15.)  We need only check the next
2847 					 * smaller and next larger existing moduli, relying on
2848 					 * previous enforcement of this rule to be sure that the
2849 					 * rest are in line.
2850 					 */
2851 
2852 					/*
2853 					 * Get the greatest (modulus, remainder) pair contained in
2854 					 * boundinfo->datums that is less than or equal to the
2855 					 * (spec->modulus, spec->remainder) pair.
2856 					 */
2857 					offset = partition_hash_bsearch(boundinfo,
2858 													spec->modulus,
2859 													spec->remainder);
2860 					if (offset < 0)
2861 					{
2862 						int			next_modulus;
2863 
2864 						/*
2865 						 * All existing moduli are greater or equal, so the
2866 						 * new one must be a factor of the smallest one, which
2867 						 * is first in the boundinfo.
2868 						 */
2869 						next_modulus = DatumGetInt32(boundinfo->datums[0][0]);
2870 						if (next_modulus % spec->modulus != 0)
2871 							ereport(ERROR,
2872 									(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2873 									 errmsg("every hash partition modulus must be a factor of the next larger modulus"),
2874 									 errdetail("The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\".",
2875 											   spec->modulus, next_modulus,
2876 											   get_rel_name(partdesc->oids[0]))));
2877 					}
2878 					else
2879 					{
2880 						int			prev_modulus;
2881 
2882 						/*
2883 						 * We found the largest (modulus, remainder) pair less
2884 						 * than or equal to the new one.  That modulus must be
2885 						 * a divisor of, or equal to, the new modulus.
2886 						 */
2887 						prev_modulus = DatumGetInt32(boundinfo->datums[offset][0]);
2888 
2889 						if (spec->modulus % prev_modulus != 0)
2890 							ereport(ERROR,
2891 									(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2892 									 errmsg("every hash partition modulus must be a factor of the next larger modulus"),
2893 									 errdetail("The new modulus %d is not divisible by %d, the modulus of existing partition \"%s\".",
2894 											   spec->modulus,
2895 											   prev_modulus,
2896 											   get_rel_name(partdesc->oids[offset]))));
2897 
2898 						if (offset + 1 < boundinfo->ndatums)
2899 						{
2900 							int			next_modulus;
2901 
2902 							/*
2903 							 * Look at the next higher (modulus, remainder)
2904 							 * pair.  That could have the same modulus and a
2905 							 * larger remainder than the new pair, in which
2906 							 * case we're good.  If it has a larger modulus,
2907 							 * the new modulus must divide that one.
2908 							 */
2909 							next_modulus = DatumGetInt32(boundinfo->datums[offset + 1][0]);
2910 
2911 							if (next_modulus % spec->modulus != 0)
2912 								ereport(ERROR,
2913 										(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2914 										 errmsg("every hash partition modulus must be a factor of the next larger modulus"),
2915 										 errdetail("The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\".",
2916 												   spec->modulus, next_modulus,
2917 												   get_rel_name(partdesc->oids[offset + 1]))));
2918 						}
2919 					}
2920 
2921 					greatest_modulus = boundinfo->nindexes;
2922 					remainder = spec->remainder;
2923 
2924 					/*
2925 					 * Normally, the lowest remainder that could conflict with
2926 					 * the new partition is equal to the remainder specified
2927 					 * for the new partition, but when the new partition has a
2928 					 * modulus higher than any used so far, we need to adjust.
2929 					 */
2930 					if (remainder >= greatest_modulus)
2931 						remainder = remainder % greatest_modulus;
2932 
2933 					/* Check every potentially-conflicting remainder. */
2934 					do
2935 					{
2936 						if (boundinfo->indexes[remainder] != -1)
2937 						{
2938 							overlap = true;
2939 							overlap_location = spec->location;
2940 							with = boundinfo->indexes[remainder];
2941 							break;
2942 						}
2943 						remainder += spec->modulus;
2944 					} while (remainder < greatest_modulus);
2945 				}
2946 
2947 				break;
2948 			}
2949 
2950 		case PARTITION_STRATEGY_LIST:
2951 			{
2952 				Assert(spec->strategy == PARTITION_STRATEGY_LIST);
2953 
2954 				if (partdesc->nparts > 0)
2955 				{
2956 					ListCell   *cell;
2957 
2958 					Assert(boundinfo &&
2959 						   boundinfo->strategy == PARTITION_STRATEGY_LIST &&
2960 						   (boundinfo->ndatums > 0 ||
2961 							partition_bound_accepts_nulls(boundinfo) ||
2962 							partition_bound_has_default(boundinfo)));
2963 
2964 					foreach(cell, spec->listdatums)
2965 					{
2966 						Const	   *val = castNode(Const, lfirst(cell));
2967 
2968 						overlap_location = val->location;
2969 						if (!val->constisnull)
2970 						{
2971 							int			offset;
2972 							bool		equal;
2973 
2974 							offset = partition_list_bsearch(&key->partsupfunc[0],
2975 															key->partcollation,
2976 															boundinfo,
2977 															val->constvalue,
2978 															&equal);
2979 							if (offset >= 0 && equal)
2980 							{
2981 								overlap = true;
2982 								with = boundinfo->indexes[offset];
2983 								break;
2984 							}
2985 						}
2986 						else if (partition_bound_accepts_nulls(boundinfo))
2987 						{
2988 							overlap = true;
2989 							with = boundinfo->null_index;
2990 							break;
2991 						}
2992 					}
2993 				}
2994 
2995 				break;
2996 			}
2997 
2998 		case PARTITION_STRATEGY_RANGE:
2999 			{
3000 				PartitionRangeBound *lower,
3001 						   *upper;
3002 				int			cmpval;
3003 
3004 				Assert(spec->strategy == PARTITION_STRATEGY_RANGE);
3005 				lower = make_one_partition_rbound(key, -1, spec->lowerdatums, true);
3006 				upper = make_one_partition_rbound(key, -1, spec->upperdatums, false);
3007 
3008 				/*
3009 				 * First check if the resulting range would be empty with
3010 				 * specified lower and upper bounds.  partition_rbound_cmp
3011 				 * cannot return zero here, since the lower-bound flags are
3012 				 * different.
3013 				 */
3014 				cmpval = partition_rbound_cmp(key->partnatts,
3015 											  key->partsupfunc,
3016 											  key->partcollation,
3017 											  lower->datums, lower->kind,
3018 											  true, upper);
3019 				Assert(cmpval != 0);
3020 				if (cmpval > 0)
3021 				{
3022 					/* Point to problematic key in the lower datums list. */
3023 					PartitionRangeDatum *datum = list_nth(spec->lowerdatums,
3024 														  cmpval - 1);
3025 
3026 					ereport(ERROR,
3027 							(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3028 							 errmsg("empty range bound specified for partition \"%s\"",
3029 									relname),
3030 							 errdetail("Specified lower bound %s is greater than or equal to upper bound %s.",
3031 									   get_range_partbound_string(spec->lowerdatums),
3032 									   get_range_partbound_string(spec->upperdatums)),
3033 							 parser_errposition(pstate, datum->location)));
3034 				}
3035 
3036 				if (partdesc->nparts > 0)
3037 				{
3038 					int			offset;
3039 
3040 					Assert(boundinfo &&
3041 						   boundinfo->strategy == PARTITION_STRATEGY_RANGE &&
3042 						   (boundinfo->ndatums > 0 ||
3043 							partition_bound_has_default(boundinfo)));
3044 
3045 					/*
3046 					 * Test whether the new lower bound (which is treated
3047 					 * inclusively as part of the new partition) lies inside
3048 					 * an existing partition, or in a gap.
3049 					 *
3050 					 * If it's inside an existing partition, the bound at
3051 					 * offset + 1 will be the upper bound of that partition,
3052 					 * and its index will be >= 0.
3053 					 *
3054 					 * If it's in a gap, the bound at offset + 1 will be the
3055 					 * lower bound of the next partition, and its index will
3056 					 * be -1. This is also true if there is no next partition,
3057 					 * since the index array is initialised with an extra -1
3058 					 * at the end.
3059 					 */
3060 					offset = partition_range_bsearch(key->partnatts,
3061 													 key->partsupfunc,
3062 													 key->partcollation,
3063 													 boundinfo, lower,
3064 													 &cmpval);
3065 
3066 					if (boundinfo->indexes[offset + 1] < 0)
3067 					{
3068 						/*
3069 						 * Check that the new partition will fit in the gap.
3070 						 * For it to fit, the new upper bound must be less
3071 						 * than or equal to the lower bound of the next
3072 						 * partition, if there is one.
3073 						 */
3074 						if (offset + 1 < boundinfo->ndatums)
3075 						{
3076 							Datum	   *datums;
3077 							PartitionRangeDatumKind *kind;
3078 							bool		is_lower;
3079 
3080 							datums = boundinfo->datums[offset + 1];
3081 							kind = boundinfo->kind[offset + 1];
3082 							is_lower = (boundinfo->indexes[offset + 1] == -1);
3083 
3084 							cmpval = partition_rbound_cmp(key->partnatts,
3085 														  key->partsupfunc,
3086 														  key->partcollation,
3087 														  datums, kind,
3088 														  is_lower, upper);
3089 							if (cmpval < 0)
3090 							{
3091 								/*
3092 								 * Point to problematic key in the upper
3093 								 * datums list.
3094 								 */
3095 								PartitionRangeDatum *datum =
3096 								list_nth(spec->upperdatums, Abs(cmpval) - 1);
3097 
3098 								/*
3099 								 * The new partition overlaps with the
3100 								 * existing partition between offset + 1 and
3101 								 * offset + 2.
3102 								 */
3103 								overlap = true;
3104 								overlap_location = datum->location;
3105 								with = boundinfo->indexes[offset + 2];
3106 							}
3107 						}
3108 					}
3109 					else
3110 					{
3111 						/*
3112 						 * The new partition overlaps with the existing
3113 						 * partition between offset and offset + 1.
3114 						 */
3115 						PartitionRangeDatum *datum;
3116 
3117 						/*
3118 						 * Point to problematic key in the lower datums list;
3119 						 * if we have equality, point to the first one.
3120 						 */
3121 						datum = cmpval == 0 ? linitial(spec->lowerdatums) :
3122 							list_nth(spec->lowerdatums, Abs(cmpval) - 1);
3123 						overlap = true;
3124 						overlap_location = datum->location;
3125 						with = boundinfo->indexes[offset + 1];
3126 					}
3127 				}
3128 
3129 				break;
3130 			}
3131 
3132 		default:
3133 			elog(ERROR, "unexpected partition strategy: %d",
3134 				 (int) key->strategy);
3135 	}
3136 
3137 	if (overlap)
3138 	{
3139 		Assert(with >= 0);
3140 		ereport(ERROR,
3141 				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3142 				 errmsg("partition \"%s\" would overlap partition \"%s\"",
3143 						relname, get_rel_name(partdesc->oids[with])),
3144 				 parser_errposition(pstate, overlap_location)));
3145 	}
3146 }
3147 
3148 /*
3149  * check_default_partition_contents
3150  *
3151  * This function checks if there exists a row in the default partition that
3152  * would properly belong to the new partition being added.  If it finds one,
3153  * it throws an error.
3154  */
3155 void
3156 check_default_partition_contents(Relation parent, Relation default_rel,
3157 								 PartitionBoundSpec *new_spec)
3158 {
3159 	List	   *new_part_constraints;
3160 	List	   *def_part_constraints;
3161 	List	   *all_parts;
3162 	ListCell   *lc;
3163 
3164 	new_part_constraints = (new_spec->strategy == PARTITION_STRATEGY_LIST)
3165 		? get_qual_for_list(parent, new_spec)
3166 		: get_qual_for_range(parent, new_spec, false);
3167 	def_part_constraints =
3168 		get_proposed_default_constraint(new_part_constraints);
3169 
3170 	/*
3171 	 * Map the Vars in the constraint expression from parent's attnos to
3172 	 * default_rel's.
3173 	 */
3174 	def_part_constraints =
3175 		map_partition_varattnos(def_part_constraints, 1, default_rel,
3176 								parent);
3177 
3178 	/*
3179 	 * If the existing constraints on the default partition imply that it will
3180 	 * not contain any row that would belong to the new partition, we can
3181 	 * avoid scanning the default partition.
3182 	 */
3183 	if (PartConstraintImpliedByRelConstraint(default_rel, def_part_constraints))
3184 	{
3185 		ereport(DEBUG1,
3186 				(errmsg_internal("updated partition constraint for default partition \"%s\" is implied by existing constraints",
3187 								 RelationGetRelationName(default_rel))));
3188 		return;
3189 	}
3190 
3191 	/*
3192 	 * Scan the default partition and its subpartitions, and check for rows
3193 	 * that do not satisfy the revised partition constraints.
3194 	 */
3195 	if (default_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3196 		all_parts = find_all_inheritors(RelationGetRelid(default_rel),
3197 										AccessExclusiveLock, NULL);
3198 	else
3199 		all_parts = list_make1_oid(RelationGetRelid(default_rel));
3200 
3201 	foreach(lc, all_parts)
3202 	{
3203 		Oid			part_relid = lfirst_oid(lc);
3204 		Relation	part_rel;
3205 		Expr	   *partition_constraint;
3206 		EState	   *estate;
3207 		ExprState  *partqualstate = NULL;
3208 		Snapshot	snapshot;
3209 		ExprContext *econtext;
3210 		TableScanDesc scan;
3211 		MemoryContext oldCxt;
3212 		TupleTableSlot *tupslot;
3213 
3214 		/* Lock already taken above. */
3215 		if (part_relid != RelationGetRelid(default_rel))
3216 		{
3217 			part_rel = table_open(part_relid, NoLock);
3218 
3219 			/*
3220 			 * Map the Vars in the constraint expression from default_rel's
3221 			 * the sub-partition's.
3222 			 */
3223 			partition_constraint = make_ands_explicit(def_part_constraints);
3224 			partition_constraint = (Expr *)
3225 				map_partition_varattnos((List *) partition_constraint, 1,
3226 										part_rel, default_rel);
3227 
3228 			/*
3229 			 * If the partition constraints on default partition child imply
3230 			 * that it will not contain any row that would belong to the new
3231 			 * partition, we can avoid scanning the child table.
3232 			 */
3233 			if (PartConstraintImpliedByRelConstraint(part_rel,
3234 													 def_part_constraints))
3235 			{
3236 				ereport(DEBUG1,
3237 						(errmsg_internal("updated partition constraint for default partition \"%s\" is implied by existing constraints",
3238 										 RelationGetRelationName(part_rel))));
3239 
3240 				table_close(part_rel, NoLock);
3241 				continue;
3242 			}
3243 		}
3244 		else
3245 		{
3246 			part_rel = default_rel;
3247 			partition_constraint = make_ands_explicit(def_part_constraints);
3248 		}
3249 
3250 		/*
3251 		 * Only RELKIND_RELATION relations (i.e. leaf partitions) need to be
3252 		 * scanned.
3253 		 */
3254 		if (part_rel->rd_rel->relkind != RELKIND_RELATION)
3255 		{
3256 			if (part_rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
3257 				ereport(WARNING,
3258 						(errcode(ERRCODE_CHECK_VIOLATION),
3259 						 errmsg("skipped scanning foreign table \"%s\" which is a partition of default partition \"%s\"",
3260 								RelationGetRelationName(part_rel),
3261 								RelationGetRelationName(default_rel))));
3262 
3263 			if (RelationGetRelid(default_rel) != RelationGetRelid(part_rel))
3264 				table_close(part_rel, NoLock);
3265 
3266 			continue;
3267 		}
3268 
3269 		estate = CreateExecutorState();
3270 
3271 		/* Build expression execution states for partition check quals */
3272 		partqualstate = ExecPrepareExpr(partition_constraint, estate);
3273 
3274 		econtext = GetPerTupleExprContext(estate);
3275 		snapshot = RegisterSnapshot(GetLatestSnapshot());
3276 		tupslot = table_slot_create(part_rel, &estate->es_tupleTable);
3277 		scan = table_beginscan(part_rel, snapshot, 0, NULL);
3278 
3279 		/*
3280 		 * Switch to per-tuple memory context and reset it for each tuple
3281 		 * produced, so we don't leak memory.
3282 		 */
3283 		oldCxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
3284 
3285 		while (table_scan_getnextslot(scan, ForwardScanDirection, tupslot))
3286 		{
3287 			econtext->ecxt_scantuple = tupslot;
3288 
3289 			if (!ExecCheck(partqualstate, econtext))
3290 				ereport(ERROR,
3291 						(errcode(ERRCODE_CHECK_VIOLATION),
3292 						 errmsg("updated partition constraint for default partition \"%s\" would be violated by some row",
3293 								RelationGetRelationName(default_rel)),
3294 						 errtable(default_rel)));
3295 
3296 			ResetExprContext(econtext);
3297 			CHECK_FOR_INTERRUPTS();
3298 		}
3299 
3300 		MemoryContextSwitchTo(oldCxt);
3301 		table_endscan(scan);
3302 		UnregisterSnapshot(snapshot);
3303 		ExecDropSingleTupleTableSlot(tupslot);
3304 		FreeExecutorState(estate);
3305 
3306 		if (RelationGetRelid(default_rel) != RelationGetRelid(part_rel))
3307 			table_close(part_rel, NoLock);	/* keep the lock until commit */
3308 	}
3309 }
3310 
3311 /*
3312  * get_hash_partition_greatest_modulus
3313  *
3314  * Returns the greatest modulus of the hash partition bound.
3315  * This is no longer used in the core code, but we keep it around
3316  * in case external modules are using it.
3317  */
3318 int
3319 get_hash_partition_greatest_modulus(PartitionBoundInfo bound)
3320 {
3321 	Assert(bound && bound->strategy == PARTITION_STRATEGY_HASH);
3322 	return bound->nindexes;
3323 }
3324 
3325 /*
3326  * make_one_partition_rbound
3327  *
3328  * Return a PartitionRangeBound given a list of PartitionRangeDatum elements
3329  * and a flag telling whether the bound is lower or not.  Made into a function
3330  * because there are multiple sites that want to use this facility.
3331  */
3332 static PartitionRangeBound *
3333 make_one_partition_rbound(PartitionKey key, int index, List *datums, bool lower)
3334 {
3335 	PartitionRangeBound *bound;
3336 	ListCell   *lc;
3337 	int			i;
3338 
3339 	Assert(datums != NIL);
3340 
3341 	bound = (PartitionRangeBound *) palloc0(sizeof(PartitionRangeBound));
3342 	bound->index = index;
3343 	bound->datums = (Datum *) palloc0(key->partnatts * sizeof(Datum));
3344 	bound->kind = (PartitionRangeDatumKind *) palloc0(key->partnatts *
3345 													  sizeof(PartitionRangeDatumKind));
3346 	bound->lower = lower;
3347 
3348 	i = 0;
3349 	foreach(lc, datums)
3350 	{
3351 		PartitionRangeDatum *datum = castNode(PartitionRangeDatum, lfirst(lc));
3352 
3353 		/* What's contained in this range datum? */
3354 		bound->kind[i] = datum->kind;
3355 
3356 		if (datum->kind == PARTITION_RANGE_DATUM_VALUE)
3357 		{
3358 			Const	   *val = castNode(Const, datum->value);
3359 
3360 			if (val->constisnull)
3361 				elog(ERROR, "invalid range bound datum");
3362 			bound->datums[i] = val->constvalue;
3363 		}
3364 
3365 		i++;
3366 	}
3367 
3368 	return bound;
3369 }
3370 
3371 /*
3372  * partition_rbound_cmp
3373  *
3374  * For two range bounds this decides whether the 1st one (specified by
3375  * datums1, kind1, and lower1) is <, =, or > the bound specified in *b2.
3376  *
3377  * 0 is returned if they are equal, otherwise a non-zero integer whose sign
3378  * indicates the ordering, and whose absolute value gives the 1-based
3379  * partition key number of the first mismatching column.
3380  *
3381  * partnatts, partsupfunc and partcollation give the number of attributes in the
3382  * bounds to be compared, comparison function to be used and the collations of
3383  * attributes, respectively.
3384  *
3385  * Note that if the values of the two range bounds compare equal, then we take
3386  * into account whether they are upper or lower bounds, and an upper bound is
3387  * considered to be smaller than a lower bound. This is important to the way
3388  * that RelationBuildPartitionDesc() builds the PartitionBoundInfoData
3389  * structure, which only stores the upper bound of a common boundary between
3390  * two contiguous partitions.
3391  */
3392 static int32
3393 partition_rbound_cmp(int partnatts, FmgrInfo *partsupfunc,
3394 					 Oid *partcollation,
3395 					 Datum *datums1, PartitionRangeDatumKind *kind1,
3396 					 bool lower1, PartitionRangeBound *b2)
3397 {
3398 	int32		colnum = 0;
3399 	int32		cmpval = 0;		/* placate compiler */
3400 	int			i;
3401 	Datum	   *datums2 = b2->datums;
3402 	PartitionRangeDatumKind *kind2 = b2->kind;
3403 	bool		lower2 = b2->lower;
3404 
3405 	for (i = 0; i < partnatts; i++)
3406 	{
3407 		/* Track column number in case we need it for result */
3408 		colnum++;
3409 
3410 		/*
3411 		 * First, handle cases where the column is unbounded, which should not
3412 		 * invoke the comparison procedure, and should not consider any later
3413 		 * columns. Note that the PartitionRangeDatumKind enum elements
3414 		 * compare the same way as the values they represent.
3415 		 */
3416 		if (kind1[i] < kind2[i])
3417 			return -colnum;
3418 		else if (kind1[i] > kind2[i])
3419 			return colnum;
3420 		else if (kind1[i] != PARTITION_RANGE_DATUM_VALUE)
3421 		{
3422 			/*
3423 			 * The column bounds are both MINVALUE or both MAXVALUE. No later
3424 			 * columns should be considered, but we still need to compare
3425 			 * whether they are upper or lower bounds.
3426 			 */
3427 			break;
3428 		}
3429 
3430 		cmpval = DatumGetInt32(FunctionCall2Coll(&partsupfunc[i],
3431 												 partcollation[i],
3432 												 datums1[i],
3433 												 datums2[i]));
3434 		if (cmpval != 0)
3435 			break;
3436 	}
3437 
3438 	/*
3439 	 * If the comparison is anything other than equal, we're done. If they
3440 	 * compare equal though, we still have to consider whether the boundaries
3441 	 * are inclusive or exclusive.  Exclusive one is considered smaller of the
3442 	 * two.
3443 	 */
3444 	if (cmpval == 0 && lower1 != lower2)
3445 		cmpval = lower1 ? 1 : -1;
3446 
3447 	return cmpval == 0 ? 0 : (cmpval < 0 ? -colnum : colnum);
3448 }
3449 
3450 /*
3451  * partition_rbound_datum_cmp
3452  *
3453  * Return whether range bound (specified in rb_datums and rb_kind)
3454  * is <, =, or > partition key of tuple (tuple_datums)
3455  *
3456  * n_tuple_datums, partsupfunc and partcollation give number of attributes in
3457  * the bounds to be compared, comparison function to be used and the collations
3458  * of attributes resp.
3459  */
3460 int32
3461 partition_rbound_datum_cmp(FmgrInfo *partsupfunc, Oid *partcollation,
3462 						   Datum *rb_datums, PartitionRangeDatumKind *rb_kind,
3463 						   Datum *tuple_datums, int n_tuple_datums)
3464 {
3465 	int			i;
3466 	int32		cmpval = -1;
3467 
3468 	for (i = 0; i < n_tuple_datums; i++)
3469 	{
3470 		if (rb_kind[i] == PARTITION_RANGE_DATUM_MINVALUE)
3471 			return -1;
3472 		else if (rb_kind[i] == PARTITION_RANGE_DATUM_MAXVALUE)
3473 			return 1;
3474 
3475 		cmpval = DatumGetInt32(FunctionCall2Coll(&partsupfunc[i],
3476 												 partcollation[i],
3477 												 rb_datums[i],
3478 												 tuple_datums[i]));
3479 		if (cmpval != 0)
3480 			break;
3481 	}
3482 
3483 	return cmpval;
3484 }
3485 
3486 /*
3487  * partition_hbound_cmp
3488  *
3489  * Compares modulus first, then remainder if modulus is equal.
3490  */
3491 static int32
3492 partition_hbound_cmp(int modulus1, int remainder1, int modulus2, int remainder2)
3493 {
3494 	if (modulus1 < modulus2)
3495 		return -1;
3496 	if (modulus1 > modulus2)
3497 		return 1;
3498 	if (modulus1 == modulus2 && remainder1 != remainder2)
3499 		return (remainder1 > remainder2) ? 1 : -1;
3500 	return 0;
3501 }
3502 
3503 /*
3504  * partition_list_bsearch
3505  *		Returns the index of the greatest bound datum that is less than equal
3506  * 		to the given value or -1 if all of the bound datums are greater
3507  *
3508  * *is_equal is set to true if the bound datum at the returned index is equal
3509  * to the input value.
3510  */
3511 int
3512 partition_list_bsearch(FmgrInfo *partsupfunc, Oid *partcollation,
3513 					   PartitionBoundInfo boundinfo,
3514 					   Datum value, bool *is_equal)
3515 {
3516 	int			lo,
3517 				hi,
3518 				mid;
3519 
3520 	lo = -1;
3521 	hi = boundinfo->ndatums - 1;
3522 	while (lo < hi)
3523 	{
3524 		int32		cmpval;
3525 
3526 		mid = (lo + hi + 1) / 2;
3527 		cmpval = DatumGetInt32(FunctionCall2Coll(&partsupfunc[0],
3528 												 partcollation[0],
3529 												 boundinfo->datums[mid][0],
3530 												 value));
3531 		if (cmpval <= 0)
3532 		{
3533 			lo = mid;
3534 			*is_equal = (cmpval == 0);
3535 			if (*is_equal)
3536 				break;
3537 		}
3538 		else
3539 			hi = mid - 1;
3540 	}
3541 
3542 	return lo;
3543 }
3544 
3545 /*
3546  * partition_range_bsearch
3547  *		Returns the index of the greatest range bound that is less than or
3548  *		equal to the given range bound or -1 if all of the range bounds are
3549  *		greater
3550  *
3551  * Upon return from this function, *cmpval is set to 0 if the bound at the
3552  * returned index matches the input range bound exactly, otherwise a
3553  * non-zero integer whose sign indicates the ordering, and whose absolute
3554  * value gives the 1-based partition key number of the first mismatching
3555  * column.
3556  */
3557 static int
3558 partition_range_bsearch(int partnatts, FmgrInfo *partsupfunc,
3559 						Oid *partcollation,
3560 						PartitionBoundInfo boundinfo,
3561 						PartitionRangeBound *probe, int32 *cmpval)
3562 {
3563 	int			lo,
3564 				hi,
3565 				mid;
3566 
3567 	lo = -1;
3568 	hi = boundinfo->ndatums - 1;
3569 	while (lo < hi)
3570 	{
3571 		mid = (lo + hi + 1) / 2;
3572 		*cmpval = partition_rbound_cmp(partnatts, partsupfunc,
3573 									   partcollation,
3574 									   boundinfo->datums[mid],
3575 									   boundinfo->kind[mid],
3576 									   (boundinfo->indexes[mid] == -1),
3577 									   probe);
3578 		if (*cmpval <= 0)
3579 		{
3580 			lo = mid;
3581 			if (*cmpval == 0)
3582 				break;
3583 		}
3584 		else
3585 			hi = mid - 1;
3586 	}
3587 
3588 	return lo;
3589 }
3590 
3591 /*
3592  * partition_range_datum_bsearch
3593  *		Returns the index of the greatest range bound that is less than or
3594  *		equal to the given tuple or -1 if all of the range bounds are greater
3595  *
3596  * *is_equal is set to true if the range bound at the returned index is equal
3597  * to the input tuple.
3598  */
3599 int
3600 partition_range_datum_bsearch(FmgrInfo *partsupfunc, Oid *partcollation,
3601 							  PartitionBoundInfo boundinfo,
3602 							  int nvalues, Datum *values, bool *is_equal)
3603 {
3604 	int			lo,
3605 				hi,
3606 				mid;
3607 
3608 	lo = -1;
3609 	hi = boundinfo->ndatums - 1;
3610 	while (lo < hi)
3611 	{
3612 		int32		cmpval;
3613 
3614 		mid = (lo + hi + 1) / 2;
3615 		cmpval = partition_rbound_datum_cmp(partsupfunc,
3616 											partcollation,
3617 											boundinfo->datums[mid],
3618 											boundinfo->kind[mid],
3619 											values,
3620 											nvalues);
3621 		if (cmpval <= 0)
3622 		{
3623 			lo = mid;
3624 			*is_equal = (cmpval == 0);
3625 
3626 			if (*is_equal)
3627 				break;
3628 		}
3629 		else
3630 			hi = mid - 1;
3631 	}
3632 
3633 	return lo;
3634 }
3635 
3636 /*
3637  * partition_hash_bsearch
3638  *		Returns the index of the greatest (modulus, remainder) pair that is
3639  *		less than or equal to the given (modulus, remainder) pair or -1 if
3640  *		all of them are greater
3641  */
3642 int
3643 partition_hash_bsearch(PartitionBoundInfo boundinfo,
3644 					   int modulus, int remainder)
3645 {
3646 	int			lo,
3647 				hi,
3648 				mid;
3649 
3650 	lo = -1;
3651 	hi = boundinfo->ndatums - 1;
3652 	while (lo < hi)
3653 	{
3654 		int32		cmpval,
3655 					bound_modulus,
3656 					bound_remainder;
3657 
3658 		mid = (lo + hi + 1) / 2;
3659 		bound_modulus = DatumGetInt32(boundinfo->datums[mid][0]);
3660 		bound_remainder = DatumGetInt32(boundinfo->datums[mid][1]);
3661 		cmpval = partition_hbound_cmp(bound_modulus, bound_remainder,
3662 									  modulus, remainder);
3663 		if (cmpval <= 0)
3664 		{
3665 			lo = mid;
3666 
3667 			if (cmpval == 0)
3668 				break;
3669 		}
3670 		else
3671 			hi = mid - 1;
3672 	}
3673 
3674 	return lo;
3675 }
3676 
3677 /*
3678  * qsort_partition_hbound_cmp
3679  *
3680  * Hash bounds are sorted by modulus, then by remainder.
3681  */
3682 static int32
3683 qsort_partition_hbound_cmp(const void *a, const void *b)
3684 {
3685 	PartitionHashBound *h1 = (*(PartitionHashBound *const *) a);
3686 	PartitionHashBound *h2 = (*(PartitionHashBound *const *) b);
3687 
3688 	return partition_hbound_cmp(h1->modulus, h1->remainder,
3689 								h2->modulus, h2->remainder);
3690 }
3691 
3692 /*
3693  * qsort_partition_list_value_cmp
3694  *
3695  * Compare two list partition bound datums.
3696  */
3697 static int32
3698 qsort_partition_list_value_cmp(const void *a, const void *b, void *arg)
3699 {
3700 	Datum		val1 = (*(PartitionListValue *const *) a)->value,
3701 				val2 = (*(PartitionListValue *const *) b)->value;
3702 	PartitionKey key = (PartitionKey) arg;
3703 
3704 	return DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[0],
3705 										   key->partcollation[0],
3706 										   val1, val2));
3707 }
3708 
3709 /*
3710  * qsort_partition_rbound_cmp
3711  *
3712  * Used when sorting range bounds across all range partitions.
3713  */
3714 static int32
3715 qsort_partition_rbound_cmp(const void *a, const void *b, void *arg)
3716 {
3717 	PartitionRangeBound *b1 = (*(PartitionRangeBound *const *) a);
3718 	PartitionRangeBound *b2 = (*(PartitionRangeBound *const *) b);
3719 	PartitionKey key = (PartitionKey) arg;
3720 
3721 	return compare_range_bounds(key->partnatts, key->partsupfunc,
3722 								key->partcollation,
3723 								b1, b2);
3724 }
3725 
3726 /*
3727  * get_partition_operator
3728  *
3729  * Return oid of the operator of the given strategy for the given partition
3730  * key column.  It is assumed that the partitioning key is of the same type as
3731  * the chosen partitioning opclass, or at least binary-compatible.  In the
3732  * latter case, *need_relabel is set to true if the opclass is not of a
3733  * polymorphic type (indicating a RelabelType node needed on top), otherwise
3734  * false.
3735  */
3736 static Oid
3737 get_partition_operator(PartitionKey key, int col, StrategyNumber strategy,
3738 					   bool *need_relabel)
3739 {
3740 	Oid			operoid;
3741 
3742 	/*
3743 	 * Get the operator in the partitioning opfamily using the opclass'
3744 	 * declared input type as both left- and righttype.
3745 	 */
3746 	operoid = get_opfamily_member(key->partopfamily[col],
3747 								  key->partopcintype[col],
3748 								  key->partopcintype[col],
3749 								  strategy);
3750 	if (!OidIsValid(operoid))
3751 		elog(ERROR, "missing operator %d(%u,%u) in partition opfamily %u",
3752 			 strategy, key->partopcintype[col], key->partopcintype[col],
3753 			 key->partopfamily[col]);
3754 
3755 	/*
3756 	 * If the partition key column is not of the same type as the operator
3757 	 * class and not polymorphic, tell caller to wrap the non-Const expression
3758 	 * in a RelabelType.  This matches what parse_coerce.c does.
3759 	 */
3760 	*need_relabel = (key->parttypid[col] != key->partopcintype[col] &&
3761 					 key->partopcintype[col] != RECORDOID &&
3762 					 !IsPolymorphicType(key->partopcintype[col]));
3763 
3764 	return operoid;
3765 }
3766 
3767 /*
3768  * make_partition_op_expr
3769  *		Returns an Expr for the given partition key column with arg1 and
3770  *		arg2 as its leftop and rightop, respectively
3771  */
3772 static Expr *
3773 make_partition_op_expr(PartitionKey key, int keynum,
3774 					   uint16 strategy, Expr *arg1, Expr *arg2)
3775 {
3776 	Oid			operoid;
3777 	bool		need_relabel = false;
3778 	Expr	   *result = NULL;
3779 
3780 	/* Get the correct btree operator for this partitioning column */
3781 	operoid = get_partition_operator(key, keynum, strategy, &need_relabel);
3782 
3783 	/*
3784 	 * Chosen operator may be such that the non-Const operand needs to be
3785 	 * coerced, so apply the same; see the comment in
3786 	 * get_partition_operator().
3787 	 */
3788 	if (!IsA(arg1, Const) &&
3789 		(need_relabel ||
3790 		 key->partcollation[keynum] != key->parttypcoll[keynum]))
3791 		arg1 = (Expr *) makeRelabelType(arg1,
3792 										key->partopcintype[keynum],
3793 										-1,
3794 										key->partcollation[keynum],
3795 										COERCE_EXPLICIT_CAST);
3796 
3797 	/* Generate the actual expression */
3798 	switch (key->strategy)
3799 	{
3800 		case PARTITION_STRATEGY_LIST:
3801 			{
3802 				List	   *elems = (List *) arg2;
3803 				int			nelems = list_length(elems);
3804 
3805 				Assert(nelems >= 1);
3806 				Assert(keynum == 0);
3807 
3808 				if (nelems > 1 &&
3809 					!type_is_array(key->parttypid[keynum]))
3810 				{
3811 					ArrayExpr  *arrexpr;
3812 					ScalarArrayOpExpr *saopexpr;
3813 
3814 					/* Construct an ArrayExpr for the right-hand inputs */
3815 					arrexpr = makeNode(ArrayExpr);
3816 					arrexpr->array_typeid =
3817 						get_array_type(key->parttypid[keynum]);
3818 					arrexpr->array_collid = key->parttypcoll[keynum];
3819 					arrexpr->element_typeid = key->parttypid[keynum];
3820 					arrexpr->elements = elems;
3821 					arrexpr->multidims = false;
3822 					arrexpr->location = -1;
3823 
3824 					/* Build leftop = ANY (rightop) */
3825 					saopexpr = makeNode(ScalarArrayOpExpr);
3826 					saopexpr->opno = operoid;
3827 					saopexpr->opfuncid = get_opcode(operoid);
3828 					saopexpr->hashfuncid = InvalidOid;
3829 					saopexpr->useOr = true;
3830 					saopexpr->inputcollid = key->partcollation[keynum];
3831 					saopexpr->args = list_make2(arg1, arrexpr);
3832 					saopexpr->location = -1;
3833 
3834 					result = (Expr *) saopexpr;
3835 				}
3836 				else
3837 				{
3838 					List	   *elemops = NIL;
3839 					ListCell   *lc;
3840 
3841 					foreach(lc, elems)
3842 					{
3843 						Expr	   *elem = lfirst(lc),
3844 								   *elemop;
3845 
3846 						elemop = make_opclause(operoid,
3847 											   BOOLOID,
3848 											   false,
3849 											   arg1, elem,
3850 											   InvalidOid,
3851 											   key->partcollation[keynum]);
3852 						elemops = lappend(elemops, elemop);
3853 					}
3854 
3855 					result = nelems > 1 ? makeBoolExpr(OR_EXPR, elemops, -1) : linitial(elemops);
3856 				}
3857 				break;
3858 			}
3859 
3860 		case PARTITION_STRATEGY_RANGE:
3861 			result = make_opclause(operoid,
3862 								   BOOLOID,
3863 								   false,
3864 								   arg1, arg2,
3865 								   InvalidOid,
3866 								   key->partcollation[keynum]);
3867 			break;
3868 
3869 		default:
3870 			elog(ERROR, "invalid partitioning strategy");
3871 			break;
3872 	}
3873 
3874 	return result;
3875 }
3876 
3877 /*
3878  * get_qual_for_hash
3879  *
3880  * Returns a CHECK constraint expression to use as a hash partition's
3881  * constraint, given the parent relation and partition bound structure.
3882  *
3883  * The partition constraint for a hash partition is always a call to the
3884  * built-in function satisfies_hash_partition().
3885  */
3886 static List *
3887 get_qual_for_hash(Relation parent, PartitionBoundSpec *spec)
3888 {
3889 	PartitionKey key = RelationGetPartitionKey(parent);
3890 	FuncExpr   *fexpr;
3891 	Node	   *relidConst;
3892 	Node	   *modulusConst;
3893 	Node	   *remainderConst;
3894 	List	   *args;
3895 	ListCell   *partexprs_item;
3896 	int			i;
3897 
3898 	/* Fixed arguments. */
3899 	relidConst = (Node *) makeConst(OIDOID,
3900 									-1,
3901 									InvalidOid,
3902 									sizeof(Oid),
3903 									ObjectIdGetDatum(RelationGetRelid(parent)),
3904 									false,
3905 									true);
3906 
3907 	modulusConst = (Node *) makeConst(INT4OID,
3908 									  -1,
3909 									  InvalidOid,
3910 									  sizeof(int32),
3911 									  Int32GetDatum(spec->modulus),
3912 									  false,
3913 									  true);
3914 
3915 	remainderConst = (Node *) makeConst(INT4OID,
3916 										-1,
3917 										InvalidOid,
3918 										sizeof(int32),
3919 										Int32GetDatum(spec->remainder),
3920 										false,
3921 										true);
3922 
3923 	args = list_make3(relidConst, modulusConst, remainderConst);
3924 	partexprs_item = list_head(key->partexprs);
3925 
3926 	/* Add an argument for each key column. */
3927 	for (i = 0; i < key->partnatts; i++)
3928 	{
3929 		Node	   *keyCol;
3930 
3931 		/* Left operand */
3932 		if (key->partattrs[i] != 0)
3933 		{
3934 			keyCol = (Node *) makeVar(1,
3935 									  key->partattrs[i],
3936 									  key->parttypid[i],
3937 									  key->parttypmod[i],
3938 									  key->parttypcoll[i],
3939 									  0);
3940 		}
3941 		else
3942 		{
3943 			keyCol = (Node *) copyObject(lfirst(partexprs_item));
3944 			partexprs_item = lnext(key->partexprs, partexprs_item);
3945 		}
3946 
3947 		args = lappend(args, keyCol);
3948 	}
3949 
3950 	fexpr = makeFuncExpr(F_SATISFIES_HASH_PARTITION,
3951 						 BOOLOID,
3952 						 args,
3953 						 InvalidOid,
3954 						 InvalidOid,
3955 						 COERCE_EXPLICIT_CALL);
3956 
3957 	return list_make1(fexpr);
3958 }
3959 
3960 /*
3961  * get_qual_for_list
3962  *
3963  * Returns an implicit-AND list of expressions to use as a list partition's
3964  * constraint, given the parent relation and partition bound structure.
3965  *
3966  * The function returns NIL for a default partition when it's the only
3967  * partition since in that case there is no constraint.
3968  */
3969 static List *
3970 get_qual_for_list(Relation parent, PartitionBoundSpec *spec)
3971 {
3972 	PartitionKey key = RelationGetPartitionKey(parent);
3973 	List	   *result;
3974 	Expr	   *keyCol;
3975 	Expr	   *opexpr;
3976 	NullTest   *nulltest;
3977 	ListCell   *cell;
3978 	List	   *elems = NIL;
3979 	bool		list_has_null = false;
3980 
3981 	/*
3982 	 * Only single-column list partitioning is supported, so we are worried
3983 	 * only about the partition key with index 0.
3984 	 */
3985 	Assert(key->partnatts == 1);
3986 
3987 	/* Construct Var or expression representing the partition column */
3988 	if (key->partattrs[0] != 0)
3989 		keyCol = (Expr *) makeVar(1,
3990 								  key->partattrs[0],
3991 								  key->parttypid[0],
3992 								  key->parttypmod[0],
3993 								  key->parttypcoll[0],
3994 								  0);
3995 	else
3996 		keyCol = (Expr *) copyObject(linitial(key->partexprs));
3997 
3998 	/*
3999 	 * For default list partition, collect datums for all the partitions. The
4000 	 * default partition constraint should check that the partition key is
4001 	 * equal to none of those.
4002 	 */
4003 	if (spec->is_default)
4004 	{
4005 		int			i;
4006 		int			ndatums = 0;
4007 		PartitionDesc pdesc = RelationGetPartitionDesc(parent, false);
4008 		PartitionBoundInfo boundinfo = pdesc->boundinfo;
4009 
4010 		if (boundinfo)
4011 		{
4012 			ndatums = boundinfo->ndatums;
4013 
4014 			if (partition_bound_accepts_nulls(boundinfo))
4015 				list_has_null = true;
4016 		}
4017 
4018 		/*
4019 		 * If default is the only partition, there need not be any partition
4020 		 * constraint on it.
4021 		 */
4022 		if (ndatums == 0 && !list_has_null)
4023 			return NIL;
4024 
4025 		for (i = 0; i < ndatums; i++)
4026 		{
4027 			Const	   *val;
4028 
4029 			/*
4030 			 * Construct Const from known-not-null datum.  We must be careful
4031 			 * to copy the value, because our result has to be able to outlive
4032 			 * the relcache entry we're copying from.
4033 			 */
4034 			val = makeConst(key->parttypid[0],
4035 							key->parttypmod[0],
4036 							key->parttypcoll[0],
4037 							key->parttyplen[0],
4038 							datumCopy(*boundinfo->datums[i],
4039 									  key->parttypbyval[0],
4040 									  key->parttyplen[0]),
4041 							false,	/* isnull */
4042 							key->parttypbyval[0]);
4043 
4044 			elems = lappend(elems, val);
4045 		}
4046 	}
4047 	else
4048 	{
4049 		/*
4050 		 * Create list of Consts for the allowed values, excluding any nulls.
4051 		 */
4052 		foreach(cell, spec->listdatums)
4053 		{
4054 			Const	   *val = castNode(Const, lfirst(cell));
4055 
4056 			if (val->constisnull)
4057 				list_has_null = true;
4058 			else
4059 				elems = lappend(elems, copyObject(val));
4060 		}
4061 	}
4062 
4063 	if (elems)
4064 	{
4065 		/*
4066 		 * Generate the operator expression from the non-null partition
4067 		 * values.
4068 		 */
4069 		opexpr = make_partition_op_expr(key, 0, BTEqualStrategyNumber,
4070 										keyCol, (Expr *) elems);
4071 	}
4072 	else
4073 	{
4074 		/*
4075 		 * If there are no partition values, we don't need an operator
4076 		 * expression.
4077 		 */
4078 		opexpr = NULL;
4079 	}
4080 
4081 	if (!list_has_null)
4082 	{
4083 		/*
4084 		 * Gin up a "col IS NOT NULL" test that will be ANDed with the main
4085 		 * expression.  This might seem redundant, but the partition routing
4086 		 * machinery needs it.
4087 		 */
4088 		nulltest = makeNode(NullTest);
4089 		nulltest->arg = keyCol;
4090 		nulltest->nulltesttype = IS_NOT_NULL;
4091 		nulltest->argisrow = false;
4092 		nulltest->location = -1;
4093 
4094 		result = opexpr ? list_make2(nulltest, opexpr) : list_make1(nulltest);
4095 	}
4096 	else
4097 	{
4098 		/*
4099 		 * Gin up a "col IS NULL" test that will be OR'd with the main
4100 		 * expression.
4101 		 */
4102 		nulltest = makeNode(NullTest);
4103 		nulltest->arg = keyCol;
4104 		nulltest->nulltesttype = IS_NULL;
4105 		nulltest->argisrow = false;
4106 		nulltest->location = -1;
4107 
4108 		if (opexpr)
4109 		{
4110 			Expr	   *or;
4111 
4112 			or = makeBoolExpr(OR_EXPR, list_make2(nulltest, opexpr), -1);
4113 			result = list_make1(or);
4114 		}
4115 		else
4116 			result = list_make1(nulltest);
4117 	}
4118 
4119 	/*
4120 	 * Note that, in general, applying NOT to a constraint expression doesn't
4121 	 * necessarily invert the set of rows it accepts, because NOT (NULL) is
4122 	 * NULL.  However, the partition constraints we construct here never
4123 	 * evaluate to NULL, so applying NOT works as intended.
4124 	 */
4125 	if (spec->is_default)
4126 	{
4127 		result = list_make1(make_ands_explicit(result));
4128 		result = list_make1(makeBoolExpr(NOT_EXPR, result, -1));
4129 	}
4130 
4131 	return result;
4132 }
4133 
4134 /*
4135  * get_qual_for_range
4136  *
4137  * Returns an implicit-AND list of expressions to use as a range partition's
4138  * constraint, given the parent relation and partition bound structure.
4139  *
4140  * For a multi-column range partition key, say (a, b, c), with (al, bl, cl)
4141  * as the lower bound tuple and (au, bu, cu) as the upper bound tuple, we
4142  * generate an expression tree of the following form:
4143  *
4144  *	(a IS NOT NULL) and (b IS NOT NULL) and (c IS NOT NULL)
4145  *		AND
4146  *	(a > al OR (a = al AND b > bl) OR (a = al AND b = bl AND c >= cl))
4147  *		AND
4148  *	(a < au OR (a = au AND b < bu) OR (a = au AND b = bu AND c < cu))
4149  *
4150  * It is often the case that a prefix of lower and upper bound tuples contains
4151  * the same values, for example, (al = au), in which case, we will emit an
4152  * expression tree of the following form:
4153  *
4154  *	(a IS NOT NULL) and (b IS NOT NULL) and (c IS NOT NULL)
4155  *		AND
4156  *	(a = al)
4157  *		AND
4158  *	(b > bl OR (b = bl AND c >= cl))
4159  *		AND
4160  *	(b < bu OR (b = bu AND c < cu))
4161  *
4162  * If a bound datum is either MINVALUE or MAXVALUE, these expressions are
4163  * simplified using the fact that any value is greater than MINVALUE and less
4164  * than MAXVALUE. So, for example, if cu = MAXVALUE, c < cu is automatically
4165  * true, and we need not emit any expression for it, and the last line becomes
4166  *
4167  *	(b < bu) OR (b = bu), which is simplified to (b <= bu)
4168  *
4169  * In most common cases with only one partition column, say a, the following
4170  * expression tree will be generated: a IS NOT NULL AND a >= al AND a < au
4171  *
4172  * For default partition, it returns the negation of the constraints of all
4173  * the other partitions.
4174  *
4175  * External callers should pass for_default as false; we set it to true only
4176  * when recursing.
4177  */
4178 static List *
4179 get_qual_for_range(Relation parent, PartitionBoundSpec *spec,
4180 				   bool for_default)
4181 {
4182 	List	   *result = NIL;
4183 	ListCell   *cell1,
4184 			   *cell2,
4185 			   *partexprs_item,
4186 			   *partexprs_item_saved;
4187 	int			i,
4188 				j;
4189 	PartitionRangeDatum *ldatum,
4190 			   *udatum;
4191 	PartitionKey key = RelationGetPartitionKey(parent);
4192 	Expr	   *keyCol;
4193 	Const	   *lower_val,
4194 			   *upper_val;
4195 	List	   *lower_or_arms,
4196 			   *upper_or_arms;
4197 	int			num_or_arms,
4198 				current_or_arm;
4199 	ListCell   *lower_or_start_datum,
4200 			   *upper_or_start_datum;
4201 	bool		need_next_lower_arm,
4202 				need_next_upper_arm;
4203 
4204 	if (spec->is_default)
4205 	{
4206 		List	   *or_expr_args = NIL;
4207 		PartitionDesc pdesc = RelationGetPartitionDesc(parent, false);
4208 		Oid		   *inhoids = pdesc->oids;
4209 		int			nparts = pdesc->nparts,
4210 					i;
4211 
4212 		for (i = 0; i < nparts; i++)
4213 		{
4214 			Oid			inhrelid = inhoids[i];
4215 			HeapTuple	tuple;
4216 			Datum		datum;
4217 			bool		isnull;
4218 			PartitionBoundSpec *bspec;
4219 
4220 			tuple = SearchSysCache1(RELOID, inhrelid);
4221 			if (!HeapTupleIsValid(tuple))
4222 				elog(ERROR, "cache lookup failed for relation %u", inhrelid);
4223 
4224 			datum = SysCacheGetAttr(RELOID, tuple,
4225 									Anum_pg_class_relpartbound,
4226 									&isnull);
4227 			if (isnull)
4228 				elog(ERROR, "null relpartbound for relation %u", inhrelid);
4229 
4230 			bspec = (PartitionBoundSpec *)
4231 				stringToNode(TextDatumGetCString(datum));
4232 			if (!IsA(bspec, PartitionBoundSpec))
4233 				elog(ERROR, "expected PartitionBoundSpec");
4234 
4235 			if (!bspec->is_default)
4236 			{
4237 				List	   *part_qual;
4238 
4239 				part_qual = get_qual_for_range(parent, bspec, true);
4240 
4241 				/*
4242 				 * AND the constraints of the partition and add to
4243 				 * or_expr_args
4244 				 */
4245 				or_expr_args = lappend(or_expr_args, list_length(part_qual) > 1
4246 									   ? makeBoolExpr(AND_EXPR, part_qual, -1)
4247 									   : linitial(part_qual));
4248 			}
4249 			ReleaseSysCache(tuple);
4250 		}
4251 
4252 		if (or_expr_args != NIL)
4253 		{
4254 			Expr	   *other_parts_constr;
4255 
4256 			/*
4257 			 * Combine the constraints obtained for non-default partitions
4258 			 * using OR.  As requested, each of the OR's args doesn't include
4259 			 * the NOT NULL test for partition keys (which is to avoid its
4260 			 * useless repetition).  Add the same now.
4261 			 */
4262 			other_parts_constr =
4263 				makeBoolExpr(AND_EXPR,
4264 							 lappend(get_range_nulltest(key),
4265 									 list_length(or_expr_args) > 1
4266 									 ? makeBoolExpr(OR_EXPR, or_expr_args,
4267 													-1)
4268 									 : linitial(or_expr_args)),
4269 							 -1);
4270 
4271 			/*
4272 			 * Finally, the default partition contains everything *NOT*
4273 			 * contained in the non-default partitions.
4274 			 */
4275 			result = list_make1(makeBoolExpr(NOT_EXPR,
4276 											 list_make1(other_parts_constr), -1));
4277 		}
4278 
4279 		return result;
4280 	}
4281 
4282 	/*
4283 	 * If it is the recursive call for default, we skip the get_range_nulltest
4284 	 * to avoid accumulating the NullTest on the same keys for each partition.
4285 	 */
4286 	if (!for_default)
4287 		result = get_range_nulltest(key);
4288 
4289 	/*
4290 	 * Iterate over the key columns and check if the corresponding lower and
4291 	 * upper datums are equal using the btree equality operator for the
4292 	 * column's type.  If equal, we emit single keyCol = common_value
4293 	 * expression.  Starting from the first column for which the corresponding
4294 	 * lower and upper bound datums are not equal, we generate OR expressions
4295 	 * as shown in the function's header comment.
4296 	 */
4297 	i = 0;
4298 	partexprs_item = list_head(key->partexprs);
4299 	partexprs_item_saved = partexprs_item;	/* placate compiler */
4300 	forboth(cell1, spec->lowerdatums, cell2, spec->upperdatums)
4301 	{
4302 		EState	   *estate;
4303 		MemoryContext oldcxt;
4304 		Expr	   *test_expr;
4305 		ExprState  *test_exprstate;
4306 		Datum		test_result;
4307 		bool		isNull;
4308 
4309 		ldatum = castNode(PartitionRangeDatum, lfirst(cell1));
4310 		udatum = castNode(PartitionRangeDatum, lfirst(cell2));
4311 
4312 		/*
4313 		 * Since get_range_key_properties() modifies partexprs_item, and we
4314 		 * might need to start over from the previous expression in the later
4315 		 * part of this function, save away the current value.
4316 		 */
4317 		partexprs_item_saved = partexprs_item;
4318 
4319 		get_range_key_properties(key, i, ldatum, udatum,
4320 								 &partexprs_item,
4321 								 &keyCol,
4322 								 &lower_val, &upper_val);
4323 
4324 		/*
4325 		 * If either value is NULL, the corresponding partition bound is
4326 		 * either MINVALUE or MAXVALUE, and we treat them as unequal, because
4327 		 * even if they're the same, there is no common value to equate the
4328 		 * key column with.
4329 		 */
4330 		if (!lower_val || !upper_val)
4331 			break;
4332 
4333 		/* Create the test expression */
4334 		estate = CreateExecutorState();
4335 		oldcxt = MemoryContextSwitchTo(estate->es_query_cxt);
4336 		test_expr = make_partition_op_expr(key, i, BTEqualStrategyNumber,
4337 										   (Expr *) lower_val,
4338 										   (Expr *) upper_val);
4339 		fix_opfuncids((Node *) test_expr);
4340 		test_exprstate = ExecInitExpr(test_expr, NULL);
4341 		test_result = ExecEvalExprSwitchContext(test_exprstate,
4342 												GetPerTupleExprContext(estate),
4343 												&isNull);
4344 		MemoryContextSwitchTo(oldcxt);
4345 		FreeExecutorState(estate);
4346 
4347 		/* If not equal, go generate the OR expressions */
4348 		if (!DatumGetBool(test_result))
4349 			break;
4350 
4351 		/*
4352 		 * The bounds for the last key column can't be equal, because such a
4353 		 * range partition would never be allowed to be defined (it would have
4354 		 * an empty range otherwise).
4355 		 */
4356 		if (i == key->partnatts - 1)
4357 			elog(ERROR, "invalid range bound specification");
4358 
4359 		/* Equal, so generate keyCol = lower_val expression */
4360 		result = lappend(result,
4361 						 make_partition_op_expr(key, i, BTEqualStrategyNumber,
4362 												keyCol, (Expr *) lower_val));
4363 
4364 		i++;
4365 	}
4366 
4367 	/* First pair of lower_val and upper_val that are not equal. */
4368 	lower_or_start_datum = cell1;
4369 	upper_or_start_datum = cell2;
4370 
4371 	/* OR will have as many arms as there are key columns left. */
4372 	num_or_arms = key->partnatts - i;
4373 	current_or_arm = 0;
4374 	lower_or_arms = upper_or_arms = NIL;
4375 	need_next_lower_arm = need_next_upper_arm = true;
4376 	while (current_or_arm < num_or_arms)
4377 	{
4378 		List	   *lower_or_arm_args = NIL,
4379 				   *upper_or_arm_args = NIL;
4380 
4381 		/* Restart scan of columns from the i'th one */
4382 		j = i;
4383 		partexprs_item = partexprs_item_saved;
4384 
4385 		for_both_cell(cell1, spec->lowerdatums, lower_or_start_datum,
4386 					  cell2, spec->upperdatums, upper_or_start_datum)
4387 		{
4388 			PartitionRangeDatum *ldatum_next = NULL,
4389 					   *udatum_next = NULL;
4390 
4391 			ldatum = castNode(PartitionRangeDatum, lfirst(cell1));
4392 			if (lnext(spec->lowerdatums, cell1))
4393 				ldatum_next = castNode(PartitionRangeDatum,
4394 									   lfirst(lnext(spec->lowerdatums, cell1)));
4395 			udatum = castNode(PartitionRangeDatum, lfirst(cell2));
4396 			if (lnext(spec->upperdatums, cell2))
4397 				udatum_next = castNode(PartitionRangeDatum,
4398 									   lfirst(lnext(spec->upperdatums, cell2)));
4399 			get_range_key_properties(key, j, ldatum, udatum,
4400 									 &partexprs_item,
4401 									 &keyCol,
4402 									 &lower_val, &upper_val);
4403 
4404 			if (need_next_lower_arm && lower_val)
4405 			{
4406 				uint16		strategy;
4407 
4408 				/*
4409 				 * For the non-last columns of this arm, use the EQ operator.
4410 				 * For the last column of this arm, use GT, unless this is the
4411 				 * last column of the whole bound check, or the next bound
4412 				 * datum is MINVALUE, in which case use GE.
4413 				 */
4414 				if (j - i < current_or_arm)
4415 					strategy = BTEqualStrategyNumber;
4416 				else if (j == key->partnatts - 1 ||
4417 						 (ldatum_next &&
4418 						  ldatum_next->kind == PARTITION_RANGE_DATUM_MINVALUE))
4419 					strategy = BTGreaterEqualStrategyNumber;
4420 				else
4421 					strategy = BTGreaterStrategyNumber;
4422 
4423 				lower_or_arm_args = lappend(lower_or_arm_args,
4424 											make_partition_op_expr(key, j,
4425 																   strategy,
4426 																   keyCol,
4427 																   (Expr *) lower_val));
4428 			}
4429 
4430 			if (need_next_upper_arm && upper_val)
4431 			{
4432 				uint16		strategy;
4433 
4434 				/*
4435 				 * For the non-last columns of this arm, use the EQ operator.
4436 				 * For the last column of this arm, use LT, unless the next
4437 				 * bound datum is MAXVALUE, in which case use LE.
4438 				 */
4439 				if (j - i < current_or_arm)
4440 					strategy = BTEqualStrategyNumber;
4441 				else if (udatum_next &&
4442 						 udatum_next->kind == PARTITION_RANGE_DATUM_MAXVALUE)
4443 					strategy = BTLessEqualStrategyNumber;
4444 				else
4445 					strategy = BTLessStrategyNumber;
4446 
4447 				upper_or_arm_args = lappend(upper_or_arm_args,
4448 											make_partition_op_expr(key, j,
4449 																   strategy,
4450 																   keyCol,
4451 																   (Expr *) upper_val));
4452 			}
4453 
4454 			/*
4455 			 * Did we generate enough of OR's arguments?  First arm considers
4456 			 * the first of the remaining columns, second arm considers first
4457 			 * two of the remaining columns, and so on.
4458 			 */
4459 			++j;
4460 			if (j - i > current_or_arm)
4461 			{
4462 				/*
4463 				 * We must not emit any more arms if the new column that will
4464 				 * be considered is unbounded, or this one was.
4465 				 */
4466 				if (!lower_val || !ldatum_next ||
4467 					ldatum_next->kind != PARTITION_RANGE_DATUM_VALUE)
4468 					need_next_lower_arm = false;
4469 				if (!upper_val || !udatum_next ||
4470 					udatum_next->kind != PARTITION_RANGE_DATUM_VALUE)
4471 					need_next_upper_arm = false;
4472 				break;
4473 			}
4474 		}
4475 
4476 		if (lower_or_arm_args != NIL)
4477 			lower_or_arms = lappend(lower_or_arms,
4478 									list_length(lower_or_arm_args) > 1
4479 									? makeBoolExpr(AND_EXPR, lower_or_arm_args, -1)
4480 									: linitial(lower_or_arm_args));
4481 
4482 		if (upper_or_arm_args != NIL)
4483 			upper_or_arms = lappend(upper_or_arms,
4484 									list_length(upper_or_arm_args) > 1
4485 									? makeBoolExpr(AND_EXPR, upper_or_arm_args, -1)
4486 									: linitial(upper_or_arm_args));
4487 
4488 		/* If no work to do in the next iteration, break away. */
4489 		if (!need_next_lower_arm && !need_next_upper_arm)
4490 			break;
4491 
4492 		++current_or_arm;
4493 	}
4494 
4495 	/*
4496 	 * Generate the OR expressions for each of lower and upper bounds (if
4497 	 * required), and append to the list of implicitly ANDed list of
4498 	 * expressions.
4499 	 */
4500 	if (lower_or_arms != NIL)
4501 		result = lappend(result,
4502 						 list_length(lower_or_arms) > 1
4503 						 ? makeBoolExpr(OR_EXPR, lower_or_arms, -1)
4504 						 : linitial(lower_or_arms));
4505 	if (upper_or_arms != NIL)
4506 		result = lappend(result,
4507 						 list_length(upper_or_arms) > 1
4508 						 ? makeBoolExpr(OR_EXPR, upper_or_arms, -1)
4509 						 : linitial(upper_or_arms));
4510 
4511 	/*
4512 	 * As noted above, for non-default, we return list with constant TRUE. If
4513 	 * the result is NIL during the recursive call for default, it implies
4514 	 * this is the only other partition which can hold every value of the key
4515 	 * except NULL. Hence we return the NullTest result skipped earlier.
4516 	 */
4517 	if (result == NIL)
4518 		result = for_default
4519 			? get_range_nulltest(key)
4520 			: list_make1(makeBoolConst(true, false));
4521 
4522 	return result;
4523 }
4524 
4525 /*
4526  * get_range_key_properties
4527  *		Returns range partition key information for a given column
4528  *
4529  * This is a subroutine for get_qual_for_range, and its API is pretty
4530  * specialized to that caller.
4531  *
4532  * Constructs an Expr for the key column (returned in *keyCol) and Consts
4533  * for the lower and upper range limits (returned in *lower_val and
4534  * *upper_val).  For MINVALUE/MAXVALUE limits, NULL is returned instead of
4535  * a Const.  All of these structures are freshly palloc'd.
4536  *
4537  * *partexprs_item points to the cell containing the next expression in
4538  * the key->partexprs list, or NULL.  It may be advanced upon return.
4539  */
4540 static void
4541 get_range_key_properties(PartitionKey key, int keynum,
4542 						 PartitionRangeDatum *ldatum,
4543 						 PartitionRangeDatum *udatum,
4544 						 ListCell **partexprs_item,
4545 						 Expr **keyCol,
4546 						 Const **lower_val, Const **upper_val)
4547 {
4548 	/* Get partition key expression for this column */
4549 	if (key->partattrs[keynum] != 0)
4550 	{
4551 		*keyCol = (Expr *) makeVar(1,
4552 								   key->partattrs[keynum],
4553 								   key->parttypid[keynum],
4554 								   key->parttypmod[keynum],
4555 								   key->parttypcoll[keynum],
4556 								   0);
4557 	}
4558 	else
4559 	{
4560 		if (*partexprs_item == NULL)
4561 			elog(ERROR, "wrong number of partition key expressions");
4562 		*keyCol = copyObject(lfirst(*partexprs_item));
4563 		*partexprs_item = lnext(key->partexprs, *partexprs_item);
4564 	}
4565 
4566 	/* Get appropriate Const nodes for the bounds */
4567 	if (ldatum->kind == PARTITION_RANGE_DATUM_VALUE)
4568 		*lower_val = castNode(Const, copyObject(ldatum->value));
4569 	else
4570 		*lower_val = NULL;
4571 
4572 	if (udatum->kind == PARTITION_RANGE_DATUM_VALUE)
4573 		*upper_val = castNode(Const, copyObject(udatum->value));
4574 	else
4575 		*upper_val = NULL;
4576 }
4577 
4578 /*
4579  * get_range_nulltest
4580  *
4581  * A non-default range partition table does not currently allow partition
4582  * keys to be null, so emit an IS NOT NULL expression for each key column.
4583  */
4584 static List *
4585 get_range_nulltest(PartitionKey key)
4586 {
4587 	List	   *result = NIL;
4588 	NullTest   *nulltest;
4589 	ListCell   *partexprs_item;
4590 	int			i;
4591 
4592 	partexprs_item = list_head(key->partexprs);
4593 	for (i = 0; i < key->partnatts; i++)
4594 	{
4595 		Expr	   *keyCol;
4596 
4597 		if (key->partattrs[i] != 0)
4598 		{
4599 			keyCol = (Expr *) makeVar(1,
4600 									  key->partattrs[i],
4601 									  key->parttypid[i],
4602 									  key->parttypmod[i],
4603 									  key->parttypcoll[i],
4604 									  0);
4605 		}
4606 		else
4607 		{
4608 			if (partexprs_item == NULL)
4609 				elog(ERROR, "wrong number of partition key expressions");
4610 			keyCol = copyObject(lfirst(partexprs_item));
4611 			partexprs_item = lnext(key->partexprs, partexprs_item);
4612 		}
4613 
4614 		nulltest = makeNode(NullTest);
4615 		nulltest->arg = keyCol;
4616 		nulltest->nulltesttype = IS_NOT_NULL;
4617 		nulltest->argisrow = false;
4618 		nulltest->location = -1;
4619 		result = lappend(result, nulltest);
4620 	}
4621 
4622 	return result;
4623 }
4624 
4625 /*
4626  * compute_partition_hash_value
4627  *
4628  * Compute the hash value for given partition key values.
4629  */
4630 uint64
4631 compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc, Oid *partcollation,
4632 							 Datum *values, bool *isnull)
4633 {
4634 	int			i;
4635 	uint64		rowHash = 0;
4636 	Datum		seed = UInt64GetDatum(HASH_PARTITION_SEED);
4637 
4638 	for (i = 0; i < partnatts; i++)
4639 	{
4640 		/* Nulls are just ignored */
4641 		if (!isnull[i])
4642 		{
4643 			Datum		hash;
4644 
4645 			Assert(OidIsValid(partsupfunc[i].fn_oid));
4646 
4647 			/*
4648 			 * Compute hash for each datum value by calling respective
4649 			 * datatype-specific hash functions of each partition key
4650 			 * attribute.
4651 			 */
4652 			hash = FunctionCall2Coll(&partsupfunc[i], partcollation[i],
4653 									 values[i], seed);
4654 
4655 			/* Form a single 64-bit hash value */
4656 			rowHash = hash_combine64(rowHash, DatumGetUInt64(hash));
4657 		}
4658 	}
4659 
4660 	return rowHash;
4661 }
4662 
4663 /*
4664  * satisfies_hash_partition
4665  *
4666  * This is an SQL-callable function for use in hash partition constraints.
4667  * The first three arguments are the parent table OID, modulus, and remainder.
4668  * The remaining arguments are the value of the partitioning columns (or
4669  * expressions); these are hashed and the results are combined into a single
4670  * hash value by calling hash_combine64.
4671  *
4672  * Returns true if remainder produced when this computed single hash value is
4673  * divided by the given modulus is equal to given remainder, otherwise false.
4674  * NB: it's important that this never return null, as the constraint machinery
4675  * would consider that to be a "pass".
4676  *
4677  * See get_qual_for_hash() for usage.
4678  */
4679 Datum
4680 satisfies_hash_partition(PG_FUNCTION_ARGS)
4681 {
4682 	typedef struct ColumnsHashData
4683 	{
4684 		Oid			relid;
4685 		int			nkeys;
4686 		Oid			variadic_type;
4687 		int16		variadic_typlen;
4688 		bool		variadic_typbyval;
4689 		char		variadic_typalign;
4690 		Oid			partcollid[PARTITION_MAX_KEYS];
4691 		FmgrInfo	partsupfunc[FLEXIBLE_ARRAY_MEMBER];
4692 	} ColumnsHashData;
4693 	Oid			parentId;
4694 	int			modulus;
4695 	int			remainder;
4696 	Datum		seed = UInt64GetDatum(HASH_PARTITION_SEED);
4697 	ColumnsHashData *my_extra;
4698 	uint64		rowHash = 0;
4699 
4700 	/* Return false if the parent OID, modulus, or remainder is NULL. */
4701 	if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2))
4702 		PG_RETURN_BOOL(false);
4703 	parentId = PG_GETARG_OID(0);
4704 	modulus = PG_GETARG_INT32(1);
4705 	remainder = PG_GETARG_INT32(2);
4706 
4707 	/* Sanity check modulus and remainder. */
4708 	if (modulus <= 0)
4709 		ereport(ERROR,
4710 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4711 				 errmsg("modulus for hash partition must be an integer value greater than zero")));
4712 	if (remainder < 0)
4713 		ereport(ERROR,
4714 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4715 				 errmsg("remainder for hash partition must be an integer value greater than or equal to zero")));
4716 	if (remainder >= modulus)
4717 		ereport(ERROR,
4718 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4719 				 errmsg("remainder for hash partition must be less than modulus")));
4720 
4721 	/*
4722 	 * Cache hash function information.
4723 	 */
4724 	my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4725 	if (my_extra == NULL || my_extra->relid != parentId)
4726 	{
4727 		Relation	parent;
4728 		PartitionKey key;
4729 		int			j;
4730 
4731 		/* Open parent relation and fetch partition key info */
4732 		parent = relation_open(parentId, AccessShareLock);
4733 		key = RelationGetPartitionKey(parent);
4734 
4735 		/* Reject parent table that is not hash-partitioned. */
4736 		if (key == NULL || key->strategy != PARTITION_STRATEGY_HASH)
4737 			ereport(ERROR,
4738 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4739 					 errmsg("\"%s\" is not a hash partitioned table",
4740 							get_rel_name(parentId))));
4741 
4742 		if (!get_fn_expr_variadic(fcinfo->flinfo))
4743 		{
4744 			int			nargs = PG_NARGS() - 3;
4745 
4746 			/* complain if wrong number of column values */
4747 			if (key->partnatts != nargs)
4748 				ereport(ERROR,
4749 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4750 						 errmsg("number of partitioning columns (%d) does not match number of partition keys provided (%d)",
4751 								key->partnatts, nargs)));
4752 
4753 			/* allocate space for our cache */
4754 			fcinfo->flinfo->fn_extra =
4755 				MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt,
4756 									   offsetof(ColumnsHashData, partsupfunc) +
4757 									   sizeof(FmgrInfo) * nargs);
4758 			my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4759 			my_extra->relid = parentId;
4760 			my_extra->nkeys = key->partnatts;
4761 			memcpy(my_extra->partcollid, key->partcollation,
4762 				   key->partnatts * sizeof(Oid));
4763 
4764 			/* check argument types and save fmgr_infos */
4765 			for (j = 0; j < key->partnatts; ++j)
4766 			{
4767 				Oid			argtype = get_fn_expr_argtype(fcinfo->flinfo, j + 3);
4768 
4769 				if (argtype != key->parttypid[j] && !IsBinaryCoercible(argtype, key->parttypid[j]))
4770 					ereport(ERROR,
4771 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4772 							 errmsg("column %d of the partition key has type %s, but supplied value is of type %s",
4773 									j + 1, format_type_be(key->parttypid[j]), format_type_be(argtype))));
4774 
4775 				fmgr_info_copy(&my_extra->partsupfunc[j],
4776 							   &key->partsupfunc[j],
4777 							   fcinfo->flinfo->fn_mcxt);
4778 			}
4779 		}
4780 		else
4781 		{
4782 			ArrayType  *variadic_array = PG_GETARG_ARRAYTYPE_P(3);
4783 
4784 			/* allocate space for our cache -- just one FmgrInfo in this case */
4785 			fcinfo->flinfo->fn_extra =
4786 				MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt,
4787 									   offsetof(ColumnsHashData, partsupfunc) +
4788 									   sizeof(FmgrInfo));
4789 			my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4790 			my_extra->relid = parentId;
4791 			my_extra->nkeys = key->partnatts;
4792 			my_extra->variadic_type = ARR_ELEMTYPE(variadic_array);
4793 			get_typlenbyvalalign(my_extra->variadic_type,
4794 								 &my_extra->variadic_typlen,
4795 								 &my_extra->variadic_typbyval,
4796 								 &my_extra->variadic_typalign);
4797 			my_extra->partcollid[0] = key->partcollation[0];
4798 
4799 			/* check argument types */
4800 			for (j = 0; j < key->partnatts; ++j)
4801 				if (key->parttypid[j] != my_extra->variadic_type)
4802 					ereport(ERROR,
4803 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4804 							 errmsg("column %d of the partition key has type \"%s\", but supplied value is of type \"%s\"",
4805 									j + 1,
4806 									format_type_be(key->parttypid[j]),
4807 									format_type_be(my_extra->variadic_type))));
4808 
4809 			fmgr_info_copy(&my_extra->partsupfunc[0],
4810 						   &key->partsupfunc[0],
4811 						   fcinfo->flinfo->fn_mcxt);
4812 		}
4813 
4814 		/* Hold lock until commit */
4815 		relation_close(parent, NoLock);
4816 	}
4817 
4818 	if (!OidIsValid(my_extra->variadic_type))
4819 	{
4820 		int			nkeys = my_extra->nkeys;
4821 		int			i;
4822 
4823 		/*
4824 		 * For a non-variadic call, neither the number of arguments nor their
4825 		 * types can change across calls, so avoid the expense of rechecking
4826 		 * here.
4827 		 */
4828 
4829 		for (i = 0; i < nkeys; i++)
4830 		{
4831 			Datum		hash;
4832 
4833 			/* keys start from fourth argument of function. */
4834 			int			argno = i + 3;
4835 
4836 			if (PG_ARGISNULL(argno))
4837 				continue;
4838 
4839 			hash = FunctionCall2Coll(&my_extra->partsupfunc[i],
4840 									 my_extra->partcollid[i],
4841 									 PG_GETARG_DATUM(argno),
4842 									 seed);
4843 
4844 			/* Form a single 64-bit hash value */
4845 			rowHash = hash_combine64(rowHash, DatumGetUInt64(hash));
4846 		}
4847 	}
4848 	else
4849 	{
4850 		ArrayType  *variadic_array = PG_GETARG_ARRAYTYPE_P(3);
4851 		int			i;
4852 		int			nelems;
4853 		Datum	   *datum;
4854 		bool	   *isnull;
4855 
4856 		deconstruct_array(variadic_array,
4857 						  my_extra->variadic_type,
4858 						  my_extra->variadic_typlen,
4859 						  my_extra->variadic_typbyval,
4860 						  my_extra->variadic_typalign,
4861 						  &datum, &isnull, &nelems);
4862 
4863 		/* complain if wrong number of column values */
4864 		if (nelems != my_extra->nkeys)
4865 			ereport(ERROR,
4866 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4867 					 errmsg("number of partitioning columns (%d) does not match number of partition keys provided (%d)",
4868 							my_extra->nkeys, nelems)));
4869 
4870 		for (i = 0; i < nelems; i++)
4871 		{
4872 			Datum		hash;
4873 
4874 			if (isnull[i])
4875 				continue;
4876 
4877 			hash = FunctionCall2Coll(&my_extra->partsupfunc[0],
4878 									 my_extra->partcollid[0],
4879 									 datum[i],
4880 									 seed);
4881 
4882 			/* Form a single 64-bit hash value */
4883 			rowHash = hash_combine64(rowHash, DatumGetUInt64(hash));
4884 		}
4885 	}
4886 
4887 	PG_RETURN_BOOL(rowHash % modulus == remainder);
4888 }
4889