diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog
index eac1b96e800be28b24089337e69206261b410771..152484943461dc7b66affe553361594ff98a00c1 100644
--- a/src/interfaces/ecpg/ChangeLog
+++ b/src/interfaces/ecpg/ChangeLog
@@ -463,3 +463,17 @@ Fri Feb 19 21:40:14 CET 1999
 	- Fixed bug in libecpg that caused it to start transactions only for
 	  the first connection.
 	- Set library version to 2.7.1
+
+Son Feb 21 14:10:47 CET 1999
+
+	- Fixed variable detection in libecpg.
+
+Mon Feb 22 19:47:45 CET 1999
+
+	- Added 'at <db_connection>' option to all commands it is apllicable
+	  to. Due to changing the API of some libecpg functions this
+	  requires me to increase the major version number.
+	- Synced pgc.l with scan.l.
+	- Added support for unions.
+	- Set library version to 3.0.0
+	- Set ecpg version to 3.0.0
diff --git a/src/interfaces/ecpg/TODO b/src/interfaces/ecpg/TODO
index 82b8a5d8b85b070dbe2eb82a6de7d08fc1b04ce7..0b4be6dd9f4da286f1f33f10c0ea772a4ee962f0 100644
--- a/src/interfaces/ecpg/TODO
+++ b/src/interfaces/ecpg/TODO
@@ -11,9 +11,9 @@ DESCRIPTOR statement will be ignored.
 
 it would be nice to be able to use :var[:index] as cvariable
 
-'at DB connection' is missing for several commands (is this standard?)
+support for dynamic SQL with unknown number of variables with SQLDA structure
 
-support for unions
+allocate memory for pointers as C input variables
 
 Missing statements:
  - exec sql allocate
diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h
index 4e1d6f9cde4b44d7c14b649f6aa5949a0fd3f7d6..98153747f6f8f37a954da5cd402e9f07036c8759 100644
--- a/src/interfaces/ecpg/include/ecpglib.h
+++ b/src/interfaces/ecpg/include/ecpglib.h
@@ -8,8 +8,8 @@ extern		"C"
 	void		ECPGdebug(int, FILE *);
 	bool		ECPGsetconn(int, const char *);
 	bool		ECPGconnect(int, const char *, const char *, const char *, const char *);
-	bool		ECPGdo(int, char *,...);
-	bool		ECPGtrans(int, const char *);
+	bool		ECPGdo(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 *);
diff --git a/src/interfaces/ecpg/include/ecpgtype.h b/src/interfaces/ecpg/include/ecpgtype.h
index e92220481da0df7176ca975970582e73992b7254..8ca4d697c158e887dd7ffd1cddc016c4978ca2fb 100644
--- a/src/interfaces/ecpg/include/ecpgtype.h
+++ b/src/interfaces/ecpg/include/ecpgtype.h
@@ -43,10 +43,10 @@ extern		"C"
 		ECPGt_varchar, ECPGt_varchar2,
 		ECPGt_array,
 		ECPGt_struct,
+		ECPGt_char_variable,
 		ECPGt_EOIT,				/* End of insert types. */
 		ECPGt_EORT,				/* End of result types. */
-		ECPGt_NO_INDICATOR,		/* no indicator */
-		ECPGt_char_variable
+		ECPGt_NO_INDICATOR		/* no indicator */
 	};
 
 #define IS_SIMPLE_TYPE(type) ((type) >= ECPGt_char && (type) <= ECPGt_varchar2)
diff --git a/src/interfaces/ecpg/lib/Makefile.in b/src/interfaces/ecpg/lib/Makefile.in
index 4872e8c0fd5ae229f9e4563f852ff21e18719de0..ef2373fa78e49fd5aa40661e243451d50afd815c 100644
--- a/src/interfaces/ecpg/lib/Makefile.in
+++ b/src/interfaces/ecpg/lib/Makefile.in
@@ -6,13 +6,13 @@
 # Copyright (c) 1994, Regents of the University of California
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.42 1999/02/21 03:02:35 scrappy Exp $
+#    $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.43 1999/02/23 12:56:55 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
 NAME= ecpg
-SO_MAJOR_VERSION= 2
-SO_MINOR_VERSION= 7.1
+SO_MAJOR_VERSION= 3
+SO_MINOR_VERSION= 0.0
 
 SRCDIR= @top_srcdir@
 include $(SRCDIR)/Makefile.global
diff --git a/src/interfaces/ecpg/lib/ecpglib.c b/src/interfaces/ecpg/lib/ecpglib.c
index 2a7745f2a6747067cd84ab9ab8781d4ec72a2228..e686edd512d4e007ce48983973fe4ab6b424ae57 100644
--- a/src/interfaces/ecpg/lib/ecpglib.c
+++ b/src/interfaces/ecpg/lib/ecpglib.c
@@ -17,6 +17,7 @@
 #include <unistd.h>
 #include <stdarg.h>
 #include <string.h>
+#include <ctype.h>
 
 #include <libpq-fe.h>
 #include <libpq/pqcomm.h>
@@ -78,6 +79,7 @@ struct statement
 {
 	int	    lineno;
 	char	   *command;
+	struct connection *connection;
 	struct variable *inlist;
 	struct variable *outlist;
 };
@@ -104,6 +106,21 @@ register_error(long code, char *fmt,...)
 	sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc);
 }
 
