Moved Informix stuff to its own compat library. Interval datetype is now fully functi...
authorMichael Meskes
Sun, 30 Mar 2003 11:48:19 +0000 (11:48 +0000)
committerMichael Meskes
Sun, 30 Mar 2003 11:48:19 +0000 (11:48 +0000)
14 files changed:
src/interfaces/ecpg/ChangeLog
src/interfaces/ecpg/Makefile
src/interfaces/ecpg/ecpglib/execute.c
src/interfaces/ecpg/include/ecpg_informix.h
src/interfaces/ecpg/include/pgtypes_date.h
src/interfaces/ecpg/include/pgtypes_error.h
src/interfaces/ecpg/include/pgtypes_numeric.h
src/interfaces/ecpg/pgtypeslib/Makefile
src/interfaces/ecpg/pgtypeslib/datetime.c
src/interfaces/ecpg/pgtypeslib/dt.h
src/interfaces/ecpg/pgtypeslib/dt_common.c
src/interfaces/ecpg/pgtypeslib/numeric.c
src/interfaces/ecpg/pgtypeslib/timestamp.c
src/interfaces/ecpg/test/dt_test.pgc

index 77ab60c2b3c0c984cf2eaaa12303cc3d43d3da7a..321bd3a63c6d3b8909f1557ac7e7dbeb693a668f 100644 (file)
@@ -1376,7 +1376,17 @@ Thu Mar 27 15:23:58 CET 2003
    - Some more updates to pgtypeslib.
    - Set optimization to -O1 until I find the reason why code is broken
      with -O2.
+
+Sat Mar 29 22:03:16 CET 2003
+
+   - Moved Informix compatibility stuff its own library.
+   - Added interval datetypes.
+
+Sun Mar 30 13:43:13 CEST 2003
+
+   - Interval datetype now fully functional.
    - Set ecpg version to 2.12.0.
    - Set ecpg library to 3.4.2.
    - Set pgtypes library to 1.0.0
+   - Set compat library to 1.0.0
 
index 50b97bc2d59b5bfcfab73b3e4f63128fbc220940..74286ce6ece54a662322801e0c6733d486a8fc68 100644 (file)
@@ -6,11 +6,13 @@ all install installdirs uninstall dep depend distprep:
    $(MAKE) -C include $@
    $(MAKE) -C ecpglib $@
    $(MAKE) -C pgtypeslib $@
+   $(MAKE) -C compatlib $@
    $(MAKE) -C preproc $@
 
 clean distclean maintainer-clean:
    -$(MAKE) -C include $@
    -$(MAKE) -C ecpglib $@
    -$(MAKE) -C pgtypeslib $@
+   -$(MAKE) -C compatlib $@
    -$(MAKE) -C preproc $@
    -$(MAKE) -C test clean
index a1e0f5456b4dfddfdb7d2a0fed0b7f4b3a40f610..6a9b38e7a884048239c40f2d7512ed74459138a1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.6 2003/03/27 14:29:17 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.7 2003/03/30 11:48:18 meskes Exp $ */
 
 /*
  * The aim is to get a simpler inteface to the database routines.
@@ -847,7 +847,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
                    {
                        for (element = 0; element < var->arrsize; element++)
                        {
-                           str = PGTYPESnumeric_ntoa((Numeric *)((var + var->offset * element)->value));
+                           str = PGTYPESnumeric_ntoa((Numeric *)((var + var->offset * element)->value), 0);
                            slen = strlen (str);
                            
                            if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + 5, stmt->lineno)))
@@ -863,7 +863,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
                    }
                    else
                    {
-                       str = PGTYPESnumeric_ntoa((Numeric *)(var->value));
+                       str = PGTYPESnumeric_ntoa((Numeric *)(var->value), 0);
                        slen = strlen (str);
                    
                        if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno)))
@@ -1239,7 +1239,9 @@ ECPGexecute(struct statement * stmt)
    {
        ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
                stmt->lineno, notify->relname, notify->be_pid);
-       PQfreemem(notify);
+/*     PQfreemem(notify);*/
+       free(notify);
+#warning Remove PQfreemem define
    }
 
    return status;
