2626#include "libpq/pqformat.h"
2727#include "utils/builtins.h"
2828#include "utils/cash.h"
29+ #include "utils/float.h"
2930#include "utils/numeric.h"
3031#include "utils/pg_locale.h"
3132
@@ -86,6 +87,82 @@ num_word(Cash value)
8687 return buf ;
8788} /* num_word() */
8889
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+
89166/* cash_in()
90167 * Convert a string to a cash data type.
91168 * Format is [$]###[,]###[.##]
@@ -612,11 +689,8 @@ cash_pl(PG_FUNCTION_ARGS)
612689{
613690 Cash c1 = PG_GETARG_CASH (0 );
614691 Cash 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{
629703 Cash c1 = PG_GETARG_CASH (0 );
630704 Cash 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{
665736 Cash c = PG_GETARG_CASH (0 );
666737 float8 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{
680749 float8 f = PG_GETARG_FLOAT8 (0 );
681750 Cash 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{
695762 Cash c = PG_GETARG_CASH (0 );
696763 float8 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{
715775 Cash c = PG_GETARG_CASH (0 );
716776 float4 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{
730788 float4 f = PG_GETARG_FLOAT4 (0 );
731789 Cash 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{
746802 Cash c = PG_GETARG_CASH (0 );
747803 float4 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{
766815 Cash c = PG_GETARG_CASH (0 );
767816 int64 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{
781828 int64 i = PG_GETARG_INT64 (0 );
782829 Cash 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{
795840 Cash c = PG_GETARG_CASH (0 );
796841 int64 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{
816853 Cash c = PG_GETARG_CASH (0 );
817854 int32 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{
831866 int32 i = PG_GETARG_INT32 (0 );
832867 Cash 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{
847880 Cash c = PG_GETARG_CASH (0 );
848881 int32 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{
868893 Cash c = PG_GETARG_CASH (0 );
869894 int16 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{
882905 int16 s = PG_GETARG_INT16 (0 );
883906 Cash 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{
897918 Cash c = PG_GETARG_CASH (0 );
898919 int16 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()
0 commit comments