From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>

Subject: [HACKERS] Money integration patches

Here are patches to integrate the money data type. I have included
some math and aggregate functions and have made the locale support optional
by #ifdef USE_LOCALE bracketing of functions.

Modules affected are:
builtins.h.patch
cash.c.patch
cash.h.patch
main.c.patch
pg_aggregate.h.patch
pg_operator.h.patch
pg_proc.h.patch
pg_type.h.patch

I changed the data type to be pass-by-reference rather than by-value
to pave the way for a larger internal representation (64-bit ints?).
Also, I changed the tabbing of cash.c and cash.h to match most of
the other Postgres source code files (4 space indent, 8 spaces == 1 tab).

The locale stuff should be tested under another convention (Russian?)
but I don't know what the correct results should be so perhaps someone
else can give them a try. Will update docs and regression tests in
the next few days.
This commit is contained in:
Marc G. Fournier 1997-04-15 17:41:44 +00:00
parent d8a300d867
commit 88d740462f
9 changed files with 582 additions and 289 deletions

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/main/main.c,v 1.5 1997/04/12 09:37:31 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/main/main.c,v 1.6 1997/04/15 17:39:17 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@ -38,6 +38,7 @@ main(int argc, char *argv[])
#ifdef USE_LOCALE
setlocale(LC_CTYPE,""); /* take locale information from an environment */
setlocale(LC_COLLATE,"");
setlocale(LC_MONETARY,"");
#endif
#if defined(NOFIXADE) || defined(NOPRINTADE)
/*

View File

@ -19,10 +19,11 @@
# be converted to Method 2.
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/port/Attic/Makefile.in,v 1.3 1997/03/19 02:33:29 scrappy Exp $
# $Header: /cvsroot/pgsql/src/backend/port/Attic/Makefile.in,v 1.4 1997/04/15 17:39:23 scrappy Exp $
#
#-------------------------------------------------------------------------
SRCDIR=../..
include ../../Makefile.global
ifndef PORTNAME

View File

@ -1,274 +1,521 @@
/*
cash.c
Written by D'Arcy J.M. Cain
* cash.c
* Written by D'Arcy J.M. Cain
*
* Functions to allow input and output of money normally but store
* and handle it as longs
*
* A slightly modified version of this file and a discussion of the
* workings can be found in the book "Software Solutions in C" by
* Dale Schumacher, Academic Press, ISBN: 0-12-632360-7.
*
* $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.4 1997/04/15 17:39:44 scrappy Exp $
*/
Functions to allow input and output of money normally but store
and handle it as longs
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include <locale.h>
Set tabstops to 4 for best results
A slightly modified version of this file and a discussion of the
workings can be found in the book "Software Solutions in C" by
Dale Schumacher, Academic Press, ISBN: 0-12-632360-7.
$Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.3 1997/04/10 20:51:13 scrappy Exp $
*/
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include <locale.h>
#include <utils/cash.h>
#include "postgres.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/cash.h"
/* when we go to 64 bit values we will have to modify this */
#define CASH_BUFSZ 24
#define CASH_BUFSZ 24
#define TERMINATOR (CASH_BUFSZ - 1)
#define LAST_PAREN (TERMINATOR - 1)
#define LAST_DIGIT (LAST_PAREN - 1)
#define TERMINATOR (CASH_BUFSZ - 1)
#define LAST_PAREN (TERMINATOR - 1)
#define LAST_DIGIT (LAST_PAREN - 1)
/* function to convert a long to a dollars and cents representation */
#ifdef USE_LOCALE
static struct lconv *lconv = NULL;
#endif
/* cash_in()
* Convert a string to a cash data type.
* Format is [$]###[,]###[.##]
* Examples: 123.45 $123.45 $123,456.78
*
* This is currently implemented as a 32-bit integer.
* XXX HACK It looks as though some of the symbols for
* monetary values returned by localeconv() can be multiple
* bytes/characters. This code assumes one byte only. - tgl 97/04/14
*/
Cash *
cash_in(const char *str)
{
Cash *result;
Cash value = 0;
Cash dec = 0;
Cash sgn = 1;
int seen_dot = 0;
const char *s = str;
int fpoint;
char dsymbol, ssymbol, psymbol, nsymbol, csymbol;
#ifdef USE_LOCALE
if (lconv == NULL) *lconv = localeconv();
/* frac_digits in the C locale seems to return CHAR_MAX */
/* best guess is 2 in this case I think */
fpoint = ((lconv->frac_digits != CHAR_MAX)? lconv->frac_digits: 2); /* int_frac_digits? */
dsymbol = *lconv->mon_decimal_point;
ssymbol = *lconv->mon_thousands_sep;
csymbol = *lconv->currency_symbol;
psymbol = *lconv->positive_sign;
nsymbol = *lconv->negative_sign;
#else
fpoint = 2;
dsymbol = '.';
ssymbol = ',';
csymbol = '$';
psymbol = '+';
nsymbol = '-';
#endif
/* we need to add all sorts of checking here. For now just */
/* strip all leading whitespace and any leading dollar sign */
while (isspace(*s) || *s == csymbol) s++;
/* a leading minus or paren signifies a negative number */
/* again, better heuristics needed */
if (*s == nsymbol || *s == '(') {
sgn = -1;
s++;
} else if (*s == psymbol) {
s++;
}
while (isspace(*s) || *s == csymbol) s++;
for (; ; s++) {
/* we look for digits as long as we have less */
/* than the required number of decimal places */
if (isdigit(*s) && dec < fpoint) {
value = (value * 10) + *s - '0';
if (seen_dot)
dec++;
/* decimal point? then start counting fractions... */
} else if (*s == dsymbol && !seen_dot) {
seen_dot = 1;
/* "thousands" separator? then skip... */
} else if (*s == ssymbol) {
} else {
/* round off */
if (isdigit(*s) && *s >= '5')
value++;
/* adjust for less than required decimal places */
for (; dec < fpoint; dec++)
value *= 10;
break;
}
}
while (isspace(*s) || *s == ')') s++;
if (*s != '\0')
elog(WARN,"Bad money external representation %s",str);
if (!PointerIsValid(result = PALLOCTYPE(Cash)))
elog(WARN,"Memory allocation failed, can't input cash '%s'",str);
*result = (value * sgn);
return(result);
} /* cash_in() */
/* cash_out()
* Function to convert cash to a dollars and cents representation.
* XXX HACK This code appears to assume US conventions for
* positive-valued amounts. - tgl 97/04/14
*/
const char *
cash_out(long value)
cash_out(Cash *value)
{
char *retbuf, buf[CASH_BUFSZ];
struct lconv *lc = localeconv();
int mod_group = *lc->mon_grouping;
int comma = *lc->mon_thousands_sep;
int points = lc->frac_digits; /* int_frac_digits? */
int minus = 0;
int count = LAST_DIGIT;
int point_pos;
int comma_position = 0;
char *result;
char buf[CASH_BUFSZ];
int minus = 0;
int count = LAST_DIGIT;
int point_pos;
int comma_position = 0;
char mon_group, comma, points;
char csymbol, dsymbol, *nsymbol;
char convention;
/* frac_digits in the C locale seems to return CHAR_MAX */
/* best guess is 2 in this case I think */
if (points == CHAR_MAX)
points = 2;
#ifdef USE_LOCALE
if (lconv == NULL) *lconv = localeconv();
point_pos = LAST_DIGIT - points;
mon_group = *lconv->mon_grouping;
comma = *lconv->mon_thousands_sep;
csymbol = *lconv->currency_symbol;
dsymbol = *lconv->mon_decimal_point;
nsymbol = lconv->negative_sign;
/* frac_digits in the C locale seems to return CHAR_MAX */
/* best guess is 2 in this case I think */
points = ((lconv->frac_digits != CHAR_MAX)? lconv->frac_digits: 2); /* int_frac_digits? */
convention = lconv->n_sign_posn;
#else
mon_group = 3;
comma = ',';
csymbol = '$';
dsymbol = '.';
nsymbol = "-";
points = 2;
convention = 0;
#endif
/* We're playing a little fast and loose with this. Shoot me. */
if (!mod_group || mod_group == CHAR_MAX)
mod_group = 3;
point_pos = LAST_DIGIT - points;
/* allow more than three decimal points and separate them */
if (comma)
{
point_pos -= (points - 1)/mod_group;
comma_position = point_pos % (mod_group + 1);
}
/* We're playing a little fast and loose with this. Shoot me. */
if (!mon_group || mon_group == CHAR_MAX)
mon_group = 3;
/* we work with positive amounts and add the minus sign at the end */
if (value < 0)
{
minus = 1;
value *= -1;
}
/* allow more than three decimal points and separate them */
if (comma) {
point_pos -= (points - 1)/mon_group;
comma_position = point_pos % (mon_group + 1);
}
/* allow for trailing negative strings */
memset(buf, ' ', CASH_BUFSZ);
buf[TERMINATOR] = buf[LAST_PAREN] = 0;
/* we work with positive amounts and add the minus sign at the end */
if (*value < 0) {
minus = 1;
*value *= -1;
}
while (value || count > (point_pos - 2))
{
if (points && count == point_pos)
buf[count--] = *lc->decimal_point;
else if (comma && count % (mod_group + 1) == comma_position)
buf[count--] = comma;
/* allow for trailing negative strings */
memset(buf, ' ', CASH_BUFSZ);
buf[TERMINATOR] = buf[LAST_PAREN] = '\0';
buf[count--] = (value % 10) + '0';
value /= 10;
}
while (*value || count > (point_pos - 2)) {
if (points && count == point_pos)
buf[count--] = dsymbol;
else if (comma && count % (mon_group + 1) == comma_position)
buf[count--] = comma;
if (buf[LAST_DIGIT] == ',')
buf[LAST_DIGIT] = buf[LAST_PAREN];
buf[count--] = (*value % 10) + '0';
*value /= 10;
}
/* see if we need to signify negative amount */
if (minus)
{
retbuf = palloc(CASH_BUFSZ + 2 - count + strlen(lc->negative_sign));
buf[count] = csymbol;
/* Position code of 0 means use parens */
if (!lc->n_sign_posn)
sprintf(retbuf, "(%s)", buf + count);
else if (lc->n_sign_posn == 2)
sprintf(retbuf, "%s%s", buf + count, lc->negative_sign);
else
sprintf(retbuf, "%s%s", lc->negative_sign, buf + count);
}
if (buf[LAST_DIGIT] == ',')
buf[LAST_DIGIT] = buf[LAST_PAREN];
/* see if we need to signify negative amount */
if (minus) {
if (!PointerIsValid(result = PALLOC(CASH_BUFSZ + 2 - count + strlen(nsymbol))))
elog(WARN,"Memory allocation failed, can't output cash",NULL);
/* Position code of 0 means use parens */
if (convention == 0)
sprintf(result, "(%s)", buf + count);
else if (convention == 2)
sprintf(result, "%s%s", buf + count, nsymbol);
else
{
retbuf = palloc(CASH_BUFSZ + 2 - count);
strcpy(retbuf, buf + count);
}
sprintf(result, "%s%s", nsymbol, buf + count);
} else {
if (!PointerIsValid(result = PALLOC(CASH_BUFSZ + 2 - count)))
elog(WARN,"Memory allocation failed, can't output cash",NULL);
return retbuf;
}
strcpy(result, buf + count);
}
/* convert a string to a long integer */
long
cash_in(const char *s)
return(result);
} /* cash_out() */
bool
cash_eq(Cash *c1, Cash *c2)
{
long value = 0;
long dec = 0;
long sgn = 1;
int seen_dot = 0;
struct lconv *lc = localeconv();
int fpoint = lc->frac_digits; /* int_frac_digits? */
if (!PointerIsValid(c1) || !PointerIsValid(c2))
return(FALSE);
/* we need to add all sorts of checking here. For now just */
/* strip all leading whitespace and any leading dollar sign */
while (isspace(*s) || *s == '$')
s++;
return(*c1 == *c2);
} /* cash_eq() */
/* a leading minus or paren signifies a negative number */
/* again, better heuristics needed */
if (*s == '-' || *s == '(')
{
sgn = -1;
s++;
}
else if (*s == '+')
s++;
bool
cash_ne(Cash *c1, Cash *c2)
{
if (!PointerIsValid(c1) || !PointerIsValid(c2))
return(FALSE);
/* frac_digits in the C locale seems to return CHAR_MAX */
/* best guess is 2 in this case I think */
if (fpoint == CHAR_MAX)
fpoint = 2;
return(*c1 != *c2);
} /* cash_ne() */
for (; ; s++)
{
/* we look for digits as long as we have less */
/* than the required number of decimal places */
if (isdigit(*s) && dec < fpoint)
{
value = (value * 10) + *s - '0';
bool
cash_lt(Cash *c1, Cash *c2)
{
if (!PointerIsValid(c1) || !PointerIsValid(c2))
return(FALSE);
if (seen_dot)
dec++;
}
else if (*s == *lc->decimal_point && !seen_dot)
seen_dot = 1;
else
{
/* round off */
if (isdigit(*s) && *s >= '5')
value++;
return(*c1 < *c2);
} /* cash_lt() */
/* adjust for less than required decimal places */
for (; dec < fpoint; dec++)
value *= 10;
bool
cash_le(Cash *c1, Cash *c2)
{
if (!PointerIsValid(c1) || !PointerIsValid(c2))
return(FALSE);
return(value * sgn);
}
}
}
return(*c1 <= *c2);
} /* cash_le() */
bool
cash_gt(Cash *c1, Cash *c2)
{
if (!PointerIsValid(c1) || !PointerIsValid(c2))
return(FALSE);
return(*c1 > *c2);
} /* cash_gt() */
bool
cash_ge(Cash *c1, Cash *c2)
{
if (!PointerIsValid(c1) || !PointerIsValid(c2))
return(FALSE);
return(*c1 >= *c2);
} /* cash_ge() */
/* used by cash_words_out() below */
/* cash_pl()
* Add two cash values.
*/
Cash *
cash_pl(Cash *c1, Cash *c2)
{
Cash *result;
if (!PointerIsValid(c1) || !PointerIsValid(c2))
return(NULL);
if (!PointerIsValid(result = PALLOCTYPE(Cash)))
elog(WARN,"Memory allocation failed, can't add cash",NULL);
*result = (*c1 + *c2);
return(result);
} /* cash_pl() */
/* cash_mi()
* Subtract two cash values.
*/
Cash *
cash_mi(Cash *c1, Cash *c2)
{
Cash *result;
if (!PointerIsValid(c1) || !PointerIsValid(c2))
return(NULL);
if (!PointerIsValid(result = PALLOCTYPE(Cash)))
elog(WARN,"Memory allocation failed, can't subtract cash",NULL);
*result = (*c1 - *c2);
return(result);
} /* cash_mi() */
/* cash_mul()
* Multiply cash by floating point number.
*/
Cash *
cash_mul(Cash *c, float8 *f)
{
Cash *result;
if (!PointerIsValid(f) || !PointerIsValid(c))
return(NULL);
if (!PointerIsValid(result = PALLOCTYPE(Cash)))
elog(WARN,"Memory allocation failed, can't multiply cash",NULL);
*result = ((*f) * (*c));
return(result);
} /* cash_mul() */
/* cash_div()
* Divide cash by floating point number.
*
* XXX Don't know if rounding or truncating is correct behavior.
* Round for now. - tgl 97/04/15
*/
Cash *
cash_div(Cash *c, float8 *f)
{
Cash *result;
if (!PointerIsValid(f) || !PointerIsValid(c))
return(NULL);
if (!PointerIsValid(result = PALLOCTYPE(Cash)))
elog(WARN,"Memory allocation failed, can't divide cash",NULL);
*result = rint(*c / *f);
return(result);
} /* cash_div() */
/* cashlarger()
* Return larger of two cash values.
*/
Cash *
cashlarger(Cash *c1, Cash *c2)
{
Cash *result;
if (!PointerIsValid(c1) || !PointerIsValid(c2))
return(NULL);
if (!PointerIsValid(result = PALLOCTYPE(Cash)))
elog(WARN,"Memory allocation failed, can't return larger cash",NULL);
*result = ((*c1 > *c2)? *c1: *c2);
return(result);
} /* cashlarger() */
/* cashsmaller()
* Return smaller of two cash values.
*/
Cash *
cashsmaller(Cash *c1, Cash *c2)
{
Cash *result;
if (!PointerIsValid(c1) || !PointerIsValid(c2))
return(NULL);
if (!PointerIsValid(result = PALLOCTYPE(Cash)))
elog(WARN,"Memory allocation failed, can't return smaller cash",NULL);
*result = ((*c1 < *c2)? *c1: *c2);
return(result);
} /* cashsmaller() */
/* cash_words_out()
* This converts a long as well but to a representation using words
* Obviously way North American centric - sorry
*/
const char *
cash_words_out(Cash *value)
{
static char buf[128];
char *p = buf;
Cash m0;
Cash m1;
Cash m2;
Cash m3;
/* work with positive numbers */
if (*value < 0) {
*value *= -1;
strcpy(buf, "minus ");
p += 6;
} else {
*buf = 0;
}
m0 = *value % 100; /* cents */
m1 = (*value/100) % 1000; /* hundreds */
m2 = (*value/100000) % 1000; /* thousands */
m3 = *value/100000000 % 1000; /* millions */
if (m3) {
strcat(buf, num_word(m3));
strcat(buf, " million ");
}
if (m2) {
strcat(buf, num_word(m2));
strcat(buf, " thousand ");
}
if (m1)
strcat(buf, num_word(m1));
if (!*p)
strcat(buf, "zero");
strcat(buf, (int)(*value/100) == 1 ? " dollar and " : " dollars and ");
strcat(buf, num_word(m0));
strcat(buf, m0 == 1 ? " cent" : " cents");
*buf = toupper(*buf);
return(buf);
} /* cash_words_out() */
/*************************************************************************
* Private routines
************************************************************************/
static const char *
num_word(int value)
num_word(Cash value)
{
static char buf[128];
static const char *small[] = {
"zero", "one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty",
"thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety"
};
const char **big = small + 18;
int tu = value % 100;
static char buf[128];
static const char *small[] = {
"zero", "one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty",
"thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety"
};
const char **big = small + 18;
int tu = value % 100;
/* deal with the simple cases first */
if (value <= 20)
return(small[value]);
/* is it an even multiple of 100? */
if (!tu)
{
sprintf(buf, "%s hundred", small[value/100]);
return(buf);
}
/* more than 99? */
if (value > 99)
{
/* is it an even multiple of 10 other than 10? */
if (value % 10 == 0 && tu > 10)
sprintf(buf, "%s hundred %s",
small[value/100], big[tu/10]);
else if (tu < 20)
sprintf(buf, "%s hundred and %s",
small[value/100], small[tu]);
else
sprintf(buf, "%s hundred %s %s",
small[value/100], big[tu/10], small[tu % 10]);
}
else
{
/* is it an even multiple of 10 other than 10? */
if (value % 10 == 0 && tu > 10)
sprintf(buf, "%s", big[tu/10]);
else if (tu < 20)
sprintf(buf, "%s", small[tu]);
else
sprintf(buf, "%s %s", big[tu/10], small[tu % 10]);
}
/* deal with the simple cases first */
if (value <= 20)
return(small[value]);
/* is it an even multiple of 100? */
if (!tu) {
sprintf(buf, "%s hundred", small[value/100]);
return(buf);
}
}
/* this converts a long as well but to a representation using words */
/* obviously way North American centric - sorry */
const char *
cash_words_out(long value)
{
static char buf[128];
char *p = buf;
long m0;
long m1;
long m2;
long m3;
/* work with positive numbers */
if (value < 0)
{
value *= -1;
strcpy(buf, "minus ");
p += 6;
}
/* more than 99? */
if (value > 99) {
/* is it an even multiple of 10 other than 10? */
if (value % 10 == 0 && tu > 10)
sprintf(buf, "%s hundred %s",
small[value/100], big[tu/10]);
else if (tu < 20)
sprintf(buf, "%s hundred and %s",
small[value/100], small[tu]);
else
*buf = 0;
sprintf(buf, "%s hundred %s %s",
small[value/100], big[tu/10], small[tu % 10]);
m0 = value % 100; /* cents */
m1 = (value/100) % 1000; /* hundreds */
m2 = (value/100000) % 1000; /* thousands */
m3 = value/100000000 % 1000; /* millions */
} else {
/* is it an even multiple of 10 other than 10? */
if (value % 10 == 0 && tu > 10)
sprintf(buf, "%s", big[tu/10]);
else if (tu < 20)
sprintf(buf, "%s", small[tu]);
else
sprintf(buf, "%s %s", big[tu/10], small[tu % 10]);
}
if (m3)
{
strcat(buf, num_word(m3));
strcat(buf, " million ");
}
if (m2)
{
strcat(buf, num_word(m2));
strcat(buf, " thousand ");
}
if (m1)
strcat(buf, num_word(m1));
if (!*p)
strcat(buf, "zero");
strcat(buf, (int)(value/100) == 1 ? " dollar and " : " dollars and ");
strcat(buf, num_word(m0));
strcat(buf, m0 == 1 ? " cent" : " cents");
*buf = toupper(*buf);
return(buf);
}
return(buf);
} /* num_word() */