index 3d39c90b02be8b53a75034826d41539c732b4bb9..46df5a2d32a73bbce161a85078b0f7768adb3ecf 100644 (file)
@@ -2,6 +2,9 @@
  * This file contains stuff needed to be as compatible to Informix as possible.
  */
 
+#include 
+#include 
+
 #define SQLNOTFOUND 100
 
 #ifndef Date
index 882ddab82df7952763a2dc84613586d2c1495c48..76dedb866cf20aba8e1bac8084015c9327158927 100644 (file)
@@ -1,12 +1,17 @@
 #ifndef PGTYPES_DATETIME
 #define PGTYPES_DATETIME
 
+#include 
+
 #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 */
index 7cab1971b98960fd7dc4ffddabd16f2cf20ec462..2965a01476e2a60e14711df30a664662181e699e 100644 (file)
@@ -1,8 +1,15 @@
-#define    PGTYPES_OVERFLOW    201
-#define PGTYPES_BAD_NUMERIC    202
-#define PGTYPES_DIVIDE_ZERO    203
+#define    PGTYPES_NUM_OVERFLOW        201
+#define PGTYPES_NUM_BAD_NUMERIC        202
+#define PGTYPES_NUM_DIVIDE_ZERO        203
 
-#define PGTYPES_BAD_DATE   210
+#define PGTYPES_DATE_BAD_DATE      210
+#define PGTYPES_DATE_ERR_EARGS     211
+#define PGTYPES_DATE_ERR_ENOSHORTDATE  212
+#define PGTYPES_DATE_ERR_ENOTDMY   213
+#define PGTYPES_DATE_BAD_DAY       214
+#define PGTYPES_DATE_BAD_MONTH     215
 
-#define PGTYPES_BAD_TIMESTAMP  220
+#define PGTYPES_TS_BAD_TIMESTAMP   220
+
+#define PGTYPES_INTVL_BAD_INTERVAL 230
 
index 3fe849a3ad9730e76428b24f87f857c5ef91ecd7..977233afca0daafb8f7af63edf27e2d4c4d601be 100644 (file)
@@ -23,7 +23,7 @@ typedef struct
 Numeric *PGTYPESnew(void);
 void PGTYPESnumeric_free(Numeric *);
 Numeric *PGTYPESnumeric_aton(char *, char **);
-char *PGTYPESnumeric_ntoa(Numeric *);
+char *PGTYPESnumeric_ntoa(Numeric *, int);
 int PGTYPESnumeric_add(Numeric *, Numeric *, Numeric *);
 int PGTYPESnumeric_sub(Numeric *, Numeric *, Numeric *);
 int PGTYPESnumeric_mul(Numeric *, Numeric *, Numeric *);
index 97d8cbb24ea91f69af2a44423df06de73d825287..5a9e66408e56a803c38258d5116d7b1b34cc9308 100644 (file)
@@ -4,7 +4,7 @@
 #
 # Copyright (c) 1994, Regents of the University of California
 #
-# $Header: /cvsroot/pgsql/src/interfaces/ecpg/pgtypeslib/Makefile,v 1.3 2003/03/27 14:29:17 meskes Exp $
+# $Header: /cvsroot/pgsql/src/interfaces/ecpg/pgtypeslib/Makefile,v 1.4 2003/03/30 11:48:18 meskes Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -18,7 +18,7 @@ SO_MINOR_VERSION= 0.0
 
 override CPPFLAGS := -O1 -g -I$(top_srcdir)/src/interfaces/ecpg/include -I$(top_srcdir)/src/include/utils $(CPPFLAGS)
 
-OBJS= numeric.o datetime.o common.o dt_common.o timestamp.o
+OBJS= numeric.o datetime.o common.o dt_common.o timestamp.o interval.o
 
 all: all-lib
 
