PostgreSQL Source Code  git master
cash.c File Reference
#include "postgres.h"
#include <limits.h>
#include <ctype.h>
#include <math.h>
#include "common/int.h"
#include "libpq/pqformat.h"
#include "utils/builtins.h"
#include "utils/cash.h"
#include "utils/float.h"
#include "utils/numeric.h"
#include "utils/pg_locale.h"
Include dependency graph for cash.c:

Go to the source code of this file.

Functions

static void append_num_word (StringInfo buf, Cash value)
 
static Cash cash_pl_cash (Cash c1, Cash c2)
 
static Cash cash_mi_cash (Cash c1, Cash c2)
 
static Cash cash_mul_float8 (Cash c, float8 f)
 
static Cash cash_div_float8 (Cash c, float8 f)
 
static Cash cash_mul_int64 (Cash c, int64 i)
 
static Cash cash_div_int64 (Cash c, int64 i)
 
Datum cash_in (PG_FUNCTION_ARGS)
 
Datum cash_out (PG_FUNCTION_ARGS)
 
Datum cash_recv (PG_FUNCTION_ARGS)
 
Datum cash_send (PG_FUNCTION_ARGS)
 
Datum cash_eq (PG_FUNCTION_ARGS)
 
Datum cash_ne (PG_FUNCTION_ARGS)
 
Datum cash_lt (PG_FUNCTION_ARGS)
 
Datum cash_le (PG_FUNCTION_ARGS)
 
Datum cash_gt (PG_FUNCTION_ARGS)
 
Datum cash_ge (PG_FUNCTION_ARGS)
 
Datum cash_cmp (PG_FUNCTION_ARGS)
 
Datum cash_pl (PG_FUNCTION_ARGS)
 
Datum cash_mi (PG_FUNCTION_ARGS)
 
Datum cash_div_cash (PG_FUNCTION_ARGS)
 
Datum cash_mul_flt8 (PG_FUNCTION_ARGS)
 
Datum flt8_mul_cash (PG_FUNCTION_ARGS)
 
Datum cash_div_flt8 (PG_FUNCTION_ARGS)
 
Datum cash_mul_flt4 (PG_FUNCTION_ARGS)
 
Datum flt4_mul_cash (PG_FUNCTION_ARGS)
 
Datum cash_div_flt4 (PG_FUNCTION_ARGS)
 
Datum cash_mul_int8 (PG_FUNCTION_ARGS)
 
Datum int8_mul_cash (PG_FUNCTION_ARGS)
 
Datum cash_div_int8 (PG_FUNCTION_ARGS)
 
Datum cash_mul_int4 (PG_FUNCTION_ARGS)
 
Datum int4_mul_cash (PG_FUNCTION_ARGS)
 
Datum cash_div_int4 (PG_FUNCTION_ARGS)
 
Datum cash_mul_int2 (PG_FUNCTION_ARGS)
 
Datum int2_mul_cash (PG_FUNCTION_ARGS)
 
Datum cash_div_int2 (PG_FUNCTION_ARGS)
 
Datum cashlarger (PG_FUNCTION_ARGS)
 
Datum cashsmaller (PG_FUNCTION_ARGS)
 
Datum cash_words (PG_FUNCTION_ARGS)
 
Datum cash_numeric (PG_FUNCTION_ARGS)
 
Datum numeric_cash (PG_FUNCTION_ARGS)
 
Datum int4_cash (PG_FUNCTION_ARGS)
 
Datum int8_cash (PG_FUNCTION_ARGS)
 

Function Documentation

◆ append_num_word()

static void append_num_word ( StringInfo  buf,
Cash  value 
)
static

Definition at line 39 of file cash.c.

40 {
41  static const char *const small[] = {
42  "zero", "one", "two", "three", "four", "five", "six", "seven",
43  "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
44  "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty",
45  "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"
46  };
47  const char *const *big = small + 18;
48  int tu = value % 100;
49 
50  /* deal with the simple cases first */
51  if (value <= 20)
52  {
54  return;
55  }
56 
57  /* is it an even multiple of 100? */
58  if (!tu)
59  {
60  appendStringInfo(buf, "%s hundred", small[value / 100]);
61  return;
62  }
63 
64  /* more than 99? */
65  if (value > 99)
66  {
67  /* is it an even multiple of 10 other than 10? */
68  if (value % 10 == 0 && tu > 10)
69  appendStringInfo(buf, "%s hundred %s",
70  small[value / 100], big[tu / 10]);
71  else if (tu < 20)
72  appendStringInfo(buf, "%s hundred and %s",
73  small[value / 100], small[tu]);
74  else
75  appendStringInfo(buf, "%s hundred %s %s",
76  small[value / 100], big[tu / 10], small[tu % 10]);
77  }
78  else
79  {
80  /* is it an even multiple of 10 other than 10? */
81  if (value % 10 == 0 && tu > 10)
82  appendStringInfoString(buf, big[tu / 10]);
83  else if (tu < 20)
84  appendStringInfoString(buf, small[tu]);
85  else
86  appendStringInfo(buf, "%s %s", big[tu / 10], small[tu % 10]);
87  }
88 } /* num_word() */
static struct @157 value
static char * buf
Definition: pg_test_fsync.c:73
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182

References appendStringInfo(), appendStringInfoString(), buf, and value.

Referenced by cash_words().

◆ cash_cmp()

Datum cash_cmp ( PG_FUNCTION_ARGS  )

Definition at line 672 of file cash.c.

673 {
674  Cash c1 = PG_GETARG_CASH(0);
675  Cash c2 = PG_GETARG_CASH(1);
676 
677  if (c1 > c2)
678  PG_RETURN_INT32(1);
679  else if (c1 == c2)
680  PG_RETURN_INT32(0);
681  else
682  PG_RETURN_INT32(-1);
683 }
int64 Cash
Definition: cash.h:17
#define PG_GETARG_CASH(n)
Definition: cash.h:32
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354

