From 7b85b730f59c9330b825472011d22bd173005c27 Mon Sep 17 00:00:00 2001 From: Michael Meskes Date: Tue, 1 Apr 2003 14:37:25 +0000 Subject: [PATCH] More patches for informix compatibility. --- src/interfaces/ecpg/compatlib/informix.c | 71 ++- src/interfaces/ecpg/ecpglib/data.c | 22 +- src/interfaces/ecpg/ecpglib/execute.c | 22 +- src/interfaces/ecpg/include/decimal.h | 12 +- src/interfaces/ecpg/include/pgtypes_date.h | 10 +- src/interfaces/ecpg/include/pgtypes_error.h | 23 +- .../ecpg/include/pgtypes_interval.h | 6 +- src/interfaces/ecpg/include/pgtypes_numeric.h | 16 +- .../ecpg/include/pgtypes_timestamp.h | 10 +- src/interfaces/ecpg/pgtypeslib/common.c | 112 +++- src/interfaces/ecpg/pgtypeslib/datetime.c | 68 +-- src/interfaces/ecpg/pgtypeslib/dt.h | 39 +- src/interfaces/ecpg/pgtypeslib/dt_common.c | 5 + src/interfaces/ecpg/pgtypeslib/extern.h | 44 +- src/interfaces/ecpg/pgtypeslib/interval.c | 4 +- src/interfaces/ecpg/pgtypeslib/numeric.c | 34 +- src/interfaces/ecpg/pgtypeslib/timestamp.c | 508 +++++++++++++++--- 17 files changed, 772 insertions(+), 234 deletions(-) diff --git a/src/interfaces/ecpg/compatlib/informix.c b/src/interfaces/ecpg/compatlib/informix.c index b8fd79acde..23e0a820f2 100644 --- a/src/interfaces/ecpg/compatlib/informix.c +++ b/src/interfaces/ecpg/compatlib/informix.c @@ -64,7 +64,7 @@ deccvasc(char *cp, int len, Numeric *np) ret = -1201; else { - np = PGTYPESnumeric_aton(str, NULL); + np = PGTYPESnumeric_from_asc(str, NULL); if (!np) { switch (errno) @@ -85,19 +85,19 @@ deccvasc(char *cp, int len, Numeric *np) int deccvdbl(double dbl, Numeric *np) { - return(PGTYPESnumeric_dton(dbl, np)); + return(PGTYPESnumeric_from_double(dbl, np)); } int deccvint(int in, Numeric *np) { - return(PGTYPESnumeric_iton(in, np)); + return(PGTYPESnumeric_from_int(in, np)); } int deccvlong(long lng, Numeric *np) { - return(PGTYPESnumeric_lton(lng, np)); + return(PGTYPESnumeric_from_long(lng, np)); } int @@ -159,9 +159,9 @@ dectoasc(Numeric *np, char *cp, int len, int right) char *str; if (right >= 0) - str = PGTYPESnumeric_ntoa(np, right); + str = PGTYPESnumeric_to_asc(np, right); else - str = PGTYPESnumeric_ntoa(np, 0); + str = PGTYPESnumeric_to_asc(np, 0); if (!str) return -1; @@ -176,13 +176,13 @@ dectoasc(Numeric *np, char *cp, int len, int right) int dectodbl(Numeric *np, double *dblp) { - return(PGTYPESnumeric_ntod(np, dblp)); + return(PGTYPESnumeric_to_double(np, dblp)); } int dectoint(Numeric *np, int *ip) { - int ret = PGTYPESnumeric_ntoi(np, ip); + int ret = PGTYPESnumeric_to_int(np, ip); if (ret == PGTYPES_NUM_OVERFLOW) ret = -1200; @@ -193,7 +193,7 @@ dectoint(Numeric *np, int *ip) int dectolong(Numeric *np, long *lngp) { - int ret = PGTYPESnumeric_ntol(np, lngp); + int ret = PGTYPESnumeric_to_long(np, lngp); if (ret == PGTYPES_NUM_OVERFLOW) ret = -1200; @@ -205,7 +205,7 @@ dectolong(Numeric *np, long *lngp) int rdatestr (Date d, char *str) { - char *tmp = PGTYPESdate_dtoa(d); + char *tmp = PGTYPESdate_to_asc(d); if (!tmp) return -1210; @@ -217,6 +217,15 @@ rdatestr (Date d, char *str) return 0; } +int +rstrdate (char *str, Date *d) +{ + Date dat = PGTYPESdate_from_asc(str, NULL); + + /* XXX: ERROR handling hier und in datetime.c */ + return 0; +} + void rtoday (Date *d) { @@ -237,7 +246,7 @@ rdefmtdate (Date *d, char *fmt, char *str) /* TODO: take care of DBCENTURY environment variable */ /* PGSQL functions allow all centuries */ - if (PGTYPESdate_defmtdate(d, fmt, str) == 0) + if (PGTYPESdate_defmt_asc(d, fmt, str) == 0) return 0; switch (errno) @@ -254,7 +263,7 @@ rdefmtdate (Date *d, char *fmt, char *str) int rfmtdate (Date d, char *fmt, char *str) { - if (PGTYPESdate_fmtdate(d, fmt, str) == 0) + if (PGTYPESdate_fmt_asc(d, fmt, str) == 0) return 0; if (errno == ENOMEM) @@ -275,19 +284,36 @@ rmdyjul (short mdy[3], Date *d) void dtcurrent (Timestamp *ts) { - return; + PGTYPEStimestamp_current (ts); } int dtcvasc (char *str, Timestamp *ts) { + Timestamp ts_tmp; + int i; + char **endptr = &str; + + ts_tmp = PGTYPEStimestamp_from_asc(str, endptr); + i = errno; + if (i) { + return i; + } + if (**endptr) { + /* extra characters exist at the end */ + return -1264; + } + + /* everything went fine */ + *ts = ts_tmp; + return 0; } int dtsub (Timestamp *ts1, Timestamp *ts2, Interval *iv) { - return 0; + return PGTYPEStimestamp_sub(ts1, ts2, iv); } int @@ -299,22 +325,21 @@ dttoasc (Timestamp *ts, char *output) int dttofmtasc (Timestamp *ts, char *output, int str_len, char *fmtstr) { - return 0; + return PGTYPEStimestamp_fmt_asc(ts, output, str_len, fmtstr); } int intoasc(Interval *i, char *str) { + str = PGTYPESinterval_to_asc(i); + + if (!str) + return -errno; + return 0; } /* And finally some misc functions */ -int -rstrdate (char *str, Date *d) -{ - return 0; -} - int rfmtlong(long lvalue, char *format, char *outbuf) { @@ -352,8 +377,10 @@ rtypmsize(int type, int len) } void -rupshift(char *s) +rupshift(char *str) { + for (; *str != '\0'; str++) + if (islower(*str)) *str = toupper(*str); return; } diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c index 5d6f31f089..cae1c500d9 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.3 2003/03/27 14:29:17 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.4 2003/04/01 14:37:25 meskes Exp $ */ #include "postgres_fe.h" @@ -384,9 +384,9 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, if (pval) { if (isarray && *pval == '"') - nres = PGTYPESnumeric_aton(pval + 1, &scan_length); + nres = PGTYPESnumeric_from_asc(pval + 1, &scan_length); else - nres = PGTYPESnumeric_aton(pval, &scan_length); + nres = PGTYPESnumeric_from_asc(pval, &scan_length); if (isarray && *scan_length == '"') scan_length++; @@ -399,7 +399,7 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, } } else - nres = PGTYPESnumeric_aton("0.0", &scan_length); + nres = PGTYPESnumeric_from_asc("0.0", &scan_length); PGTYPESnumeric_copy(nres, (Numeric *)(var + offset * act_tuple)); break; @@ -408,9 +408,9 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, if (pval) { if (isarray && *pval == '"') - ires = PGTYPESinterval_atoi(pval + 1, &scan_length); + ires = PGTYPESinterval_from_asc(pval + 1, &scan_length); else - ires = PGTYPESinterval_atoi(pval, &scan_length); + ires = PGTYPESinterval_from_asc(pval, &scan_length); if (isarray && *scan_length == '"') scan_length++; @@ -423,7 +423,7 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, } } else - ires = PGTYPESinterval_atoi("0 seconds", NULL); + ires = PGTYPESinterval_from_asc("0 seconds", NULL); PGTYPESinterval_copy(ires, (Interval *)(var + offset * act_tuple)); break; @@ -431,9 +431,9 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, if (pval) { if (isarray && *pval == '"') - ddres = PGTYPESdate_atod(pval + 1, &scan_length); + ddres = PGTYPESdate_from_asc(pval + 1, &scan_length); else - ddres = PGTYPESdate_atod(pval, &scan_length); + ddres = PGTYPESdate_from_asc(pval, &scan_length); if (isarray && *scan_length == '"') scan_length++; @@ -453,9 +453,9 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, if (pval) { if (isarray && *pval == '"') - tres = PGTYPEStimestamp_atot(pval + 1, &scan_length); + tres = PGTYPEStimestamp_from_asc(pval + 1, &scan_length); else - tres = PGTYPEStimestamp_atot(pval, &scan_length); + tres = PGTYPEStimestamp_from_asc(pval, &scan_length); if (isarray && *scan_length == '"') scan_length++; diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c index 6a9b38e7a8..99850664e8 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.7 2003/03/30 11:48:18 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.8 2003/04/01 14:37:25 meskes Exp $ */ /* * The aim is to get a simpler inteface to the database routines. @@ -847,7 +847,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var, { for (element = 0; element < var->arrsize; element++) { - str = PGTYPESnumeric_ntoa((Numeric *)((var + var->offset * element)->value), 0); + str = PGTYPESnumeric_to_asc((Numeric *)((var + var->offset * element)->value), 0); slen = strlen (str); if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + 5, stmt->lineno))) @@ -863,7 +863,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var, } else { - str = PGTYPESnumeric_ntoa((Numeric *)(var->value), 0); + str = PGTYPESnumeric_to_asc((Numeric *)(var->value), 0); slen = strlen (str); if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno))) @@ -888,7 +888,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var, { for (element = 0; element < var->arrsize; element++) { - str = PGTYPESinterval_itoa((Interval *)((var + var->offset * element)->value)); + str = PGTYPESinterval_to_asc((Interval *)((var + var->offset * element)->value)); slen = strlen (str); if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + 5, stmt->lineno))) @@ -904,7 +904,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var, } else { - str = PGTYPESinterval_itoa((Interval *)(var->value)); + str = PGTYPESinterval_to_asc((Interval *)(var->value)); slen = strlen (str); if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno))) @@ -929,7 +929,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var, { for (element = 0; element < var->arrsize; element++) { - str = PGTYPESdate_dtoa(*(Date *)((var + var->offset * element)->value)); + str = PGTYPESdate_to_asc(*(Date *)((var + var->offset * element)->value)); slen = strlen (str); if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + 5, stmt->lineno))) @@ -945,7 +945,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var, } else { - str = PGTYPESdate_dtoa(*(Date *)(var->value)); + str = PGTYPESdate_to_asc(*(Date *)(var->value)); slen = strlen (str); if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno))) @@ -970,7 +970,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var, { for (element = 0; element < var->arrsize; element++) { - str = PGTYPEStimestamp_ttoa(*(Timestamp *)((var + var->offset * element)->value)); + str = PGTYPEStimestamp_to_asc(*(Timestamp *)((var + var->offset * element)->value)); slen = strlen (str); if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + 5, stmt->lineno))) @@ -986,7 +986,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var, } else { - str = PGTYPEStimestamp_ttoa(*(Timestamp *)(var->value)); + str = PGTYPEStimestamp_to_asc(*(Timestamp *)(var->value)); slen = strlen (str); if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno))) @@ -1239,9 +1239,7 @@ ECPGexecute(struct statement * stmt) { ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n", stmt->lineno, notify->relname, notify->be_pid); -/* PQfreemem(notify);*/ - free(notify); -#warning Remove PQfreemem define + PQfreemem(notify); } return status; diff --git a/src/interfaces/ecpg/include/decimal.h b/src/interfaces/ecpg/include/decimal.h index 10c8f3b179..acbb758814 100644 --- a/src/interfaces/ecpg/include/decimal.h +++ b/src/interfaces/ecpg/include/decimal.h @@ -4,16 +4,16 @@ #define dec_t Numeric #endif /* dec_t */ -int decadd(dec_t *, Numeric *, Numeric *); -int deccmp(dec_t *, Numeric *); -void deccopy(dec_t *, Numeric *); +int decadd(dec_t *, dec_t *, dec_t *); +int deccmp(dec_t *, dec_t *); +void deccopy(dec_t *, dec_t *); int deccvasc(char *, int, dec_t *); int deccvdbl(double, dec_t *); int deccvint(int, dec_t *); int deccvlong(long, dec_t *); -int decdiv(dec_t *, Numeric *, Numeric *); -int decmul(dec_t *, Numeric *, Numeric *); -int decsub(dec_t *, Numeric *, Numeric *); +int decdiv(dec_t *, dec_t *, dec_t *); +int decmul(dec_t *, dec_t *, dec_t *); +int decsub(dec_t *, dec_t *, dec_t *); int dectoasc(dec_t *, char *, int, int); int dectodbl(dec_t *, double *); int dectoint(dec_t *, int *); diff --git a/src/interfaces/ecpg/include/pgtypes_date.h b/src/interfaces/ecpg/include/pgtypes_date.h index 76dedb866c..190a9de703 100644 --- a/src/interfaces/ecpg/include/pgtypes_date.h +++ b/src/interfaces/ecpg/include/pgtypes_date.h @@ -5,13 +5,13 @@ #define Date long -extern Date PGTYPESdate_atod(char *, char **); -extern char *PGTYPESdate_dtoa(Date); -extern Date PGTYPESdate_ttod(Timestamp); +extern Date PGTYPESdate_from_asc(char *, char **); +extern char *PGTYPESdate_to_asc(Date); +extern Date PGTYPESdate_from_timestamp(Timestamp); extern void PGTYPESdate_julmdy(Date, int*); extern void PGTYPESdate_mdyjul(int*, Date *); extern int PGTYPESdate_dayofweek(Date); extern void PGTYPESdate_today (Date *); -extern int PGTYPESdate_defmtdate(Date *, char *, char *); -extern int PGTYPESdate_fmtdate(Date, char *, char *); +extern int PGTYPESdate_defmt_asc(Date *, char *, char *); +extern int PGTYPESdate_fmt_asc(Date, char *, char *); #endif /* PGTYPES_DATETIME */ diff --git a/src/interfaces/ecpg/include/pgtypes_error.h b/src/interfaces/ecpg/include/pgtypes_error.h index 2965a01476..e5a102ca98 100644 --- a/src/interfaces/ecpg/include/pgtypes_error.h +++ b/src/interfaces/ecpg/include/pgtypes_error.h @@ -1,15 +1,16 @@ -#define PGTYPES_NUM_OVERFLOW 201 -#define PGTYPES_NUM_BAD_NUMERIC 202 -#define PGTYPES_NUM_DIVIDE_ZERO 203 +#define PGTYPES_NUM_OVERFLOW 301 +#define PGTYPES_NUM_BAD_NUMERIC 302 +#define PGTYPES_NUM_DIVIDE_ZERO 303 -#define PGTYPES_DATE_BAD_DATE 210 -#define PGTYPES_DATE_ERR_EARGS 211 -#define PGTYPES_DATE_ERR_ENOSHORTDATE 212 -#define PGTYPES_DATE_ERR_ENOTDMY 213 -#define PGTYPES_DATE_BAD_DAY 214 -#define PGTYPES_DATE_BAD_MONTH 215 +#define PGTYPES_DATE_BAD_DATE 310 +#define PGTYPES_DATE_ERR_EARGS 311 +#define PGTYPES_DATE_ERR_ENOSHORTDATE 312 +#define PGTYPES_DATE_ERR_ENOTDMY 313 +#define PGTYPES_DATE_BAD_DAY 314 +#define PGTYPES_DATE_BAD_MONTH 315 -#define PGTYPES_TS_BAD_TIMESTAMP 220 +#define PGTYPES_TS_BAD_TIMESTAMP 320 +#define PGTYPES_TS_ERR_EINFTIME 321 -#define PGTYPES_INTVL_BAD_INTERVAL 230 +#define PGTYPES_INTVL_BAD_INTERVAL 330 diff --git a/src/interfaces/ecpg/include/pgtypes_interval.h b/src/interfaces/ecpg/include/pgtypes_interval.h index b3c71b0597..884df67216 100644 --- a/src/interfaces/ecpg/include/pgtypes_interval.h +++ b/src/interfaces/ecpg/include/pgtypes_interval.h @@ -1,8 +1,6 @@ #ifndef PGTYPES_INTERVAL #define PGTYPES_INTERVAL -#include - typedef struct { #ifdef HAVE_INT64_TIMESTAMP @@ -13,8 +11,8 @@ typedef struct long month; /* months and years, after time for alignment */ } Interval; -extern Interval *PGTYPESinterval_atoi(char *, char **); -extern char *PGTYPESinterval_itoa(Interval *); +extern Interval *PGTYPESinterval_from_asc(char *, char **); +extern char *PGTYPESinterval_to_asc(Interval *); extern int PGTYPESinterval_copy(Interval *, Interval *); #endif /* PGTYPES_INTERVAL */ diff --git a/src/interfaces/ecpg/include/pgtypes_numeric.h b/src/interfaces/ecpg/include/pgtypes_numeric.h index 977233afca..685326e4a8 100644 --- a/src/interfaces/ecpg/include/pgtypes_numeric.h +++ b/src/interfaces/ecpg/include/pgtypes_numeric.h @@ -22,19 +22,19 @@ typedef struct Numeric *PGTYPESnew(void); void PGTYPESnumeric_free(Numeric *); -Numeric *PGTYPESnumeric_aton(char *, char **); -char *PGTYPESnumeric_ntoa(Numeric *, int); +Numeric *PGTYPESnumeric_from_asc(char *, char **); +char *PGTYPESnumeric_to_asc(Numeric *, int); int PGTYPESnumeric_add(Numeric *, Numeric *, Numeric *); int PGTYPESnumeric_sub(Numeric *, Numeric *, Numeric *); int PGTYPESnumeric_mul(Numeric *, Numeric *, Numeric *); int PGTYPESnumeric_div(Numeric *, Numeric *, Numeric *); int PGTYPESnumeric_cmp(Numeric *, Numeric *); -int PGTYPESnumeric_iton(signed int, Numeric *); -int PGTYPESnumeric_lton(signed long int, Numeric *); +int PGTYPESnumeric_from_int(signed int, Numeric *); +int PGTYPESnumeric_from_long(signed long int, Numeric *); int PGTYPESnumeric_copy(Numeric *, Numeric *); -int PGTYPESnumeric_dton(double, Numeric *); -int PGTYPESnumeric_ntod(Numeric *, double *); -int PGTYPESnumeric_ntoi(Numeric *, int *); -int PGTYPESnumeric_ntol(Numeric *, long *); +int PGTYPESnumeric_from_double(double, Numeric *); +int PGTYPESnumeric_to_double(Numeric *, double *); +int PGTYPESnumeric_to_int(Numeric *, int *); +int PGTYPESnumeric_to_long(Numeric *, long *); #endif /* PGTYPES_NUMERIC */ diff --git a/src/interfaces/ecpg/include/pgtypes_timestamp.h b/src/interfaces/ecpg/include/pgtypes_timestamp.h index 48a54b1381..189d09a2d2 100644 --- a/src/interfaces/ecpg/include/pgtypes_timestamp.h +++ b/src/interfaces/ecpg/include/pgtypes_timestamp.h @@ -1,6 +1,8 @@ #ifndef PGTYPES_TIMESTAMP #define PGTYPES_TIMESTAMP +#include + #ifdef HAVE_INT64_TIMESTAMP typedef int64 Timestamp; typedef int64 TimestampTz; @@ -10,7 +12,11 @@ typedef double Timestamp; typedef double TimestampTz; #endif -extern Timestamp PGTYPEStimestamp_atot(char *, char **); -extern char *PGTYPEStimestamp_ttoa(Timestamp); +extern Timestamp PGTYPEStimestamp_from_asc(char *, char **); +extern char *PGTYPEStimestamp_to_asc(Timestamp); +extern int PGTYPEStimestamp_sub (Timestamp *, Timestamp *, Interval *); +extern int PGTYPEStimestamp_fmt_asc (Timestamp *, char *, int, char *); +extern void PGTYPEStimestamp_current (Timestamp *); + #endif /* PGTYPES_TIMESTAMP */ diff --git a/src/interfaces/ecpg/pgtypeslib/common.c b/src/interfaces/ecpg/pgtypeslib/common.c index 719b18b029..0be74b21df 100644 --- a/src/interfaces/ecpg/pgtypeslib/common.c +++ b/src/interfaces/ecpg/pgtypeslib/common.c @@ -1,8 +1,10 @@ -#include +#include #include +#include +#include #include "extern.h" - + char * pgtypes_alloc(long size) { @@ -28,3 +30,109 @@ pgtypes_strdup(char *str) return (new); } +int +pgtypes_fmt_replace(union un_fmt_replace replace_val, int replace_type, char** output, int *pstr_len) { + /* general purpose variable, set to 0 in order to fix compiler + * warning */ + int i = 0; + switch(replace_type) { + case PGTYPES_REPLACE_NOTHING: + break; + case PGTYPES_REPLACE_STRING_CONSTANT: + case PGTYPES_REPLACE_STRING_MALLOCED: + i = strlen(replace_val.replace_str); + if (i + 1 <= *pstr_len) { + /* copy over i + 1 bytes, that includes the + * tailing terminator */ + strncpy(*output, replace_val.replace_str, i + 1); + *pstr_len -= i; + *output += i; + if (replace_type == PGTYPES_REPLACE_STRING_MALLOCED) { + free(replace_val.replace_str); + } + return 0; + } else { + return -1; + } + break; + case PGTYPES_REPLACE_CHAR: + if (*pstr_len >= 2) { + (*output)[0] = replace_val.replace_char; + (*output)[1] = '\0'; + (*pstr_len)--; + (*output)++; + return 0; + } else { + return -1; + } + break; + case PGTYPES_REPLACE_DOUBLE_NF: + case PGTYPES_REPLACE_INT64: + case PGTYPES_REPLACE_UINT: + case PGTYPES_REPLACE_UINT_2_LZ: + case PGTYPES_REPLACE_UINT_2_LS: + case PGTYPES_REPLACE_UINT_3_LZ: + case PGTYPES_REPLACE_UINT_4_LZ: + { + char* t = pgtypes_alloc(PGTYPES_FMT_NUM_MAX_DIGITS); + if (!t) { + return ENOMEM; + } + switch (replace_type) { + case PGTYPES_REPLACE_DOUBLE_NF: + i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS, + "%0.0g", replace_val.replace_double); + break; +#ifdef HAVE_INT6 + case PGTYPES_REPLACE_INT64: + i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS, + INT64_FORMAT, replace_val.replace_int64); + break; +#endif + case PGTYPES_REPLACE_UINT: + i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS, + "%u", replace_val.replace_uint); + break; + case PGTYPES_REPLACE_UINT_2_LZ: + i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS, + "%02u", replace_val.replace_uint); + break; + case PGTYPES_REPLACE_UINT_2_LS: + i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS, + "%2u", replace_val.replace_uint); + break; + case PGTYPES_REPLACE_UINT_3_LZ: + i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS, + "%03u", replace_val.replace_uint); + break; + case PGTYPES_REPLACE_UINT_4_LZ: + i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS, + "%04u", replace_val.replace_uint); + break; + } + + if (i < 0) { + free(t); + return -1; + } + i = strlen(t); + *pstr_len -= i; + /* if *pstr_len == 0, we don't have enough + * space for the terminator and the + * conversion fails */ + if (*pstr_len <= 0) { + free(t); + return -1; + } + strcpy(*output, t); + *output += i; + free(t); + } + break; + default: + break; + } + return 0; +} + + diff --git a/src/interfaces/ecpg/pgtypeslib/datetime.c b/src/interfaces/ecpg/pgtypeslib/datetime.c index fbc55462bf..1a9bed268c 100644 --- a/src/interfaces/ecpg/pgtypeslib/datetime.c +++ b/src/interfaces/ecpg/pgtypeslib/datetime.c @@ -4,18 +4,15 @@ #include #include #include +#include #include "dt.h" #include "extern.h" #include "pgtypes_error.h" #include "pgtypes_date.h" -/* XXX: currently not used. - * pgsql: timestamp_date() - * Convert timestamp to date data type. - */ Date -PGTYPESdate_ttod(Timestamp dt) +PGTYPESdate_from_timestamp(Timestamp dt) { Date dDate; @@ -36,7 +33,7 @@ PGTYPESdate_ttod(Timestamp dt) } Date -PGTYPESdate_atod(char *str, char **endptr) +PGTYPESdate_from_asc(char *str, char **endptr) { Date dDate; @@ -87,7 +84,7 @@ PGTYPESdate_atod(char *str, char **endptr) } char * -PGTYPESdate_dtoa(Date dDate) +PGTYPESdate_to_asc(Date dDate) { struct tm tt, *tm = &tt; char buf[MAXDATELEN + 1]; @@ -154,16 +151,8 @@ PGTYPESdate_today (Date *d) #define PGTYPES_FMTDATE_YEAR_DIGITS_SHORT 5 #define PGTYPES_FMTDATE_YEAR_DIGITS_LONG 6 -static char* pgtypes_date_weekdays_short[] = {"Sun", "Mon", "Tue", "Wed", - "Thu", "Fri", "Sat", NULL}; - -static char* pgtypes_date_months[] = {"January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December", NULL}; -static char* pgtypes_date_months_short[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL}; - int -PGTYPESdate_fmtdate(Date dDate, char* fmtstring, char* outbuf) { +PGTYPESdate_fmt_asc(Date dDate, char* fmtstring, char* outbuf) { static struct { char* format; int component; @@ -180,15 +169,6 @@ PGTYPESdate_fmtdate(Date dDate, char* fmtstring, char* outbuf) { { NULL, 0 } }; - -/* These are the constants that decide which printf() format we'll use in - * order to get a string representation of the value */ -#define PGTYPES_DATE_REPLACE_STRING_MALLOCED 1 -#define PGTYPES_DATE_REPLACE_STRING_CONSTANT 2 -#define PGTYPES_DATE_REPLACE_UINT 3 -#define PGTYPES_DATE_REPLACE_UINT_2_LZ 4 -#define PGTYPES_DATE_REPLACE_UINT_4_LZ 5 - union { char* replace_str; unsigned int replace_uint; @@ -213,44 +193,44 @@ PGTYPESdate_fmtdate(Date dDate, char* fmtstring, char* outbuf) { switch(mapping[i].component) { case PGTYPES_FMTDATE_DOW_LITERAL_SHORT: replace_val.replace_str = pgtypes_date_weekdays_short[dow]; - replace_type = PGTYPES_DATE_REPLACE_STRING_CONSTANT; + replace_type = PGTYPES_REPLACE_STRING_CONSTANT; break; case PGTYPES_FMTDATE_DAY_DIGITS_LZ: replace_val.replace_uint = tm.tm_mday; - replace_type = PGTYPES_DATE_REPLACE_UINT_2_LZ; + replace_type = PGTYPES_REPLACE_UINT_2_LZ; break; case PGTYPES_FMTDATE_MONTH_LITERAL_SHORT: - replace_val.replace_str = pgtypes_date_months_short[tm.tm_mon-1]; - replace_type = PGTYPES_DATE_REPLACE_STRING_CONSTANT; + replace_val.replace_str = months[tm.tm_mon-1]; + replace_type = PGTYPES_REPLACE_STRING_CONSTANT; break; case PGTYPES_FMTDATE_MONTH_DIGITS_LZ: replace_val.replace_uint = tm.tm_mon; - replace_type = PGTYPES_DATE_REPLACE_UINT_2_LZ; + replace_type = PGTYPES_REPLACE_UINT_2_LZ; break; case PGTYPES_FMTDATE_YEAR_DIGITS_LONG: replace_val.replace_uint = tm.tm_year; - replace_type = PGTYPES_DATE_REPLACE_UINT_4_LZ; + replace_type = PGTYPES_REPLACE_UINT_4_LZ; break; case PGTYPES_FMTDATE_YEAR_DIGITS_SHORT: replace_val.replace_uint = tm.tm_year % 1000; - replace_type = PGTYPES_DATE_REPLACE_UINT_2_LZ; + replace_type = PGTYPES_REPLACE_UINT_2_LZ; break; default: /* should not happen, set something * anyway */ replace_val.replace_str = " "; - replace_type = PGTYPES_DATE_REPLACE_STRING_CONSTANT; + replace_type = PGTYPES_REPLACE_STRING_CONSTANT; } switch(replace_type) { - case PGTYPES_DATE_REPLACE_STRING_MALLOCED: - case PGTYPES_DATE_REPLACE_STRING_CONSTANT: + case PGTYPES_REPLACE_STRING_MALLOCED: + case PGTYPES_REPLACE_STRING_CONSTANT: strncpy(start_pattern, replace_val.replace_str, strlen(replace_val.replace_str)); - if (replace_type == PGTYPES_DATE_REPLACE_STRING_MALLOCED) { + if (replace_type == PGTYPES_REPLACE_STRING_MALLOCED) { free(replace_val.replace_str); } break; - case PGTYPES_DATE_REPLACE_UINT: + case PGTYPES_REPLACE_UINT: { char* t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS); if (!t) { @@ -262,7 +242,7 @@ PGTYPESdate_fmtdate(Date dDate, char* fmtstring, char* outbuf) { free(t); } break; - case PGTYPES_DATE_REPLACE_UINT_2_LZ: + case PGTYPES_REPLACE_UINT_2_LZ: { char* t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS); if (!t) { @@ -274,7 +254,7 @@ PGTYPESdate_fmtdate(Date dDate, char* fmtstring, char* outbuf) { free(t); } break; - case PGTYPES_DATE_REPLACE_UINT_4_LZ: + case PGTYPES_REPLACE_UINT_4_LZ: { char* t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS); if (!t) { @@ -289,7 +269,7 @@ PGTYPESdate_fmtdate(Date dDate, char* fmtstring, char* outbuf) { default: /* doesn't happen (we set * replace_type to - * PGTYPES_DATE_REPLACE_STRING_CONSTANT + * PGTYPES_REPLACE_STRING_CONSTANT * in case of an error above) */ break; } @@ -300,7 +280,7 @@ PGTYPESdate_fmtdate(Date dDate, char* fmtstring, char* outbuf) { /* - * PGTYPESdate_rdefmtdate + * PGTYPESdate_defmt_asc * * function works as follows: * - first we analyze the paramters @@ -314,7 +294,7 @@ PGTYPESdate_fmtdate(Date dDate, char* fmtstring, char* outbuf) { #define PGTYPES_DATE_MONTH_MAXLENGTH 20 /* probably even less :-) */ int -PGTYPESdate_defmtdate(Date *d, char *fmt, char *str) +PGTYPESdate_defmt_asc(Date *d, char *fmt, char *str) { /* token[2] = { 4,6 } means that token 2 starts at * position 4 and ends at (including) position 6 */ @@ -537,7 +517,7 @@ PGTYPESdate_defmtdate(Date *d, char *fmt, char *str) * variable i */ if (list == pgtypes_date_months) { if (list[i+1] == NULL) { - list = pgtypes_date_months_short; + list = months; i = -1; } } @@ -613,6 +593,8 @@ PGTYPESdate_defmtdate(Date *d, char *fmt, char *str) return -1; } + /* XXX: DBCENTURY ? */ + *d = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - date2j(2000, 1, 1); return 0; diff --git a/src/interfaces/ecpg/pgtypeslib/dt.h b/src/interfaces/ecpg/pgtypeslib/dt.h index e2019af32e..8dce06d1bd 100644 --- a/src/interfaces/ecpg/pgtypeslib/dt.h +++ b/src/interfaces/ecpg/pgtypeslib/dt.h @@ -272,33 +272,38 @@ extern int day_tab[2][13]; #define TIMESTAMP_IS_NOEND(j) ((j) == DT_NOEND) #define TIMESTAMP_NOT_FINITE(j) (TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j)) -extern int DecodeTimeOnly(char **field, int *ftype, +int DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct tm * tm, fsec_t *fsec, int *tzp); -extern int DecodeInterval(char **field, int *ftype, +int DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct tm * tm, fsec_t *fsec); -extern int EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str); -extern int EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str, bool); -extern int EncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str); +int EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str); +int EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str, bool); +int EncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str); -extern int DecodeUnits(int field, char *lowtoken, int *val); -extern bool ClearDateCache(bool, bool, bool); +int DecodeUnits(int field, char *lowtoken, int *val); +bool ClearDateCache(bool, bool, bool); -extern int j2day(int jd); +int j2day(int jd); -extern bool CheckDateTokenTables(void); +bool CheckDateTokenTables(void); -extern int EncodeDateOnly(struct tm *, int, char *, bool); -extern void GetEpochTime(struct tm *); -extern int ParseDateTime(char *, char *, char **, int *, int, int *, char **); -extern int DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, int *, bool); -extern void j2date(int, int *, int *, int *); -extern void GetCurrentDateTime(struct tm*); -extern int date2j(int, int, int); -extern double rint(double x); +int EncodeDateOnly(struct tm *, int, char *, bool); +void GetEpochTime(struct tm *); +int ParseDateTime(char *, char *, char **, int *, int, int *, char **); +int DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, int *, bool); +void j2date(int, int *, int *, int *); +void GetCurrentDateTime(struct tm*); +int date2j(int, int, int); +double rint(double x); + +extern char* pgtypes_date_weekdays_short[]; +extern char* pgtypes_date_months[]; +extern char* months[]; +extern char* days[]; #endif /* DT_H */ diff --git a/src/interfaces/ecpg/pgtypeslib/dt_common.c b/src/interfaces/ecpg/pgtypeslib/dt_common.c index 2da16b14d4..739ce8b5b1 100644 --- a/src/interfaces/ecpg/pgtypeslib/dt_common.c +++ b/src/interfaces/ecpg/pgtypeslib/dt_common.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "dt.h" #include "extern.h" @@ -505,6 +506,10 @@ char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", NULL}; +char* pgtypes_date_weekdays_short[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL}; + +char* pgtypes_date_months[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", NULL}; + #ifndef HAVE_RINT /* @(#)s_rint.c 5.1 93/09/24 */ diff --git a/src/interfaces/ecpg/pgtypeslib/extern.h b/src/interfaces/ecpg/pgtypeslib/extern.h index b843107f65..222128767b 100644 --- a/src/interfaces/ecpg/pgtypeslib/extern.h +++ b/src/interfaces/ecpg/pgtypeslib/extern.h @@ -1,4 +1,40 @@ -#include - -extern char *pgtypes_alloc(long); -extern char *pgtypes_strdup(char *); +#ifndef __PGTYPES_COMMON_H__ +#define __PGTYPES_COMMON_H__ + +#include "pgtypes_error.h" + +/* These are the constants that decide which printf() format we'll use in + * order to get a string representation of the value */ +#define PGTYPES_REPLACE_NOTHING 0 +#define PGTYPES_REPLACE_STRING_MALLOCED 1 +#define PGTYPES_REPLACE_STRING_CONSTANT 2 +#define PGTYPES_REPLACE_CHAR 3 +#define PGTYPES_REPLACE_DOUBLE_NF 4 /* no fractional part */ +#define PGTYPES_REPLACE_INT64 5 +#define PGTYPES_REPLACE_UINT 6 +#define PGTYPES_REPLACE_UINT_2_LZ 7 /* 2 digits, pad with leading zero */ +#define PGTYPES_REPLACE_UINT_2_LS 8 /* 2 digits, pad with leading space */ +#define PGTYPES_REPLACE_UINT_3_LZ 9 +#define PGTYPES_REPLACE_UINT_4_LZ 10 + +#define PGTYPES_FMT_NUM_MAX_DIGITS 40 + +union un_fmt_replace { + char* replace_str; + unsigned int replace_uint; + char replace_char; + unsigned long int replace_luint; + double replace_double; +#ifdef HAVE_INT64_TIMESTAMP + int64 replace_int64; +#endif +}; + +int pgtypes_fmt_replace(union un_fmt_replace, int, char**, int*); + +char *pgtypes_alloc(long); +char *pgtypes_strdup(char *); + + +#endif /* __PGTYPES_COMMON_H__ */ + diff --git a/src/interfaces/ecpg/pgtypeslib/interval.c b/src/interfaces/ecpg/pgtypeslib/interval.c index 3d20bd3db3..62a3141a4e 100644 --- a/src/interfaces/ecpg/pgtypeslib/interval.c +++ b/src/interfaces/ecpg/pgtypeslib/interval.c @@ -745,7 +745,7 @@ tm2interval(struct tm * tm, fsec_t fsec, Interval *span) } /* tm2interval() */ Interval * -PGTYPESinterval_atoi(char *str, char **endptr) +PGTYPESinterval_from_asc(char *str, char **endptr) { Interval *result = NULL; fsec_t fsec; @@ -800,7 +800,7 @@ PGTYPESinterval_atoi(char *str, char **endptr) } char * -PGTYPESinterval_itoa(Interval *span) +PGTYPESinterval_to_asc(Interval *span) { struct tm tt, *tm = &tt; diff --git a/src/interfaces/ecpg/pgtypeslib/numeric.c b/src/interfaces/ecpg/pgtypeslib/numeric.c index fc09a6e4ce..8988df06df 100644 --- a/src/interfaces/ecpg/pgtypeslib/numeric.c +++ b/src/interfaces/ecpg/pgtypeslib/numeric.c @@ -362,14 +362,8 @@ get_str_from_var(Numeric *var, int dscale) return str; } -/* ---------- - * PGTYPESnumeric_aton() - - * - * Input function for numeric data type - * ---------- - */ Numeric * -PGTYPESnumeric_aton(char *str, char **endptr) +PGTYPESnumeric_from_asc(char *str, char **endptr) { Numeric *value = (Numeric *)pgtypes_alloc(sizeof(Numeric)); int ret; @@ -394,14 +388,8 @@ PGTYPESnumeric_aton(char *str, char **endptr) return(value); } -/* ---------- - * numeric_out() - - * - * Output function for numeric data type - * ---------- - */ char * -PGTYPESnumeric_ntoa(Numeric *num, int dscale) +PGTYPESnumeric_to_asc(Numeric *num, int dscale) { if (dscale <= 0) dscale = num->dscale; @@ -1328,14 +1316,14 @@ PGTYPESnumeric_cmp(Numeric *var1, Numeric *var2) { } int -PGTYPESnumeric_iton(signed int int_val, Numeric *var) { +PGTYPESnumeric_from_int(signed int int_val, Numeric *var) { /* implicit conversion */ signed long int long_int = int_val; - return PGTYPESnumeric_lton(long_int, var); + return PGTYPESnumeric_from_long(long_int, var); } int -PGTYPESnumeric_lton(signed long int long_val, Numeric *var) { +PGTYPESnumeric_from_long(signed long int long_val, Numeric *var) { /* calculate the size of the long int number */ /* a number n needs log_10 n digits */ /* however we multiply by 10 each time and compare instead of @@ -1408,7 +1396,7 @@ PGTYPESnumeric_copy(Numeric *src, Numeric *dst) { } int -PGTYPESnumeric_dton(double d, Numeric *dst) +PGTYPESnumeric_from_double(double d, Numeric *dst) { char buffer[100]; Numeric *tmp; @@ -1416,7 +1404,7 @@ PGTYPESnumeric_dton(double d, Numeric *dst) if (sprintf(buffer, "%f", d) == 0) return -1; - if ((tmp = PGTYPESnumeric_aton(buffer, NULL)) == NULL) + if ((tmp = PGTYPESnumeric_from_asc(buffer, NULL)) == NULL) return -1; if (PGTYPESnumeric_copy(tmp, dst) != 0) return -1; @@ -1449,7 +1437,7 @@ numericvar_to_double_no_overflow(Numeric *var, double *dp) } int -PGTYPESnumeric_ntod(Numeric* nv, double* dp) { +PGTYPESnumeric_to_double(Numeric* nv, double* dp) { double tmp; int i; @@ -1460,11 +1448,11 @@ PGTYPESnumeric_ntod(Numeric* nv, double* dp) { } int -PGTYPESnumeric_ntoi(Numeric* nv, int* ip) { +PGTYPESnumeric_to_int(Numeric* nv, int* ip) { long l; int i; - if ((i = PGTYPESnumeric_ntol(nv, &l)) != 0) + if ((i = PGTYPESnumeric_to_long(nv, &l)) != 0) return i; if (l < -INT_MAX || l > INT_MAX) { @@ -1477,7 +1465,7 @@ PGTYPESnumeric_ntoi(Numeric* nv, int* ip) { } int -PGTYPESnumeric_ntol(Numeric* nv, long* lp) { +PGTYPESnumeric_to_long(Numeric* nv, long* lp) { int i; long l = 0; diff --git a/src/interfaces/ecpg/pgtypeslib/timestamp.c b/src/interfaces/ecpg/pgtypeslib/timestamp.c index 181e63dc2a..9cea9a3db0 100644 --- a/src/interfaces/ecpg/pgtypeslib/timestamp.c +++ b/src/interfaces/ecpg/pgtypeslib/timestamp.c @@ -11,36 +11,36 @@ #include "dt.h" #include "extern.h" -#include "pgtypes_error.h" #include "pgtypes_timestamp.h" +#include "pgtypes_date.h" #include "datetime.h" #ifdef HAVE_INT64_TIMESTAMP static int64 time2t(const int hour, const int min, const int sec, const fsec_t fsec) { - return ((((((hour * 60) + min) * 60) + sec) * INT64CONST(1000000)) + fsec); -} /* time2t() */ + return ((((((hour * 60) + min) * 60) + sec) * INT64CONST(1000000)) + fsec); +} /* time2t() */ #else static double time2t(const int hour, const int min, const int sec, const fsec_t fsec) { - return ((((hour * 60) + min) * 60) + sec + fsec); -} /* time2t() */ + return ((((hour * 60) + min) * 60) + sec + fsec); +} /* time2t() */ #endif static Timestamp dt2local(Timestamp dt, int tz) { #ifdef HAVE_INT64_TIMESTAMP - dt -= (tz * INT64CONST(1000000)); + dt -= (tz * INT64CONST(1000000)); #else - dt -= tz; - dt = JROUND(dt); + dt -= tz; + dt = JROUND(dt); #endif - return dt; -} /* dt2local() */ + return dt; +} /* dt2local() */ /* tm2timestamp() * Convert a tm structure to a timestamp data type. @@ -82,44 +82,44 @@ tm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, Timestamp *result) static Timestamp SetEpochTimestamp(void) { - Timestamp dt; - struct tm tt, *tm = &tt; + Timestamp dt; + struct tm tt, *tm = &tt; GetEpochTime(tm); tm2timestamp(tm, 0, NULL, &dt); - return dt; -} /* SetEpochTimestamp() */ + return dt; +} /* SetEpochTimestamp() */ static void dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec) { #ifdef HAVE_INT64_TIMESTAMP - int64 time; + int64 time; #else - double time; + double time; #endif - time = jd; + time = jd; #ifdef HAVE_INT64_TIMESTAMP - *hour = (time / INT64CONST(3600000000)); - time -= ((*hour) * INT64CONST(3600000000)); - *min = (time / INT64CONST(60000000)); - time -= ((*min) * INT64CONST(60000000)); - *sec = (time / INT64CONST(1000000)); - *fsec = (time - (*sec * INT64CONST(1000000))); - *sec = (time / INT64CONST(1000000)); - *fsec = (time - (*sec * INT64CONST(1000000))); + *hour = (time / INT64CONST(3600000000)); + time -= ((*hour) * INT64CONST(3600000000)); + *min = (time / INT64CONST(60000000)); + time -= ((*min) * INT64CONST(60000000)); + *sec = (time / INT64CONST(1000000)); + *fsec = (time - (*sec * INT64CONST(1000000))); + *sec = (time / INT64CONST(1000000)); + *fsec = (time - (*sec * INT64CONST(1000000))); #else - *hour = (time / 3600); - time -= ((*hour) * 3600); - *min = (time / 60); - time -= ((*min) * 60); - *sec = time; - *fsec = JROUND(time - *sec); + *hour = (time / 3600); + time -= ((*hour) * 3600); + *min = (time / 60); + time -= ((*min) * 60); + *sec = time; + *fsec = JROUND(time - *sec); #endif - return; -} /* dt2time() */ + return; +} /* dt2time() */ /* timestamp2tm() * Convert timestamp data type to POSIX time structure. @@ -136,8 +136,8 @@ static int timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, fsec_t *fsec, char **tzn) { #ifdef HAVE_INT64_TIMESTAMP - int date, - date0; + int date, + date0; int64 time; #else @@ -254,18 +254,18 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, fsec_t *fsec, char **tzn) static int EncodeSpecialTimestamp(Timestamp dt, char *str) { - if (TIMESTAMP_IS_NOBEGIN(dt)) - strcpy(str, EARLY); - else if (TIMESTAMP_IS_NOEND(dt)) - strcpy(str, LATE); - else - return FALSE; + if (TIMESTAMP_IS_NOBEGIN(dt)) + strcpy(str, EARLY); + else if (TIMESTAMP_IS_NOEND(dt)) + strcpy(str, LATE); + else + return FALSE; - return TRUE; -} /* EncodeSpecialTimestamp() */ + return TRUE; +} /* EncodeSpecialTimestamp() */ Timestamp -PGTYPEStimestamp_atot(char *str, char **endptr) +PGTYPEStimestamp_from_asc(char *str, char **endptr) { Timestamp result; #ifdef HAVE_INT64_TIMESTAMP @@ -275,14 +275,14 @@ PGTYPEStimestamp_atot(char *str, char **endptr) #endif fsec_t fsec; struct tm tt, *tm = &tt; - int tz; - int dtype; - int nf; - char *field[MAXDATEFIELDS]; - int ftype[MAXDATEFIELDS]; + int tz; + int dtype; + int nf; + char *field[MAXDATEFIELDS]; + int ftype[MAXDATEFIELDS]; char lowstr[MAXDATELEN + MAXDATEFIELDS]; - char *realptr; - char **ptr = (endptr != NULL) ? endptr : &realptr; + char *realptr; + char **ptr = (endptr != NULL) ? endptr : &realptr; errno = 0; if (strlen(str) >= sizeof(lowstr)) @@ -304,7 +304,7 @@ PGTYPEStimestamp_atot(char *str, char **endptr) if (tm2timestamp(tm, fsec, NULL, &result) != 0) { errno = PGTYPES_TS_BAD_TIMESTAMP; - return (noresult);; + return (noresult); } break; @@ -335,22 +335,406 @@ PGTYPEStimestamp_atot(char *str, char **endptr) } char * -PGTYPEStimestamp_ttoa(Timestamp tstamp) +PGTYPEStimestamp_to_asc(Timestamp tstamp) { - struct tm tt, *tm = &tt; - char buf[MAXDATELEN + 1]; - char *tzn = NULL; - fsec_t fsec; + struct tm tt, *tm = &tt; + char buf[MAXDATELEN + 1]; + char *tzn = NULL; + fsec_t fsec; int DateStyle = 0; if (TIMESTAMP_NOT_FINITE(tstamp)) - EncodeSpecialTimestamp(tstamp, buf); - else if (timestamp2tm(tstamp, NULL, tm, &fsec, NULL) == 0) - EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf, 0); - else + EncodeSpecialTimestamp(tstamp, buf); + else if (timestamp2tm(tstamp, NULL, tm, &fsec, NULL) == 0) + EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf, 0); + else { errno = PGTYPES_TS_BAD_TIMESTAMP; return NULL; } - return pgtypes_strdup(buf); + return pgtypes_strdup(buf); +} + +void +PGTYPEStimestamp_current (Timestamp *ts) +{ + struct tm tm; + + GetCurrentDateTime(&tm); + tm2timestamp(&tm, 0, NULL, ts); + return; +} + +static int +dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm, + char* output, int *pstr_len, char *fmtstr) +{ + union un_fmt_replace replace_val; + int replace_type; + int i; + char* p = fmtstr; + char* q = output; + + while (*p) { + if (*p == '%') { + p++; + /* fix compiler warning */ + replace_type = PGTYPES_REPLACE_NOTHING; + switch (*p) { + case 'a': + replace_val.replace_str = pgtypes_date_weekdays_short[dow]; + replace_type = PGTYPES_REPLACE_STRING_CONSTANT; + break; + case 'A': + replace_val.replace_str = days[dow]; + replace_type = PGTYPES_REPLACE_STRING_CONSTANT; + break; + case 'b': + case 'h': + replace_val.replace_str = months[tm->tm_mon]; + replace_type = PGTYPES_REPLACE_STRING_CONSTANT; + break; + case 'B': + replace_val.replace_str = pgtypes_date_months[tm->tm_mon]; + replace_type = PGTYPES_REPLACE_STRING_CONSTANT; + break; + case 'c': + /* XXX */ + break; + case 'C': + replace_val.replace_uint = (tm->tm_year + 1900) / 100; + replace_type = PGTYPES_REPLACE_UINT_2_LZ; + break; + case 'd': + replace_val.replace_uint = tm->tm_mday; + replace_type = PGTYPES_REPLACE_UINT_2_LZ; + break; + case 'D': + /* ts, dDate, dow, tm is + * information about the timestamp + * + * q is the start of the current + * output buffer + * + * pstr_len is a pointer to the + * remaining size of output, i.e. + * the size of q */ + i = dttofmtasc_replace(ts, dDate, dow, tm, + q, pstr_len, + "%m/%d/%y"); + if (i) { return i; } + break; + case 'e': + replace_val.replace_uint = tm->tm_mday; + replace_type = PGTYPES_REPLACE_UINT_2_LS; + break; + case 'E': + { + char tmp[4] = "%Ex"; + p++; + if (*p == '\0') { + return -1; + } + tmp[2] = *p; + /* XXX: fall back to strftime */ + /* strftime's month is 0 + * based, ours is 1 based */ + tm->tm_mon -= 1; + i = strftime(q, *pstr_len, tmp, tm); + if (i == 0) { return -1; } + while (*q) { + q++; + (*pstr_len)--; + } + tm->tm_mon += 1; + replace_type = PGTYPES_REPLACE_NOTHING; + break; + } + case 'G': + /* XXX: fall back to strftime */ + tm->tm_mon -= 1; + i = strftime(q, *pstr_len, "%G", tm); + if (i == 0) { return -1; } + while (*q) { + q++; + (*pstr_len)--; + } + tm->tm_mon += 1; + replace_type = PGTYPES_REPLACE_NOTHING; + break; + case 'g': + /* XXX: fall back to strftime */ + tm->tm_mon -= 1; + i = strftime(q, *pstr_len, "%g", tm); + if (i == 0) { return -1; } + while (*q) { + q++; + (*pstr_len)--; + } + tm->tm_mon += 1; + replace_type = PGTYPES_REPLACE_NOTHING; + break; + case 'H': + replace_val.replace_uint = tm->tm_hour; + replace_type = PGTYPES_REPLACE_UINT_2_LZ; + break; + case 'I': + replace_val.replace_uint = tm->tm_hour % 12; + replace_type = PGTYPES_REPLACE_UINT_2_LZ; + break; + case 'j': + replace_val.replace_uint = tm->tm_yday; + replace_type = PGTYPES_REPLACE_UINT_3_LZ; + break; + case 'k': + replace_val.replace_uint = tm->tm_hour; + replace_type = PGTYPES_REPLACE_UINT_2_LS; + break; + case 'l': + replace_val.replace_uint = tm->tm_hour % 12; + replace_type = PGTYPES_REPLACE_UINT_2_LS; + break; + case 'm': + replace_val.replace_uint = tm->tm_mon; + replace_type = PGTYPES_REPLACE_UINT_2_LZ; + break; + case 'M': + replace_val.replace_uint = tm->tm_min; + replace_type = PGTYPES_REPLACE_UINT_2_LZ; + break; + case 'n': + replace_val.replace_char = '\n'; + replace_type = PGTYPES_REPLACE_CHAR; + break; + case 'p': + if (tm->tm_hour < 12) { + replace_val.replace_str = "AM"; + } else { + replace_val.replace_str = "PM"; + } + replace_type = PGTYPES_REPLACE_STRING_CONSTANT; + break; + case 'P': + if (tm->tm_hour < 12) { + replace_val.replace_str = "am"; + } else { + replace_val.replace_str = "pm"; + } + replace_type = PGTYPES_REPLACE_STRING_CONSTANT; + break; + case 'r': + i = dttofmtasc_replace(ts, dDate, dow, tm, + q, pstr_len, + "%I:%M:%S %p"); + if (i) { return i; } + break; + case 'R': + i = dttofmtasc_replace(ts, dDate, dow, tm, + q, pstr_len, + "%H:%M"); + if (i) { return i; } + break; + case 's': +#ifdef HAVE_INT64_TIMESTAMP + replace_val.replace_int64 = ((*ts - SetEpochTimestamp()) / 1000000e0); + replace_type = PGTYPES_REPLACE_INT64; +#else + replace_val.replace_double = *ts - SetEpochTimestamp(); + replace_type = PGTYPES_REPLACE_DOUBLE_NF; +#endif + break; + case 'S': + replace_val.replace_uint = tm->tm_sec; + replace_type = PGTYPES_REPLACE_UINT; + break; + case 't': + replace_val.replace_char = '\t'; + replace_type = PGTYPES_REPLACE_CHAR; + break; + case 'T': + i = dttofmtasc_replace(ts, dDate, dow, tm, + q, pstr_len, + "%H:%M:%S"); + if (i) { return i; } + break; + case 'u': + if (dow == 0) { dow = 7; } + replace_val.replace_uint = dow; + replace_type = PGTYPES_REPLACE_UINT; + break; + case 'U': + /* XXX: fall back to strftime */ + tm->tm_mon -= 1; + i = strftime(q, *pstr_len, "%U", tm); + if (i == 0) { return -1; } + while (*q) { + q++; + (*pstr_len)--; + } + tm->tm_mon += 1; + replace_type = PGTYPES_REPLACE_NOTHING; + break; + case 'V': + /* XXX: fall back to strftime */ + i = strftime(q, *pstr_len, "%V", tm); + if (i == 0) { return -1; } + while (*q) { + q++; + (*pstr_len)--; + } + replace_type = PGTYPES_REPLACE_NOTHING; + break; + case 'w': + replace_val.replace_uint = dow; + replace_type = PGTYPES_REPLACE_UINT; + break; + case 'W': + /* XXX: fall back to strftime */ + tm->tm_mon -= 1; + i = strftime(q, *pstr_len, "%U", tm); + if (i == 0) { return -1; } + while (*q) { + q++; + (*pstr_len)--; + } + tm->tm_mon += 1; + replace_type = PGTYPES_REPLACE_NOTHING; + break; + case 'x': + /* XXX: fall back to strftime */ + tm->tm_mon -= 1; + i = strftime(q, *pstr_len, "%x", tm); + if (i == 0) { return -1; } + while (*q) { + q++; + (*pstr_len)--; + } + tm->tm_mon += 1; + replace_type = PGTYPES_REPLACE_NOTHING; + break; + case 'X': + /* XXX: fall back to strftime */ + tm->tm_mon -= 1; + i = strftime(q, *pstr_len, "%X", tm); + if (i == 0) { return -1; } + while (*q) { + q++; + (*pstr_len)--; + } + tm->tm_mon += 1; + replace_type = PGTYPES_REPLACE_NOTHING; + break; + case 'y': + replace_val.replace_uint = tm->tm_year % 100; + replace_type = PGTYPES_REPLACE_UINT_2_LZ; + break; + case 'Y': + replace_val.replace_uint = tm->tm_year + 1900; + replace_type = PGTYPES_REPLACE_UINT; + break; + case 'z': + /* XXX: fall back to strftime */ + tm->tm_mon -= 1; + i = strftime(q, *pstr_len, "%z", tm); + if (i == 0) { return -1; } + while (*q) { + q++; + (*pstr_len)--; + } + tm->tm_mon += 1; + replace_type = PGTYPES_REPLACE_NOTHING; + break; + case 'Z': + /* XXX: fall back to strftime */ + tm->tm_mon -= 1; + i = strftime(q, *pstr_len, "%Z", tm); + if (i == 0) { return -1; } + while (*q) { + q++; + (*pstr_len)--; + } + tm->tm_mon += 1; + replace_type = PGTYPES_REPLACE_NOTHING; + break; + case '%': + replace_val.replace_char = '%'; + replace_type = PGTYPES_REPLACE_CHAR; + break; + case '\0': + /* fmtstr: blabla%' */ + /* this is not compliant to the + * specification */ + return -1; + default: + /* if we don't know the pattern, we + * just copy it */ + if (*pstr_len > 1) { + *q = '%'; + q++; (*pstr_len)--; + if (*pstr_len > 1) { + *q = *p; + q++; (*pstr_len)--; + } else { + *q = '\0'; + return -1; + } + *q = '\0'; + } else { + return -1; + } + break; + } + i = pgtypes_fmt_replace(replace_val, replace_type, &q, pstr_len); + if (i) { + return i; + } + } else { + if (*pstr_len > 1) { + *q = *p; + (*pstr_len)--; + q++; + *q = '\0'; + } else { + return -1; + } + } + p++; + } + return 0; +} + + +int +PGTYPEStimestamp_fmt_asc (Timestamp *ts, char *output, int str_len, char *fmtstr) +{ + struct tm tm; + fsec_t fsec; + Date dDate; + int dow; + + dDate = PGTYPESdate_from_timestamp(*ts); + dow = PGTYPESdate_dayofweek(dDate); + timestamp2tm(*ts, NULL, &tm, &fsec, NULL); + + return dttofmtasc_replace(ts, dDate, dow, &tm, output, &str_len, fmtstr); +} + +int +PGTYPEStimestamp_sub (Timestamp *ts1, Timestamp *ts2, Interval *iv) +{ + if (TIMESTAMP_NOT_FINITE(*ts1) || TIMESTAMP_NOT_FINITE(*ts2)) + { + return PGTYPES_TS_ERR_EINFTIME; + } + else +#ifdef HAVE_INT64_TIMESTAMP + iv->time = (ts1 - ts2); +#else + iv->time = JROUND(ts1 - ts2); +#endif + + iv->month = 0; + + return 0; } + -- GitLab