+static struct connection *
+get_connection(const char *connection_name)
+{
+	struct connection *con = all_connections;;
+	
+	if (connection_name == NULL || strcmp(connection_name, "CURRENT") == 0)
+		return actual_connection;
+		
+	for (; con && strcmp(connection_name, con->name) != 0; con = con->next);
+	if (con)
+		return con;
+	else
+		return NULL;
+}
+
 static void
 ECPGfinish(struct connection * act)
 {
@@ -145,7 +162,6 @@ ecpg_alloc(long size, int lineno)
 
 	if (!new)
 	{
-		ECPGfinish(actual_connection);
 		ECPGlog("out of memory\n");
 		register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
 		return NULL;
@@ -162,7 +178,6 @@ ecpg_strdup(const char *string, int lineno)
 
 	if (!new)
 	{
-		ECPGfinish(actual_connection);
 		ECPGlog("out of memory\n");
 		register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
 		return NULL;
@@ -238,9 +253,26 @@ quote_strings(char *arg, int lineno)
 	return res;
 }
 
-/* create a list of variables */
+/*
+ * create a list of variables 
+ * The variables are listed with input variables preceeding outputvariables
+ * The end of each group is marked by an end marker.
+ * per variable we list:
+ * type - as defined in ecpgtype.h
+ * value - where to store the data
+ * varcharsize - length of string in case we have a stringvariable, else 0
+ * arraysize - 0 for pointer (we don't know the size of the array),
+ * 1 for simple variable, size for arrays
+ * offset - offset between ith and (i+1)th entry in an array,
+ * normally that means sizeof(type)
+ * ind_type - type of indicator variable
+ * ind_value - pointer to indicator variable
+ * ind_varcharsize - empty
+ * ind_arraysize -  arraysize of indicator array
+ * ind_offset - indicator offset
+ */
 static bool
-create_statement(int lineno, struct statement ** stmt, char *query, va_list ap)
+create_statement(int lineno, struct connection *connection, struct statement ** stmt, char *query, va_list ap)
 {
 	struct variable **list = &((*stmt)->inlist);
 	enum ECPGttype type;
@@ -249,6 +281,7 @@ create_statement(int lineno, struct statement ** stmt, char *query, va_list ap)
 		return false;
 
 	(*stmt)->command = query;
+	(*stmt)->connection = connection;
 	(*stmt)->lineno = lineno;
 
 	list = &((*stmt)->inlist);
@@ -278,7 +311,8 @@ create_statement(int lineno, struct statement ** stmt, char *query, va_list ap)
 			var->ind_arrsize = va_arg(ap, long);
 			var->ind_offset = va_arg(ap, long);
 			var->next = NULL;
-			
+
+			/* if variable is NULL, the statement hasn't been prepared */			
 			if (var->value == NULL)
 			{
 				ECPGlog("create_statement: invalid statement name\n");
@@ -564,27 +598,27 @@ ECPGexecute(struct statement * stmt)
 
 	/* Now the request is built. */
 
-	if (actual_connection->committed && !no_auto_trans)
+	if (stmt->connection->committed && !no_auto_trans)
 	{
-		if ((results = PQexec(actual_connection->connection, "begin transaction")) == NULL)
+		if ((results = PQexec(stmt->connection->connection, "begin transaction")) == NULL)
 		{
 			register_error(ECPG_TRANS, "Error starting transaction line %d.", stmt->lineno);
 			return false;
 		}
 		PQclear(results);
-		actual_connection->committed = false;
+		stmt->connection->committed = false;
 	}
 
-	ECPGlog("ECPGexecute line %d: QUERY: %s\n", stmt->lineno, copiedquery);
-	results = PQexec(actual_connection->connection, copiedquery);
+	ECPGlog("ECPGexecute line %d: QUERY: %s on connection %s\n", stmt->lineno, copiedquery, stmt->connection->name);
+	results = PQexec(stmt->connection->connection, copiedquery);
 	free(copiedquery);
 
 	if (results == NULL)
 	{
 		ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno,
-				PQerrorMessage(actual_connection->connection));
+				PQerrorMessage(stmt->connection->connection));
 		register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
-			PQerrorMessage(actual_connection->connection), stmt->lineno);
+			PQerrorMessage(stmt->connection->connection), stmt->lineno);
 	}
 	else
 	{
@@ -642,6 +676,7 @@ ECPGexecute(struct statement * stmt)
 						status = false;
 						break;
 					}
+					
 					for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
 					{
 						pval = PQgetvalue(results, act_tuple, act_field);
@@ -909,18 +944,18 @@ ECPGexecute(struct statement * stmt)
 			case PGRES_FATAL_ERROR:
 			case PGRES_BAD_RESPONSE:
 				ECPGlog("ECPGexecute line %d: Error: %s",
-						stmt->lineno, PQerrorMessage(actual_connection->connection));
+						stmt->lineno, PQerrorMessage(stmt->connection->connection));
 				register_error(ECPG_PGSQL, "Error: %s line %d.",
-							   PQerrorMessage(actual_connection->connection), stmt->lineno);
+							   PQerrorMessage(stmt->connection->connection), stmt->lineno);
 				status = false;
 				break;
 			case PGRES_COPY_OUT:
 				ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT ... tossing.\n", stmt->lineno);
-				PQendcopy(actual_connection->connection);
+				PQendcopy(stmt->connection->connection);
 				break;
 			case PGRES_COPY_IN:
 				ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.\n", stmt->lineno);
-				PQendcopy(actual_connection->connection);
+				PQendcopy(stmt->connection->connection);
 				break;
 			default:
 				ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
@@ -932,7 +967,7 @@ ECPGexecute(struct statement * stmt)
 	}
 
 	/* check for asynchronous returns */