References PG_GETARG_CASH, and PG_RETURN_INT32.

◆ cash_div_cash()

Datum cash_div_cash ( PG_FUNCTION_ARGS  )

Definition at line 716 of file cash.c.

717 {
718  Cash dividend = PG_GETARG_CASH(0);
719  Cash divisor = PG_GETARG_CASH(1);
720  float8 quotient;
721 
722  if (divisor == 0)
723  ereport(ERROR,
724  (errcode(ERRCODE_DIVISION_BY_ZERO),
725  errmsg("division by zero")));
726 
727  quotient = (float8) dividend / (float8) divisor;
728  PG_RETURN_FLOAT8(quotient);
729 }
double float8
Definition: c.h:633
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367

References ereport, errcode(), errmsg(), ERROR, PG_GETARG_CASH, and PG_RETURN_FLOAT8.

◆ cash_div_float8()

static Cash cash_div_float8 ( Cash  c,
float8  f 
)
inlinestatic

Definition at line 130 of file cash.c.

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 }
#define FLOAT8_FITS_IN_INT64(num)
Definition: c.h:1095
#define unlikely(x)
Definition: c.h:314
static float8 float8_div(const float8 val1, const float8 val2)
Definition: float.h:238
char * c

References ereport, errcode(), errmsg(), ERROR, float8_div(), FLOAT8_FITS_IN_INT64, res, and unlikely.

Referenced by cash_div_flt4(), and cash_div_flt8().

◆ cash_div_flt4()

Datum cash_div_flt4 ( PG_FUNCTION_ARGS  )

Definition at line 802 of file cash.c.

803 {
804  Cash c = PG_GETARG_CASH(0);
805  float4 f = PG_GETARG_FLOAT4(1);
806 
808 }
float float4
Definition: c.h:632
static Cash cash_div_float8(Cash c, float8 f)
Definition: cash.c:130
#define PG_RETURN_CASH(x)
Definition: cash.h:33
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:281

References cash_div_float8(), PG_GETARG_CASH, PG_GETARG_FLOAT4, and PG_RETURN_CASH.

◆ cash_div_flt8()

Datum cash_div_flt8 ( PG_FUNCTION_ARGS  )

Definition at line 762 of file cash.c.

763 {
764  Cash c = PG_GETARG_CASH(0);
765  float8 f = PG_GETARG_FLOAT8(1);
766 
768 }
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:282

References cash_div_float8(), PG_GETARG_CASH, PG_GETARG_FLOAT8, and PG_RETURN_CASH.

◆ cash_div_int2()

Datum cash_div_int2 ( PG_FUNCTION_ARGS  )

Definition at line 918 of file cash.c.

919 {
920  Cash c = PG_GETARG_CASH(0);
921  int16 s = PG_GETARG_INT16(1);
922 
923  PG_RETURN_CASH(cash_div_int64(c, (int64) s));
924 }
signed short int16
Definition: c.h:496
static Cash cash_div_int64(Cash c, int64 i)
Definition: cash.c:156
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271

References cash_div_int64(), PG_GETARG_CASH, PG_GETARG_INT16, and PG_RETURN_CASH.

◆ cash_div_int4()

Datum cash_div_int4 ( PG_FUNCTION_ARGS  )

Definition at line 880 of file cash.c.

881 {
882  Cash c = PG_GETARG_CASH(0);
883  int32 i = PG_GETARG_INT32(1);
884 
885  PG_RETURN_CASH(cash_div_int64(c, (int64) i));
886 }
signed int int32
Definition: c.h:497
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
int i
Definition: isn.c:73

References cash_div_int64(), i, PG_GETARG_CASH, PG_GETARG_INT32, and PG_RETURN_CASH.

◆ cash_div_int64()

static Cash cash_div_int64 ( Cash  c,
int64  i 
)
inlinestatic

Definition at line 156 of file cash.c.

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 }

References ereport, errcode(), errmsg(), ERROR, i, and unlikely.

Referenced by cash_div_int2(), cash_div_int4(), and cash_div_int8().

◆ cash_div_int8()

Datum cash_div_int8 ( PG_FUNCTION_ARGS  )

Definition at line 840 of file cash.c.

841 {
842  Cash c = PG_GETARG_CASH(0);
843  int64 i = PG_GETARG_INT64(1);
844 
846 }
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283

References cash_div_int64(), i, PG_GETARG_CASH, PG_GETARG_INT64, and PG_RETURN_CASH.

◆ cash_eq()

Datum cash_eq ( PG_FUNCTION_ARGS  )

Definition at line 618 of file cash.c.

619 {
620  Cash c1 = PG_GETARG_CASH(0);
621  Cash c2 = PG_GETARG_CASH(1);
622 
623  PG_RETURN_BOOL(c1 == c2);
624 }
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359

References PG_GETARG_CASH, and PG_RETURN_BOOL.

◆ cash_ge()

Datum cash_ge ( PG_FUNCTION_ARGS  )

Definition at line 663 of file cash.c.

664 {
665  Cash c1 = PG_GETARG_CASH(0);
666  Cash c2 = PG_GETARG_CASH(1);
667 
668  PG_RETURN_BOOL(c1 >= c2);
669 }

References PG_GETARG_CASH, and PG_RETURN_BOOL.

◆ cash_gt()

Datum cash_gt ( PG_FUNCTION_ARGS  )

Definition at line 654 of file cash.c.

655 {
656  Cash c1 = PG_GETARG_CASH(0);
657  Cash c2 = PG_GETARG_CASH(1);
658 
659  PG_RETURN_BOOL(c1 > c2);
660 }

References PG_GETARG_CASH, and PG_RETURN_BOOL.

◆ cash_in()

Datum cash_in ( PG_FUNCTION_ARGS  )

Definition at line 173 of file cash.c.