index 4bd5c1051796ef58cc965d3e91646278507effd0..fbc55462bf39c75ba4d2394547fa60b6b5c4be7b 100644 (file)
@@ -9,7 +9,31 @@
 #include "extern.h"
 #include "pgtypes_error.h"
 #include "pgtypes_date.h"
-#include "ecpg_informix.h"
+
+/* XXX: currently not used.
+ * pgsql: timestamp_date()
+ * Convert timestamp to date data type.
+ */
+Date
+PGTYPESdate_ttod(Timestamp dt)
+{
+   Date        dDate;
+
+   dDate = 0; /* suppress compiler warning */
+
+   if (TIMESTAMP_NOT_FINITE(dt))
+       return 
+
+#ifdef HAVE_INT64_TIMESTAMP
+   /* Microseconds to days */
+   dDate = (dt / INT64CONST(86400000000));
+#else
+   /* Seconds to days */
+   dDate = (dt / 86400.0);
+#endif
+
+   return dDate;
+}
 
 Date
 PGTYPESdate_atod(char *str, char **endptr)
@@ -32,14 +56,14 @@ PGTYPESdate_atod(char *str, char **endptr)
 
    if (strlen(str) >= sizeof(lowstr))
    {
-       errno = PGTYPES_BAD_DATE;
+       errno = PGTYPES_DATE_BAD_DATE;
        return -1;
    }
 
    if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0)
     || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp, EuroDates) != 0))
    {
-       errno = PGTYPES_BAD_DATE;
+       errno = PGTYPES_DATE_BAD_DATE;
        return -1;
    }
 
@@ -53,7 +77,7 @@ PGTYPESdate_atod(char *str, char **endptr)
            break;
 
        default:
-           errno = PGTYPES_BAD_DATE;
+           errno = PGTYPES_DATE_BAD_DATE;
            return -1;
    }
 
@@ -75,74 +99,521 @@ PGTYPESdate_dtoa(Date dDate)
    return pgtypes_strdup(buf);
 }
 
-int
+void
 PGTYPESdate_julmdy(Date jd, int* mdy)
 {
-   printf("day: %d\n", mdy[0]);
-   printf("month: %d\n", mdy[1]);
-   printf("year: %d\n", mdy[2]);
-   j2date((int) jd, mdy+2, mdy+1, mdy+0);
-   return 0;
+   int y, m, d;
+   
+   j2date((int) jd, &y, &m, &d);
+   mdy[0] = (short int) m;
+   mdy[1] = (short int) d;
+   mdy[2] = (short int) y;
 }
 
-int
+void
 PGTYPESdate_mdyjul(int* mdy, Date *jdate)
 {
    /* month is mdy[0] */
    /* day   is mdy[1] */
    /* year  is mdy[2] */
-   printf("day: %d\n", mdy[1]);
-   printf("month: %d\n", mdy[0]);
-   printf("year: %d\n", mdy[2]);
-   *jdate = (Date) date2j(mdy[2], mdy[0], mdy[1]);
-   return 0;
-}
 
-int
-PGTYPESdate_day(Date dDate)
-{
-   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;
 }
-
index d20c0cd819d04f4806b4cb6e94aad7cc07eaf0c7..e2019af32e0736cc81079a410e22fc64700458a8 100644 (file)
@@ -296,6 +296,7 @@ extern void GetEpochTime(struct tm *);
 extern int ParseDateTime(char *, char *, char **, int *, int, int *, char **);
 extern int DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, int *, bool);
 extern void j2date(int, int *, int *, int *);
+extern void GetCurrentDateTime(struct tm*);
 extern int date2j(int, int, int);
 extern double rint(double x);
 
index 3b85f7df1526c8509790eb277d77a12860512138..2da16b14d4ad798326e63634d658cc3008ee191a 100644 (file)
@@ -426,10 +426,81 @@ static datetkn datetktbl[] = {
    {ZULU, TZ, POS(0)},         /* UTC */
 };
 
