@@ -358,10 +358,10 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
358358 PartitionKey key , int * * mapping )
359359{
360360PartitionBoundInfo boundinfo ;
361- PartitionHashBound * * hbounds = NULL ;
361+ PartitionHashBound * hbounds ;
362362int i ;
363- int ndatums = 0 ;
364363int greatest_modulus ;
364+ Datum * boundDatums ;
365365
366366boundinfo = (PartitionBoundInfoData * )
367367palloc0 (sizeof (PartitionBoundInfoData ));
@@ -370,9 +370,8 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
370370boundinfo -> null_index = -1 ;
371371boundinfo -> default_index = -1 ;
372372
373- ndatums = nparts ;
374- hbounds = (PartitionHashBound * * )
375- palloc (nparts * sizeof (PartitionHashBound * ));
373+ hbounds = (PartitionHashBound * )
374+ palloc (nparts * sizeof (PartitionHashBound ));
376375
377376/* Convert from node to the internal representation */
378377for (i = 0 ; i < nparts ; i ++ )
@@ -382,37 +381,44 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
382381if (spec -> strategy != PARTITION_STRATEGY_HASH )
383382elog (ERROR , "invalid strategy in partition bound spec" );
384383
385- hbounds [i ] = (PartitionHashBound * ) palloc (sizeof (PartitionHashBound ));
386- hbounds [i ]-> modulus = spec -> modulus ;
387- hbounds [i ]-> remainder = spec -> remainder ;
388- hbounds [i ]-> index = i ;
384+ hbounds [i ].modulus = spec -> modulus ;
385+ hbounds [i ].remainder = spec -> remainder ;
386+ hbounds [i ].index = i ;
389387}
390388
391389/* Sort all the bounds in ascending order */
392- qsort (hbounds , nparts , sizeof (PartitionHashBound * ),
390+ qsort (hbounds , nparts , sizeof (PartitionHashBound ),
393391 qsort_partition_hbound_cmp );
394392
395393/* After sorting, moduli are now stored in ascending order. */
396- greatest_modulus = hbounds [ndatums - 1 ]-> modulus ;
394+ greatest_modulus = hbounds [nparts - 1 ]. modulus ;
397395
398- boundinfo -> ndatums = ndatums ;
399- boundinfo -> datums = (Datum * * ) palloc0 (ndatums * sizeof (Datum * ));
396+ boundinfo -> ndatums = nparts ;
397+ boundinfo -> datums = (Datum * * ) palloc0 (nparts * sizeof (Datum * ));
398+ boundinfo -> kind = NULL ;
400399boundinfo -> nindexes = greatest_modulus ;
401400boundinfo -> indexes = (int * ) palloc (greatest_modulus * sizeof (int ));
402401for (i = 0 ; i < greatest_modulus ; i ++ )
403402boundinfo -> indexes [i ] = -1 ;
404403
404+ /*
405+ * In the loop below, to save from allocating a series of small datum
406+ * arrays, here we just allocate a single array and below we'll just
407+ * assign a portion of this array per partition.
408+ */
409+ boundDatums = (Datum * ) palloc (nparts * 2 * sizeof (Datum ));
410+
405411/*
406412 * For hash partitioning, there are as many datums (modulus and remainder
407413 * pairs) as there are partitions. Indexes are simply values ranging from
408414 * 0 to (nparts - 1).
409415 */
410416for (i = 0 ; i < nparts ; i ++ )
411417{
412- int modulus = hbounds [i ]-> modulus ;
413- int remainder = hbounds [i ]-> remainder ;
418+ int modulus = hbounds [i ]. modulus ;
419+ int remainder = hbounds [i ]. remainder ;
414420
415- boundinfo -> datums [i ] = ( Datum * ) palloc ( 2 * sizeof ( Datum )) ;
421+ boundinfo -> datums [i ] = & boundDatums [ i * 2 ] ;
416422boundinfo -> datums [i ][0 ] = Int32GetDatum (modulus );
417423boundinfo -> datums [i ][1 ] = Int32GetDatum (remainder );
418424
@@ -424,14 +430,39 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
424430remainder += modulus ;
425431}
426432
427- (* mapping )[hbounds [i ]-> index ] = i ;
428- pfree (hbounds [i ]);
433+ (* mapping )[hbounds [i ].index ] = i ;
429434}
430435pfree (hbounds );
431436
432437return boundinfo ;
433438}
434439
440+ /*
441+ * get_non_null_list_datum_count
442+ * Counts the number of non-null Datums in each partition.
443+ */
444+ static int
445+ get_non_null_list_datum_count (PartitionBoundSpec * * boundspecs , int nparts )
446+ {
447+ int i ;
448+ int count = 0 ;
449+
450+ for (i = 0 ; i < nparts ; i ++ )
451+ {
452+ ListCell * lc ;
453+
454+ foreach (lc , boundspecs [i ]-> listdatums )
455+ {
456+ Const * val = castNode (Const , lfirst (lc ));
457+
458+ if (!val -> constisnull )
459+ count ++ ;
460+ }
461+ }
462+
463+ return count ;
464+ }
465+
435466/*
436467 * create_list_bounds
437468 * Create a PartitionBoundInfo for a list partitioned table
@@ -441,14 +472,14 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
441472 PartitionKey key , int * * mapping )
442473{
443474PartitionBoundInfo boundinfo ;
444- PartitionListValue * * all_values = NULL ;
445- ListCell * cell ;
446- int i = 0 ;
447- int ndatums = 0 ;
475+ PartitionListValue * all_values ;
476+ int i ;
477+ int j ;
478+ int ndatums ;
448479int next_index = 0 ;
449480int default_index = -1 ;
450481int null_index = -1 ;
451- List * non_null_values = NIL ;
482+ Datum * boundDatums ;
452483
453484boundinfo = (PartitionBoundInfoData * )
454485palloc0 (sizeof (PartitionBoundInfoData ));
@@ -457,8 +488,12 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
457488boundinfo -> null_index = -1 ;
458489boundinfo -> default_index = -1 ;
459490
491+ ndatums = get_non_null_list_datum_count (boundspecs , nparts );
492+ all_values = (PartitionListValue * )
493+ palloc (ndatums * sizeof (PartitionListValue ));
494+
460495/* Create a unified list of non-null values across all partitions. */
461- for (i = 0 ; i < nparts ; i ++ )
496+ for (j = 0 , i = 0 ; i < nparts ; i ++ )
462497{
463498PartitionBoundSpec * spec = boundspecs [i ];
464499ListCell * c ;
@@ -480,14 +515,12 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
480515foreach (c , spec -> listdatums )
481516{
482517Const * val = castNode (Const , lfirst (c ));
483- PartitionListValue * list_value = NULL ;
484518
485519if (!val -> constisnull )
486520{
487- list_value = (PartitionListValue * )
488- palloc0 (sizeof (PartitionListValue ));
489- list_value -> index = i ;
490- list_value -> value = val -> constvalue ;
521+ all_values [j ].index = i ;
522+ all_values [j ].value = val -> constvalue ;
523+ j ++ ;
491524}
492525else
493526{
@@ -499,40 +532,28 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
499532elog (ERROR , "found null more than once" );
500533null_index = i ;
501534}
502-
503- if (list_value )
504- non_null_values = lappend (non_null_values , list_value );
505535}
506536}
507537
508- ndatums = list_length (non_null_values );
509-
510- /*
511- * Collect all list values in one array. Alongside the value, we also save
512- * the index of partition the value comes from.
513- */
514- all_values = (PartitionListValue * * )
515- palloc (ndatums * sizeof (PartitionListValue * ));
516- i = 0 ;
517- foreach (cell , non_null_values )
518- {
519- PartitionListValue * src = lfirst (cell );
520-
521- all_values [i ] = (PartitionListValue * )
522- palloc (sizeof (PartitionListValue ));
523- all_values [i ]-> value = src -> value ;
524- all_values [i ]-> index = src -> index ;
525- i ++ ;
526- }
538+ /* ensure we found a Datum for every slot in the all_values array */
539+ Assert (j == ndatums );
527540
528- qsort_arg (all_values , ndatums , sizeof (PartitionListValue * ),
541+ qsort_arg (all_values , ndatums , sizeof (PartitionListValue ),
529542 qsort_partition_list_value_cmp , (void * ) key );
530543
531544boundinfo -> ndatums = ndatums ;
532545boundinfo -> datums = (Datum * * ) palloc0 (ndatums * sizeof (Datum * ));
546+ boundinfo -> kind = NULL ;
533547boundinfo -> nindexes = ndatums ;
534548boundinfo -> indexes = (int * ) palloc (ndatums * sizeof (int ));
535549
550+ /*
551+ * In the loop below, to save from allocating a series of small datum
552+ * arrays, here we just allocate a single array and below we'll just
553+ * assign a portion of this array per datum.
554+ */
555+ boundDatums = (Datum * ) palloc (ndatums * sizeof (Datum ));
556+
536557/*
537558 * Copy values. Canonical indexes are values ranging from 0 to (nparts -
538559 * 1) assigned to each partition such that all datums of a given partition
@@ -541,10 +562,10 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
541562 */
542563for (i = 0 ; i < ndatums ; i ++ )
543564{
544- int orig_index = all_values [i ]-> index ;
565+ int orig_index = all_values [i ]. index ;
545566
546- boundinfo -> datums [i ] = ( Datum * ) palloc ( sizeof ( Datum )) ;
547- boundinfo -> datums [i ][0 ] = datumCopy (all_values [i ]-> value ,
567+ boundinfo -> datums [i ] = & boundDatums [ i ] ;
568+ boundinfo -> datums [i ][0 ] = datumCopy (all_values [i ]. value ,
548569key -> parttypbyval [0 ],
549570key -> parttyplen [0 ]);
550571
@@ -555,6 +576,8 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
555576boundinfo -> indexes [i ] = (* mapping )[orig_index ];
556577}
557578
579+ pfree (all_values );
580+
558581/*
559582 * Set the canonical value for null_index, if any.
560583 *
@@ -603,10 +626,13 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
603626PartitionRangeBound * * all_bounds ,
604627 * prev ;
605628int i ,
606- k ;
629+ k ,
630+ partnatts ;
607631int ndatums = 0 ;
608632int default_index = -1 ;
609633int next_index = 0 ;
634+ Datum * boundDatums ;
635+ PartitionRangeDatumKind * boundKinds ;
610636
611637boundinfo = (PartitionBoundInfoData * )
612638palloc0 (sizeof (PartitionBoundInfoData ));
@@ -707,6 +733,8 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
707733prev = cur ;
708734}
709735
736+ pfree (all_bounds );
737+
710738/* Update ndatums to hold the count of distinct datums. */
711739ndatums = k ;
712740
@@ -731,16 +759,24 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
731759boundinfo -> nindexes = ndatums + 1 ;
732760boundinfo -> indexes = (int * ) palloc ((ndatums + 1 ) * sizeof (int ));
733761
762+ /*
763+ * In the loop below, to save from allocating a series of small arrays,
764+ * here we just allocate a single array for Datums and another for
765+ * PartitionRangeDatumKinds, below we'll just assign a portion of these
766+ * arrays in each loop.
767+ */
768+ partnatts = key -> partnatts ;
769+ boundDatums = (Datum * ) palloc (ndatums * partnatts * sizeof (Datum ));
770+ boundKinds = (PartitionRangeDatumKind * ) palloc (ndatums * partnatts *
771+ sizeof (PartitionRangeDatumKind ));
772+
734773for (i = 0 ; i < ndatums ; i ++ )
735774{
736775int j ;
737776
738- boundinfo -> datums [i ] = (Datum * ) palloc (key -> partnatts *
739- sizeof (Datum ));
740- boundinfo -> kind [i ] = (PartitionRangeDatumKind * )
741- palloc (key -> partnatts *
742- sizeof (PartitionRangeDatumKind ));
743- for (j = 0 ; j < key -> partnatts ; j ++ )
777+ boundinfo -> datums [i ] = & boundDatums [i * partnatts ];
778+ boundinfo -> kind [i ] = & boundKinds [i * partnatts ];
779+ for (j = 0 ; j < partnatts ; j ++ )
744780{
745781if (rbounds [i ]-> kind [j ] == PARTITION_RANGE_DATUM_VALUE )
746782boundinfo -> datums [i ][j ] =
@@ -772,6 +808,8 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
772808}
773809}
774810
811+ pfree (rbounds );
812+
775813/* Set the canonical value for default_index, if any. */
776814if (default_index != -1 )
777815{
@@ -914,6 +952,7 @@ partition_bounds_copy(PartitionBoundInfo src,
914952int partnatts ;
915953bool hash_part ;
916954int natts ;
955+ Datum * boundDatums ;
917956
918957dest = (PartitionBoundInfo ) palloc (sizeof (PartitionBoundInfoData ));
919958
@@ -929,15 +968,27 @@ partition_bounds_copy(PartitionBoundInfo src,
929968
930969if (src -> kind != NULL )
931970{
971+ PartitionRangeDatumKind * boundKinds ;
972+
973+ /* only RANGE partition should have a non-NULL kind */
974+ Assert (key -> strategy == PARTITION_STRATEGY_RANGE );
975+
932976dest -> kind = (PartitionRangeDatumKind * * ) palloc (ndatums *
933977 sizeof (PartitionRangeDatumKind * ));
978+
979+ /*
980+ * In the loop below, to save from allocating a series of small arrays
981+ * for storing the PartitionRangeDatumKind, we allocate a single chunk
982+ * here and use a smaller portion of it for each datum.
983+ */
984+ boundKinds = (PartitionRangeDatumKind * ) palloc (ndatums * partnatts *
985+ sizeof (PartitionRangeDatumKind ));
986+
934987for (i = 0 ; i < ndatums ; i ++ )
935988{
936- dest -> kind [i ] = (PartitionRangeDatumKind * ) palloc (partnatts *
937- sizeof (PartitionRangeDatumKind ));
938-
989+ dest -> kind [i ] = & boundKinds [i * partnatts ];
939990memcpy (dest -> kind [i ], src -> kind [i ],
940- sizeof (PartitionRangeDatumKind ) * key -> partnatts );
991+ sizeof (PartitionRangeDatumKind ) * partnatts );
941992}
942993}
943994else
@@ -949,12 +1000,13 @@ partition_bounds_copy(PartitionBoundInfo src,
9491000 */
9501001hash_part = (key -> strategy == PARTITION_STRATEGY_HASH );
9511002natts = hash_part ? 2 : partnatts ;
1003+ boundDatums = palloc (ndatums * natts * sizeof (Datum ));
9521004
9531005for (i = 0 ; i < ndatums ; i ++ )
9541006{
9551007int j ;
9561008
957- dest -> datums [i ] = ( Datum * ) palloc ( sizeof ( Datum ) * natts ) ;
1009+ dest -> datums [i ] = & boundDatums [ i * natts ] ;
9581010
9591011for (j = 0 ; j < natts ; j ++ )
9601012{
@@ -3682,8 +3734,8 @@ partition_hash_bsearch(PartitionBoundInfo boundinfo,
36823734static int32
36833735qsort_partition_hbound_cmp (const void * a , const void * b )
36843736{
3685- PartitionHashBound * h1 = (* ( PartitionHashBound * const * ) a ) ;
3686- PartitionHashBound * h2 = (* ( PartitionHashBound * const * ) b ) ;
3737+ PartitionHashBound * const h1 = (PartitionHashBound * const ) a ;
3738+ PartitionHashBound * const h2 = (PartitionHashBound * const ) b ;
36873739
36883740return partition_hbound_cmp (h1 -> modulus , h1 -> remainder ,
36893741h2 -> modulus , h2 -> remainder );
@@ -3697,8 +3749,8 @@ qsort_partition_hbound_cmp(const void *a, const void *b)
36973749static int32
36983750qsort_partition_list_value_cmp (const void * a , const void * b , void * arg )
36993751{
3700- Datum val1 = (* (PartitionListValue * const * ) a )-> value ,
3701- val2 = (* (PartitionListValue * const * ) b )-> value ;
3752+ Datum val1 = ((PartitionListValue * const ) a )-> value ,
3753+ val2 = ((PartitionListValue * const ) b )-> value ;
37023754PartitionKey key = (PartitionKey ) arg ;
37033755
37043756return DatumGetInt32 (FunctionCall2Coll (& key -> partsupfunc [0 ],
0 commit comments