mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
Started adding date and timestamp.
This commit is contained in:
@ -1360,6 +1360,10 @@ Sun Mar 16 11:28:01 CET 2003
|
|||||||
- Started with a pgtypes library.
|
- Started with a pgtypes library.
|
||||||
- Renamed lib directory to ecpglib.
|
- Renamed lib directory to ecpglib.
|
||||||
- Added numerical functions to library and preprocessor.
|
- Added numerical functions to library and preprocessor.
|
||||||
|
|
||||||
|
Don Mar 20 16:53:40 CET 2003
|
||||||
|
|
||||||
|
- Added date/timestamp to library and preprocessor.
|
||||||
- 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
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */
|
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.2 2003/03/20 15:56:50 meskes Exp $ */
|
||||||
|
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
|
|
||||||
@ -11,6 +11,8 @@
|
|||||||
#include "extern.h"
|
#include "extern.h"
|
||||||
#include "sqlca.h"
|
#include "sqlca.h"
|
||||||
#include "pgtypes_numeric.h"
|
#include "pgtypes_numeric.h"
|
||||||
|
#include "pgtypes_date.h"
|
||||||
|
#include "pgtypes_timestamp.h"
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
||||||
@ -99,6 +101,8 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
|||||||
double dres;
|
double dres;
|
||||||
char *scan_length;
|
char *scan_length;
|
||||||
NumericVar *nres;
|
NumericVar *nres;
|
||||||
|
Date ddres;
|
||||||
|
Timestamp tres;
|
||||||
|
|
||||||
case ECPGt_short:
|
case ECPGt_short:
|
||||||
case ECPGt_int:
|
case ECPGt_int:
|
||||||
@ -397,7 +401,51 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
|||||||
|
|
||||||
PGTYPESnumeric_copy(nres, (NumericVar *)(var + offset * act_tuple));
|
PGTYPESnumeric_copy(nres, (NumericVar *)(var + offset * act_tuple));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ECPGt_date:
|
||||||
|
if (pval)
|
||||||
|
{
|
||||||
|
if (isarray && *pval == '"')
|
||||||
|
ddres = PGTYPESdate_atod(pval + 1, &scan_length);
|
||||||
|
else
|
||||||
|
ddres = PGTYPESdate_atod(pval, &scan_length);
|
||||||
|
|
||||||
|
if (isarray && *scan_length == '"')
|
||||||
|
scan_length++;
|
||||||
|
|
||||||
|
if ((isarray && *scan_length != ',' && *scan_length != '}')
|
||||||
|
|| (!isarray && *scan_length != '\0')) /* Garbage left */
|
||||||
|
{
|
||||||
|
ECPGraise(lineno, ECPG_FLOAT_FORMAT, pval);
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
*((Date *)(var + offset * act_tuple)) = ddres;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ECPGt_timestamp:
|
||||||
|
if (pval)
|
||||||
|
{
|
||||||
|
if (isarray && *pval == '"')
|
||||||
|
tres = PGTYPEStimestamp_atot(pval + 1, &scan_length);
|
||||||
|
else
|
||||||
|
tres = PGTYPEStimestamp_atot(pval, &scan_length);
|
||||||
|
|
||||||
|
if (isarray && *scan_length == '"')
|
||||||
|
scan_length++;
|
||||||
|
|
||||||
|
if ((isarray && *scan_length != ',' && *scan_length != '}')
|
||||||
|
|| (!isarray && *scan_length != '\0')) /* Garbage left */
|
||||||
|
{
|
||||||
|
ECPGraise(lineno, ECPG_FLOAT_FORMAT, pval);
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
*((Timestamp *)(var + offset * act_tuple)) = tres;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ECPGraise(lineno, ECPG_UNSUPPORTED, ECPGtype_name(type));
|
ECPGraise(lineno, ECPG_UNSUPPORTED, ECPGtype_name(type));
|
||||||
return (false);
|
return (false);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.3 2003/03/19 16:05:41 petere Exp $ */
|
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.4 2003/03/20 15:56:50 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.
|
||||||
@ -27,6 +27,8 @@
|
|||||||
#include "sqlca.h"
|
#include "sqlca.h"
|
||||||
#include "sql3types.h"
|
#include "sql3types.h"
|
||||||
#include "pgtypes_numeric.h"
|
#include "pgtypes_numeric.h"
|
||||||
|
#include "pgtypes_date.h"
|
||||||
|
#include "pgtypes_timestamp.h"
|
||||||
|
|
||||||
/* variables visible to the programs */
|
/* variables visible to the programs */
|
||||||
struct sqlca sqlca =
|
struct sqlca sqlca =
|
||||||
@ -59,8 +61,7 @@ struct sqlca sqlca =
|
|||||||
/* This function returns a newly malloced string that has the \
|
/* This function returns a newly malloced string that has the \
|
||||||
in the argument quoted with \ and the ' quoted with ' as SQL92 says.
|
in the argument quoted with \ and the ' quoted with ' as SQL92 says.
|
||||||
*/
|
*/
|
||||||
static
|
static char *
|
||||||
char *
|
|
||||||
quote_postgres(char *arg, int lineno)
|
quote_postgres(char *arg, int lineno)
|
||||||
{
|
{
|
||||||
char *res = (char *) ECPGalloc(2 * strlen(arg) + 3, lineno);
|
char *res = (char *) ECPGalloc(2 * strlen(arg) + 3, lineno);
|
||||||
@ -876,6 +877,89 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
|
|||||||
free(str);
|
free(str);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ECPGt_date:
|
||||||
|
{
|
||||||
|
char *str = NULL;
|
||||||
|
int slen;
|
||||||
|
|
||||||
|
if (var->arrsize > 1)
|
||||||
|
{
|
||||||
|
for (element = 0; element < var->arrsize; element++)
|
||||||
|
{
|
||||||
|
str = PGTYPESdate_dtoa(*(Date *)((var + var->offset * element)->value));
|
||||||
|
slen = strlen (str);
|
||||||
|
|
||||||
|
if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + 5, stmt->lineno)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!element)
|
||||||
|
strcpy(mallocedval, "'{");
|
||||||
|
|
||||||
|
strncpy(mallocedval + strlen(mallocedval), str , slen + 1);
|
||||||
|
strcpy(mallocedval + strlen(mallocedval), ",");
|
||||||
|
}
|
||||||
|
strcpy(mallocedval + strlen(mallocedval) - 1, "}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str = PGTYPESdate_dtoa(*(Date *)(var->value));
|
||||||
|
slen = strlen (str);
|
||||||
|
|
||||||
|
if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
strncpy(mallocedval, str , slen);
|
||||||
|
mallocedval[slen] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
*tobeinserted_p = mallocedval;
|
||||||
|
*malloced_p = true;
|
||||||
|
free(str);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ECPGt_timestamp:
|
||||||
|
{
|
||||||
|
char *str = NULL;
|
||||||
|
int slen;
|
||||||
|
|
||||||
|
if (var->arrsize > 1)
|
||||||
|
{
|
||||||
|
for (element = 0; element < var->arrsize; element++)
|
||||||
|
{
|
||||||
|
str = PGTYPEStimestamp_ttoa(*(Timestamp *)((var + var->offset * element)->value));
|
||||||
|
slen = strlen (str);
|
||||||
|
|
||||||
|
if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + 5, stmt->lineno)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!element)
|
||||||
|
strcpy(mallocedval, "'{");
|
||||||
|
|
||||||
|
strncpy(mallocedval + strlen(mallocedval), str , slen + 1);
|
||||||
|
strcpy(mallocedval + strlen(mallocedval), ",");
|
||||||
|
}
|
||||||
|
strcpy(mallocedval + strlen(mallocedval) - 1, "}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str = PGTYPEStimestamp_ttoa(*(Timestamp *)(var->value));
|
||||||
|
slen = strlen (str);
|
||||||
|
|
||||||
|
if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
strncpy(mallocedval, str , slen);
|
||||||
|
mallocedval[slen] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
*tobeinserted_p = mallocedval;
|
||||||
|
*malloced_p = true;
|
||||||
|
free(str);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Not implemented yet */
|
/* Not implemented yet */
|
||||||
ECPGraise(stmt->lineno, ECPG_UNSUPPORTED, (char *) ECPGtype_name(var->type));
|
ECPGraise(stmt->lineno, ECPG_UNSUPPORTED, (char *) ECPGtype_name(var->type));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/typename.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */
|
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/typename.c,v 1.2 2003/03/20 15:56:50 meskes Exp $ */
|
||||||
|
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
|
|
||||||
@ -49,6 +49,10 @@ ECPGtype_name(enum ECPGttype typ)
|
|||||||
return "char";
|
return "char";
|
||||||
case ECPGt_numeric:
|
case ECPGt_numeric:
|
||||||
return "numeric";
|
return "numeric";
|
||||||
|
case ECPGt_date:
|
||||||
|
return "date";
|
||||||
|
case ECPGt_timestamp:
|
||||||
|
return "timestamp";
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -2,4 +2,14 @@
|
|||||||
|
|
||||||
#ifndef dec_t
|
#ifndef dec_t
|
||||||
#define dec_t NumericVar
|
#define dec_t NumericVar
|
||||||
|
|
||||||
|
#define CSHORTTYPE 0
|
||||||
|
#define CMONEYTYPE 0
|
||||||
|
#define CCHARTYPE 0
|
||||||
|
#define CDECIMALTYPE 0
|
||||||
|
#define CINTTYPE 0
|
||||||
|
#define CDATETYPE 0
|
||||||
|
#define CDOUBLETYPE 0
|
||||||
|
#define CLONGTYPE 0
|
||||||
|
|
||||||
#endif /* dec_t */
|
#endif /* dec_t */
|
||||||
|
@ -52,7 +52,9 @@ enum ECPGttype
|
|||||||
ECPGt_NO_INDICATOR, /* no indicator */
|
ECPGt_NO_INDICATOR, /* no indicator */
|
||||||
ECPGt_long_long, ECPGt_unsigned_long_long,
|
ECPGt_long_long, ECPGt_unsigned_long_long,
|
||||||
ECPGt_descriptor, /* sql descriptor, no C variable */
|
ECPGt_descriptor, /* sql descriptor, no C variable */
|
||||||
ECPGt_numeric
|
ECPGt_numeric,
|
||||||
|
ECPGt_date,
|
||||||
|
ECPGt_timestamp
|
||||||
};
|
};
|
||||||
|
|
||||||
/* descriptor items */
|
/* descriptor items */
|
||||||
|
12
src/interfaces/ecpg/include/pgtypes_date.h
Normal file
12
src/interfaces/ecpg/include/pgtypes_date.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef PGTYPES_DATETIME
|
||||||
|
#define PGTYPES_DATETIME
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
#endif /* PGTYPES_DATETIME */
|
@ -2,5 +2,7 @@
|
|||||||
#define PGTYPES_BAD_NUMERIC 202
|
#define PGTYPES_BAD_NUMERIC 202
|
||||||
#define PGTYPES_DIVIDE_ZERO 203
|
#define PGTYPES_DIVIDE_ZERO 203
|
||||||
|
|
||||||
#define PGTYPES_BAD_DATE 300
|
#define PGTYPES_BAD_DATE 210
|
||||||
|
|
||||||
|
#define PGTYPES_BAD_TIMESTAMP 220
|
||||||
|
|
||||||
|
16
src/interfaces/ecpg/include/pgtypes_timestamp.h
Normal file
16
src/interfaces/ecpg/include/pgtypes_timestamp.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef PGTYPES_TIMESTAMP
|
||||||
|
#define PGTYPES_TIMESTAMP
|
||||||
|
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
typedef int64 Timestamp;
|
||||||
|
typedef int64 TimestampTz;
|
||||||
|
|
||||||
|
#else
|
||||||
|
typedef double Timestamp;
|
||||||
|
typedef double TimestampTz;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern Timestamp PGTYPEStimestamp_atot(char *, char **);
|
||||||
|
extern char *PGTYPEStimestamp_ttoa(Timestamp);
|
||||||
|
|
||||||
|
#endif /* PGTYPES_TIMESTAMP */
|
@ -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.1 2003/03/16 10:42:54 meskes Exp $
|
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/pgtypeslib/Makefile,v 1.2 2003/03/20 15:56:50 meskes Exp $
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ SO_MINOR_VERSION= 0.0
|
|||||||
|
|
||||||
override CPPFLAGS := -g -I$(top_srcdir)/src/interfaces/ecpg/include -I$(top_srcdir)/src/include/utils $(CPPFLAGS)
|
override CPPFLAGS := -g -I$(top_srcdir)/src/interfaces/ecpg/include -I$(top_srcdir)/src/include/utils $(CPPFLAGS)
|
||||||
|
|
||||||
OBJS= numeric.o
|
OBJS= numeric.o datetime.o common.o dt_common.o timestamp.o
|
||||||
|
|
||||||
all: all-lib
|
all: all-lib
|
||||||
|
|
||||||
|
29
src/interfaces/ecpg/pgtypeslib/common.c
Normal file
29
src/interfaces/ecpg/pgtypeslib/common.c
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "extern.h"
|
||||||
|
|
||||||
|
char *
|
||||||
|
pgtypes_alloc(long size)
|
||||||
|
{
|
||||||
|
char *new = (char *) calloc(1L, size);
|
||||||
|
|
||||||
|
if (!new)
|
||||||
|
{
|
||||||
|
errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(new, '\0', size);
|
||||||
|
return (new);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
pgtypes_strdup(char *str)
|
||||||
|
{
|
||||||
|
char *new = (char *) strdup(str);
|
||||||
|
|
||||||
|
if (!new)
|
||||||
|
errno = ENOMEM;
|
||||||
|
return (new);
|
||||||
|
}
|
||||||
|
|
105
src/interfaces/ecpg/pgtypeslib/datetime.c
Normal file
105
src/interfaces/ecpg/pgtypeslib/datetime.c
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "dt.h"
|
||||||
|
#include "extern.h"
|
||||||
|
#include "pgtypes_error.h"
|
||||||
|
#include "pgtypes_date.h"
|
||||||
|
|
||||||
|
Date
|
||||||
|
PGTYPESdate_atod(char *str, char **endptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
Date dDate;
|
||||||
|
fsec_t fsec;
|
||||||
|
struct tm tt,
|
||||||
|
*tm = &tt;
|
||||||
|
int tzp;
|
||||||
|
int dtype;
|
||||||
|
int nf;
|
||||||
|
char *field[MAXDATEFIELDS];
|
||||||
|
int ftype[MAXDATEFIELDS];
|
||||||
|
char lowstr[MAXDATELEN + 1];
|
||||||
|
char *realptr;
|
||||||
|
char **ptr = (endptr != NULL) ? endptr : &realptr;
|
||||||
|
|
||||||
|
bool EuroDates = FALSE;
|
||||||
|
|
||||||
|
if (strlen(str) >= sizeof(lowstr))
|
||||||
|
{
|
||||||
|
errno = PGTYPES_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;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dtype)
|
||||||
|
{
|
||||||
|
case DTK_DATE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DTK_EPOCH:
|
||||||
|
GetEpochTime(tm);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errno = PGTYPES_BAD_DATE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dDate = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1));
|
||||||
|
|
||||||
|
return dDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
PGTYPESdate_dtoa(Date dDate)
|
||||||
|
{
|
||||||
|
struct tm tt, *tm = &tt;
|
||||||
|
char buf[MAXDATELEN + 1];
|
||||||
|
int DateStyle=0;
|
||||||
|
bool EuroDates = FALSE;
|
||||||
|
|
||||||
|
j2date((dDate + date2j(2000, 1, 1)), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
|
||||||
|
EncodeDateOnly(tm, DateStyle, buf, EuroDates);
|
||||||
|
return pgtypes_strdup(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
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
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return j2day(dDate);
|
||||||
|
}
|
||||||
|
|
303
src/interfaces/ecpg/pgtypeslib/dt.h
Normal file
303
src/interfaces/ecpg/pgtypeslib/dt.h
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
#ifndef DT_H
|
||||||
|
#define DT_H
|
||||||
|
|
||||||
|
#define MAXTZLEN 10
|
||||||
|
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
|
||||||
|
typedef int32 fsec_t;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef double fsec_t;
|
||||||
|
|
||||||
|
#define TIME_PREC_INV 1000000.0
|
||||||
|
#define JROUND(j) (rint(((double) (j))*TIME_PREC_INV)/TIME_PREC_INV)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef bool
|
||||||
|
#define bool char
|
||||||
|
#endif /* ndef bool */
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif /* FALSE */
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif /* TRUE */
|
||||||
|
|
||||||
|
#define USE_POSTGRES_DATES 0
|
||||||
|
#define USE_ISO_DATES 1
|
||||||
|
#define USE_SQL_DATES 2
|
||||||
|
#define USE_GERMAN_DATES 3
|
||||||
|
|
||||||
|
#define DAGO "ago"
|
||||||
|
#define EPOCH "epoch"
|
||||||
|
#define INVALID "invalid"
|
||||||
|
#define EARLY "-infinity"
|
||||||
|
#define LATE "infinity"
|
||||||
|
#define NOW "now"
|
||||||
|
#define TODAY "today"
|
||||||
|
#define TOMORROW "tomorrow"
|
||||||
|
#define YESTERDAY "yesterday"
|
||||||
|
#define ZULU "zulu"
|
||||||
|
|
||||||
|
#define DMICROSEC "usecond"
|
||||||
|
#define DMILLISEC "msecond"
|
||||||
|
#define DSECOND "second"
|
||||||
|
#define DMINUTE "minute"
|
||||||
|
#define DHOUR "hour"
|
||||||
|
#define DDAY "day"
|
||||||
|
#define DWEEK "week"
|
||||||
|
#define DMONTH "month"
|
||||||
|
#define DQUARTER "quarter"
|
||||||
|
#define DYEAR "year"
|
||||||
|
#define DDECADE "decade"
|
||||||
|
#define DCENTURY "century"
|
||||||
|
#define DMILLENNIUM "millennium"
|
||||||
|
#define DA_D "ad"
|
||||||
|
#define DB_C "bc"
|
||||||
|
#define DTIMEZONE "timezone"
|
||||||
|
#define DCURRENT "current"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fundamental time field definitions for parsing.
|
||||||
|
*
|
||||||
|
* Meridian: am, pm, or 24-hour style.
|
||||||
|
* Millennium: ad, bc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define AM 0
|
||||||
|
#define PM 1
|
||||||
|
#define HR24 2
|
||||||
|
|
||||||
|
#define AD 0
|
||||||
|
#define BC 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fields for time decoding.
|
||||||
|
*
|
||||||
|
* Can't have more of these than there are bits in an unsigned int
|
||||||
|
* since these are turned into bit masks during parsing and decoding.
|
||||||
|
*
|
||||||
|
* Furthermore, the values for YEAR, MONTH, DAY, HOUR, MINUTE, SECOND
|
||||||
|
* must be in the range 0..14 so that the associated bitmasks can fit
|
||||||
|
* into the left half of an INTERVAL's typmod value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RESERV 0
|
||||||
|
#define MONTH 1
|
||||||
|
#define YEAR 2
|
||||||
|
#define DAY 3
|
||||||
|
#define JULIAN 4
|
||||||
|
#define TZ 5
|
||||||
|
#define DTZ 6
|
||||||
|
#define DTZMOD 7
|
||||||
|
#define IGNORE_DTF 8
|
||||||
|
#define AMPM 9
|
||||||
|
#define HOUR 10
|
||||||
|
#define MINUTE 11
|
||||||
|
#define SECOND 12
|
||||||
|
#define DOY 13
|
||||||
|
#define DOW 14
|
||||||
|
#define UNITS 15
|
||||||
|
#define ADBC 16
|
||||||
|
/* these are only for relative dates */
|
||||||
|
#define AGO 17
|
||||||
|
#define ABS_BEFORE 18
|
||||||
|
#define ABS_AFTER 19
|
||||||
|
/* generic fields to help with parsing */
|
||||||
|
#define ISODATE 20
|
||||||
|
#define ISOTIME 21
|
||||||
|
/* reserved for unrecognized string values */
|
||||||
|
#define UNKNOWN_FIELD 31
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Token field definitions for time parsing and decoding.
|
||||||
|
* These need to fit into the datetkn table type.
|
||||||
|
* At the moment, that means keep them within [-127,127].
|
||||||
|
* These are also used for bit masks in DecodeDateDelta()
|
||||||
|
* so actually restrict them to within [0,31] for now.
|
||||||
|
* - thomas 97/06/19
|
||||||
|
* Not all of these fields are used for masks in DecodeDateDelta
|
||||||
|
* so allow some larger than 31. - thomas 1997-11-17
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DTK_NUMBER 0
|
||||||
|
#define DTK_STRING 1
|
||||||
|
|
||||||
|
#define DTK_DATE 2
|
||||||
|
#define DTK_TIME 3
|
||||||
|
#define DTK_TZ 4
|
||||||
|
#define DTK_AGO 5
|
||||||
|
|
||||||
|
#define DTK_SPECIAL 6
|
||||||
|
#define DTK_INVALID 7
|
||||||
|
#define DTK_CURRENT 8
|
||||||
|
#define DTK_EARLY 9
|
||||||
|
#define DTK_LATE 10
|
||||||
|
#define DTK_EPOCH 11
|
||||||
|
#define DTK_NOW 12
|
||||||
|
#define DTK_YESTERDAY 13
|
||||||
|
#define DTK_TODAY 14
|
||||||
|
#define DTK_TOMORROW 15
|
||||||
|
#define DTK_ZULU 16
|
||||||
|
|
||||||
|
#define DTK_DELTA 17
|
||||||
|
#define DTK_SECOND 18
|
||||||
|
#define DTK_MINUTE 19
|
||||||
|
#define DTK_HOUR 20
|
||||||
|
#define DTK_DAY 21
|
||||||
|
#define DTK_WEEK 22
|
||||||
|
#define DTK_MONTH 23
|
||||||
|
#define DTK_QUARTER 24
|
||||||
|
#define DTK_YEAR 25
|
||||||
|
#define DTK_DECADE 26
|
||||||
|
#define DTK_CENTURY 27
|
||||||
|
#define DTK_MILLENNIUM 28
|
||||||
|
#define DTK_MILLISEC 29
|
||||||
|
#define DTK_MICROSEC 30
|
||||||
|
#define DTK_JULIAN 31
|
||||||
|
|
||||||
|
#define DTK_DOW 32
|
||||||
|
#define DTK_DOY 33
|
||||||
|
#define DTK_TZ_HOUR 34
|
||||||
|
#define DTK_TZ_MINUTE 35
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bit mask definitions for time parsing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DTK_M(t) (0x01 << (t))
|
||||||
|
|
||||||
|
#define DTK_DATE_M (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY))
|
||||||
|
#define DTK_TIME_M (DTK_M(HOUR) | DTK_M(MINUTE) | DTK_M(SECOND))
|
||||||
|
|
||||||
|
#define MAXDATELEN 51 /* maximum possible length of an input
|
||||||
|
* date string (not counting tr. null) */
|
||||||
|
#define MAXDATEFIELDS 25 /* maximum possible number of fields in a
|
||||||
|
* date string */
|
||||||
|
#define TOKMAXLEN 10 /* only this many chars are stored in
|
||||||
|
* datetktbl */
|
||||||
|
|
||||||
|
/* keep this struct small; it gets used a lot */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
#if defined(_AIX)
|
||||||
|
char *token;
|
||||||
|
#else
|
||||||
|
char token[TOKMAXLEN];
|
||||||
|
#endif /* _AIX */
|
||||||
|
char type;
|
||||||
|
char value; /* this may be unsigned, alas */
|
||||||
|
} datetkn;
|
||||||
|
|
||||||
|
|
||||||
|
/* TMODULO()
|
||||||
|
* Macro to replace modf(), which is broken on some platforms.
|
||||||
|
* t = input and remainder
|
||||||
|
* q = integer part
|
||||||
|
* u = divisor
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
#define TMODULO(t,q,u) \
|
||||||
|
do { \
|
||||||
|
q = (t / u); \
|
||||||
|
if (q != 0) t -= (q * u); \
|
||||||
|
} while(0)
|
||||||
|
#else
|
||||||
|
#define TMODULO(t,q,u) \
|
||||||
|
do { \
|
||||||
|
q = ((t < 0)? ceil(t / u): floor(t / u)); \
|
||||||
|
if (q != 0) t -= rint(q * u); \
|
||||||
|
} while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Global variable holding time zone information. */
|
||||||
|
#if defined(__CYGWIN__) || defined(N_PLAT_NLM)
|
||||||
|
#define TIMEZONE_GLOBAL _timezone
|
||||||
|
#else
|
||||||
|
#define TIMEZONE_GLOBAL timezone
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Date/time validation
|
||||||
|
* Include check for leap year.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int day_tab[2][13];
|
||||||
|
|
||||||
|
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
|
||||||
|
|
||||||
|
/* Julian date support for date2j() and j2date()
|
||||||
|
* Set the minimum year to one greater than the year of the first valid day
|
||||||
|
* to avoid having to check year and day both. - tgl 97/05/08
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define JULIAN_MINYEAR (-4713)
|
||||||
|
#define JULIAN_MINMONTH (11)
|
||||||
|
#define JULIAN_MINDAY (24)
|
||||||
|
|
||||||
|
#define IS_VALID_JULIAN(y,m,d) (((y) > JULIAN_MINYEAR) \
|
||||||
|
|| (((y) == JULIAN_MINYEAR) && (((m) > JULIAN_MINMONTH) \
|
||||||
|
|| (((m) == JULIAN_MINMONTH) && ((d) >= JULIAN_MINDAY)))))
|
||||||
|
|
||||||
|
#define UTIME_MINYEAR (1901)
|
||||||
|
#define UTIME_MINMONTH (12)
|
||||||
|
#define UTIME_MINDAY (14)
|
||||||
|
#define UTIME_MAXYEAR (2038)
|
||||||
|
#define UTIME_MAXMONTH (01)
|
||||||
|
#define UTIME_MAXDAY (18)
|
||||||
|
|
||||||
|
#define IS_VALID_UTIME(y,m,d) ((((y) > UTIME_MINYEAR) \
|
||||||
|
|| (((y) == UTIME_MINYEAR) && (((m) > UTIME_MINMONTH) \
|
||||||
|
|| (((m) == UTIME_MINMONTH) && ((d) >= UTIME_MINDAY))))) \
|
||||||
|
&& (((y) < UTIME_MAXYEAR) \
|
||||||
|
|| (((y) == UTIME_MAXYEAR) && (((m) < UTIME_MAXMONTH) \
|
||||||
|
|| (((m) == UTIME_MAXMONTH) && ((d) <= UTIME_MAXDAY))))))
|
||||||
|
|
||||||
|
#ifdef HUGE_VAL
|
||||||
|
#define DT_NOBEGIN (-HUGE_VAL)
|
||||||
|
#define DT_NOEND (HUGE_VAL)
|
||||||
|
#else
|
||||||
|
#define DT_NOBEGIN (-DBL_MAX)
|
||||||
|
#define DT_NOEND (DBL_MAX)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TIMESTAMP_NOBEGIN(j) do {j = DT_NOBEGIN;} while (0)
|
||||||
|
#define TIMESTAMP_NOEND(j) do {j = DT_NOEND;} while (0)
|
||||||
|
#define TIMESTAMP_IS_NOBEGIN(j) ((j) == DT_NOBEGIN)
|
||||||
|
#define TIMESTAMP_IS_NOEND(j) ((j) == DT_NOEND)
|
||||||
|
#define TIMESTAMP_NOT_FINITE(j) (TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j))
|
||||||
|
|
||||||
|
extern int DecodeTimeOnly(char **field, int *ftype,
|
||||||
|
int nf, int *dtype,
|
||||||
|
struct tm * tm, fsec_t *fsec, int *tzp);
|
||||||
|
|
||||||
|
extern int DecodeInterval(char **field, int *ftype,
|
||||||
|
int nf, int *dtype,
|
||||||
|
struct tm * tm, fsec_t *fsec);
|
||||||
|
|
||||||
|
extern int EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str);
|
||||||
|
extern int EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str, bool);
|
||||||
|
extern int EncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str);
|
||||||
|
|
||||||
|
extern int DecodeUnits(int field, char *lowtoken, int *val);
|
||||||
|
extern bool ClearDateCache(bool, bool, bool);
|
||||||
|
|
||||||
|
extern int j2day(int jd);
|
||||||
|
|
||||||
|
extern bool CheckDateTokenTables(void);
|
||||||
|
|
||||||
|
extern int EncodeDateOnly(struct tm *, int, char *, bool);
|
||||||
|
extern void GetEpochTime(struct tm *);
|
||||||
|
extern int ParseDateTime(char *, char *, char **, int *, int, int *, char **);
|
||||||
|
extern int DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, int *, bool);
|
||||||
|
extern void j2date(int, int *, int *, int *);
|
||||||
|
extern int date2j(int, int, int);
|
||||||
|
extern double rint(double x);
|
||||||
|
|
||||||
|
#endif /* DT_H */
|
||||||
|
|
2558
src/interfaces/ecpg/pgtypeslib/dt_common.c
Normal file
2558
src/interfaces/ecpg/pgtypeslib/dt_common.c
Normal file
File diff suppressed because it is too large
Load Diff
4
src/interfaces/ecpg/pgtypeslib/extern.h
Normal file
4
src/interfaces/ecpg/pgtypeslib/extern.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
extern char *pgtypes_alloc(long);
|
||||||
|
extern char *pgtypes_strdup(char *);
|
@ -5,9 +5,9 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "c.h"
|
#include "c.h"
|
||||||
|
#include "extern.h"
|
||||||
#include "numeric.h"
|
#include "numeric.h"
|
||||||
#include "pgtypes_error.h"
|
#include "pgtypes_error.h"
|
||||||
|
|
||||||
@ -25,21 +25,6 @@
|
|||||||
|
|
||||||
#include "pgtypes_numeric.h"
|
#include "pgtypes_numeric.h"
|
||||||
|
|
||||||
static char *
|
|
||||||
pgtypes_alloc(long size)
|
|
||||||
{
|
|
||||||
char *new = (char *) calloc(1L, size);
|
|
||||||
|
|
||||||
if (!new)
|
|
||||||
{
|
|
||||||
errno = ENOMEM;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(new, '\0', size);
|
|
||||||
return (new);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* ----------
|
/* ----------
|
||||||
* apply_typmod() -
|
* apply_typmod() -
|
||||||
|
356
src/interfaces/ecpg/pgtypeslib/timestamp.c
Normal file
356
src/interfaces/ecpg/pgtypeslib/timestamp.c
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __FAST_MATH__
|
||||||
|
#error -ffast-math is known to break this code
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "dt.h"
|
||||||
|
#include "extern.h"
|
||||||
|
#include "pgtypes_error.h"
|
||||||
|
#include "pgtypes_timestamp.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
static int64
|
||||||
|
time2t(const int hour, const int min, const int sec, const fsec_t fsec)
|
||||||
|
{
|
||||||
|
return ((((((hour * 60) + min) * 60) + sec) * INT64CONST(1000000)) + fsec);
|
||||||
|
} /* time2t() */
|
||||||
|
|
||||||
|
#else
|
||||||
|
static double
|
||||||
|
time2t(const int hour, const int min, const int sec, const fsec_t fsec)
|
||||||
|
{
|
||||||
|
return ((((hour * 60) + min) * 60) + sec + fsec);
|
||||||
|
} /* time2t() */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static Timestamp
|
||||||
|
dt2local(Timestamp dt, int tz)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
dt -= (tz * INT64CONST(1000000));
|
||||||
|
#else
|
||||||
|
dt -= tz;
|
||||||
|
dt = JROUND(dt);
|
||||||
|
#endif
|
||||||
|
return dt;
|
||||||
|
} /* dt2local() */
|
||||||
|
|
||||||
|
/* tm2timestamp()
|
||||||
|
* Convert a tm structure to a timestamp data type.
|
||||||
|
* Note that year is _not_ 1900-based, but is an explicit full value.
|
||||||
|
* Also, month is one-based, _not_ zero-based.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
tm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, Timestamp *result)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
int date;
|
||||||
|
int64 time;
|
||||||
|
|
||||||
|
#else
|
||||||
|
double date,
|
||||||
|
time;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Julian day routines are not correct for negative Julian days */
|
||||||
|
if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
|
||||||
|
time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
*result = ((date * INT64CONST(86400000000)) + time);
|
||||||
|
if ((*result < 0 && date >= 0) || (*result >= 0 && date < 0))
|
||||||
|
elog(ERROR, "TIMESTAMP out of range '%04d-%02d-%02d'",
|
||||||
|
tm->tm_year, tm->tm_mon, tm->tm_mday);
|
||||||
|
#else
|
||||||
|
*result = ((date * 86400) + time);
|
||||||
|
#endif
|
||||||
|
if (tzp != NULL)
|
||||||
|
*result = dt2local(*result, -(*tzp));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} /* tm2timestamp() */
|
||||||
|
|
||||||
|
static Timestamp
|
||||||
|
SetEpochTimestamp(void)
|
||||||
|
{
|
||||||
|
Timestamp dt;
|
||||||
|
struct tm tt, *tm = &tt;
|
||||||
|
|
||||||
|
GetEpochTime(tm);
|
||||||
|
tm2timestamp(tm, 0, NULL, &dt);
|
||||||
|
return dt;
|
||||||
|
} /* SetEpochTimestamp() */
|
||||||
|
|
||||||
|
static void
|
||||||
|
dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
int64 time;
|
||||||
|
#else
|
||||||
|
double time;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
time = jd;
|
||||||
|
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
*hour = (time / INT64CONST(3600000000));
|
||||||
|
time -= ((*hour) * INT64CONST(3600000000));
|
||||||
|
*min = (time / INT64CONST(60000000));
|
||||||
|
time -= ((*min) * INT64CONST(60000000));
|
||||||
|
*sec = (time / INT64CONST(1000000));
|
||||||
|
*fsec = (time - (*sec * INT64CONST(1000000)));
|
||||||
|
*sec = (time / INT64CONST(1000000));
|
||||||
|
*fsec = (time - (*sec * INT64CONST(1000000)));
|
||||||
|
#else
|
||||||
|
*hour = (time / 3600);
|
||||||
|
time -= ((*hour) * 3600);
|
||||||
|
*min = (time / 60);
|
||||||
|
time -= ((*min) * 60);
|
||||||
|
*sec = time;
|
||||||
|
*fsec = JROUND(time - *sec);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
} /* dt2time() */
|
||||||
|
|
||||||
|
/* timestamp2tm()
|
||||||
|
* Convert timestamp data type to POSIX time structure.
|
||||||
|
* Note that year is _not_ 1900-based, but is an explicit full value.
|
||||||
|
* Also, month is one-based, _not_ zero-based.
|
||||||
|
* Returns:
|
||||||
|
* 0 on success
|
||||||
|
* -1 on out of range
|
||||||
|
*
|
||||||
|
* For dates within the system-supported time_t range, convert to the
|
||||||
|
* local time zone. If out of this range, leave as GMT. - tgl 97/05/27
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, fsec_t *fsec, char **tzn)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
int date,
|
||||||
|
date0;
|
||||||
|
int64 time;
|
||||||
|
|
||||||
|
#else
|
||||||
|
double date,
|
||||||
|
date0;
|
||||||
|
double time;
|
||||||
|
#endif
|
||||||
|
time_t utime;
|
||||||
|
|
||||||
|
#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
|
||||||
|
struct tm *tx;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
date0 = date2j(2000, 1, 1);
|
||||||
|
|
||||||
|
time = dt;
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
TMODULO(time, date, INT64CONST(86400000000));
|
||||||
|
|
||||||
|
if (time < INT64CONST(0))
|
||||||
|
{
|
||||||
|
time += INT64CONST(86400000000);
|
||||||
|
date -= 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
TMODULO(time, date, 86400e0);
|
||||||
|
|
||||||
|
if (time < 0)
|
||||||
|
{
|
||||||
|
time += 86400;
|
||||||
|
date -= 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Julian day routine does not work for negative Julian days */
|
||||||
|
if (date < -date0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* add offset to go from J2000 back to standard Julian date */
|
||||||
|
date += date0;
|
||||||
|
|
||||||
|
j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
||||||
|
dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
|
||||||
|
|
||||||
|
if (tzp != NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Does this fall within the capabilities of the localtime()
|
||||||
|
* interface? Then use this to rotate to the local time zone.
|
||||||
|
*/
|
||||||
|
if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
|
||||||
|
{
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
utime = ((dt / INT64CONST(1000000))
|
||||||
|
+ ((date0 - date2j(1970, 1, 1)) * INT64CONST(86400)));
|
||||||
|
#else
|
||||||
|
utime = (dt + ((date0 - date2j(1970, 1, 1)) * 86400));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
|
||||||
|
tx = localtime(&utime);
|
||||||
|
tm->tm_year = tx->tm_year + 1900;
|
||||||
|
tm->tm_mon = tx->tm_mon + 1;
|
||||||
|
tm->tm_mday = tx->tm_mday;
|
||||||
|
tm->tm_hour = tx->tm_hour;
|
||||||
|
tm->tm_min = tx->tm_min;
|
||||||
|
tm->tm_isdst = tx->tm_isdst;
|
||||||
|
|
||||||
|
#if defined(HAVE_TM_ZONE)
|
||||||
|
tm->tm_gmtoff = tx->tm_gmtoff;
|
||||||
|
tm->tm_zone = tx->tm_zone;
|
||||||
|
|
||||||
|
*tzp = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */
|
||||||
|
if (tzn != NULL)
|
||||||
|
*tzn = (char *) tm->tm_zone;
|
||||||
|
#elif defined(HAVE_INT_TIMEZONE)
|
||||||
|
*tzp = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL);
|
||||||
|
if (tzn != NULL)
|
||||||
|
*tzn = tzname[(tm->tm_isdst > 0)];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */
|
||||||
|
*tzp = 0;
|
||||||
|
/* Mark this as *no* time zone available */
|
||||||
|
tm->tm_isdst = -1;
|
||||||
|
if (tzn != NULL)
|
||||||
|
*tzn = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dt = dt2local(dt, *tzp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*tzp = 0;
|
||||||
|
/* Mark this as *no* time zone available */
|
||||||
|
tm->tm_isdst = -1;
|
||||||
|
if (tzn != NULL)
|
||||||
|
*tzn = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tm->tm_isdst = -1;
|
||||||
|
if (tzn != NULL)
|
||||||
|
*tzn = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} /* timestamp2tm() */
|
||||||
|
|
||||||
|
/* EncodeSpecialTimestamp()
|
||||||
|
* * Convert reserved timestamp data type to string.
|
||||||
|
* */
|
||||||
|
static int
|
||||||
|
EncodeSpecialTimestamp(Timestamp dt, char *str)
|
||||||
|
{
|
||||||
|
if (TIMESTAMP_IS_NOBEGIN(dt))
|
||||||
|
strcpy(str, EARLY);
|
||||||
|
else if (TIMESTAMP_IS_NOEND(dt))
|
||||||
|
strcpy(str, LATE);
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
} /* EncodeSpecialTimestamp() */
|
||||||
|
|
||||||
|
Timestamp
|
||||||
|
PGTYPEStimestamp_atot(char *str, char **endptr)
|
||||||
|
{
|
||||||
|
Timestamp result;
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
int64 noresult = 0;
|
||||||
|
#else
|
||||||
|
double noresult = 0.0;
|
||||||
|
#endif
|
||||||
|
fsec_t fsec;
|
||||||
|
struct tm tt, *tm = &tt;
|
||||||
|
int tz;
|
||||||
|
int dtype;
|
||||||
|
int nf;
|
||||||
|
char *field[MAXDATEFIELDS];
|
||||||
|
int ftype[MAXDATEFIELDS];
|
||||||
|
char lowstr[MAXDATELEN + MAXDATEFIELDS];
|
||||||
|
char *realptr;
|
||||||
|
char **ptr = (endptr != NULL) ? endptr : &realptr;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if (strlen(str) >= sizeof(lowstr))
|
||||||
|
{
|
||||||
|
errno = PGTYPES_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;
|
||||||
|
return (noresult);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dtype)
|
||||||
|
{
|
||||||
|
case DTK_DATE:
|
||||||
|
if (tm2timestamp(tm, fsec, NULL, &result) != 0)
|
||||||
|
{
|
||||||
|
errno = PGTYPES_BAD_TIMESTAMP;
|
||||||
|
return (noresult);;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DTK_EPOCH:
|
||||||
|
result = SetEpochTimestamp();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DTK_LATE:
|
||||||
|
TIMESTAMP_NOEND(result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DTK_EARLY:
|
||||||
|
TIMESTAMP_NOBEGIN(result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DTK_INVALID:
|
||||||
|
errno = PGTYPES_BAD_TIMESTAMP;
|
||||||
|
return (noresult);
|
||||||
|
|
||||||
|
default:
|
||||||
|
errno = PGTYPES_BAD_TIMESTAMP;
|
||||||
|
return (noresult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AdjustTimestampForTypmod(&result, typmod); */
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
PGTYPEStimestamp_ttoa(Timestamp tstamp)
|
||||||
|
{
|
||||||
|
struct tm tt, *tm = &tt;
|
||||||
|
char buf[MAXDATELEN + 1];
|
||||||
|
char *tzn = NULL;
|
||||||
|
fsec_t fsec;
|
||||||
|
int DateStyle = 0;
|
||||||
|
|
||||||
|
if (TIMESTAMP_NOT_FINITE(tstamp))
|
||||||
|
EncodeSpecialTimestamp(tstamp, buf);
|
||||||
|
else if (timestamp2tm(tstamp, NULL, tm, &fsec, NULL) == 0)
|
||||||
|
EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf, 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errno = PGTYPES_BAD_TIMESTAMP;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return pgtypes_strdup(buf);
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.212 2003/03/16 10:42:54 meskes Exp $ */
|
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.213 2003/03/20 15:56:50 meskes Exp $ */
|
||||||
|
|
||||||
/* Copyright comment */
|
/* Copyright comment */
|
||||||
%{
|
%{
|
||||||
@ -4223,6 +4223,22 @@ single_vt_type: common_type
|
|||||||
$$.type_index = -1;
|
$$.type_index = -1;
|
||||||
$$.type_sizeof = NULL;
|
$$.type_sizeof = NULL;
|
||||||
}
|
}
|
||||||
|
else if (strcmp($1, "date") == 0)
|
||||||
|
{
|
||||||
|
$$.type_enum = ECPGt_date;
|
||||||
|
$$.type_str = make_str("Date");
|
||||||
|
$$.type_dimension = -1;
|
||||||
|
$$.type_index = -1;
|
||||||
|
$$.type_sizeof = NULL;
|
||||||
|
}
|
||||||
|
else if (strcmp($1, "timestamp") == 0)
|
||||||
|
{
|
||||||
|
$$.type_enum = ECPGt_timestamp;
|
||||||
|
$$.type_str = make_str("Timestamp");
|
||||||
|
$$.type_dimension = -1;
|
||||||
|
$$.type_index = -1;
|
||||||
|
$$.type_sizeof = NULL;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* this is for typedef'ed types */
|
/* this is for typedef'ed types */
|
||||||
@ -4236,17 +4252,6 @@ single_vt_type: common_type
|
|||||||
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
|
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| ECPGColLabelCommon '(' precision opt_scale ')'
|
|
||||||
{
|
|
||||||
if (strcmp($1, "numeric") != 0 && strcmp($1, "decimal") != 0)
|
|
||||||
mmerror(PARSE_ERROR, ET_ERROR, "Only numeric/decimal have precision/scale argument");
|
|
||||||
|
|
||||||
$$.type_enum = ECPGt_numeric;
|
|
||||||
$$.type_str = EMPTY;
|
|
||||||
$$.type_dimension = -1;
|
|
||||||
$$.type_index = -1;
|
|
||||||
$$.type_sizeof = NULL;
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4415,6 +4420,17 @@ common_type: simple_type
|
|||||||
$$.type_index = -1;
|
$$.type_index = -1;
|
||||||
$$.type_sizeof = NULL;
|
$$.type_sizeof = NULL;
|
||||||
}
|
}
|
||||||
|
| ECPGColLabelCommon '(' precision opt_scale ')'
|
||||||
|
{
|
||||||
|
if (strcmp($1, "numeric") != 0 && strcmp($1, "decimal") != 0)
|
||||||
|
mmerror(PARSE_ERROR, ET_ERROR, "Only numeric/decimal have precision/scale argument");
|
||||||
|
|
||||||
|
$$.type_enum = ECPGt_numeric;
|
||||||
|
$$.type_str = EMPTY;
|
||||||
|
$$.type_dimension = -1;
|
||||||
|
$$.type_index = -1;
|
||||||
|
$$.type_sizeof = NULL;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
var_type: common_type
|
var_type: common_type
|
||||||
@ -4464,6 +4480,22 @@ var_type: common_type
|
|||||||
$$.type_index = -1;
|
$$.type_index = -1;
|
||||||
$$.type_sizeof = NULL;
|
$$.type_sizeof = NULL;
|
||||||
}
|
}
|
||||||
|
else if (strcmp($1, "date") == 0)
|
||||||
|
{
|
||||||
|
$$.type_enum = ECPGt_date;
|
||||||
|
$$.type_str = make_str("Date");
|
||||||
|
$$.type_dimension = -1;
|
||||||
|
$$.type_index = -1;
|
||||||
|
$$.type_sizeof = NULL;
|
||||||
|
}
|
||||||
|
else if (strcmp($1, "timestamp") == 0)
|
||||||
|
{
|
||||||
|
$$.type_enum = ECPGt_timestamp;
|
||||||
|
$$.type_str = make_str("Timestamp");
|
||||||
|
$$.type_dimension = -1;
|
||||||
|
$$.type_index = -1;
|
||||||
|
$$.type_sizeof = NULL;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* this is for typedef'ed types */
|
/* this is for typedef'ed types */
|
||||||
@ -4477,17 +4509,6 @@ var_type: common_type
|
|||||||
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
|
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| ECPGColLabelCommon '(' precision opt_scale ')'
|
|
||||||
{
|
|
||||||
if (strcmp($1, "numeric") != 0 && strcmp($1, "decimal") != 0)
|
|
||||||
mmerror(PARSE_ERROR, ET_ERROR, "Only numeric/decimal have precision/scale argument");
|
|
||||||
|
|
||||||
$$.type_enum = ECPGt_numeric;
|
|
||||||
$$.type_str = EMPTY;
|
|
||||||
$$.type_dimension = -1;
|
|
||||||
$$.type_index = -1;
|
|
||||||
$$.type_sizeof = NULL;
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
enum_type: SQL_ENUM opt_symbol enum_definition
|
enum_type: SQL_ENUM opt_symbol enum_definition
|
||||||
|
@ -175,6 +175,12 @@ get_type(enum ECPGttype type)
|
|||||||
case ECPGt_descriptor:
|
case ECPGt_descriptor:
|
||||||
return ("ECPGt_descriptor");
|
return ("ECPGt_descriptor");
|
||||||
break;
|
break;
|
||||||
|
case ECPGt_date:
|
||||||
|
return ("ECPGt_date");
|
||||||
|
break;
|
||||||
|
case ECPGt_timestamp:
|
||||||
|
return ("ECPGt_timestamp");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
sprintf(errortext, "illegal variable type %d\n", type);
|
sprintf(errortext, "illegal variable type %d\n", type);
|
||||||
yyerror(errortext);
|
yyerror(errortext);
|
||||||
@ -330,6 +336,22 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
|
|||||||
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
|
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
|
||||||
sprintf(offset, "sizeof(struct NumericVar)");
|
sprintf(offset, "sizeof(struct NumericVar)");
|
||||||
break;
|
break;
|
||||||
|
case ECPGt_date:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we have to use a pointer and translate the variable type
|
||||||
|
*/
|
||||||
|
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
|
||||||
|
sprintf(offset, "sizeof(Date)");
|
||||||
|
break;
|
||||||
|
case ECPGt_timestamp:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we have to use a pointer and translate the variable type
|
||||||
|
*/
|
||||||
|
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
|
||||||
|
sprintf(offset, "sizeof(Date)");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Makefile,v 1.34 2003/03/16 10:42:54 meskes Exp $
|
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Makefile,v 1.35 2003/03/20 15:56:50 meskes Exp $
|
||||||
|
|
||||||
subdir = src/interfaces/ecpg/test
|
subdir = src/interfaces/ecpg/test
|
||||||
top_builddir = ../../../..
|
top_builddir = ../../../..
|
||||||
@ -8,7 +8,7 @@ override CPPFLAGS := -I$(srcdir)/../include $(CPPFLAGS) -g
|
|||||||
|
|
||||||
ECPG = ../preproc/ecpg -I$(srcdir)/../include
|
ECPG = ../preproc/ecpg -I$(srcdir)/../include
|
||||||
|
|
||||||
TESTS = test1 test2 test3 test4 perftest dyntest dyntest2 test_notice test_code100 test_init testdynalloc num_test
|
TESTS = test1 test2 test3 test4 perftest dyntest dyntest2 test_notice test_code100 test_init testdynalloc num_test dt_test
|
||||||
|
|
||||||
all: $(TESTS)
|
all: $(TESTS)
|
||||||
|
|
||||||
|
51
src/interfaces/ecpg/test/dt_test.pgc
Normal file
51
src/interfaces/ecpg/test/dt_test.pgc
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <pgtypes_date.h>
|
||||||
|
#include <pgtypes_timestamp.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
exec sql begin declare section;
|
||||||
|
date date1;
|
||||||
|
timestamp ts1;
|
||||||
|
char *text;
|
||||||
|
exec sql end declare section;
|
||||||
|
#if 0
|
||||||
|
Date date2;
|
||||||
|
short int mdy[3] = { 4, 19, 1998 };
|
||||||
|
#endif
|
||||||
|
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 insert into date_test(d, ts) values ('Mon Jan 17 1966', '2000-7-12 17:34:29');
|
||||||
|
|
||||||
|
exec sql select * into :date1, :ts1 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
|
||||||
|
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;
|
||||||
|
|
||||||
|
PGTYPESdate_julmdy(date2, mdy);
|
||||||
|
printf("m: %d, d: %d, y: %d\n", mdy[0], mdy[1], mdy[2]);
|
||||||
|
#endif
|
||||||
|
exec sql rollback;
|
||||||
|
exec sql disconnect;
|
||||||
|
|
||||||
|
if (dbgs != NULL)
|
||||||
|
fclose(dbgs);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ main()
|
|||||||
NumericVar *value1, *value2, *res;
|
NumericVar *value1, *value2, *res;
|
||||||
exec sql begin declare section;
|
exec sql begin declare section;
|
||||||
decimal(14,7) des = {0, 0, 0, 0, 0, NULL, NULL} ;
|
decimal(14,7) des = {0, 0, 0, 0, 0, NULL, NULL} ;
|
||||||
|
numeric num;
|
||||||
exec sql end declare section;
|
exec sql end declare section;
|
||||||
double d;
|
double d;
|
||||||
FILE *dbgs;
|
FILE *dbgs;
|
||||||
@ -52,6 +53,13 @@ main()
|
|||||||
text = PGTYPESnumeric_ntoa(res);
|
text = PGTYPESnumeric_ntoa(res);
|
||||||
PGTYPESnumeric_ntod(res, &d);
|
PGTYPESnumeric_ntod(res, &d);
|
||||||
printf("div = %s %e\n", text, d);
|
printf("div = %s %e\n", text, d);
|
||||||
|
|
||||||
|
exec sql rollback;
|
||||||
|
exec sql disconnect;
|
||||||
|
|
||||||
|
if (dbgs != NULL)
|
||||||
|
fclose(dbgs);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user