-	notify = PQnotifies(actual_connection->connection);
+	notify = PQnotifies(stmt->connection->connection);
 	if (notify)
 	{
 		ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
@@ -944,20 +979,27 @@ ECPGexecute(struct statement * stmt)
 }
 
 bool
-ECPGdo(int lineno, char *query,...)
+ECPGdo(int lineno, const char *connection_name, char *query,...)
 {
 	va_list		args;
 	struct statement *stmt;
+	struct connection *con = get_connection(connection_name);
 
+	if (con == NULL)
+	{
+		register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name, lineno);
+		return (false);
+	}
+		
 	va_start(args, query);
-	if (create_statement(lineno, &stmt, query, args) == false)
+	if (create_statement(lineno, con, &stmt, query, args) == false)
 		return (false);
 	va_end(args);
 
 	/* are we connected? */
-	if (actual_connection == NULL || actual_connection->connection == NULL)
+	if (con == NULL || con->connection == NULL)
 	{
-		ECPGlog("ECPGdo: not connected\n");
+		ECPGlog("ECPGdo: not connected to %s\n", con->name);
 		register_error(ECPG_NOT_CONN, "Not connected in line %d", lineno);
 		return false;
 	}
@@ -967,16 +1009,23 @@ ECPGdo(int lineno, char *query,...)
 
 
 bool
-ECPGtrans(int lineno, const char *transaction)
+ECPGtrans(int lineno, const char *connection_name, const char *transaction)
 {
 	PGresult   *res;
+	struct connection *con = get_connection(connection_name);
+	
+	if (con == NULL)
+	{
+		register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name, lineno);
+		return (false);
+	}
 
-	ECPGlog("ECPGtrans line %d action = %s\n", lineno, transaction);
+	ECPGlog("ECPGtrans line %d action = %s connection = %s\n", lineno, transaction, con->name);
 
 	/* if we have no connection we just simulate the command */