174 {
175  char *str = PG_GETARG_CSTRING(0);
176  Node *escontext = fcinfo->context;
177  Cash result;
178  Cash value = 0;
179  Cash dec = 0;
180  Cash sgn = 1;
181  bool seen_dot = false;
182  const char *s = str;
183  int fpoint;
184  char dsymbol;
185  const char *ssymbol,
186  *psymbol,
187  *nsymbol,
188  *csymbol;
189  struct lconv *lconvert = PGLC_localeconv();
190 
191  /*
192  * frac_digits will be CHAR_MAX in some locales, notably C. However, just
193  * testing for == CHAR_MAX is risky, because of compilers like gcc that
194  * "helpfully" let you alter the platform-standard definition of whether
195  * char is signed or not. If we are so unfortunate as to get compiled
196  * with a nonstandard -fsigned-char or -funsigned-char switch, then our
197  * idea of CHAR_MAX will not agree with libc's. The safest course is not
198  * to test for CHAR_MAX at all, but to impose a range check for plausible
199  * frac_digits values.
200  */
201  fpoint = lconvert->frac_digits;
202  if (fpoint < 0 || fpoint > 10)
203  fpoint = 2; /* best guess in this case, I think */
204 
205  /* we restrict dsymbol to be a single byte, but not the other symbols */
206  if (*lconvert->mon_decimal_point != '\0' &&
207  lconvert->mon_decimal_point[1] == '\0')
208  dsymbol = *lconvert->mon_decimal_point;
209  else
210  dsymbol = '.';
211  if (*lconvert->mon_thousands_sep != '\0')
212  ssymbol = lconvert->mon_thousands_sep;
213  else /* ssymbol should not equal dsymbol */
214  ssymbol = (dsymbol != ',') ? "," : ".";
215  csymbol = (*lconvert->currency_symbol != '\0') ? lconvert->currency_symbol : "$";
216  psymbol = (*lconvert->positive_sign != '\0') ? lconvert->positive_sign : "+";
217  nsymbol = (*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-";
218 
219 #ifdef CASHDEBUG
220  printf("cashin- precision '%d'; decimal '%c'; thousands '%s'; currency '%s'; positive '%s'; negative '%s'\n",
221  fpoint, dsymbol, ssymbol, csymbol, psymbol, nsymbol);
222 #endif
223 
224  /* we need to add all sorts of checking here. For now just */
225  /* strip all leading whitespace and any leading currency symbol */
226  while (isspace((unsigned char) *s))
227  s++;
228  if (strncmp(s, csymbol, strlen(csymbol)) == 0)
229  s += strlen(csymbol);
230  while (isspace((unsigned char) *s))
231  s++;
232 
233 #ifdef CASHDEBUG
234  printf("cashin- string is '%s'\n", s);
235 #endif
236 
237  /* a leading minus or paren signifies a negative number */
238  /* again, better heuristics needed */
239  /* XXX - doesn't properly check for balanced parens - djmc */
240  if (strncmp(s, nsymbol, strlen(nsymbol)) == 0)
241  {
242  sgn = -1;
243  s += strlen(nsymbol);
244  }
245  else if (*s == '(')
246  {
247  sgn = -1;
248  s++;
249  }
250  else if (strncmp(s, psymbol, strlen(psymbol)) == 0)
251  s += strlen(psymbol);
252 
253 #ifdef CASHDEBUG
254  printf("cashin- string is '%s'\n", s);
255 #endif
256 
257  /* allow whitespace and currency symbol after the sign, too */
258  while (isspace((unsigned char) *s))
259  s++;
260  if (strncmp(s, csymbol, strlen(csymbol)) == 0)
261  s += strlen(csymbol);
262  while (isspace((unsigned char) *s))
263  s++;
264 
265 #ifdef CASHDEBUG
266  printf("cashin- string is '%s'\n", s);
267 #endif
268 
269  /*
270  * We accumulate the absolute amount in "value" and then apply the sign at
271  * the end. (The sign can appear before or after the digits, so it would
272  * be more complicated to do otherwise.) Because of the larger range of
273  * negative signed integers, we build "value" in the negative and then
274  * flip the sign at the end, catching most-negative-number overflow if
275  * necessary.
276  */
277 
278  for (; *s; s++)
279  {
280  /*
281  * We look for digits as long as we have found less than the required
282  * number of decimal places.
283  */
284  if (isdigit((unsigned char) *s) && (!seen_dot || dec < fpoint))
285  {
286  int8 digit = *s - '0';
287 
288  if (pg_mul_s64_overflow(value, 10, &value) ||
289  pg_sub_s64_overflow(value, digit, &value))
290  ereturn(escontext, (Datum) 0,
291  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
292  errmsg("value \"%s\" is out of range for type %s",
293  str, "money")));
294 
295  if (seen_dot)
296  dec++;
297  }
298  /* decimal point? then start counting fractions... */
299  else if (*s == dsymbol && !seen_dot)
300  {
301  seen_dot = true;
302  }
303  /* ignore if "thousands" separator, else we're done */
304  else if (strncmp(s, ssymbol, strlen(ssymbol)) == 0)
305  s += strlen(ssymbol) - 1;
306  else
307  break;
308  }
309 
310  /* round off if there's another digit */
311  if (isdigit((unsigned char) *s) && *s >= '5')
312  {
313  /* remember we build the value in the negative */
314  if (pg_sub_s64_overflow(value, 1, &value))
315  ereturn(escontext, (Datum) 0,
316  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
317  errmsg("value \"%s\" is out of range for type %s",
318  str, "money")));
319  }
320 
321  /* adjust for less than required decimal places */
322  for (; dec < fpoint; dec++)
323  {
324  if (pg_mul_s64_overflow(value, 10, &value))
325  ereturn(escontext, (Datum) 0,
326  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
327  errmsg("value \"%s\" is out of range for type %s",
328  str, "money")));
329  }
330 
331  /*
332  * should only be trailing digits followed by whitespace, right paren,
333  * trailing sign, and/or trailing currency symbol
334  */
335  while (isdigit((unsigned char) *s))
336  s++;
337 
338  while (*s)
339  {
340  if (isspace((unsigned char) *s) || *s == ')')
341  s++;
342  else if (strncmp(s, nsymbol, strlen(nsymbol)) == 0)
343  {
344  sgn = -1;
345  s += strlen(nsymbol);
346  }
347  else if (strncmp(s, psymbol, strlen(psymbol)) == 0)
348  s += strlen(psymbol);
349  else if (strncmp(s, csymbol, strlen(csymbol)) == 0)
350  s += strlen(csymbol);
351  else
352  ereturn(escontext, (Datum) 0,
353  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
354  errmsg("invalid input syntax for type %s: \"%s\"",
355  "money", str)));
356  }
357 
358  /*
359  * If the value is supposed to be positive, flip the sign, but check for
360  * the most negative number.
361  */
362  if (sgn > 0)
363  {
364  if (value == PG_INT64_MIN)
365  ereturn(escontext, (Datum) 0,
366  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
367  errmsg("value \"%s\" is out of range for type %s",
368  str, "money")));
369  result = -value;
370  }
371  else
372  result = value;
373 
374 #ifdef CASHDEBUG
375  printf("cashin- result is " INT64_FORMAT "\n", result);
376 #endif
377 
378  PG_RETURN_CASH(result);
379 }
signed char int8
Definition: c.h:495
#define INT64_FORMAT
Definition: c.h:551
#define PG_INT64_MIN
Definition: c.h:594
#define ereturn(context, dummy_value,...)
Definition: elog.h:277
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
const char * str
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:261
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:230
struct lconv * PGLC_localeconv(void)
Definition: pg_locale.c:571
#define printf(...)
Definition: port.h:244
uintptr_t Datum
Definition: postgres.h:64
Definition: nodes.h:129

