From 26188e8c1751a2ef97fb6192fbc1bbc9f313a4d6 Mon Sep 17 00:00:00 2001 From: Michael Meskes Date: Fri, 13 Jun 2003 10:50:58 +0000 Subject: [PATCH] - Enable FETCH without INTO. - Compatibility functions for INFORMIX handling of DECLARE statement. --- src/interfaces/ecpg/ChangeLog | 5 ++ src/interfaces/ecpg/compatlib/informix.c | 55 +++++++++++++++++++++ src/interfaces/ecpg/ecpglib/connect.c | 19 +------ src/interfaces/ecpg/ecpglib/execute.c | 4 +- src/interfaces/ecpg/include/ecpg_informix.h | 6 ++- src/interfaces/ecpg/include/ecpglib.h | 1 - src/interfaces/ecpg/preproc/ecpg.c | 5 +- src/interfaces/ecpg/preproc/extern.h | 3 +- src/interfaces/ecpg/preproc/preproc.y | 49 ++++++++++++++++-- src/interfaces/ecpg/test/test2.pgc | 6 +-- 10 files changed, 123 insertions(+), 30 deletions(-) diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index 858c7f9111..284b94f2ba 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -1482,6 +1482,11 @@ Wed Jun 11 08:30:41 CEST 2003 - Make sure a variable is no longer referenced when it is removed. - Fixed counting bug in parsing "->" operator. + +Fri Jun 13 10:11:12 CEST 2003 + + - Enable FETCH without INTO. + - Compatibility functions for INFORMIX handling of DECLARE statement. - Set ecpg version to 2.12.0. - Set ecpg library to 3.4.2. - Set pgtypes library to 1.0.0 diff --git a/src/interfaces/ecpg/compatlib/informix.c b/src/interfaces/ecpg/compatlib/informix.c index 078cc1b295..3729fe3dd1 100644 --- a/src/interfaces/ecpg/compatlib/informix.c +++ b/src/interfaces/ecpg/compatlib/informix.c @@ -8,6 +8,8 @@ #include #include +char * ECPGalloc(long, int); + /* we start with the numeric functions */ int decadd(Numeric *arg1, Numeric *arg2, Numeric *sum) @@ -673,3 +675,56 @@ 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)); +} + +static struct var_list +{ + int number; + void *pointer; + struct var_list *next; +} *ivlist = NULL; + +void +ECPG_informix_set_var(int number, void *pointer, int lineno) +{ + struct var_list *ptr; + + for (ptr = ivlist; ptr != NULL; ptr = ptr->next) + { + if (ptr->number == number) + { + /* already known => just change pointer value */ + ptr->pointer = pointer; + return; + } + } + + /* a new one has to be added */ + ptr = (struct var_list *) ECPGalloc (sizeof(struct var_list), lineno); + ptr->number = number; + ptr->pointer = pointer; + ptr->next = ivlist; + ivlist = ptr; +} + +void * +ECPG_informix_get_var(int number) +{ + struct var_list *ptr; + + for (ptr = ivlist; ptr != NULL && ptr->number != number; ptr = ptr->next); + return (ptr) ? ptr->pointer : NULL; +} + diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c index 0c8ac72f18..61e078da90 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.5 2003/05/20 11:05:27 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.6 2003/06/13 10:50:57 meskes Exp $ */ #include "postgres_fe.h" @@ -257,21 +257,6 @@ ECPGnoticeProcessor(void *arg, const char *message) sqlca.sqlwarn[0] = 'W'; } -/* this contains some quick hacks, needs to be cleaned up, but it works */ -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)); -} - /* 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) @@ -341,7 +326,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/execute.c b/src/interfaces/ecpg/ecpglib/execute.c index 99850664e8..03d1fbd646 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.8 2003/04/01 14:37:25 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.9 2003/06/13 10:50:57 meskes Exp $ */ /* * The aim is to get a simpler inteface to the database routines. @@ -1239,7 +1239,7 @@ ECPGexecute(struct statement * stmt) { ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n", stmt->lineno, notify->relname, notify->be_pid); - PQfreemem(notify); + PQfreemem(notify); } return status; diff --git a/src/interfaces/ecpg/include/ecpg_informix.h b/src/interfaces/ecpg/include/ecpg_informix.h index ff75759837..4493dc6f29 100644 --- a/src/interfaces/ecpg/include/ecpg_informix.h +++ b/src/interfaces/ecpg/include/ecpg_informix.h @@ -4,6 +4,7 @@ #include #include +#include #define SQLNOTFOUND 100 @@ -31,4 +32,7 @@ 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 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 679ff1a763..21e2db33f0 100644 --- a/src/interfaces/ecpg/include/ecpglib.h +++ b/src/interfaces/ecpg/include/ecpglib.h @@ -42,7 +42,6 @@ void ECPGdebug(int, FILE *); bool ECPGstatus(int, const char *); bool ECPGsetcommit(int, const char *, const char *); bool ECPGsetconn(int, const char *); -bool ECPGconnect_informix(int, const char *, const char *, const char *, const char *, int); bool ECPGconnect(int, const char *, const char *, const char *, const char *, int); bool ECPGdo(int, const char *, char *,...); bool ECPGtrans(int, const char *, const char *); diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c index d219047df7..bba130792d 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.72 2003/05/30 08:39:00 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.73 2003/06/13 10:50:57 meskes Exp $ */ /* New main for ecpg, the PostgreSQL embedded SQL precompiler. */ /* (C) Michael Meskes Feb 5th, 1998 */ @@ -359,6 +359,9 @@ main(int argc, char *const argv[]) /* and structure member lists */ memset(struct_member_list, 0, sizeof(struct_member_list)); + /* and our variable counter for Informix compatibility */ + ecpg_informix_var = 0; + /* finally the actual connection */ connection = NULL; diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h index bc0cceaae9..ae6c5bc204 100644 --- a/src/interfaces/ecpg/preproc/extern.h +++ b/src/interfaces/ecpg/preproc/extern.h @@ -17,7 +17,8 @@ extern int braces_open, auto_create_c, system_includes, ret_value, - struct_level; + struct_level, + ecpg_informix_var; extern char *descriptor_index; extern char *descriptor_name; extern char *connection; diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 83015d04a5..fa622f314b 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.230 2003/06/11 06:39:12 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.231 2003/06/13 10:50:57 meskes Exp $ */ /* Copyright comment */ %{ @@ -11,6 +11,7 @@ */ int struct_level = 0; int braces_open; /* brace level counter */ +int ecpg_informix_var = 0; char errortext[128]; char *connection = NULL; char *input_filename = NULL; @@ -141,6 +142,7 @@ make3_str(char *str1, char *str2, char *str3) return(res_str); } +/* and the rest */ static char * make_name(void) { @@ -186,6 +188,36 @@ create_questionmarks(char *name, bool array) return(result); } +static char * +adjust_informix(struct arguments *list) +{ + /* Informix accepts DECLARE with variables that are out of scope when OPEN is called. + * This breaks standard and leads to some very dangerous programming. + * Since they do, we have to work around and accept their syntax as well. + * But we will do so ONLY in Informix mode. + * We have to change the variables to our own struct and just store the pointer instead of the variable */ + + struct arguments *ptr; + char *result = make_str(""); + + for (ptr = list; ptr != NULL; ptr = ptr->next) + { + char temp[sizeof(int)+sizeof(", &()")]; + char *original_var; + + /* change variable name to "ECPG_informix_get_var()" */ + original_var = ptr->variable->name; + sprintf(temp, "%d))", ecpg_informix_var); + ptr->variable = new_variable(cat_str(4, make_str("*("), mm_strdup(ECPGtype_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size), 0); + + /* create call to "ECPG_informix_set_var(, . )" */ + sprintf(temp, "%d, &(", ecpg_informix_var++); + result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n")); + } + + return result; +} + %} %union { @@ -1098,7 +1130,10 @@ opt_drop_behavior: CASCADE { $$ = make_str("cascade"); } * *****************************************************************************/ -ClosePortalStmt: CLOSE name { $$ = cat2_str(make_str("close"), $2); } +ClosePortalStmt: CLOSE name + { + $$ = cat2_str(make_str("close"), $2); + } ; /***************************************************************************** @@ -1734,6 +1769,10 @@ FetchStmt: FETCH fetch_direction from_in name ecpg_into_using { $$ = cat_str(4, make_str("fetch"), $2, $3, $4); } | FETCH name ecpg_into_using { $$ = cat2_str(make_str("fetch"), $2); } + | FETCH fetch_direction from_in name + { $$ = cat_str(4, make_str("fetch"), $2, $3, $4); } + | FETCH name + { $$ = cat2_str(make_str("fetch"), $2); } | MOVE fetch_direction from_in name { $$ = cat_str(4, make_str("move"), $2, $3, $4); } | MOVE name @@ -2630,10 +2669,12 @@ DeclareCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt this->argsinsert = argsinsert; this->argsresult = argsresult; argsinsert = argsresult = NULL; - cur = this; - $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/")); + if (compat == ECPG_COMPAT_INFORMIX) + $$ = cat_str(5, adjust_informix(this->argsinsert), adjust_informix(this->argsresult), make_str("/*"), mm_strdup(this->command), make_str("*/")); + else + $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/")); } ; diff --git a/src/interfaces/ecpg/test/test2.pgc b/src/interfaces/ecpg/test/test2.pgc index 701b11afb5..0d11c0c38a 100644 --- a/src/interfaces/ecpg/test/test2.pgc +++ b/src/interfaces/ecpg/test/test2.pgc @@ -12,6 +12,9 @@ typedef union { int integer; short smallint; } ind; #define BUFFERSIZ 8 exec sql type str is varchar[BUFFERSIZ]; +exec sql declare cur cursor for + select name, born, age, married, children from meskes; + int main () { @@ -34,9 +37,6 @@ exec sql end declare section; exec sql var ind_married is long; - exec sql declare cur cursor for - select name, born, age, married, children from meskes; - char msg[128]; FILE *dbgs; -- 2.40.0