Commit 1a9b0613 authored by Michael Meskes's avatar Michael Meskes

- Applied error reporting patch by Matthew Vanecek

- Started with an Informix compatibility option.
parent e529e9fa
...@@ -1324,3 +1324,13 @@ Tue Jan 21 20:50:58 CET 2003 ...@@ -1324,3 +1324,13 @@ Tue Jan 21 20:50:58 CET 2003
- Set ecpg version to 2.11.0. - Set ecpg version to 2.11.0.
- Synced preproc.y with gram.y. - Synced preproc.y with gram.y.
Thu Feb 13 14:06:28 CET 2003
- Applied patch by Matthew Vanecek <mevanecek@yahoo.com> for better
error reporting.
- Started working on an Informix compatibility mode. With option "-C
INFORMIX" set, ecpg now accepts "$" as alias for "exec sql" and to
denote variables inside SQL statements.
- Set ecpg version to 2.12.0.
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# #
# Copyright (c) 1994, Regents of the University of California # Copyright (c) 1994, Regents of the University of California
# #
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile,v 1.18 2002/12/11 04:07:39 momjian Exp $ # $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile,v 1.19 2003/02/13 13:11:52 meskes Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -16,7 +16,7 @@ NAME= ecpg ...@@ -16,7 +16,7 @@ NAME= ecpg
SO_MAJOR_VERSION= 3 SO_MAJOR_VERSION= 3
SO_MINOR_VERSION= 4.2 SO_MINOR_VERSION= 4.2
override CPPFLAGS := -I$(top_srcdir)/src/interfaces/ecpg/include -I$(libpq_srcdir) $(CPPFLAGS) override CPPFLAGS := -g -I$(top_srcdir)/src/interfaces/ecpg/include -I$(libpq_srcdir) $(CPPFLAGS)
OBJS= execute.o typename.o descriptor.o data.o error.o prepare.o memory.o \ OBJS= execute.o typename.o descriptor.o data.o error.o prepare.o memory.o \
......
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/connect.c,v 1.19 2002/09/04 20:31:46 momjian Exp $ */ /* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/connect.c,v 1.20 2003/02/13 13:11:52 meskes Exp $ */
#include "postgres_fe.h" #include "postgres_fe.h"
...@@ -419,15 +419,20 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd, ...@@ -419,15 +419,20 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd,
if (PQstatus(this->connection) == CONNECTION_BAD) if (PQstatus(this->connection) == CONNECTION_BAD)
{ {
const char *errmsg = PQerrorMessage(this->connection);
char *db = realname ? realname : "<DEFAULT>";
set_backend_err(errmsg, lineno);
ecpg_finish(this); ecpg_finish(this);
ECPGlog("connect: could not open database %s on %s port %s %s%s%s%s in line %d\n", ECPGlog("connect: could not open database %s on %s port %s %s%s%s%s in line %d\n\t%s\n",
realname ? realname : "<DEFAULT>", db,
host ? host : "<DEFAULT>", host ? host : "<DEFAULT>",
port ? port : "<DEFAULT>", port ? port : "<DEFAULT>",
options ? "with options " : "", options ? options : "", options ? "with options " : "", options ? options : "",
user ? "for user " : "", user ? user : "", user ? "for user " : "", user ? user : "",
lineno); lineno, errmsg);
ECPGraise(lineno, ECPG_CONNECT, realname ? realname : "<DEFAULT>");
ECPGraise(lineno, ECPG_CONNECT, db);
if (host) if (host)
ECPGfree(host); ECPGfree(host);
if (port) if (port)
......
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/error.c,v 1.16 2002/09/04 20:31:46 momjian Exp $ */ /* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/error.c,v 1.17 2003/02/13 13:11:52 meskes Exp $ */
#include "postgres_fe.h" #include "postgres_fe.h"
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
#include "extern.h" #include "extern.h"
#include "sqlca.h" #include "sqlca.h"
/* This should hold the back-end error message from
* the last back-end operation. */
char *ECPGerr;
void void
ECPGraise(int line, int code, const char *str) ECPGraise(int line, int code, const char *str)
{ {
...@@ -162,6 +166,29 @@ ECPGraise(int line, int code, const char *str) ...@@ -162,6 +166,29 @@ ECPGraise(int line, int code, const char *str)
ECPGfree_auto_mem(); ECPGfree_auto_mem();
} }
/* Set the error message string from the backend */
void
set_backend_err(const char *err, int lineno)
{
if (ECPGerr)
ECPGfree(ECPGerr);
if (!err)
{
ECPGerr = NULL;
return;
}
ECPGerr = ECPGstrdup(err, lineno);
}
/* Retrieve the error message from the backend. */
char *
ECPGerrmsg(void)
{
return ECPGerr;
}
/* print out an error message */ /* print out an error message */
void void
sqlprint(void) sqlprint(void)
......
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/execute.c,v 1.40 2002/10/21 13:09:31 meskes Exp $ */ /* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/execute.c,v 1.41 2003/02/13 13:11:52 meskes Exp $ */
/* /*
* The aim is to get a simpler inteface to the database routines. * The aim is to get a simpler inteface to the database routines.
...@@ -850,6 +850,7 @@ ECPGexecute(struct statement * stmt) ...@@ -850,6 +850,7 @@ ECPGexecute(struct statement * stmt)
{ {
bool status = false; bool status = false;
char *copiedquery; char *copiedquery;
char *errmsg, *cmdstat;
PGresult *results; PGresult *results;
PGnotify *notify; PGnotify *notify;
struct variable *var; struct variable *var;
...@@ -949,9 +950,10 @@ ECPGexecute(struct statement * stmt) ...@@ -949,9 +950,10 @@ ECPGexecute(struct statement * stmt)
if (results == NULL) if (results == NULL)
{ {
ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno, errmsg = PQerrorMessage(stmt->connection->connection);
PQerrorMessage(stmt->connection->connection)); ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno, errmsg);
ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection)); ECPGraise(stmt->lineno, ECPG_PGSQL, errmsg);
set_backend_err(errmsg, stmt->lineno);
} }
else else
...@@ -961,7 +963,9 @@ ECPGexecute(struct statement * stmt) ...@@ -961,7 +963,9 @@ ECPGexecute(struct statement * stmt)
*/ */
{ {
bool clear_result = TRUE; bool clear_result = TRUE;
errmsg = PQresultErrorMessage(results);
set_backend_err(errmsg, stmt->lineno);
var = stmt->outlist; var = stmt->outlist;
switch (PQresultStatus(results)) switch (PQresultStatus(results))
{ {
...@@ -1027,20 +1031,20 @@ ECPGexecute(struct statement * stmt) ...@@ -1027,20 +1031,20 @@ ECPGexecute(struct statement * stmt)
break; break;
case PGRES_COMMAND_OK: case PGRES_COMMAND_OK:
status = true; status = true;
cmdstat = PQcmdStatus(results);
sqlca.sqlerrd[1] = PQoidValue(results); sqlca.sqlerrd[1] = PQoidValue(results);
sqlca.sqlerrd[2] = atol(PQcmdTuples(results)); sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, PQcmdStatus(results)); ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, cmdstat);
if (!sqlca.sqlerrd[2] && (!strncmp(PQcmdStatus(results), "UPDATE", 6) if (!sqlca.sqlerrd[2] && ( !strncmp(cmdstat, "UPDATE", 6)
|| !strncmp(PQcmdStatus(results), "INSERT", 6) || !strncmp(cmdstat, "INSERT", 6)
|| !strncmp(PQcmdStatus(results), "DELETE", 6))) || !strncmp(cmdstat, "DELETE", 6)))
ECPGraise(stmt->lineno, ECPG_NOT_FOUND, NULL); ECPGraise(stmt->lineno, ECPG_NOT_FOUND, NULL);
break; break;
case PGRES_NONFATAL_ERROR: case PGRES_NONFATAL_ERROR:
case PGRES_FATAL_ERROR: case PGRES_FATAL_ERROR:
case PGRES_BAD_RESPONSE: case PGRES_BAD_RESPONSE:
ECPGlog("ECPGexecute line %d: Error: %s", ECPGlog("ECPGexecute line %d: Error: %s", stmt->lineno, errmsg);
stmt->lineno, PQerrorMessage(stmt->connection->connection)); ECPGraise(stmt->lineno, ECPG_PGSQL, errmsg);
ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection));
status = false; status = false;
break; break;
case PGRES_COPY_OUT: case PGRES_COPY_OUT:
...@@ -1054,7 +1058,7 @@ ECPGexecute(struct statement * stmt) ...@@ -1054,7 +1058,7 @@ ECPGexecute(struct statement * stmt)
default: default:
ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n", ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
stmt->lineno); stmt->lineno);
ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection)); ECPGraise(stmt->lineno, ECPG_PGSQL, errmsg);
status = false; status = false;
break; break;
} }
......
...@@ -5,6 +5,10 @@ ...@@ -5,6 +5,10 @@
#include "libpq-fe.h" #include "libpq-fe.h"
/* Here are some methods used by the lib. */ /* Here are some methods used by the lib. */
/* Stores the backend error message for client access */
void set_backend_err(const char *err, int lineon);
/* Returns a pointer to a string containing a simple type name. */ /* Returns a pointer to a string containing a simple type name. */
void ECPGadd_mem(void *ptr, int lineno); void ECPGadd_mem(void *ptr, int lineno);
......
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.58 2002/10/18 22:05:36 petere Exp $ */ /* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.59 2003/02/13 13:11:52 meskes Exp $ */
/* New main for ecpg, the PostgreSQL embedded SQL precompiler. */ /* New main for ecpg, the PostgreSQL embedded SQL precompiler. */
/* (C) Michael Meskes <meskes@postgresql.org> Feb 5th, 1998 */ /* (C) Michael Meskes <meskes@postgresql.org> Feb 5th, 1998 */
...@@ -19,6 +19,9 @@ extern char *optarg; ...@@ -19,6 +19,9 @@ extern char *optarg;
int ret_value = 0, int ret_value = 0,
autocommit = false, autocommit = false,
auto_create_c = false; auto_create_c = false;
enum COMPAT_MODE compat = ECPG_COMPAT_PGSQL;
struct _include_path *include_paths = NULL; struct _include_path *include_paths = NULL;
struct cursor *cur = NULL; struct cursor *cur = NULL;
struct typedefs *types = NULL; struct typedefs *types = NULL;
...@@ -38,6 +41,8 @@ help(const char *progname) ...@@ -38,6 +41,8 @@ help(const char *progname)
#ifdef YYDEBUG #ifdef YYDEBUG
printf(" -d generate parser debug output\n"); printf(" -d generate parser debug output\n");
#endif #endif
printf(" -C <mode> set compatibility mode\n"
" mode may be INFORMIX only at the moment\n");
printf(" -D SYMBOL define SYMBOL\n"); printf(" -D SYMBOL define SYMBOL\n");
printf(" -I DIRECTORY search DIRECTORY for include files\n"); printf(" -I DIRECTORY search DIRECTORY for include files\n");
printf(" -o OUTFILE write result to OUTFILE\n"); printf(" -o OUTFILE write result to OUTFILE\n");
...@@ -107,7 +112,7 @@ main(int argc, char *const argv[]) ...@@ -107,7 +112,7 @@ main(int argc, char *const argv[])
add_include_path("/usr/local/include"); add_include_path("/usr/local/include");
add_include_path("."); add_include_path(".");
while ((c = getopt(argc, argv, "vco:I:tD:d")) != -1) while ((c = getopt(argc, argv, "vco:I:tD:dC:")) != -1)
{ {
switch (c) switch (c)
{ {
...@@ -130,6 +135,15 @@ main(int argc, char *const argv[]) ...@@ -130,6 +135,15 @@ main(int argc, char *const argv[])
case 'c': case 'c':
auto_create_c = true; auto_create_c = true;
break; break;
case 'C':
if (strcmp(optarg, "INFORMIX") == 0)
compat = ECPG_COMPAT_INFORMIX;
else
{
fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
return ILLEGAL_OPTION;
}
break;
case 'D': case 'D':
add_preprocessor_define(optarg); add_preprocessor_define(optarg);
break; break;
......
...@@ -93,4 +93,7 @@ extern ScanKeyword *ScanKeywordLookup(char *text); ...@@ -93,4 +93,7 @@ extern ScanKeyword *ScanKeywordLookup(char *text);
#define INDICATOR_NOT_STRUCT 6 #define INDICATOR_NOT_STRUCT 6
#define INDICATOR_NOT_SIMPLE 7 #define INDICATOR_NOT_SIMPLE 7
enum COMPAT_MODE { ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX};
extern enum COMPAT_MODE compat;
#endif /* _ECPG_PREPROC_EXTERN_H */ #endif /* _ECPG_PREPROC_EXTERN_H */
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.101 2002/11/07 06:06:17 tgl Exp $ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.102 2003/02/13 13:11:52 meskes Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -70,7 +70,6 @@ static struct _if_value ...@@ -70,7 +70,6 @@ static struct _if_value
%option 8bit %option 8bit
%option never-interactive %option never-interactive
%option nounput
%option noyywrap %option noyywrap
%option yylineno %option yylineno
...@@ -247,6 +246,10 @@ whitespace ({space}+|{comment}) ...@@ -247,6 +246,10 @@ whitespace ({space}+|{comment})
horiz_whitespace ({horiz_space}|{comment}) horiz_whitespace ({horiz_space}|{comment})
whitespace_with_newline ({horiz_whitespace}*{newline}{whitespace}*) whitespace_with_newline ({horiz_whitespace}*{newline}{whitespace}*)
/* special characters for other dbms */
/* we have to react differently in compat mode */
informix_special [\$]
other . other .
/* some stuff needed for ecpg */ /* some stuff needed for ecpg */
...@@ -416,6 +419,16 @@ cppline {space}*#(.*\\{space})*.* ...@@ -416,6 +419,16 @@ cppline {space}*#(.*\\{space})*.*
} }
<xdc>{xdcinside} { addlit(yytext, yyleng); } <xdc>{xdcinside} { addlit(yytext, yyleng); }
<SQL>{typecast} { return TYPECAST; } <SQL>{typecast} { return TYPECAST; }
<SQL>{informix_special} {
/* are we simulating Informix? */
if (compat == ECPG_COMPAT_INFORMIX)
{
printf ("unput $\n");
unput(':');
}
else
return yytext[0];
}
<SQL>{self} { /* <SQL>{self} { /*
* We may find a ';' inside a structure * We may find a ';' inside a structure
* definition in a TYPE or VAR statement. * definition in a TYPE or VAR statement.
...@@ -584,7 +597,17 @@ cppline {space}*#(.*\\{space})*.* ...@@ -584,7 +597,17 @@ cppline {space}*#(.*\\{space})*.*
} }
<SQL>{other} { return yytext[0]; } <SQL>{other} { return yytext[0]; }
<C>{exec_sql} { BEGIN SQL; return SQL_START; } <C>{exec_sql} { BEGIN SQL; return SQL_START; }
<C>{ccomment} { /* ignore */ } <C>{informix_special} {
/* are we simulating Informix? */
if (compat == ECPG_COMPAT_INFORMIX)
{
BEGIN SQL;
return SQL_START;
}
else
return S_ANYTHING;
}
<C>{ccomment} { /* ignore */ }
<C>{xch} { <C>{xch} {
char* endptr; char* endptr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment