]> granicus.if.org Git - postgresql/commitdiff
Implemented Informix special way to treat NULLs, removed warnings, synced.
authorMichael Meskes <meskes@postgresql.org>
Wed, 25 Jun 2003 10:44:21 +0000 (10:44 +0000)
committerMichael Meskes <meskes@postgresql.org>
Wed, 25 Jun 2003 10:44:21 +0000 (10:44 +0000)
20 files changed:
src/interfaces/ecpg/compatlib/informix.c
src/interfaces/ecpg/ecpglib/connect.c
src/interfaces/ecpg/ecpglib/data.c
src/interfaces/ecpg/ecpglib/execute.c
src/interfaces/ecpg/ecpglib/extern.h
src/interfaces/ecpg/ecpglib/misc.c
src/interfaces/ecpg/ecpglib/prepare.c
src/interfaces/ecpg/include/Makefile
src/interfaces/ecpg/include/ecpg_informix.h
src/interfaces/ecpg/include/ecpglib.h
src/interfaces/ecpg/include/pgtypes_numeric.h
src/interfaces/ecpg/include/sqltypes.h
src/interfaces/ecpg/pgtypeslib/timestamp.c
src/interfaces/ecpg/preproc/ecpg.c
src/interfaces/ecpg/preproc/extern.h
src/interfaces/ecpg/preproc/keywords.c
src/interfaces/ecpg/preproc/output.c
src/interfaces/ecpg/preproc/preproc.y
src/interfaces/ecpg/test/Makefile
src/interfaces/ecpg/test/test_informix.pgc [new file with mode: 0644]

index 2ac89e8f7e12b68757c47b48826921eed2a12ceb..71f914d036951fab8547c778bb06fd4d670dca8c 100644 (file)
@@ -4,6 +4,7 @@
 #include <math.h>
 #include <ctype.h>
 
+#include <ecpgtype.h>
 #include <ecpg_informix.h>
 #include <pgtypes_error.h>
 #include <pgtypes_date.h>
@@ -645,18 +646,6 @@ rgetmsg(int msgnum, char *s, int maxsize)
        return 0;
 }
 
-int
-risnull(int vtype, char *pcvar)
-{
-       return 0;
-}
-
-int
-rsetnull(int vtype, char *pcvar)
-{
-       return 0;
-}
-
 int
 rtypalign(int offset, int type)
 {
@@ -681,30 +670,6 @@ dtcvfmtasc (char *inbuf, char *fmtstr, dtime_t *dtvalue)
        return 0;
 }
 
-bool
-ECPGconnect_informix(int lineno, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit)
-{
-        char *informix_name = (char *)name, *envname;
-
-        /* Informix uses an environment variable DBPATH that overrides
-        * the connection parameters given here.
-        * We do the same with PG_DBPATH as the syntax is different. */
-        envname = getenv("PG_DBPATH");
-        if (envname)
-                informix_name = envname;
-               return (ECPGconnect(lineno, informix_name, user, passwd, connection_name , autocommit));
-}
-
-bool
-ECPGdeallocate_informix(int lineno, char *name)
-{
-       ECPGdeallocate_one(lineno, name);
-
-       /* Just ignore all errors since we do not know the list of cursors we
-        * are allowed to free. We have to trust that the software. */
-       return true;
-}
-       
 static struct var_list
 {
        int number;
@@ -744,3 +709,14 @@ ECPG_informix_get_var(int number)
        return (ptr) ? ptr->pointer : NULL;
 }
 
+int rsetnull(int t, char *ptr)
+{
+       ECPGset_informix_null(t, ptr);
+       return 0;
+}
+
+int risnull(int t, char *ptr)
+{
+       return(ECPGis_informix_null(t, ptr));
+}
+
index 58692a1b1be86a0a27060c7032940ce6172a0ec8..cda4bbd15bfb06f70482284a6e9d9cd5e112978e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.7 2003/06/15 04:07:58 momjian Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.8 2003/06/25 10:44:21 meskes Exp $ */
 
 #define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
@@ -173,7 +173,7 @@ ECPGnoticeProcessor(void *arg, const char *message)
        struct sqlca_t *sqlca = ECPGget_sqlca();
 
        /* these notices raise an error */