+static datetkn deltatktbl[] = {
+   /* text, token, lexval */
+   {"@", IGNORE_DTF, 0},       /* postgres relative prefix */
+   {DAGO, AGO, 0},             /* "ago" indicates negative time offset */
+   {"c", UNITS, DTK_CENTURY},  /* "century" relative */
+   {"cent", UNITS, DTK_CENTURY},       /* "century" relative */
+   {"centuries", UNITS, DTK_CENTURY},  /* "centuries" relative */
+   {DCENTURY, UNITS, DTK_CENTURY},     /* "century" relative */
+   {"d", UNITS, DTK_DAY},      /* "day" relative */
+   {DDAY, UNITS, DTK_DAY},     /* "day" relative */
+   {"days", UNITS, DTK_DAY},   /* "days" relative */
+   {"dec", UNITS, DTK_DECADE}, /* "decade" relative */
+   {DDECADE, UNITS, DTK_DECADE},       /* "decade" relative */
+   {"decades", UNITS, DTK_DECADE},     /* "decades" relative */
+   {"decs", UNITS, DTK_DECADE},    /* "decades" relative */
+   {"h", UNITS, DTK_HOUR},     /* "hour" relative */
+   {DHOUR, UNITS, DTK_HOUR},   /* "hour" relative */
+   {"hours", UNITS, DTK_HOUR}, /* "hours" relative */
+   {"hr", UNITS, DTK_HOUR},    /* "hour" relative */
+   {"hrs", UNITS, DTK_HOUR},   /* "hours" relative */
+   {INVALID, RESERV, DTK_INVALID},     /* reserved for invalid time */
+   {"m", UNITS, DTK_MINUTE},   /* "minute" relative */
+   {"microsecon", UNITS, DTK_MICROSEC},        /* "microsecond" relative */
+   {"mil", UNITS, DTK_MILLENNIUM},     /* "millennium" relative */
+   {"millennia", UNITS, DTK_MILLENNIUM},       /* "millennia" relative */
+   {DMILLENNIUM, UNITS, DTK_MILLENNIUM},       /* "millennium" relative */
+   {"millisecon", UNITS, DTK_MILLISEC},        /* relative */
+   {"mils", UNITS, DTK_MILLENNIUM},    /* "millennia" relative */
+   {"min", UNITS, DTK_MINUTE}, /* "minute" relative */
+   {"mins", UNITS, DTK_MINUTE},    /* "minutes" relative */
+   {DMINUTE, UNITS, DTK_MINUTE},       /* "minute" relative */
+   {"minutes", UNITS, DTK_MINUTE},     /* "minutes" relative */
+   {"mon", UNITS, DTK_MONTH},  /* "months" relative */
+   {"mons", UNITS, DTK_MONTH}, /* "months" relative */
+   {DMONTH, UNITS, DTK_MONTH}, /* "month" relative */
+   {"months", UNITS, DTK_MONTH},
+   {"ms", UNITS, DTK_MILLISEC},
+   {"msec", UNITS, DTK_MILLISEC},
+   {DMILLISEC, UNITS, DTK_MILLISEC},
+   {"mseconds", UNITS, DTK_MILLISEC},
+   {"msecs", UNITS, DTK_MILLISEC},
+   {"qtr", UNITS, DTK_QUARTER},    /* "quarter" relative */
+   {DQUARTER, UNITS, DTK_QUARTER},     /* "quarter" relative */
+   {"reltime", IGNORE_DTF, 0}, /* pre-v6.1 "Undefined Reltime" */
+   {"s", UNITS, DTK_SECOND},
+   {"sec", UNITS, DTK_SECOND},
+   {DSECOND, UNITS, DTK_SECOND},
+   {"seconds", UNITS, DTK_SECOND},
+   {"secs", UNITS, DTK_SECOND},
+   {DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
+   {"timezone_h", UNITS, DTK_TZ_HOUR}, /* timezone hour units */
+   {"timezone_m", UNITS, DTK_TZ_MINUTE},       /* timezone minutes units */
+   {"undefined", RESERV, DTK_INVALID}, /* pre-v6.1 invalid time */
+   {"us", UNITS, DTK_MICROSEC},    /* "microsecond" relative */
+   {"usec", UNITS, DTK_MICROSEC},      /* "microsecond" relative */
+   {DMICROSEC, UNITS, DTK_MICROSEC},   /* "microsecond" relative */
+   {"useconds", UNITS, DTK_MICROSEC},  /* "microseconds" relative */
+   {"usecs", UNITS, DTK_MICROSEC},     /* "microseconds" relative */
+   {"w", UNITS, DTK_WEEK},     /* "week" relative */
+   {DWEEK, UNITS, DTK_WEEK},   /* "week" relative */
+   {"weeks", UNITS, DTK_WEEK}, /* "weeks" relative */
+   {"y", UNITS, DTK_YEAR},     /* "year" relative */
+   {DYEAR, UNITS, DTK_YEAR},   /* "year" relative */
+   {"years", UNITS, DTK_YEAR}, /* "years" relative */
+   {"yr", UNITS, DTK_YEAR},    /* "year" relative */
+   {"yrs", UNITS, DTK_YEAR},   /* "years" relative */
+};
+
 static unsigned int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0];