References ereturn, errcode(), errmsg(), INT64_FORMAT, PG_GETARG_CSTRING, PG_INT64_MIN, pg_mul_s64_overflow(), PG_RETURN_CASH, pg_sub_s64_overflow(), PGLC_localeconv(), printf, str, and value.

◆ cash_le()

Datum cash_le ( PG_FUNCTION_ARGS  )

Definition at line 645 of file cash.c.

646 {
647  Cash c1 = PG_GETARG_CASH(0);
648  Cash c2 = PG_GETARG_CASH(1);
649 
650  PG_RETURN_BOOL(c1 <= c2);
651 }

References PG_GETARG_CASH, and PG_RETURN_BOOL.

◆ cash_lt()

Datum cash_lt ( PG_FUNCTION_ARGS  )

Definition at line 636 of file cash.c.

637 {
638  Cash c1 = PG_GETARG_CASH(0);
639  Cash c2 = PG_GETARG_CASH(1);
640 
641  PG_RETURN_BOOL(c1 < c2);
642 }

References PG_GETARG_CASH, and PG_RETURN_BOOL.

◆ cash_mi()

Datum cash_mi ( PG_FUNCTION_ARGS  )

Definition at line 703 of file cash.c.

704 {
705  Cash c1 = PG_GETARG_CASH(0);
706  Cash c2 = PG_GETARG_CASH(1);
707 
708  PG_RETURN_CASH(cash_mi_cash(c1, c2));
709 }
static Cash cash_mi_cash(Cash c1, Cash c2)
Definition: cash.c:104

References cash_mi_cash(), PG_GETARG_CASH, and PG_RETURN_CASH.

◆ cash_mi_cash()

static Cash cash_mi_cash ( Cash  c1,
Cash  c2 
)
inlinestatic

Definition at line 104 of file cash.c.

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 }

References ereport, errcode(), errmsg(), ERROR, pg_sub_s64_overflow(), res, and unlikely.

Referenced by cash_mi().

◆ cash_mul_float8()

static Cash cash_mul_float8 ( Cash  c,
float8  f 
)
inlinestatic

Definition at line 117 of file cash.c.

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 }
static float8 float8_mul(const float8 val1, const float8 val2)
Definition: float.h:208

References ereport, errcode(), errmsg(), ERROR, FLOAT8_FITS_IN_INT64, float8_mul(), res, and unlikely.

Referenced by cash_mul_flt4(), cash_mul_flt8(), flt4_mul_cash(), and flt8_mul_cash().

◆ cash_mul_flt4()

Datum cash_mul_flt4 ( PG_FUNCTION_ARGS  )

Definition at line 775 of file cash.c.

776 {
777  Cash c = PG_GETARG_CASH(0);
778  float4 f = PG_GETARG_FLOAT4(1);
779 
781 }
static Cash cash_mul_float8(Cash c, float8 f)
Definition: cash.c:117

References cash_mul_float8(), PG_GETARG_CASH, PG_GETARG_FLOAT4, and PG_RETURN_CASH.

◆ cash_mul_flt8()

Datum cash_mul_flt8 ( PG_FUNCTION_ARGS  )

Definition at line 736 of file cash.c.

737 {
738  Cash c = PG_GETARG_CASH(0);
739  float8 f = PG_GETARG_FLOAT8(1);
740 
742 }

References cash_mul_float8(), PG_GETARG_CASH, PG_GETARG_FLOAT8, and PG_RETURN_CASH.

◆ cash_mul_int2()

Datum cash_mul_int2 ( PG_FUNCTION_ARGS  )

Definition at line 893 of file cash.c.

894 {
895  Cash c = PG_GETARG_CASH(0);
896  int16 s = PG_GETARG_INT16(1);
897 
898  PG_RETURN_CASH(cash_mul_int64(c, (int64) s));
899 }
static Cash cash_mul_int64(Cash c, int64 i)
Definition: cash.c:143