-       if (strncmp(message, "WARNING: ", 9))
+       if (strncmp(message, "WARNING: ", 9) && strncmp(message, "NOTICE: ", 8))
        {
                ECPGlog("ECPGnoticeProcessor: strange warning '%s'\n", message);
                ECPGnoticeProcessor_raise(ECPG_WARNING_UNRECOGNIZED, message);
@@ -290,9 +290,10 @@ ECPGnoticeProcessor(void *arg, const char *message)
 
 /* this contains some quick hacks, needs to be cleaned up, but it works */
 bool
-ECPGconnect(int lineno, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit)
+ECPGconnect(int lineno, int c, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit)
 {
        struct sqlca_t *sqlca = ECPGget_sqlca();
+       enum COMPAT_MODE compat = c;
        struct connection *this;
        char       *dbname = strdup(name),
                           *host = NULL,
@@ -302,6 +303,22 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd,
                           *options = NULL;
 
        ECPGinit_sqlca(sqlca);
+       
+       if (compat == ECPG_COMPAT_INFORMIX)
+       {
+               char *envname;
+               
+               /* Informix uses an environment variable DBPATH that overrides
+                * the connection parameters given here.
+                * We do the same with PG_DBPATH as the syntax is different. */
+               envname = getenv("PG_DBPATH");
+               if (envname)
+               {
+                       free(dbname);
+                       dbname = envname;
+               }
+                                       
+       }
 
        if ((this = (struct connection *) ECPGalloc(sizeof(struct connection), lineno)) == NULL)
                return false;
@@ -358,7 +375,7 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd,
                                *tmp = '\0';
                        }
 
-                       tmp = last_path_separator(dbname + offset); 
+                       tmp = last_path_separator(dbname + offset);
                        if (tmp != NULL)        /* database name given */
                        {
                                realname = strdup(tmp + 1);
index 0930380829fffebac98d6cc4c867c2615fa6efa1..8e0138d527ddeed0f910a8c89645bb2196825794 100644 (file)
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.7 2003/06/22 11:00:48 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.8 2003/06/25 10:44:21 meskes Exp $ */
 
 #define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
@@ -20,7 +20,7 @@ bool
 ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
                         enum ECPGttype type, enum ECPGttype ind_type,
                         char *var, char *ind, long varcharsize, long offset,
-                        long ind_offset, bool isarray)
+                        long ind_offset, bool isarray, enum COMPAT_MODE compat, bool force_indicator)
 {
        struct sqlca_t *sqlca = ECPGget_sqlca();
        char       *pval = (char *) PQgetvalue(results, act_tuple, act_field);
@@ -55,44 +55,48 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
        /*
         * check for null value and set indicator accordingly
         */
-       switch (ind_type)
+       if (PQgetisnull(results, act_tuple, act_field))
        {
-               case ECPGt_short:
-               case ECPGt_unsigned_short:
-/*                     ((short *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);*/
-                       *((short *) (ind + ind_offset * act_tuple)) = -PQgetisnull(results, act_tuple, act_field);
-                       break;
-               case ECPGt_int:
-               case ECPGt_unsigned_int:
-/*                     ((int *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);*/
-                       *((int *) (ind + ind_offset * act_tuple)) = -PQgetisnull(results, act_tuple, act_field);
-                       break;
-               case ECPGt_long:
-               case ECPGt_unsigned_long:
-/*                     ((long *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);*/
-                       *((long *) (ind + ind_offset * act_tuple)) = -PQgetisnull(results, act_tuple, act_field);
-                       break;
+               switch (ind_type)
+               {
+                       case ECPGt_short:
+                       case ECPGt_unsigned_short:
+                               *((short *) (ind + ind_offset * act_tuple)) = -1;
+                               break;
+                       case ECPGt_int:
+                       case ECPGt_unsigned_int:
+                               *((int *) (ind + ind_offset * act_tuple)) = -1;
+                               break;
+                       case ECPGt_long:
+                       case ECPGt_unsigned_long:
+                               *((long *) (ind + ind_offset * act_tuple)) = -1;
+                               break;
 #ifdef HAVE_LONG_LONG_INT_64
-               case ECPGt_long_long:
-               case ECPGt_unsigned_long_long:
-/*                     ((long long int *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);*/
-                       *((long long int *) (ind + ind_offset * act_tuple)) = -PQgetisnull(results, act_tuple, act_field);
-                       break;
-/*             case ECPGt_unsigned_long_long:
-                       ((unsigned long long int *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
-                       break;*/
+                       case ECPGt_long_long:
+                       case ECPGt_unsigned_long_long:
+                               *((long long int *) (ind + ind_offset * act_tuple)) = -1;
+                               break;
 #endif   /* HAVE_LONG_LONG_INT_64 */
-               case ECPGt_NO_INDICATOR:
-                       if (PQgetisnull(results, act_tuple, act_field))
-                       {
-                               ECPGraise(lineno, ECPG_MISSING_INDICATOR, NULL);
+                       case ECPGt_NO_INDICATOR:
+                               if (force_indicator == false && compat == ECPG_COMPAT_INFORMIX)
+                               {
+                                       /* Informix has an additional way to specify NULLs
+                                        * note that this uses special values to denote NULL */
+                                       ECPGset_informix_null(type, var + offset * act_tuple);
+                               }
+                               else
+                               {
+                                       ECPGraise(lineno, ECPG_MISSING_INDICATOR, NULL);
+                                       return (false);
+                               }
+                               break;
+                       default:
+                               ECPGraise(lineno, ECPG_UNSUPPORTED, ECPGtype_name(ind_type));
                                return (false);
-                       }
-                       break;
-               default:
-                       ECPGraise(lineno, ECPG_UNSUPPORTED, ECPGtype_name(ind_type));
-                       return (false);
-                       break;
+                               break;
+               }
+
+               return (true);
        }
 
        do
index 4bc0ba801749fa788d9850cadf0e360eb50b3c35..af4d23b7e79b5811774ca02344463697fd1e4d7b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.11 2003/06/20 12:00:59 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.12 2003/06/25 10:44:21 meskes Exp $ */
 
 /*
  * The aim is to get a simpler inteface to the database routines.
@@ -88,7 +88,7 @@ quote_postgres(char *arg, int lineno)
  * ind_offset - indicator offset
  */
 static bool
-create_statement(int lineno, struct connection * connection, struct statement ** stmt, char *query, va_list ap)
+create_statement(int lineno, int compat, int force_indicator, struct connection * connection, struct statement ** stmt, char *query, va_list ap)
 {
        struct variable **list = &((*stmt)->inlist);
        enum ECPGttype type;
@@ -99,6 +99,8 @@ create_statement(int lineno, struct connection * connection, struct statement **
        (*stmt)->command = query;
        (*stmt)->connection = connection;
        (*stmt)->lineno = lineno;
+       (*stmt)->compat = compat;
+       (*stmt)->force_indicator = force_indicator;
 
        list = &((*stmt)->inlist);
 
@@ -428,7 +430,7 @@ ECPGstore_result(const PGresult *results, int act_field,
 
                        if (!ECPGget_data(results, act_tuple, act_field, stmt->lineno,
                                                 var->type, var->ind_type, current_data_location,
-                                                         var->ind_value, len, 0, 0, isarray))
+                                                         var->ind_value, len, 0, 0, isarray, stmt->compat, stmt->force_indicator))
                                status = false;
                        else
                        {
@@ -447,7 +449,7 @@ ECPGstore_result(const PGresult *results, int act_field,
                {
                        if (!ECPGget_data(results, act_tuple, act_field, stmt->lineno,
                                                          var->type, var->ind_type, var->value,
-                                                         var->ind_value, var->varcharsize, var->offset, var->ind_offset, isarray))
+                                                         var->ind_value, var->varcharsize, var->offset, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
                                status = false;
                }
        }
@@ -505,10 +507,16 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
                                *tobeinserted_p = "null";
                        break;
 #endif   /* HAVE_LONG_LONG_INT_64 */
+               case ECPGt_NO_INDICATOR:
+                       if (stmt->force_indicator == false && stmt->compat == ECPG_COMPAT_INFORMIX)
+                       {
+                               if (ECPGis_informix_null(var->type, var->value))
+                                       *tobeinserted_p = "null";
+                       }
+                       break;
                default:
                        break;
        }
-
        if (**tobeinserted_p == '\0')
        {
                switch (var->type)
@@ -1222,7 +1230,7 @@ ECPGexecute(struct statement * stmt)
 }
 
 bool
-ECPGdo(int lineno, const char *connection_name, char *query,...)
+ECPGdo(int lineno, int compat, int force_indicator, const char *connection_name, char *query,...)
 {
        va_list         args;
        struct statement *stmt;
@@ -1244,7 +1252,7 @@ ECPGdo(int lineno, const char *connection_name, char *query,...)
 
        /* construct statement in our own structure */
        va_start(args, query);
-       if (create_statement(lineno, con, &stmt, query, args) == false)
+       if (create_statement(lineno, compat, force_indicator, con, &stmt, query, args) == false)
        {
                setlocale(LC_NUMERIC, oldlocale);
                ECPGfree(oldlocale);
@@ -1280,7 +1288,8 @@ bool
 ECPGdo_descriptor(int line, const char *connection,
                                  const char *descriptor, const char *query)
 {
-       return ECPGdo(line, connection, (char *) query, ECPGt_EOIT,
+       return ECPGdo(line, ECPG_COMPAT_PGSQL, true, connection, (char *) query, ECPGt_EOIT,
                                  ECPGt_descriptor, descriptor, 0L, 0L, 0L,
                                  ECPGt_NO_INDICATOR, NULL, 0L, 0L, 0L, ECPGt_EORT);
 }
+
index a43526c7603bd4c8449d790f6a295606f074ccd9..a7f37491da862dd4a0afe1e4159686298bb7c608 100644 (file)
@@ -5,6 +5,8 @@
 #include "libpq-fe.h"
 #include "sqlca.h"
 
+enum COMPAT_MODE { ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX};
+
 /* Here are some methods used by the lib. */
 
 /* Stores the backend error message for client access */
@@ -18,7 +20,7 @@ char *ECPGerrmsg(void);
 void           ECPGadd_mem(void *ptr, int lineno);
 
 bool ECPGget_data(const PGresult *, int, int, int, enum ECPGttype type,
-                        enum ECPGttype, char *, char *, long, long, long, bool);
+                        enum ECPGttype, char *, char *, long, long, long, bool, enum COMPAT_MODE, bool);
 struct connection *ECPGget_connection(const char *);
 char      *ECPGalloc(long, int);
 char      *ECPGrealloc(void *, long, int);
@@ -54,6 +56,8 @@ struct statement
        int                     lineno;
        char       *command;
        struct connection *connection;
+       enum COMPAT_MODE compat;
+       bool force_indicator;
        struct variable *inlist;
        struct variable *outlist;
 };
index ae2e090fe988b96d35b46f52ee8c7f8a01de9620..ae78f97b85a0123eefe3e8d36394ff51e43b0bd5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.4 2003/06/15 04:56:45 momjian Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.5 2003/06/25 10:44:21 meskes Exp $ */
 
 #define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
 #include "ecpgerrno.h"
 #include "extern.h"
 #include "sqlca.h"
+#include "pgtypes_numeric.h"
+#include "pgtypes_date.h"
+#include "pgtypes_timestamp.h"
+#include "pgtypes_interval.h"
 
 static struct sqlca_t sqlca_init =
 {
@@ -238,3 +242,114 @@ ECPGlog(const char *format,...)
        pthread_mutex_unlock(&debug_mutex);
 #endif
 }
+
+void
+ECPGset_informix_null(enum ECPGttype type, void *ptr)
+{
+       switch (type)
+       {
+               case ECPGt_char: 
+               case ECPGt_unsigned_char:
+                       *((char *) ptr) = 0x00;
+                       break;
+               case ECPGt_short:
+               case ECPGt_unsigned_short:
+                       *((short int *) ptr) = SHRT_MIN;
+                       break;
+               case ECPGt_int:
+               case ECPGt_unsigned_int:
+                       *((int *) ptr) = INT_MIN;
+                       break;
+               case ECPGt_long:
+               case ECPGt_unsigned_long:
+               case ECPGt_date:
+                       *((long *) ptr) = LONG_MIN;
+                       break;
+#ifdef HAVE_LONG_LONG_INT_64
+               case ECPGt_long_long:
+               case ECPGt_unsigned_long_long:
+                       *((long long *) ptr) = LONG_LONG_MIN;
+                       break;
+#endif   /* HAVE_LONG_LONG_INT_64 */
+               case ECPGt_float:
+                       memset((char *) ptr, 0xff, sizeof(float));
+                       break;
+               case ECPGt_double:
+                       memset((char *) ptr, 0xff, sizeof(double));
+                       break;
+               case ECPGt_varchar:
+                       *(((struct ECPGgeneric_varchar *) ptr)->arr) = 0x00;
+                       break;
+               case ECPGt_numeric:
+                       ((Numeric *) ptr)->sign = NUMERIC_NAN;
+                       break;
+               case ECPGt_interval:
+                       memset((char *) ptr, 0xff, sizeof(Interval));
+                       break;
+               case ECPGt_timestamp:
+                       memset((char *) ptr, 0xff, sizeof(Timestamp));
+                       break;
+               default:
+                       break;
+       }
+}
+
+static bool _check(unsigned char *ptr, int length)
+{
+       for (;ptr[length] == 0xff && length >= 0; length --);
+       if (length < 0) return true;
+       return false;
+}
+
+bool
+ECPGis_informix_null(enum ECPGttype type, void *ptr)
+{
+       switch (type)
+       {
+               case ECPGt_char: 
+               case ECPGt_unsigned_char:
+                       if (*((char *)ptr) == 0x00) return true;
+                       break;
+               case ECPGt_short:
+               case ECPGt_unsigned_short:
+                       if (*((short int *) ptr) == SHRT_MIN) return true;
+                       break;
+               case ECPGt_int:
+               case ECPGt_unsigned_int:
+                       if (*((int *) ptr) == INT_MIN) return true;
+                       break;
+               case ECPGt_long:
+               case ECPGt_unsigned_long:
+               case ECPGt_date:
+                       if (*((long *) ptr) == LONG_MIN) return true;
+                       break;
+#ifdef HAVE_LONG_LONG_INT_64
+               case ECPGt_long_long:
+               case ECPGt_unsigned_long_long:
+                       if (*((long long *) ptr) == LONG_LONG_MIN) return true;
+                       break;
+#endif   /* HAVE_LONG_LONG_INT_64 */
+               case ECPGt_float:
+                       return(_check(ptr, sizeof(float)));
+                       break;
+               case ECPGt_double:
+                       return(_check(ptr, sizeof(double)));
+                       break;
+               case ECPGt_varchar:
+                       if (*(((struct ECPGgeneric_varchar *) ptr)->arr) == 0x00) return true;
+                       break;
+               case ECPGt_numeric:
+                       if (((Numeric *) ptr)->sign == NUMERIC_NAN) return true;
+                       break;
+               case ECPGt_interval:
+                       return(_check(ptr, sizeof(Interval)));
+                       break;
+               case ECPGt_timestamp:
+                       return(_check(ptr, sizeof(Timestamp)));
+                       break;
+               default:
+                       break;
+       }
+
+       return false;
+}
index 5f8c92c092c34bda2f716961e53afd836e9a0579..a10f386fc8c31687bda594cfc53678481391cfa6 100644 (file)
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.3 2003/06/20 13:36:34 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.4 2003/06/25 10:44:21 meskes Exp $ */
 
 #define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
@@ -64,7 +64,7 @@ ECPGprepare(int lineno, char *name, char *variable)
        for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);
        if (this)
        {
-               bool            b = ECPGdeallocate(lineno, name);
+               bool b = ECPGdeallocate(lineno, ECPG_COMPAT_PGSQL, name);
 
                if (!b)
                        return false;
@@ -105,15 +105,22 @@ ECPGprepare(int lineno, char *name, char *variable)
 
 /* handle the EXEC SQL DEALLOCATE PREPARE statement */
 bool
-ECPGdeallocate(int lineno, char *name)
+ECPGdeallocate(int lineno, int c, char *name)
 {
        bool ret = ECPGdeallocate_one(lineno, name);
+       enum COMPAT_MODE compat = c;
 
+       if (compat == ECPG_COMPAT_INFORMIX)
+       {
+               /* Just ignore all errors since we do not know the list of cursors we
+                * are allowed to free. We have to trust that the software. */
+               return true;
+       }
+       
        if (!ret) 
                ECPGraise(lineno, ECPG_INVALID_STMT, name);
 
        return ret;
-               
 }
 
 bool
@@ -147,7 +154,7 @@ ECPGdeallocate_all(int lineno)
        /* deallocate all prepared statements */
        while (prep_stmts != NULL)
        {
-               bool            b = ECPGdeallocate(lineno, prep_stmts->name);
+               bool    b = ECPGdeallocate(lineno, ECPG_COMPAT_PGSQL, prep_stmts->name);
 
                if (!b)
                        return false;
index 9226bac8c412782b77dd6881336b9b069d62e5eb..e4c1530f3c71a5424e544c5366b8cf35ba27c6d3 100644 (file)
@@ -5,7 +5,8 @@ include $(top_builddir)/src/Makefile.global
 install: all installdirs install-headers
 
 .PHONY: install-headers
-ecpg_headers = ecpgerrno.h ecpglib.h ecpgtype.h sqlca.h sql3types.h ecpg_informix.h pgtypes_error.h pgtypes_numeric.h pgtypes_timestamp.h pgtypes_date.h datetime.h decimal.h 
+ecpg_headers = ecpgerrno.h ecpglib.h ecpgtype.h sqlca.h sql3types.h ecpg_informix.h pgtypes_error.h pgtypes_numeric.h pgtypes_timestamp.h pgtypes_date.h datetime.h decimal.h pgtypes_interval.h
+
 install-headers: $(ecpg_headers)
        for i in $^; do $(INSTALL_DATA) $$i $(DESTDIR)$(includedir); done
 
index f79478663260ce54b112bed9fe37bd3aec85c4ea..59991c70a9168e63ae3a80df4fe551753fff3360 100644 (file)
@@ -33,7 +33,5 @@ extern void rupshift(char *);
 extern int byleng(char *, int);
 extern void ldchar(char *, int, char *);
 
-extern bool ECPGconnect_informix(int, const char *, const char *, const char *, const char *, int);
-extern bool ECPGdeallocate_informix(int, char *);
 extern void ECPG_informix_set_var(int, void *, int);
 extern void *ECPG_informix_get_var(int);
index ae272927c6f85e8958eac16a61093de1865babb7..66985bf3b60a496d924f99a944b54c1bd12b93c1 100644 (file)
@@ -45,12 +45,12 @@ void                ECPGdebug(int, FILE *);
 bool           ECPGstatus(int, const char *);
 bool           ECPGsetcommit(int, const char *, const char *);
 bool           ECPGsetconn(int, const char *);
-bool           ECPGconnect(int, const char *, const char *, const char *, const char *, int);
-bool           ECPGdo(int, const char *, char *,...);
+bool           ECPGconnect(int, int, const char *, const char *, const char *, const char *, int);
+bool           ECPGdo(int, int, int, const char *, char *,...);
 bool           ECPGtrans(int, const char *, const char *);
 bool           ECPGdisconnect(int, const char *);
 bool           ECPGprepare(int, char *, char *);
-bool           ECPGdeallocate(int, char *);
+bool           ECPGdeallocate(int, int, char *);
 bool           ECPGdeallocate_one(int, char *);
 bool           ECPGdeallocate_all(int);
 char      *ECPGprepared_statement(char *);
@@ -75,13 +75,13 @@ void                ECPGraise(int line, int code, const char *str);
 bool           ECPGget_desc_header(int, char *, int *);
 bool           ECPGget_desc(int, char *, int,...);
 
+void           ECPGset_informix_null(enum ECPGttype, void *);
+bool           ECPGis_informix_null(enum ECPGttype, void *);
 bool           ECPGdescribe(int, bool, const char *, ...);
 
 /* dynamic result allocation */
 void           ECPGfree_auto_mem(void);
 
-enum COMPAT_MODE { ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX};
-
 #ifdef __cplusplus
 }
 
index 685326e4a80c10d1d9ae93c69323e649e96b0ba5..cd7552db384d7c69eef648826a2cbbfa56493a3e 100644 (file)
@@ -3,6 +3,7 @@
 
 #define NUMERIC_POS                     0x0000
 #define NUMERIC_NEG                     0x4000
+#define NUMERIC_NAN                     0xC000
 #define NUMERIC_MAX_PRECISION           1000
 #define NUMERIC_MAX_DISPLAY_SCALE       NUMERIC_MAX_PRECISION
 #define NUMERIC_MIN_DISPLAY_SCALE       0
index 5e305fb2c5b29cf37e7c23be3913ab4b624a9e4c..e6a96bcf48df05f1ce2b433a7e33acb27196cee1 100644 (file)
@@ -1,25 +1,25 @@
-#define CCHARTYPE      100
-#define CSHORTTYPE     101
-#define CINTTYPE       102
-#define CLONGTYPE      103
-#define CFLOATTYPE     104
-#define CDOUBLETYPE    105
-#define CDECIMALTYPE   107
+#define CCHARTYPE      ECPGt_char
+#define CSHORTTYPE     ECPGt_short
+#define CINTTYPE       ECPGt_int
+#define CLONGTYPE      ECPGt_long
+#define CFLOATTYPE     ECPGt_float
+#define CDOUBLETYPE    ECPGt_double
+#define CDECIMALTYPE   ECPGt_numeric
 #define CFIXCHARTYPE   108
-#define CSTRINGTYPE    109
-#define CDATETYPE      110
+#define CSTRINGTYPE    ECPGt_char
+#define CDATETYPE      ECPGt_date
 #define CMONEYTYPE     111
 #define CDTIMETYPE     112
 #define CLOCATORTYPE    113
-#define CVCHARTYPE     114
+#define CVCHARTYPE     ECPGt_varchar   
 #define CINVTYPE       115
 #define CFILETYPE      116
-#define CINT8TYPE      117
+#define CINT8TYPE      ECPGt_long_long
 #define CCOLLTYPE       118   
 #define CLVCHARTYPE     119
 #define CFIXBINTYPE     120
 #define CVARBINTYPE     121
-#define CBOOLTYPE       122
+#define CBOOLTYPE       ECPGt_bool
 #define CROWTYPE        123
 #define CLVCHARPTRTYPE  124
 #define CTYPEMAX       25
index 9cea9a3db01574d5fa330289110737a0a6ca64cd..59449941eafa7b8c2bc19465c27a498e2e9b493b 100644 (file)
@@ -464,15 +464,19 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
                                        break;
                                case 'g':
                                        /* XXX: fall back to strftime */
-                                       tm->tm_mon -= 1;
-                                       i = strftime(q, *pstr_len, "%g", tm);
-                                       if (i == 0) { return -1; }
-                                       while (*q) {
-                                               q++;
-                                               (*pstr_len)--;
+                                       {
+                                               char *fmt = "%g"; /* Keep compiler quiet about 2-digit year */
+       
+                                               tm->tm_mon -= 1;
+                                               i = strftime(q, *pstr_len, fmt, tm);
+                                               if (i == 0) { return -1; }
+                                               while (*q) {
+                                                       q++;
+                                                       (*pstr_len)--;
+                                               }
+                                               tm->tm_mon += 1;
+                                               replace_type = PGTYPES_REPLACE_NOTHING;
                                        }
-                                       tm->tm_mon += 1;
-                                       replace_type = PGTYPES_REPLACE_NOTHING;
                                        break;
                                case 'H':
                                        replace_val.replace_uint = tm->tm_hour;
@@ -602,15 +606,19 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
                                        break;
                                case 'x':
                                        /* XXX: fall back to strftime */
-                                       tm->tm_mon -= 1;
-                                       i = strftime(q, *pstr_len, "%x", tm);
-                                       if (i == 0) { return -1; }
-                                       while (*q) {
-                                               q++;
-                                               (*pstr_len)--;
+                                       {
+                                               char *fmt = "%x"; /* Keep compiler quiet about 2-digit year */
+
+                                               tm->tm_mon -= 1;
+                                               i = strftime(q, *pstr_len, fmt, tm);
+                                               if (i == 0) { return -1; }
+                                               while (*q) {
+                                                       q++;
+                                                       (*pstr_len)--;
+                                               }
+                                               tm->tm_mon += 1;
+                                               replace_type = PGTYPES_REPLACE_NOTHING;
                                        }
-                                       tm->tm_mon += 1;
-                                       replace_type = PGTYPES_REPLACE_NOTHING;
                                        break;
                                case 'X':
                                        /* XXX: fall back to strftime */
index bba130792d23c410c0cda3937af6ffb15362ce59..0256080a50a9d3ca7512ea20e8559b34325e9136 100644 (file)
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.73 2003/06/13 10:50:57 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.74 2003/06/25 10:44:21 meskes Exp $ */
 
 /* New main for ecpg, the PostgreSQL embedded SQL precompiler. */
 /* (C) Michael Meskes <meskes@postgresql.org> Feb 5th, 1998 */
@@ -20,7 +20,8 @@ extern char *optarg;
 int                    ret_value = 0,
                        autocommit = false,
                        auto_create_c = false,
-                       system_includes = false;
+                       system_includes = false,
+                       force_indicator = true;
 
 enum COMPAT_MODE       compat = ECPG_COMPAT_PGSQL;
 
@@ -44,8 +45,9 @@ help(const char *progname)
        printf("  -d             generate parser debug output\n");
 #endif
        printf("  -C <mode>      set compatibility mode\n"
-                  "                 mode may be INFORMIX only at the moment\n"
-                  "                 INFORMIX mode implies '-i'\n");
+                  "                 mode may be \"INFORMIX\" only at the moment\n");
+       printf("  -r <option>    specify runtime behaviour\n"
+                  "                 option may be only \"no_indicator\" at the moment\n");     
        printf("  -D SYMBOL      define SYMBOL\n");
        printf("  -I DIRECTORY   search DIRECTORY for include files\n");
        printf("  -o OUTFILE     write result to OUTFILE\n");
@@ -132,7 +134,7 @@ main(int argc, char *const argv[])
                }
        }
 
-       while ((c = getopt(argc, argv, "vcio:I:tD:dC:")) != -1)
+       while ((c = getopt(argc, argv, "vcio:I:tD:dC:r:")) != -1)
        {
                switch (c)
                {
@@ -177,6 +179,15 @@ main(int argc, char *const argv[])
                                        return ILLEGAL_OPTION;
                                }                               
                                break;
+                       case 'r':
+                               if (strcmp(optarg, "no_indicator") == 0)
+                                       force_indicator = false;
+                               else
+                               {
+                                       fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
+                                       return ILLEGAL_OPTION;
+                               }
+                               break;
                        case 'D':
                                add_preprocessor_define(optarg);
                                break;
index ae6c5bc20491d66356855a05b5580546bf8822af..f38cb244ae91b6bbed4a027f683132ab78444c7a 100644 (file)
@@ -16,6 +16,7 @@ extern int    braces_open,
                        autocommit,
                        auto_create_c,
                        system_includes,
+                       force_indicator,
                        ret_value,
                        struct_level,
                        ecpg_informix_var;
index e6b0d6651f4c4f81e93241b338c5824e4e03d92b..4971c9fa7d85d891fe1cc8865bea5780d55fdc98 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.58 2003/05/23 15:19:34 meskes Exp $
+ *       $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.59 2003/06/25 10:44:21 meskes Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -100,6 +100,7 @@ static ScanKeyword ScanKeywords[] = {
        {"decimal", DECIMAL_P},
        {"declare", DECLARE},
        {"default", DEFAULT},
+       {"defaults", DEFAULTS},
        {"deferrable", DEFERRABLE},
        {"deferred", DEFERRED},
        {"definer", DEFINER},
@@ -119,6 +120,7 @@ static ScanKeyword ScanKeywords[] = {
        {"end", END_P},
        {"escape", ESCAPE},
        {"except", EXCEPT},
+       {"excluding", EXCLUDING},
        {"exclusive", EXCLUSIVE},
        {"execute", EXECUTE},
        {"exists", EXISTS},
@@ -150,6 +152,7 @@ static ScanKeyword ScanKeywords[] = {
        {"immutable", IMMUTABLE},
        {"implicit", IMPLICIT_P},
        {"in", IN_P},
+       {"including", INCLUDING},
        {"increment", INCREMENT},
        {"index", INDEX},
        {"inherits", INHERITS},
index 57509ea809c15b910bd535206ea39bb7b3e62c23..055ad7f039e2688f72a9f7fa3b3ee4e107e7c38b 100644 (file)
@@ -109,7 +109,7 @@ output_statement(char *stmt, int mode, char *con)
        int                     i,
                                j = strlen(stmt);
 
-       fprintf(yyout, "{ ECPGdo(__LINE__, %s, \"", con ? con : "NULL");
+       fprintf(yyout, "{ ECPGdo(__LINE__, %d, %d, %s, \"", compat, force_indicator, con ? con : "NULL");
 
        /* output this char by char as we have to filter '\"' */
        for (i = 0; i < j; i++)
index 92776168822ec05eecb510229f97365418bc648f..ff175700cf4b41a9388b87955dd86557dccfef02 100644 (file)
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.237 2003/06/24 23:14:49 momjian Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.238 2003/06/25 10:44:21 meskes Exp $ */
 
 /* Copyright comment */
 %{
@@ -275,10 +275,10 @@ adjust_informix(struct arguments *list)
         CREATE CREATEDB CREATEUSER CROSS CURRENT_DATE CURRENT_TIME
         CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
 
-        DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT
+        DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
        DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS
        DESC DISTINCT DO DOMAIN_P DOUBLE_P DROP
-        EACH ELSE ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUSIVE
+        EACH ELSE ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUSIVE EXCLUDING
         EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
 
         FALSE_P FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD FREEZE FROM
@@ -287,9 +287,10 @@ adjust_informix(struct arguments *list)
        GET GLOBAL GRANT GROUP_P
         HANDLER HAVING HOLD HOUR_P
 
-       ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCREMENT INDEX INHERITS
-        INITIALLY INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P
-        INTEGER INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
+       ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT
+       INDEX INHERITS INITIALLY INNER_P INOUT INPUT_P
+       INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT
+       INTERVAL INTO INVOKER IS ISNULL ISOLATION
 
         JOIN
 
@@ -397,7 +398,7 @@ adjust_informix(struct arguments *list)
 %type  <str>   columnList DeleteStmt LockStmt UpdateStmt DeclareCursorStmt
 %type  <str>   NotifyStmt columnElem UnlistenStmt TableElement rowdefinition
 %type  <str>   copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary
-%type  <str>   FetchStmt from_in CreateOpClassStmt
+%type  <str>   FetchStmt from_in CreateOpClassStmt like_including_defaults
 %type  <str>   ClosePortalStmt DropStmt VacuumStmt AnalyzeStmt opt_verbose
 %type  <str>   opt_full func_arg OptWithOids opt_freeze 
 %type  <str>   analyze_keyword opt_name_list ExplainStmt index_params
@@ -615,10 +616,7 @@ stmt:  AlterDatabaseSetStmt                { output_statement($1, 0, connection); }
                        if (connection)
                                mmerror(PARSE_ERROR, ET_ERROR, "no at option for connect statement.\n");
 
-                       if (compat == ECPG_COMPAT_INFORMIX)
-                               fprintf(yyout, "{ ECPGconnect_informix(__LINE__, %s, %d); ", $1, autocommit);
-                       else
-                               fprintf(yyout, "{ ECPGconnect(__LINE__, %s, %d); ", $1, autocommit);
+                       fprintf(yyout, "{ ECPGconnect(__LINE__, %d, %s, %d); ", compat, $1, autocommit);
                        reset_variables();
                        whenever_action(2);
                        free($1);
@@ -674,10 +672,7 @@ stmt:  AlterDatabaseSetStmt                { output_statement($1, 0, connection); }
                }
                | ECPGFree
                {
-                       if (compat == ECPG_COMPAT_INFORMIX)
-                               fprintf(yyout, "{ ECPGdeallocate_informix(__LINE__, \"%s\");", $1);
-                       else
-                               fprintf(yyout, "{ ECPGdeallocate(__LINE__, \"%s\");", $1);
+                       fprintf(yyout, "{ ECPGdeallocate(__LINE__, %d, \"%s\");", compat, $1);
 
                        whenever_action(2);
                        free($1);
@@ -1311,13 +1306,18 @@ ConstraintAttr: DEFERRABLE              { $$ = make_str("deferrable"); }
                | INITIALLY IMMEDIATE   { $$ = make_str("initially immediate"); }
                ;
 
-TableLikeClause:  LIKE any_name
-                       {
-                               mmerror(PARSE_ERROR, ET_ERROR, "LIKE in table definitions not yet supported");
-                               $$ = cat2_str(make_str("like"), $2);
-                       }
+TableLikeClause:  LIKE qualified_name like_including_defaults
+               {
+                       $$ = cat_str(3, make_str("like"), $2, $3);
+               }
                ;
 
+like_including_defaults:
+               INCLUDING DEFAULTS      { $$ = make_str("including defaults"); }
+              | EXCLUDING DEFAULTS     { $$ = make_str("excluding defaults"); }
+              | /* EMPTY */            { $$ = EMPTY; } 
+             ;
+
 /* ConstraintElem specifies constraint syntax which is not embedded into
  *     a column definition. ColConstraintElem specifies the embedded form.
  * - thomas 1997-12-03
@@ -3476,6 +3476,8 @@ a_expr:  c_expr
                        { $$ = cat_str(3, $1, make_str("not in"), $4); }
                | a_expr qual_all_Op sub_type select_with_parens %prec Op
                        { $$ = cat_str(4, $1, $2, $3, $4); }
+               | a_expr qual_all_Op sub_type '(' a_expr ')' %prec Op
+                       { $$ = cat_str(6, $1, $2, $3, make_str("("), $5, make_str(")")); }
                | UNIQUE select_with_parens %prec Op
                        { $$ = cat2_str(make_str("unique"), $2); }
                | r_expr
@@ -3881,6 +3883,8 @@ inf_val_list: a_expr
 
 update_target_el:  ColId opt_indirection '=' a_expr
                        { $$ = cat_str(4, $1, $2, make_str("="), $4); }
+               | ColId opt_indirection '=' DEFAULT
+                       { $$ = cat_str(3, $1, $2, make_str("= default")); }
                ;
 
 insert_target_list:  insert_target_list ',' insert_target_el
@@ -5744,6 +5748,7 @@ unreserved_keyword:
                | DAY_P                         { $$ = make_str("day"); }
                | DEALLOCATE                    { $$ = make_str("deallocate"); }
                | DECLARE                       { $$ = make_str("declare"); }
+               | DEFAULTS                      { $$ = make_str("defaults"); }
                | DEFERRED                      { $$ = make_str("deferred"); }
                | DELETE_P                      { $$ = make_str("delete"); }
                | DELIMITER                     { $$ = make_str("delimiter"); }
@@ -5755,6 +5760,7 @@ unreserved_keyword:
                | ENCODING                      { $$ = make_str("encoding"); }
                | ENCRYPTED                     { $$ = make_str("encrypted"); }
                | ESCAPE                        { $$ = make_str("escape"); }
+               | EXCLUDING                     { $$ = make_str("excluding"); }
                | EXCLUSIVE                     { $$ = make_str("exclusive"); }
                | EXECUTE                       { $$ = make_str("execute"); }
                | EXPLAIN                       { $$ = make_str("explain"); }
@@ -5770,6 +5776,7 @@ unreserved_keyword:
                | IMMEDIATE                     { $$ = make_str("immediate"); }
                | IMMUTABLE                     { $$ = make_str("immutable"); }
                | IMPLICIT_P                    { $$ = make_str("implicit"); }
+               | INCLUDING                     { $$ = make_str("including"); }
                | INCREMENT                     { $$ = make_str("increment"); }
                | INDEX                         { $$ = make_str("index"); }
                | INHERITS                      { $$ = make_str("inherits"); }
index eb3860128fa9570dc18abcff2838352543357b58..78bbcbe286a0e649d194bd08dd2ead40ec1d5f1a 100644 (file)
@@ -1,4 +1,4 @@
-# $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Makefile,v 1.36 2003/04/08 17:09:51 tgl Exp $
+# $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Makefile,v 1.37 2003/06/25 10:44:21 meskes Exp $
 
 subdir = src/interfaces/ecpg/test
 top_builddir = ../../../..
@@ -8,15 +8,21 @@ override CPPFLAGS := -I$(srcdir)/../include $(CPPFLAGS)
 
 ECPG = ../preproc/ecpg -I$(srcdir)/../include
 
-TESTS = test1 test2 test3 test4 perftest dyntest dyntest2 test_notice test_code100 test_init testdynalloc num_test dt_test
+TESTS = test1 test2 test3 test4 perftest dyntest dyntest2 test_notice test_code100 test_init testdynalloc num_test dt_test test_informix
 
 all: $(TESTS)
 
 %: %.o
        $(CC) $(CFLAGS) $(LDFLAGS) -L../ecpglib -L ../pgtypeslib -L../../libpq $^ $(LIBS) -lpgtypes -lecpg -lpq -o $@
 
+test_informix: test_informix.o
+       $(CC) $(CFLAGS) $(LDFLAGS) -L../compatlib -L../ecpglib -L ../pgtypeslib -L../../libpq $^ $(LIBS) -lpgtypes -lecpg -lecpg_compat -lpq -o $@
+       
 %.c: %.pgc
        $(ECPG) $<
 
+test_informix.c: test_informix.pgc
+       $(ECPG) -C INFORMIX $<
 clean:
        rm -f $(TESTS) $(TESTS:%=%.o) $(TESTS:%=%.c) log
+       
diff --git a/src/interfaces/ecpg/test/test_informix.pgc b/src/interfaces/ecpg/test/test_informix.pgc
new file mode 100644 (file)
index 0000000..fd0512c
--- /dev/null
@@ -0,0 +1,49 @@
+#include "sqltypes.h"
+
+void openit(void);
+
+int main()
+{
+       $int i = 14; 
+       $int j;
+       FILE *dbgs;
+
+       if ((dbgs = fopen("log", "w")) != NULL)
+               ECPGdebug(1, dbgs);
+       
+       $connect to mm;
+
+       $create table test(i int primary key, j int);
+
+       rsetnull(CINTTYPE, (char *)&j);
+       $insert into test (i, j) values (7, :j);
+       $insert into test (i, j) values (:i, 1);
+
+       $declare c cursor for select * from test where i <= :i;
+       openit();
+
+       j=0;
+       while (1)
+       {
+               $fetch in c into :i, :j;
+               if (sqlca.sqlcode == 100) break;
+               else if (sqlca.sqlcode != 0) printf ("Error: %ld\n", sqlca.sqlcode);
+
+               if (risnull(CINTTYPE, (char *)&j))
+                       printf("%d\n", i);
+               else
+                       printf("%d %d\n", i, j);
+       }
+       
+       $drop table test;
+
+       $disconnect;
+
+       return 0;
+}
+
+void openit(void)
+{
+       $open c;
+}
+