+static unsigned int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
 
 static datetkn    *datecache[MAXDATEFIELDS] = {NULL};
 
+static datetkn    *deltacache[MAXDATEFIELDS] = {NULL};
+
 char       *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};
 
 char       *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", NULL};
@@ -561,6 +632,39 @@ datebsearch(char *key, datetkn *base, unsigned int nel)
            return NULL;
 }
 
+/* DecodeUnits()
+ * Decode text string using lookup table.
+ * This routine supports time interval decoding.
+ */
+int
+DecodeUnits(int field, char *lowtoken, int *val)
+{
+   int         type;
+   datetkn    *tp;
+
+   if ((deltacache[field] != NULL)
+       && (strncmp(lowtoken, deltacache[field]->token, TOKMAXLEN) == 0))
+       tp = deltacache[field];
+   else
+       tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
+   deltacache[field] = tp;
+   if (tp == NULL)
+   {
+       type = UNKNOWN_FIELD;
+       *val = 0;
+   }
+   else
+   {
+       type = tp->type;
+       if ((type == TZ) || (type == DTZ))
+           *val = FROMVAL(tp);
+       else
+           *val = tp->value;
+   }
+
+   return type;
+}  /* DecodeUnits() */
+
 /*
  * Calendar time to Julian date conversions.
  * Julian date is commonly used in astronomical applications,
@@ -1088,7 +1192,7 @@ abstime2tm(AbsoluteTime _time, int *tzp, struct tm * tm, char **tzn)
 #endif
 }
 
-static void
+void
 GetCurrentDateTime(struct tm * tm)
 {
    int         tz;
index 9b0a1f2e14e9b0b7c62bf80c5e026287ee00cfe1..fc09a6e4ced275330f9099e1cadfbe8e977a2d44 100644 (file)
@@ -9,7 +9,6 @@
 #include "c.h"
 #include "extern.h"
 #include "pgtypes_error.h"
-#include "decimal.h"
 
 #define Max(x, y)               ((x) > (y) ? (x) : (y))
 #define Min(x, y)               ((x) < (y) ? (x) : (y))
@@ -96,7 +95,7 @@ apply_typmod(Numeric *var, long typmod)
 
        if (tweight >= maxweight && i < var->ndigits)
        {
-           errno = PGTYPES_OVERFLOW;
+           errno = PGTYPES_NUM_OVERFLOW;
            return -1;
        }
    }
@@ -188,7 +187,7 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
 
    if (!isdigit((unsigned char) *(*ptr)))
    {
-       errno=PGTYPES_BAD_NUMERIC;
+       errno=PGTYPES_NUM_BAD_NUMERIC;
        return -1;
    }
 
@@ -206,7 +205,7 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
        {
            if (have_dp)
            {
-               errno = PGTYPES_BAD_NUMERIC;
+               errno = PGTYPES_NUM_BAD_NUMERIC;
                return -1;
            }
            have_dp = TRUE;
@@ -227,14 +226,14 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
        exponent = strtol((*ptr), &endptr, 10);
        if (endptr == (*ptr))
        {
-           errno = PGTYPES_BAD_NUMERIC;
+           errno = PGTYPES_NUM_BAD_NUMERIC;
            return -1;
        }
        (*ptr) = endptr;
        if (exponent > NUMERIC_MAX_PRECISION ||
            exponent < -NUMERIC_MAX_PRECISION)
        {
-           errno = PGTYPES_BAD_NUMERIC;
+           errno = PGTYPES_NUM_BAD_NUMERIC;
            return -1;
        }
        dest->weight += (int) exponent;
@@ -248,7 +247,7 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
    {
        if (!isspace((unsigned char) *(*ptr)))
        {
-           errno = PGTYPES_BAD_NUMERIC;
+           errno = PGTYPES_NUM_BAD_NUMERIC;
            return -1;
        }
        (*ptr)++;
@@ -402,9 +401,12 @@ PGTYPESnumeric_aton(char *str, char **endptr)
  * ----------
  */
 char *