-	if (actual_connection && actual_connection->connection)
+	if (con && con->connection)
 	{
-		if ((res = PQexec(actual_connection->connection, transaction)) == NULL)
+		if ((res = PQexec(con->connection, transaction)) == NULL)
 		{
 			register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
 			return FALSE;
@@ -987,7 +1036,7 @@ ECPGtrans(int lineno, const char *transaction)
 	{
 		struct prepared_statement *this;
 			
-		actual_connection->committed = true;
+		con->committed = true;
 
 		/* deallocate all prepared statements */
 		for (this = prep_stmts; this != NULL; this = this->next)
@@ -1005,11 +1054,8 @@ ECPGtrans(int lineno, const char *transaction)
 bool
 ECPGsetconn(int lineno, const char *connection_name)
 {
-	struct connection *con = all_connections;
-
-	ECPGlog("ECPGsetconn: setting actual connection to %s\n", connection_name);
+	struct connection *con = get_connection(connection_name);
 
-	for (; con && strcmp(connection_name, con->name) != 0; con = con->next);
 	if (con)
 	{
 		actual_connection = con;
@@ -1070,9 +1116,7 @@ ECPGdisconnect(int lineno, const char *connection_name)
 {
 	struct connection *con;
 
-	if (strcmp(connection_name, "CURRENT") == 0)
-		ECPGfinish(actual_connection);
-	else if (strcmp(connection_name, "ALL") == 0)
+	if (strcmp(connection_name, "ALL") == 0)
 	{
 		for (con = all_connections; con;)
 		{
@@ -1084,7 +1128,8 @@ ECPGdisconnect(int lineno, const char *connection_name)
 	}
 	else
 	{
-		for (con = all_connections; con && strcmp(con->name, connection_name) != 0; con = con->next);
+		con = get_connection(connection_name);
+		
 		if (con == NULL)
 		{
 			ECPGlog("disconnect: not connected to connection %s\n", connection_name);
@@ -1136,6 +1181,21 @@ sqlprint(void)
 	printf("sql error %s\n", sqlca.sqlerrm.sqlerrmc);
 }
 
+static bool
+isvarchar(unsigned char c)
+{
+	if (isalnum(c))
+		return true;
+	
+	if (c == '_' || c == '>' || c == '-' || c == '.')
+		return true;
+		
+	if (c >= 128)
+		return true;
+		
+	return(false);
+}
+
 static void
 replace_variables(char *text)
 {
@@ -1150,7 +1210,7 @@ replace_variables(char *text)
 		if (!string && *ptr == ':')
 		{
 			ptr[0] = ptr[1] = ';';
-			for (ptr += 2; *ptr && *ptr != ' '; ptr++)
+			for (ptr += 2; *ptr && isvarchar(*ptr); ptr++)
 				*ptr = ' ';
 		}
 	}
@@ -1162,7 +1222,7 @@ ECPGprepare(int lineno, char *name, char *variable)
 {
 	struct statement *stmt;
 	struct prepared_statement *this;
-
+	
 	/* check if we already have prepared this statement */
 	for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);		
 	if (this)
@@ -1186,6 +1246,7 @@ ECPGprepare(int lineno, char *name, char *variable)
 
 	/* create statement */
 	stmt->lineno = lineno;
+       	stmt->connection = NULL;
         stmt->command = ecpg_strdup(variable, lineno);
         stmt->inlist = stmt->outlist = NULL;
         
diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile
index 87e788c83ccdf2b4e4ef9cc404c0b236b2921073..66c8911c5a8f04f94b59f47c8ebec258c5842e18 100644
--- a/src/interfaces/ecpg/preproc/Makefile
+++ b/src/interfaces/ecpg/preproc/Makefile
@@ -1,8 +1,8 @@
 SRCDIR= ../../..
 include $(SRCDIR)/Makefile.global
 
-MAJOR_VERSION=2
-MINOR_VERSION=5
+MAJOR_VERSION=3
+MINOR_VERSION=0
 PATCHLEVEL=0
 
 CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
diff --git a/src/interfaces/ecpg/preproc/c_keywords.c b/src/interfaces/ecpg/preproc/c_keywords.c
index 5395b533d3845b5a690b837534ebc83aefa1ffee..9a8b94bd256d0b0311f2a6ffcc83602f3d19b5e6 100644
--- a/src/interfaces/ecpg/preproc/c_keywords.c
+++ b/src/interfaces/ecpg/preproc/c_keywords.c
@@ -36,6 +36,7 @@ static ScanKeyword ScanKeywords[] = {
 	{"signed", S_SIGNED},
 	{"static", S_STATIC},
 	{"struct", S_STRUCT},
+	{"union", S_UNION},
 	{"unsigned", S_UNSIGNED},
 	{"varchar", S_VARCHAR},
 };
diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c
index 2594718cd124bdcbd1e78207c0ba66e63860bb70..6b37442c836ad0e66f7185f91defdcc9f44643a3 100644
--- a/src/interfaces/ecpg/preproc/ecpg.c
+++ b/src/interfaces/ecpg/preproc/ecpg.c
@@ -165,6 +165,7 @@ main(int argc, char *const argv[])
 					struct arguments *l1, *l2;
 
 					free(ptr->command);
+					free(ptr->connection);
 					free(ptr->name);
 					for (l1 = ptr->argsinsert; l1; l1 = l2)
 					{
diff --git a/src/interfaces/ecpg/preproc/ecpg_keywords.c b/src/interfaces/ecpg/preproc/ecpg_keywords.c
index 52eea065b8373faa30f8484aae60ecf35e246aa4..25c1f2b9813babb23710fee42f822834db565671 100644
--- a/src/interfaces/ecpg/preproc/ecpg_keywords.c
+++ b/src/interfaces/ecpg/preproc/ecpg_keywords.c
@@ -20,6 +20,7 @@
  */
 static ScanKeyword ScanKeywords[] = {
 	/* name					value			*/
+	{"at", SQL_AT},
 	{"bool", SQL_BOOL},
 	{"break", SQL_BREAK},
 	{"call", SQL_CALL},
diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h
index d5bc1fc9cabb4afa5379bc861629e84c987627df..94c76a507af5f544995c7e375bae68998008baa7 100644
--- a/src/interfaces/ecpg/preproc/extern.h
+++ b/src/interfaces/ecpg/preproc/extern.h
@@ -6,7 +6,7 @@
 
 extern int	braces_open,
 			no_auto_trans, struct_level;
-extern char *yytext;
+extern char *yytext, errortext[128];
 extern int	yylineno,
 			yyleng;
 extern FILE *yyin,
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index 5ddac659bbc4cef6f3f57f22db512f6b4144023c..82369690763a1ad45c73145fb02866498031edf2 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -105,7 +105,6 @@ xqstart			{quote}
 xqstop			{quote}
 xqdouble		{quote}{quote}
 xqinside		[^\\']*
-xqembedded		"\\'"
 xqliteral		[\\](.|\n)
 xqcat			{quote}{space}*\n{space}*{quote}
 
@@ -244,22 +243,9 @@ cppline		{space}*#.*(\\{space}*\n)*\n*
 					return SCONST;
 				}
 <xq>{xqdouble}	|
-<xq>{xqinside}	{
-					if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
-						yyerror("ERROR: quoted string parse buffer exceeded");
-					memcpy(literal+llen, yytext, yyleng+1);
-					llen += yyleng;
-				}
-<xq>{xqembedded} {
-					if ((llen+yyleng-1) > (MAX_PARSE_BUFFER - 1))
-						yyerror("ERROR: quoted string parse buffer exceeded");
-					memcpy(literal+llen, yytext, yyleng+1);
-					*(literal+llen) = '\'';
-					llen += yyleng;
-				}
-
+<xq>{xqinside}  |
 <xq>{xqliteral} {
-					if ((llen+yyleng-1) > (MAX_PARSE_BUFFER - 1))
+					if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
 						yyerror("ERROR: quoted string parse buffer exceeded");
 					memcpy(literal+llen, yytext, yyleng+1);
 					llen += yyleng;
diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y
index 7bb95d77e8cb8c2e58546e922c2c1f51daa6c8fa..ae5edf294d96474b2254588514afac21a68da649 100644
--- a/src/interfaces/ecpg/preproc/preproc.y
+++ b/src/interfaces/ecpg/preproc/preproc.y
@@ -18,7 +18,8 @@
  * Variables containing simple states.
  */
 int	struct_level = 0;
-static char	errortext[128];
+char	errortext[128];
+static char	*connection = NULL;
 static int      QueryIsRule = 0, ForUpdateNotAllowed = 0;
 static struct this_type actual_type[STRUCT_DEPTH];
 static char     *actual_storage[STRUCT_DEPTH];
@@ -489,7 +490,7 @@ output_statement(char * stmt, int mode)
 {
 	int i, j=strlen(stmt);
 
-	fputs("ECPGdo(__LINE__, \"", yyout);
+	fprintf(yyout, "ECPGdo(__LINE__, %s, \"", connection ? connection : "NULL");
 
 	/* do this char by char as we have to filter '\"' */
 	for (i = 0;i < j; i++)
@@ -504,6 +505,8 @@ output_statement(char * stmt, int mode)
 	fputs("ECPGt_EORT);", yyout);
 	whenever_action(mode);
 	free(stmt);
+	if (connection != NULL)
+		free(connection);
 }
 
 static struct typedefs *
@@ -612,7 +615,7 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
 }
 
 /* special embedded SQL token */
-%token		SQL_BOOL SQL_BREAK 
+%token		SQL_AT SQL_BOOL SQL_BREAK 
 %token		SQL_CALL SQL_CONNECT SQL_CONNECTION SQL_CONTINUE
 %token		SQL_DEALLOCATE SQL_DISCONNECT SQL_ENUM 
 %token		SQL_FOUND SQL_FREE SQL_GO SQL_GOTO
@@ -625,8 +628,8 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
 /* C token */
 %token		S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_ENUM S_EXTERN
 %token		S_FLOAT S_INT S
-%token		S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT 
-%token		S_UNSIGNED S_VARCHAR
+%token		S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT
+%token		S_UNION S_UNSIGNED S_VARCHAR
 
 /* I need this and don't know where it is defined inside the backend */
 %token		TYPECAST
@@ -785,8 +788,9 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
 %type  <str>	ECPGSetConnection c_line cpp_line s_enum ECPGTypedef
 %type  <str>	enum_type civariableonly ECPGCursorStmt ECPGDeallocate
 %type  <str>	ECPGFree ECPGDeclare ECPGVar sql_variable_declarations
-%type  <str>	sql_declaration sql_variable_list sql_variable
+%type  <str>	sql_declaration sql_variable_list sql_variable opt_at
 %type  <str>    struct_type s_struct declaration variable_declarations
+%type  <str>    s_struct_or_union sql_struct_or_union
 
 %type  <type_enum> simple_type varchar_type
 
@@ -803,13 +807,16 @@ prog: statements;
 statements: /* empty */
 	| statements statement
 
-statement: ecpgstart stmt SQL_SEMI
+statement: ecpgstart opt_at stmt SQL_SEMI { connection = NULL; }
+	| ecpgstart stmt SQL_SEMI
 	| ECPGDeclaration
 	| c_thing 			{ fprintf(yyout, "%s", $1); free($1); }
 	| cpp_line			{ fprintf(yyout, "%s", $1); free($1); }
 	| blockstart			{ fputs($1, yyout); free($1); }
 	| blockend			{ fputs($1, yyout); free($1); }
 
+opt_at:	SQL_AT connection_target	{ connection = $2; }
+
 stmt:  AddAttrStmt			{ output_statement($1, 0); }
 		| AlterUserStmt		{ output_statement($1, 0); }
 		| ClosePortalStmt	{ output_statement($1, 0); }
@@ -853,7 +860,7 @@ stmt:  AddAttrStmt			{ output_statement($1, 0); }
 					}
 		| RuleStmt		{ output_statement($1, 0); }
 		| TransactionStmt	{
-						fprintf(yyout, "ECPGtrans(__LINE__, \"%s\");", $1);
+						fprintf(yyout, "ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
 						whenever_action(0);
 						free($1);
 					}
@@ -866,6 +873,9 @@ stmt:  AddAttrStmt			{ output_statement($1, 0); }
 		| VariableShowStmt	{ output_statement($1, 0); }
 		| VariableResetStmt	{ output_statement($1, 0); }
 		| ECPGConnect		{
+						if (connection)
+							yyerror("no at option for connect statement.\n");
+
 						fprintf(yyout, "no_auto_trans = %d;\n", no_auto_trans);
 						fprintf(yyout, "ECPGconnect(__LINE__, %s);", $1);
 						whenever_action(0);
@@ -876,6 +886,9 @@ stmt:  AddAttrStmt			{ output_statement($1, 0); }
                                                 free($1); 
 					}
 		| ECPGDeallocate	{
+						if (connection)
+							yyerror("no at option for connect statement.\n");
+
 						fputs($1, yyout);
 						whenever_action(0);
 						free($1);
@@ -885,6 +898,9 @@ stmt:  AddAttrStmt			{ output_statement($1, 0); }
 						free($1);
 					}
 		| ECPGDisconnect	{
+						if (connection)
+							yyerror("no at option for disconnect statement.\n");
+
 						fprintf(yyout, "ECPGdisconnect(__LINE__, \"%s\");", $1); 
 						whenever_action(0);
 						free($1);
@@ -893,7 +909,7 @@ stmt:  AddAttrStmt			{ output_statement($1, 0); }
 						output_statement($1, 0);
 					}
 		| ECPGFree		{
-						fprintf(yyout, "ECPGdeallocate(__LINE__, \"%s\");", $1); 
+						fprintf(yyout, "ECPGdeallocate(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1); 
 						whenever_action(0);
 						free($1);
 					}
@@ -912,7 +928,7 @@ stmt:  AddAttrStmt			{ output_statement($1, 0); }
 							yyerror(errortext);
 						}
                   
-						fprintf(yyout, "ECPGdo(__LINE__, \"%s\",", ptr->command);
+						fprintf(yyout, "ECPGdo(__LINE__, %s, \"%s\",", ptr->connection ? ptr->connection : "NULL", ptr->command);
 						/* dump variables to C file*/
 						dump_variables(ptr->argsinsert, 0);
 						dump_variables(argsinsert, 0);
@@ -923,25 +939,40 @@ stmt:  AddAttrStmt			{ output_statement($1, 0); }
 						free($1);
 					}
 		| ECPGPrepare		{
+						if (connection)
+							yyerror("no at option for set connection statement.\n");
+
 						fprintf(yyout, "ECPGprepare(__LINE__, %s);", $1); 
 						whenever_action(0);
 						free($1);
 					}
 		| ECPGRelease		{ /* output already done */ }
 		| ECPGSetConnection     {
+						if (connection)
+							yyerror("no at option for set connection statement.\n");
+
 						fprintf(yyout, "ECPGsetconn(__LINE__, %s);", $1);
 						whenever_action(0);
                                        		free($1);
 					}
 		| ECPGTypedef		{
+						if (connection)
+							yyerror("no at option for typedef statement.\n");
+
 						fputs($1, yyout);
                                                 free($1);
 					}
 		| ECPGVar		{
+						if (connection)
+							yyerror("no at option for var statement.\n");
+
 						fputs($1, yyout);
                                                 free($1);
 					}
 		| ECPGWhenever		{
+						if (connection)
+							yyerror("no at option for whenever statement.\n");
+
 						fputs($1, yyout);
 						output_line_number();
 						free($1);
@@ -2727,6 +2758,7 @@ CursorStmt:  DECLARE name opt_cursor CURSOR FOR SelectStmt cursor_clause
 			        	/* initial definition */
 				        this->next = cur;
 				        this->name = $2;
+					this->connection = connection;
 				        this->command =  cat2_str(cat5_str(make1_str("declare"), mm_strdup($2), $3, make1_str("cursor for"), $6), $7);
 					this->argsinsert = argsinsert;
 					this->argsresult = argsresult;
@@ -3103,6 +3135,7 @@ Generic:  generic
 
 generic:  ident					{ $$ = $1; }
 		| TYPE_P			{ $$ = make1_str("type"); }
+		| SQL_AT			{ $$ = make1_str("at"); }
 		| SQL_BOOL			{ $$ = make1_str("bool"); }
 		| SQL_BREAK			{ $$ = make1_str("break"); }
 		| SQL_CALL			{ $$ = make1_str("call"); }
@@ -4306,6 +4339,7 @@ ColId:  ident					{ $$ = $1; }
 		| VALID				{ $$ = make1_str("valid"); }
 		| VERSION			{ $$ = make1_str("version"); }
 		| ZONE				{ $$ = make1_str("zone"); }
+		| SQL_AT			{ $$ = make1_str("at"); }
 		| SQL_BOOL			{ $$ = make1_str("bool"); }
 		| SQL_BREAK			{ $$ = make1_str("break"); }
 		| SQL_CALL			{ $$ = make1_str("call"); }
@@ -4602,6 +4636,7 @@ ECPGCursorStmt:  DECLARE name opt_cursor CURSOR FOR ident cursor_clause
 			        	/* initial definition */
 				        this->next = cur;
 				        this->name = $2;
+					this->connection = connection;
 				        this->command =  cat5_str(make1_str("declare"), mm_strdup($2), $3, make1_str("cursor for ;;"), $7);
 					this->argsresult = NULL;
 
@@ -4731,14 +4766,17 @@ struct_type: s_struct '{' variable_declarations '}'
 	    $$ = cat4_str($1, make1_str("{"), $3, make1_str("}"));
 	}
 
-s_struct : S_STRUCT opt_symbol
+s_struct : s_struct_or_union opt_symbol
         {
             struct_member_list[struct_level++] = NULL;
             if (struct_level >= STRUCT_DEPTH)
                  yyerror("Too many levels in nested structure definition");
-	    $$ = cat2_str(make1_str("struct"), $2);
+	    $$ = cat2_str($1, $2);
 	}
 
+s_struct_or_union: S_STRUCT { $$ = make1_str("struct"); }
+		|  S_UNION  { $$ = make1_str("union"); }
+
 opt_symbol: /* empty */ 	{ $$ = make1_str(""); }
 	| symbol		{ $$ = $1; }
 
@@ -4940,7 +4978,7 @@ ECPGRelease: TransactionStmt SQL_RELEASE
 		if (strncmp($1, "begin", 5) == 0)
                         yyerror("RELEASE does not make sense when beginning a transaction");
 
-		fprintf(yyout, "ECPGtrans(__LINE__, \"%s\");", $1);
+		fprintf(yyout, "ECPGtrans(__LINE__, %s, \"%s\");", connection, $1);
 		whenever_action(0);
 		fprintf(yyout, "ECPGdisconnect(\"\");"); 
 		whenever_action(0);
@@ -5151,7 +5189,7 @@ ctype: CHAR
 		$$.type_index = -1;
 		$$.type_dimension = -1;
 	}
-	| SQL_STRUCT
+	| sql_struct_or_union
 	{
 		struct_member_list[struct_level++] = NULL;
 		if (struct_level >= STRUCT_DEPTH)
@@ -5159,7 +5197,7 @@ ctype: CHAR
 	} '{' sql_variable_declarations '}'
 	{
 		ECPGfree_struct_member(struct_member_list[struct_level--]);
-		$$.type_str = cat3_str(make1_str("struct {"), $4, make1_str("}"));
+		$$.type_str = cat4_str($1, make1_str("{"), $4, make1_str("}"));
 		$$.type_enum = ECPGt_struct;
                 $$.type_index = -1;
                 $$.type_dimension = -1;
@@ -5175,6 +5213,9 @@ ctype: CHAR
 		struct_member_list[struct_level] = this->struct_member_list;
 	}
 
+sql_struct_or_union: SQL_STRUCT	{ $$ = make1_str("struct"); }
+		|    UNION  { $$ = make1_str("union"); }
+
 opt_signed: SQL_SIGNED | /* empty */
 
 sql_variable_declarations: /* empty */
@@ -5735,6 +5776,7 @@ c_anything:  IDENT 	{ $$ = $1; }
 	| S_SIGNED	{ $$ = make1_str("signed"); }
 	| S_STATIC	{ $$ = make1_str("static"); }
         | S_STRUCT	{ $$ = make1_str("struct"); }
+        | S_UNION	{ $$ = make1_str("union"); }
 	| S_UNSIGNED	{ $$ = make1_str("unsigned"); }
 	| S_VARCHAR	{ $$ = make1_str("varchar"); }
 	| S_ANYTHING	{ $$ = make_name(); }
diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c
index dd3546b50ad83ea186461a496e5ba17fe9c9d412..b5144d5d9a7ef60e0c63c54899cf64217c6f1210 100644
--- a/src/interfaces/ecpg/preproc/type.c
+++ b/src/interfaces/ecpg/preproc/type.c
@@ -164,7 +164,8 @@ get_type(enum ECPGttype typ)
 			return ("ECPGt_char_variable");
 			break;
 		default:
-			abort();
+			sprintf(errortext, "illegal variable type %d\n", typ);
+			yyerror(errortext);
 	}
 }
 
@@ -357,7 +358,8 @@ ECPGfree_type(struct ECPGtype * typ)
 			if (IS_SIMPLE_TYPE(typ->u.element->typ))
 				free(typ->u.element);
 			else if (typ->u.element->typ == ECPGt_array)
-				abort();		/* Array of array, */
+				/* Array of array, */
+				yyerror("internal error, found multi-dimensional array\n");
 			else if (typ->u.element->typ == ECPGt_struct)
 			{
 				/* Array of structs. */
@@ -365,7 +367,10 @@ ECPGfree_type(struct ECPGtype * typ)
 				free(typ->u.members);
 			}
 			else
-				abort();
+			{
+				sprintf(errortext, "illegal variable type %d\n", typ);
+				yyerror(errortext);
+			}
 		}
 		else if (typ->typ == ECPGt_struct)
 		{
@@ -373,7 +378,10 @@ ECPGfree_type(struct ECPGtype * typ)
 			free(typ->u.members);
 		}
 		else
-			abort();
+		{
+			sprintf(errortext, "illegal variable type %d\n", typ);
+			yyerror(errortext);
+		}
 	}
 	free(typ);
 }
diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h
index f9642d92766e922b74c12454201b615e5cb2f09c..59cf3be9009e4e0cd3266161fad563892569b4bc 100644
--- a/src/interfaces/ecpg/preproc/type.h
+++ b/src/interfaces/ecpg/preproc/type.h
@@ -101,6 +101,7 @@ struct cursor
 {
 	char	   *name;
 	char	   *command;
+	char	   *connection;
 	struct arguments *argsinsert;
 	struct arguments *argsresult;
 	struct cursor *next;
diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile
index 45d65fb44c67c4c5ceaf584d569307cf64ec596f..2c4ba01ee0da0de121c99566b14203037eaa3063 100644
--- a/src/interfaces/ecpg/test/Makefile
+++ b/src/interfaces/ecpg/test/Makefile
@@ -15,4 +15,4 @@ perftest.c:perftest.pgc
 	/usr/local/pgsql/bin/ecpg $?
 
 clean:
-	/bin/rm test1 test2 perftest *.c log
+	-/bin/rm test1 test2 perftest *.c log
diff --git a/src/interfaces/ecpg/test/test1.pgc b/src/interfaces/ecpg/test/test1.pgc
index ac2dbdc04e165ded68688c8da6b99e780dcabeb8..a1e13bb517554d62e259c563a3a6054ea28a000b 100644
--- a/src/interfaces/ecpg/test/test1.pgc
+++ b/src/interfaces/ecpg/test/test1.pgc
@@ -4,7 +4,7 @@ exec sql whenever sqlerror sqlprint;
 
 exec sql include sqlca;
 
-exec sql define AMOUNT 8;
+exec sql define AMOUNT 4;
 
 exec sql type intarray is int[AMOUNT];
 exec sql type string is char(6); 
@@ -30,21 +30,31 @@ exec sql end declare section;
                 ECPGdebug(1, dbgs);
 
 	strcpy(msg, "connect");
-	exec sql connect to mm;
+	exec sql connect to mm as main;
+
+	strcpy(msg, "connect");
+        exec sql connect to pm;
 
 	strcpy(msg, "create");
+	exec sql at main create table test(name char(6), amount int, letter char(1));
 	exec sql create table test(name char(6), amount int, letter char(1));
 
 	strcpy(msg, "commit");
+	exec sql at main commit;
 	exec sql commit;
 
+	strcpy(msg, "set connection");
+	exec sql set connection main;
+
 	strcpy(msg, "execute insert 1");
-        sprintf(command, "insert into test(name, amount, letter) values ('foobar', 1, 'f')");
+        sprintf(command, "insert into test(name, amount, letter) values ('db: mm', 1, 'f')");
+        exec sql execute immediate :command;
+        sprintf(command, "insert into test(name, amount, letter) values ('db: mm', 2, 't')");
         exec sql execute immediate :command;
 
         strcpy(msg, "execute insert 2");
-        sprintf(command, "insert into test(name, amount, letter) select name, amount+1, letter from test");
-        exec sql execute immediate :command;
+        sprintf(command, "insert into test(name, amount, letter) values ('db: pm', 1, 'f')");
+        exec sql at pm execute immediate :command;
 
         strcpy(msg, "execute insert 3");
         sprintf(command, "insert into test(name, amount, letter) select name, amount+10, letter from test");
@@ -55,27 +65,35 @@ exec sql end declare section;
         strcpy(msg, "execute insert 4");
         sprintf(command, "insert into test(name, amount, letter) select name, amount+;;, letter from test");
 	exec sql prepare I from :command;
-        exec sql execute I using :increment;
+        exec sql at pm execute I using :increment;
         
 	printf("Inserted %d tuples via prepared execute\n", sqlca.sqlerrd[2]);
 
 	strcpy(msg, "commit");
 	exec sql commit;
+	exec sql at pm commit;
 
         strcpy(msg, "select");
         exec sql select name, amount, letter into :name, :amount, :letter from test;
 
+        for (i=0, j=sqlca.sqlerrd[2]; i<j; i++)
+            printf("name[%d]=%6.6s\tamount[%d]=%d\tletter[%d]=%c\n", i, name[i], i, amount[i],i, letter[i][0]);
+
+        exec sql at pm select name, amount, letter into :name, :amount, :letter from test;
+
         for (i=0, j=sqlca.sqlerrd[2]; i<j; i++)
             printf("name[%d]=%6.6s\tamount[%d]=%d\tletter[%d]=%c\n", i, name[i], i, amount[i],i, letter[i][0]);
         
 	strcpy(msg, "drop");
 	exec sql drop table test;
+	exec sql at pm drop table test;
 
 	strcpy(msg, "commit");
 	exec sql commit;
+	exec sql at pm commit;
 
 	strcpy(msg, "disconnect"); 
-        exec sql disconnect;
+        exec sql disconnect all;
         
 	if (dbgs != NULL)
                 fclose(dbgs);
diff --git a/src/interfaces/ecpg/test/test2.pgc b/src/interfaces/ecpg/test/test2.pgc
index ed06f179bc488b4d4d90badc733f6cb0214a09e8..568add1463440ba10a5a0908a181b24721f0ffe2 100644
--- a/src/interfaces/ecpg/test/test2.pgc
+++ b/src/interfaces/ecpg/test/test2.pgc
@@ -5,6 +5,9 @@ exec sql include header_test;
 exec sql type c is char reference;
 typedef char* c;
 
+exec sql type ind is union { int integer; short smallinteger; };
+typedef union { int integer; short smallinteger; } ind;
+
 int
 main ()
 {
@@ -18,15 +21,17 @@ exec sql begin declare section;
 					birthinfo ind_birth;
 				  } ind_personal;
 	int ind_married;
+	ind children;
+	ind ind_children;
 	char married[9];
 	c testname="Petra";
-	char *query="select name, born, age, married from meskes where name = :var1";
+	char *query="select name, born, age, married, children from meskes where name = :var1";
 exec sql end declare section;
 
 	exec sql var ind_married is long;
 
 	exec sql declare cur cursor for
-	       select name, born, age, married from meskes;
+	       select name, born, age, married, children from meskes;
 
 	char msg[128], command[128];
 	FILE *dbgs;
@@ -38,11 +43,11 @@ exec sql end declare section;
 	exec sql connect to unix:postgresql://localhost:5432/mm; 
 
 	strcpy(msg, "create");
-	exec sql create table meskes(name char(8), born integer, age smallint, married char(8));
+	exec sql create table meskes(name char(8), born integer, age smallint, married char(8), children integer);
 
 	strcpy(msg, "insert");
-	exec sql insert into meskes(name, married) values ('Petra', '19900404');
-	exec sql insert into meskes(name, born, age, married) values ('Michael', 19660117, 33, '19900404');
+	exec sql insert into meskes(name, married, children) values ('Petra', '19900404', 3);
+	exec sql insert into meskes(name, born, age, married, children) values ('Michael', 19660117, 33, '19900404', 3);
 	exec sql insert into meskes(name, born, age) values ('Carsten', 19910103, 8);
 	exec sql insert into meskes(name, born, age) values ('Marc', 19930907, 5);
 	exec sql insert into meskes(name, born, age) values ('Chris', 19970923, 1);
@@ -57,7 +62,7 @@ exec sql end declare section;
 
 	while (1) {
 		strcpy(msg, "fetch");
-		exec sql fetch in cur into :personal:ind_personal, :married:ind_married;
+		exec sql fetch in cur into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallinteger;
 		printf("%8.8s", personal.name.arr);
 		if (!ind_personal.ind_birth.born)
 			printf(", born %d", personal.birth.born);
@@ -65,6 +70,8 @@ exec sql end declare section;
 			printf(", age = %d", personal.birth.age);
 		if (!ind_married)
 			printf(", married %s", married);
+		if (!ind_children.smallinteger)
+			printf(", children = %d", children.integer);
 		putchar('\n');
 	}
 
@@ -82,7 +89,7 @@ exec sql end declare section;
 
 	while (1) {
 		strcpy(msg, "fetch");
-		exec sql fetch in prep into :personal:ind_personal, :married:ind_married;
+		exec sql fetch in prep into :personal:ind_personal, :married:ind_married, :children.integer:ind_children.smallinteger;
 		printf("%8.8s", personal.name.arr);
 		if (!ind_personal.ind_birth.born)
 			printf(", born %d", personal.birth.born);
@@ -90,6 +97,8 @@ exec sql end declare section;
 			printf(", age = %d", personal.birth.age);
 		if (!ind_married)
 			printf(", married %s", married);
+		if (!ind_children.smallinteger)
+			printf(", children = %d", children.integer);
 		putchar('\n');
 	}