From 2bdd2e5dcff20e4cf5987c901a71b794808d582b Mon Sep 17 00:00:00 2001 From: Michael Meskes <meskes@postgresql.org> Date: Tue, 1 Jul 2003 12:40:52 +0000 Subject: [PATCH] Use ISO dates in pgtypeslib by default. Applied patch by Philip Yarra to fix some thread issues. Added a new data type "decimal" which is mostly the same as our "numeric" but uses a fixed length array to store the digits. This is for compatibility with Informix and maybe others. --- src/interfaces/ecpg/ChangeLog | 8 + src/interfaces/ecpg/compatlib/informix.c | 285 ++++++++++++------ src/interfaces/ecpg/ecpglib/connect.c | 28 +- src/interfaces/ecpg/ecpglib/data.c | 8 +- src/interfaces/ecpg/ecpglib/execute.c | 21 +- src/interfaces/ecpg/ecpglib/misc.c | 14 +- src/interfaces/ecpg/ecpglib/typename.c | 4 +- src/interfaces/ecpg/include/decimal.h | 2 +- src/interfaces/ecpg/include/ecpgtype.h | 4 +- src/interfaces/ecpg/include/pgtypes_numeric.h | 16 +- src/interfaces/ecpg/include/sqltypes.h | 2 +- src/interfaces/ecpg/pgtypeslib/numeric.c | 44 ++- src/interfaces/ecpg/pgtypeslib/timestamp.c | 2 +- src/interfaces/ecpg/preproc/preproc.y | 35 +-- src/interfaces/ecpg/preproc/type.c | 3 + src/interfaces/ecpg/test/Makefile | 4 +- src/interfaces/ecpg/test/num_test.pgc | 6 +- src/interfaces/ecpg/test/test_informix.pgc | 7 +- 18 files changed, 349 insertions(+), 144 deletions(-) diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index 32cb6f40ec8..ad428b5da01 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -1533,6 +1533,14 @@ Sun Jun 29 11:22:48 CEST 2003 around. PostgreSQL numeric type remains the same. - In INFORMIX_SE mode with autcommit set, make all cursors be "with hold". Is this really they way SE behaves? + +Tue Jul 1 11:57:56 CEST 2003 + + - Use ISO dates in pgtypeslib by default. + - Applied patch by Philip Yarra to fix some thread issues. + - Added a new data type "decimal" which is mostly the same as our + "numeric" but uses a fixed length array to store the digits. This is + for compatibility with Informix and maybe others. - Set ecpg version to 3.0.0 - Set ecpg library to 4.0.0 - Set pgtypes library to 1.0.0 diff --git a/src/interfaces/ecpg/compatlib/informix.c b/src/interfaces/ecpg/compatlib/informix.c index 71f914d0369..3bdbce693e0 100644 --- a/src/interfaces/ecpg/compatlib/informix.c +++ b/src/interfaces/ecpg/compatlib/informix.c @@ -11,50 +11,115 @@ char * ECPGalloc(long, int); -/* we start with the numeric functions */ -int -decadd(Numeric *arg1, Numeric *arg2, Numeric *sum) +static int +deccall2(Decimal *arg1, Decimal *arg2, int (*ptr)(Numeric *, Numeric *)) { - Numeric *temp_sum = malloc(sizeof(Numeric)) ; + Numeric *a1, *a2; int i; + + if ((a1 = PGTYPESnumeric_new()) == NULL) + return -1211; - if (temp_sum == NULL) + if ((a2 = PGTYPESnumeric_new()) == NULL) + { + PGTYPESnumeric_free(a1); return -1211; + } + + if (PGTYPESnumeric_from_decimal(arg1, a1) != 0) + { + PGTYPESnumeric_free(a1); + PGTYPESnumeric_free(a2); + return -1211; + } - i = PGTYPESnumeric_add(arg1, arg2, temp_sum); + if (PGTYPESnumeric_from_decimal(arg2, a2) != 0) + { + PGTYPESnumeric_free(a1); + PGTYPESnumeric_free(a2); + return -1211; + } + + i = (*ptr)(a1, a2); + + PGTYPESnumeric_free(a1); + PGTYPESnumeric_free(a2); + + return (i); +} - if (i == 0) /* No error */ +static int +deccall3(Decimal *arg1, Decimal *arg2, Decimal *result, int (*ptr)(Numeric *, Numeric *, Numeric *)) +{ + Numeric *a1, *a2, *nres; + int i; + + if ((a1 = PGTYPESnumeric_new()) == NULL) + return -1211; + + if ((a2 = PGTYPESnumeric_new()) == NULL) { + PGTYPESnumeric_free(a1); + return -1211; + } - if (PGTYPESnumeric_copy(temp_sum, sum) !=0) - return -1211; + if ((nres = PGTYPESnumeric_new()) == NULL) + { + PGTYPESnumeric_free(a1); + PGTYPESnumeric_free(a2); + return -1211; + } - free(temp_sum); - return 0; + if (PGTYPESnumeric_from_decimal(arg1, a1) != 0) + { + PGTYPESnumeric_free(a1); + PGTYPESnumeric_free(a2); + PGTYPESnumeric_free(nres); + return -1211; } - else + + if (PGTYPESnumeric_from_decimal(arg2, a2) != 0) { - free(temp_sum); - - if (errno == PGTYPES_NUM_OVERFLOW) - return -1200; + PGTYPESnumeric_free(a1); + PGTYPESnumeric_free(a2); + PGTYPESnumeric_free(nres); + return -1211; } + + i = (*ptr)(a1, a2, nres); + + if (i == 0) /* No error */ + PGTYPESnumeric_to_decimal(nres, result); + + PGTYPESnumeric_free(nres); + PGTYPESnumeric_free(a1); + PGTYPESnumeric_free(a2); + + return (i); +} +/* we start with the numeric functions */ +int +decadd(Decimal *arg1, Decimal *arg2, Decimal *sum) +{ + deccall3(arg1, arg2, sum, PGTYPESnumeric_add); - return -1201; + if (errno == PGTYPES_NUM_OVERFLOW) + return -1200; + else if (errno != 0) + return -1201; + else return 0; } int -deccmp(Numeric *arg1, Numeric *arg2) +deccmp(Decimal *arg1, Decimal *arg2) { - int i = PGTYPESnumeric_cmp(arg1, arg2); - - return (i); + return(deccall2(arg1, arg2, PGTYPESnumeric_cmp)); } void -deccopy(Numeric *src, Numeric *target) +deccopy(Decimal *src, Decimal *target) { - PGTYPESnumeric_copy(src, target); + memcpy(target, src, sizeof(Decimal)); } static char * @@ -77,12 +142,13 @@ strndup(const char *str, size_t len) } int -deccvasc(char *cp, int len, Numeric *np) +deccvasc(char *cp, int len, Decimal *np) { - char *str = strndup(cp, len); /* Numeric_in always converts the complete string */ + char *str = strndup(cp, len); /* Decimal_in always converts the complete string */ int ret = 0; Numeric *result; + if (!str) ret = -1201; else @@ -102,129 +168,136 @@ deccvasc(char *cp, int len, Numeric *np) } else { - if (PGTYPESnumeric_copy(result, np) !=0) - ret = -1211; + if (PGTYPESnumeric_to_decimal(result, np) !=0) + ret = -1200; free(result); } } + free(str); return ret; } int -deccvdbl(double dbl, Numeric *np) +deccvdbl(double dbl, Decimal *np) { - return(PGTYPESnumeric_from_double(dbl, np)); + Numeric *nres = PGTYPESnumeric_new(); + int result = 1; + + if (nres == NULL) + return -1211; + + result = PGTYPESnumeric_from_double(dbl, nres); + if (result == 0) + result = PGTYPESnumeric_to_decimal(nres, np); + + PGTYPESnumeric_free(nres); + return(result); } int -deccvint(int in, Numeric *np) +deccvint(int in, Decimal *np) { - return(PGTYPESnumeric_from_int(in, np)); + Numeric *nres = PGTYPESnumeric_new(); + int result = 1; + + if (nres == NULL) + return -1211; + + result = PGTYPESnumeric_from_int(in, nres); + if (result == 0) + result = PGTYPESnumeric_to_decimal(nres, np); + + PGTYPESnumeric_free(nres); + return(result); } int -deccvlong(long lng, Numeric *np) +deccvlong(long lng, Decimal *np) { - return(PGTYPESnumeric_from_long(lng, np)); + Numeric *nres = PGTYPESnumeric_new(); + int result = 1; + + if (nres == NULL) + return -1211; + + result = PGTYPESnumeric_from_long(lng, nres); + if (result == 0) + result = PGTYPESnumeric_to_decimal(nres, np); + + PGTYPESnumeric_free(nres); + return(result); } int -decdiv(Numeric *n1, Numeric *n2, Numeric *n3) +decdiv(Decimal *n1, Decimal *n2, Decimal *n3) { - Numeric *temp = malloc(sizeof(Numeric)); - int i, ret = 0; - - if (temp == NULL) - return -1211; - - i = PGTYPESnumeric_div(n1, n2, temp); + int i = deccall3(n1, n2, n3, PGTYPESnumeric_div); if (i != 0) switch (errno) { - case PGTYPES_NUM_DIVIDE_ZERO: ret = -1202; + case PGTYPES_NUM_DIVIDE_ZERO: return -1202; break; - case PGTYPES_NUM_OVERFLOW: ret = -1200; + case PGTYPES_NUM_OVERFLOW: return -1200; break; - default: ret = -1201; + default: return -1201; break; } - else - if (PGTYPESnumeric_copy(temp, n3) !=0) - ret = -1211; - - free(temp); - return ret; + + return 0; } int -decmul(Numeric *n1, Numeric *n2, Numeric *n3) +decmul(Decimal *n1, Decimal *n2, Decimal *n3) { - Numeric *temp = malloc(sizeof(Numeric)); - int i, ret = 0; - - if (temp == NULL) - return -1211; + int i = deccall3(n1, n2, n3, PGTYPESnumeric_mul); - i = PGTYPESnumeric_mul(n1, n2, temp); - if (i != 0) switch (errno) { - case PGTYPES_NUM_OVERFLOW: ret = -1200; + case PGTYPES_NUM_OVERFLOW: return -1200; break; - default: ret = -1201; + default: return -1201; break; } - else - if (PGTYPESnumeric_copy(temp, n3) !=0) - ret = -1211; - - free(temp); - return ret; + return 0; } int -decsub(Numeric *n1, Numeric *n2, Numeric *n3) +decsub(Decimal *n1, Decimal *n2, Decimal *n3) { - Numeric *temp = malloc(sizeof(Numeric)); - int i, ret = 0; - - if (temp == NULL) - return -1211; - - i = PGTYPESnumeric_sub(n1, n2, temp); + int i = deccall3(n1, n2, n3, PGTYPESnumeric_sub); if (i != 0) switch (errno) { - case PGTYPES_NUM_OVERFLOW: ret = -1200; + case PGTYPES_NUM_OVERFLOW: return -1200; break; - default: ret = -1201; + default: return -1201; break; } - else - if (PGTYPESnumeric_copy(temp, n3) !=0) - ret = -1211; - - free(temp); - return ret; + return 0; } int -dectoasc(Numeric *np, char *cp, int len, int right) +dectoasc(Decimal *np, char *cp, int len, int right) { char *str; + Numeric *nres; + + if (PGTYPESnumeric_from_decimal(np, nres) != 0) + return -1211; if (right >= 0) - str = PGTYPESnumeric_to_asc(np, right); + str = PGTYPESnumeric_to_asc(nres, right); else - str = PGTYPESnumeric_to_asc(np, 0); + str = PGTYPESnumeric_to_asc(nres, 0); + PGTYPESnumeric_free(nres); if (!str) return -1; @@ -236,15 +309,36 @@ dectoasc(Numeric *np, char *cp, int len, int right) } int -dectodbl(Numeric *np, double *dblp) +dectodbl(Decimal *np, double *dblp) { - return(PGTYPESnumeric_to_double(np, dblp)); + Numeric *nres = PGTYPESnumeric_new();; + int i; + + if (nres == NULL) + return -1211; + + if (PGTYPESnumeric_from_decimal(np, nres) != 0) + return -1211; + + i = PGTYPESnumeric_to_double(nres, dblp); + PGTYPESnumeric_free(nres); + + return i; } int -dectoint(Numeric *np, int *ip) +dectoint(Decimal *np, int *ip) { - int ret = PGTYPESnumeric_to_int(np, ip); + int ret; + Numeric *nres = PGTYPESnumeric_new(); + + if (nres == NULL) + return -1211; + + if (PGTYPESnumeric_from_decimal(np, nres) != 0) + return -1211; + + ret = PGTYPESnumeric_to_int(nres, ip); if (ret == PGTYPES_NUM_OVERFLOW) ret = -1200; @@ -253,9 +347,18 @@ dectoint(Numeric *np, int *ip) } int -dectolong(Numeric *np, long *lngp) +dectolong(Decimal *np, long *lngp) { - int ret = PGTYPESnumeric_to_long(np, lngp); + int ret; + Numeric *nres = PGTYPESnumeric_new();; + + if (nres == NULL) + return -1211; + + if (PGTYPESnumeric_from_decimal(np, nres) != 0) + return -1211; + + ret = PGTYPESnumeric_to_long(nres, lngp); if (ret == PGTYPES_NUM_OVERFLOW) ret = -1200; diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c index 77505f1184a..d7c721acd33 100644 --- a/src/interfaces/ecpg/ecpglib/connect.c +++ b/src/interfaces/ecpg/ecpglib/connect.c @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.9 2003/06/26 11:37:05 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.10 2003/07/01 12:40:51 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" @@ -18,15 +18,11 @@ static pthread_mutex_t connections_mutex = PTHREAD_MUTEX_INITIALIZER; static struct connection *all_connections = NULL; static struct connection *actual_connection = NULL; -struct connection * -ECPGget_connection(const char *connection_name) +static struct connection * +ecpg_get_connection_nr(const char *connection_name) { struct connection *ret = NULL; -#ifdef USE_THREADS - pthread_mutex_lock(&connections_mutex); -#endif - if( (connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0) ) { ret = actual_connection; @@ -43,11 +39,25 @@ ECPGget_connection(const char *connection_name) ret = con; } + return( ret ); +} + +struct connection * +ECPGget_connection(const char *connection_name) +{ + struct connection *ret = NULL; +#ifdef USE_THREADS + pthread_mutex_lock(&connections_mutex); +#endif + + ret = ecpg_get_connection_nr(connection_name); + #ifdef USE_THREADS pthread_mutex_unlock(&connections_mutex); #endif - return( ret ); + return (ret); + } static void @@ -546,7 +556,7 @@ ECPGdisconnect(int lineno, const char *connection_name) } else { - con = ECPGget_connection(connection_name); + con = ecpg_get_connection_nr(connection_name); if (!ECPGinit(con, connection_name, lineno)) { diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c index 77f35e639e0..c9da13794df 100644 --- a/src/interfaces/ecpg/ecpglib/data.c +++ b/src/interfaces/ecpg/ecpglib/data.c @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.9 2003/06/26 11:37:05 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.10 2003/07/01 12:40:51 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" @@ -398,6 +398,7 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, } break; + case ECPGt_decimal: case ECPGt_numeric: if (pval) { @@ -419,7 +420,10 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, else nres = PGTYPESnumeric_from_asc("0.0", &scan_length); - PGTYPESnumeric_copy(nres, (Numeric *)(var + offset * act_tuple)); + if (type == ECPGt_numeric) + PGTYPESnumeric_copy(nres, (Numeric *)(var + offset * act_tuple)); + else + PGTYPESnumeric_to_decimal(nres, (Decimal *)(var + offset * act_tuple)); break; case ECPGt_interval: diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c index ad5ab5d1f02..bc945a442c1 100644 --- a/src/interfaces/ecpg/ecpglib/execute.c +++ b/src/interfaces/ecpg/ecpglib/execute.c @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.13 2003/06/26 11:37:05 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.14 2003/07/01 12:40:51 meskes Exp $ */ /* * The aim is to get a simpler inteface to the database routines. @@ -820,16 +820,24 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var, } break; + case ECPGt_decimal: case ECPGt_numeric: { char *str = NULL; int slen; + Numeric *nval = PGTYPESnumeric_new(); if (var->arrsize > 1) { for (element = 0; element < var->arrsize; element++) { - str = PGTYPESnumeric_to_asc((Numeric *)((var + var->offset * element)->value), 0); + if (var->type == ECPGt_numeric) + PGTYPESnumeric_copy((Numeric *)((var + var->offset * element)->value), nval); + else + PGTYPESnumeric_from_decimal((Decimal *)((var + var->offset * element)->value), nval); + + str = PGTYPESnumeric_to_asc(nval, 0); + PGTYPESnumeric_free(nval); slen = strlen (str); if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + 5, stmt->lineno))) @@ -845,7 +853,14 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var, } else { - str = PGTYPESnumeric_to_asc((Numeric *)(var->value), 0); + if (var->type == ECPGt_numeric) + PGTYPESnumeric_copy((Numeric *)(var->value), nval); + else + PGTYPESnumeric_from_decimal((Decimal *)(var->value), nval); + + str = PGTYPESnumeric_to_asc(nval, 0); + + PGTYPESnumeric_free(nval); slen = strlen (str); if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno))) diff --git a/src/interfaces/ecpg/ecpglib/misc.c b/src/interfaces/ecpg/ecpglib/misc.c index 33091e7d8c0..6c9bd208c7b 100644 --- a/src/interfaces/ecpg/ecpglib/misc.c +++ b/src/interfaces/ecpg/ecpglib/misc.c @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.8 2003/06/26 01:45:04 momjian Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.9 2003/07/01 12:40:51 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" @@ -85,6 +85,7 @@ static struct sqlca_t sqlca = #ifdef USE_THREADS static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER; #endif static int simple_debug = 0; static FILE *debugstream = NULL; @@ -204,7 +205,7 @@ void ECPGdebug(int n, FILE *dbgs) { #ifdef USE_THREADS - pthread_mutex_lock(&debug_mutex); + pthread_mutex_lock(&debug_init_mutex); #endif simple_debug = n; @@ -212,7 +213,7 @@ ECPGdebug(int n, FILE *dbgs) ECPGlog("ECPGdebug: set to %d\n", simple_debug); #ifdef USE_THREADS - pthread_mutex_unlock(&debug_mutex); + pthread_mutex_unlock(&debug_init_mutex); #endif } @@ -241,6 +242,7 @@ ECPGlog(const char *format,...) va_start(ap, format); vfprintf(debugstream, f, ap); va_end(ap); + fflush(debugstream); ECPGfree(f); } @@ -287,6 +289,9 @@ ECPGset_informix_null(enum ECPGttype type, void *ptr) case ECPGt_varchar: *(((struct ECPGgeneric_varchar *) ptr)->arr) = 0x00; break; + case ECPGt_decimal: + ((Decimal *) ptr)->sign = NUMERIC_NAN; + break; case ECPGt_numeric: ((Numeric *) ptr)->sign = NUMERIC_NAN; break; @@ -345,6 +350,9 @@ ECPGis_informix_null(enum ECPGttype type, void *ptr) case ECPGt_varchar: if (*(((struct ECPGgeneric_varchar *) ptr)->arr) == 0x00) return true; break; + case ECPGt_decimal: + if (((Decimal *) ptr)->sign == NUMERIC_NAN) return true; + break; case ECPGt_numeric: if (((Numeric *) ptr)->sign == NUMERIC_NAN) return true; break; diff --git a/src/interfaces/ecpg/ecpglib/typename.c b/src/interfaces/ecpg/ecpglib/typename.c index f8eb793ba37..752b4f6063e 100644 --- a/src/interfaces/ecpg/ecpglib/typename.c +++ b/src/interfaces/ecpg/ecpglib/typename.c @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/typename.c,v 1.7 2003/06/20 12:01:46 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/typename.c,v 1.8 2003/07/01 12:40:51 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" @@ -48,6 +48,8 @@ ECPGtype_name(enum ECPGttype typ) return "varchar"; case ECPGt_char_variable: return "char"; + case ECPGt_decimal: + return "Decimal"; case ECPGt_numeric: return "Numeric"; case ECPGt_date: diff --git a/src/interfaces/ecpg/include/decimal.h b/src/interfaces/ecpg/include/decimal.h index acbb758814a..e0cb06bd5c8 100644 --- a/src/interfaces/ecpg/include/decimal.h +++ b/src/interfaces/ecpg/include/decimal.h @@ -1,7 +1,7 @@ #include <pgtypes_numeric.h> #ifndef dec_t -#define dec_t Numeric +#define dec_t Decimal #endif /* dec_t */ int decadd(dec_t *, dec_t *, dec_t *); diff --git a/src/interfaces/ecpg/include/ecpgtype.h b/src/interfaces/ecpg/include/ecpgtype.h index 94899413da5..7a299d0be89 100644 --- a/src/interfaces/ecpg/include/ecpgtype.h +++ b/src/interfaces/ecpg/include/ecpgtype.h @@ -44,8 +44,8 @@ enum ECPGttype ECPGt_bool, ECPGt_float, ECPGt_double, ECPGt_varchar, ECPGt_varchar2, - ECPGt_numeric, - ECPGt_decimal, /* only used internally */ + ECPGt_numeric, /* this is a decimal that stores its digits in a malloced array */ + ECPGt_decimal, /* this is a decimal that stores its digits in a fixed array */ ECPGt_date, ECPGt_timestamp, ECPGt_interval, diff --git a/src/interfaces/ecpg/include/pgtypes_numeric.h b/src/interfaces/ecpg/include/pgtypes_numeric.h index cd7552db384..28b902f290d 100644 --- a/src/interfaces/ecpg/include/pgtypes_numeric.h +++ b/src/interfaces/ecpg/include/pgtypes_numeric.h @@ -9,6 +9,8 @@ #define NUMERIC_MIN_DISPLAY_SCALE 0 #define NUMERIC_MIN_SIG_DIGITS 16 +#define DECSIZE 30 + typedef unsigned char NumericDigit; typedef struct { @@ -21,7 +23,17 @@ typedef struct NumericDigit *digits; /* decimal digits */ } Numeric; -Numeric *PGTYPESnew(void); +typedef struct +{ + int ndigits; /* number of digits in digits[] - can be 0! */ + int weight; /* weight of first digit */ + int rscale; /* result scale */ + int dscale; /* display scale */ + int sign; /* NUMERIC_POS, NUMERIC_NEG, or NUMERIC_NAN */ + NumericDigit digits[DECSIZE]; /* decimal digits */ +} Decimal; + +Numeric *PGTYPESnumeric_new(void); void PGTYPESnumeric_free(Numeric *); Numeric *PGTYPESnumeric_from_asc(char *, char **); char *PGTYPESnumeric_to_asc(Numeric *, int); @@ -37,5 +49,7 @@ int PGTYPESnumeric_from_double(double, Numeric *); int PGTYPESnumeric_to_double(Numeric *, double *); int PGTYPESnumeric_to_int(Numeric *, int *); int PGTYPESnumeric_to_long(Numeric *, long *); +int PGTYPESnumeric_to_decimal(Numeric *, Decimal *); +int PGTYPESnumeric_from_decimal(Decimal *, Numeric *); #endif /* PGTYPES_NUMERIC */ diff --git a/src/interfaces/ecpg/include/sqltypes.h b/src/interfaces/ecpg/include/sqltypes.h index e6a96bcf48d..c50bf54314b 100644 --- a/src/interfaces/ecpg/include/sqltypes.h +++ b/src/interfaces/ecpg/include/sqltypes.h @@ -4,7 +4,7 @@ #define CLONGTYPE ECPGt_long #define CFLOATTYPE ECPGt_float #define CDOUBLETYPE ECPGt_double -#define CDECIMALTYPE ECPGt_numeric +#define CDECIMALTYPE ECPGt_decimal #define CFIXCHARTYPE 108 #define CSTRINGTYPE ECPGt_char #define CDATETYPE ECPGt_date diff --git a/src/interfaces/ecpg/pgtypeslib/numeric.c b/src/interfaces/ecpg/pgtypeslib/numeric.c index a3f96339848..b2b1e9e6124 100644 --- a/src/interfaces/ecpg/pgtypeslib/numeric.c +++ b/src/interfaces/ecpg/pgtypeslib/numeric.c @@ -126,7 +126,7 @@ alloc_var(Numeric *var, int ndigits) } Numeric * -PGTYPESnew(void) +PGTYPESnumeric_new(void) { Numeric *var; @@ -1489,3 +1489,45 @@ PGTYPESnumeric_to_long(Numeric* nv, long* lp) { return 0; } +int +PGTYPESnumeric_to_decimal(Numeric *src, Decimal *dst) { + int i; + + if (src->ndigits > DECSIZE) { + errno = PGTYPES_NUM_OVERFLOW; + return -1; + } + + dst->weight = src->weight; + dst->rscale = src->rscale; + dst->dscale = src->dscale; + dst->sign = src->sign; + dst->ndigits = src->ndigits; + + for (i = 0; i < src->ndigits; i++) { + dst->digits[i] = src->digits[i]; + } + + return 0; +} + +int +PGTYPESnumeric_from_decimal(Decimal *src, Numeric *dst) { + int i; + + zero_var(dst); + + dst->weight = src->weight; + dst->rscale = src->rscale; + dst->dscale = src->dscale; + dst->sign = src->sign; + + if (alloc_var(dst, src->ndigits) != 0) + return -1; + + for (i = 0; i < src->ndigits; i++) { + dst->digits[i] = src->digits[i]; + } + + return 0; +} diff --git a/src/interfaces/ecpg/pgtypeslib/timestamp.c b/src/interfaces/ecpg/pgtypeslib/timestamp.c index e65929b0d26..08d5db19e9f 100644 --- a/src/interfaces/ecpg/pgtypeslib/timestamp.c +++ b/src/interfaces/ecpg/pgtypeslib/timestamp.c @@ -341,7 +341,7 @@ PGTYPEStimestamp_to_asc(Timestamp tstamp) char buf[MAXDATELEN + 1]; char *tzn = NULL; fsec_t fsec; - int DateStyle = 0; + int DateStyle = 1; /* this defaults to ISO_DATES, shall we make it an option? */ if (TIMESTAMP_NOT_FINITE(tstamp)) EncodeSpecialTimestamp(tstamp, buf); diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index b82adfa7325..a4aa18e50ce 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.243 2003/06/29 16:52:58 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.244 2003/07/01 12:40:51 meskes Exp $ */ /* Copyright comment */ %{ @@ -4453,7 +4453,7 @@ single_vt_type: common_type else if (strcmp($1, "decimal") == 0) { $$.type_enum = ECPGt_decimal; - $$.type_str = make_str("Numeric"); + $$.type_str = make_str("Decimal"); $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; @@ -4751,11 +4751,19 @@ common_type: simple_type } | ECPGColLabelCommon '(' precision opt_scale ')' { - if (strcmp($1, "numeric") != 0 && strcmp($1, "decimal") != 0) + if (strcmp($1, "numeric") == 0) + { + $$.type_enum = ECPGt_numeric; + $$.type_str = make_str("Numeric"); + } + else if (strcmp($1, "decimal") == 0) + { + $$.type_enum = ECPGt_decimal; + $$.type_str = make_str("Decimal"); + } + else mmerror(PARSE_ERROR, ET_ERROR, "Only numeric/decimal have precision/scale argument"); - $$.type_enum = (strcmp($1, "numeric") != 0) ? ECPGt_decimal : ECPGt_numeric; - $$.type_str = make_str("Numeric"); $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; @@ -4807,7 +4815,7 @@ var_type: common_type else if (strcmp($1, "decimal") == 0) { $$.type_enum = ECPGt_decimal; - $$.type_str = make_str("Numeric"); + $$.type_str = make_str("Deciaml"); $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; @@ -5076,21 +5084,6 @@ variable: opt_pointer ECPGColLabelCommon opt_array_bounds opt_initializer $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4); break; - case ECPGt_decimal: /* this is used by informix and need to be initialized */ - if (atoi(dimension) < 0) - type = ECPGmake_simple_type(ECPGt_numeric, make_str("1")); - else - type = ECPGmake_array_type(ECPGmake_simple_type(ECPGt_numeric, make_str("1")), dimension); - - if (strlen($4) == 0) - { - $4 = mm_alloc(sizeof(" = {0, 0, 0, 0, 0, NULL, NULL}")); - strcpy($4, " = {0, 0, 0, 0, 0, NULL, NULL}"); - } - - $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4); - - break; default: if (atoi(dimension) < 0) type = ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1")); diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index 80406bbccc5..58ef58af985 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -172,6 +172,9 @@ get_type(enum ECPGttype type) case ECPGt_const: /* constant string quoted */ return ("ECPGt_const"); break; + case ECPGt_decimal: + return ("ECPGt_decimal"); + break; case ECPGt_numeric: return ("ECPGt_numeric"); break; diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile index 78bbcbe286a..7e7f1fee07d 100644 --- a/src/interfaces/ecpg/test/Makefile +++ b/src/interfaces/ecpg/test/Makefile @@ -1,4 +1,4 @@ -# $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Makefile,v 1.37 2003/06/25 10:44:21 meskes Exp $ +# $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Makefile,v 1.38 2003/07/01 12:40:52 meskes Exp $ subdir = src/interfaces/ecpg/test top_builddir = ../../../.. @@ -22,7 +22,7 @@ test_informix: test_informix.o $(ECPG) $< test_informix.c: test_informix.pgc - $(ECPG) -C INFORMIX $< + $(ECPG) -C INFORMIX -r no_indicator $< clean: rm -f $(TESTS) $(TESTS:%=%.o) $(TESTS:%=%.c) log diff --git a/src/interfaces/ecpg/test/num_test.pgc b/src/interfaces/ecpg/test/num_test.pgc index 5b83af5bd07..7cf687c220a 100644 --- a/src/interfaces/ecpg/test/num_test.pgc +++ b/src/interfaces/ecpg/test/num_test.pgc @@ -18,16 +18,16 @@ main() exec sql whenever sqlerror do sqlprint(); exec sql connect to mm; - exec sql create table test (text char(5), num decimal(14,7)); + exec sql create table test (text char(5), num numeric(14,7)); - value1 = PGTYPESnew(); + value1 = PGTYPESnumeric_new(); PGTYPESnumeric_from_int(1407, value1); text = PGTYPESnumeric_to_asc(value1, 0); printf("long = %s\n", text); value1 = PGTYPESnumeric_from_asc("2369.7", NULL); value2 = PGTYPESnumeric_from_asc("10.0", NULL); - res = PGTYPESnew(); + res = PGTYPESnumeric_new(); PGTYPESnumeric_add(value1, value2, res); text = PGTYPESnumeric_to_asc(res, 0); printf("add = %s\n", text); diff --git a/src/interfaces/ecpg/test/test_informix.pgc b/src/interfaces/ecpg/test/test_informix.pgc index 0ca4c0647fc..fa0de6eb6ef 100644 --- a/src/interfaces/ecpg/test/test_informix.pgc +++ b/src/interfaces/ecpg/test/test_informix.pgc @@ -5,7 +5,7 @@ void openit(void); int main() { $int i = 14; - $decimal j; + $decimal j, m, n; FILE *dbgs; if ((dbgs = fopen("log", "w")) != NULL) @@ -41,7 +41,10 @@ int main() } } - $delete from test where i=87; + deccvint(7, &j); + deccvint(14, &m); + decadd(&j, &m, &n); + $delete from test where i=:n; printf("delete: %ld\n", sqlca.sqlcode); $commit; -- GitLab