-PGTYPESnumeric_ntoa(Numeric *num)
+PGTYPESnumeric_ntoa(Numeric *num, int dscale)
 {
-   return(get_str_from_var(num, num->dscale));
+   if (dscale <= 0)
+       dscale = num->dscale;
+
+   return(get_str_from_var(num, dscale));
 }
 
 /* ----------
@@ -1117,7 +1119,7 @@ PGTYPESnumeric_div(Numeric *var1, Numeric *var2, Numeric *result)
    ndigits_tmp = var2->ndigits + 1;
    if (ndigits_tmp == 1)
    {
-       errno= PGTYPES_DIVIDE_ZERO;
+       errno= PGTYPES_NUM_DIVIDE_ZERO;
        return -1;
    }
 
@@ -1320,7 +1322,7 @@ PGTYPESnumeric_cmp(Numeric *var1, Numeric *var2) {
        return -1;
    }
 
-   errno = PGTYPES_BAD_NUMERIC;
+   errno = PGTYPES_NUM_BAD_NUMERIC;
    return INT_MAX;
 
 }
@@ -1438,7 +1440,7 @@ numericvar_to_double_no_overflow(Numeric *var, double *dp)
    {
        /* shouldn't happen ... */
        free(tmp);
-       errno = PGTYPES_BAD_NUMERIC;
+       errno = PGTYPES_NUM_BAD_NUMERIC;
        return -1;
    } 
    *dp = val;
