2626#include "libpq/pqformat.h"
2727#include "utils/builtins.h"
2828#include "utils/cash.h"
29+ #include "utils/float.h"
2930#include "utils/int8.h"
3031#include "utils/numeric.h"
3132#include "utils/pg_locale.h"
@@ -87,6 +88,82 @@ num_word(Cash value)
8788return buf ;
8889}/* num_word() */
8990
91+ static inline Cash
92+ cash_pl_cash (Cash c1 ,Cash c2 )
93+ {
94+ Cash res ;
95+
96+ if (unlikely (pg_add_s64_overflow (c1 ,c2 ,& res )))
97+ ereport (ERROR ,
98+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
99+ errmsg ("money out of range" )));
100+
101+ return res ;
102+ }
103+
104+ static inline Cash
105+ cash_mi_cash (Cash c1 ,Cash c2 )
106+ {
107+ Cash res ;
108+
109+ if (unlikely (pg_sub_s64_overflow (c1 ,c2 ,& res )))
110+ ereport (ERROR ,
111+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
112+ errmsg ("money out of range" )));
113+
114+ return res ;
115+ }
116+
117+ static inline Cash
118+ cash_mul_float8 (Cash c ,float8 f )
119+ {
120+ float8 res = rint (float8_mul ((float8 )c ,f ));
121+
122+ if (unlikely (isnan (res )|| !FLOAT8_FITS_IN_INT64 (res )))
123+ ereport (ERROR ,
124+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
125+ errmsg ("money out of range" )));
126+
127+ return (Cash )res ;
128+ }
129+
130+ static inline Cash
131+ cash_div_float8 (Cash c ,float8 f )
132+ {
133+ float8 res = rint (float8_div ((float8 )c ,f ));
134+
135+ if (unlikely (isnan (res )|| !FLOAT8_FITS_IN_INT64 (res )))
136+ ereport (ERROR ,
137+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
138+ errmsg ("money out of range" )));
139+
140+ return (Cash )res ;
141+ }
142+
143+ static inline Cash
144+ cash_mul_int64 (Cash c ,int64 i )
145+ {
146+ Cash res ;
147+
148+ if (unlikely (pg_mul_s64_overflow (c ,i ,& res )))
149+ ereport (ERROR ,
150+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
151+ errmsg ("money out of range" )));
152+
153+ return res ;
154+ }
155+
156+ static inline Cash
157+ cash_div_int64 (Cash c ,int64 i )
158+ {
159+ if (unlikely (i == 0 ))
160+ ereport (ERROR ,
161+ (errcode (ERRCODE_DIVISION_BY_ZERO ),
162+ errmsg ("division by zero" )));
163+
164+ return c /i ;
165+ }
166+
90167/* cash_in()
91168 * Convert a string to a cash data type.
92169 * Format is [$]###[,]###[.##]
@@ -612,11 +689,8 @@ cash_pl(PG_FUNCTION_ARGS)
612689{
613690Cash c1 = PG_GETARG_CASH (0 );
614691Cash c2 = PG_GETARG_CASH (1 );
615- Cash result ;
616-
617- result = c1 + c2 ;
618692
619- PG_RETURN_CASH (result );
693+ PG_RETURN_CASH (cash_pl_cash ( c1 , c2 ) );
620694}
621695
622696
@@ -628,11 +702,8 @@ cash_mi(PG_FUNCTION_ARGS)
628702{
629703Cash c1 = PG_GETARG_CASH (0 );
630704Cash c2 = PG_GETARG_CASH (1 );
631- Cash result ;
632-
633- result = c1 - c2 ;
634705
635- PG_RETURN_CASH (result );
706+ PG_RETURN_CASH (cash_mi_cash ( c1 , c2 ) );
636707}
637708
638709
@@ -664,10 +735,8 @@ cash_mul_flt8(PG_FUNCTION_ARGS)
664735{
665736Cash c = PG_GETARG_CASH (0 );
666737float8 f = PG_GETARG_FLOAT8 (1 );
667- Cash result ;
668738
669- result = rint (c * f );
670- PG_RETURN_CASH (result );
739+ PG_RETURN_CASH (cash_mul_float8 (c ,f ));
671740}
672741
673742
@@ -679,10 +748,8 @@ flt8_mul_cash(PG_FUNCTION_ARGS)
679748{
680749float8 f = PG_GETARG_FLOAT8 (0 );
681750Cash c = PG_GETARG_CASH (1 );
682- Cash result ;
683751
684- result = rint (f * c );
685- PG_RETURN_CASH (result );
752+ PG_RETURN_CASH (cash_mul_float8 (c ,f ));
686753}
687754
688755
@@ -694,15 +761,8 @@ cash_div_flt8(PG_FUNCTION_ARGS)
694761{
695762Cash c = PG_GETARG_CASH (0 );
696763float8 f = PG_GETARG_FLOAT8 (1 );
697- Cash result ;
698764
699- if (f == 0.0 )
700- ereport (ERROR ,
701- (errcode (ERRCODE_DIVISION_BY_ZERO ),
702- errmsg ("division by zero" )));
703-
704- result = rint (c /f );
705- PG_RETURN_CASH (result );
765+ PG_RETURN_CASH (cash_div_float8 (c ,f ));
706766}
707767
708768
@@ -714,10 +774,8 @@ cash_mul_flt4(PG_FUNCTION_ARGS)
714774{
715775Cash c = PG_GETARG_CASH (0 );
716776float4 f = PG_GETARG_FLOAT4 (1 );
717- Cash result ;
718777
719- result = rint (c * (float8 )f );
720- PG_RETURN_CASH (result );
778+ PG_RETURN_CASH (cash_mul_float8 (c , (float8 )f ));
721779}
722780
723781
@@ -729,10 +787,8 @@ flt4_mul_cash(PG_FUNCTION_ARGS)
729787{
730788float4 f = PG_GETARG_FLOAT4 (0 );
731789Cash c = PG_GETARG_CASH (1 );
732- Cash result ;
733790
734- result = rint ((float8 )f * c );
735- PG_RETURN_CASH (result );
791+ PG_RETURN_CASH (cash_mul_float8 (c , (float8 )f ));
736792}
737793
738794
@@ -745,15 +801,8 @@ cash_div_flt4(PG_FUNCTION_ARGS)
745801{
746802Cash c = PG_GETARG_CASH (0 );
747803float4 f = PG_GETARG_FLOAT4 (1 );
748- Cash result ;
749-
750- if (f == 0.0 )
751- ereport (ERROR ,
752- (errcode (ERRCODE_DIVISION_BY_ZERO ),
753- errmsg ("division by zero" )));
754804
755- result = rint (c / (float8 )f );
756- PG_RETURN_CASH (result );
805+ PG_RETURN_CASH (cash_div_float8 (c , (float8 )f ));
757806}
758807
759808
@@ -765,10 +814,8 @@ cash_mul_int8(PG_FUNCTION_ARGS)
765814{
766815Cash c = PG_GETARG_CASH (0 );
767816int64 i = PG_GETARG_INT64 (1 );
768- Cash result ;
769817
770- result = c * i ;
771- PG_RETURN_CASH (result );
818+ PG_RETURN_CASH (cash_mul_int64 (c ,i ));
772819}
773820
774821
@@ -780,10 +827,8 @@ int8_mul_cash(PG_FUNCTION_ARGS)
780827{
781828int64 i = PG_GETARG_INT64 (0 );
782829Cash c = PG_GETARG_CASH (1 );
783- Cash result ;
784830
785- result = i * c ;
786- PG_RETURN_CASH (result );
831+ PG_RETURN_CASH (cash_mul_int64 (c ,i ));
787832}
788833
789834/* cash_div_int8()
@@ -794,16 +839,8 @@ cash_div_int8(PG_FUNCTION_ARGS)
794839{
795840Cash c = PG_GETARG_CASH (0 );
796841int64 i = PG_GETARG_INT64 (1 );
797- Cash result ;
798-
799- if (i == 0 )
800- ereport (ERROR ,
801- (errcode (ERRCODE_DIVISION_BY_ZERO ),
802- errmsg ("division by zero" )));
803842
804- result = c /i ;
805-
806- PG_RETURN_CASH (result );
843+ PG_RETURN_CASH (cash_div_int64 (c ,i ));
807844}
808845
809846
@@ -815,10 +852,8 @@ cash_mul_int4(PG_FUNCTION_ARGS)
815852{
816853Cash c = PG_GETARG_CASH (0 );
817854int32 i = PG_GETARG_INT32 (1 );
818- Cash result ;
819855
820- result = c * i ;
821- PG_RETURN_CASH (result );
856+ PG_RETURN_CASH (cash_mul_int64 (c , (int64 )i ));
822857}
823858
824859
@@ -830,10 +865,8 @@ int4_mul_cash(PG_FUNCTION_ARGS)
830865{
831866int32 i = PG_GETARG_INT32 (0 );
832867Cash c = PG_GETARG_CASH (1 );
833- Cash result ;
834868
835- result = i * c ;
836- PG_RETURN_CASH (result );
869+ PG_RETURN_CASH (cash_mul_int64 (c , (int64 )i ));
837870}
838871
839872
@@ -846,16 +879,8 @@ cash_div_int4(PG_FUNCTION_ARGS)
846879{
847880Cash c = PG_GETARG_CASH (0 );
848881int32 i = PG_GETARG_INT32 (1 );
849- Cash result ;
850-
851- if (i == 0 )
852- ereport (ERROR ,
853- (errcode (ERRCODE_DIVISION_BY_ZERO ),
854- errmsg ("division by zero" )));
855-
856- result = c /i ;
857882
858- PG_RETURN_CASH (result );
883+ PG_RETURN_CASH (cash_div_int64 ( c , ( int64 ) i ) );
859884}
860885
861886
@@ -867,10 +892,8 @@ cash_mul_int2(PG_FUNCTION_ARGS)
867892{
868893Cash c = PG_GETARG_CASH (0 );
869894int16 s = PG_GETARG_INT16 (1 );
870- Cash result ;
871895
872- result = c * s ;
873- PG_RETURN_CASH (result );
896+ PG_RETURN_CASH (cash_mul_int64 (c , (int64 )s ));
874897}
875898
876899/* int2_mul_cash()
@@ -881,10 +904,8 @@ int2_mul_cash(PG_FUNCTION_ARGS)
881904{
882905int16 s = PG_GETARG_INT16 (0 );
883906Cash c = PG_GETARG_CASH (1 );
884- Cash result ;
885907
886- result = s * c ;
887- PG_RETURN_CASH (result );
908+ PG_RETURN_CASH (cash_mul_int64 (c , (int64 )s ));
888909}
889910
890911/* cash_div_int2()
@@ -896,15 +917,8 @@ cash_div_int2(PG_FUNCTION_ARGS)
896917{
897918Cash c = PG_GETARG_CASH (0 );
898919int16 s = PG_GETARG_INT16 (1 );
899- Cash result ;
900920
901- if (s == 0 )
902- ereport (ERROR ,
903- (errcode (ERRCODE_DIVISION_BY_ZERO ),
904- errmsg ("division by zero" )));
905-
906- result = c /s ;
907- PG_RETURN_CASH (result );
921+ PG_RETURN_CASH (cash_div_int64 (c , (int64 )s ));
908922}
909923
910924/* cashlarger()