LCOV - differential code coverage report
Current view: top level - src/backend/partitioning - partbounds.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 95.5 % 1572 1501 3 13 54 1 17 962 6 516 52 964 1 8
Current Date: 2023-04-08 17:13:01 Functions: 98.1 % 52 51 1 51 1 51
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 100.0 % 1 1 1
Legend: Lines: hit not hit (120,180] days: 25.0 % 4 1 3 1
(180,240] days: 100.0 % 4 4 4
(240..) days: 95.6 % 1563 1495 13 54 1 17 962 516 52 964
Function coverage date bins:
(240..) days: 49.0 % 104 51 1 51 1 51

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

Generated by: LCOV version v1.16-55-g56c0a2a