@@ -1466,7 +1468,7 @@ PGTYPESnumeric_ntoi(Numeric* nv, int* ip) {
        return i;
 
    if (l < -INT_MAX || l > INT_MAX) {
-       errno = PGTYPES_OVERFLOW;
+       errno = PGTYPES_NUM_OVERFLOW;
        return -1;
    } 
 
@@ -1488,7 +1490,7 @@ PGTYPESnumeric_ntol(Numeric* nv, long* lp) {
        l++;
    }
    if (l > LONG_MAX || l < 0) {
-       errno = PGTYPES_OVERFLOW;
+       errno = PGTYPES_NUM_OVERFLOW;
        return -1;
    }
    
@@ -1499,196 +1501,3 @@ PGTYPESnumeric_ntol(Numeric* nv, long* lp) {
    return 0;
 }
 
-/* Finally we need some wrappers for the INFORMIX functions */
-int
-decadd(Numeric *arg1, Numeric *arg2, Numeric *sum)
-{
-   int i = PGTYPESnumeric_add(arg1, arg2, sum);
-
-   if (i == 0) /* No error */
-       return 0;
-   if (errno == PGTYPES_OVERFLOW)
-       return -1200;
-
-   return -1201;   
-}
-
-int
-deccmp(Numeric *arg1, Numeric *arg2)
-{
-   int i = PGTYPESnumeric_cmp(arg1, arg2);
-   
-   /* TODO: Need to return DECUNKNOWN instead of PGTYPES_BAD_NUMERIC */
-   return (i);
-}
-
-void
-deccopy(Numeric *src, Numeric *target)
-{
-   PGTYPESnumeric_copy(src, target);
-}
-
-static char *
-strndup(char *str, int len)
-{
-   int real_len = strlen(str);
-   int use_len = (real_len > len) ? len : real_len;
-   
-   char *new = pgtypes_alloc(use_len + 1);
-
-   if (new)
-   {
-       memcpy(str, new, use_len);
-       new[use_len] = '\0';
-   }
-
-   return new;
-}
-
-int
-deccvasc(char *cp, int len, Numeric *np)
-{
-   char *str = strndup(cp, len); /* Numeric_in always converts the complete string */
-   int ret = 0;
-   
-   if (!str)
-       ret = -1201;
-   else
-   {
-       np = PGTYPESnumeric_aton(str, NULL);
-       if (!np)
-       {
-           switch (errno)
-           {
-               case PGTYPES_OVERFLOW:    ret = -1200;
-                                 break;
-               case PGTYPES_BAD_NUMERIC: ret = -1213;
-                             break;
-               default:          ret = -1216;
-                             break;
-           }
-       }
-   }
-   
-   return ret;
-}
-
-int
-deccvdbl(double dbl, Numeric *np)
-{
-   return(PGTYPESnumeric_dton(dbl, np));
-}
-
-int
-deccvint(int in, Numeric *np)
-{
-   return(PGTYPESnumeric_iton(in, np));
-}
-
-int
-deccvlong(long lng, Numeric *np)
-{
-   return(PGTYPESnumeric_lton(lng, np));   
-}
-
-int
-decdiv(Numeric *n1, Numeric *n2, Numeric *n3)
-{
-   int i = PGTYPESnumeric_div(n1, n2, n3), ret = 0;
-
-   if (i != 0)
-       switch (errno)
-       {
-           case PGTYPES_DIVIDE_ZERO: ret = -1202;
-                         break;
-           case PGTYPES_OVERFLOW:    ret = -1200;
-                         break;
-           default:          ret = -1201;
-                         break;
-       }
-
-   return ret;
-}
-
-int 
-decmul(Numeric *n1, Numeric *n2, Numeric *n3)
-{
-   int i = PGTYPESnumeric_mul(n1, n2, n3), ret = 0;
-
-   if (i != 0)
-       switch (errno)
-       {
-           case PGTYPES_OVERFLOW:    ret = -1200;
-                         break;
-           default:          ret = -1201;
-                         break;
-       }
-
-   return ret;
-}
-
-int
-decsub(Numeric *n1, Numeric *n2, Numeric *n3)
-{
-   int i = PGTYPESnumeric_sub(n1, n2, n3), ret = 0;
-
-   if (i != 0)
-       switch (errno)
-       {
-           case PGTYPES_OVERFLOW:    ret = -1200;
-                         break;
-           default:          ret = -1201;
-                         break;
-       }
-
-   return ret;
-}
-
-int
-dectoasc(Numeric *np, char *cp, int len, int right)
-{
-   char *str;
-   
-   if (right >= 0)
-       str = get_str_from_var(np, right);
-   else
-       str = get_str_from_var(np, np->dscale);
-
-   if (!str)
-       return -1;
-   
-   /* TODO: have to take care of len here and create exponatial notion if necessary */
-   strncpy(cp, str, len);
-   free (str);
-
-   return 0;
-}
-
-int
-dectodbl(Numeric *np, double *dblp)
-{
-   return(PGTYPESnumeric_ntod(np, dblp));
-}
-
-int
-dectoint(Numeric *np, int *ip)
-{
-   int ret = PGTYPESnumeric_ntoi(np, ip);
-
-   if (ret == PGTYPES_OVERFLOW)
-       ret = -1200;
-   
-   return ret;
-}
-
-int
-dectolong(Numeric *np, long *lngp) 
-{
-   int ret = PGTYPESnumeric_ntol(np, lngp);
-
-   if (ret == PGTYPES_OVERFLOW)
-       ret = -1200;
-   
-   return ret;
-}
-
index bf1ca57c6ef4fc4e8569994913dcf5452fe4ab34..181e63dc2ae7a721d708017f6c425c335caf5ce8 100644 (file)
@@ -13,7 +13,6 @@
 #include "extern.h"
 #include "pgtypes_error.h"
 #include "pgtypes_timestamp.h"
-#include "pgtypes_interval.h"
 #include "datetime.h"
 
 #ifdef HAVE_INT64_TIMESTAMP
@@ -288,14 +287,14 @@ PGTYPEStimestamp_atot(char *str, char **endptr)
    errno = 0;
    if (strlen(str) >= sizeof(lowstr))
    {
-       errno = PGTYPES_BAD_TIMESTAMP;
+       errno = PGTYPES_TS_BAD_TIMESTAMP;
        return (noresult);
    }
 
    if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0)
      || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz, 0) != 0))
    {
-                errno = PGTYPES_BAD_TIMESTAMP;
+                errno = PGTYPES_TS_BAD_TIMESTAMP;
                 return (noresult);
         }
    
