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:
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
};
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user