26
26
#include "libpq/pqformat.h"
27
27
#include "utils/builtins.h"
28
28
#include "utils/cash.h"
29
+ #include "utils/float.h"
29
30
#include "utils/numeric.h"
30
31
#include "utils/pg_locale.h"
31
32
@@ -86,6 +87,82 @@ num_word(Cash value)
86
87
return buf ;
87
88
}/* num_word() */
88
89
90
+ static inline Cash
91
+ cash_pl_cash (Cash c1 ,Cash c2 )
92
+ {
93
+ Cash res ;
94
+
95
+ if (unlikely (pg_add_s64_overflow (c1 ,c2 ,& res )))
96
+ ereport (ERROR ,
97
+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
98
+ errmsg ("money out of range" )));
99
+
100
+ return res ;
101
+ }
102
+
103
+ static inline Cash
104
+ cash_mi_cash (Cash c1 ,Cash c2 )
105
+ {
106
+ Cash res ;
107
+
108
+ if (unlikely (pg_sub_s64_overflow (c1 ,c2 ,& res )))
109
+ ereport (ERROR ,
110
+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
111
+ errmsg ("money out of range" )));
112
+
113
+ return res ;
114
+ }
115
+
116
+ static inline Cash
117
+ cash_mul_float8 (Cash c ,float8 f )
118
+ {
119
+ float8 res = rint (float8_mul ((float8 )c ,f ));
120
+
121
+ if (unlikely (isnan (res )|| !FLOAT8_FITS_IN_INT64 (res )))
122
+ ereport (ERROR ,
123
+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
124
+ errmsg ("money out of range" )));
125
+
126
+ return (Cash )res ;
127
+ }
128
+
129
+ static inline Cash
130
+ cash_div_float8 (Cash c ,float8 f )
131
+ {
132
+ float8 res = rint (float8_div ((float8 )c ,f ));
133
+
134
+ if (unlikely (isnan (res )|| !FLOAT8_FITS_IN_INT64 (res )))
135
+ ereport (ERROR ,
136
+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
137
+ errmsg ("money out of range" )));
138
+
139
+ return (Cash )res ;
140
+ }
141
+
142
+ static inline Cash
143
+ cash_mul_int64 (Cash c ,int64 i )
144
+ {
145
+ Cash res ;
146
+
147
+ if (unlikely (pg_mul_s64_overflow (c ,i ,& res )))
148
+ ereport (ERROR ,
149
+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
150
+ errmsg ("money out of range" )));
151
+
152
+ return res ;
153
+ }
154
+
155
+ static inline Cash
156
+ cash_div_int64 (Cash c ,int64 i )
157
+ {
158
+ if (unlikely (i == 0 ))
159
+ ereport (ERROR ,
160
+ (errcode (ERRCODE_DIVISION_BY_ZERO ),
161
+ errmsg ("division by zero" )));
162
+
163
+ return c /i ;
164
+ }
165
+
89
166
/* cash_in()
90
167
* Convert a string to a cash data type.
91
168
* Format is [$]###[,]###[.##]
@@ -611,11 +688,8 @@ cash_pl(PG_FUNCTION_ARGS)
611
688
{
612
689
Cash c1 = PG_GETARG_CASH (0 );
613
690
Cash c2 = PG_GETARG_CASH (1 );
614
- Cash result ;
615
-
616
- result = c1 + c2 ;
617
691
618
- PG_RETURN_CASH (result );
692
+ PG_RETURN_CASH (cash_pl_cash ( c1 , c2 ) );
619
693
}
620
694
621
695
@@ -627,11 +701,8 @@ cash_mi(PG_FUNCTION_ARGS)
627
701
{
628
702
Cash c1 = PG_GETARG_CASH (0 );
629
703
Cash c2 = PG_GETARG_CASH (1 );
630
- Cash result ;
631
-
632
- result = c1 - c2 ;
633
704
634
- PG_RETURN_CASH (result );
705
+ PG_RETURN_CASH (cash_mi_cash ( c1 , c2 ) );
635
706
}
636
707
637
708
@@ -663,10 +734,8 @@ cash_mul_flt8(PG_FUNCTION_ARGS)
663
734
{
664
735
Cash c = PG_GETARG_CASH (0 );
665
736
float8 f = PG_GETARG_FLOAT8 (1 );
666
- Cash result ;
667
737
668
- result = rint (c * f );
669
- PG_RETURN_CASH (result );
738
+ PG_RETURN_CASH (cash_mul_float8 (c ,f ));
670
739
}
671
740
672
741
@@ -678,10 +747,8 @@ flt8_mul_cash(PG_FUNCTION_ARGS)
678
747
{
679
748
float8 f = PG_GETARG_FLOAT8 (0 );
680
749
Cash c = PG_GETARG_CASH (1 );
681
- Cash result ;
682
750
683
- result = rint (f * c );
684
- PG_RETURN_CASH (result );
751
+ PG_RETURN_CASH (cash_mul_float8 (c ,f ));
685
752
}
686
753
687
754
@@ -693,15 +760,8 @@ cash_div_flt8(PG_FUNCTION_ARGS)
693
760
{
694
761
Cash c = PG_GETARG_CASH (0 );
695
762
float8 f = PG_GETARG_FLOAT8 (1 );
696
- Cash result ;
697
763
698
- if (f == 0.0 )
699
- ereport (ERROR ,
700
- (errcode (ERRCODE_DIVISION_BY_ZERO ),
701
- errmsg ("division by zero" )));
702
-
703
- result = rint (c /f );
704
- PG_RETURN_CASH (result );
764
+ PG_RETURN_CASH (cash_div_float8 (c ,f ));
705
765
}
706
766
707
767
@@ -713,10 +773,8 @@ cash_mul_flt4(PG_FUNCTION_ARGS)
713
773
{
714
774
Cash c = PG_GETARG_CASH (0 );
715
775
float4 f = PG_GETARG_FLOAT4 (1 );
716
- Cash result ;
717
776
718
- result = rint (c * (float8 )f );
719
- PG_RETURN_CASH (result );
777
+ PG_RETURN_CASH (cash_mul_float8 (c , (float8 )f ));
720
778
}
721
779
722
780
@@ -728,10 +786,8 @@ flt4_mul_cash(PG_FUNCTION_ARGS)
728
786
{
729
787
float4 f = PG_GETARG_FLOAT4 (0 );
730
788
Cash c = PG_GETARG_CASH (1 );
731
- Cash result ;
732
789
733
- result = rint ((float8 )f * c );
734
- PG_RETURN_CASH (result );
790
+ PG_RETURN_CASH (cash_mul_float8 (c , (float8 )f ));
735
791
}
736
792
737
793
@@ -744,15 +800,8 @@ cash_div_flt4(PG_FUNCTION_ARGS)
744
800
{
745
801
Cash c = PG_GETARG_CASH (0 );
746
802
float4 f = PG_GETARG_FLOAT4 (1 );
747
- Cash result ;
748
-
749
- if (f == 0.0 )
750
- ereport (ERROR ,
751
- (errcode (ERRCODE_DIVISION_BY_ZERO ),
752
- errmsg ("division by zero" )));
753
803
754
- result = rint (c / (float8 )f );
755
- PG_RETURN_CASH (result );
804
+ PG_RETURN_CASH (cash_div_float8 (c , (float8 )f ));
756
805
}
757
806
758
807
@@ -764,10 +813,8 @@ cash_mul_int8(PG_FUNCTION_ARGS)
764
813
{
765
814
Cash c = PG_GETARG_CASH (0 );
766
815
int64 i = PG_GETARG_INT64 (1 );
767
- Cash result ;
768
816
769
- result = c * i ;
770
- PG_RETURN_CASH (result );
817
+ PG_RETURN_CASH (cash_mul_int64 (c ,i ));
771
818
}
772
819
773
820
@@ -779,10 +826,8 @@ int8_mul_cash(PG_FUNCTION_ARGS)
779
826
{
780
827
int64 i = PG_GETARG_INT64 (0 );
781
828
Cash c = PG_GETARG_CASH (1 );
782
- Cash result ;
783
829
784
- result = i * c ;
785
- PG_RETURN_CASH (result );
830
+ PG_RETURN_CASH (cash_mul_int64 (c ,i ));
786
831
}
787
832
788
833
/* cash_div_int8()
@@ -793,16 +838,8 @@ cash_div_int8(PG_FUNCTION_ARGS)
793
838
{
794
839
Cash c = PG_GETARG_CASH (0 );
795
840
int64 i = PG_GETARG_INT64 (1 );
796
- Cash result ;
797
-
798
- if (i == 0 )
799
- ereport (ERROR ,
800
- (errcode (ERRCODE_DIVISION_BY_ZERO ),
801
- errmsg ("division by zero" )));
802
841
803
- result = c /i ;
804
-
805
- PG_RETURN_CASH (result );
842
+ PG_RETURN_CASH (cash_div_int64 (c ,i ));
806
843
}
807
844
808
845
@@ -814,10 +851,8 @@ cash_mul_int4(PG_FUNCTION_ARGS)
814
851
{
815
852
Cash c = PG_GETARG_CASH (0 );
816
853
int32 i = PG_GETARG_INT32 (1 );
817
- Cash result ;
818
854
819
- result = c * i ;
820
- PG_RETURN_CASH (result );
855
+ PG_RETURN_CASH (cash_mul_int64 (c , (int64 )i ));
821
856
}
822
857
823
858
@@ -829,10 +864,8 @@ int4_mul_cash(PG_FUNCTION_ARGS)
829
864
{
830
865
int32 i = PG_GETARG_INT32 (0 );
831
866
Cash c = PG_GETARG_CASH (1 );
832
- Cash result ;
833
867
834
- result = i * c ;
835
- PG_RETURN_CASH (result );
868
+ PG_RETURN_CASH (cash_mul_int64 (c , (int64 )i ));
836
869
}
837
870
838
871
@@ -845,16 +878,8 @@ cash_div_int4(PG_FUNCTION_ARGS)
845
878
{
846
879
Cash c = PG_GETARG_CASH (0 );
847
880
int32 i = PG_GETARG_INT32 (1 );
848
- Cash result ;
849
-
850
- if (i == 0 )
851
- ereport (ERROR ,
852
- (errcode (ERRCODE_DIVISION_BY_ZERO ),
853
- errmsg ("division by zero" )));
854
-
855
- result = c /i ;
856
881
857
- PG_RETURN_CASH (result );
882
+ PG_RETURN_CASH (cash_div_int64 ( c , ( int64 ) i ) );
858
883
}
859
884
860
885
@@ -866,10 +891,8 @@ cash_mul_int2(PG_FUNCTION_ARGS)
866
891
{
867
892
Cash c = PG_GETARG_CASH (0 );
868
893
int16 s = PG_GETARG_INT16 (1 );
869
- Cash result ;
870
894
871
- result = c * s ;
872
- PG_RETURN_CASH (result );
895
+ PG_RETURN_CASH (cash_mul_int64 (c , (int64 )s ));
873
896
}
874
897
875
898
/* int2_mul_cash()
@@ -880,10 +903,8 @@ int2_mul_cash(PG_FUNCTION_ARGS)
880
903
{
881
904
int16 s = PG_GETARG_INT16 (0 );
882
905
Cash c = PG_GETARG_CASH (1 );
883
- Cash result ;
884
906
885
- result = s * c ;
886
- PG_RETURN_CASH (result );
907
+ PG_RETURN_CASH (cash_mul_int64 (c , (int64 )s ));
887
908
}
888
909
889
910
/* cash_div_int2()
@@ -895,15 +916,8 @@ cash_div_int2(PG_FUNCTION_ARGS)
895
916
{
896
917
Cash c = PG_GETARG_CASH (0 );
897
918
int16 s = PG_GETARG_INT16 (1 );
898
- Cash result ;
899
919
900
- if (s == 0 )
901
- ereport (ERROR ,
902
- (errcode (ERRCODE_DIVISION_BY_ZERO ),
903
- errmsg ("division by zero" )));
904
-
905
- result = c /s ;
906
- PG_RETURN_CASH (result );
920
+ PG_RETURN_CASH (cash_div_int64 (c , (int64 )s ));
907
921
}
908
922
909
923
/* cashlarger()