@@ -304,7 +303,7 @@ PGTYPEStimestamp_atot(char *str, char **endptr)
        case DTK_DATE:
            if (tm2timestamp(tm, fsec, NULL, &result) != 0)
            {
-               errno = PGTYPES_BAD_TIMESTAMP;
+               errno = PGTYPES_TS_BAD_TIMESTAMP;
                return (noresult);;
            }
            break;
@@ -322,11 +321,11 @@ PGTYPEStimestamp_atot(char *str, char **endptr)
            break;
 
        case DTK_INVALID:
-           errno = PGTYPES_BAD_TIMESTAMP;
+           errno = PGTYPES_TS_BAD_TIMESTAMP;
            return (noresult);
 
        default:
-           errno = PGTYPES_BAD_TIMESTAMP;
+           errno = PGTYPES_TS_BAD_TIMESTAMP;
            return (noresult);
    }
 
@@ -350,67 +349,8 @@ PGTYPEStimestamp_ttoa(Timestamp tstamp)
                 EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf, 0);
         else
    {
-       errno = PGTYPES_BAD_TIMESTAMP;
+       errno = PGTYPES_TS_BAD_TIMESTAMP;
        return NULL;
    }
         return pgtypes_strdup(buf);
 }
-
-void
-dtcurrent (Timestamp *ts)
-{
-   return;
-}
-
-int
-dtcvasc (char *str, Timestamp *ts)
-{
-   return 0;
-}
-
-int
-dtsub (Timestamp *ts1, Timestamp *ts2, Interval *iv)
-{
-   return 0;
-}
-
-int
-dttoasc (Timestamp *ts, char *output)
-{
-   return 0;
-}
-
-int
-dttofmtasc (Timestamp *ts, char *output, int str_len, char *fmtstr)
-{
-   return 0;
-}
-
-int
-intoasc(Interval *i, char *str)
-{
-   return 0;
-}
-
-Interval *
-PGTYPESinterval_atoi(char *str, char **endptr)
-{
-   Interval    *result = NULL;
-   
-   return result;
-}
-
-char *
-PGTYPESinterval_itoa(Interval *intvl)
-{
-        char            buf[MAXDATELEN + 1];
-
-        return pgtypes_strdup(buf);
-}
-
-int 
-PGTYPESinterval_copy(Interval *intvlsrc, Interval *intrcldest)
-{
-       return 0;
-}
-
index 34f520f891b57ca6859cc96845cb21fe51032a4f..68d099136ec52095dfb1886287626b8b9140dc08 100644 (file)
 #include 
+#include 
+#include 
 #include 
 #include 
+#include 
 
 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)