ret = -1201;
else
{
- np = PGTYPESnumeric_aton(str, NULL);
+ np = PGTYPESnumeric_from_asc(str, NULL);
if (!np)
{
switch (errno)
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
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;
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;
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;
int
rdatestr (Date d, char *str)
{
- char *tmp = PGTYPESdate_dtoa(d);
+ char *tmp = PGTYPESdate_to_asc(d);
if (!tmp)
return -1210;
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)
{
/* 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)
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)
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
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)
{
}
void
-rupshift(char *s)
+rupshift(char *str)
{
+ for (; *str != '\0'; str++)
+ if (islower(*str)) *str = toupper(*str);
return;
}
-/* $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"
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++;
}
}
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;
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++;
}
}
else
- ires = PGTYPESinterval_atoi("0 seconds", NULL);
+ ires = PGTYPESinterval_from_asc("0 seconds", NULL);
PGTYPESinterval_copy(ires, (Interval *)(var + offset * act_tuple));
break;
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++;
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++;
-/* $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.
{
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)))
}
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)))
{
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)))
}
else
{
- str = PGTYPESinterval_itoa((Interval *)(var->value));
+ str = PGTYPESinterval_to_asc((Interval *)(var->value));
slen = strlen (str);
if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno)))
{
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)))
}
else
{
- str = PGTYPESdate_dtoa(*(Date *)(var->value));
+ str = PGTYPESdate_to_asc(*(Date *)(var->value));
slen = strlen (str);
if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno)))
{
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)))
}
else
{
- str = PGTYPEStimestamp_ttoa(*(Timestamp *)(var->value));
+ str = PGTYPEStimestamp_to_asc(*(Timestamp *)(var->value));
slen = strlen (str);
if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno)))
{
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;
#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 *);
#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 */
-#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
#ifndef PGTYPES_INTERVAL
#define PGTYPES_INTERVAL
-#include <pgtypes_timestamp.h>
-
typedef struct
{
#ifdef HAVE_INT64_TIMESTAMP
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 */
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 */
#ifndef PGTYPES_TIMESTAMP
#define PGTYPES_TIMESTAMP
+#include <pgtypes_interval.h>
+
#ifdef HAVE_INT64_TIMESTAMP
typedef int64 Timestamp;
typedef int64 TimestampTz;
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 */
-#include <errno.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
#include "extern.h"
-
+
char *
pgtypes_alloc(long size)
{
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;
+}
+
+
#include <float.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#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;
}
Date
-PGTYPESdate_atod(char *str, char **endptr)
+PGTYPESdate_from_asc(char *str, char **endptr)
{
Date dDate;
}
char *
-PGTYPESdate_dtoa(Date dDate)
+PGTYPESdate_to_asc(Date dDate)
{
struct tm tt, *tm = &tt;
char buf[MAXDATELEN + 1];
#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;
{ 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;
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) {
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) {
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) {
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;
}
/*
- * PGTYPESdate_rdefmtdate
+ * PGTYPESdate_defmt_asc
*
* function works as follows:
* - first we analyze the paramters
#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 */
* variable i */
if (list == pgtypes_date_months) {
if (list[i+1] == NULL) {
- list = pgtypes_date_months_short;
+ list = months;
i = -1;
}
}
return -1;
}
+ /* XXX: DBCENTURY ? */
+
*d = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - date2j(2000, 1, 1);
return 0;
#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 */
#include <float.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include "dt.h"
#include "extern.h"
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 */
-#include <string.h>
-
-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__ */
+
} /* tm2interval() */
Interval *
-PGTYPESinterval_atoi(char *str, char **endptr)
+PGTYPESinterval_from_asc(char *str, char **endptr)
{
Interval *result = NULL;
fsec_t fsec;
}
char *
-PGTYPESinterval_itoa(Interval *span)
+PGTYPESinterval_to_asc(Interval *span)
{
struct tm tt,
*tm = &tt;
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;
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;
}
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
}
int
-PGTYPESnumeric_dton(double d, Numeric *dst)
+PGTYPESnumeric_from_double(double d, Numeric *dst)
{
char buffer[100];
Numeric *tmp;
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;
}
int
-PGTYPESnumeric_ntod(Numeric* nv, double* dp) {
+PGTYPESnumeric_to_double(Numeric* nv, double* dp) {
double tmp;
int i;
}
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) {
}
int
-PGTYPESnumeric_ntol(Numeric* nv, long* lp) {
+PGTYPESnumeric_to_long(Numeric* nv, long* lp) {
int i;
long l = 0;
#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.
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.
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
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
#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))
if (tm2timestamp(tm, fsec, NULL, &result) != 0)
{
errno = PGTYPES_TS_BAD_TIMESTAMP;
- return (noresult);;
+ return (noresult);
}
break;
}
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;
}
+