References cash_mul_int64(), PG_GETARG_CASH, PG_GETARG_INT16, and PG_RETURN_CASH.

◆ cash_mul_int4()

Datum cash_mul_int4 ( PG_FUNCTION_ARGS  )

Definition at line 853 of file cash.c.

854 {
855  Cash c = PG_GETARG_CASH(0);
856  int32 i = PG_GETARG_INT32(1);
857 
858  PG_RETURN_CASH(cash_mul_int64(c, (int64) i));
859 }

References cash_mul_int64(), i, PG_GETARG_CASH, PG_GETARG_INT32, and PG_RETURN_CASH.

◆ cash_mul_int64()

static Cash cash_mul_int64 ( Cash  c,
int64  i 
)
inlinestatic

Definition at line 143 of file cash.c.

144 {
145  Cash res;
146 
148  ereport(ERROR,
149  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
150  errmsg("money out of range")));
151 
152  return res;
153 }

References ereport, errcode(), errmsg(), ERROR, i, pg_mul_s64_overflow(), res, and unlikely.

Referenced by cash_mul_int2(), cash_mul_int4(), cash_mul_int8(), int2_mul_cash(), int4_mul_cash(), and int8_mul_cash().

◆ cash_mul_int8()

Datum cash_mul_int8 ( PG_FUNCTION_ARGS  )

Definition at line 815 of file cash.c.

816 {
817  Cash c = PG_GETARG_CASH(0);
818  int64 i = PG_GETARG_INT64(1);
819 
821 }

References cash_mul_int64(), i, PG_GETARG_CASH, PG_GETARG_INT64, and PG_RETURN_CASH.

◆ cash_ne()

Datum cash_ne ( PG_FUNCTION_ARGS  )

Definition at line 627 of file cash.c.

628 {
629  Cash c1 = PG_GETARG_CASH(0);
630  Cash c2 = PG_GETARG_CASH(1);
631 
632  PG_RETURN_BOOL(c1 != c2);
633 }

References PG_GETARG_CASH, and PG_RETURN_BOOL.

◆ cash_numeric()

Datum cash_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1051 of file cash.c.

1052 {
1053  Cash money = PG_GETARG_CASH(0);
1054  Datum result;
1055  int fpoint;
1056  struct lconv *lconvert = PGLC_localeconv();
1057 
1058  /* see comments about frac_digits in cash_in() */
1059  fpoint = lconvert->frac_digits;
1060  if (fpoint < 0 || fpoint > 10)
1061  fpoint = 2;
1062 
1063  /* convert the integral money value to numeric */
1064  result = NumericGetDatum(int64_to_numeric(money));
1065 
1066  /* scale appropriately, if needed */
1067  if (fpoint > 0)
1068  {
1069  int64 scale;
1070  int i;
1072  Datum quotient;
1073 
1074  /* compute required scale factor */
1075  scale = 1;
1076  for (i = 0; i < fpoint; i++)
1077  scale *= 10;
1079 
1080  /*
1081  * Given integral inputs approaching INT64_MAX, select_div_scale()
1082  * might choose a result scale of zero, causing loss of fractional
1083  * digits in the quotient. We can ensure an exact result by setting
1084  * the dscale of either input to be at least as large as the desired
1085  * result scale. numeric_round() will do that for us.
1086  */
1088  numeric_scale,
1089  Int32GetDatum(fpoint));
1090 
1091  /* Now we can safely divide ... */
1092  quotient = DirectFunctionCall2(numeric_div, result, numeric_scale);
1093 
1094  /* ... and forcibly round to exactly the intended number of digits */
1096  quotient,
1097  Int32GetDatum(fpoint));
1098  }
1099 
1100  PG_RETURN_DATUM(result);
1101 }
Datum numeric_div(PG_FUNCTION_ARGS)
Definition: numeric.c:3121
Datum numeric_round(PG_FUNCTION_ARGS)
Definition: numeric.c:1542
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4280
Datum numeric_scale(PG_FUNCTION_ARGS)
Definition: numeric.c:4119
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:643
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73
static int scale
Definition: pgbench.c:181
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212

References DirectFunctionCall2, i, Int32GetDatum(), int64_to_numeric(), numeric_div(), numeric_round(), numeric_scale(), NumericGetDatum(), PG_GETARG_CASH, PG_RETURN_DATUM, PGLC_localeconv(), and scale.

◆ cash_out()

Datum cash_out ( PG_FUNCTION_ARGS  )

Definition at line 387 of file cash.c.

