Started adding date and timestamp.
This commit is contained in:
parent
26a6378e84
commit
2e6f97560a
@ -1360,6 +1360,10 @@ Sun Mar 16 11:28:01 CET 2003
|
||||
- Started with a pgtypes library.
|
||||
- Renamed lib directory to ecpglib.
|
||||
- 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 library to 3.4.2.
|
||||
- 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"
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#include "extern.h"
|
||||
#include "sqlca.h"
|
||||
#include "pgtypes_numeric.h"
|
||||
#include "pgtypes_date.h"
|
||||
#include "pgtypes_timestamp.h"
|
||||
|
||||
bool
|
||||
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;
|
||||
char *scan_length;
|
||||
NumericVar *nres;
|
||||
Date ddres;
|
||||
Timestamp tres;
|
||||
|
||||
case ECPGt_short:
|
||||
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));
|
||||
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:
|
||||
ECPGraise(lineno, ECPG_UNSUPPORTED, ECPGtype_name(type));
|
||||
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.
|
||||
@ -27,6 +27,8 @@
|
||||
#include "sqlca.h"
|
||||
#include "sql3types.h"
|
||||
#include "pgtypes_numeric.h"
|
||||
#include "pgtypes_date.h"
|
||||
#include "pgtypes_timestamp.h"
|
||||
|
||||
/* variables visible to the programs */
|
||||
struct sqlca sqlca =
|
||||
@ -59,8 +61,7 @@ struct sqlca sqlca =
|
||||
/* This function returns a newly malloced string that has the \
|
||||
in the argument quoted with \ and the ' quoted with ' as SQL92 says.
|
||||
*/
|
||||
static
|
||||
char *
|
||||
static char *
|
||||
quote_postgres(char *arg, int 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);
|
||||
}
|
||||
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:
|
||||
/* Not implemented yet */
|
||||
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"
|
||||
|
||||
@ -49,6 +49,10 @@ ECPGtype_name(enum ECPGttype typ)
|
||||
return "char";
|
||||
case ECPGt_numeric:
|
||||
return "numeric";
|
||||
case ECPGt_date:
|
||||
return "date";
|
||||
case ECPGt_timestamp:
|
||||
return "timestamp";
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
@ -2,4 +2,14 @@
|
||||
|
||||
#ifndef dec_t
|
||||
#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 */
|
||||
|
@ -52,7 +52,9 @@ enum ECPGttype
|
||||
ECPGt_NO_INDICATOR, /* no indicator */
|
||||
ECPGt_long_long, ECPGt_unsigned_long_long,
|
||||
ECPGt_descriptor, /* sql descriptor, no C variable */
|
||||
ECPGt_numeric
|
||||
ECPGt_numeric,
|
||||
ECPGt_date,
|
||||
ECPGt_timestamp
|
||||
};
|
||||
|
||||
/* 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_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
|
||||
#
|
||||
# $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)
|
||||
|
||||
OBJS= numeric.o
|
||||
OBJS= numeric.o datetime.o common.o dt_common.o timestamp.o
|
||||
|
||||
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 <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "c.h"
|
||||
#include "extern.h"
|
||||
#include "numeric.h"
|
||||
#include "pgtypes_error.h"
|
||||
|
||||
@ -25,21 +25,6 @@
|
||||
|
||||
#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
|
||||
/* ----------
|
||||
* 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 */
|
||||
%{
|
||||
@ -4223,6 +4223,22 @@ single_vt_type: common_type
|
||||
$$.type_index = -1;
|
||||
$$.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
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
| 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_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
|
||||
@ -4464,6 +4480,22 @@ var_type: common_type
|
||||
$$.type_index = -1;
|
||||
$$.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
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
| 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
|
||||
|
@ -175,6 +175,12 @@ get_type(enum ECPGttype type)
|
||||
case ECPGt_descriptor:
|
||||
return ("ECPGt_descriptor");
|
||||
break;
|
||||
case ECPGt_date:
|
||||
return ("ECPGt_date");
|
||||
break;
|
||||
case ECPGt_timestamp:
|
||||
return ("ECPGt_timestamp");
|
||||
break;
|
||||
default:
|
||||
sprintf(errortext, "illegal variable type %d\n", type);
|
||||
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(offset, "sizeof(struct NumericVar)");
|
||||
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:
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
top_builddir = ../../../..
|
||||
@ -8,7 +8,7 @@ override CPPFLAGS := -I$(srcdir)/../include $(CPPFLAGS) -g
|
||||
|
||||
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)
|
||||
|
||||
|
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;
|
||||
exec sql begin declare section;
|
||||
decimal(14,7) des = {0, 0, 0, 0, 0, NULL, NULL} ;
|
||||
numeric num;
|
||||
exec sql end declare section;
|
||||
double d;
|
||||
FILE *dbgs;
|
||||
@ -52,6 +53,13 @@ main()
|
||||
text = PGTYPESnumeric_ntoa(res);
|
||||
PGTYPESnumeric_ntod(res, &d);
|
||||
printf("div = %s %e\n", text, d);
|
||||
|
||||
exec sql rollback;
|
||||
exec sql disconnect;
|
||||
|
||||
if (dbgs != NULL)
|
||||
fclose(dbgs);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user