1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-02 04:21:28 +03:00

Implemented Informix special way to treat NULLs, removed warnings, synced.

This commit is contained in:
Michael Meskes
2003-06-25 10:44:21 +00:00
parent ff4c69e021
commit fd3ca524eb
20 changed files with 373 additions and 156 deletions

View 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);

View 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

View 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);
}

View 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;
};

View 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"
@@ -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;
}

View 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;