388 {
390  uint64 uvalue;
391  char *result;
392  char buf[128];
393  char *bufptr;
394  int digit_pos;
395  int points,
396  mon_group;
397  char dsymbol;
398  const char *ssymbol,
399  *csymbol,
400  *signsymbol;
401  char sign_posn,
402  cs_precedes,
403  sep_by_space;
404  struct lconv *lconvert = PGLC_localeconv();
405 
406  /* see comments about frac_digits in cash_in() */
407  points = lconvert->frac_digits;
408  if (points < 0 || points > 10)
409  points = 2; /* best guess in this case, I think */
410 
411  /*
412  * As with frac_digits, must apply a range check to mon_grouping to avoid
413  * being fooled by variant CHAR_MAX values.
414  */
415  mon_group = *lconvert->mon_grouping;
416  if (mon_group <= 0 || mon_group > 6)
417  mon_group = 3;
418 
419  /* we restrict dsymbol to be a single byte, but not the other symbols */
420  if (*lconvert->mon_decimal_point != '\0' &&
421  lconvert->mon_decimal_point[1] == '\0')
422  dsymbol = *lconvert->mon_decimal_point;
423  else
424  dsymbol = '.';
425  if (*lconvert->mon_thousands_sep != '\0')
426  ssymbol = lconvert->mon_thousands_sep;
427  else /* ssymbol should not equal dsymbol */
428  ssymbol = (dsymbol != ',') ? "," : ".";
429  csymbol = (*lconvert->currency_symbol != '\0') ? lconvert->currency_symbol : "$";
430 
431  if (value < 0)
432  {
433  /* set up formatting data */
434  signsymbol = (*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-";
435  sign_posn = lconvert->n_sign_posn;
436  cs_precedes = lconvert->n_cs_precedes;
437  sep_by_space = lconvert->n_sep_by_space;
438  }
439  else
440  {
441  signsymbol = lconvert->positive_sign;
442  sign_posn = lconvert->p_sign_posn;
443  cs_precedes = lconvert->p_cs_precedes;
444  sep_by_space = lconvert->p_sep_by_space;
445  }
446 
447  /* make the amount positive for digit-reconstruction loop */
448  uvalue = pg_abs_s64(value);
449 
450  /* we build the digits+decimal-point+sep string right-to-left in buf[] */
451  bufptr = buf + sizeof(buf) - 1;
452  *bufptr = '\0';
453 
454  /*
455  * Generate digits till there are no non-zero digits left and we emitted
456  * at least one to the left of the decimal point. digit_pos is the
457  * current digit position, with zero as the digit just left of the decimal
458  * point, increasing to the right.
459  */
460  digit_pos = points;
461  do
462  {
463  if (points && digit_pos == 0)
464  {
465  /* insert decimal point, but not if value cannot be fractional */
466  *(--bufptr) = dsymbol;
467  }
468  else if (digit_pos < 0 && (digit_pos % mon_group) == 0)
469  {
470  /* insert thousands sep, but only to left of radix point */
471  bufptr -= strlen(ssymbol);
472  memcpy(bufptr, ssymbol, strlen(ssymbol));
473  }
474 
475  *(--bufptr) = (uvalue % 10) + '0';
476  uvalue = uvalue / 10;
477  digit_pos--;
478  } while (uvalue || digit_pos >= 0);
479 
480  /*----------
481  * Now, attach currency symbol and sign symbol in the correct order.
482  *
483  * The POSIX spec defines these values controlling this code:
484  *
485  * p/n_sign_posn:
486  * 0 Parentheses enclose the quantity and the currency_symbol.
487  * 1 The sign string precedes the quantity and the currency_symbol.
488  * 2 The sign string succeeds the quantity and the currency_symbol.
489  * 3 The sign string precedes the currency_symbol.
490  * 4 The sign string succeeds the currency_symbol.
491  *
492  * p/n_cs_precedes: 0 means currency symbol after value, else before it.
493  *
494  * p/n_sep_by_space:
495  * 0 No <space> separates the currency symbol and value.
496  * 1 If the currency symbol and sign string are adjacent, a <space>
497  * separates them from the value; otherwise, a <space> separates
498  * the currency symbol from the value.
499  * 2 If the currency symbol and sign string are adjacent, a <space>
500  * separates them; otherwise, a <space> separates the sign string
501  * from the value.
502  *----------
503  */
504  switch (sign_posn)
505  {
506  case 0:
507  if (cs_precedes)
508  result = psprintf("(%s%s%s)",
509  csymbol,
510  (sep_by_space == 1) ? " " : "",
511  bufptr);
512  else
513  result = psprintf("(%s%s%s)",
514  bufptr,
515  (sep_by_space == 1) ? " " : "",
516  csymbol);
517  break;
518  case 1:
519  default:
520  if (cs_precedes)
521  result = psprintf("%s%s%s%s%s",
522  signsymbol,
523  (sep_by_space == 2) ? " " : "",
524  csymbol,
525  (sep_by_space == 1) ? " " : "",
526  bufptr);
527  else
528  result = psprintf("%s%s%s%s%s",
529  signsymbol,
530  (sep_by_space == 2) ? " " : "",
531  bufptr,
532  (sep_by_space == 1) ? " " : "",
533  csymbol);
534  break;
535  case 2:
536  if (cs_precedes)
537  result = psprintf("%s%s%s%s%s",
538  csymbol,
539  (sep_by_space == 1) ? " " : "",
540  bufptr,
541  (sep_by_space == 2) ? " " : "",
542  signsymbol);
543  else
544  result = psprintf("%s%s%s%s%s",
545  bufptr,
546  (sep_by_space == 1) ? " " : "",
547  csymbol,
548  (sep_by_space == 2) ? " " : "",
549  signsymbol);
550  break;
551  case 3:
552  if (cs_precedes)
553  result = psprintf("%s%s%s%s%s",
554  signsymbol,
555  (sep_by_space == 2) ? " " : "",
556  csymbol,
557  (sep_by_space == 1) ? " " : "",
558  bufptr);
559  else
560  result = psprintf("%s%s%s%s%s",
561  bufptr,
562  (sep_by_space == 1) ? " " : "",
563  signsymbol,
564  (sep_by_space == 2) ? " " : "",
565  csymbol);
566  break;
567  case 4:
568  if (cs_precedes)
569  result = psprintf("%s%s%s%s%s",
570  csymbol,
571  (sep_by_space == 2) ? " " : "",
572  signsymbol,
573  (sep_by_space == 1) ? " " : "",
574  bufptr);
575  else
576  result = psprintf("%s%s%s%s%s",
577  bufptr,
578  (sep_by_space == 1) ? " " : "",
579  csymbol,
580  (sep_by_space == 2) ? " " : "",
581  signsymbol);
582  break;
583  }
584 
585  PG_RETURN_CSTRING(result);
586 }
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
static uint64 pg_abs_s64(int64 a)
Definition: int.h:304
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46

References buf, if(), pg_abs_s64(), PG_GETARG_CASH, PG_RETURN_CSTRING, PGLC_localeconv(), psprintf(), and value.

◆ cash_pl()

Datum cash_pl ( PG_FUNCTION_ARGS  )

Definition at line 690 of file cash.c.

691 {
692  Cash c1 = PG_GETARG_CASH(0);
693  Cash c2 = PG_GETARG_CASH(1);
694 
695  PG_RETURN_CASH(cash_pl_cash(c1, c2));
696 }
static Cash cash_pl_cash(Cash c1, Cash c2)
Definition: cash.c:91

References cash_pl_cash(), PG_GETARG_CASH, and PG_RETURN_CASH.

◆ cash_pl_cash()

static Cash cash_pl_cash ( Cash  c1,
Cash  c2 
)
inlinestatic

Definition at line 91 of file cash.c.

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 }
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:203

