mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Moved Informix stuff to its own compat library. Interval datetype is now fully functional.
This commit is contained in:
@ -1376,7 +1376,17 @@ Thu Mar 27 15:23:58 CET 2003
|
|||||||
- Some more updates to pgtypeslib.
|
- Some more updates to pgtypeslib.
|
||||||
- Set optimization to -O1 until I find the reason why code is broken
|
- Set optimization to -O1 until I find the reason why code is broken
|
||||||
with -O2.
|
with -O2.
|
||||||
|
|
||||||
|
Sat Mar 29 22:03:16 CET 2003
|
||||||
|
|
||||||
|
- Moved Informix compatibility stuff its own library.
|
||||||
|
- Added interval datetypes.
|
||||||
|
|
||||||
|
Sun Mar 30 13:43:13 CEST 2003
|
||||||
|
|
||||||
|
- Interval datetype now fully functional.
|
||||||
- Set ecpg version to 2.12.0.
|
- Set ecpg version to 2.12.0.
|
||||||
- Set ecpg library to 3.4.2.
|
- Set ecpg library to 3.4.2.
|
||||||
- Set pgtypes library to 1.0.0
|
- Set pgtypes library to 1.0.0
|
||||||
|
- Set compat library to 1.0.0
|
||||||
|
|
||||||
|
@ -6,11 +6,13 @@ all install installdirs uninstall dep depend distprep:
|
|||||||
$(MAKE) -C include $@
|
$(MAKE) -C include $@
|
||||||
$(MAKE) -C ecpglib $@
|
$(MAKE) -C ecpglib $@
|
||||||
$(MAKE) -C pgtypeslib $@
|
$(MAKE) -C pgtypeslib $@
|
||||||
|
$(MAKE) -C compatlib $@
|
||||||
$(MAKE) -C preproc $@
|
$(MAKE) -C preproc $@
|
||||||
|
|
||||||
clean distclean maintainer-clean:
|
clean distclean maintainer-clean:
|
||||||
-$(MAKE) -C include $@
|
-$(MAKE) -C include $@
|
||||||
-$(MAKE) -C ecpglib $@
|
-$(MAKE) -C ecpglib $@
|
||||||
-$(MAKE) -C pgtypeslib $@
|
-$(MAKE) -C pgtypeslib $@
|
||||||
|
-$(MAKE) -C compatlib $@
|
||||||
-$(MAKE) -C preproc $@
|
-$(MAKE) -C preproc $@
|
||||||
-$(MAKE) -C test clean
|
-$(MAKE) -C test clean
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.6 2003/03/27 14:29:17 meskes Exp $ */
|
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.7 2003/03/30 11:48:18 meskes Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The aim is to get a simpler inteface to the database routines.
|
* 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++)
|
for (element = 0; element < var->arrsize; element++)
|
||||||
{
|
{
|
||||||
str = PGTYPESnumeric_ntoa((Numeric *)((var + var->offset * element)->value));
|
str = PGTYPESnumeric_ntoa((Numeric *)((var + var->offset * element)->value), 0);
|
||||||
slen = strlen (str);
|
slen = strlen (str);
|
||||||
|
|
||||||
if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + 5, stmt->lineno)))
|
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
|
else
|
||||||
{
|
{
|
||||||
str = PGTYPESnumeric_ntoa((Numeric *)(var->value));
|
str = PGTYPESnumeric_ntoa((Numeric *)(var->value), 0);
|
||||||
slen = strlen (str);
|
slen = strlen (str);
|
||||||
|
|
||||||
if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno)))
|
if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno)))
|
||||||
@ -1239,7 +1239,9 @@ ECPGexecute(struct statement * stmt)
|
|||||||
{
|
{
|
||||||
ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
|
ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
|
||||||
stmt->lineno, notify->relname, notify->be_pid);
|
stmt->lineno, notify->relname, notify->be_pid);
|
||||||
PQfreemem(notify);
|
/* PQfreemem(notify);*/
|
||||||
|
free(notify);
|
||||||
|
#warning Remove PQfreemem define
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
* This file contains stuff needed to be as compatible to Informix as possible.
|
* This file contains stuff needed to be as compatible to Informix as possible.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <decimal.h>
|
||||||
|
#include <datetime.h>
|
||||||
|
|
||||||
#define SQLNOTFOUND 100
|
#define SQLNOTFOUND 100
|
||||||
|
|
||||||
#ifndef Date
|
#ifndef Date
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
#ifndef PGTYPES_DATETIME
|
#ifndef PGTYPES_DATETIME
|
||||||
#define PGTYPES_DATETIME
|
#define PGTYPES_DATETIME
|
||||||
|
|
||||||
|
#include <pgtypes_timestamp.h>
|
||||||
|
|
||||||
#define Date long
|
#define Date long
|
||||||
|
|
||||||
extern Date PGTYPESdate_atod(char *, char **);
|
extern Date PGTYPESdate_atod(char *, char **);
|
||||||
extern char *PGTYPESdate_dtoa(Date);
|
extern char *PGTYPESdate_dtoa(Date);
|
||||||
extern int PGTYPESdate_julmdy(Date, int*);
|
extern Date PGTYPESdate_ttod(Timestamp);
|
||||||
extern int PGTYPESdate_mdyjul(int*, Date *);
|
extern void PGTYPESdate_julmdy(Date, int*);
|
||||||
extern int PGTYPESdate_day(Date);
|
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 *);
|
||||||
#endif /* PGTYPES_DATETIME */
|
#endif /* PGTYPES_DATETIME */
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
#define PGTYPES_OVERFLOW 201
|
#define PGTYPES_NUM_OVERFLOW 201
|
||||||
#define PGTYPES_BAD_NUMERIC 202
|
#define PGTYPES_NUM_BAD_NUMERIC 202
|
||||||
#define PGTYPES_DIVIDE_ZERO 203
|
#define PGTYPES_NUM_DIVIDE_ZERO 203
|
||||||
|
|
||||||
#define PGTYPES_BAD_DATE 210
|
#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_BAD_TIMESTAMP 220
|
#define PGTYPES_TS_BAD_TIMESTAMP 220
|
||||||
|
|
||||||
|
#define PGTYPES_INTVL_BAD_INTERVAL 230
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ typedef struct
|
|||||||
Numeric *PGTYPESnew(void);
|
Numeric *PGTYPESnew(void);
|
||||||
void PGTYPESnumeric_free(Numeric *);
|
void PGTYPESnumeric_free(Numeric *);
|
||||||
Numeric *PGTYPESnumeric_aton(char *, char **);
|
Numeric *PGTYPESnumeric_aton(char *, char **);
|
||||||
char *PGTYPESnumeric_ntoa(Numeric *);
|
char *PGTYPESnumeric_ntoa(Numeric *, int);
|
||||||
int PGTYPESnumeric_add(Numeric *, Numeric *, Numeric *);
|
int PGTYPESnumeric_add(Numeric *, Numeric *, Numeric *);
|
||||||
int PGTYPESnumeric_sub(Numeric *, Numeric *, Numeric *);
|
int PGTYPESnumeric_sub(Numeric *, Numeric *, Numeric *);
|
||||||
int PGTYPESnumeric_mul(Numeric *, Numeric *, Numeric *);
|
int PGTYPESnumeric_mul(Numeric *, Numeric *, Numeric *);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 1994, Regents of the University of California
|
# Copyright (c) 1994, Regents of the University of California
|
||||||
#
|
#
|
||||||
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/pgtypeslib/Makefile,v 1.3 2003/03/27 14:29:17 meskes Exp $
|
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/pgtypeslib/Makefile,v 1.4 2003/03/30 11:48:18 meskes Exp $
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ SO_MINOR_VERSION= 0.0
|
|||||||
|
|
||||||
override CPPFLAGS := -O1 -g -I$(top_srcdir)/src/interfaces/ecpg/include -I$(top_srcdir)/src/include/utils $(CPPFLAGS)
|
override CPPFLAGS := -O1 -g -I$(top_srcdir)/src/interfaces/ecpg/include -I$(top_srcdir)/src/include/utils $(CPPFLAGS)
|
||||||
|
|
||||||
OBJS= numeric.o datetime.o common.o dt_common.o timestamp.o
|
OBJS= numeric.o datetime.o common.o dt_common.o timestamp.o interval.o
|
||||||
|
|
||||||
all: all-lib
|
all: all-lib
|
||||||
|
|
||||||
|
@ -9,7 +9,31 @@
|
|||||||
#include "extern.h"
|
#include "extern.h"
|
||||||
#include "pgtypes_error.h"
|
#include "pgtypes_error.h"
|
||||||
#include "pgtypes_date.h"
|
#include "pgtypes_date.h"
|
||||||
#include "ecpg_informix.h"
|
|
||||||
|
/* XXX: currently not used.
|
||||||
|
* pgsql: timestamp_date()
|
||||||
|
* Convert timestamp to date data type.
|
||||||
|
*/
|
||||||
|
Date
|
||||||
|
PGTYPESdate_ttod(Timestamp dt)
|
||||||
|
{
|
||||||
|
Date dDate;
|
||||||
|
|
||||||
|
dDate = 0; /* suppress compiler warning */
|
||||||
|
|
||||||
|
if (TIMESTAMP_NOT_FINITE(dt))
|
||||||
|
return
|
||||||
|
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
/* Microseconds to days */
|
||||||
|
dDate = (dt / INT64CONST(86400000000));
|
||||||
|
#else
|
||||||
|
/* Seconds to days */
|
||||||
|
dDate = (dt / 86400.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return dDate;
|
||||||
|
}
|
||||||
|
|
||||||
Date
|
Date
|
||||||
PGTYPESdate_atod(char *str, char **endptr)
|
PGTYPESdate_atod(char *str, char **endptr)
|
||||||
@ -32,14 +56,14 @@ PGTYPESdate_atod(char *str, char **endptr)
|
|||||||
|
|
||||||
if (strlen(str) >= sizeof(lowstr))
|
if (strlen(str) >= sizeof(lowstr))
|
||||||
{
|
{
|
||||||
errno = PGTYPES_BAD_DATE;
|
errno = PGTYPES_DATE_BAD_DATE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0)
|
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0)
|
||||||
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp, EuroDates) != 0))
|
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp, EuroDates) != 0))
|
||||||
{
|
{
|
||||||
errno = PGTYPES_BAD_DATE;
|
errno = PGTYPES_DATE_BAD_DATE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +77,7 @@ PGTYPESdate_atod(char *str, char **endptr)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
errno = PGTYPES_BAD_DATE;
|
errno = PGTYPES_DATE_BAD_DATE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,74 +99,521 @@ PGTYPESdate_dtoa(Date dDate)
|
|||||||
return pgtypes_strdup(buf);
|
return pgtypes_strdup(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
PGTYPESdate_julmdy(Date jd, int* mdy)
|
PGTYPESdate_julmdy(Date jd, int* mdy)
|
||||||
{
|
{
|
||||||
printf("day: %d\n", mdy[0]);
|
int y, m, d;
|
||||||
printf("month: %d\n", mdy[1]);
|
|
||||||
printf("year: %d\n", mdy[2]);
|
j2date((int) jd, &y, &m, &d);
|
||||||
j2date((int) jd, mdy+2, mdy+1, mdy+0);
|
mdy[0] = (short int) m;
|
||||||
return 0;
|
mdy[1] = (short int) d;
|
||||||
|
mdy[2] = (short int) y;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
PGTYPESdate_mdyjul(int* mdy, Date *jdate)
|
PGTYPESdate_mdyjul(int* mdy, Date *jdate)
|
||||||
{
|
{
|
||||||
/* month is mdy[0] */
|
/* month is mdy[0] */
|
||||||
/* day is mdy[1] */
|
/* day is mdy[1] */
|
||||||
/* year is mdy[2] */
|
/* year is mdy[2] */
|
||||||
printf("day: %d\n", mdy[1]);
|
|
||||||
printf("month: %d\n", mdy[0]);
|
|
||||||
printf("year: %d\n", mdy[2]);
|
|
||||||
*jdate = (Date) date2j(mdy[2], mdy[0], mdy[1]);
|
*jdate = (Date) date2j(mdy[2], mdy[0], mdy[1]);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
PGTYPESdate_day(Date dDate)
|
PGTYPESdate_dayofweek(Date dDate)
|
||||||
{
|
{
|
||||||
return j2day(dDate);
|
/*
|
||||||
}
|
Sunday: 0
|
||||||
|
Monday: 1
|
||||||
int
|
Tuesday: 2
|
||||||
rdatestr (Date d, char *str)
|
Wednesday: 3
|
||||||
{
|
Thursday: 4
|
||||||
return 0;
|
Friday: 5
|
||||||
|
Saturday: 6
|
||||||
|
*/
|
||||||
|
return 6-j2day(dDate+3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rtoday (Date *d)
|
PGTYPESdate_today (Date *d)
|
||||||
{
|
{
|
||||||
|
struct tm ts;
|
||||||
|
|
||||||
|
GetCurrentDateTime(&ts);
|
||||||
|
*d = date2j(ts.tm_year, ts.tm_mon, ts.tm_mday) - date2j(2000, 1, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PGTYPES_DATE_NUM_MAX_DIGITS 20 /* should suffice for most years... */
|
||||||
|
|
||||||
|
#define PGTYPES_FMTDATE_DAY_DIGITS_LZ 1 /* LZ means "leading zeroes" */
|
||||||
|
#define PGTYPES_FMTDATE_DOW_LITERAL_SHORT 2
|
||||||
|
#define PGTYPES_FMTDATE_MONTH_DIGITS_LZ 3
|
||||||
|
#define PGTYPES_FMTDATE_MONTH_LITERAL_SHORT 4
|
||||||
|
#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
|
int
|
||||||
rjulmdy (Date d, short mdy[3])
|
PGTYPESdate_fmtdate(Date dDate, char* fmtstring, char* outbuf) {
|
||||||
{
|
static struct {
|
||||||
|
char* format;
|
||||||
|
int component;
|
||||||
|
} mapping[] = {
|
||||||
|
/* format items have to be sorted according to their length,
|
||||||
|
* since the first pattern that matches gets replaced by its
|
||||||
|
* value */
|
||||||
|
{"ddd", PGTYPES_FMTDATE_DOW_LITERAL_SHORT },
|
||||||
|
{"dd", PGTYPES_FMTDATE_DAY_DIGITS_LZ },
|
||||||
|
{"mmm", PGTYPES_FMTDATE_MONTH_LITERAL_SHORT },
|
||||||
|
{"mm", PGTYPES_FMTDATE_MONTH_DIGITS_LZ },
|
||||||
|
{"yyyy", PGTYPES_FMTDATE_YEAR_DIGITS_LONG },
|
||||||
|
{"yy", PGTYPES_FMTDATE_YEAR_DIGITS_SHORT },
|
||||||
|
{ 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;
|
||||||
|
} replace_val;
|
||||||
|
int replace_type;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int dow;
|
||||||
|
char* start_pattern;
|
||||||
|
struct tm tm;
|
||||||
|
|
||||||
|
/* XXX error handling ? */
|
||||||
|
/* copy the string over */
|
||||||
|
strcpy(outbuf, fmtstring);
|
||||||
|
|
||||||
|
/* get the date */
|
||||||
|
j2date((dDate + date2j(2000, 1, 1)), &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
|
||||||
|
dow = PGTYPESdate_dayofweek(dDate);
|
||||||
|
|
||||||
|
for (i = 0; mapping[i].format != NULL; i++) {
|
||||||
|
while ((start_pattern = strstr(outbuf, mapping[i].format)) != NULL) {
|
||||||
|
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;
|
||||||
|
break;
|
||||||
|
case PGTYPES_FMTDATE_DAY_DIGITS_LZ:
|
||||||
|
replace_val.replace_uint = tm.tm_mday;
|
||||||
|
replace_type = PGTYPES_DATE_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;
|
||||||
|
break;
|
||||||
|
case PGTYPES_FMTDATE_MONTH_DIGITS_LZ:
|
||||||
|
replace_val.replace_uint = tm.tm_mon;
|
||||||
|
replace_type = PGTYPES_DATE_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;
|
||||||
|
break;
|
||||||
|
case PGTYPES_FMTDATE_YEAR_DIGITS_SHORT:
|
||||||
|
replace_val.replace_uint = tm.tm_year % 1000;
|
||||||
|
replace_type = PGTYPES_DATE_REPLACE_UINT_2_LZ;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* should not happen, set something
|
||||||
|
* anyway */
|
||||||
|
replace_val.replace_str = " ";
|
||||||
|
replace_type = PGTYPES_DATE_REPLACE_STRING_CONSTANT;
|
||||||
|
}
|
||||||
|
switch(replace_type) {
|
||||||
|
case PGTYPES_DATE_REPLACE_STRING_MALLOCED:
|
||||||
|
case PGTYPES_DATE_REPLACE_STRING_CONSTANT:
|
||||||
|
strncpy(start_pattern, replace_val.replace_str,
|
||||||
|
strlen(replace_val.replace_str));
|
||||||
|
if (replace_type == PGTYPES_DATE_REPLACE_STRING_MALLOCED) {
|
||||||
|
free(replace_val.replace_str);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PGTYPES_DATE_REPLACE_UINT:
|
||||||
|
{
|
||||||
|
char* t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS);
|
||||||
|
if (!t) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
snprintf(t, PGTYPES_DATE_NUM_MAX_DIGITS,
|
||||||
|
"%u", replace_val.replace_uint);
|
||||||
|
strncpy(start_pattern, t, strlen(t));
|
||||||
|
free(t);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PGTYPES_DATE_REPLACE_UINT_2_LZ:
|
||||||
|
{
|
||||||
|
char* t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS);
|
||||||
|
if (!t) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
snprintf(t, PGTYPES_DATE_NUM_MAX_DIGITS,
|
||||||
|
"%02u", replace_val.replace_uint);
|
||||||
|
strncpy(start_pattern, t, strlen(t));
|
||||||
|
free(t);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PGTYPES_DATE_REPLACE_UINT_4_LZ:
|
||||||
|
{
|
||||||
|
char* t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS);
|
||||||
|
if (!t) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
snprintf(t, PGTYPES_DATE_NUM_MAX_DIGITS,
|
||||||
|
"%04u", replace_val.replace_uint);
|
||||||
|
strncpy(start_pattern, t, strlen(t));
|
||||||
|
free(t);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* doesn't happen (we set
|
||||||
|
* replace_type to
|
||||||
|
* PGTYPES_DATE_REPLACE_STRING_CONSTANT
|
||||||
|
* in case of an error above) */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PGTYPESdate_rdefmtdate
|
||||||
|
*
|
||||||
|
* function works as follows:
|
||||||
|
* - first we analyze the paramters
|
||||||
|
* - if this is a special case with no delimiters, add delimters
|
||||||
|
* - find the tokens. First we look for numerical values. If we have found
|
||||||
|
* less than 3 tokens, we check for the months' names and thereafter for
|
||||||
|
* the abbreviations of the months' names.
|
||||||
|
* - then we see which parameter should be the date, the month and the
|
||||||
|
* year and from these values we calculate the date
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PGTYPES_DATE_MONTH_MAXLENGTH 20 /* probably even less :-) */
|
||||||
int
|
int
|
||||||
rdefmtdate (Date *d, char *fmt, char *str)
|
PGTYPESdate_defmtdate(Date *d, char *fmt, char *str)
|
||||||
{
|
{
|
||||||
|
/* token[2] = { 4,6 } means that token 2 starts at
|
||||||
|
* position 4 and ends at (including) position 6 */
|
||||||
|
int token[3][2];
|
||||||
|
int token_values[3] = { -1, -1, -1 };
|
||||||
|
char* fmt_token_order;
|
||||||
|
char* fmt_ystart, *fmt_mstart, *fmt_dstart;
|
||||||
|
int i;
|
||||||
|
int reading_digit;
|
||||||
|
int token_count;
|
||||||
|
char* str_copy;
|
||||||
|
struct tm tm;
|
||||||
|
|
||||||
|
if (!d || !str || !fmt) {
|
||||||
|
errno = PGTYPES_DATE_ERR_EARGS;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* analyze the fmt string */
|
||||||
|
fmt_ystart = strstr(fmt, "yy");
|
||||||
|
fmt_mstart = strstr(fmt, "mm");
|
||||||
|
fmt_dstart = strstr(fmt, "dd");
|
||||||
|
|
||||||
|
if (!fmt_ystart || !fmt_mstart || !fmt_dstart) {
|
||||||
|
errno = PGTYPES_DATE_ERR_EARGS;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fmt_ystart < fmt_mstart) {
|
||||||
|
/* y m */
|
||||||
|
if (fmt_dstart < fmt_ystart) {
|
||||||
|
/* d y m */
|
||||||
|
fmt_token_order = "dym";
|
||||||
|
} else if (fmt_dstart > fmt_mstart) {
|
||||||
|
/* y m d */
|
||||||
|
fmt_token_order = "ymd";
|
||||||
|
} else {
|
||||||
|
/* y d m */
|
||||||
|
fmt_token_order = "ydm";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* fmt_ystart > fmt_mstart */
|
||||||
|
/* m y */
|
||||||
|
if (fmt_dstart < fmt_mstart) {
|
||||||
|
/* d m y */
|
||||||
|
fmt_token_order = "dmy";
|
||||||
|
} else if (fmt_dstart > fmt_ystart) {
|
||||||
|
/* m y d */
|
||||||
|
fmt_token_order = "myd";
|
||||||
|
} else {
|
||||||
|
/* m d y */
|
||||||
|
fmt_token_order = "mdy";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handle the special cases where there is no delimiter between the
|
||||||
|
* digits. If we see this:
|
||||||
|
*
|
||||||
|
* only digits, 6 or 8 bytes then it might be ddmmyy and ddmmyyyy
|
||||||
|
* (or similar)
|
||||||
|
*
|
||||||
|
* we reduce it to a string with delimiters and continue processing
|
||||||
|
* */
|
||||||
|
|
||||||
|
/* check if we have only digits */
|
||||||
|
reading_digit = 1;
|
||||||
|
for (i = 0; str[i]; i++) {
|
||||||
|
if (!isdigit(str[i])) {
|
||||||
|
reading_digit = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (reading_digit) {
|
||||||
|
int frag_length[3];
|
||||||
|
int target_pos;
|
||||||
|
|
||||||
|
i = strlen(str);
|
||||||
|
if (i != 8 && i != 6) {
|
||||||
|
errno = PGTYPES_DATE_ERR_ENOSHORTDATE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* okay, this really is the special case */
|
||||||
|
|
||||||
|
/* as long as the string, one additional byte for the
|
||||||
|
* terminator and 2 for the delimiters between the 3 fiedls
|
||||||
|
* */
|
||||||
|
str_copy = pgtypes_alloc(strlen(str) + 1 + 2);
|
||||||
|
if (!str_copy) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* determine length of the fragments */
|
||||||
|
if (i == 6) {
|
||||||
|
frag_length[0] = 2; frag_length[1] = 2; frag_length[2] = 2;
|
||||||
|
} else {
|
||||||
|
if (fmt_token_order[0] == 'y') {
|
||||||
|
frag_length[0] = 4; frag_length[1] = 2; frag_length[2] = 2;
|
||||||
|
} else if (fmt_token_order[1] == 'y') {
|
||||||
|
frag_length[0] = 2; frag_length[1] = 4; frag_length[2] = 2;
|
||||||
|
} else {
|
||||||
|
frag_length[0] = 2; frag_length[1] = 2; frag_length[2] = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target_pos = 0;
|
||||||
|
/* XXX: Here we could calculate the positions of the tokens
|
||||||
|
* and save the for loop down there where we again check
|
||||||
|
* with isdigit() for digits. */
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
int start_pos = 0;
|
||||||
|
if (i >= 1) { start_pos += frag_length[0]; }
|
||||||
|
if (i == 2) { start_pos += frag_length[1]; }
|
||||||
|
|
||||||
|
strncpy(str_copy + target_pos, str + start_pos,
|
||||||
|
frag_length[i]);
|
||||||
|
target_pos += frag_length[i];
|
||||||
|
if (i != 2) {
|
||||||
|
str_copy[target_pos] = ' ';
|
||||||
|
target_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str_copy[target_pos] = '\0';
|
||||||
|
} else {
|
||||||
|
str_copy = pgtypes_strdup(str);
|
||||||
|
if (!str_copy) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert the whole string to lower case */
|
||||||
|
for (i = 0; str_copy[i]; i++) {
|
||||||
|
str_copy[i] = (char) tolower(str_copy[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look for numerical tokens */
|
||||||
|
reading_digit = 0;
|
||||||
|
token_count = 0;
|
||||||
|
for (i = 0; i < strlen(str_copy); i++) {
|
||||||
|
if (!isdigit(str_copy[i]) && reading_digit) {
|
||||||
|
/* the token is finished */
|
||||||
|
token[token_count][1] = i-1;
|
||||||
|
reading_digit = 0;
|
||||||
|
token_count++;
|
||||||
|
} else if (isdigit(str_copy[i]) && !reading_digit) {
|
||||||
|
/* we have found a token */
|
||||||
|
token[token_count][0] = i;
|
||||||
|
reading_digit = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* we're at the end of the input string, but maybe we are still reading a
|
||||||
|
* number... */
|
||||||
|
if (reading_digit) {
|
||||||
|
token[token_count][1] = i-1;
|
||||||
|
token_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (token_count < 2) {
|
||||||
|
/* not all tokens found, no way to find 2 missing tokens
|
||||||
|
* with string matches */
|
||||||
|
free(str_copy);
|
||||||
|
errno = PGTYPES_DATE_ERR_ENOTDMY;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token_count != 3) {
|
||||||
|
/* not all tokens found but we may find another one with
|
||||||
|
* string matches by testing for the months names and months
|
||||||
|
* abbreviations */
|
||||||
|
char *month_lower_tmp = pgtypes_alloc(PGTYPES_DATE_MONTH_MAXLENGTH);
|
||||||
|
char *start_pos;
|
||||||
|
int j;
|
||||||
|
int offset;
|
||||||
|
int found = 0;
|
||||||
|
char** list;
|
||||||
|
|
||||||
|
if (!month_lower_tmp) {
|
||||||
|
/* free variables we alloc'ed before */
|
||||||
|
free(str_copy);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
list = pgtypes_date_months;
|
||||||
|
for (i = 0; list[i]; i++) {
|
||||||
|
for (j = 0; j < PGTYPES_DATE_MONTH_MAXLENGTH; j++) {
|
||||||
|
month_lower_tmp[j] = (char) tolower(list[i][j]);
|
||||||
|
if (!month_lower_tmp[j]) {
|
||||||
|
/* properly terminated */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((start_pos = strstr(str_copy, month_lower_tmp))) {
|
||||||
|
offset = start_pos - str_copy;
|
||||||
|
/* sort the new token into the numeric
|
||||||
|
* tokens, shift them if necessary */
|
||||||
|
if (offset < token[0][0]) {
|
||||||
|
token[2][0] = token[1][0];
|
||||||
|
token[2][1] = token[1][1];
|
||||||
|
token[1][0] = token[0][0];
|
||||||
|
token[1][1] = token[0][1];
|
||||||
|
token_count = 0;
|
||||||
|
} else if (offset < token[1][0]) {
|
||||||
|
token[2][0] = token[1][0];
|
||||||
|
token[2][1] = token[1][1];
|
||||||
|
token_count = 1;
|
||||||
|
} else {
|
||||||
|
token_count = 2;
|
||||||
|
}
|
||||||
|
token[token_count][0] = offset;
|
||||||
|
token[token_count][1] = offset + strlen(month_lower_tmp) - 1;
|
||||||
|
/* the value is the index of the month in
|
||||||
|
* the array of months + 1 (January is month
|
||||||
|
* 0) */
|
||||||
|
token_values[token_count] = i+1;
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* evil[tm] hack:
|
||||||
|
* if we read the pgtypes_date_months and haven't
|
||||||
|
* found a match, reset list to point to
|
||||||
|
* pgtypes_date_months_short and reset the counter
|
||||||
|
* variable i */
|
||||||
|
if (list == pgtypes_date_months) {
|
||||||
|
if (list[i+1] == NULL) {
|
||||||
|
list = pgtypes_date_months_short;
|
||||||
|
i = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
free(month_lower_tmp);
|
||||||
|
free(str_copy);
|
||||||
|
errno = PGTYPES_DATE_ERR_ENOTDMY;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* here we found a month. token[token_count] and
|
||||||
|
* token_values[token_count] reflect the month's details.
|
||||||
|
*
|
||||||
|
* only the month can be specified with a literal. Here we can do a
|
||||||
|
* quick check if the month is at the right position according to
|
||||||
|
* the format string because we can check if the token that
|
||||||
|
* we expect to be the month is at the position of the only
|
||||||
|
* token that already has a value. If we wouldn't check here
|
||||||
|
* we could say "December 4 1990" with a fmt string of
|
||||||
|
* "dd mm yy" for 12 April 1990.
|
||||||
|
*/
|
||||||
|
if (fmt_token_order[token_count] != 'm') {
|
||||||
|
/* deal with the error later on */
|
||||||
|
token_values[token_count] = -1;
|
||||||
|
}
|
||||||
|
free(month_lower_tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* terminate the tokens with ASCII-0 and get their values */
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
*(str_copy + token[i][1] + 1) = '\0';
|
||||||
|
/* A month already has a value set, check for token_value == -1 */
|
||||||
|
if (token_values[i] == -1) {
|
||||||
|
errno = 0;
|
||||||
|
token_values[i] = strtol(str_copy + token[i][0], (char **) NULL, 10);
|
||||||
|
/* strtol sets errno in case of an error */
|
||||||
|
if (errno) {
|
||||||
|
token_values[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fmt_token_order[i] == 'd') {
|
||||||
|
tm.tm_mday = token_values[i];
|
||||||
|
} else if (fmt_token_order[i] == 'm') {
|
||||||
|
tm.tm_mon = token_values[i];
|
||||||
|
} else if (fmt_token_order[i] == 'y') {
|
||||||
|
tm.tm_year = token_values[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(str_copy);
|
||||||
|
|
||||||
|
if (tm.tm_mday < 1 || tm.tm_mday > 31)
|
||||||
|
{
|
||||||
|
errno = PGTYPES_DATE_BAD_DAY;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tm.tm_mon < 1 || tm.tm_mon > 12)
|
||||||
|
{
|
||||||
|
errno = PGTYPES_DATE_BAD_MONTH;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tm.tm_mday == 31 && (tm.tm_mon == 4 || tm.tm_mon == 6 || tm.tm_mon == 9 || tm.tm_mon ==11))
|
||||||
|
{
|
||||||
|
errno = PGTYPES_DATE_BAD_DAY;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tm.tm_mon == 2 && tm.tm_mday > 29)
|
||||||
|
{
|
||||||
|
errno = PGTYPES_DATE_BAD_DAY;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*d = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - date2j(2000, 1, 1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
rfmtdate (Date d, char *fmt, char *str)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
rmdyjul (short mdy[3], Date *d)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
rstrdate (char *str, Date *d)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -296,6 +296,7 @@ extern void GetEpochTime(struct tm *);
|
|||||||
extern int ParseDateTime(char *, char *, char **, int *, int, int *, char **);
|
extern int ParseDateTime(char *, char *, char **, int *, int, int *, char **);
|
||||||
extern int DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, int *, bool);
|
extern int DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, int *, bool);
|
||||||
extern void j2date(int, int *, int *, int *);
|
extern void j2date(int, int *, int *, int *);
|
||||||
|
extern void GetCurrentDateTime(struct tm*);
|
||||||
extern int date2j(int, int, int);
|
extern int date2j(int, int, int);
|
||||||
extern double rint(double x);
|
extern double rint(double x);
|
||||||
|
|
||||||
|
@ -426,10 +426,81 @@ static datetkn datetktbl[] = {
|
|||||||
{ZULU, TZ, POS(0)}, /* UTC */
|
{ZULU, TZ, POS(0)}, /* UTC */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static datetkn deltatktbl[] = {
|
||||||
|
/* text, token, lexval */
|
||||||
|
{"@", IGNORE_DTF, 0}, /* postgres relative prefix */
|
||||||
|
{DAGO, AGO, 0}, /* "ago" indicates negative time offset */
|
||||||
|
{"c", UNITS, DTK_CENTURY}, /* "century" relative */
|
||||||
|
{"cent", UNITS, DTK_CENTURY}, /* "century" relative */
|
||||||
|
{"centuries", UNITS, DTK_CENTURY}, /* "centuries" relative */
|
||||||
|
{DCENTURY, UNITS, DTK_CENTURY}, /* "century" relative */
|
||||||
|
{"d", UNITS, DTK_DAY}, /* "day" relative */
|
||||||
|
{DDAY, UNITS, DTK_DAY}, /* "day" relative */
|
||||||
|
{"days", UNITS, DTK_DAY}, /* "days" relative */
|
||||||
|
{"dec", UNITS, DTK_DECADE}, /* "decade" relative */
|
||||||
|
{DDECADE, UNITS, DTK_DECADE}, /* "decade" relative */
|
||||||
|
{"decades", UNITS, DTK_DECADE}, /* "decades" relative */
|
||||||
|
{"decs", UNITS, DTK_DECADE}, /* "decades" relative */
|
||||||
|
{"h", UNITS, DTK_HOUR}, /* "hour" relative */
|
||||||
|
{DHOUR, UNITS, DTK_HOUR}, /* "hour" relative */
|
||||||
|
{"hours", UNITS, DTK_HOUR}, /* "hours" relative */
|
||||||
|
{"hr", UNITS, DTK_HOUR}, /* "hour" relative */
|
||||||
|
{"hrs", UNITS, DTK_HOUR}, /* "hours" relative */
|
||||||
|
{INVALID, RESERV, DTK_INVALID}, /* reserved for invalid time */
|
||||||
|
{"m", UNITS, DTK_MINUTE}, /* "minute" relative */
|
||||||
|
{"microsecon", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
|
||||||
|
{"mil", UNITS, DTK_MILLENNIUM}, /* "millennium" relative */
|
||||||
|
{"millennia", UNITS, DTK_MILLENNIUM}, /* "millennia" relative */
|
||||||
|
{DMILLENNIUM, UNITS, DTK_MILLENNIUM}, /* "millennium" relative */
|
||||||
|
{"millisecon", UNITS, DTK_MILLISEC}, /* relative */
|
||||||
|
{"mils", UNITS, DTK_MILLENNIUM}, /* "millennia" relative */
|
||||||
|
{"min", UNITS, DTK_MINUTE}, /* "minute" relative */
|
||||||
|
{"mins", UNITS, DTK_MINUTE}, /* "minutes" relative */
|
||||||
|
{DMINUTE, UNITS, DTK_MINUTE}, /* "minute" relative */
|
||||||
|
{"minutes", UNITS, DTK_MINUTE}, /* "minutes" relative */
|
||||||
|
{"mon", UNITS, DTK_MONTH}, /* "months" relative */
|
||||||
|
{"mons", UNITS, DTK_MONTH}, /* "months" relative */
|
||||||
|
{DMONTH, UNITS, DTK_MONTH}, /* "month" relative */
|
||||||
|
{"months", UNITS, DTK_MONTH},
|
||||||
|
{"ms", UNITS, DTK_MILLISEC},
|
||||||
|
{"msec", UNITS, DTK_MILLISEC},
|
||||||
|
{DMILLISEC, UNITS, DTK_MILLISEC},
|
||||||
|
{"mseconds", UNITS, DTK_MILLISEC},
|
||||||
|
{"msecs", UNITS, DTK_MILLISEC},
|
||||||
|
{"qtr", UNITS, DTK_QUARTER}, /* "quarter" relative */
|
||||||
|
{DQUARTER, UNITS, DTK_QUARTER}, /* "quarter" relative */
|
||||||
|
{"reltime", IGNORE_DTF, 0}, /* pre-v6.1 "Undefined Reltime" */
|
||||||
|
{"s", UNITS, DTK_SECOND},
|
||||||
|
{"sec", UNITS, DTK_SECOND},
|
||||||
|
{DSECOND, UNITS, DTK_SECOND},
|
||||||
|
{"seconds", UNITS, DTK_SECOND},
|
||||||
|
{"secs", UNITS, DTK_SECOND},
|
||||||
|
{DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
|
||||||
|
{"timezone_h", UNITS, DTK_TZ_HOUR}, /* timezone hour units */
|
||||||
|
{"timezone_m", UNITS, DTK_TZ_MINUTE}, /* timezone minutes units */
|
||||||
|
{"undefined", RESERV, DTK_INVALID}, /* pre-v6.1 invalid time */
|
||||||
|
{"us", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
|
||||||
|
{"usec", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
|
||||||
|
{DMICROSEC, UNITS, DTK_MICROSEC}, /* "microsecond" relative */
|
||||||
|
{"useconds", UNITS, DTK_MICROSEC}, /* "microseconds" relative */
|
||||||
|
{"usecs", UNITS, DTK_MICROSEC}, /* "microseconds" relative */
|
||||||
|
{"w", UNITS, DTK_WEEK}, /* "week" relative */
|
||||||
|
{DWEEK, UNITS, DTK_WEEK}, /* "week" relative */
|
||||||
|
{"weeks", UNITS, DTK_WEEK}, /* "weeks" relative */
|
||||||
|
{"y", UNITS, DTK_YEAR}, /* "year" relative */
|
||||||
|
{DYEAR, UNITS, DTK_YEAR}, /* "year" relative */
|
||||||
|
{"years", UNITS, DTK_YEAR}, /* "years" relative */
|
||||||
|
{"yr", UNITS, DTK_YEAR}, /* "year" relative */
|
||||||
|
{"yrs", UNITS, DTK_YEAR}, /* "years" relative */
|
||||||
|
};
|
||||||
|
|
||||||
static unsigned int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0];
|
static unsigned int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0];
|
||||||
|
static unsigned int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
|
||||||
|
|
||||||
static datetkn *datecache[MAXDATEFIELDS] = {NULL};
|
static datetkn *datecache[MAXDATEFIELDS] = {NULL};
|
||||||
|
|
||||||
|
static datetkn *deltacache[MAXDATEFIELDS] = {NULL};
|
||||||
|
|
||||||
char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};
|
char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};
|
||||||
|
|
||||||
char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", NULL};
|
char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", NULL};
|
||||||
@ -561,6 +632,39 @@ datebsearch(char *key, datetkn *base, unsigned int nel)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* DecodeUnits()
|
||||||
|
* Decode text string using lookup table.
|
||||||
|
* This routine supports time interval decoding.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
DecodeUnits(int field, char *lowtoken, int *val)
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
datetkn *tp;
|
||||||
|
|
||||||
|
if ((deltacache[field] != NULL)
|
||||||
|
&& (strncmp(lowtoken, deltacache[field]->token, TOKMAXLEN) == 0))
|
||||||
|
tp = deltacache[field];
|
||||||
|
else
|
||||||
|
tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
|
||||||
|
deltacache[field] = tp;
|
||||||
|
if (tp == NULL)
|
||||||
|
{
|
||||||
|
type = UNKNOWN_FIELD;
|
||||||
|
*val = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type = tp->type;
|
||||||
|
if ((type == TZ) || (type == DTZ))
|
||||||
|
*val = FROMVAL(tp);
|
||||||
|
else
|
||||||
|
*val = tp->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
} /* DecodeUnits() */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calendar time to Julian date conversions.
|
* Calendar time to Julian date conversions.
|
||||||
* Julian date is commonly used in astronomical applications,
|
* Julian date is commonly used in astronomical applications,
|
||||||
@ -1088,7 +1192,7 @@ abstime2tm(AbsoluteTime _time, int *tzp, struct tm * tm, char **tzn)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
GetCurrentDateTime(struct tm * tm)
|
GetCurrentDateTime(struct tm * tm)
|
||||||
{
|
{
|
||||||
int tz;
|
int tz;
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "c.h"
|
#include "c.h"
|
||||||
#include "extern.h"
|
#include "extern.h"
|
||||||
#include "pgtypes_error.h"
|
#include "pgtypes_error.h"
|
||||||
#include "decimal.h"
|
|
||||||
|
|
||||||
#define Max(x, y) ((x) > (y) ? (x) : (y))
|
#define Max(x, y) ((x) > (y) ? (x) : (y))
|
||||||
#define Min(x, y) ((x) < (y) ? (x) : (y))
|
#define Min(x, y) ((x) < (y) ? (x) : (y))
|
||||||
@ -96,7 +95,7 @@ apply_typmod(Numeric *var, long typmod)
|
|||||||
|
|
||||||
if (tweight >= maxweight && i < var->ndigits)
|
if (tweight >= maxweight && i < var->ndigits)
|
||||||
{
|
{
|
||||||
errno = PGTYPES_OVERFLOW;
|
errno = PGTYPES_NUM_OVERFLOW;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -188,7 +187,7 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
|
|||||||
|
|
||||||
if (!isdigit((unsigned char) *(*ptr)))
|
if (!isdigit((unsigned char) *(*ptr)))
|
||||||
{
|
{
|
||||||
errno=PGTYPES_BAD_NUMERIC;
|
errno=PGTYPES_NUM_BAD_NUMERIC;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +205,7 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
|
|||||||
{
|
{
|
||||||
if (have_dp)
|
if (have_dp)
|
||||||
{
|
{
|
||||||
errno = PGTYPES_BAD_NUMERIC;
|
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
have_dp = TRUE;
|
have_dp = TRUE;
|
||||||
@ -227,14 +226,14 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
|
|||||||
exponent = strtol((*ptr), &endptr, 10);
|
exponent = strtol((*ptr), &endptr, 10);
|
||||||
if (endptr == (*ptr))
|
if (endptr == (*ptr))
|
||||||
{
|
{
|
||||||
errno = PGTYPES_BAD_NUMERIC;
|
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
(*ptr) = endptr;
|
(*ptr) = endptr;
|
||||||
if (exponent > NUMERIC_MAX_PRECISION ||
|
if (exponent > NUMERIC_MAX_PRECISION ||
|
||||||
exponent < -NUMERIC_MAX_PRECISION)
|
exponent < -NUMERIC_MAX_PRECISION)
|
||||||
{
|
{
|
||||||
errno = PGTYPES_BAD_NUMERIC;
|
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
dest->weight += (int) exponent;
|
dest->weight += (int) exponent;
|
||||||
@ -248,7 +247,7 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
|
|||||||
{
|
{
|
||||||
if (!isspace((unsigned char) *(*ptr)))
|
if (!isspace((unsigned char) *(*ptr)))
|
||||||
{
|
{
|
||||||
errno = PGTYPES_BAD_NUMERIC;
|
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
(*ptr)++;
|
(*ptr)++;
|
||||||
@ -402,9 +401,12 @@ PGTYPESnumeric_aton(char *str, char **endptr)
|
|||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
PGTYPESnumeric_ntoa(Numeric *num)
|
PGTYPESnumeric_ntoa(Numeric *num, int dscale)
|
||||||
{
|
{
|
||||||
return(get_str_from_var(num, num->dscale));
|
if (dscale <= 0)
|
||||||
|
dscale = num->dscale;
|
||||||
|
|
||||||
|
return(get_str_from_var(num, dscale));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
@ -1117,7 +1119,7 @@ PGTYPESnumeric_div(Numeric *var1, Numeric *var2, Numeric *result)
|
|||||||
ndigits_tmp = var2->ndigits + 1;
|
ndigits_tmp = var2->ndigits + 1;
|
||||||
if (ndigits_tmp == 1)
|
if (ndigits_tmp == 1)
|
||||||
{
|
{
|
||||||
errno= PGTYPES_DIVIDE_ZERO;
|
errno= PGTYPES_NUM_DIVIDE_ZERO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1320,7 +1322,7 @@ PGTYPESnumeric_cmp(Numeric *var1, Numeric *var2) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = PGTYPES_BAD_NUMERIC;
|
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||||
return INT_MAX;
|
return INT_MAX;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1438,7 +1440,7 @@ numericvar_to_double_no_overflow(Numeric *var, double *dp)
|
|||||||
{
|
{
|
||||||
/* shouldn't happen ... */
|
/* shouldn't happen ... */
|
||||||
free(tmp);
|
free(tmp);
|
||||||
errno = PGTYPES_BAD_NUMERIC;
|
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*dp = val;
|
*dp = val;
|
||||||
@ -1466,7 +1468,7 @@ PGTYPESnumeric_ntoi(Numeric* nv, int* ip) {
|
|||||||
return i;
|
return i;
|
||||||
|
|
||||||
if (l < -INT_MAX || l > INT_MAX) {
|
if (l < -INT_MAX || l > INT_MAX) {
|
||||||
errno = PGTYPES_OVERFLOW;
|
errno = PGTYPES_NUM_OVERFLOW;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1488,7 +1490,7 @@ PGTYPESnumeric_ntol(Numeric* nv, long* lp) {
|
|||||||
l++;
|
l++;
|
||||||
}
|
}
|
||||||
if (l > LONG_MAX || l < 0) {
|
if (l > LONG_MAX || l < 0) {
|
||||||
errno = PGTYPES_OVERFLOW;
|
errno = PGTYPES_NUM_OVERFLOW;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1499,196 +1501,3 @@ PGTYPESnumeric_ntol(Numeric* nv, long* lp) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally we need some wrappers for the INFORMIX functions */
|
|
||||||
int
|
|
||||||
decadd(Numeric *arg1, Numeric *arg2, Numeric *sum)
|
|
||||||
{
|
|
||||||
int i = PGTYPESnumeric_add(arg1, arg2, sum);
|
|
||||||
|
|
||||||
if (i == 0) /* No error */
|
|
||||||
return 0;
|
|
||||||
if (errno == PGTYPES_OVERFLOW)
|
|
||||||
return -1200;
|
|
||||||
|
|
||||||
return -1201;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
deccmp(Numeric *arg1, Numeric *arg2)
|
|
||||||
{
|
|
||||||
int i = PGTYPESnumeric_cmp(arg1, arg2);
|
|
||||||
|
|
||||||
/* TODO: Need to return DECUNKNOWN instead of PGTYPES_BAD_NUMERIC */
|
|
||||||
return (i);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
deccopy(Numeric *src, Numeric *target)
|
|
||||||
{
|
|
||||||
PGTYPESnumeric_copy(src, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
strndup(char *str, int len)
|
|
||||||
{
|
|
||||||
int real_len = strlen(str);
|
|
||||||
int use_len = (real_len > len) ? len : real_len;
|
|
||||||
|
|
||||||
char *new = pgtypes_alloc(use_len + 1);
|
|
||||||
|
|
||||||
if (new)
|
|
||||||
{
|
|
||||||
memcpy(str, new, use_len);
|
|
||||||
new[use_len] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
deccvasc(char *cp, int len, Numeric *np)
|
|
||||||
{
|
|
||||||
char *str = strndup(cp, len); /* Numeric_in always converts the complete string */
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (!str)
|
|
||||||
ret = -1201;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
np = PGTYPESnumeric_aton(str, NULL);
|
|
||||||
if (!np)
|
|
||||||
{
|
|
||||||
switch (errno)
|
|
||||||
{
|
|
||||||
case PGTYPES_OVERFLOW: ret = -1200;
|
|
||||||
break;
|
|
||||||
case PGTYPES_BAD_NUMERIC: ret = -1213;
|
|
||||||
break;
|
|
||||||
default: ret = -1216;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
deccvdbl(double dbl, Numeric *np)
|
|
||||||
{
|
|
||||||
return(PGTYPESnumeric_dton(dbl, np));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
deccvint(int in, Numeric *np)
|
|
||||||
{
|
|
||||||
return(PGTYPESnumeric_iton(in, np));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
deccvlong(long lng, Numeric *np)
|
|
||||||
{
|
|
||||||
return(PGTYPESnumeric_lton(lng, np));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
decdiv(Numeric *n1, Numeric *n2, Numeric *n3)
|
|
||||||
{
|
|
||||||
int i = PGTYPESnumeric_div(n1, n2, n3), ret = 0;
|
|
||||||
|
|
||||||
if (i != 0)
|
|
||||||
switch (errno)
|
|
||||||
{
|
|
||||||
case PGTYPES_DIVIDE_ZERO: ret = -1202;
|
|
||||||
break;
|
|
||||||
case PGTYPES_OVERFLOW: ret = -1200;
|
|
||||||
break;
|
|
||||||
default: ret = -1201;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
decmul(Numeric *n1, Numeric *n2, Numeric *n3)
|
|
||||||
{
|
|
||||||
int i = PGTYPESnumeric_mul(n1, n2, n3), ret = 0;
|
|
||||||
|
|
||||||
if (i != 0)
|
|
||||||
switch (errno)
|
|
||||||
{
|
|
||||||
case PGTYPES_OVERFLOW: ret = -1200;
|
|
||||||
break;
|
|
||||||
default: ret = -1201;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
decsub(Numeric *n1, Numeric *n2, Numeric *n3)
|
|
||||||
{
|
|
||||||
int i = PGTYPESnumeric_sub(n1, n2, n3), ret = 0;
|
|
||||||
|
|
||||||
if (i != 0)
|
|
||||||
switch (errno)
|
|
||||||
{
|
|
||||||
case PGTYPES_OVERFLOW: ret = -1200;
|
|
||||||
break;
|
|
||||||
default: ret = -1201;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
dectoasc(Numeric *np, char *cp, int len, int right)
|
|
||||||
{
|
|
||||||
char *str;
|
|
||||||
|
|
||||||
if (right >= 0)
|
|
||||||
str = get_str_from_var(np, right);
|
|
||||||
else
|
|
||||||
str = get_str_from_var(np, np->dscale);
|
|
||||||
|
|
||||||
if (!str)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* TODO: have to take care of len here and create exponatial notion if necessary */
|
|
||||||
strncpy(cp, str, len);
|
|
||||||
free (str);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
dectodbl(Numeric *np, double *dblp)
|
|
||||||
{
|
|
||||||
return(PGTYPESnumeric_ntod(np, dblp));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
dectoint(Numeric *np, int *ip)
|
|
||||||
{
|
|
||||||
int ret = PGTYPESnumeric_ntoi(np, ip);
|
|
||||||
|
|
||||||
if (ret == PGTYPES_OVERFLOW)
|
|
||||||
ret = -1200;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
dectolong(Numeric *np, long *lngp)
|
|
||||||
{
|
|
||||||
int ret = PGTYPESnumeric_ntol(np, lngp);
|
|
||||||
|
|
||||||
if (ret == PGTYPES_OVERFLOW)
|
|
||||||
ret = -1200;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include "extern.h"
|
#include "extern.h"
|
||||||
#include "pgtypes_error.h"
|
#include "pgtypes_error.h"
|
||||||
#include "pgtypes_timestamp.h"
|
#include "pgtypes_timestamp.h"
|
||||||
#include "pgtypes_interval.h"
|
|
||||||
#include "datetime.h"
|
#include "datetime.h"
|
||||||
|
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
@ -288,14 +287,14 @@ PGTYPEStimestamp_atot(char *str, char **endptr)
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
if (strlen(str) >= sizeof(lowstr))
|
if (strlen(str) >= sizeof(lowstr))
|
||||||
{
|
{
|
||||||
errno = PGTYPES_BAD_TIMESTAMP;
|
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||||
return (noresult);
|
return (noresult);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0)
|
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0)
|
||||||
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz, 0) != 0))
|
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz, 0) != 0))
|
||||||
{
|
{
|
||||||
errno = PGTYPES_BAD_TIMESTAMP;
|
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||||
return (noresult);
|
return (noresult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +303,7 @@ PGTYPEStimestamp_atot(char *str, char **endptr)
|
|||||||
case DTK_DATE:
|
case DTK_DATE:
|
||||||
if (tm2timestamp(tm, fsec, NULL, &result) != 0)
|
if (tm2timestamp(tm, fsec, NULL, &result) != 0)
|
||||||
{
|
{
|
||||||
errno = PGTYPES_BAD_TIMESTAMP;
|
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||||
return (noresult);;
|
return (noresult);;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -322,11 +321,11 @@ PGTYPEStimestamp_atot(char *str, char **endptr)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DTK_INVALID:
|
case DTK_INVALID:
|
||||||
errno = PGTYPES_BAD_TIMESTAMP;
|
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||||
return (noresult);
|
return (noresult);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
errno = PGTYPES_BAD_TIMESTAMP;
|
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||||
return (noresult);
|
return (noresult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,67 +349,8 @@ PGTYPEStimestamp_ttoa(Timestamp tstamp)
|
|||||||
EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf, 0);
|
EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf, 0);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
errno = PGTYPES_BAD_TIMESTAMP;
|
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return pgtypes_strdup(buf);
|
return pgtypes_strdup(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
dtcurrent (Timestamp *ts)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
dtcvasc (char *str, Timestamp *ts)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
dtsub (Timestamp *ts1, Timestamp *ts2, Interval *iv)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
dttoasc (Timestamp *ts, char *output)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
dttofmtasc (Timestamp *ts, char *output, int str_len, char *fmtstr)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
intoasc(Interval *i, char *str)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Interval *
|
|
||||||
PGTYPESinterval_atoi(char *str, char **endptr)
|
|
||||||
{
|
|
||||||
Interval *result = NULL;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
PGTYPESinterval_itoa(Interval *intvl)
|
|
||||||
{
|
|
||||||
char buf[MAXDATELEN + 1];
|
|
||||||
|
|
||||||
return pgtypes_strdup(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
PGTYPESinterval_copy(Interval *intvlsrc, Interval *intrcldest)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,46 +1,153 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <pgtypes_date.h>
|
#include <pgtypes_date.h>
|
||||||
#include <pgtypes_timestamp.h>
|
#include <pgtypes_timestamp.h>
|
||||||
|
#include <pgtypes_interval.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
exec sql begin declare section;
|
exec sql begin declare section;
|
||||||
date date1;
|
date date1;
|
||||||
timestamp ts1;
|
timestamp ts1;
|
||||||
char *text;
|
interval iv1;
|
||||||
|
char *text;
|
||||||
exec sql end declare section;
|
exec sql end declare section;
|
||||||
#if 0
|
|
||||||
Date date2;
|
Date date2;
|
||||||
short int mdy[3] = { 4, 19, 1998 };
|
int mdy[3] = { 4, 19, 1998 };
|
||||||
#endif
|
char *fmt, *out, *in;
|
||||||
|
|
||||||
FILE *dbgs;
|
FILE *dbgs;
|
||||||
|
|
||||||
if ((dbgs = fopen("log", "w")) != NULL)
|
if ((dbgs = fopen("log", "w")) != NULL)
|
||||||
ECPGdebug(1, dbgs);
|
ECPGdebug(1, dbgs);
|
||||||
exec sql whenever sqlerror do sqlprint();
|
exec sql whenever sqlerror do sqlprint();
|
||||||
exec sql connect to mm;
|
exec sql connect to mm;
|
||||||
exec sql create table date_test (d date, ts timestamp);
|
exec sql create table date_test (d date, ts timestamp, iv interval);
|
||||||
|
|
||||||
exec sql insert into date_test(d, ts) values ('Mon Jan 17 1966', '2000-7-12 17:34:29');
|
exec sql insert into date_test(d, ts, iv) values ('Mon Jan 17 1966', '2000-7-12 17:34:29', now()-'Mon Jan 17 1966');
|
||||||
|
|
||||||
exec sql select * into :date1, :ts1 from date_test;
|
exec sql select * into :date1, :ts1 , :iv1 from date_test;
|
||||||
|
|
||||||
text = PGTYPESdate_dtoa(date1);
|
text = PGTYPESdate_dtoa(date1);
|
||||||
printf ("Date: %s\n", text);
|
printf ("Date: %s\n", text);
|
||||||
ts1 = PGTYPEStimestamp_atot("2000-7-12 17:34:29", NULL);
|
|
||||||
text = PGTYPEStimestamp_ttoa(ts1);
|
text = PGTYPEStimestamp_ttoa(ts1);
|
||||||
printf ("timestamp: %s\n", text);
|
printf ("timestamp: %s\n", text);
|
||||||
#if 0
|
|
||||||
|
text = PGTYPESinterval_itoa(&iv1);
|
||||||
|
printf ("interval: %s\n", text);
|
||||||
|
|
||||||
PGTYPESdate_mdyjul(mdy, &date2);
|
PGTYPESdate_mdyjul(mdy, &date2);
|
||||||
printf("m: %d, d: %d, y: %d\n", mdy[0], mdy[1], mdy[2]);
|
printf("m: %d, d: %d, y: %d\n", mdy[0], mdy[1], mdy[2]);
|
||||||
/* reset */
|
/* reset */
|
||||||
mdy[0] = mdy[1] = mdy[2] = 0;
|
mdy[0] = mdy[1] = mdy[2] = 0;
|
||||||
|
|
||||||
|
printf("date seems to get encoded to julian %ld\n", date2);
|
||||||
|
|
||||||
PGTYPESdate_julmdy(date2, mdy);
|
PGTYPESdate_julmdy(date2, mdy);
|
||||||
printf("m: %d, d: %d, y: %d\n", mdy[0], mdy[1], mdy[2]);
|
printf("m: %d, d: %d, y: %d\n", mdy[0], mdy[1], mdy[2]);
|
||||||
#endif
|
|
||||||
exec sql rollback;
|
ts1 = PGTYPEStimestamp_atot("2003-12-04 17:34:29", NULL);
|
||||||
|
text = PGTYPEStimestamp_ttoa(ts1);
|
||||||
|
|
||||||
|
printf("date_day of %s is %d\n", text, PGTYPESdate_dayofweek(ts1));
|
||||||
|
|
||||||
|
PGTYPESdate_today(&date1);
|
||||||
|
text = PGTYPESdate_dtoa(date1);
|
||||||
|
printf("today is %s\n", text);
|
||||||
|
|
||||||
|
fmt = "(ddd), mmm. dd, yyyy, repeat: (ddd), mmm. dd, yyyy. end";
|
||||||
|
out = (char*) malloc(strlen(fmt) + 1);
|
||||||
|
|
||||||
|
PGTYPESdate_fmtdate(date1, fmt, out);
|
||||||
|
printf("Today in format \"%s\" is \"%s\"\n", fmt, out);
|
||||||
|
free(out);
|
||||||
|
|
||||||
|
/* rdefmtdate() */
|
||||||
|
|
||||||
|
date1 = 0; text = "";
|
||||||
|
fmt = "yy/mm/dd";
|
||||||
|
in = "In the year 1995, the month of December, it is the 25th day";
|
||||||
|
/* 0123456789012345678901234567890123456789012345678901234567890
|
||||||
|
* 0 1 2 3 4 5 6
|
||||||
|
*/
|
||||||
|
PGTYPESdate_defmtdate(&date1, fmt, in);
|
||||||
|
text = PGTYPESdate_dtoa(date1);
|
||||||
|
printf("defmtdate1: %s\n", text);
|
||||||
|
|
||||||
|
date1 = 0; text = "";
|
||||||
|
fmt = "mmmm. dd. yyyy";
|
||||||
|
in = "12/25/95";
|
||||||
|
PGTYPESdate_defmtdate(&date1, fmt, in);
|
||||||
|
text = PGTYPESdate_dtoa(date1);
|
||||||
|
printf("defmtdate2: %s\n", text);
|
||||||
|
|
||||||
|
date1 = 0; text = "";
|
||||||
|
fmt = "yy/mm/dd";
|
||||||
|
in = "95/12/25";
|
||||||
|
PGTYPESdate_defmtdate(&date1, fmt, in);
|
||||||
|
text = PGTYPESdate_dtoa(date1);
|
||||||
|
printf("defmtdate3: %s\n", text);
|
||||||
|
|
||||||
|
date1 = 0; text = "";
|
||||||
|
fmt = "yy/mm/dd";
|
||||||
|
in = "1995, December 25th";
|
||||||
|
PGTYPESdate_defmtdate(&date1, fmt, in);
|
||||||
|
text = PGTYPESdate_dtoa(date1);
|
||||||
|
printf("defmtdate4: %s\n", text);
|
||||||
|
|
||||||
|
date1 = 0; text = "";
|
||||||
|
fmt = "dd-mm-yy";
|
||||||
|
in = "This is 25th day of December, 1995";
|
||||||
|
PGTYPESdate_defmtdate(&date1, fmt, in);
|
||||||
|
text = PGTYPESdate_dtoa(date1);
|
||||||
|
printf("defmtdate5: %s\n", text);
|
||||||
|
|
||||||
|
date1 = 0; text = "";
|
||||||
|
fmt = "mmddyy";
|
||||||
|
in = "Dec. 25th, 1995";
|
||||||
|
PGTYPESdate_defmtdate(&date1, fmt, in);
|
||||||
|
text = PGTYPESdate_dtoa(date1);
|
||||||
|
printf("defmtdate6: %s\n", text);
|
||||||
|
|
||||||
|
date1 = 0; text = "";
|
||||||
|
fmt = "mmm. dd. yyyy";
|
||||||
|
in = "dec 25th 1995";
|
||||||
|
PGTYPESdate_defmtdate(&date1, fmt, in);
|
||||||
|
text = PGTYPESdate_dtoa(date1);
|
||||||
|
printf("defmtdate7: %s\n", text);
|
||||||
|
|
||||||
|
date1 = 0; text = "";
|
||||||
|
fmt = "mmm. dd. yyyy";
|
||||||
|
in = "DEC-25-1995";
|
||||||
|
PGTYPESdate_defmtdate(&date1, fmt, in);
|
||||||
|
text = PGTYPESdate_dtoa(date1);
|
||||||
|
printf("defmtdate8: %s\n", text);
|
||||||
|
|
||||||
|
date1 = 0; text = "";
|
||||||
|
fmt = "mm yy dd.";
|
||||||
|
in = "12199525";
|
||||||
|
PGTYPESdate_defmtdate(&date1, fmt, in);
|
||||||
|
text = PGTYPESdate_dtoa(date1);
|
||||||
|
printf("defmtdate9: %s\n", text);
|
||||||
|
|
||||||
|
date1 = 0; text = "";
|
||||||
|
fmt = "yyyy fierj mm dd.";
|
||||||
|
in = "19951225";
|
||||||
|
PGTYPESdate_defmtdate(&date1, fmt, in);
|
||||||
|
text = PGTYPESdate_dtoa(date1);
|
||||||
|
printf("defmtdate10: %s\n", text);
|
||||||
|
|
||||||
|
date1 = 0; text = "";
|
||||||
|
fmt = "mm/dd/yy";
|
||||||
|
in = "122595";
|
||||||
|
PGTYPESdate_defmtdate(&date1, fmt, in);
|
||||||
|
text = PGTYPESdate_dtoa(date1);
|
||||||
|
printf("defmtdate12: %s\n", text);
|
||||||
|
|
||||||
|
exec sql rollback;
|
||||||
exec sql disconnect;
|
exec sql disconnect;
|
||||||
|
|
||||||
if (dbgs != NULL)
|
if (dbgs != NULL)
|
||||||
|
Reference in New Issue
Block a user