@@ -665,7 +665,20 @@ range_serialize(Ranges *range)
665
665
{
666
666
if (typbyval ) /* simple by-value data types */
667
667
{
668
- memcpy (ptr , & range -> values [i ], typlen );
668
+ Datum tmp ;
669
+
670
+ /*
671
+ * For values passed by value, we need to copy just the
672
+ * significant bytes - we can't use memcpy directly, as that
673
+ * assumes little endian behavior. store_att_byval does
674
+ * almost what we need, but it requires properly aligned
675
+ * buffer - the output buffer does not guarantee that. So we
676
+ * simply use a local Datum variable (which guarantees proper
677
+ * alignment), and then copy the value from it.
678
+ */
679
+ store_att_byval (& tmp , range -> values [i ], typlen );
680
+
681
+ memcpy (ptr , & tmp , typlen );
669
682
ptr += typlen ;
670
683
}
671
684
else if (typlen > 0 ) /* fixed-length by-ref types */
@@ -710,9 +723,11 @@ range_deserialize(int maxvalues, SerializedRanges *serialized)
710
723
{
711
724
int i ,
712
725
nvalues ;
713
- char * ptr ;
726
+ char * ptr ,
727
+ * dataptr ;
714
728
bool typbyval ;
715
729
int typlen ;
730
+ Size datalen ;
716
731
717
732
Ranges * range ;
718
733
@@ -740,34 +755,81 @@ range_deserialize(int maxvalues, SerializedRanges *serialized)
740
755
typlen = get_typlen (serialized -> typid );
741
756
742
757
/*
743
- * And now deconstruct the values into Datum array. We don't need to copy
744
- * the values and will instead just point the values to the serialized
745
- * varlena value (assuming it will be kept around).
758
+ * And now deconstruct the values into Datum array. We have to copy the
759
+ * data because the serialized representation ignores alignment, and we
760
+ * don't want to rely it will be kept around anyway.
761
+ */
762
+ ptr = serialized -> data ;
763
+
764
+ /*
765
+ * We don't want to allocate many pieces, so we just allocate everything
766
+ * in one chunk. How much space will we need?
767
+ *
768
+ * XXX We don't need to copy simple by-value data types.
769
+ */
770
+ datalen = 0 ;
771
+ dataptr = NULL ;
772
+ for (i = 0 ; (i < nvalues ) && (!typbyval ); i ++ )
773
+ {
774
+ if (typlen > 0 ) /* fixed-length by-ref types */
775
+ datalen += MAXALIGN (typlen );
776
+ else if (typlen == -1 ) /* varlena */
777
+ {
778
+ datalen += MAXALIGN (VARSIZE_ANY (DatumGetPointer (ptr )));
779
+ ptr += VARSIZE_ANY (DatumGetPointer (ptr ));
780
+ }
781
+ else if (typlen == -2 ) /* cstring */
782
+ {
783
+ datalen += MAXALIGN (strlen (DatumGetPointer (ptr )) + 1 );
784
+ ptr += strlen (DatumGetPointer (ptr )) + 1 ;
785
+ }
786
+ }
787
+
788
+ if (datalen > 0 )
789
+ dataptr = palloc (datalen );
790
+
791
+ /*
792
+ * Restore the source pointer (might have been modified when calculating
793
+ * the space we need to allocate).
746
794
*/
747
795
ptr = serialized -> data ;
748
796
749
797
for (i = 0 ; i < nvalues ; i ++ )
750
798
{
751
799
if (typbyval ) /* simple by-value data types */
752
800
{
753
- memcpy (& range -> values [i ], ptr , typlen );
801
+ Datum v = 0 ;
802
+
803
+ memcpy (& v , ptr , typlen );
804
+
805
+ range -> values [i ] = fetch_att (& v , true, typlen );
754
806
ptr += typlen ;
755
807
}
756
808
else if (typlen > 0 ) /* fixed-length by-ref types */
757
809
{
758
- /* no copy, just set the value to the pointer */
759
- range -> values [i ] = PointerGetDatum (ptr );
810
+ range -> values [i ] = PointerGetDatum (dataptr );
811
+
812
+ memcpy (dataptr , ptr , typlen );
813
+ dataptr += MAXALIGN (typlen );
814
+
760
815
ptr += typlen ;
761
816
}
762
817
else if (typlen == -1 ) /* varlena */
763
818
{
764
- range -> values [i ] = PointerGetDatum (ptr );
765
- ptr += VARSIZE_ANY (DatumGetPointer (range -> values [i ]));
819
+ range -> values [i ] = PointerGetDatum (dataptr );
820
+
821
+ memcpy (dataptr , ptr , VARSIZE_ANY (ptr ));
822
+ dataptr += MAXALIGN (VARSIZE_ANY (ptr ));
823
+ ptr += VARSIZE_ANY (ptr );
766
824
}
767
825
else if (typlen == -2 ) /* cstring */
768
826
{
769
- range -> values [i ] = PointerGetDatum (ptr );
770
- ptr += strlen (DatumGetPointer (range -> values [i ])) + 1 ;
827
+ Size slen = strlen (ptr ) + 1 ;
828
+ range -> values [i ] = PointerGetDatum (dataptr );
829
+
830
+ memcpy (dataptr , ptr , slen );
831
+ dataptr += MAXALIGN (slen );
832
+ ptr += (slen );
771
833
}
772
834
773
835
/* make sure we haven't overflown the buffer end */
@@ -2823,7 +2885,6 @@ minmax_multi_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype,
2823
2885
ObjectIdGetDatum (attr -> atttypid ),
2824
2886
ObjectIdGetDatum (subtype ),
2825
2887
Int16GetDatum (strategynum ));
2826
-
2827
2888
if (!HeapTupleIsValid (tuple ))
2828
2889
elog (ERROR , "missing operator %d(%u,%u) in opfamily %u" ,
2829
2890
strategynum , attr -> atttypid , subtype , opfamily );
0 commit comments