@@ -358,10 +358,10 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
358
358
PartitionKey key ,int * * mapping )
359
359
{
360
360
PartitionBoundInfo boundinfo ;
361
- PartitionHashBound * * hbounds = NULL ;
361
+ PartitionHashBound * hbounds ;
362
362
int i ;
363
- int ndatums = 0 ;
364
363
int greatest_modulus ;
364
+ Datum * boundDatums ;
365
365
366
366
boundinfo = (PartitionBoundInfoData * )
367
367
palloc0 (sizeof (PartitionBoundInfoData ));
@@ -370,9 +370,8 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
370
370
boundinfo -> null_index = -1 ;
371
371
boundinfo -> default_index = -1 ;
372
372
373
- ndatums = nparts ;
374
- hbounds = (PartitionHashBound * * )
375
- palloc (nparts * sizeof (PartitionHashBound * ));
373
+ hbounds = (PartitionHashBound * )
374
+ palloc (nparts * sizeof (PartitionHashBound ));
376
375
377
376
/* Convert from node to the internal representation */
378
377
for (i = 0 ;i < nparts ;i ++ )
@@ -382,37 +381,44 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
382
381
if (spec -> strategy != PARTITION_STRATEGY_HASH )
383
382
elog (ERROR ,"invalid strategy in partition bound spec" );
384
383
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 ;
389
387
}
390
388
391
389
/* Sort all the bounds in ascending order */
392
- qsort (hbounds ,nparts ,sizeof (PartitionHashBound * ),
390
+ qsort (hbounds ,nparts ,sizeof (PartitionHashBound ),
393
391
qsort_partition_hbound_cmp );
394
392
395
393
/* After sorting, moduli are now stored in ascending order. */
396
- greatest_modulus = hbounds [ndatums - 1 ]-> modulus ;
394
+ greatest_modulus = hbounds [nparts - 1 ]. modulus ;
397
395
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 ;
400
399
boundinfo -> nindexes = greatest_modulus ;
401
400
boundinfo -> indexes = (int * )palloc (greatest_modulus * sizeof (int ));
402
401
for (i = 0 ;i < greatest_modulus ;i ++ )
403
402
boundinfo -> indexes [i ]= -1 ;
404
403
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
+
405
411
/*
406
412
* For hash partitioning, there are as many datums (modulus and remainder
407
413
* pairs) as there are partitions. Indexes are simply values ranging from
408
414
* 0 to (nparts - 1).
409
415
*/
410
416
for (i = 0 ;i < nparts ;i ++ )
411
417
{
412
- int modulus = hbounds [i ]-> modulus ;
413
- int remainder = hbounds [i ]-> remainder ;
418
+ int modulus = hbounds [i ]. modulus ;
419
+ int remainder = hbounds [i ]. remainder ;
414
420
415
- boundinfo -> datums [i ]= ( Datum * ) palloc ( 2 * sizeof ( Datum )) ;
421
+ boundinfo -> datums [i ]= & boundDatums [ i * 2 ] ;
416
422
boundinfo -> datums [i ][0 ]= Int32GetDatum (modulus );
417
423
boundinfo -> datums [i ][1 ]= Int32GetDatum (remainder );
418
424
@@ -424,14 +430,39 @@ create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
424
430
remainder += modulus ;
425
431
}
426
432
427
- (* mapping )[hbounds [i ]-> index ]= i ;
428
- pfree (hbounds [i ]);
433
+ (* mapping )[hbounds [i ].index ]= i ;
429
434
}
430
435
pfree (hbounds );
431
436
432
437
return boundinfo ;
433
438
}
434
439
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
+
435
466
/*
436
467
* create_list_bounds
437
468
*Create a PartitionBoundInfo for a list partitioned table
@@ -441,14 +472,14 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
441
472
PartitionKey key ,int * * mapping )
442
473
{
443
474
PartitionBoundInfo 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 ;
448
479
int next_index = 0 ;
449
480
int default_index = -1 ;
450
481
int null_index = -1 ;
451
- List * non_null_values = NIL ;
482
+ Datum * boundDatums ;
452
483
453
484
boundinfo = (PartitionBoundInfoData * )
454
485
palloc0 (sizeof (PartitionBoundInfoData ));
@@ -457,8 +488,12 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
457
488
boundinfo -> null_index = -1 ;
458
489
boundinfo -> default_index = -1 ;
459
490
491
+ ndatums = get_non_null_list_datum_count (boundspecs ,nparts );
492
+ all_values = (PartitionListValue * )
493
+ palloc (ndatums * sizeof (PartitionListValue ));
494
+
460
495
/* 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 ++ )
462
497
{
463
498
PartitionBoundSpec * spec = boundspecs [i ];
464
499
ListCell * c ;
@@ -480,14 +515,12 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
480
515
foreach (c ,spec -> listdatums )
481
516
{
482
517
Const * val = castNode (Const ,lfirst (c ));
483
- PartitionListValue * list_value = NULL ;
484
518
485
519
if (!val -> constisnull )
486
520
{
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 ++ ;
491
524
}
492
525
else
493
526
{
@@ -499,40 +532,28 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
499
532
elog (ERROR ,"found null more than once" );
500
533
null_index = i ;
501
534
}
502
-
503
- if (list_value )
504
- non_null_values = lappend (non_null_values ,list_value );
505
535
}
506
536
}
507
537
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 );
527
540
528
- qsort_arg (all_values ,ndatums ,sizeof (PartitionListValue * ),
541
+ qsort_arg (all_values ,ndatums ,sizeof (PartitionListValue ),
529
542
qsort_partition_list_value_cmp , (void * )key );
530
543
531
544
boundinfo -> ndatums = ndatums ;
532
545
boundinfo -> datums = (Datum * * )palloc0 (ndatums * sizeof (Datum * ));
546
+ boundinfo -> kind = NULL ;
533
547
boundinfo -> nindexes = ndatums ;
534
548
boundinfo -> indexes = (int * )palloc (ndatums * sizeof (int ));
535
549
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
+
536
557
/*
537
558
* Copy values. Canonical indexes are values ranging from 0 to (nparts -
538
559
* 1) assigned to each partition such that all datums of a given partition
@@ -541,10 +562,10 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
541
562
*/
542
563
for (i = 0 ;i < ndatums ;i ++ )
543
564
{
544
- int orig_index = all_values [i ]-> index ;
565
+ int orig_index = all_values [i ]. index ;
545
566
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 ,
548
569
key -> parttypbyval [0 ],
549
570
key -> parttyplen [0 ]);
550
571
@@ -555,6 +576,8 @@ create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
555
576
boundinfo -> indexes [i ]= (* mapping )[orig_index ];
556
577
}
557
578
579
+ pfree (all_values );
580
+
558
581
/*
559
582
* Set the canonical value for null_index, if any.
560
583
*
@@ -603,10 +626,13 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
603
626
PartitionRangeBound * * all_bounds ,
604
627
* prev ;
605
628
int i ,
606
- k ;
629
+ k ,
630
+ partnatts ;
607
631
int ndatums = 0 ;
608
632
int default_index = -1 ;
609
633
int next_index = 0 ;
634
+ Datum * boundDatums ;
635
+ PartitionRangeDatumKind * boundKinds ;
610
636
611
637
boundinfo = (PartitionBoundInfoData * )
612
638
palloc0 (sizeof (PartitionBoundInfoData ));
@@ -707,6 +733,8 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
707
733
prev = cur ;
708
734
}
709
735
736
+ pfree (all_bounds );
737
+
710
738
/* Update ndatums to hold the count of distinct datums. */
711
739
ndatums = k ;
712
740
@@ -731,16 +759,24 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
731
759
boundinfo -> nindexes = ndatums + 1 ;
732
760
boundinfo -> indexes = (int * )palloc ((ndatums + 1 )* sizeof (int ));
733
761
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
+
734
773
for (i = 0 ;i < ndatums ;i ++ )
735
774
{
736
775
int j ;
737
776
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 ++ )
744
780
{
745
781
if (rbounds [i ]-> kind [j ]== PARTITION_RANGE_DATUM_VALUE )
746
782
boundinfo -> datums [i ][j ]=
@@ -772,6 +808,8 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
772
808
}
773
809
}
774
810
811
+ pfree (rbounds );
812
+
775
813
/* Set the canonical value for default_index, if any. */
776
814
if (default_index != -1 )
777
815
{
@@ -914,6 +952,7 @@ partition_bounds_copy(PartitionBoundInfo src,
914
952
int partnatts ;
915
953
bool hash_part ;
916
954
int natts ;
955
+ Datum * boundDatums ;
917
956
918
957
dest = (PartitionBoundInfo )palloc (sizeof (PartitionBoundInfoData ));
919
958
@@ -929,15 +968,27 @@ partition_bounds_copy(PartitionBoundInfo src,
929
968
930
969
if (src -> kind != NULL )
931
970
{
971
+ PartitionRangeDatumKind * boundKinds ;
972
+
973
+ /* only RANGE partition should have a non-NULL kind */
974
+ Assert (key -> strategy == PARTITION_STRATEGY_RANGE );
975
+
932
976
dest -> kind = (PartitionRangeDatumKind * * )palloc (ndatums *
933
977
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
+
934
987
for (i = 0 ;i < ndatums ;i ++ )
935
988
{
936
- dest -> kind [i ]= (PartitionRangeDatumKind * )palloc (partnatts *
937
- sizeof (PartitionRangeDatumKind ));
938
-
989
+ dest -> kind [i ]= & boundKinds [i * partnatts ];
939
990
memcpy (dest -> kind [i ],src -> kind [i ],
940
- sizeof (PartitionRangeDatumKind )* key -> partnatts );
991
+ sizeof (PartitionRangeDatumKind )* partnatts );
941
992
}
942
993
}
943
994
else
@@ -949,12 +1000,13 @@ partition_bounds_copy(PartitionBoundInfo src,
949
1000
*/
950
1001
hash_part = (key -> strategy == PARTITION_STRATEGY_HASH );
951
1002
natts = hash_part ?2 :partnatts ;
1003
+ boundDatums = palloc (ndatums * natts * sizeof (Datum ));
952
1004
953
1005
for (i = 0 ;i < ndatums ;i ++ )
954
1006
{
955
1007
int j ;
956
1008
957
- dest -> datums [i ]= ( Datum * ) palloc ( sizeof ( Datum ) * natts ) ;
1009
+ dest -> datums [i ]= & boundDatums [ i * natts ] ;
958
1010
959
1011
for (j = 0 ;j < natts ;j ++ )
960
1012
{
@@ -3682,8 +3734,8 @@ partition_hash_bsearch(PartitionBoundInfo boundinfo,
3682
3734
static int32
3683
3735
qsort_partition_hbound_cmp (const void * a ,const void * b )
3684
3736
{
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 ;
3687
3739
3688
3740
return partition_hbound_cmp (h1 -> modulus ,h1 -> remainder ,
3689
3741
h2 -> modulus ,h2 -> remainder );
@@ -3697,8 +3749,8 @@ qsort_partition_hbound_cmp(const void *a, const void *b)
3697
3749
static int32
3698
3750
qsort_partition_list_value_cmp (const void * a ,const void * b ,void * arg )
3699
3751
{
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 ;
3702
3754
PartitionKey key = (PartitionKey )arg ;
3703
3755
3704
3756
return DatumGetInt32 (FunctionCall2Coll (& key -> partsupfunc [0 ],