View File

@ -7,7 +7,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_aggregate.h,v 1.5 1997/04/03 19:56:19 scrappy Exp $
* $Id: pg_aggregate.h,v 1.6 1997/04/15 17:40:19 scrappy Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -35,9 +35,9 @@
* aggtransfn2 transition function 2
* aggfinalfn final function
* aggbasetype type of data on which aggregate operates
* aggtranstype1 output types for xition func 1
* aggtranstype2 output types for xition func 2
* aggfinaltype output type for final func
* aggtranstype1 output types for transition func 1
* aggtranstype2 output types for transition func 2
* aggfinaltype output type for final function
* agginitval1 initial aggregate value
* agginitval2 initial value for transition state 2
* ----------------------------------------------------------------
@ -91,11 +91,13 @@ DATA(insert OID = 0 ( avg PGUID int4pl int4inc int4div 23 23 23
DATA(insert OID = 0 ( avg PGUID int2pl int2inc int2div 21 21 21 21 _null_ 0 ));
DATA(insert OID = 0 ( avg PGUID float4pl float4inc float4div 700 700 700 700 _null_ 0.0 ));
DATA(insert OID = 0 ( avg PGUID float8pl float8inc float8div 701 701 701 701 _null_ 0.0 ));
DATA(insert OID = 0 ( avg PGUID cash_pl float8inc cash_div 790 790 701 790 _null_ 0.0 ));
DATA(insert OID = 0 ( sum PGUID int4pl - - 23 23 0 23 _null_ _null_ ));
DATA(insert OID = 0 ( sum PGUID int2pl - - 21 21 0 21 _null_ _null_ ));
DATA(insert OID = 0 ( sum PGUID float4pl - - 700 700 0 700 _null_ _null_ ));
DATA(insert OID = 0 ( sum PGUID float8pl - - 701 701 0 701 _null_ _null_ ));
DATA(insert OID = 0 ( sum PGUID cash_pl - - 790 790 0 790 _null_ _null_ ));
DATA(insert OID = 0 ( max PGUID int4larger - - 23 23 0 23 _null_ _null_ ));
DATA(insert OID = 0 ( max PGUID int2larger - - 21 21 0 21 _null_ _null_ ));
@ -104,6 +106,7 @@ DATA(insert OID = 0 ( max PGUID float8larger - - 701 701 0 701 _null_ _nul
DATA(insert OID = 0 ( max PGUID int4larger - - 702 702 0 702 _null_ _null_ ));
DATA(insert OID = 0 ( max PGUID date_larger - - 1082 1082 0 1082 _null_ _null_ ));
DATA(insert OID = 0 ( max PGUID float8larger - - 1084 1084 0 1084 _null_ _null_ ));
DATA(insert OID = 0 ( max PGUID cashlarger - - 790 790 0 790 _null_ _null_ ));
DATA(insert OID = 0 ( min PGUID int4smaller - - 23 23 0 23 _null_ _null_ ));
DATA(insert OID = 0 ( min PGUID int2smaller - - 21 21 0 21 _null_ _null_ ));
@ -112,6 +115,7 @@ DATA(insert OID = 0 ( min PGUID float8smaller - - 701 701 0 701 _null_ _nul
DATA(insert OID = 0 ( min PGUID int4smaller - - 702 702 0 702 _null_ _null_ ));
DATA(insert OID = 0 ( min PGUID date_smaller - - 1082 1082 0 1082 _null_ _null_ ));
DATA(insert OID = 0 ( min PGUID float8smaller - - 1084 1084 0 1084 _null_ _null_ ));
DATA(insert OID = 0 ( min PGUID cashsmaller - - 790 790 0 790 _null_ _null_ ));
DATA(insert OID = 0 ( count PGUID - int4inc - 0 0 23 23 _null_ 0 ));

View File

@ -7,7 +7,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_operator.h,v 1.7 1997/04/02 18:36:12 scrappy Exp $
* $Id: pg_operator.h,v 1.8 1997/04/15 17:40:44 scrappy Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -353,6 +353,17 @@ DATA(insert OID = 841 ( "!~" PGUID 0 b t f 409 25 16 0 839 0 0 char2re
DATA(insert OID = 840 ( "~" PGUID 0 b t f 410 25 16 0 842 0 0 char4regexeq eqsel eqjoinsel ));
DATA(insert OID = 842 ( "!~" PGUID 0 b t f 410 25 16 0 840 0 0 char4regexne neqsel neqjoinsel ));
DATA(insert OID = 900 ( "=" PGUID 0 b t t 790 790 16 900 901 902 902 cash_eq eqsel eqjoinsel ));
DATA(insert OID = 901 ( "<>" PGUID 0 b t f 790 790 16 901 900 0 0 cash_ne neqsel neqjoinsel ));
DATA(insert OID = 902 ( "<" PGUID 0 b t f 790 790 16 903 905 0 0 cash_lt intltsel intltjoinsel ));
DATA(insert OID = 903 ( ">" PGUID 0 b t f 790 790 16 902 904 0 0 cash_gt intgtsel intgtjoinsel ));
DATA(insert OID = 904 ( "<=" PGUID 0 b t f 790 790 16 905 903 0 0 cash_le intltsel intltjoinsel ));
DATA(insert OID = 905 ( ">=" PGUID 0 b t f 790 790 16 904 902 0 0 cash_ge intgtsel intgtjoinsel ));
DATA(insert OID = 906 ( "+" PGUID 0 b t f 790 790 790 906 0 0 0 cash_pl - - ));
DATA(insert OID = 907 ( "-" PGUID 0 b t f 790 790 790 0 0 0 0 cash_mi - - ));
DATA(insert OID = 908 ( "*" PGUID 0 b t f 790 701 790 909 0 0 0 cash_mul - - ));
DATA(insert OID = 909 ( "/" PGUID 0 b t f 790 701 790 0 0 0 0 cash_div - - ));
DATA(insert OID = 930 ( "<" PGUID 0 b t f 910 910 16 934 933 0 0 oidint4lt intltsel intltjoinsel ));
DATA(insert OID = 931 ( "<=" PGUID 0 b t f 910 910 16 933 934 0 0 oidint4le intltsel intltjoinsel ));
DATA(insert OID = 932 ( "=" PGUID 0 b t f 910 910 16 932 935 0 0 oidint4eq intltsel intltjoinsel ));
@ -360,28 +371,28 @@ DATA(insert OID = 933 ( ">=" PGUID 0 b t f 910 910 16 931 930 0 0 oidi
DATA(insert OID = 934 ( ">" PGUID 0 b t f 910 910 16 930 931 0 0 oidint4gt intltsel intltjoinsel ));
DATA(insert OID = 935 ( "<>" PGUID 0 b t f 910 910 16 935 932 0 0 oidint4ne intltsel intltjoinsel ));
DATA(insert OID = 965 ( "^" PGUID 0 b t f 701 701 701 0 0 0 0 dpow - - ));
DATA(insert OID = 965 ( "^" PGUID 0 b t f 701 701 701 0 0 0 0 dpow - - ));
DATA(insert OID = 966 ( "+" PGUID 0 b t f 1034 1033 1034 0 0 0 0 aclinsert intltsel intltjoinsel ));
DATA(insert OID = 967 ( "-" PGUID 0 b t f 1034 1033 1034 0 0 0 0 aclremove intltsel intltjoinsel ));
DATA(insert OID = 968 ( "~" PGUID 0 b t f 1034 1033 16 0 0 0 0 aclcontains intltsel intltjoinsel ));
DATA(insert OID = 1054 ( "=" PGUID 0 b t t 1042 1042 16 1054 1057 1058 1058 bpchareq eqsel eqjoinsel ));
DATA(insert OID = 1055 ( "~" PGUID 0 b t f 1042 25 16 0 1056 0 0 textregexeq eqsel eqjoinsel ));
DATA(insert OID = 1056 ( "!~" PGUID 0 b t f 1042 25 16 0 1055 0 0 textregexne neqsel neqjoinsel ));
DATA(insert OID = 1057 ( "<>" PGUID 0 b t f 1042 1042 16 1057 1054 0 0 bpcharne neqsel neqjoinsel ));
DATA(insert OID = 1058 ( "<" PGUID 0 b t f 1042 1042 16 1060 1061 0 0 bpcharlt intltsel intltjoinsel ));
DATA(insert OID = 1059 ( "<=" PGUID 0 b t f 1042 1042 16 1061 1060 0 0 bpcharle intltsel intltjoinsel ));
DATA(insert OID = 1060 ( ">" PGUID 0 b t f 1042 1042 16 1058 1059 0 0 bpchargt intltsel intltjoinsel ));
DATA(insert OID = 1061 ( ">=" PGUID 0 b t f 1042 1042 16 1059 1058 0 0 bpcharge intltsel intltjoinsel ));
DATA(insert OID = 1054 ( "=" PGUID 0 b t t 1042 1042 16 1054 1057 1058 1058 bpchareq eqsel eqjoinsel ));
DATA(insert OID = 1055 ( "~" PGUID 0 b t f 1042 25 16 0 1056 0 0 textregexeq eqsel eqjoinsel ));
DATA(insert OID = 1056 ( "!~" PGUID 0 b t f 1042 25 16 0 1055 0 0 textregexne neqsel neqjoinsel ));
DATA(insert OID = 1057 ( "<>" PGUID 0 b t f 1042 1042 16 1057 1054 0 0 bpcharne neqsel neqjoinsel ));
DATA(insert OID = 1058 ( "<" PGUID 0 b t f 1042 1042 16 1060 1061 0 0 bpcharlt intltsel intltjoinsel ));
DATA(insert OID = 1059 ( "<=" PGUID 0 b t f 1042 1042 16 1061 1060 0 0 bpcharle intltsel intltjoinsel ));
DATA(insert OID = 1060 ( ">" PGUID 0 b t f 1042 1042 16 1058 1059 0 0 bpchargt intltsel intltjoinsel ));
DATA(insert OID = 1061 ( ">=" PGUID 0 b t f 1042 1042 16 1059 1058 0 0 bpcharge intltsel intltjoinsel ));
DATA(insert OID = 1062 ( "=" PGUID 0 b t t 1043 1043 16 1062 1065 1066 1066 varchareq eqsel eqjoinsel ));
DATA(insert OID = 1063 ( "~" PGUID 0 b t f 1043 25 16 0 1064 0 0 textregexeq eqsel eqjoinsel ));
DATA(insert OID = 1064 ( "!~" PGUID 0 b t f 1043 25 16 0 1063 0 0 textregexne neqsel neqjoinsel ));
DATA(insert OID = 1065 ( "<>" PGUID 0 b t f 1043 1043 16 1065 1062 0 0 varcharne neqsel neqjoinsel ));
DATA(insert OID = 1066 ( "<" PGUID 0 b t f 1043 1043 16 1068 1069 0 0 varcharlt intltsel intltjoinsel ));
DATA(insert OID = 1067 ( "<=" PGUID 0 b t f 1043 1043 16 1069 1068 0 0 varcharle intltsel intltjoinsel ));
DATA(insert OID = 1068 ( ">" PGUID 0 b t f 1043 1043 16 1066 1067 0 0 varchargt intltsel intltjoinsel ));
DATA(insert OID = 1069 ( ">=" PGUID 0 b t f 1043 1043 16 1067 1066 0 0 varcharge intltsel intltjoinsel ));
DATA(insert OID = 1062 ( "=" PGUID 0 b t t 1043 1043 16 1062 1065 1066 1066 varchareq eqsel eqjoinsel ));
DATA(insert OID = 1063 ( "~" PGUID 0 b t f 1043 25 16 0 1064 0 0 textregexeq eqsel eqjoinsel ));
DATA(insert OID = 1064 ( "!~" PGUID 0 b t f 1043 25 16 0 1063 0 0 textregexne neqsel neqjoinsel ));
DATA(insert OID = 1065 ( "<>" PGUID 0 b t f 1043 1043 16 1065 1062 0 0 varcharne neqsel neqjoinsel ));
DATA(insert OID = 1066 ( "<" PGUID 0 b t f 1043 1043 16 1068 1069 0 0 varcharlt intltsel intltjoinsel ));
DATA(insert OID = 1067 ( "<=" PGUID 0 b t f 1043 1043 16 1069 1068 0 0 varcharle intltsel intltjoinsel ));
DATA(insert OID = 1068 ( ">" PGUID 0 b t f 1043 1043 16 1066 1067 0 0 varchargt intltsel intltjoinsel ));
DATA(insert OID = 1069 ( ">=" PGUID 0 b t f 1043 1043 16 1067 1066 0 0 varcharge intltsel intltjoinsel ));
/* date operators */
DATA(insert OID = 1093 ( "=" PGUID 0 b t t 1082 1082 16 1093 1094 1095 1095 date_eq eqsel eqjoinsel ));

View File

@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_proc.h,v 1.16 1997/04/02 18:36:24 scrappy Exp $
* $Id: pg_proc.h,v 1.17 1997/04/15 17:41:03 scrappy Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@ -618,6 +618,21 @@ DATA(insert OID = 859 ( namenlike PGUID 11 f t f 2 f 16 "19 25" 100 0 0
DATA(insert OID = 860 ( char16like PGUID 11 f t f 2 f 16 "20 25" 100 0 0 100 foo bar ));
DATA(insert OID = 861 ( char16nlike PGUID 11 f t f 2 f 16 "20 25" 100 0 0 100 foo bar ));
DATA(insert OID = 886 ( cash_in PGUID 11 f t f 1 f 790 "0" 100 0 0 100 foo bar ));
DATA(insert OID = 887 ( cash_out PGUID 11 f t f 1 f 23 "0" 100 0 0 100 foo bar ));
DATA(insert OID = 888 ( cash_eq PGUID 11 f t f 2 f 16 "790 790" 100 0 0 100 foo bar ));
DATA(insert OID = 889 ( cash_ne PGUID 11 f t f 2 f 16 "790 790" 100 0 0 100 foo bar ));
DATA(insert OID = 890 ( cash_lt PGUID 11 f t f 2 f 16 "790 790" 100 0 0 100 foo bar ));
DATA(insert OID = 891 ( cash_le PGUID 11 f t f 2 f 16 "790 790" 100 0 0 100 foo bar ));
DATA(insert OID = 892 ( cash_gt PGUID 11 f t f 2 f 16 "790 790" 100 0 0 100 foo bar ));
DATA(insert OID = 893 ( cash_ge PGUID 11 f t f 2 f 16 "790 790" 100 0 0 100 foo bar ));
DATA(insert OID = 894 ( cash_pl PGUID 11 f t f 2 f 790 "790 790" 100 0 0 100 foo bar ));
DATA(insert OID = 895 ( cash_mi PGUID 11 f t f 2 f 790 "790 790" 100 0 0 100 foo bar ));
DATA(insert OID = 896 ( cash_mul PGUID 11 f t f 2 f 790 "790 701" 100 0 0 100 foo bar ));
DATA(insert OID = 897 ( cash_div PGUID 11 f t f 2 f 790 "790 701" 100 0 0 100 foo bar ));
DATA(insert OID = 898 ( cashlarger PGUID 11 f t f 2 f 790 "790 790" 100 0 0 100 foo bar ));
DATA(insert OID = 899 ( cashsmaller PGUID 11 f t f 2 f 790 "790 790" 100 0 0 100 foo bar ));
/* OIDS 900 - 999 */
DATA(insert OID = 920 ( oidint4in PGUID 11 f t f 1 f 910 "0" 100 0 0 100 foo bar));
@ -790,6 +805,7 @@ DATA(insert OID = 1193 ( timespan_text PGUID 11 f t f 1 f 1186 "25" 100 0
DATA(insert OID = 1194 ( timespan_reltime PGUID 11 f t f 1 f 703 "1186" 100 0 0 100 foo bar ));
/* reserve OIDs 1195-1199 for additional date/time conversion routines! tgl 97/03/19 */
/* OIDS 1200 - 1299 */
DATA(insert OID = 1200 ( int42reltime PGUID 11 f t f 1 f 703 "21" 100 0 0 100 foo bar ));
DATA(insert OID = 1290 ( char2icregexeq PGUID 11 f t f 2 f 16 "409 25" 100 0 0 100 foo bar ));
@ -808,6 +824,8 @@ DATA(insert OID = 1241 ( nameicregexne PGUID 11 f t f 2 f 16 "19 25" 100 0 0
DATA(insert OID = 1297 ( timestamp_in PGUID 11 f t f 1 f 1296 "0" 100 0 0 100 foo bar ));
DATA(insert OID = 1298 ( timestamp_out PGUID 11 f t f 1 f 23 "0" 100 0 0 100 foo bar ));
DATA(insert OID = 1299 ( now PGUID 11 f t f 0 f 1296 "0" 100 0 0 100 foo bar ));
/* OIDS 1300 - 1399 */
DATA(insert OID = 1306 ( timestampeq PGUID 11 f t f 2 f 16 "1296 1296" 100 0 0 100 foo bar ));
DATA(insert OID = 1307 ( timestampne PGUID 11 f t f 2 f 16 "1296 1296" 100 0 0 100 foo bar ));
DATA(insert OID = 1308 ( timestamplt PGUID 11 f t f 2 f 16 "1296 1296" 100 0 0 100 foo bar ));
@ -854,6 +872,7 @@ DATA(insert OID = 1391 ( isfinite PGUID 14 f t f 1 f 16 "1186" 100 0 0 10
DATA(insert OID = 1392 ( isfinite PGUID 14 f t f 1 f 16 "702" 100 0 0 100 "select abstime_finite($1)" - ));
/* reserve OIDs 1370-1399 for additional date/time conversion routines! tgl 97/04/01 */
/* OIDS 1400 - 1499 */
DATA(insert OID = 1400 ( float PGUID 14 f t f 1 f 701 "701" 100 0 0 100 "select $1" - ));
DATA(insert OID = 1401 ( float PGUID 14 f t f 1 f 701 "700" 100 0 0 100 "select ftod($1)" - ));
DATA(insert OID = 1402 ( float4 PGUID 14 f t f 1 f 700 "700" 100 0 0 100 "select $1" - ));
@ -861,7 +880,6 @@ DATA(insert OID = 1403 ( float4 PGUID 14 f t f 1 f 700 "701" 100 0 0 10
DATA(insert OID = 1404 ( int PGUID 14 f t f 1 f 23 "23" 100 0 0 100 "select $1" - ));
DATA(insert OID = 1405 ( int2 PGUID 14 f t f 1 f 21 "21" 100 0 0 100 "select $1" - ));
/* reserve OIDs 1370-1399 for additional date/time conversion routines! tgl 97/04/01 */
/* Oracle Compatibility Related Functions - By Edmund Mergl <E.Mergl@bawue.de> */
DATA(insert OID = 870 ( lower PGUID 11 f t f 1 f 25 "25" 100 0 0 100 foo bar ));
DATA(insert OID = 871 ( upper PGUID 11 f t f 1 f 25 "25" 100 0 0 100 foo bar ));

View File

@ -7,7 +7,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_type.h,v 1.9 1997/03/25 08:11:01 scrappy Exp $
* $Id: pg_type.h,v 1.10 1997/04/15 17:41:19 scrappy Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -143,24 +143,20 @@ typedef TypeTupleFormData *TypeTupleForm;
/* OIDS 1 - 99 */
DATA(insert OID = 16 ( bool PGUID 1 1 t b t \054 0 0 boolin boolout boolin boolout c _null_ ));
#define BOOLOID 16
DATA(insert OID = 17 ( bytea PGUID -1 -1 f b t \054 0 18 byteain byteaout byteain byteaout i _null_ ));
DATA(insert OID = 18 ( char PGUID 1 1 t b t \054 0 0 charin charout charin charout c _null_ ));
#define CHAROID 18
DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout d _null_ ));
DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout d _null_ ));
#define NAMEOID 19
DATA(insert OID = 20 ( char16 PGUID 16 16 f b t \054 0 18 char16in char16out char16in char16out i _null_ ));
/*DATA(insert OID = 20 ( dt PGUID 4 10 t b t \054 0 0 dtin dtout dtin dtout i _null_ )); */
DATA(insert OID = 21 ( int2 PGUID 2 5 t b t \054 0 0 int2in int2out int2in int2out s _null_ ));
#define INT2OID 21
DATA(insert OID = 22 ( int28 PGUID 16 50 f b t \054 0 21 int28in int28out int28in int28out i _null_ ));
/*
* XXX -- the implementation of int28's in postgres is a hack, and will
* go away someday. until that happens, there is a case (in the
@ -168,12 +164,9 @@ DATA(insert OID = 22 ( int28 PGUID 16 50 f b t \054 0 21 int28in int28ou
* over piles of int28's on the sidewalk. in order to do so, we
* need the OID of the int28 row from pg_type.
*/
#define INT28OID 22
DATA(insert OID = 23 ( int4 PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out i _null_ ));
#define INT4OID 23
DATA(insert OID = 24 ( regproc PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i _null_ ));
@ -181,7 +174,6 @@ DATA(insert OID = 25 ( text PGUID -1 -1 f b t \054 0 18 textin textout
#define TEXTOID 25
DATA(insert OID = 26 ( oid PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out i _null_ ));
#define OIDOID 26
DATA(insert OID = 27 ( tid PGUID 6 19 f b t \054 0 0 tidin tidout tidin tidout i _null_ ));
@ -232,21 +224,20 @@ DATA(insert OID = 605 ( filename PGUID 256 -1 f b t \054 0 18 filename_in file
/* OIDS 700 - 799 */
#define FLOAT4OID 700
DATA(insert OID = 700 ( float4 PGUID 4 12 f b t \054 0 0 float4in float4out float4in float4out i _null_ ));
#define FLOAT8OID 701
#define FLOAT4OID 700
DATA(insert OID = 701 ( float8 PGUID 8 24 f b t \054 0 0 float8in float8out float8in float8out d _null_ ));
#define FLOAT8OID 701
DATA(insert OID = 702 ( abstime PGUID 4 20 t b t \054 0 0 nabstimein nabstimeout nabstimein nabstimeout i _null_ ));
DATA(insert OID = 703 ( reltime PGUID 4 20 t b t \054 0 0 reltimein reltimeout reltimein reltimeout i _null_ ));
DATA(insert OID = 704 ( tinterval PGUID 12 47 f b t \054 0 0 tintervalin tintervalout tintervalin tintervalout i _null_ ));
DATA(insert OID = 705 ( unknown PGUID -1 -1 f b t \054 0 18 textin textout textin textout i _null_ ));
#define UNKNOWNOID 705
DATA(insert OID = 790 ( money PGUID 4 47 f b t \054 0 0 cash_in cash_out cash_in cash_out i _null_ ));
#define CASHOID 790
DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i _null_ ));
/* OIDS 800 - 899 */
DATA(insert OID = 810 ( oidint2 PGUID 6 20 f b t \054 0 0 oidint2in oidint2out oidint2in oidint2out i _null_ ));
@ -292,10 +283,10 @@ DATA(insert OID = 1039 ( _char2 PGUID -1 -1 f b t \054 0 409 array_in arr
DATA(insert OID = 1040 ( _char4 PGUID -1 -1 f b t \054 0 410 array_in array_out array_in array_out i _null_ ));
DATA(insert OID = 1041 ( _char8 PGUID -1 -1 f b t \054 0 411 array_in array_out array_in array_out i _null_ ));
#define BPCHAROID 1042
DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 18 bpcharin bpcharout bpcharin bpcharout i _null_ ));
#define VARCHAROID 1043
#define BPCHAROID 1042
DATA(insert OID = 1043 ( varchar PGUID -1 -1 f b t \054 0 18 varcharin varcharout varcharin varcharout i _null_ ));
#define VARCHAROID 1043
DATA(insert OID = 1082 ( date PGUID 4 10 t b t \054 0 0 date_in date_out date_in date_out i _null_ ));
#define DATEOID 1082

View File

@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: builtins.h,v 1.14 1997/04/02 18:31:52 scrappy Exp $
* $Id: builtins.h,v 1.15 1997/04/15 17:41:35 scrappy Exp $
*
* NOTES
* This should normally only be included by fmgr.h.
@ -22,6 +22,7 @@
#include <utils/geo_decls.h>
#include <utils/datetime.h>
#include <utils/nabstime.h>
#include <utils/cash.h>
#include <utils/rel.h>
/*

View File

@ -1,16 +1,35 @@
/*
cash.h
Written by D'Arcy J.M. Cain
* cash.h
* Written by D'Arcy J.M. Cain
*
* Functions to allow input and output of money normally but store
* and handle it as long integers.
*/
functions to allow input and output of money normally but store
and handle it as long integers
*/
#ifndef CASH_H
#define CASH_H
#ifndef _CASH_H
#define _CASH_H
typedef long int Cash;
const char *cash_out(long value);
long cash_in(const char *str);
const char *cash_words_out(long value);
const char *cash_out(Cash *value);
Cash *cash_in(const char *str);
#endif /* _CASH_H */
bool cash_eq(Cash *c1, Cash *c2);
bool cash_ne(Cash *c1, Cash *c2);
bool cash_lt(Cash *c1, Cash *c2);
bool cash_le(Cash *c1, Cash *c2);
bool cash_gt(Cash *c1, Cash *c2);
bool cash_ge(Cash *c1, Cash *c2);
Cash *cash_pl(Cash *c1, Cash *c2);
Cash *cash_mi(Cash *c1, Cash *c2);
Cash *cash_mul(Cash *c, float8 *f);
Cash *cash_div(Cash *c, float8 *f);
Cash *cashlarger(Cash *c1, Cash *c2);
Cash *cashsmaller(Cash *c1, Cash *c2);
const char *cash_words_out(Cash *value);
static const char *num_word(Cash value);
#endif /* CASH_H */