mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-03-01 19:45:33 +08:00
Moved Informix stuff to its own compat library. Interval datetype is now fully functional.
This commit is contained in:
parent
82a91eb54e
commit
999f12982e
@ -1376,7 +1376,17 @@ Thu Mar 27 15:23:58 CET 2003
|
||||
- Some more updates to pgtypeslib.
|
||||
- Set optimization to -O1 until I find the reason why code is broken
|
||||
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 library to 3.4.2.
|
||||
- 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 ecpglib $@
|
||||
$(MAKE) -C pgtypeslib $@
|
||||
$(MAKE) -C compatlib $@
|
||||
$(MAKE) -C preproc $@
|
||||
|
||||
clean distclean maintainer-clean:
|
||||
-$(MAKE) -C include $@
|
||||
-$(MAKE) -C ecpglib $@
|
||||
-$(MAKE) -C pgtypeslib $@
|
||||
-$(MAKE) -C compatlib $@
|
||||
-$(MAKE) -C preproc $@
|
||||
-$(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.
|
||||
@ -847,7 +847,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
|
||||
{
|
||||
for (element = 0; element < var->arrsize; element++)
|
||||
{
|
||||
str = PGTYPESnumeric_ntoa((Numeric *)((var + var->offset * element)->value));
|
||||
str = PGTYPESnumeric_ntoa((Numeric *)((var + var->offset * element)->value), 0);
|
||||
slen = strlen (str);
|
||||
|
||||
if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + 5, stmt->lineno)))
|
||||
@ -863,7 +863,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
|
||||
}
|
||||
else
|
||||
{
|
||||
str = PGTYPESnumeric_ntoa((Numeric *)(var->value));
|
||||
str = PGTYPESnumeric_ntoa((Numeric *)(var->value), 0);
|
||||
slen = strlen (str);
|
||||
|
||||
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",
|
||||
stmt->lineno, notify->relname, notify->be_pid);
|
||||
PQfreemem(notify);
|
||||
/* PQfreemem(notify);*/
|
||||
free(notify);
|
||||
#warning Remove PQfreemem define
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -2,6 +2,9 @@
|
||||
* This file contains stuff needed to be as compatible to Informix as possible.
|
||||
*/
|
||||
|
||||
#include <decimal.h>
|
||||
#include <datetime.h>
|
||||
|
||||
#define SQLNOTFOUND 100
|
||||
|
||||
#ifndef Date
|
||||
|
@ -1,12 +1,17 @@
|
||||
#ifndef PGTYPES_DATETIME
|
||||
#define PGTYPES_DATETIME
|
||||
|
||||
#include <pgtypes_timestamp.h>
|
||||
|
||||
#define Date long
|
||||
|
||||
extern Date PGTYPESdate_atod(char *, char **);
|
||||
extern char *PGTYPESdate_dtoa(Date);
|
||||
extern int PGTYPESdate_julmdy(Date, int*);
|
||||
extern int PGTYPESdate_mdyjul(int*, Date *);
|
||||
extern int PGTYPESdate_day(Date);
|
||||
|
||||
extern Date PGTYPESdate_ttod(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 *);
|
||||
#endif /* PGTYPES_DATETIME */
|
||||
|
@ -1,8 +1,15 @@
|
||||
#define PGTYPES_OVERFLOW 201
|
||||
#define PGTYPES_BAD_NUMERIC 202
|
||||
#define PGTYPES_DIVIDE_ZERO 203
|
||||
#define PGTYPES_NUM_OVERFLOW 201
|
||||
#define PGTYPES_NUM_BAD_NUMERIC 202
|
||||
#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);
|
||||
void PGTYPESnumeric_free(Numeric *);
|
||||
Numeric *PGTYPESnumeric_aton(char *, char **);
|
||||
char *PGTYPESnumeric_ntoa(Numeric *);
|
||||
char *PGTYPESnumeric_ntoa(Numeric *, int);
|
||||
int PGTYPESnumeric_add(Numeric *, Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_sub(Numeric *, Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_mul(Numeric *, Numeric *, Numeric *);
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
# 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)
|
||||
|
||||
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
|
||||
|
||||
|
@ -9,7 +9,31 @@
|
||||
#include "extern.h"
|
||||
#include "pgtypes_error.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
|
||||
PGTYPESdate_atod(char *str, char **endptr)
|
||||
@ -32,14 +56,14 @@ PGTYPESdate_atod(char *str, char **endptr)
|
||||
|
||||
if (strlen(str) >= sizeof(lowstr))
|
||||
{
|
||||
errno = PGTYPES_BAD_DATE;
|
||||
errno = PGTYPES_DATE_BAD_DATE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0)
|
||||
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp, EuroDates) != 0))
|
||||
{
|
||||
errno = PGTYPES_BAD_DATE;
|
||||
errno = PGTYPES_DATE_BAD_DATE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -53,7 +77,7 @@ PGTYPESdate_atod(char *str, char **endptr)
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = PGTYPES_BAD_DATE;
|
||||
errno = PGTYPES_DATE_BAD_DATE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -75,74 +99,521 @@ PGTYPESdate_dtoa(Date dDate)
|
||||
return pgtypes_strdup(buf);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
PGTYPESdate_julmdy(Date jd, int* mdy)
|
||||
{
|
||||
printf("day: %d\n", mdy[0]);
|
||||
printf("month: %d\n", mdy[1]);
|
||||
printf("year: %d\n", mdy[2]);
|
||||
j2date((int) jd, mdy+2, mdy+1, mdy+0);
|
||||
return 0;
|
||||
int y, m, d;
|
||||
|
||||
j2date((int) jd, &y, &m, &d);
|
||||
mdy[0] = (short int) m;
|
||||
mdy[1] = (short int) d;
|
||||
mdy[2] = (short int) y;
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
PGTYPESdate_mdyjul(int* mdy, Date *jdate)
|
||||
{
|
||||
/* month is mdy[0] */
|
||||
/* day is mdy[1] */
|
||||
/* 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]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PGTYPESdate_day(Date dDate)
|
||||
PGTYPESdate_dayofweek(Date dDate)
|
||||
{
|
||||
return j2day(dDate);
|
||||
}
|
||||
|
||||
int
|
||||
rdatestr (Date d, char *str)
|
||||
{
|
||||
return 0;
|
||||
/*
|
||||
Sunday: 0
|
||||
Monday: 1
|
||||
Tuesday: 2
|
||||
Wednesday: 3
|
||||
Thursday: 4
|
||||
Friday: 5
|
||||
Saturday: 6
|
||||
*/
|
||||
return 6-j2day(dDate+3);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#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
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
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;
|
||||
}
|
||||
|
||||
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 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);
|
||||
|
||||
|
@ -426,10 +426,81 @@ static datetkn datetktbl[] = {
|
||||
{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 szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
|
||||
|
||||
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 *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", NULL};
|
||||
@ -561,6 +632,39 @@ datebsearch(char *key, datetkn *base, unsigned int nel)
|
||||
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.
|
||||
* Julian date is commonly used in astronomical applications,
|
||||
@ -1088,7 +1192,7 @@ abstime2tm(AbsoluteTime _time, int *tzp, struct tm * tm, char **tzn)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
GetCurrentDateTime(struct tm * tm)
|
||||
{
|
||||
int tz;
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "c.h"
|
||||
#include "extern.h"
|
||||
#include "pgtypes_error.h"
|
||||
#include "decimal.h"
|
||||
|
||||
#define Max(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)
|
||||
{
|
||||
errno = PGTYPES_OVERFLOW;
|
||||
errno = PGTYPES_NUM_OVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -188,7 +187,7 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
|
||||
|
||||
if (!isdigit((unsigned char) *(*ptr)))
|
||||
{
|
||||
errno=PGTYPES_BAD_NUMERIC;
|
||||
errno=PGTYPES_NUM_BAD_NUMERIC;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -206,7 +205,7 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
|
||||
{
|
||||
if (have_dp)
|
||||
{
|
||||
errno = PGTYPES_BAD_NUMERIC;
|
||||
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||
return -1;
|
||||
}
|
||||
have_dp = TRUE;
|
||||
@ -227,14 +226,14 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
|
||||
exponent = strtol((*ptr), &endptr, 10);
|
||||
if (endptr == (*ptr))
|
||||
{
|
||||
errno = PGTYPES_BAD_NUMERIC;
|
||||
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||
return -1;
|
||||
}
|
||||
(*ptr) = endptr;
|
||||
if (exponent > NUMERIC_MAX_PRECISION ||
|
||||
exponent < -NUMERIC_MAX_PRECISION)
|
||||
{
|
||||
errno = PGTYPES_BAD_NUMERIC;
|
||||
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||
return -1;
|
||||
}
|
||||
dest->weight += (int) exponent;
|
||||
@ -248,7 +247,7 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
|
||||
{
|
||||
if (!isspace((unsigned char) *(*ptr)))
|
||||
{
|
||||
errno = PGTYPES_BAD_NUMERIC;
|
||||
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||
return -1;
|
||||
}
|
||||
(*ptr)++;
|
||||
@ -402,9 +401,12 @@ PGTYPESnumeric_aton(char *str, char **endptr)
|
||||
* ----------
|
||||
*/
|
||||
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;
|
||||
if (ndigits_tmp == 1)
|
||||
{
|
||||
errno= PGTYPES_DIVIDE_ZERO;
|
||||
errno= PGTYPES_NUM_DIVIDE_ZERO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1320,7 +1322,7 @@ PGTYPESnumeric_cmp(Numeric *var1, Numeric *var2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = PGTYPES_BAD_NUMERIC;
|
||||
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||
return INT_MAX;
|
||||
|
||||
}
|
||||
@ -1438,7 +1440,7 @@ numericvar_to_double_no_overflow(Numeric *var, double *dp)
|
||||
{
|
||||
/* shouldn't happen ... */
|
||||
free(tmp);
|
||||
errno = PGTYPES_BAD_NUMERIC;
|
||||
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||
return -1;
|
||||
}
|
||||
*dp = val;
|
||||
@ -1466,7 +1468,7 @@ PGTYPESnumeric_ntoi(Numeric* nv, int* ip) {
|
||||
return i;
|
||||
|
||||
if (l < -INT_MAX || l > INT_MAX) {
|
||||
errno = PGTYPES_OVERFLOW;
|
||||
errno = PGTYPES_NUM_OVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1488,7 +1490,7 @@ PGTYPESnumeric_ntol(Numeric* nv, long* lp) {
|
||||
l++;
|
||||
}
|
||||
if (l > LONG_MAX || l < 0) {
|
||||
errno = PGTYPES_OVERFLOW;
|
||||
errno = PGTYPES_NUM_OVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1499,196 +1501,3 @@ PGTYPESnumeric_ntol(Numeric* nv, long* lp) {
|
||||
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 "pgtypes_error.h"
|
||||
#include "pgtypes_timestamp.h"
|
||||
#include "pgtypes_interval.h"
|
||||
#include "datetime.h"
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
@ -288,14 +287,14 @@ PGTYPEStimestamp_atot(char *str, char **endptr)
|
||||
errno = 0;
|
||||
if (strlen(str) >= sizeof(lowstr))
|
||||
{
|
||||
errno = PGTYPES_BAD_TIMESTAMP;
|
||||
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||
return (noresult);
|
||||
}
|
||||
|
||||
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0)
|
||||
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz, 0) != 0))
|
||||
{
|
||||
errno = PGTYPES_BAD_TIMESTAMP;
|
||||
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||
return (noresult);
|
||||
}
|
||||
|
||||
@ -304,7 +303,7 @@ PGTYPEStimestamp_atot(char *str, char **endptr)
|
||||
case DTK_DATE:
|
||||
if (tm2timestamp(tm, fsec, NULL, &result) != 0)
|
||||
{
|
||||
errno = PGTYPES_BAD_TIMESTAMP;
|
||||
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||
return (noresult);;
|
||||
}
|
||||
break;
|
||||
@ -322,11 +321,11 @@ PGTYPEStimestamp_atot(char *str, char **endptr)
|
||||
break;
|
||||
|
||||
case DTK_INVALID:
|
||||
errno = PGTYPES_BAD_TIMESTAMP;
|
||||
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||
return (noresult);
|
||||
|
||||
default:
|
||||
errno = PGTYPES_BAD_TIMESTAMP;
|
||||
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||
return (noresult);
|
||||
}
|
||||
|
||||
@ -350,67 +349,8 @@ PGTYPEStimestamp_ttoa(Timestamp tstamp)
|
||||
EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf, 0);
|
||||
else
|
||||
{
|
||||
errno = PGTYPES_BAD_TIMESTAMP;
|
||||
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||
return NULL;
|
||||
}
|
||||
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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pgtypes_date.h>
|
||||
#include <pgtypes_timestamp.h>
|
||||
#include <pgtypes_interval.h>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
exec sql begin declare section;
|
||||
date date1;
|
||||
timestamp ts1;
|
||||
char *text;
|
||||
date date1;
|
||||
timestamp ts1;
|
||||
interval iv1;
|
||||
char *text;
|
||||
exec sql end declare section;
|
||||
#if 0
|
||||
Date date2;
|
||||
short int mdy[3] = { 4, 19, 1998 };
|
||||
#endif
|
||||
int mdy[3] = { 4, 19, 1998 };
|
||||
char *fmt, *out, *in;
|
||||
|
||||
FILE *dbgs;
|
||||
|
||||
if ((dbgs = fopen("log", "w")) != NULL)
|
||||
ECPGdebug(1, dbgs);
|
||||
exec sql whenever sqlerror do sqlprint();
|
||||
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);
|
||||
printf ("Date: %s\n", text);
|
||||
ts1 = PGTYPEStimestamp_atot("2000-7-12 17:34:29", NULL);
|
||||
|
||||
text = PGTYPEStimestamp_ttoa(ts1);
|
||||
printf ("timestamp: %s\n", text);
|
||||
#if 0
|
||||
|
||||
text = PGTYPESinterval_itoa(&iv1);
|
||||
printf ("interval: %s\n", text);
|
||||
|
||||
PGTYPESdate_mdyjul(mdy, &date2);
|
||||
printf("m: %d, d: %d, y: %d\n", mdy[0], mdy[1], mdy[2]);
|
||||
/* reset */
|
||||
mdy[0] = mdy[1] = mdy[2] = 0;
|
||||
|
||||
printf("date seems to get encoded to julian %ld\n", date2);
|
||||
|
||||
PGTYPESdate_julmdy(date2, mdy);
|
||||
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;
|
||||
|
||||
if (dbgs != NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user