- 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
$(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
-/* $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.
{
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)))
}
else
{
- str = PGTYPESnumeric_ntoa((Numeric *)(var->value));
+ str = PGTYPESnumeric_ntoa((Numeric *)(var->value), 0);
slen = strlen (str);
if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno)))
{
ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
stmt->lineno, notify->relname, notify->be_pid);
- PQfreemem(notify);
+/* PQfreemem(notify);*/
+ free(notify);
+#warning Remove PQfreemem define
}
return status;
* This file contains stuff needed to be as compatible to Informix as possible.
*/
+#include <decimal.h>
+#include <datetime.h>
+
#define SQLNOTFOUND 100
#ifndef Date
#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 */
-#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
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 *);
#
# 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 $
#
#-------------------------------------------------------------------------
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
#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)
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;
}
break;
default:
- errno = PGTYPES_BAD_DATE;
+ errno = PGTYPES_DATE_BAD_DATE;
return -1;
}
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)
-{
- return j2day(dDate);
+ *jdate = (Date) date2j(mdy[2], mdy[0], mdy[1]);
}
int
-rdatestr (Date d, char *str)
+PGTYPESdate_dayofweek(Date dDate)
{
- 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;
}
-int
-rjulmdy (Date d, short mdy[3])
-{
- return 0;
-}
+#define PGTYPES_DATE_NUM_MAX_DIGITS 20 /* should suffice for most years... */
-int
-rdefmtdate (Date *d, char *fmt, char *str)
-{
- return 0;
-}
+#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
-int
-rfmtdate (Date d, char *fmt, char *str)
-{
- return 0;
-}
+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
-rmdyjul (short mdy[3], Date *d)
-{
+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
-rstrdate (char *str, Date *d)
+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;
}
-
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);
{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};
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,
#endif
}
-static void
+void
GetCurrentDateTime(struct tm * tm)
{
int tz;
#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))
if (tweight >= maxweight && i < var->ndigits)
{
- errno = PGTYPES_OVERFLOW;
+ errno = PGTYPES_NUM_OVERFLOW;
return -1;
}
}
if (!isdigit((unsigned char) *(*ptr)))
{
- errno=PGTYPES_BAD_NUMERIC;
+ errno=PGTYPES_NUM_BAD_NUMERIC;
return -1;
}
{
if (have_dp)
{
- errno = PGTYPES_BAD_NUMERIC;
+ errno = PGTYPES_NUM_BAD_NUMERIC;
return -1;
}
have_dp = TRUE;
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;
{
if (!isspace((unsigned char) *(*ptr)))
{
- errno = PGTYPES_BAD_NUMERIC;
+ errno = PGTYPES_NUM_BAD_NUMERIC;
return -1;
}
(*ptr)++;
* ----------
*/
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));
}
/* ----------
ndigits_tmp = var2->ndigits + 1;
if (ndigits_tmp == 1)
{
- errno= PGTYPES_DIVIDE_ZERO;
+ errno= PGTYPES_NUM_DIVIDE_ZERO;
return -1;
}
return -1;
}
- errno = PGTYPES_BAD_NUMERIC;
+ errno = PGTYPES_NUM_BAD_NUMERIC;
return INT_MAX;
}
{
/* shouldn't happen ... */
free(tmp);
- errno = PGTYPES_BAD_NUMERIC;
+ errno = PGTYPES_NUM_BAD_NUMERIC;
return -1;
}
*dp = val;
return i;
if (l < -INT_MAX || l > INT_MAX) {
- errno = PGTYPES_OVERFLOW;
+ errno = PGTYPES_NUM_OVERFLOW;
return -1;
}
l++;
}
if (l > LONG_MAX || l < 0) {
- errno = PGTYPES_OVERFLOW;
+ errno = PGTYPES_NUM_OVERFLOW;
return -1;
}
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;
-}
-
#include "extern.h"
#include "pgtypes_error.h"
#include "pgtypes_timestamp.h"
-#include "pgtypes_interval.h"
#include "datetime.h"
#ifdef HAVE_INT64_TIMESTAMP
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);
}
case DTK_DATE:
if (tm2timestamp(tm, fsec, NULL, &result) != 0)
{
- errno = PGTYPES_BAD_TIMESTAMP;
+ errno = PGTYPES_TS_BAD_TIMESTAMP;
return (noresult);;
}
break;
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);
}
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;
-}
-
#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)