References ereport, errcode(), errmsg(), ERROR, pg_add_s64_overflow(), res, and unlikely.

Referenced by cash_pl().

◆ cash_recv()

Datum cash_recv ( PG_FUNCTION_ARGS  )

Definition at line 592 of file cash.c.

593 {
595 
597 }
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:453
StringInfoData * StringInfo
Definition: stringinfo.h:54

References buf, PG_GETARG_POINTER, PG_RETURN_CASH, and pq_getmsgint64().

◆ cash_send()

Datum cash_send ( PG_FUNCTION_ARGS  )

Definition at line 603 of file cash.c.

604 {
605  Cash arg1 = PG_GETARG_CASH(0);
607 
609  pq_sendint64(&buf, arg1);
611 }
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:152

References buf, PG_GETARG_CASH, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), and pq_sendint64().

◆ cash_words()

Datum cash_words ( PG_FUNCTION_ARGS  )

Definition at line 961 of file cash.c.

962 {
964  uint64 val;
966  text *res;
967  Cash dollars;
968  Cash m0;
969  Cash m1;
970  Cash m2;
971  Cash m3;
972  Cash m4;
973  Cash m5;
974  Cash m6;
975 
977 
978  /* work with positive numbers */
979  if (value < 0)
980  {
981  value = -value;
982  appendStringInfoString(&buf, "minus ");
983  }
984 
985  /* Now treat as unsigned, to avoid trouble at INT_MIN */
986  val = (uint64) value;
987 
988  dollars = val / INT64CONST(100);
989  m0 = val % INT64CONST(100); /* cents */
990  m1 = (val / INT64CONST(100)) % 1000; /* hundreds */
991  m2 = (val / INT64CONST(100000)) % 1000; /* thousands */
992  m3 = (val / INT64CONST(100000000)) % 1000; /* millions */
993  m4 = (val / INT64CONST(100000000000)) % 1000; /* billions */
994  m5 = (val / INT64CONST(100000000000000)) % 1000; /* trillions */
995  m6 = (val / INT64CONST(100000000000000000)) % 1000; /* quadrillions */
996 
997  if (m6)
998  {
999  append_num_word(&buf, m6);
1000  appendStringInfoString(&buf, " quadrillion ");
1001  }
1002 
1003  if (m5)
1004  {
1005  append_num_word(&buf, m5);
1006  appendStringInfoString(&buf, " trillion ");
1007  }
1008 
1009  if (m4)
1010  {
1011  append_num_word(&buf, m4);
1012  appendStringInfoString(&buf, " billion ");
1013  }
1014 
1015  if (m3)
1016  {
1017  append_num_word(&buf, m3);
1018  appendStringInfoString(&buf, " million ");
1019  }
1020 
1021  if (m2)
1022  {
1023  append_num_word(&buf, m2);
1024  appendStringInfoString(&buf, " thousand ");
1025  }
1026 
1027  if (m1)
1028  append_num_word(&buf, m1);
1029 
1030  if (dollars == 0)
1031  appendStringInfoString(&buf, "zero");
1032 
1033  appendStringInfoString(&buf, dollars == 1 ? " dollar and " : " dollars and ");
1034  append_num_word(&buf, m0);
1035  appendStringInfoString(&buf, m0 == 1 ? " cent" : " cents");
1036 
1037  /* capitalize output */
1038  buf.data[0] = pg_toupper((unsigned char) buf.data[0]);
1039 
1040  /* return as text datum */
1041  res = cstring_to_text_with_len(buf.data, buf.len);
1042  pfree(buf.data);
1044 }
static void append_num_word(StringInfo buf, Cash value)
Definition: cash.c:39
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
long val
Definition: informix.c:689
void pfree(void *pointer)
Definition: mcxt.c:1521
unsigned char pg_toupper(unsigned char ch)
Definition: pgstrcasecmp.c:105
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
Definition: c.h:690
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196

References append_num_word(), appendStringInfoString(), buf, cstring_to_text_with_len(), initStringInfo(), pfree(), PG_GETARG_CASH, PG_RETURN_TEXT_P, pg_toupper(), res, val, and value.

◆ cashlarger()

Datum cashlarger ( PG_FUNCTION_ARGS  )

Definition at line 930 of file cash.c.

931 {
932  Cash c1 = PG_GETARG_CASH(0);
933  Cash c2 = PG_GETARG_CASH(1);
934  Cash result;
935 
936  result = (c1 > c2) ? c1 : c2;
937 
938  PG_RETURN_CASH(result);
939 }

References PG_GETARG_CASH, and PG_RETURN_CASH.

◆ cashsmaller()

Datum cashsmaller ( PG_FUNCTION_ARGS  )

Definition at line 945 of file cash.c.

946 {
947  Cash c1 = PG_GETARG_CASH(0);
948  Cash c2 = PG_GETARG_CASH(1);
949  Cash result;
950 
951  result = (c1 < c2) ? c1 : c2;
952 
953  PG_RETURN_CASH(result);
954 }

References PG_GETARG_CASH, and PG_RETURN_CASH.

◆ flt4_mul_cash()

Datum flt4_mul_cash ( PG_FUNCTION_ARGS  )

Definition at line 788 of file cash.c.

789 {
790  float4 f = PG_GETARG_FLOAT4(0);
791  Cash c = PG_GETARG_CASH(1);
792 
794 }

