diff options
Diffstat (limited to 'src')
20 files changed, 373 insertions, 156 deletions
diff --git a/src/interfaces/ecpg/compatlib/informix.c b/src/interfaces/ecpg/compatlib/informix.c index 2ac89e8f7e1..71f914d0369 100644 --- a/src/interfaces/ecpg/compatlib/informix.c +++ b/src/interfaces/ecpg/compatlib/informix.c @@ -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> @@ -646,18 +647,6 @@ rgetmsg(int msgnum, char *s, int maxsize) } int -risnull(int vtype, char *pcvar) -{ - return 0; -} - -int -rsetnull(int vtype, char *pcvar) -{ - return 0; -} - -int rtypalign(int offset, int type) { return 0; @@ -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)); +} + diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c index 58692a1b1be..cda4bbd15bf 100644 --- a/src/interfaces/ecpg/ecpglib/connect.c +++ b/src/interfaces/ecpg/ecpglib/connect.c @@ -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); diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c index 0930380829f..8e0138d527d 100644 --- a/src/interfaces/ecpg/ecpglib/data.c +++ b/src/interfaces/ecpg/ecpglib/data.c @@ -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 diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c index 4bc0ba80174..af4d23b7e79 100644 --- a/src/interfaces/ecpg/ecpglib/execute.c +++ b/src/interfaces/ecpg/ecpglib/execute.c @@ -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); } + diff --git a/src/interfaces/ecpg/ecpglib/extern.h b/src/interfaces/ecpg/ecpglib/extern.h index a43526c7603..a7f37491da8 100644 --- a/src/interfaces/ecpg/ecpglib/extern.h +++ b/src/interfaces/ecpg/ecpglib/extern.h @@ -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; }; diff --git a/src/interfaces/ecpg/ecpglib/misc.c b/src/interfaces/ecpg/ecpglib/misc.c index ae2e090fe98..ae78f97b85a 100644 --- a/src/interfaces/ecpg/ecpglib/misc.c +++ b/src/interfaces/ecpg/ecpglib/misc.c @@ -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" @@ -12,6 +12,10 @@ #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; +} diff --git a/src/interfaces/ecpg/ecpglib/prepare.c b/src/interfaces/ecpg/ecpglib/prepare.c index 5f8c92c092c..a10f386fc8c 100644 --- a/src/interfaces/ecpg/ecpglib/prepare.c +++ b/src/interfaces/ecpg/ecpglib/prepare.c @@ -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; diff --git a/src/interfaces/ecpg/include/Makefile b/src/interfaces/ecpg/include/Makefile index 9226bac8c41..e4c1530f3c7 100644 --- a/src/interfaces/ecpg/include/Makefile +++ b/src/interfaces/ecpg/include/Makefile @@ -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 diff --git a/src/interfaces/ecpg/include/ecpg_informix.h b/src/interfaces/ecpg/include/ecpg_informix.h index f7947866326..59991c70a91 100644 --- a/src/interfaces/ecpg/include/ecpg_informix.h +++ b/src/interfaces/ecpg/include/ecpg_informix.h @@ -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); diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h index ae272927c6f..66985bf3b60 100644 --- a/src/interfaces/ecpg/include/ecpglib.h +++ b/src/interfaces/ecpg/include/ecpglib.h @@ -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 } diff --git a/src/interfaces/ecpg/include/pgtypes_numeric.h b/src/interfaces/ecpg/include/pgtypes_numeric.h index 685326e4a80..cd7552db384 100644 --- a/src/interfaces/ecpg/include/pgtypes_numeric.h +++ b/src/interfaces/ecpg/include/pgtypes_numeric.h @@ -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 diff --git a/src/interfaces/ecpg/include/sqltypes.h b/src/interfaces/ecpg/include/sqltypes.h index 5e305fb2c5b..e6a96bcf48d 100644 --- a/src/interfaces/ecpg/include/sqltypes.h +++ b/src/interfaces/ecpg/include/sqltypes.h @@ -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 diff --git a/src/interfaces/ecpg/pgtypeslib/timestamp.c b/src/interfaces/ecpg/pgtypeslib/timestamp.c index 9cea9a3db01..59449941eaf 100644 --- a/src/interfaces/ecpg/pgtypeslib/timestamp.c +++ b/src/interfaces/ecpg/pgtypeslib/timestamp.c @@ -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 */ diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c index bba130792d2..0256080a50a 100644 --- a/src/interfaces/ecpg/preproc/ecpg.c +++ b/src/interfaces/ecpg/preproc/ecpg.c @@ -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; diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h index ae6c5bc2049..f38cb244ae9 100644 --- a/src/interfaces/ecpg/preproc/extern.h +++ b/src/interfaces/ecpg/preproc/extern.h @@ -16,6 +16,7 @@ extern int braces_open, autocommit, auto_create_c, system_includes, + force_indicator, ret_value, struct_level, ecpg_informix_var; diff --git a/src/interfaces/ecpg/preproc/keywords.c b/src/interfaces/ecpg/preproc/keywords.c index e6b0d6651f4..4971c9fa7d8 100644 --- a/src/interfaces/ecpg/preproc/keywords.c +++ b/src/interfaces/ecpg/preproc/keywords.c @@ -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}, diff --git a/src/interfaces/ecpg/preproc/output.c b/src/interfaces/ecpg/preproc/output.c index 57509ea809c..055ad7f039e 100644 --- a/src/interfaces/ecpg/preproc/output.c +++ b/src/interfaces/ecpg/preproc/output.c @@ -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++) diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 92776168822..ff175700cf4 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -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"); } diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile index eb3860128fa..78bbcbe286a 100644 --- a/src/interfaces/ecpg/test/Makefile +++ b/src/interfaces/ecpg/test/Makefile @@ -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 index 00000000000..fd0512c7cde --- /dev/null +++ b/src/interfaces/ecpg/test/test_informix.pgc @@ -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; +} + |