References cash_mul_float8(), PG_GETARG_CASH, PG_GETARG_FLOAT4, and PG_RETURN_CASH.

◆ flt8_mul_cash()

Datum flt8_mul_cash ( PG_FUNCTION_ARGS  )

Definition at line 749 of file cash.c.

750 {
751  float8 f = PG_GETARG_FLOAT8(0);
752  Cash c = PG_GETARG_CASH(1);
753 
755 }

References cash_mul_float8(), PG_GETARG_CASH, PG_GETARG_FLOAT8, and PG_RETURN_CASH.

◆ int2_mul_cash()

Datum int2_mul_cash ( PG_FUNCTION_ARGS  )

Definition at line 905 of file cash.c.

906 {
907  int16 s = PG_GETARG_INT16(0);
908  Cash c = PG_GETARG_CASH(1);
909 
910  PG_RETURN_CASH(cash_mul_int64(c, (int64) s));
911 }

References cash_mul_int64(), PG_GETARG_CASH, PG_GETARG_INT16, and PG_RETURN_CASH.

◆ int4_cash()

Datum int4_cash ( PG_FUNCTION_ARGS  )

Definition at line 1141 of file cash.c.

1142 {
1143  int32 amount = PG_GETARG_INT32(0);
1144  Cash result;
1145  int fpoint;
1146  int64 scale;
1147  int i;
1148  struct lconv *lconvert = PGLC_localeconv();
1149 
1150  /* see comments about frac_digits in cash_in() */
1151  fpoint = lconvert->frac_digits;
1152  if (fpoint < 0 || fpoint > 10)
1153  fpoint = 2;
1154 
1155  /* compute required scale factor */
1156  scale = 1;
1157  for (i = 0; i < fpoint; i++)
1158  scale *= 10;
1159 
1160  /* compute amount * scale, checking for overflow */
1162  Int64GetDatum(scale)));
1163 
1164  PG_RETURN_CASH(result);
1165 }
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1807
Datum int8mul(PG_FUNCTION_ARGS)
Definition: int8.c:490
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:385

References DatumGetInt64(), DirectFunctionCall2, i, Int64GetDatum(), int8mul(), PG_GETARG_INT32, PG_RETURN_CASH, PGLC_localeconv(), and scale.

◆ int4_mul_cash()

Datum int4_mul_cash ( PG_FUNCTION_ARGS  )

Definition at line 866 of file cash.c.

867 {
868  int32 i = PG_GETARG_INT32(0);
869  Cash c = PG_GETARG_CASH(1);
870 
871  PG_RETURN_CASH(cash_mul_int64(c, (int64) i));
872 }

References cash_mul_int64(), i, PG_GETARG_CASH, PG_GETARG_INT32, and PG_RETURN_CASH.

◆ int8_cash()

Datum int8_cash ( PG_FUNCTION_ARGS  )

Definition at line 1171 of file cash.c.

1172 {
1173  int64 amount = PG_GETARG_INT64(0);
1174  Cash result;
1175  int fpoint;
1176  int64 scale;
1177  int i;
1178  struct lconv *lconvert = PGLC_localeconv();
1179 
1180  /* see comments about frac_digits in cash_in() */
1181  fpoint = lconvert->frac_digits;
1182  if (fpoint < 0 || fpoint > 10)
1183  fpoint = 2;
1184 
1185  /* compute required scale factor */
1186  scale = 1;
1187  for (i = 0; i < fpoint; i++)
1188  scale *= 10;
1189 
1190  /* compute amount * scale, checking for overflow */
1192  Int64GetDatum(scale)));
1193 
1194  PG_RETURN_CASH(result);
1195 }

References DatumGetInt64(), DirectFunctionCall2, i, Int64GetDatum(), int8mul(), PG_GETARG_INT64, PG_RETURN_CASH, PGLC_localeconv(), and scale.

◆ int8_mul_cash()

Datum int8_mul_cash ( PG_FUNCTION_ARGS  )

Definition at line 828 of file cash.c.

829 {
830  int64 i = PG_GETARG_INT64(0);
831  Cash c = PG_GETARG_CASH(1);
832 
834 }

References cash_mul_int64(), i, PG_GETARG_CASH, PG_GETARG_INT64, and PG_RETURN_CASH.

◆ numeric_cash()

Datum numeric_cash ( PG_FUNCTION_ARGS  )

Definition at line 1107 of file cash.c.

1108 {
1109  Datum amount = PG_GETARG_DATUM(0);
1110  Cash result;
1111  int fpoint;
1112  int64 scale;
1113  int i;
1115  struct lconv *lconvert = PGLC_localeconv();
1116 
1117  /* see comments about frac_digits in cash_in() */
1118  fpoint = lconvert->frac_digits;
1119  if (fpoint < 0 || fpoint > 10)
1120  fpoint = 2;
1121 
1122  /* compute required scale factor */
1123  scale = 1;
1124  for (i = 0; i < fpoint; i++)
1125  scale *= 10;
1126 
1127  /* multiply the input amount by scale factor */
1129  amount = DirectFunctionCall2(numeric_mul, amount, numeric_scale);
1130 
1131  /* note that numeric_int8 will round to nearest integer for us */
1132  result = DatumGetInt64(DirectFunctionCall1(numeric_int8, amount));
1133 
1134  PG_RETURN_CASH(result);
1135 }
Datum numeric_int8(PG_FUNCTION_ARGS)
Definition: numeric.c:4532
Datum numeric_mul(PG_FUNCTION_ARGS)
Definition: numeric.c:3000
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268

References DatumGetInt64(), DirectFunctionCall1, DirectFunctionCall2, i, int64_to_numeric(), numeric_int8(), numeric_mul(), numeric_scale(), NumericGetDatum(), PG_GETARG_DATUM, PG_RETURN_CASH, PGLC_localeconv(), and scale.