From 377d131b6c351e0db1bed9cc393cdba3c1eaea56 Mon Sep 17 00:00:00 2001
From: Hiroshi Inoue <inoue@tpf.co.jp>
Date: Fri, 7 Sep 2001 06:02:24 +0000
Subject: [PATCH] 1) Most driver options could be set per DSN. 2) Keep FE/BE
 protocol more precisely. 3) Improve procedure calls. 4) A trial to avoid
 PREMATURE execution(#ifdef'd now).

Hiroshi Inoue
---
 src/interfaces/odbc/bind.c         |   8 +-
 src/interfaces/odbc/connection.c   | 220 ++++++---
 src/interfaces/odbc/connection.h   |   1 +
 src/interfaces/odbc/convert.c      | 195 +++++---
 src/interfaces/odbc/convert.h      |  20 +-
 src/interfaces/odbc/dlg_specific.c | 697 +++++++++++++++++++----------
 src/interfaces/odbc/dlg_specific.h |  11 +-
 src/interfaces/odbc/drvconn.c      |  60 ++-
 src/interfaces/odbc/environ.c      |   2 +-
 src/interfaces/odbc/execute.c      |  37 +-
 src/interfaces/odbc/info.c         |  59 +--
 src/interfaces/odbc/misc.c         |  47 +-
 src/interfaces/odbc/misc.h         |   6 +-
 src/interfaces/odbc/multibyte.c    |   2 +-
 src/interfaces/odbc/odbcapi.c      |  12 +-
 src/interfaces/odbc/odbcapi30.c    |   2 +-
 src/interfaces/odbc/options.c      |  20 +-
 src/interfaces/odbc/pgtypes.c      |  33 +-
 src/interfaces/odbc/pgtypes.h      |   2 +-
 src/interfaces/odbc/psqlodbc.c     |   6 +-
 src/interfaces/odbc/psqlodbc.h     |   7 +-
 src/interfaces/odbc/psqlodbc.rc    |  96 ++--
 src/interfaces/odbc/qresult.c      |  45 +-
 src/interfaces/odbc/resource.h     | 126 +++---
 src/interfaces/odbc/results.c      |  33 +-
 src/interfaces/odbc/setup.c        | 111 +++--
 src/interfaces/odbc/socket.c       |  22 +-
 src/interfaces/odbc/socket.h       |   3 +-
 src/interfaces/odbc/statement.c    |  47 +-
 src/interfaces/odbc/statement.h    |  14 +-
 30 files changed, 1221 insertions(+), 723 deletions(-)

diff --git a/src/interfaces/odbc/bind.c b/src/interfaces/odbc/bind.c
index 2fc340907a3..ce172365486 100644
--- a/src/interfaces/odbc/bind.c
+++ b/src/interfaces/odbc/bind.c
@@ -335,8 +335,14 @@ PGAPI_ParamOptions(
 	static char *func = "PGAPI_ParamOptions";
 	StatementClass	*stmt = (StatementClass *) hstmt;
 
-	mylog("%s: entering...\n", func);
+	mylog("%s: entering... %d %x\n", func, crow, pirow);
 
+	if (crow == 1) /* temporary solution and must be rewritten later */
+	{
+		if (pirow)
+			*pirow = 1;
+		return SQL_SUCCESS;
+	}
 	stmt->errornumber = CONN_UNSUPPORTED_OPTION;
 	stmt->errormsg = "Function not implemented";
 	SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
diff --git a/src/interfaces/odbc/connection.c b/src/interfaces/odbc/connection.c
index d0373a11bd6..9ae6a223a96 100644
--- a/src/interfaces/odbc/connection.c
+++ b/src/interfaces/odbc/connection.c
@@ -110,6 +110,7 @@ PGAPI_Connect(
 
 	/* get the values for the DSN from the registry */
 	getDSNinfo(ci, CONN_OVERWRITE);
+	logs_on_off(1, ci->drivers.debug, ci->drivers.commlog);
 	/* initialize pg_version from connInfo.protocol    */
 	CC_initialize_pg_version(conn);
 
@@ -182,6 +183,7 @@ PGAPI_Disconnect(
 		return SQL_ERROR;
 	}
 
+	logs_on_off(-1, conn->connInfo.drivers.debug, conn->connInfo.drivers.commlog);
 	mylog("%s: about to CC_cleanup\n", func);
 
 	/* Close the connection and free statements */
@@ -249,8 +251,8 @@ CC_Constructor()
 		rv->transact_status = CONN_IN_AUTOCOMMIT;		/* autocommit by default */
 
 		memset(&rv->connInfo, 0, sizeof(ConnInfo));
-
-		rv->sock = SOCK_Constructor();
+memcpy(&(rv->connInfo.drivers), &globals, sizeof(globals));
+		rv->sock = SOCK_Constructor(rv);
 		if (!rv->sock)
 			return NULL;
 
@@ -519,31 +521,31 @@ CC_connect(ConnectionClass *self, char do_password)
 	{
 		qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n",
 			 POSTGRESDRIVERVERSION,
-			 globals.fetch_max,
-			 globals.socket_buffersize,
-			 globals.unknown_sizes,
-			 globals.max_varchar_size,
-			 globals.max_longvarchar_size);
+			 ci->drivers.fetch_max,
+			 ci->drivers.socket_buffersize,
+			 ci->drivers.unknown_sizes,
+			 ci->drivers.max_varchar_size,
+			 ci->drivers.max_longvarchar_size);
 		qlog("                disable_optimizer=%d, ksqo=%d, unique_index=%d, use_declarefetch=%d\n",
-			 globals.disable_optimizer,
-			 globals.ksqo,
-			 globals.unique_index,
-			 globals.use_declarefetch);
+			 ci->drivers.disable_optimizer,
+			 ci->drivers.ksqo,
+			 ci->drivers.unique_index,
+			 ci->drivers.use_declarefetch);
 		qlog("                text_as_longvarchar=%d, unknowns_as_longvarchar=%d, bools_as_char=%d\n",
-			 globals.text_as_longvarchar,
-			 globals.unknowns_as_longvarchar,
-			 globals.bools_as_char);
+			 ci->drivers.text_as_longvarchar,
+			 ci->drivers.unknowns_as_longvarchar,
+			 ci->drivers.bools_as_char);
 
 #ifdef MULTIBYTE
-		check_client_encoding(globals.conn_settings);
+		check_client_encoding(ci->drivers.conn_settings);
 		qlog("                extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n",
-			 globals.extra_systable_prefixes,
-			 globals.conn_settings,
-			 check_client_encoding(globals.conn_settings));
+			 ci->drivers.extra_systable_prefixes,
+			 ci->drivers.conn_settings,
+			 check_client_encoding(ci->drivers.conn_settings));
 #else
 		qlog("                extra_systable_prefixes='%s', conn_settings='%s'\n",
-			 globals.extra_systable_prefixes,
-			 globals.conn_settings);
+			 ci->drivers.extra_systable_prefixes,
+			 ci->drivers.conn_settings);
 #endif
 
 		if (self->status != CONN_NOT_CONNECTED)
@@ -568,7 +570,7 @@ CC_connect(ConnectionClass *self, char do_password)
 		 */
 		if (!self->sock)
 		{
-			self->sock = SOCK_Constructor();
+			self->sock = SOCK_Constructor(self);
 			if (!self->sock)
 			{
 				self->errornumber = CONNECTION_SERVER_NOT_REACHED;
@@ -646,17 +648,21 @@ CC_connect(ConnectionClass *self, char do_password)
 	 */
 
 	if (!PROTOCOL_62(ci))
+	{
+		BOOL before_64 = PG_VERSION_LT(self, 6.4), ReadyForQuery = FALSE;
 		do
 		{
 			if (do_password)
 				beresp = 'R';
 			else
+			{
 				beresp = SOCK_get_char(sock);
+				mylog("auth got '%c'\n", beresp);
+			}
 
 			switch (beresp)
 			{
 				case 'E':
-					mylog("auth got 'E'\n");
 
 					SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
 					self->errornumber = CONN_INVALID_AUTHENTICATION;
@@ -673,7 +679,6 @@ CC_connect(ConnectionClass *self, char do_password)
 					}
 					else
 					{
-						mylog("auth got 'R'\n");
 
 						areq = SOCK_get_int(sock, 4);
 						if (areq == AUTH_REQ_MD5)
@@ -734,13 +739,28 @@ CC_connect(ConnectionClass *self, char do_password)
 							return 0;
 					}
 					break;
+				case 'K':			/* Secret key (6.4 protocol) */
+					(void) SOCK_get_int(sock, 4);	/* pid */
+					(void) SOCK_get_int(sock, 4);	/* key */
+
+					break;
+				case 'Z':			/* Backend is ready for new query (6.4) */
+					ReadyForQuery = TRUE;
+					break;
 				default:
 					self->errormsg = "Unexpected protocol character during authentication";
 					self->errornumber = CONN_INVALID_AUTHENTICATION;
 					return 0;
 			}
 
-		} while (areq != AUTH_REQ_OK);
+			/* 
+			 *	There were no ReadyForQuery responce
+			 *	before 6.4.
+			 */
+			if (before_64 && areq == AUTH_REQ_OK)
+				ReadyForQuery = TRUE;
+		} while (!ReadyForQuery);
+	}
 
 
 	CC_clear_error(self);		/* clear any password error */
@@ -917,13 +937,14 @@ CC_get_error(ConnectionClass *self, int *number, char **message)
 QResultClass *
 CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 {
-	QResultClass *result_in,
-			   *res = NULL;
+	QResultClass *result_in = NULL, *res = NULL, *retres = NULL;
 	char		swallow;
 	int			id;
 	SocketClass *sock = self->sock;
-	int		maxlen;
-	BOOL		msg_truncated;
+	int		maxlen, empty_reqs;
+	BOOL		msg_truncated, ReadyToReturn,
+			tuples_return = FALSE, query_completed = FALSE,
+			before_64 = PG_VERSION_LT(self, 6.4);
 
 	/* ERROR_MSG_LENGTH is suffcient */
 	static char msgbuffer[ERROR_MSG_LENGTH + 1];
@@ -976,7 +997,11 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 
 	mylog("send_query: done sending query\n");
 
-	while (1)
+	ReadyToReturn = FALSE;
+	empty_reqs = 0;
+	if (strcmp(query, " ") == 0)
+		empty_reqs = 1;
+	while (!ReadyToReturn)
 	{
 		/* what type of message is coming now ? */
 		id = SOCK_get_char(sock);
@@ -985,12 +1010,12 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 		{
 			self->errornumber = CONNECTION_NO_RESPONSE;
 			self->errormsg = "No response from the backend";
-			if (res)
-				QR_Destructor(res);
 
 			mylog("send_query: 'id' - %s\n", self->errormsg);
 			CC_set_no_trans(self);
-			return NULL;
+			ReadyToReturn = TRUE;
+			retres = NULL;
+			break;
 		}
 
 		mylog("send_query: got id = '%c'\n", id);
@@ -1012,9 +1037,9 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 					self->errormsg = "No response from backend while receiving a portal query command";
 					mylog("send_query: 'C' - %s\n", self->errormsg);
 					CC_set_no_trans(self);
-					if (res)
-						QR_Destructor(res);
-					return NULL;
+					ReadyToReturn = TRUE;
+					retres = NULL;
+					break;
 				}
 				else
 				{
@@ -1031,7 +1056,9 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 					if (QR_command_successful(res))
 						QR_set_status(res, PGRES_COMMAND_OK);
 					QR_set_command(res, cmdbuffer);
-
+					query_completed = TRUE;
+					if (!before_64)
+						break;
 					/*
 					 * (Quotation from the original comments) since
 					 * backend may produce more than one result for some
@@ -1041,8 +1068,13 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 					 */
 
 
-					SOCK_put_string(sock, "Q ");
-					SOCK_flush_output(sock);
+					if (empty_reqs == 0)
+					{
+						SOCK_put_string(sock, "Q ");
+						SOCK_flush_output(sock);
+						empty_reqs++;
+					}
+					break;
 
 					while (!clear)
 					{
@@ -1071,7 +1103,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
 								break;
 							case 'E':
 								msg_truncated = SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
-mylog("ERROR from backend during clear: '%s'\n", msgbuffer);
+								mylog("ERROR from backend during clear: '%s'\n", msgbuffer);
 								qlog("ERROR from backend during clear: '%s'\n", msgbuffer);
 
 								/*
@@ -1098,14 +1130,21 @@ mylog("ERROR from backend during clear: '%s'\n", msgbuffer);
 					}
 
 					mylog("send_query: returning res = %u\n", res);
-					return res;
+					break;
 				}
-			case 'K':			/* Secret key (6.4 protocol) */
-				(void) SOCK_get_int(sock, 4);	/* pid */
-				(void) SOCK_get_int(sock, 4);	/* key */
-
-				break;
 			case 'Z':			/* Backend is ready for new query (6.4) */
+				if (empty_reqs == 0)
+				{
+					ReadyToReturn = TRUE;
+					if (res && QR_get_aborted(res))
+						retres = res;
+					else if (tuples_return)
+						retres = result_in;
+					else if (query_completed)
+						retres = res;
+					else
+						ReadyToReturn = FALSE;
+				}
 				break;
 			case 'N':			/* NOTICE: */
 				msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
@@ -1126,22 +1165,26 @@ mylog("ERROR from backend during clear: '%s'\n", msgbuffer);
 			case 'I':			/* The server sends an empty query */
 				/* There is a closing '\0' following the 'I', so we eat it */
 				swallow = SOCK_get_char(sock);
+				if (!res)
+					res = QR_Constructor();
 				if ((swallow != '\0') || SOCK_get_errcode(sock) != 0)
 				{
 					self->errornumber = CONNECTION_BACKEND_CRAZY;
 					self->errormsg = "Unexpected protocol character from backend (send_query - I)";
-					if (!res)
-						res = QR_Constructor();
 					QR_set_status(res, PGRES_FATAL_ERROR);
-					return res;
+					ReadyToReturn = TRUE;
+					retres = res;
+					break;
 				}
 				else
 				{
 					/* We return the empty query */
-					if (!res)
-						res = QR_Constructor();
 					QR_set_status(res, PGRES_EMPTY_QUERY);
-					return res;
+				}
+				if (empty_reqs > 0)
+				{
+					if (--empty_reqs == 0)
+						query_completed = TRUE;
 				}
 				break;
 			case 'E':
@@ -1174,7 +1217,8 @@ mylog("ERROR from backend during clear: '%s'\n", msgbuffer);
 				while (msg_truncated)
 					msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
 
-				return res;		/* instead of NULL. Zoltan */
+				query_completed = TRUE;
+				break;
 
 			case 'P':			/* get the Portal name */
 				SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
@@ -1190,7 +1234,9 @@ mylog("ERROR from backend during clear: '%s'\n", msgbuffer);
 					{
 						self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
 						self->errormsg = "Could not create result info in send_query.";
-						return NULL;
+						ReadyToReturn = TRUE;
+						retres = NULL;
+						break;
 					}
 
 					if (qi)
@@ -1200,43 +1246,87 @@ mylog("ERROR from backend during clear: '%s'\n", msgbuffer);
 					{
 						self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
 						self->errormsg = QR_get_message(result_in);
-						return NULL;
+						ReadyToReturn = TRUE;
+						retres = NULL;
+						break;
 					}
 				}
 				else
 				{				/* next fetch, so reuse an existing result */
+					/*
+					 *	called from QR_next_tuple
+					 *	and must return immediately.
+					 */
+					ReadyToReturn = TRUE;
 					if (!QR_fetch_tuples(result_in, NULL, NULL))
 					{
 						self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
 						self->errormsg = QR_get_message(result_in);
-						return NULL;
+						retres = NULL;
+						break;
 					}
+					retres = result_in;
 				}
 
-				return result_in;
+				tuples_return = TRUE;
+				break;
 			case 'D':			/* Copy in command began successfully */
 				if (!res)
 					res = QR_Constructor();
 				if (QR_command_successful(res))
 					QR_set_status(res, PGRES_COPY_IN);
-				return res;
+				ReadyToReturn = TRUE;
+				retres = res;
+				break;
 			case 'B':			/* Copy out command began successfully */
 				if (!res)
 					res = QR_Constructor();
 				if (QR_command_successful(res))
 					QR_set_status(res, PGRES_COPY_OUT);
-				return res;
+				ReadyToReturn = TRUE;
+				retres = res;
+				break;
 			default:
 				self->errornumber = CONNECTION_BACKEND_CRAZY;
 				self->errormsg = "Unexpected protocol character from backend (send_query)";
 				CC_set_no_trans(self);
 
 				mylog("send_query: error - %s\n", self->errormsg);
-				if (res)
-					QR_Destructor(res);
-				return NULL;
+				ReadyToReturn = TRUE;
+				retres = NULL;
+				break;
+		}
+		/*
+		 *	There were no ReadyForQuery response before 6.4.
+		 */
+		if (before_64)
+		{
+			if (empty_reqs == 0 && (query_completed || tuples_return))
+				break;
 		}
 	}
+	/*
+	 *	set notice message to result_in.
+	 */
+	if (result_in && res && retres == result_in)
+	{
+		if (QR_command_successful(result_in))
+			QR_set_status(result_in, QR_get_status(res));
+		QR_set_notice(result_in, QR_get_notice(res));
+	}
+	/*
+	 *	Cleanup garbage results before returning.
+	 */
+	if (res && retres != res)
+		QR_Destructor(res);
+	if (result_in && retres != result_in)
+	{
+		if (qi && qi->result_in)
+			;
+		else
+			QR_Destructor(result_in);
+	}
+	return retres;
 }
 
 
@@ -1430,7 +1520,7 @@ CC_send_settings(ConnectionClass *self)
 	mylog("%s: result %d, status %d from set DateStyle\n", func, result, status);
 
 	/* Disable genetic optimizer based on global flag */
-	if (globals.disable_optimizer)
+	if (ci->drivers.disable_optimizer)
 	{
 		result = PGAPI_ExecDirect(hstmt, "set geqo to 'OFF'", SQL_NTS);
 		if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
@@ -1441,7 +1531,7 @@ CC_send_settings(ConnectionClass *self)
 	}
 
 	/* KSQO */
-	if (globals.ksqo)
+	if (ci->drivers.ksqo)
 	{
 		result = PGAPI_ExecDirect(hstmt, "set ksqo to 'ON'", SQL_NTS);
 		if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
@@ -1452,9 +1542,9 @@ CC_send_settings(ConnectionClass *self)
 	}
 
 	/* Global settings */
-	if (globals.conn_settings[0] != '\0')
+	if (ci->drivers.conn_settings[0] != '\0')
 	{
-		cs = strdup(globals.conn_settings);
+		cs = strdup(ci->drivers.conn_settings);
 		ptr = strtok(cs, ";");
 		while (ptr)
 		{
diff --git a/src/interfaces/odbc/connection.h b/src/interfaces/odbc/connection.h
index 4da6a7b7a85..902480896fd 100644
--- a/src/interfaces/odbc/connection.h
+++ b/src/interfaces/odbc/connection.h
@@ -159,6 +159,7 @@ typedef struct
 	char		translation_dll[MEDIUM_REGISTRY_LEN];
 	char		translation_option[SMALL_REGISTRY_LEN];
 	char		focus_password;
+	GLOBAL_VALUES	drivers; /* moved from driver's option */
 } ConnInfo;
 
 /*	Macro to determine is the connection using 6.2 protocol? */
diff --git a/src/interfaces/odbc/convert.c b/src/interfaces/odbc/convert.c
index 799b8c5b772..d0abad249e2 100644
--- a/src/interfaces/odbc/convert.c
+++ b/src/interfaces/odbc/convert.c
@@ -58,7 +58,6 @@ typedef signed char SCHAR;
 #endif
 #endif
 
-extern GLOBAL_VALUES globals;
 
 /*
  *	How to map ODBC scalar functions {fn func(args)} to Postgres.
@@ -132,10 +131,10 @@ char	   *mapFuncs[][2] = {
 	{0, 0}
 };
 
-char	   *mapFunction(char *func);
-unsigned int conv_from_octal(unsigned char *s);
-unsigned int conv_from_hex(unsigned char *s);
-char	   *conv_to_octal(unsigned char val);
+static char   *mapFunction(const char *func);
+static unsigned int conv_from_octal(const unsigned char *s);
+static unsigned int conv_from_hex(const unsigned char *s);
+static char	   *conv_to_octal(unsigned char val);
 
 /*---------
  *			A Guide for date/time/timestamp conversions
@@ -180,14 +179,16 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
 	struct tm  *tim;
 	int			pcbValueOffset,
 				rgbValueOffset;
-	char	   *rgbValueBindRow,
-			   *ptr;
+	char	   *rgbValueBindRow;
+	const char	*ptr;
 	int			bind_row = stmt->bind_row;
 	int			bind_size = stmt->options.bind_size;
 	int			result = COPY_OK;
 	BOOL		changed;
 	static		char *tempBuf= NULL;
 	static		unsigned int tempBuflen = 0;
+	const char *neutstr = value;
+	char	midtemp[16];
 
 	if (!tempBuf)
 		tempBuflen = 0;
@@ -298,11 +299,13 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
 					This is bad ;)
 
 				*/
-					
-				if (s[0] == 'T' || s[0] == 't' || s[0] == '1')
-					s[0] = '1';
+
+				strcpy(midtemp, value);
+				if (s[0] == 'f' || s[0] == 'F' || s[0] == 'n' || s[0] == 'N' || s[0] == '0')
+					midtemp[0] = '0';
 				else
-				    s[0] = '0';
+					midtemp[0] = '1';
+				neutstr = midtemp;
 
 			}
 			break;
@@ -312,7 +315,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
 			{
 				int			nval,
 							i;
-				char	   *vp;
+				const char	*vp;
 
 				/* this is an array of eight integers */
 				short	   *short_array = (short *) ((char *) rgbValue + rgbValueOffset);
@@ -423,7 +426,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
 				len = 1;
 				if (cbValueMax > len)
 				{
-					strcpy(rgbValueBindRow, value);
+					strcpy(rgbValueBindRow, neutstr);
 					mylog("PG_TYPE_BOOL: rgbValueBindRow = '%s'\n", rgbValueBindRow);
 				}
 				break;
@@ -607,13 +610,13 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
 			case SQL_C_BIT:
 				len = 1;
 				if (bind_size > 0)
-					*(UCHAR *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(value);
+					*(UCHAR *) ((char *) rgbValue + (bind_row * bind_size)) = atoi(neutstr);
 				else
-					*((UCHAR *) rgbValue + bind_row) = atoi(value);
+					*((UCHAR *) rgbValue + bind_row) = atoi(neutstr);
 
 				/*
-				 * mylog("SQL_C_BIT: val = %d, cb = %d, rgb=%d\n",
-				 * atoi(value), cbValueMax, *((UCHAR *)rgbValue));
+				 * mylog("SQL_C_BIT: bind_row = %d val = %d, cb = %d, rgb=%d\n",
+				 * bind_row, atoi(neutstr), cbValueMax, *((UCHAR *)rgbValue));
 				 */
 				break;
 
@@ -966,10 +969,17 @@ copy_statement_with_parameters(StatementClass *stmt)
 	int			lobj_fd,
 				retval;
 	BOOL	check_select_into = FALSE; /* select into check */
+	BOOL	proc_no_param = TRUE;
 	unsigned int	declare_pos;
+	ConnectionClass	*conn = SC_get_conn(stmt);
+	ConnInfo	*ci = &(conn->connInfo);
+	BOOL	prepare_dummy_cursor = FALSE;
 #ifdef	DRIVER_CURSOR_IMPLEMENT
 	BOOL ins_ctrl = FALSE;
 #endif /* DRIVER_CURSOR_IMPLEMENT */
+#ifdef	PREPARE_TRIAL
+	prepare_dummy_cursor = stmt->pre_executing;
+#endif /* PREPARE_TRIAL */
 
 
 	if (!old_statement)
@@ -986,22 +996,6 @@ copy_statement_with_parameters(StatementClass *stmt)
 	st.d = tim->tm_mday;
 	st.y = tim->tm_year + 1900;
 
-	/* If the application hasn't set a cursor name, then generate one */
-	if (stmt->cursor_name[0] == '\0')
-		sprintf(stmt->cursor_name, "SQL_CUR%p", stmt);
-
-	oldstmtlen = strlen(old_statement);
-	CVT_INIT(oldstmtlen);
-	/* For selects, prepend a declare cursor to the statement */
-	if (stmt->statement_type == STMT_TYPE_SELECT && globals.use_declarefetch)
-	{
-		sprintf(new_statement, "declare %s cursor for ", stmt->cursor_name);
-		npos = strlen(new_statement);
-		check_select_into = TRUE;
-		declare_pos = npos;
-	}
-	param_number = -1;
-
 #ifdef	DRIVER_CURSOR_IMPLEMENT
 	if (stmt->statement_type != STMT_TYPE_SELECT)
 	{
@@ -1021,6 +1015,34 @@ copy_statement_with_parameters(StatementClass *stmt)
 		else ins_ctrl = TRUE;
 	}
 #endif /* DRIVER_CURSOR_IMPLEMENT */
+
+	/* If the application hasn't set a cursor name, then generate one */
+	if (stmt->cursor_name[0] == '\0')
+		sprintf(stmt->cursor_name, "SQL_CUR%p", stmt);
+	oldstmtlen = strlen(old_statement);
+	CVT_INIT(oldstmtlen);
+	stmt->miscinfo = 0;
+	/* For selects, prepend a declare cursor to the statement */
+	if (stmt->statement_type == STMT_TYPE_SELECT)
+	{
+		SC_set_pre_executable(stmt);
+		if (prepare_dummy_cursor || ci->drivers.use_declarefetch)
+		{
+			if (prepare_dummy_cursor)
+			{
+				if (!CC_is_in_trans(conn))
+					strcpy(new_statement, "begin;");
+			}
+			else if (ci->drivers.use_declarefetch)
+				SC_set_fetchcursor(stmt);
+			sprintf(new_statement, "%s declare %s cursor for ",
+				 new_statement, stmt->cursor_name);
+			npos = strlen(new_statement);
+			check_select_into = TRUE;
+			declare_pos = npos;
+		}
+	}
+	param_number = -1;
 #ifdef MULTIBYTE
 	multibyte_init();
 #endif
@@ -1087,7 +1109,9 @@ copy_statement_with_parameters(StatementClass *stmt)
 			/* procedure calls */
 			if (stmt->statement_type == STMT_TYPE_PROCCALL)
 			{
+				int	lit_call_len = 4;
 				while (isspace((unsigned char) old_statement[++opos]));
+				/* '=?' to accept return values exists ? */
 				if (old_statement[opos] == '?')
 				{
 					param_number++;
@@ -1099,13 +1123,16 @@ copy_statement_with_parameters(StatementClass *stmt)
 					}
 					while (isspace((unsigned char) old_statement[++opos]));
 				}
-				if (strnicmp(&old_statement[opos], "call", 4))
+				if (strnicmp(&old_statement[opos], "call", lit_call_len) ||
+					!isspace(old_statement[opos + lit_call_len]))
 				{
 					opos--;
 					continue;
 				}
-				opos += (4 - 1);
-				CVT_APPEND_STR("SELECT");
+				opos += lit_call_len; 
+				CVT_APPEND_STR("SELECT ");
+				if (strchr(&old_statement[opos], '('))
+					proc_no_param = FALSE;
 				continue; 
 			}
 			*end = '\0';
@@ -1128,7 +1155,11 @@ copy_statement_with_parameters(StatementClass *stmt)
 		}
 		/* End of a procedure call */
 		else if (oldchar == '}' && stmt->statement_type == STMT_TYPE_PROCCALL)
+		{
+			if (proc_no_param)
+				CVT_APPEND_STR("()");
 			continue;
+		}
 
 		/*
 		 * Can you have parameter markers inside of quotes?  I dont think
@@ -1151,6 +1182,8 @@ copy_statement_with_parameters(StatementClass *stmt)
     				 into_table_from(&old_statement[opos]))
 			{
 				stmt->statement_type = STMT_TYPE_CREATE;
+				SC_no_pre_executable(stmt);
+				SC_no_fetchcursor(stmt);
 				stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
 				memmove(new_statement, new_statement + declare_pos, npos - declare_pos);
 				npos -= declare_pos;
@@ -1446,12 +1479,12 @@ copy_statement_with_parameters(StatementClass *stmt)
 				else
 				{
 					/* begin transaction if needed */
-					if (!CC_is_in_trans(stmt->hdbc))
+					if (!CC_is_in_trans(conn))
 					{
 						QResultClass *res;
 						char		ok;
 
-						res = CC_send_query(stmt->hdbc, "BEGIN", NULL);
+						res = CC_send_query(conn, "BEGIN", NULL);
 						if (!res)
 						{
 							stmt->errormsg = "Could not begin (in-line) a transaction";
@@ -1469,11 +1502,11 @@ copy_statement_with_parameters(StatementClass *stmt)
 							return SQL_ERROR;
 						}
 
-						CC_set_in_trans(stmt->hdbc);
+						CC_set_in_trans(conn);
 					}
 
 					/* store the oid */
-					lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE);
+					lobj_oid = lo_creat(conn, INV_READ | INV_WRITE);
 					if (lobj_oid == 0)
 					{
 						stmt->errornumber = STMT_EXEC_ERROR;
@@ -1483,7 +1516,7 @@ copy_statement_with_parameters(StatementClass *stmt)
 					}
 
 					/* store the fd */
-					lobj_fd = lo_open(stmt->hdbc, lobj_oid, INV_WRITE);
+					lobj_fd = lo_open(conn, lobj_oid, INV_WRITE);
 					if (lobj_fd < 0)
 					{
 						stmt->errornumber = STMT_EXEC_ERROR;
@@ -1492,17 +1525,17 @@ copy_statement_with_parameters(StatementClass *stmt)
 						return SQL_ERROR;
 					}
 
-					retval = lo_write(stmt->hdbc, lobj_fd, buffer, used);
+					retval = lo_write(conn, lobj_fd, buffer, used);
 
-					lo_close(stmt->hdbc, lobj_fd);
+					lo_close(conn, lobj_fd);
 
 					/* commit transaction if needed */
-					if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc))
+					if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))
 					{
 						QResultClass *res;
 						char		ok;
 
-						res = CC_send_query(stmt->hdbc, "COMMIT", NULL);
+						res = CC_send_query(conn, "COMMIT", NULL);
 						if (!res)
 						{
 							stmt->errormsg = "Could not commit (in-line) a transaction";
@@ -1520,7 +1553,7 @@ copy_statement_with_parameters(StatementClass *stmt)
 							return SQL_ERROR;
 						}
 
-						CC_set_no_trans(stmt->hdbc);
+						CC_set_no_trans(conn);
 					}
 				}
 
@@ -1589,11 +1622,11 @@ copy_statement_with_parameters(StatementClass *stmt)
 	/* make sure new_statement is always null-terminated */
 	CVT_TERMINATE
 
-	if (stmt->hdbc->DriverToDataSource != NULL)
+	if (conn->DriverToDataSource != NULL)
 	{
 		int			length = strlen(new_statement);
 
-		stmt->hdbc->DriverToDataSource(stmt->hdbc->translation_option,
+		conn->DriverToDataSource(conn->translation_option,
 									   SQL_CHAR,
 									   new_statement, length,
 									   new_statement, length, NULL,
@@ -1604,12 +1637,25 @@ copy_statement_with_parameters(StatementClass *stmt)
 	if (ins_ctrl)
 		stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
 #endif /* DRIVER_CURSOR_IMPLEMENT */
+#ifdef	PREPARE_TRIAL
+	if (prepare_dummy_cursor && SC_is_pre_executable(stmt))
+	{
+		char fetchstr[128];	
+		sprintf(fetchstr, ";fetch backward in %s;close %s;",
+				stmt->cursor_name, stmt->cursor_name);
+		if (!CC_is_in_trans(conn))
+			strcat(fetchstr, "commit;");
+		CVT_APPEND_STR(fetchstr);
+		stmt->inaccurate_result = TRUE;
+	}
+#endif /* PREPARE_TRIAL */
+
 	return SQL_SUCCESS;
 }
 
 
 char *
-mapFunction(char *func)
+mapFunction(const char *func)
 {
 	int			i;
 
@@ -1850,7 +1896,7 @@ convert_linefeeds(const char *si, char *dst, size_t max, BOOL *changed)
  *	Plus, escape any special characters.
  */
 int
-convert_special_chars(char *si, char *dst, int used)
+convert_special_chars(const char *si, char *dst, int used)
 {
 	size_t		i = 0,
 				out = 0,
@@ -1904,7 +1950,7 @@ convert_special_chars(char *si, char *dst, int used)
 
 /*	!!! Need to implement this function !!!  */
 int
-convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax)
+convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax)
 {
 	mylog("convert_pgbinary_to_char: value = '%s'\n", value);
 
@@ -1914,7 +1960,7 @@ convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax)
 
 
 unsigned int
-conv_from_octal(unsigned char *s)
+conv_from_octal(const unsigned char *s)
 {
 	int			i,
 				y = 0;
@@ -1928,7 +1974,7 @@ conv_from_octal(unsigned char *s)
 
 
 unsigned int
-conv_from_hex(unsigned char *s)
+conv_from_hex(const unsigned char *s)
 {
 	int			i,
 				y = 0,
@@ -1952,7 +1998,7 @@ conv_from_hex(unsigned char *s)
 
 /*	convert octal escapes to bytes */
 int
-convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax)
+convert_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int cbValueMax)
 {
 	size_t		i, ilen = strlen(value);
 	int			o = 0;
@@ -2007,7 +2053,7 @@ conv_to_octal(unsigned char val)
 
 /*	convert non-ascii bytes to octal escape sequences */
 int
-convert_to_pgbinary(unsigned char *in, char *out, int len)
+convert_to_pgbinary(const unsigned char *in, char *out, int len)
 {
 	int			i,
 				o = 0;
@@ -2031,7 +2077,7 @@ convert_to_pgbinary(unsigned char *in, char *out, int len)
 
 
 void
-encode(char *in, char *out)
+encode(const char *in, char *out)
 {
 	unsigned int i, ilen = strlen(in),
 				o = 0;
@@ -2058,7 +2104,7 @@ encode(char *in, char *out)
 
 
 void
-decode(char *in, char *out)
+decode(const char *in, char *out)
 {
 	unsigned int i, ilen = strlen(in),
 				o = 0;
@@ -2104,7 +2150,8 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
 				result,
 				left = -1;
 	BindInfoClass *bindInfo = NULL;
-
+	ConnectionClass	*conn = SC_get_conn(stmt);
+	ConnInfo	*ci = &(conn->connInfo);
 
 	/* If using SQLGetData, then current_col will be set */
 	if (stmt->current_col >= 0)
@@ -2121,12 +2168,12 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
 	if (!bindInfo || bindInfo->data_left == -1)
 	{
 		/* begin transaction if needed */
-		if (!CC_is_in_trans(stmt->hdbc))
+		if (!CC_is_in_trans(conn))
 		{
 			QResultClass *res;
 			char		ok;
 
-			res = CC_send_query(stmt->hdbc, "BEGIN", NULL);
+			res = CC_send_query(conn, "BEGIN", NULL);
 			if (!res)
 			{
 				stmt->errormsg = "Could not begin (in-line) a transaction";
@@ -2142,11 +2189,11 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
 				return COPY_GENERAL_ERROR;
 			}
 
-			CC_set_in_trans(stmt->hdbc);
+			CC_set_in_trans(conn);
 		}
 
 		oid = atoi(value);
-		stmt->lobj_fd = lo_open(stmt->hdbc, oid, INV_READ);
+		stmt->lobj_fd = lo_open(conn, oid, INV_READ);
 		if (stmt->lobj_fd < 0)
 		{
 			stmt->errornumber = STMT_EXEC_ERROR;
@@ -2155,15 +2202,15 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
 		}
 
 		/* Get the size */
-		retval = lo_lseek(stmt->hdbc, stmt->lobj_fd, 0L, SEEK_END);
+		retval = lo_lseek(conn, stmt->lobj_fd, 0L, SEEK_END);
 		if (retval >= 0)
 		{
-			left = lo_tell(stmt->hdbc, stmt->lobj_fd);
+			left = lo_tell(conn, stmt->lobj_fd);
 			if (bindInfo)
 				bindInfo->data_left = left;
 
 			/* return to beginning */
-			lo_lseek(stmt->hdbc, stmt->lobj_fd, 0L, SEEK_SET);
+			lo_lseek(conn, stmt->lobj_fd, 0L, SEEK_SET);
 		}
 	}
 
@@ -2177,18 +2224,18 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
 		return COPY_GENERAL_ERROR;
 	}
 
-	retval = lo_read(stmt->hdbc, stmt->lobj_fd, (char *) rgbValue, cbValueMax);
+	retval = lo_read(conn, stmt->lobj_fd, (char *) rgbValue, cbValueMax);
 	if (retval < 0)
 	{
-		lo_close(stmt->hdbc, stmt->lobj_fd);
+		lo_close(conn, stmt->lobj_fd);
 
 		/* commit transaction if needed */
-		if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc))
+		if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))
 		{
 			QResultClass *res;
 			char		ok;
 
-			res = CC_send_query(stmt->hdbc, "COMMIT", NULL);
+			res = CC_send_query(conn, "COMMIT", NULL);
 			if (!res)
 			{
 				stmt->errormsg = "Could not commit (in-line) a transaction";
@@ -2204,7 +2251,7 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
 				return COPY_GENERAL_ERROR;
 			}
 
-			CC_set_no_trans(stmt->hdbc);
+			CC_set_no_trans(conn);
 		}
 
 		stmt->lobj_fd = -1;
@@ -2227,15 +2274,15 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
 
 	if (!bindInfo || bindInfo->data_left == 0)
 	{
-		lo_close(stmt->hdbc, stmt->lobj_fd);
+		lo_close(conn, stmt->lobj_fd);
 
 		/* commit transaction if needed */
-		if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc))
+		if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))
 		{
 			QResultClass *res;
 			char		ok;
 
-			res = CC_send_query(stmt->hdbc, "COMMIT", NULL);
+			res = CC_send_query(conn, "COMMIT", NULL);
 			if (!res)
 			{
 				stmt->errormsg = "Could not commit (in-line) a transaction";
@@ -2251,7 +2298,7 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
 				return COPY_GENERAL_ERROR;
 			}
 
-			CC_set_no_trans(stmt->hdbc);
+			CC_set_no_trans(conn);
 		}
 
 		stmt->lobj_fd = -1;		/* prevent further reading */
diff --git a/src/interfaces/odbc/convert.h b/src/interfaces/odbc/convert.h
index 8a7d15e5d4b..aaf15183444 100644
--- a/src/interfaces/odbc/convert.h
+++ b/src/interfaces/odbc/convert.h
@@ -29,8 +29,8 @@ typedef struct
 	int			ss;
 } SIMPLE_TIME;
 
-int			copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *value, int col);
-int copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType,
+int			copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, const void *value, int col);
+int copy_and_convert_field(StatementClass *stmt, Int4 field_type, const void *value, Int2 fCType,
 					   PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue);
 
 int			copy_statement_with_parameters(StatementClass *stmt);
@@ -38,14 +38,14 @@ char	   *convert_escape(char *value);
 char	   *convert_money(char *s);
 char		parse_datetime(char *buf, SIMPLE_TIME *st);
 int		convert_linefeeds(const char *s, char *dst, size_t max, BOOL *changed);
-int	   convert_special_chars(char *si, char *dst, int used);
-
-int			convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax);
-int			convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax);
-int			convert_to_pgbinary(unsigned char *in, char *out, int len);
-void		encode(char *in, char *out);
-void		decode(char *in, char *out);
-int convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
+int	   convert_special_chars(const char *si, char *dst, int used);
+
+int			convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax);
+int			convert_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int cbValueMax);
+int			convert_to_pgbinary(const unsigned char *in, char *out, int len);
+void		encode(const char *in, char *out);
+void		decode(const char *in, char *out);
+int convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
 		   SDWORD cbValueMax, SDWORD *pcbValue);
 
 #endif
diff --git a/src/interfaces/odbc/dlg_specific.c b/src/interfaces/odbc/dlg_specific.c
index d28fcf966c4..facf77dd099 100644
--- a/src/interfaces/odbc/dlg_specific.c
+++ b/src/interfaces/odbc/dlg_specific.c
@@ -49,11 +49,15 @@
 #endif
 
 extern GLOBAL_VALUES globals;
-
+#ifdef	WIN32
+static int driver_optionsDraw(HWND, const ConnInfo *, int src, BOOL enable);
+static int driver_options_update(HWND hdlg, ConnInfo *ci, BOOL);
+#endif
+static void updateCommons(const ConnInfo *ci);
 
 #ifdef WIN32
 void
-SetDlgStuff(HWND hdlg, ConnInfo *ci)
+SetDlgStuff(HWND hdlg, const ConnInfo *ci)
 {
 
 	/*
@@ -87,145 +91,204 @@ GetDlgStuff(HWND hdlg, ConnInfo *ci)
 }
 
 
-int			CALLBACK
-driver_optionsProc(HWND hdlg,
-				   WORD wMsg,
-				   WPARAM wParam,
-				   LPARAM lParam)
+static int
+driver_optionsDraw(HWND hdlg, const ConnInfo *ci, int src, BOOL enable)
 {
-	switch (wMsg)
+	const GLOBAL_VALUES	*comval;
+	static BOOL	defset = FALSE;
+	static GLOBAL_VALUES	defval;
+		
+	switch (src)
 	{
-			case WM_INITDIALOG:
-
-			CheckDlgButton(hdlg, DRV_COMMLOG, globals.commlog);
-			CheckDlgButton(hdlg, DRV_OPTIMIZER, globals.disable_optimizer);
-			CheckDlgButton(hdlg, DRV_KSQO, globals.ksqo);
-			CheckDlgButton(hdlg, DRV_UNIQUEINDEX, globals.unique_index);
-			CheckDlgButton(hdlg, DRV_READONLY, globals.onlyread);
-			CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, globals.use_declarefetch);
-
-			/* Unknown (Default) Data Type sizes */
-			switch (globals.unknown_sizes)
+		case 0: /* driver common */
+			comval = &globals;
+			break;
+		case 1: /* dsn specific */
+			comval = &(ci->drivers);
+			break;
+		case 2: /* default */
+			if (!defset)
 			{
-				case UNKNOWNS_AS_DONTKNOW:
-					CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 1);
-					break;
-				case UNKNOWNS_AS_LONGEST:
-					CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 1);
-					break;
-				case UNKNOWNS_AS_MAX:
-				default:
-					CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 1);
-					break;
+				defval.commlog = DEFAULT_COMMLOG;
+				defval.disable_optimizer = DEFAULT_OPTIMIZER;
+				defval.ksqo = DEFAULT_KSQO;
+				defval.unique_index = DEFAULT_UNIQUEINDEX;
+				defval.onlyread = DEFAULT_READONLY;
+				defval.use_declarefetch = DEFAULT_USEDECLAREFETCH;
+
+				defval.parse = DEFAULT_PARSE;
+				defval.cancel_as_freestmt = DEFAULT_CANCELASFREESTMT;
+				defval.debug = DEFAULT_DEBUG;
+
+				/* Unknown Sizes */
+				defval.unknown_sizes = DEFAULT_UNKNOWNSIZES;
+				defval.text_as_longvarchar = DEFAULT_TEXTASLONGVARCHAR;
+				defval.unknowns_as_longvarchar = DEFAULT_UNKNOWNSASLONGVARCHAR;
+				defval.bools_as_char = DEFAULT_BOOLSASCHAR;
 			}
+			defset = TRUE;
+			comval = &defval;
+			break;
+	}
 
-			CheckDlgButton(hdlg, DRV_TEXT_LONGVARCHAR, globals.text_as_longvarchar);
-			CheckDlgButton(hdlg, DRV_UNKNOWNS_LONGVARCHAR, globals.unknowns_as_longvarchar);
-			CheckDlgButton(hdlg, DRV_BOOLS_CHAR, globals.bools_as_char);
+	CheckDlgButton(hdlg, DRV_COMMLOG, comval->commlog);
+	CheckDlgButton(hdlg, DRV_OPTIMIZER, comval->disable_optimizer);
+	CheckDlgButton(hdlg, DRV_KSQO, comval->ksqo);
+	CheckDlgButton(hdlg, DRV_UNIQUEINDEX, comval->unique_index);
+	EnableWindow(GetDlgItem(hdlg, DRV_UNIQUEINDEX), enable);
+	CheckDlgButton(hdlg, DRV_READONLY, comval->onlyread);
+	EnableWindow(GetDlgItem(hdlg, DRV_READONLY), enable);
+	CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, comval->use_declarefetch);
+
+	/* Unknown Sizes clear */
+	CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 0);
+	CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 0);
+	CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 0);
+	/* Unknown (Default) Data Type sizes */
+	switch (comval->unknown_sizes)
+	{
+		case UNKNOWNS_AS_DONTKNOW:
+			CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 1);
+			break;
+		case UNKNOWNS_AS_LONGEST:
+			CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 1);
+			break;
+		case UNKNOWNS_AS_MAX:
+		default:
+			CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 1);
+			break;
+	}
 
-			CheckDlgButton(hdlg, DRV_PARSE, globals.parse);
+	CheckDlgButton(hdlg, DRV_TEXT_LONGVARCHAR, comval->text_as_longvarchar);
+	CheckDlgButton(hdlg, DRV_UNKNOWNS_LONGVARCHAR, comval->unknowns_as_longvarchar);
+	CheckDlgButton(hdlg, DRV_BOOLS_CHAR, comval->bools_as_char);
+	CheckDlgButton(hdlg, DRV_PARSE, comval->parse);
+	CheckDlgButton(hdlg, DRV_CANCELASFREESTMT, comval->cancel_as_freestmt);
+	CheckDlgButton(hdlg, DRV_DEBUG, comval->debug);
+	SetDlgItemInt(hdlg, DRV_CACHE_SIZE, comval->fetch_max, FALSE);
+	SetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, comval->max_varchar_size, FALSE);
+	SetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, comval->max_longvarchar_size, TRUE);
+	SetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, comval->extra_systable_prefixes);
+
+	/* Driver Connection Settings */
+	SetDlgItemText(hdlg, DRV_CONNSETTINGS, comval->conn_settings);
+	EnableWindow(GetDlgItem(hdlg, DRV_CONNSETTINGS), enable);
+	return 0;
+}
+static int
+driver_options_update(HWND hdlg, ConnInfo *ci, BOOL updateProfile)
+{
+	GLOBAL_VALUES	*comval;
+
+	if (ci)
+		comval = &(ci->drivers);
+	else
+		comval = &globals;
+	comval->commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG);
+	comval->disable_optimizer = IsDlgButtonChecked(hdlg, DRV_OPTIMIZER);
+	comval->ksqo = IsDlgButtonChecked(hdlg, DRV_KSQO);
+	if (!ci)
+	{
+		comval->unique_index = IsDlgButtonChecked(hdlg, DRV_UNIQUEINDEX);
+		comval->onlyread = IsDlgButtonChecked(hdlg, DRV_READONLY);
+	}
+	comval->use_declarefetch = IsDlgButtonChecked(hdlg, DRV_USEDECLAREFETCH);
+
+	/* Unknown (Default) Data Type sizes */
+	if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_MAX))
+		comval->unknown_sizes = UNKNOWNS_AS_MAX;
+	else if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_DONTKNOW))
+		comval->unknown_sizes = UNKNOWNS_AS_DONTKNOW;
+	else if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_LONGEST))
+		comval->unknown_sizes = UNKNOWNS_AS_LONGEST;
+	else
+		comval->unknown_sizes = UNKNOWNS_AS_MAX;
+
+	comval->text_as_longvarchar = IsDlgButtonChecked(hdlg, DRV_TEXT_LONGVARCHAR);
+	comval->unknowns_as_longvarchar = IsDlgButtonChecked(hdlg, DRV_UNKNOWNS_LONGVARCHAR);
+	comval->bools_as_char = IsDlgButtonChecked(hdlg, DRV_BOOLS_CHAR);
+
+	comval->parse = IsDlgButtonChecked(hdlg, DRV_PARSE);
+
+	comval->cancel_as_freestmt = IsDlgButtonChecked(hdlg, DRV_CANCELASFREESTMT);
+	comval->debug = IsDlgButtonChecked(hdlg, DRV_DEBUG);
+
+	comval->fetch_max = GetDlgItemInt(hdlg, DRV_CACHE_SIZE, NULL, FALSE);
+	comval->max_varchar_size = GetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, NULL, FALSE);
+	comval->max_longvarchar_size = GetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, NULL, TRUE);		/* allows for
+																												 * SQL_NO_TOTAL */
 
-			CheckDlgButton(hdlg, DRV_CANCELASFREESTMT, globals.cancel_as_freestmt);
+	GetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, comval->extra_systable_prefixes, sizeof(comval->extra_systable_prefixes));
 
-			SetDlgItemInt(hdlg, DRV_CACHE_SIZE, globals.fetch_max, FALSE);
-			SetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, globals.max_varchar_size, FALSE);
-			SetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, globals.max_longvarchar_size, TRUE);
+	/* Driver Connection Settings */
+	if (!ci)
+		GetDlgItemText(hdlg, DRV_CONNSETTINGS, comval->conn_settings, sizeof(comval->conn_settings));
 
-			SetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, globals.extra_systable_prefixes);
+	if (updateProfile)
+		updateCommons(ci);
 
-			/* Driver Connection Settings */
-			SetDlgItemText(hdlg, DRV_CONNSETTINGS, globals.conn_settings);
+	/* fall through */
+	return 0;
+}
 
+int			CALLBACK
+driver_optionsProc(HWND hdlg,
+				   WORD wMsg,
+				   WPARAM wParam,
+				   LPARAM lParam)
+{
+	ConnInfo *ci;
+	switch (wMsg)
+	{
+		case WM_INITDIALOG:
+			SetWindowLong(hdlg, DWL_USER, lParam);	/* save for OK etc */
+			ci = (ConnInfo *) lParam;
+			if (ci && ci->dsn && ci->dsn[0])
+			{
+				driver_optionsDraw(hdlg, NULL, 0, TRUE);
+			}
+			else
+			{
+				CheckDlgButton(hdlg, DRV_OR_DSN, 1);
+				ShowWindow(GetDlgItem(hdlg, DRV_OR_DSN), SW_HIDE);
+				driver_optionsDraw(hdlg, ci, 1, FALSE);
+			}
 			break;
 
 		case WM_COMMAND:
 			switch (GET_WM_COMMAND_ID(wParam, lParam))
 			{
 				case IDOK:
-					globals.commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG);
-					globals.disable_optimizer = IsDlgButtonChecked(hdlg, DRV_OPTIMIZER);
-					globals.ksqo = IsDlgButtonChecked(hdlg, DRV_KSQO);
-					globals.unique_index = IsDlgButtonChecked(hdlg, DRV_UNIQUEINDEX);
-					globals.onlyread = IsDlgButtonChecked(hdlg, DRV_READONLY);
-					globals.use_declarefetch = IsDlgButtonChecked(hdlg, DRV_USEDECLAREFETCH);
-
-					/* Unknown (Default) Data Type sizes */
-					if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_MAX))
-						globals.unknown_sizes = UNKNOWNS_AS_MAX;
-					else if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_DONTKNOW))
-						globals.unknown_sizes = UNKNOWNS_AS_DONTKNOW;
-					else if (IsDlgButtonChecked(hdlg, DRV_UNKNOWN_LONGEST))
-						globals.unknown_sizes = UNKNOWNS_AS_LONGEST;
-					else
-						globals.unknown_sizes = UNKNOWNS_AS_MAX;
-
-					globals.text_as_longvarchar = IsDlgButtonChecked(hdlg, DRV_TEXT_LONGVARCHAR);
-					globals.unknowns_as_longvarchar = IsDlgButtonChecked(hdlg, DRV_UNKNOWNS_LONGVARCHAR);
-					globals.bools_as_char = IsDlgButtonChecked(hdlg, DRV_BOOLS_CHAR);
-
-					globals.parse = IsDlgButtonChecked(hdlg, DRV_PARSE);
-
-					globals.cancel_as_freestmt = IsDlgButtonChecked(hdlg, DRV_CANCELASFREESTMT);
-
-					globals.fetch_max = GetDlgItemInt(hdlg, DRV_CACHE_SIZE, NULL, FALSE);
-					globals.max_varchar_size = GetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, NULL, FALSE);
-					globals.max_longvarchar_size = GetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, NULL, TRUE);		/* allows for
-																												 * SQL_NO_TOTAL */
-
-					GetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, globals.extra_systable_prefixes, sizeof(globals.extra_systable_prefixes));
-
-					/* Driver Connection Settings */
-					GetDlgItemText(hdlg, DRV_CONNSETTINGS, globals.conn_settings, sizeof(globals.conn_settings));
-
-					updateGlobals();
-
-					/* fall through */
+					ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
+					driver_options_update(hdlg, IsDlgButtonChecked(hdlg, DRV_OR_DSN) ? ci : NULL,
+						ci && ci->dsn && ci->dsn[0]);
 
 				case IDCANCEL:
 					EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
 					return TRUE;
 
 				case IDDEFAULTS:
-					CheckDlgButton(hdlg, DRV_COMMLOG, DEFAULT_COMMLOG);
-					CheckDlgButton(hdlg, DRV_OPTIMIZER, DEFAULT_OPTIMIZER);
-					CheckDlgButton(hdlg, DRV_KSQO, DEFAULT_KSQO);
-					CheckDlgButton(hdlg, DRV_UNIQUEINDEX, DEFAULT_UNIQUEINDEX);
-					CheckDlgButton(hdlg, DRV_READONLY, DEFAULT_READONLY);
-					CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, DEFAULT_USEDECLAREFETCH);
-
-					CheckDlgButton(hdlg, DRV_PARSE, DEFAULT_PARSE);
-					CheckDlgButton(hdlg, DRV_CANCELASFREESTMT, DEFAULT_CANCELASFREESTMT);
-
-					/* Unknown Sizes */
-					CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 0);
-					CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 0);
-					CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 0);
-					switch (DEFAULT_UNKNOWNSIZES)
+					if (IsDlgButtonChecked(hdlg, DRV_OR_DSN))
 					{
-						case UNKNOWNS_AS_DONTKNOW:
-							CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 1);
-							break;
-						case UNKNOWNS_AS_LONGEST:
-							CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 1);
-							break;
-						case UNKNOWNS_AS_MAX:
-							CheckDlgButton(hdlg, DRV_UNKNOWN_MAX, 1);
-							break;
+						ConnInfo   *ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
+						driver_optionsDraw(hdlg, ci, 0, FALSE);
 					}
+					else
+						driver_optionsDraw(hdlg, NULL, 2, TRUE);
+					break;
 
-					CheckDlgButton(hdlg, DRV_TEXT_LONGVARCHAR, DEFAULT_TEXTASLONGVARCHAR);
-					CheckDlgButton(hdlg, DRV_UNKNOWNS_LONGVARCHAR, DEFAULT_UNKNOWNSASLONGVARCHAR);
-					CheckDlgButton(hdlg, DRV_BOOLS_CHAR, DEFAULT_BOOLSASCHAR);
-
-					SetDlgItemInt(hdlg, DRV_CACHE_SIZE, FETCH_MAX, FALSE);
-					SetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, MAX_VARCHAR_SIZE, FALSE);
-					SetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, TEXT_FIELD_SIZE, TRUE);
-
-					SetDlgItemText(hdlg, DRV_EXTRASYSTABLEPREFIXES, DEFAULT_EXTRASYSTABLEPREFIXES);
-
-					/* Driver Connection Settings */
-					SetDlgItemText(hdlg, DRV_CONNSETTINGS, "");
-
+				case DRV_OR_DSN:
+					if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
+					{
+						mylog("DRV_OR_DSN clicked\n");
+						if (IsDlgButtonChecked(hdlg, DRV_OR_DSN))
+						{
+							ConnInfo   *ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
+							driver_optionsDraw(hdlg, ci, ci ? 1 : 0, ci == NULL);
+						}
+						else
+							driver_optionsDraw(hdlg, NULL, 0, TRUE);
+					}
 					break;
 			}
 	}
@@ -331,10 +394,11 @@ ds_optionsProc(HWND hdlg,
 
 
 void
-makeConnectString(char *connect_string, ConnInfo *ci)
+makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
 {
 	char		got_dsn = (ci->dsn[0] != '\0');
 	char		encoded_conn_settings[LARGE_REGISTRY_LEN];
+	UWORD		hlen;
 
 	/* fundamental info */
 	sprintf(connect_string, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;PWD=%s",
@@ -349,20 +413,64 @@ makeConnectString(char *connect_string, ConnInfo *ci)
 	encode(ci->conn_settings, encoded_conn_settings);
 
 	/* extra info */
-	sprintf(&connect_string[strlen(connect_string)],
-			";READONLY=%s;PROTOCOL=%s;FAKEOIDINDEX=%s;SHOWOIDCOLUMN=%s;ROWVERSIONING=%s;SHOWSYSTEMTABLES=%s;CONNSETTINGS=%s",
+	hlen = strlen(connect_string),
+	sprintf(&connect_string[hlen],
+			";READONLY=%s;PROTOCOL=%s;FAKEOIDINDEX=%s;SHOWOIDCOLUMN=%s;ROWVERSIONING=%s;SHOWSYSTEMTABLES=%s;CONNSETTINGS=%s;FETCH=%d;SOCKET=%d;UNKNOWNSIZES=%d;MAXVARCHARSIZE=%d;MAXLONGVARCHARSIZE=%d;DEBUG=%d;COMMLOG=%d;OPTIMIZER=%d;KSQO=%d;USEDECLAREFETCH=%d;TEXTASLONGVARCHAR=%d;UNKNOWNSASLONGVARCHAR=%d;BOOLSASCHAR=%d;PARSE=%d;CANCELASFREESTMT=%d;EXTRASYSTABLEPREFIXES=%s",
+			ci->onlyread,
+			ci->protocol,
+			ci->fake_oid_index,
+			ci->show_oid_column,
+			ci->row_versioning,
+			ci->show_system_tables,
+			encoded_conn_settings,
+			ci->drivers.fetch_max,
+			ci->drivers.socket_buffersize,
+			ci->drivers.unknown_sizes,
+			ci->drivers.max_varchar_size,
+			ci->drivers.max_longvarchar_size,
+			ci->drivers.debug,
+			ci->drivers.commlog,
+			ci->drivers.disable_optimizer,
+			ci->drivers.ksqo,
+			ci->drivers.use_declarefetch,
+			ci->drivers.text_as_longvarchar,
+			ci->drivers.unknowns_as_longvarchar,
+			ci->drivers.bools_as_char,
+			ci->drivers.parse,
+			ci->drivers.cancel_as_freestmt,
+			ci->drivers.extra_systable_prefixes);
+	/* Abbrebiation is needed ? */
+	if (strlen(connect_string) >= len)
+		sprintf(&connect_string[hlen],
+			";A0=%s;A1=%s;A2=%s;A3=%s;A4=%s;A5=%s;A6=%s;A7=%d;A8=%d;A9=%d;B0=%d;B1=%d;B2=%d;B3=%d;B4=%d;B5=%d;B6=%d;B7=%d;B8=%d;B9=%d;C0=%d;C1=%d;C2=%s",
 			ci->onlyread,
 			ci->protocol,
 			ci->fake_oid_index,
 			ci->show_oid_column,
 			ci->row_versioning,
 			ci->show_system_tables,
-			encoded_conn_settings);
+			encoded_conn_settings,
+			ci->drivers.fetch_max,
+			ci->drivers.socket_buffersize,
+			ci->drivers.unknown_sizes,
+			ci->drivers.max_varchar_size,
+			ci->drivers.max_longvarchar_size,
+			ci->drivers.debug,
+			ci->drivers.commlog,
+			ci->drivers.disable_optimizer,
+			ci->drivers.ksqo,
+			ci->drivers.use_declarefetch,
+			ci->drivers.text_as_longvarchar,
+			ci->drivers.unknowns_as_longvarchar,
+			ci->drivers.bools_as_char,
+			ci->drivers.parse,
+			ci->drivers.cancel_as_freestmt,
+			ci->drivers.extra_systable_prefixes);
 }
 
 
 void
-copyAttributes(ConnInfo *ci, char *attribute, char *value)
+copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
 {
 	if (stricmp(attribute, "DSN") == 0)
 		strcpy(ci->dsn, value);
@@ -385,25 +493,25 @@ copyAttributes(ConnInfo *ci, char *attribute, char *value)
 	else if (stricmp(attribute, INI_PORT) == 0)
 		strcpy(ci->port, value);
 
-	else if (stricmp(attribute, INI_READONLY) == 0)
+	else if (stricmp(attribute, INI_READONLY) == 0 || stricmp(attribute, "A0") == 0)
 		strcpy(ci->onlyread, value);
 
-	else if (stricmp(attribute, INI_PROTOCOL) == 0)
+	else if (stricmp(attribute, INI_PROTOCOL) == 0 || stricmp(attribute, "A1") == 0)
 		strcpy(ci->protocol, value);
 
-	else if (stricmp(attribute, INI_SHOWOIDCOLUMN) == 0)
+	else if (stricmp(attribute, INI_SHOWOIDCOLUMN) == 0 || stricmp(attribute, "A3") == 0)
 		strcpy(ci->show_oid_column, value);
 
-	else if (stricmp(attribute, INI_FAKEOIDINDEX) == 0)
+	else if (stricmp(attribute, INI_FAKEOIDINDEX) == 0 || stricmp(attribute, "A2") == 0)
 		strcpy(ci->fake_oid_index, value);
 
-	else if (stricmp(attribute, INI_ROWVERSIONING) == 0)
+	else if (stricmp(attribute, INI_ROWVERSIONING) == 0 || stricmp(attribute, "A4") == 0)
 		strcpy(ci->row_versioning, value);
 
-	else if (stricmp(attribute, INI_SHOWSYSTEMTABLES) == 0)
+	else if (stricmp(attribute, INI_SHOWSYSTEMTABLES) == 0 || stricmp(attribute, "A5") == 0)
 		strcpy(ci->show_system_tables, value);
 
-	else if (stricmp(attribute, INI_CONNSETTINGS) == 0)
+	else if (stricmp(attribute, INI_CONNSETTINGS) == 0 || stricmp(attribute, "A6") == 0)
 	{
 		decode(value, ci->conn_settings);
 		/* strcpy(ci->conn_settings, value); */
@@ -412,6 +520,66 @@ copyAttributes(ConnInfo *ci, char *attribute, char *value)
 	mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s', conn_settings='%s')\n", ci->dsn, ci->server, ci->database, ci->username, ci->password, ci->port, ci->onlyread, ci->protocol, ci->conn_settings);
 }
 
+void
+copyCommonAttributes(ConnInfo *ci, const char *attribute, const char *value)
+{
+	if (stricmp(attribute, INI_FETCH) == 0 || stricmp(attribute, "A7") == 0)
+		ci->drivers.fetch_max = atoi(value);
+	else if (stricmp(attribute, INI_SOCKET) == 0 || stricmp(attribute, "A8") == 0)
+		ci->drivers.socket_buffersize = atoi(value);
+	else if (stricmp(attribute, INI_DEBUG) == 0 || stricmp(attribute, "B2") == 0)
+		ci->drivers.debug = atoi(value);
+	else if (stricmp(attribute, INI_COMMLOG) == 0 || stricmp(attribute, "B3") == 0)
+		ci->drivers.commlog = atoi(value);
+	else if (stricmp(attribute, INI_OPTIMIZER) == 0 || stricmp(attribute, "B4") == 0)
+		ci->drivers.disable_optimizer = atoi(value);
+	else if (stricmp(attribute, INI_KSQO) == 0 || stricmp(attribute, "B5") == 0)
+		ci->drivers.ksqo = atoi(value);
+	/*
+	else if (stricmp(attribute, INI_UNIQUEINDEX) == 0 || stricmp(attribute, "UIX") == 0)
+		ci->drivers.unique_index = atoi(value);
+	*/
+	else if (stricmp(attribute, INI_UNKNOWNSIZES) == 0 || stricmp(attribute, "A9") == 0)
+		ci->drivers.unknown_sizes = atoi(value);
+	else if (stricmp(attribute, INI_LIE) == 0)
+		ci->drivers.lie = atoi(value);
+	else if (stricmp(attribute, INI_PARSE) == 0 || stricmp(attribute, "C0") == 0)
+		ci->drivers.parse = atoi(value);
+	else if (stricmp(attribute, INI_CANCELASFREESTMT) == 0 || stricmp(attribute, "C1") == 0)
+		ci->drivers.cancel_as_freestmt = atoi(value);
+	else if (stricmp(attribute, INI_USEDECLAREFETCH) == 0 || stricmp(attribute, "B6") == 0)
+		ci->drivers.use_declarefetch = atoi(value);
+	else if (stricmp(attribute, INI_MAXVARCHARSIZE) == 0 || stricmp(attribute, "B0") == 0)
+		ci->drivers.max_varchar_size = atoi(value);
+	else if (stricmp(attribute, INI_MAXLONGVARCHARSIZE) == 0 || stricmp(attribute, "B1") == 0)
+		ci->drivers.max_longvarchar_size = atoi(value);
+	else if (stricmp(attribute, INI_TEXTASLONGVARCHAR) == 0 || stricmp(attribute, "B7") == 0)
+		ci->drivers.text_as_longvarchar = atoi(value);
+	else if (stricmp(attribute, INI_UNKNOWNSASLONGVARCHAR) == 0 || stricmp(attribute, "B8") == 0)
+		ci->drivers.unknowns_as_longvarchar = atoi(value);
+	else if (stricmp(attribute, INI_BOOLSASCHAR) == 0 || stricmp(attribute, "B9") == 0)
+		ci->drivers.bools_as_char = atoi(value);
+	else if (stricmp(attribute, INI_EXTRASYSTABLEPREFIXES) == 0 || stricmp(attribute, "C2") == 0)
+		strcpy(ci->drivers.extra_systable_prefixes, value);
+	mylog("CopyCommonAttributes: A7=%d;A8=%d;A9=%d;B0=%d;B1=%d;B2=%d;B3=%d;B4=%d;B5=%d;B6=%d;B7=%d;B8=%d;B9=%d;C0=%d;C1=%d;C2=%s",
+			ci->drivers.fetch_max,
+			ci->drivers.socket_buffersize,
+			ci->drivers.unknown_sizes,
+			ci->drivers.max_varchar_size,
+			ci->drivers.max_longvarchar_size,
+			ci->drivers.debug,
+			ci->drivers.commlog,
+			ci->drivers.disable_optimizer,
+			ci->drivers.ksqo,
+			ci->drivers.use_declarefetch,
+			ci->drivers.text_as_longvarchar,
+			ci->drivers.unknowns_as_longvarchar,
+			ci->drivers.bools_as_char,
+			ci->drivers.parse,
+			ci->drivers.cancel_as_freestmt,
+			ci->drivers.extra_systable_prefixes);
+}
+
 
 void
 getDSNdefaults(ConnInfo *ci)
@@ -449,6 +617,7 @@ getDSNinfo(ConnInfo *ci, char overwrite)
  *	If a driver keyword was present, then dont use a DSN and return.
  *	If DSN is null and no driver, then use the default datasource.
  */
+	memcpy(&ci->drivers, &globals, sizeof(globals));
 	if (DSN[0] == '\0')
 	{
 		if (ci->driver[0] != '\0')
@@ -512,7 +681,8 @@ getDSNinfo(ConnInfo *ci, char overwrite)
 		SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI);
 
 	/* Allow override of odbcinst.ini parameters here */
-	getGlobalDefaults(DSN, ODBC_INI, TRUE);
+	/* getGlobalDefaults(DSN, ODBC_INI, TRUE); */
+	getCommonDefaults(DSN, ODBC_INI, ci);
 
 	qlog("DSN info: DSN='%s',server='%s',port='%s',dbase='%s',user='%s',passwd='%s'\n",
 		 DSN,
@@ -546,9 +716,9 @@ getDSNinfo(ConnInfo *ci, char overwrite)
 
 /*	This is for datasource based options only */
 void
-writeDSNinfo(ConnInfo *ci)
+writeDSNinfo(const ConnInfo *ci)
 {
-	char	   *DSN = ci->dsn;
+	const char   *DSN = ci->dsn;
 	char		encoded_conn_settings[LARGE_REGISTRY_LEN];
 
 	encode(ci->conn_settings, encoded_conn_settings);
@@ -625,152 +795,159 @@ writeDSNinfo(ConnInfo *ci)
  *	the registry and gets any driver defaults.
  */
 void
-getGlobalDefaults(char *section, char *filename, char override)
+getCommonDefaults(const char *section, const char *filename, ConnInfo *ci)
 {
 	char		temp[256];
+	GLOBAL_VALUES	*comval;
 
+	if (ci)
+		comval = &(ci->drivers);
+	else
+		comval = &globals;
 	/* Fetch Count is stored in driver section */
 	SQLGetPrivateProfileString(section, INI_FETCH, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
 	{
-		globals.fetch_max = atoi(temp);
+		comval->fetch_max = atoi(temp);
 		/* sanity check if using cursors */
-		if (globals.fetch_max <= 0)
-			globals.fetch_max = FETCH_MAX;
+		if (comval->fetch_max <= 0)
+			comval->fetch_max = FETCH_MAX;
 	}
-	else if (!override)
-		globals.fetch_max = FETCH_MAX;
+	else if (!ci)
+		comval->fetch_max = FETCH_MAX;
 
 	/* Socket Buffersize is stored in driver section */
 	SQLGetPrivateProfileString(section, INI_SOCKET, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.socket_buffersize = atoi(temp);
-	else if (!override)
-		globals.socket_buffersize = SOCK_BUFFER_SIZE;
+		comval->socket_buffersize = atoi(temp);
+	else if (!ci)
+		comval->socket_buffersize = SOCK_BUFFER_SIZE;
 
 	/* Debug is stored in the driver section */
 	SQLGetPrivateProfileString(section, INI_DEBUG, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.debug = atoi(temp);
-	else if (!override)
-		globals.debug = DEFAULT_DEBUG;
+		comval->debug = atoi(temp);
+	else if (!ci)
+		comval->debug = DEFAULT_DEBUG;
 
 	/* CommLog is stored in the driver section */
 	SQLGetPrivateProfileString(section, INI_COMMLOG, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.commlog = atoi(temp);
-	else if (!override)
-		globals.commlog = DEFAULT_COMMLOG;
+		comval->commlog = atoi(temp);
+	else if (!ci)
+		comval->commlog = DEFAULT_COMMLOG;
 
+	if (!ci)
+		logs_on_off(0, 0, 0);
 	/* Optimizer is stored in the driver section only */
 	SQLGetPrivateProfileString(section, INI_OPTIMIZER, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.disable_optimizer = atoi(temp);
-	else if (!override)
-		globals.disable_optimizer = DEFAULT_OPTIMIZER;
+		comval->disable_optimizer = atoi(temp);
+	else if (!ci)
+		comval->disable_optimizer = DEFAULT_OPTIMIZER;
 
 	/* KSQO is stored in the driver section only */
 	SQLGetPrivateProfileString(section, INI_KSQO, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.ksqo = atoi(temp);
-	else if (!override)
-		globals.ksqo = DEFAULT_KSQO;
+		comval->ksqo = atoi(temp);
+	else if (!ci)
+		comval->ksqo = DEFAULT_KSQO;
 
 	/* Recognize Unique Index is stored in the driver section only */
 	SQLGetPrivateProfileString(section, INI_UNIQUEINDEX, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.unique_index = atoi(temp);
-	else if (!override)
-		globals.unique_index = DEFAULT_UNIQUEINDEX;
+		comval->unique_index = atoi(temp);
+	else if (!ci)
+		comval->unique_index = DEFAULT_UNIQUEINDEX;
 
 
 	/* Unknown Sizes is stored in the driver section only */
 	SQLGetPrivateProfileString(section, INI_UNKNOWNSIZES, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.unknown_sizes = atoi(temp);
-	else if (!override)
-		globals.unknown_sizes = DEFAULT_UNKNOWNSIZES;
+		comval->unknown_sizes = atoi(temp);
+	else if (!ci)
+		comval->unknown_sizes = DEFAULT_UNKNOWNSIZES;
 
 
 	/* Lie about supported functions? */
 	SQLGetPrivateProfileString(section, INI_LIE, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.lie = atoi(temp);
-	else if (!override)
-		globals.lie = DEFAULT_LIE;
+		comval->lie = atoi(temp);
+	else if (!ci)
+		comval->lie = DEFAULT_LIE;
 
 	/* Parse statements */
 	SQLGetPrivateProfileString(section, INI_PARSE, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.parse = atoi(temp);
-	else if (!override)
-		globals.parse = DEFAULT_PARSE;
+		comval->parse = atoi(temp);
+	else if (!ci)
+		comval->parse = DEFAULT_PARSE;
 
 	/* SQLCancel calls SQLFreeStmt in Driver Manager */
 	SQLGetPrivateProfileString(section, INI_CANCELASFREESTMT, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.cancel_as_freestmt = atoi(temp);
-	else if (!override)
-		globals.cancel_as_freestmt = DEFAULT_CANCELASFREESTMT;
+		comval->cancel_as_freestmt = atoi(temp);
+	else if (!ci)
+		comval->cancel_as_freestmt = DEFAULT_CANCELASFREESTMT;
 
 	/* UseDeclareFetch is stored in the driver section only */
 	SQLGetPrivateProfileString(section, INI_USEDECLAREFETCH, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.use_declarefetch = atoi(temp);
-	else if (!override)
-		globals.use_declarefetch = DEFAULT_USEDECLAREFETCH;
+		comval->use_declarefetch = atoi(temp);
+	else if (!ci)
+		comval->use_declarefetch = DEFAULT_USEDECLAREFETCH;
 
 	/* Max Varchar Size */
 	SQLGetPrivateProfileString(section, INI_MAXVARCHARSIZE, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.max_varchar_size = atoi(temp);
-	else if (!override)
-		globals.max_varchar_size = MAX_VARCHAR_SIZE;
+		comval->max_varchar_size = atoi(temp);
+	else if (!ci)
+		comval->max_varchar_size = MAX_VARCHAR_SIZE;
 
 	/* Max TextField Size */
 	SQLGetPrivateProfileString(section, INI_MAXLONGVARCHARSIZE, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.max_longvarchar_size = atoi(temp);
-	else if (!override)
-		globals.max_longvarchar_size = TEXT_FIELD_SIZE;
+		comval->max_longvarchar_size = atoi(temp);
+	else if (!ci)
+		comval->max_longvarchar_size = TEXT_FIELD_SIZE;
 
 	/* Text As LongVarchar	*/
 	SQLGetPrivateProfileString(section, INI_TEXTASLONGVARCHAR, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.text_as_longvarchar = atoi(temp);
-	else if (!override)
-		globals.text_as_longvarchar = DEFAULT_TEXTASLONGVARCHAR;
+		comval->text_as_longvarchar = atoi(temp);
+	else if (!ci)
+		comval->text_as_longvarchar = DEFAULT_TEXTASLONGVARCHAR;
 
 	/* Unknowns As LongVarchar	*/
 	SQLGetPrivateProfileString(section, INI_UNKNOWNSASLONGVARCHAR, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.unknowns_as_longvarchar = atoi(temp);
-	else if (!override)
-		globals.unknowns_as_longvarchar = DEFAULT_UNKNOWNSASLONGVARCHAR;
+		comval->unknowns_as_longvarchar = atoi(temp);
+	else if (!ci)
+		comval->unknowns_as_longvarchar = DEFAULT_UNKNOWNSASLONGVARCHAR;
 
 	/* Bools As Char */
 	SQLGetPrivateProfileString(section, INI_BOOLSASCHAR, "",
 							   temp, sizeof(temp), filename);
 	if (temp[0])
-		globals.bools_as_char = atoi(temp);
-	else if (!override)
-		globals.bools_as_char = DEFAULT_BOOLSASCHAR;
+		comval->bools_as_char = atoi(temp);
+	else if (!ci)
+		comval->bools_as_char = DEFAULT_BOOLSASCHAR;
 
 	/* Extra Systable prefixes */
 
@@ -781,15 +958,15 @@ getGlobalDefaults(char *section, char *filename, char override)
 	SQLGetPrivateProfileString(section, INI_EXTRASYSTABLEPREFIXES, "@@@",
 							   temp, sizeof(temp), filename);
 	if (strcmp(temp, "@@@"))
-		strcpy(globals.extra_systable_prefixes, temp);
-	else if (!override)
-		strcpy(globals.extra_systable_prefixes, DEFAULT_EXTRASYSTABLEPREFIXES);
+		strcpy(comval->extra_systable_prefixes, temp);
+	else if (!ci)
+		strcpy(comval->extra_systable_prefixes, DEFAULT_EXTRASYSTABLEPREFIXES);
 
-	mylog("globals.extra_systable_prefixes = '%s'\n", globals.extra_systable_prefixes);
+	mylog("globals.extra_systable_prefixes = '%s'\n", comval->extra_systable_prefixes);
 
 
 	/* Dont allow override of an override! */
-	if (!override)
+	if (!ci)
 	{
 
 		/*
@@ -797,15 +974,15 @@ getGlobalDefaults(char *section, char *filename, char override)
 		 * for override
 		 */
 		SQLGetPrivateProfileString(section, INI_CONNSETTINGS, "",
-		 globals.conn_settings, sizeof(globals.conn_settings), filename);
+			comval->conn_settings, sizeof(comval->conn_settings), filename);
 
 		/* Default state for future DSN's Readonly attribute */
 		SQLGetPrivateProfileString(section, INI_READONLY, "",
 								   temp, sizeof(temp), filename);
 		if (temp[0])
-			globals.onlyread = atoi(temp);
+			comval->onlyread = atoi(temp);
 		else
-			globals.onlyread = DEFAULT_READONLY;
+			comval->onlyread = DEFAULT_READONLY;
 
 		/*
 		 * Default state for future DSN's protocol attribute This isn't a
@@ -815,85 +992,113 @@ getGlobalDefaults(char *section, char *filename, char override)
 		SQLGetPrivateProfileString(section, INI_PROTOCOL, "@@@",
 								   temp, sizeof(temp), filename);
 		if (strcmp(temp, "@@@"))
-			strcpy(globals.protocol, temp);
+			strcpy(comval->protocol, temp);
 		else
-			strcpy(globals.protocol, DEFAULT_PROTOCOL);
+			strcpy(comval->protocol, DEFAULT_PROTOCOL);
 	}
 }
 
-
 /*
  *	This function writes any global parameters (that can be manipulated)
  *	to the ODBCINST.INI portion of the registry
  */
-void
-updateGlobals(void)
+static void
+updateCommons(const ConnInfo *ci)
 {
+	const	char		*sectionName;
+	const	char		*fileName;
+	const	GLOBAL_VALUES	*comval;
 	char		tmp[128];
 
-	sprintf(tmp, "%d", globals.fetch_max);
-	SQLWritePrivateProfileString(DBMS_NAME,
-								 INI_FETCH, tmp, ODBCINST_INI);
+	if (ci)
+		if (ci->dsn && ci->dsn[0])
+		{
+			mylog("DSN=%s updating\n", ci->dsn);
+			comval = &(ci->drivers);
+			sectionName = ci->dsn;
+			fileName = ODBC_INI;
+		}
+		else
+		{
+			mylog("ci but dsn==NULL\n");
+			return;
+		} 
+	else
+	{
+		mylog("drivers updating\n");
+		comval = &globals;
+		sectionName = DBMS_NAME;
+		fileName = ODBCINST_INI;
+	}
+	sprintf(tmp, "%d", comval->fetch_max);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_FETCH, tmp, fileName);
+
+	sprintf(tmp, "%d", comval->commlog);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_COMMLOG, tmp, fileName);
 
-	sprintf(tmp, "%d", globals.commlog);
-	SQLWritePrivateProfileString(DBMS_NAME,
-								 INI_COMMLOG, tmp, ODBCINST_INI);
+	sprintf(tmp, "%d", comval->debug);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_DEBUG, tmp, fileName);
 
-	sprintf(tmp, "%d", globals.disable_optimizer);
-	SQLWritePrivateProfileString(DBMS_NAME,
-								 INI_OPTIMIZER, tmp, ODBCINST_INI);
+	sprintf(tmp, "%d", comval->disable_optimizer);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_OPTIMIZER, tmp, fileName);
 
-	sprintf(tmp, "%d", globals.ksqo);
-	SQLWritePrivateProfileString(DBMS_NAME,
-								 INI_KSQO, tmp, ODBCINST_INI);
+	sprintf(tmp, "%d", comval->ksqo);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_KSQO, tmp, fileName);
 
-	sprintf(tmp, "%d", globals.unique_index);
-	SQLWritePrivateProfileString(DBMS_NAME,
-								 INI_UNIQUEINDEX, tmp, ODBCINST_INI);
+	/* Never update the onlyread, unique_index from this module 
+	sprintf(tmp, "%d", comval->unique_index);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_UNIQUEINDEX, tmp, fileName);
 
-	sprintf(tmp, "%d", globals.onlyread);
-	SQLWritePrivateProfileString(DBMS_NAME,
-								 INI_READONLY, tmp, ODBCINST_INI);
+	sprintf(tmp, "%d", comval->onlyread);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_READONLY, tmp, fileName);*/
 
-	sprintf(tmp, "%d", globals.use_declarefetch);
-	SQLWritePrivateProfileString(DBMS_NAME,
-								 INI_USEDECLAREFETCH, tmp, ODBCINST_INI);
+	sprintf(tmp, "%d", comval->use_declarefetch);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_USEDECLAREFETCH, tmp, fileName);
 
-	sprintf(tmp, "%d", globals.unknown_sizes);
-	SQLWritePrivateProfileString(DBMS_NAME,
-								 INI_UNKNOWNSIZES, tmp, ODBCINST_INI);
+	sprintf(tmp, "%d", comval->unknown_sizes);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_UNKNOWNSIZES, tmp, fileName);
 
-	sprintf(tmp, "%d", globals.text_as_longvarchar);
-	SQLWritePrivateProfileString(DBMS_NAME,
-							   INI_TEXTASLONGVARCHAR, tmp, ODBCINST_INI);
+	sprintf(tmp, "%d", comval->text_as_longvarchar);
+	SQLWritePrivateProfileString(sectionName,
+							   INI_TEXTASLONGVARCHAR, tmp, fileName);
 
-	sprintf(tmp, "%d", globals.unknowns_as_longvarchar);
-	SQLWritePrivateProfileString(DBMS_NAME,
-						   INI_UNKNOWNSASLONGVARCHAR, tmp, ODBCINST_INI);
+	sprintf(tmp, "%d", comval->unknowns_as_longvarchar);
+	SQLWritePrivateProfileString(sectionName,
+						   INI_UNKNOWNSASLONGVARCHAR, tmp, fileName);
 
-	sprintf(tmp, "%d", globals.bools_as_char);
-	SQLWritePrivateProfileString(DBMS_NAME,
-								 INI_BOOLSASCHAR, tmp, ODBCINST_INI);
+	sprintf(tmp, "%d", comval->bools_as_char);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_BOOLSASCHAR, tmp, fileName);
 
-	sprintf(tmp, "%d", globals.parse);
-	SQLWritePrivateProfileString(DBMS_NAME,
-								 INI_PARSE, tmp, ODBCINST_INI);
+	sprintf(tmp, "%d", comval->parse);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_PARSE, tmp, fileName);
 
-	sprintf(tmp, "%d", globals.cancel_as_freestmt);
-	SQLWritePrivateProfileString(DBMS_NAME,
-								 INI_CANCELASFREESTMT, tmp, ODBCINST_INI);
+	sprintf(tmp, "%d", comval->cancel_as_freestmt);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_CANCELASFREESTMT, tmp, fileName);
 
-	sprintf(tmp, "%d", globals.max_varchar_size);
-	SQLWritePrivateProfileString(DBMS_NAME,
-								 INI_MAXVARCHARSIZE, tmp, ODBCINST_INI);
+	sprintf(tmp, "%d", comval->max_varchar_size);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_MAXVARCHARSIZE, tmp, fileName);
 
-	sprintf(tmp, "%d", globals.max_longvarchar_size);
-	SQLWritePrivateProfileString(DBMS_NAME,
-							  INI_MAXLONGVARCHARSIZE, tmp, ODBCINST_INI);
+	sprintf(tmp, "%d", comval->max_longvarchar_size);
+	SQLWritePrivateProfileString(sectionName,
+							  INI_MAXLONGVARCHARSIZE, tmp, fileName);
 
-	SQLWritePrivateProfileString(DBMS_NAME,
-								 INI_EXTRASYSTABLEPREFIXES, globals.extra_systable_prefixes, ODBCINST_INI);
+	SQLWritePrivateProfileString(sectionName,
+								 INI_EXTRASYSTABLEPREFIXES, comval->extra_systable_prefixes, fileName);
 
-	SQLWritePrivateProfileString(DBMS_NAME,
-				  INI_CONNSETTINGS, globals.conn_settings, ODBCINST_INI);
+	/* Never update the conn_setting from this module 
+	SQLWritePrivateProfileString(sectionName,
+				  INI_CONNSETTINGS, comval->conn_settings, fileName); */
 }
diff --git a/src/interfaces/odbc/dlg_specific.h b/src/interfaces/odbc/dlg_specific.h
index 67f99449754..6d9885434f5 100644
--- a/src/interfaces/odbc/dlg_specific.h
+++ b/src/interfaces/odbc/dlg_specific.h
@@ -126,10 +126,10 @@
 #define DEFAULT_EXTRASYSTABLEPREFIXES	"dd_;"
 
 /*	prototypes */
-void		getGlobalDefaults(char *section, char *filename, char override);
+void		getCommonDefaults(const char *section, const char *filename, ConnInfo *ci);
 
 #ifdef WIN32
-void		SetDlgStuff(HWND hdlg, ConnInfo *ci);
+void		SetDlgStuff(HWND hdlg, const ConnInfo *ci);
 void		GetDlgStuff(HWND hdlg, ConnInfo *ci);
 
 int CALLBACK driver_optionsProc(HWND hdlg,
@@ -144,11 +144,12 @@ int CALLBACK ds_optionsProc(HWND hdlg,
 #endif	 /* WIN32 */
 
 void		updateGlobals(void);
-void		writeDSNinfo(ConnInfo *ci);
+void		writeDSNinfo(const ConnInfo *ci);
 void		getDSNdefaults(ConnInfo *ci);
 void		getDSNinfo(ConnInfo *ci, char overwrite);
-void		makeConnectString(char *connect_string, ConnInfo *ci);
-void		copyAttributes(ConnInfo *ci, char *attribute, char *value);
+void		makeConnectString(char *connect_string, const ConnInfo *ci, UWORD);
+void		copyAttributes(ConnInfo *ci, const char *attribute, const char *value);
+void		copyCommonAttributes(ConnInfo *ci, const char *attribute, const char *value);
 
 
 #endif
diff --git a/src/interfaces/odbc/drvconn.c b/src/interfaces/odbc/drvconn.c
index e224cbda5e7..e1eee25de55 100644
--- a/src/interfaces/odbc/drvconn.c
+++ b/src/interfaces/odbc/drvconn.c
@@ -51,7 +51,8 @@
 #include "dlg_specific.h"
 
 /* prototypes */
-void		dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci);
+void		dconn_get_connect_attributes(const UCHAR FAR *connect_string, ConnInfo *ci);
+static void	dconn_get_common_attributes(const UCHAR FAR *connect_string, ConnInfo *ci);
 
 #ifdef WIN32
 BOOL FAR PASCAL dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
@@ -61,8 +62,6 @@ extern HINSTANCE NEAR s_hModule;/* Saved module handle. */
 
 #endif
 
-extern GLOBAL_VALUES globals;
-
 
 RETCODE SQL_API
 PGAPI_DriverConnect(
@@ -115,6 +114,8 @@ PGAPI_DriverConnect(
 	 * given -- if not, it does nothing!)
 	 */
 	getDSNinfo(ci, CONN_DONT_OVERWRITE);
+	dconn_get_common_attributes(connStrIn, ci);
+	logs_on_off(1, ci->drivers.debug, ci->drivers.commlog);
 
 	/* Fill in any default parameters if they are not there. */
 	getDSNdefaults(ci);
@@ -210,7 +211,7 @@ dialog:
 	 */
 	result = SQL_SUCCESS;
 
-	makeConnectString(connStrOut, ci);
+	makeConnectString(connStrOut, ci, cbConnStrOutMax);
 	len = strlen(connStrOut);
 
 	if (szConnStrOut)
@@ -238,7 +239,7 @@ dialog:
 	if (pcbConnStrOut)
 		*pcbConnStrOut = len;
 
-	mylog("szConnStrOut = '%s'\n", szConnStrOut);
+	mylog("szConnStrOut = '%s' len=%d,%d\n", szConnStrOut, len, cbConnStrOutMax);
 	qlog("conn=%u, PGAPI_DriverConnect(out)='%s'\n", conn, szConnStrOut);
 
 
@@ -323,8 +324,9 @@ dconn_FDriverConnectProc(
 					return TRUE;
 
 				case IDC_DRIVER:
+					ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
 					DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
-								hdlg, driver_optionsProc, (LPARAM) NULL);
+								hdlg, driver_optionsProc, (LPARAM) ci);
 					break;
 
 				case IDC_DATASOURCE:
@@ -342,7 +344,7 @@ dconn_FDriverConnectProc(
 
 
 void
-dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
+dconn_get_connect_attributes(const UCHAR FAR *connect_string, ConnInfo *ci)
 {
 	char	   *our_connect_string;
 	char	   *pair,
@@ -386,3 +388,47 @@ dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
 
 	free(our_connect_string);
 }
+
+static void
+dconn_get_common_attributes(const UCHAR FAR *connect_string, ConnInfo *ci)
+{
+	char	   *our_connect_string;
+	char	   *pair,
+			   *attribute,
+			   *value,
+			   *equals;
+	char	   *strtok_arg;
+
+	our_connect_string = strdup(connect_string);
+	strtok_arg = our_connect_string;
+
+	mylog("our_connect_string = '%s'\n", our_connect_string);
+
+	while (1)
+	{
+		pair = strtok(strtok_arg, ";");
+		if (strtok_arg)
+			strtok_arg = 0;
+		if (!pair)
+			break;
+
+		equals = strchr(pair, '=');
+		if (!equals)
+			continue;
+
+		*equals = '\0';
+		attribute = pair;		/* ex. DSN */
+		value = equals + 1;		/* ex. 'CEO co1' */
+
+		mylog("attribute = '%s', value = '%s'\n", attribute, value);
+
+		if (!attribute || !value)
+			continue;
+
+		/* Copy the appropriate value to the conninfo  */
+		copyCommonAttributes(ci, attribute, value);
+
+	}
+
+	free(our_connect_string);
+}
diff --git a/src/interfaces/odbc/environ.c b/src/interfaces/odbc/environ.c
index d21c0540cac..8e9156d2d0c 100644
--- a/src/interfaces/odbc/environ.c
+++ b/src/interfaces/odbc/environ.c
@@ -43,7 +43,7 @@ PGAPI_AllocEnv(HENV FAR *phenv)
 	 * should work.
 	 */
 	if (globals.socket_buffersize <= 0)
-		getGlobalDefaults(DBMS_NAME, ODBCINST_INI, FALSE);
+		getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);
 
 	*phenv = (HENV) EN_Constructor();
 	if (!*phenv)
diff --git a/src/interfaces/odbc/execute.c b/src/interfaces/odbc/execute.c
index 374d700193d..bd2600bd4fe 100644
--- a/src/interfaces/odbc/execute.c
+++ b/src/interfaces/odbc/execute.c
@@ -34,7 +34,7 @@
 #include "lobj.h"
 #include "pgapifunc.h"
 
-extern GLOBAL_VALUES globals;
+/*extern GLOBAL_VALUES globals;*/
 
 
 /*		Perform a Prepare on the SQL statement */
@@ -340,7 +340,32 @@ PGAPI_Execute(
 		return retval;
 
 	mylog("   stmt_with_params = '%s'\n", stmt->stmt_with_params);
-
+#ifdef PREPARE_TRIAL
+	if (stmt->inaccurate_result)
+		if (SC_is_pre_executable(stmt))
+		{
+			BOOL	in_trans = CC_is_in_trans(conn);
+			QResultClass	*res;
+			CC_set_in_trans(conn);
+			stmt->result = res = CC_send_query(conn, stmt->stmt_with_params, NULL);
+			if (res && QR_aborted(res))
+			{
+				CC_abort(conn);
+				stmt->errornumber = STMT_EXEC_ERROR;
+				stmt->errormsg = "Handle prepare error";
+				return SQL_ERROR;
+			}
+			else
+			{
+				if (!in_trans)
+					CC_set_no_trans(conn);
+				stmt->status =STMT_FINISHED;
+				return SQL_SUCCESS;
+			}
+		}
+		else
+			return SQL_SUCCESS;
+#endif	/* PREPARE_TRIAL */
 	return SC_execute(stmt);
 }
 
@@ -437,6 +462,7 @@ PGAPI_Cancel(
 #ifdef WIN32
 	HMODULE		hmodule;
 	FARPROC		addr;
+	ConnInfo *ci;
 
 #endif
 
@@ -448,6 +474,7 @@ PGAPI_Cancel(
 		SC_log_error(func, "", NULL);
 		return SQL_INVALID_HANDLE;
 	}
+	ci = &(SC_get_conn(stmt)->connInfo);
 
 	/*
 	 * Not in the middle of SQLParamData/SQLPutData so cancel like a
@@ -466,7 +493,7 @@ PGAPI_Cancel(
 		 */
 
 #ifdef WIN32
-		if (globals.cancel_as_freestmt)
+		if (ci->drivers.cancel_as_freestmt)
 		{
 			hmodule = GetModuleHandle("ODBC32");
 			addr = GetProcAddress(hmodule, "SQLFreeStmt");
@@ -569,6 +596,7 @@ PGAPI_ParamData(
 	StatementClass *stmt = (StatementClass *) hstmt;
 	int			i,
 				retval;
+	ConnInfo *ci;
 
 	mylog("%s: entering...\n", func);
 
@@ -577,6 +605,7 @@ PGAPI_ParamData(
 		SC_log_error(func, "", NULL);
 		return SQL_INVALID_HANDLE;
 	}
+	ci = &(SC_get_conn(stmt)->connInfo);
 
 	mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, stmt->data_at_exec, stmt->parameters_allocated);
 
@@ -602,7 +631,7 @@ PGAPI_ParamData(
 		lo_close(stmt->hdbc, stmt->lobj_fd);
 
 		/* commit transaction if needed */
-		if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc))
+		if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(stmt->hdbc))
 		{
 			QResultClass *res;
 			char		ok;
diff --git a/src/interfaces/odbc/info.c b/src/interfaces/odbc/info.c
index 1bc96ac888c..2f5d4c88d03 100644
--- a/src/interfaces/odbc/info.c
+++ b/src/interfaces/odbc/info.c
@@ -54,7 +54,7 @@
 #define TRIGGER_UPDATE 0x02
 
 
-extern GLOBAL_VALUES globals;
+/* extern GLOBAL_VALUES globals; */
 
 
 
@@ -83,7 +83,7 @@ PGAPI_GetInfo(
 		return SQL_INVALID_HANDLE;
 	}
 
-	ci = &conn->connInfo;
+	ci = &(conn->connInfo);
 
 	switch (fInfoType)
 	{
@@ -113,7 +113,7 @@ PGAPI_GetInfo(
 		case SQL_BOOKMARK_PERSISTENCE:	/* ODBC 2.0 */
 			/* very simple bookmark support */
 			len = 4;
-			value = globals.use_declarefetch ? 0 : (SQL_BP_SCROLL);
+			value = ci->drivers.use_declarefetch ? 0 : (SQL_BP_SCROLL);
 			break;
 
 		case SQL_COLUMN_ALIAS:	/* ODBC 2.0 */
@@ -167,7 +167,7 @@ PGAPI_GetInfo(
 			len = 2;
 			value = SQL_CB_CLOSE;
 #ifdef	DRIVER_CURSOR_IMPLEMENT
-			if (!globals.use_declarefetch)
+			if (!ci->drivers.use_declarefetch)
 				value = SQL_CB_PRESERVE;
 #endif /* DRIVER_CURSOR_IMPLEMENT */
 			break;
@@ -176,7 +176,7 @@ PGAPI_GetInfo(
 			len = 2;
 			value = SQL_CB_CLOSE;
 #ifdef	DRIVER_CURSOR_IMPLEMENT
-			if (!globals.use_declarefetch)
+			if (!ci->drivers.use_declarefetch)
 				value = SQL_CB_PRESERVE;
 #endif /* DRIVER_CURSOR_IMPLEMENT */
 			break;
@@ -261,7 +261,7 @@ PGAPI_GetInfo(
 
 		case SQL_FETCH_DIRECTION:		/* ODBC 1.0 */
 			len = 4;
-			value = globals.use_declarefetch ? (SQL_FD_FETCH_NEXT) : (SQL_FD_FETCH_NEXT |
+			value = ci->drivers.use_declarefetch ? (SQL_FD_FETCH_NEXT) : (SQL_FD_FETCH_NEXT |
 													 SQL_FD_FETCH_FIRST |
 													  SQL_FD_FETCH_LAST |
 													 SQL_FD_FETCH_PRIOR |
@@ -315,7 +315,7 @@ PGAPI_GetInfo(
 
 		case SQL_LOCK_TYPES:	/* ODBC 2.0 */
 			len = 4;
-			value = globals.lie ? (SQL_LCK_NO_CHANGE | SQL_LCK_EXCLUSIVE | SQL_LCK_UNLOCK) : SQL_LCK_NO_CHANGE;
+			value = ci->drivers.lie ? (SQL_LCK_NO_CHANGE | SQL_LCK_EXCLUSIVE | SQL_LCK_UNLOCK) : SQL_LCK_NO_CHANGE;
 			break;
 
 		case SQL_MAX_BINARY_LITERAL_LEN:		/* ODBC 2.0 */
@@ -523,12 +523,12 @@ PGAPI_GetInfo(
 
 		case SQL_POS_OPERATIONS:		/* ODBC 2.0 */
 			len = 4;
-			value = globals.lie ? (SQL_POS_POSITION | SQL_POS_REFRESH | SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD) : (SQL_POS_POSITION | SQL_POS_REFRESH);
+			value = ci->drivers.lie ? (SQL_POS_POSITION | SQL_POS_REFRESH | SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD) : (SQL_POS_POSITION | SQL_POS_REFRESH);
 			break;
 
 		case SQL_POSITIONED_STATEMENTS: /* ODBC 2.0 */
 			len = 4;
-			value = globals.lie ? (SQL_PS_POSITIONED_DELETE |
+			value = ci->drivers.lie ? (SQL_PS_POSITIONED_DELETE |
 								   SQL_PS_POSITIONED_UPDATE |
 								   SQL_PS_SELECT_FOR_UPDATE) : 0;
 			break;
@@ -571,12 +571,12 @@ PGAPI_GetInfo(
 			 * Driver doesn't support keyset-driven or mixed cursors, so
 			 * not much point in saying row updates are supported
 			 */
-			p = globals.lie ? "Y" : "N";
+			p = ci->drivers.lie ? "Y" : "N";
 			break;
 
 		case SQL_SCROLL_CONCURRENCY:	/* ODBC 1.0 */
 			len = 4;
-			value = globals.lie ? (SQL_SCCO_READ_ONLY |
+			value = ci->drivers.lie ? (SQL_SCCO_READ_ONLY |
 								   SQL_SCCO_LOCK |
 								   SQL_SCCO_OPT_ROWVER |
 							 SQL_SCCO_OPT_VALUES) : (SQL_SCCO_READ_ONLY);
@@ -584,11 +584,11 @@ PGAPI_GetInfo(
 
 		case SQL_SCROLL_OPTIONS:		/* ODBC 1.0 */
 			len = 4;
-			value = globals.lie ? (SQL_SO_FORWARD_ONLY |
+			value = ci->drivers.lie ? (SQL_SO_FORWARD_ONLY |
 								   SQL_SO_STATIC |
 								   SQL_SO_KEYSET_DRIVEN |
 								   SQL_SO_DYNAMIC |
-								   SQL_SO_MIXED) : (globals.use_declarefetch ? SQL_SO_FORWARD_ONLY : (SQL_SO_FORWARD_ONLY | SQL_SO_STATIC));
+								   SQL_SO_MIXED) : (ci->drivers.use_declarefetch ? SQL_SO_FORWARD_ONLY : (SQL_SO_FORWARD_ONLY | SQL_SO_STATIC));
 			break;
 
 		case SQL_SEARCH_PATTERN_ESCAPE: /* ODBC 1.0 */
@@ -605,7 +605,7 @@ PGAPI_GetInfo(
 
 		case SQL_STATIC_SENSITIVITY:	/* ODBC 2.0 */
 			len = 4;
-			value = globals.lie ? (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES) : 0;
+			value = ci->drivers.lie ? (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES) : 0;
 			break;
 
 		case SQL_STRING_FUNCTIONS:		/* ODBC 1.0 */
@@ -782,7 +782,7 @@ PGAPI_GetTypeInfo(
 
 	for (i = 0, sqlType = sqlTypes[0]; sqlType; sqlType = sqlTypes[++i])
 	{
-		pgType = sqltype_to_pgtype(sqlType);
+		pgType = sqltype_to_pgtype(stmt, sqlType);
 
 		if (fSqlType == SQL_ALL_TYPES || fSqlType == sqlType)
 		{
@@ -833,12 +833,13 @@ PGAPI_GetFunctions(
 				UWORD FAR *pfExists)
 {
 	static char *func = "PGAPI_GetFunctions";
+	ConnInfo *ci = &(((ConnectionClass *)hdbc)->connInfo);
 
 	mylog("%s: entering...%u\n", func, fFunction);
 
 	if (fFunction == SQL_API_ALL_FUNCTIONS)
 	{
-		if (globals.lie)
+		if (ci->drivers.lie)
 		{
 			int			i;
 
@@ -923,7 +924,7 @@ PGAPI_GetFunctions(
 	}
 	else
 	{
-		if (globals.lie)
+		if (ci->drivers.lie)
 			*pfExists = TRUE;
 		else
 		{
@@ -1156,8 +1157,8 @@ PGAPI_Tables(
 	stmt->manual_result = TRUE;
 	stmt->errormsg_created = TRUE;
 
-	conn = (ConnectionClass *) (stmt->hdbc);
-	ci = &stmt->hdbc->connInfo;
+	conn = SC_get_conn(stmt);
+	ci = &(conn->connInfo);
 
 	result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt);
 	if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
@@ -1188,7 +1189,7 @@ PGAPI_Tables(
 	my_strcat(tables_query, " and relname like '%.*s'", szTableName, cbTableName);
 
 	/* Parse the extra systable prefix	*/
-	strcpy(prefixes, globals.extra_systable_prefixes);
+	strcpy(prefixes, ci->drivers.extra_systable_prefixes);
 	i = 0;
 	prefix[i] = strtok(prefixes, ";");
 	while (prefix[i] && i < 32)
@@ -1477,8 +1478,8 @@ PGAPI_Columns(
 	stmt->manual_result = TRUE;
 	stmt->errormsg_created = TRUE;
 
-	conn = (ConnectionClass *) (stmt->hdbc);
-	ci = &stmt->hdbc->connInfo;
+	conn = SC_get_conn(stmt);
+	ci = &(conn->connInfo);
 
 	/*
 	 * Create the query to find out the columns (Note: pre 6.3 did not
@@ -1778,8 +1779,8 @@ PGAPI_Columns(
 			if (mod_length >= 4)
 				mod_length -= 4;/* the length is in atttypmod - 4 */
 
-			if (mod_length > globals.max_varchar_size || mod_length <= 0)
-				mod_length = globals.max_varchar_size;
+			if (mod_length > ci->drivers.max_varchar_size || mod_length <= 0)
+				mod_length = ci->drivers.max_varchar_size;
 
 			mylog("%s: field type is VARCHAR,BPCHAR: field_type = %d, mod_length = %d\n", func, field_type, mod_length);
 
@@ -1896,7 +1897,7 @@ PGAPI_SpecialColumns(
 		SC_log_error(func, "", NULL);
 		return SQL_INVALID_HANDLE;
 	}
-	ci = &stmt->hdbc->connInfo;
+	ci = &(SC_get_conn(stmt)->connInfo);
 
 	stmt->manual_result = TRUE;
 
@@ -2062,7 +2063,7 @@ PGAPI_Statistics(
 	stmt->manual_result = TRUE;
 	stmt->errormsg_created = TRUE;
 
-	ci = &stmt->hdbc->connInfo;
+	ci = &(SC_get_conn(stmt)->connInfo);
 
 	stmt->result = QR_Constructor();
 	if (!stmt->result)
@@ -2301,7 +2302,7 @@ PGAPI_Statistics(
 		set_tuplefield_string(&row->tuple[2], table_name);
 
 		/* non-unique index? */
-		set_tuplefield_int2(&row->tuple[3], (Int2) (globals.unique_index ? FALSE : TRUE));
+		set_tuplefield_int2(&row->tuple[3], (Int2) (ci->drivers.unique_index ? FALSE : TRUE));
 
 		/* no index qualifier */
 		set_tuplefield_string(&row->tuple[4], "");
@@ -2345,7 +2346,7 @@ PGAPI_Statistics(
 				set_tuplefield_string(&row->tuple[2], table_name);
 
 				/* non-unique index? */
-				if (globals.unique_index)
+				if (ci->drivers.unique_index)
 					set_tuplefield_int2(&row->tuple[3], (Int2) (atoi(isunique) ? FALSE : TRUE));
 				else
 					set_tuplefield_int2(&row->tuple[3], TRUE);
@@ -2556,7 +2557,7 @@ PGAPI_PrimaryKeys(
 		return SQL_ERROR;
 	}
 
-	conn = (ConnectionClass *) (stmt->hdbc);
+	conn = SC_get_conn(stmt);
 	if (PG_VERSION_LE(conn, 6.4))
 		qstart = 2;
 	else
diff --git a/src/interfaces/odbc/misc.c b/src/interfaces/odbc/misc.c
index 1bfb877cbf7..87a4ee01ff5 100644
--- a/src/interfaces/odbc/misc.c
+++ b/src/interfaces/odbc/misc.c
@@ -30,11 +30,11 @@
 #endif
 
 extern GLOBAL_VALUES globals;
-void		generate_filename(char *, char *, char *);
+void	generate_filename(const char *, const char *, char *);
 
 
 void
-generate_filename(char *dirname, char *prefix, char *filename)
+generate_filename(const char *dirname, const char *prefix, char *filename)
 {
 	int			pid = 0;
 
@@ -58,6 +58,33 @@ generate_filename(char *dirname, char *prefix, char *filename)
 	return;
 }
 
+static	int	mylog_on = 0, qlog_on = 0;
+void logs_on_off(int cnopen, int mylog_onoff, int qlog_onoff)
+{
+	static	int	mylog_on_count = 0, mylog_off_count = 0,
+			qlog_on_count = 0, qlog_off_count = 0;
+
+	if (mylog_onoff)
+		mylog_on_count += cnopen;
+	else 
+		mylog_off_count += cnopen;
+	if (mylog_on_count > 0)
+		mylog_on = 1;
+	else if (mylog_off_count > 0)
+		mylog_on = 0;
+	else
+		mylog_on = globals.debug;
+	if (qlog_onoff)
+		qlog_on_count += cnopen;
+	else 
+		qlog_off_count += cnopen;
+	if (qlog_on_count > 0)
+		qlog_on = 1;
+	else if (qlog_off_count > 0)
+		qlog_on = 0;
+	else
+		qlog_on = globals.commlog;
+}
 
 #ifdef MY_LOG
 void
@@ -65,9 +92,9 @@ mylog(char *fmt,...)
 {
 	va_list		args;
 	char		filebuf[80];
-	FILE	   *LOGFP = globals.mylogFP;
+	static FILE	*LOGFP = NULL;
 
-	if (globals.debug)
+	if (mylog_on)
 	{
 		va_start(args, fmt);
 
@@ -75,7 +102,6 @@ mylog(char *fmt,...)
 		{
 			generate_filename(MYLOGDIR, MYLOGFILE, filebuf);
 			LOGFP = fopen(filebuf, PG_BINARY_W);
-			globals.mylogFP = LOGFP;
 			setbuf(LOGFP, NULL);
 		}
 
@@ -95,9 +121,9 @@ qlog(char *fmt,...)
 {
 	va_list		args;
 	char		filebuf[80];
-	FILE	   *LOGFP = globals.qlogFP;
+	static FILE   *LOGFP = NULL;
 
-	if (globals.commlog)
+	if (qlog_on)
 	{
 		va_start(args, fmt);
 
@@ -105,7 +131,6 @@ qlog(char *fmt,...)
 		{
 			generate_filename(QLOGDIR, QLOGFILE, filebuf);
 			LOGFP = fopen(filebuf, PG_BINARY_W);
-			globals.qlogFP = LOGFP;
 			setbuf(LOGFP, NULL);
 		}
 
@@ -139,7 +164,7 @@ qlog(char *fmt,...)
  *	(not including null term)
  */
 int
-my_strcpy(char *dst, int dst_len, char *src, int src_len)
+my_strcpy(char *dst, int dst_len, const char *src, int src_len)
 {
 	if (dst_len <= 0)
 		return STRCPY_FAIL;
@@ -214,7 +239,7 @@ strncpy_null(char *dst, const char *src, int len)
  *------
  */
 char *
-make_string(char *s, int len, char *buf)
+make_string(const char *s, int len, char *buf)
 {
 	int			length;
 	char	   *str;
@@ -248,7 +273,7 @@ make_string(char *s, int len, char *buf)
  *	This routine could be modified to use vsprintf() to handle multiple arguments.
  */
 char *
-my_strcat(char *buf, char *fmt, char *s, int len)
+my_strcat(char *buf, const char *fmt, const char *s, int len)
 {
 	if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0)))
 	{
diff --git a/src/interfaces/odbc/misc.h b/src/interfaces/odbc/misc.h
index dc2ef0d5bea..016b4b7a5e9 100644
--- a/src/interfaces/odbc/misc.h
+++ b/src/interfaces/odbc/misc.h
@@ -89,8 +89,8 @@ extern void qlog(char *fmt,...);
 void		remove_newlines(char *string);
 char	   *strncpy_null(char *dst, const char *src, int len);
 char	   *trim(char *string);
-char	   *make_string(char *s, int len, char *buf);
-char	   *my_strcat(char *buf, char *fmt, char *s, int len);
+char	   *make_string(const char *s, int len, char *buf);
+char	   *my_strcat(char *buf, const char *fmt, const char *s, int len);
 
 /* defines for return value of my_strcpy */
 #define STRCPY_SUCCESS		1
@@ -98,6 +98,6 @@ char	   *my_strcat(char *buf, char *fmt, char *s, int len);
 #define STRCPY_TRUNCATED	(-1)
 #define STRCPY_NULL			(-2)
 
-int			my_strcpy(char *dst, int dst_len, char *src, int src_len);
+int			my_strcpy(char *dst, int dst_len, const char *src, int src_len);
 
 #endif
diff --git a/src/interfaces/odbc/multibyte.c b/src/interfaces/odbc/multibyte.c
index abc6b3d6eb4..fa81f4775f4 100644
--- a/src/interfaces/odbc/multibyte.c
+++ b/src/interfaces/odbc/multibyte.c
@@ -88,7 +88,7 @@ check_client_encoding(unsigned char *str)
 		multibyte_client_encoding = BIG5;
 		return ("BIG5");
 	}
-	return ("OHTER");
+	return ("OTHER");
 }
 
 
diff --git a/src/interfaces/odbc/odbcapi.c b/src/interfaces/odbc/odbcapi.c
index 60205c011b6..dbb3142401f 100644
--- a/src/interfaces/odbc/odbcapi.c
+++ b/src/interfaces/odbc/odbcapi.c
@@ -254,7 +254,7 @@ RETCODE  SQL_API SQLGetData(HSTMT StatementHandle,
 RETCODE  SQL_API SQLGetFunctions(HDBC ConnectionHandle,
            SQLUSMALLINT FunctionId, SQLUSMALLINT *Supported)
 {
-	mylog("[SQLGetFunctions");
+	mylog("[SQLGetFunctions]");
 #if (ODBCVER >= 0x3000)
 	if (FunctionId == SQL_API_ODBC3_ALL_FUNCTIONS)
 		return PGAPI_GetFunctions30(ConnectionHandle, FunctionId, Supported);
@@ -270,10 +270,12 @@ RETCODE  SQL_API SQLGetInfo(HDBC ConnectionHandle,
 	mylog("[SQLGetInfo(30)]");
 	if ((ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
            	BufferLength, StringLength)) == SQL_ERROR)
-		return PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue,
-           	BufferLength, StringLength);
-	else
-		return ret;
+	{
+		if (((ConnectionClass *) ConnectionHandle)->driver_version >= 0x3000)
+			return PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue,
+           			BufferLength, StringLength);
+	}
+	return ret;
 #else
 	mylog("[SQLGetInfo]");
 	return PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
diff --git a/src/interfaces/odbc/odbcapi30.c b/src/interfaces/odbc/odbcapi30.c
index cee57934df2..e657595c031 100644
--- a/src/interfaces/odbc/odbcapi30.c
+++ b/src/interfaces/odbc/odbcapi30.c
@@ -395,7 +395,7 @@ RETCODE  SQL_API SQLSetEnvAttr(HENV EnvironmentHandle,
 			/* *((unsigned int *) Value) = SQL_CP_RELAXED_MATCH; */
 			return SQL_SUCCESS;
 		case SQL_ATTR_ODBC_VERSION:
-			if ((SQLUINTEGER) Value == SQL_OV_ODBC3)
+			if ((SQLUINTEGER) Value == SQL_OV_ODBC2)
 				return SQL_SUCCESS;
 			break;
 		case SQL_ATTR_OUTPUT_NTS:
diff --git a/src/interfaces/odbc/options.c b/src/interfaces/odbc/options.c
index 77421b63ebd..aa18bb1615c 100644
--- a/src/interfaces/odbc/options.c
+++ b/src/interfaces/odbc/options.c
@@ -33,7 +33,6 @@
 #include "pgapifunc.h"
 
 
-extern GLOBAL_VALUES globals;
 
 RETCODE set_statement_option(ConnectionClass *conn,
 					 StatementClass *stmt,
@@ -49,7 +48,12 @@ set_statement_option(ConnectionClass *conn,
 {
 	static char *func = "set_statement_option";
 	char		changed = FALSE;
+	ConnInfo *ci = NULL;
 
+	if (conn)
+		ci = &(conn->connInfo);
+	else if (stmt)
+		ci = &(SC_get_conn(stmt)->connInfo);
 	switch (fOption)
 	{
 		case SQL_ASYNC_ENABLE:	/* ignored */
@@ -70,7 +74,7 @@ set_statement_option(ConnectionClass *conn,
 			 * read-only
 			 */
 			mylog("SetStmtOption(): SQL_CONCURRENCY = %d\n", vParam);
-			if (globals.lie || vParam == SQL_CONCUR_READ_ONLY || vParam == SQL_CONCUR_ROWVER)
+			if (ci->drivers.lie || vParam == SQL_CONCUR_READ_ONLY || vParam == SQL_CONCUR_ROWVER)
 			{
 				if (conn)
 			 		conn->stmtOptions.scroll_concurrency = vParam;
@@ -95,7 +99,7 @@ set_statement_option(ConnectionClass *conn,
 			 */
 			mylog("SetStmtOption(): SQL_CURSOR_TYPE = %d\n", vParam);
 
-			if (globals.lie)
+			if (ci->drivers.lie)
 			{
 				if (conn)
 					conn->stmtOptions.cursor_type = vParam;
@@ -104,7 +108,7 @@ set_statement_option(ConnectionClass *conn,
 			}
 			else
 			{
-				if (globals.use_declarefetch)
+				if (ci->drivers.use_declarefetch)
 				{
 					if (conn)
 						conn->stmtOptions.cursor_type = SQL_CURSOR_FORWARD_ONLY;
@@ -147,7 +151,7 @@ set_statement_option(ConnectionClass *conn,
 			break;
 
 			/*-------
-			 *	if (globals.lie)
+			 *	if (ci->drivers.lie)
 			 *		stmt->keyset_size = vParam;
 			 *	else
 			 *	{
@@ -433,6 +437,7 @@ PGAPI_GetConnectOption(
 {
 	static char *func = "PGAPI_GetConnectOption";
 	ConnectionClass *conn = (ConnectionClass *) hdbc;
+	ConnInfo *ci = &(conn->connInfo);
 
 	mylog("%s: entering...\n", func);
 
@@ -464,7 +469,7 @@ PGAPI_GetConnectOption(
 			break;
 
 		case SQL_PACKET_SIZE:	/* NOT SUPPORTED */
-			*((UDWORD *) pvParam) = globals.socket_buffersize;
+			*((UDWORD *) pvParam) = ci->drivers.socket_buffersize;
 			break;
 
 		case SQL_QUIET_MODE:	/* NOT SUPPORTED */
@@ -536,6 +541,7 @@ PGAPI_GetStmtOption(
 	static char *func = "PGAPI_GetStmtOption";
 	StatementClass *stmt = (StatementClass *) hstmt;
 	QResultClass *res;
+	ConnInfo *ci = &(SC_get_conn(stmt)->connInfo);
 
 	mylog("%s: entering...\n", func);
 
@@ -557,7 +563,7 @@ PGAPI_GetStmtOption(
 
 			res = stmt->result;
 
-			if (stmt->manual_result || !globals.use_declarefetch)
+			if (stmt->manual_result || !ci->drivers.use_declarefetch)
 			{
 				/* make sure we're positioned on a valid row */
 				if ((stmt->currTuple < 0) ||
diff --git a/src/interfaces/odbc/pgtypes.c b/src/interfaces/odbc/pgtypes.c
index fdc38d62a19..f2b18535901 100644
--- a/src/interfaces/odbc/pgtypes.c
+++ b/src/interfaces/odbc/pgtypes.c
@@ -34,7 +34,6 @@
 #endif
 
 
-extern GLOBAL_VALUES globals;
 
 Int4		getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
 
@@ -105,9 +104,10 @@ Int2		sqlTypes[] = {
 
 
 Int4
-sqltype_to_pgtype(SWORD fSqlType)
+sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
 {
 	Int4		pgType;
+	ConnInfo *ci = &(SC_get_conn(stmt)->connInfo);
 
 	switch (fSqlType)
 	{
@@ -120,7 +120,7 @@ sqltype_to_pgtype(SWORD fSqlType)
 			break;
 
 		case SQL_BIT:
-			pgType = globals.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL;
+			pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL;
 			break;
 
 		case SQL_DATE:
@@ -150,7 +150,7 @@ sqltype_to_pgtype(SWORD fSqlType)
 			break;
 
 		case SQL_LONGVARCHAR:
-			pgType = globals.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
+			pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
 			break;
 
 		case SQL_REAL:
@@ -202,6 +202,7 @@ sqltype_to_pgtype(SWORD fSqlType)
 Int2
 pgtype_to_sqltype(StatementClass *stmt, Int4 type)
 {
+	ConnInfo *ci = &(SC_get_conn(stmt)->connInfo);
 	switch (type)
 	{
 		case PG_TYPE_CHAR:
@@ -218,7 +219,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
 			return SQL_VARCHAR;
 
 		case PG_TYPE_TEXT:
-			return globals.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
+			return ci->drivers.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
 
 		case PG_TYPE_BYTEA:
 			return SQL_VARBINARY;
@@ -255,7 +256,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
 		case PG_TYPE_MONEY:
 			return SQL_FLOAT;
 		case PG_TYPE_BOOL:
-			return globals.bools_as_char ? SQL_CHAR : SQL_BIT;
+			return ci->drivers.bools_as_char ? SQL_CHAR : SQL_BIT;
 
 		default:
 
@@ -268,7 +269,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
 			if (type == stmt->hdbc->lobj_type)
 				return SQL_LONGVARBINARY;
 
-			return globals.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
+			return ci->drivers.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
 	}
 }
 
@@ -276,6 +277,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
 Int2
 pgtype_to_ctype(StatementClass *stmt, Int4 type)
 {
+	ConnInfo *ci = &(SC_get_conn(stmt)->connInfo);
 	switch (type)
 	{
 		case PG_TYPE_INT8:
@@ -303,7 +305,7 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
 		case PG_TYPE_MONEY:
 			return SQL_C_FLOAT;
 		case PG_TYPE_BOOL:
-			return globals.bools_as_char ? SQL_C_CHAR : SQL_C_BIT;
+			return ci->drivers.bools_as_char ? SQL_C_CHAR : SQL_C_BIT;
 
 		case PG_TYPE_BYTEA:
 			return SQL_C_BINARY;
@@ -470,6 +472,7 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
 				maxsize;
 	QResultClass *result;
 	ColumnInfoClass *flds;
+	ConnInfo *ci = &(SC_get_conn(stmt)->connInfo);
 
 	mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type, col, handle_unknown_size_as);
 
@@ -477,22 +480,22 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
 	switch (type)
 	{
 		case PG_TYPE_TEXT:
-			if (globals.text_as_longvarchar)
-				maxsize = globals.max_longvarchar_size;
+			if (ci->drivers.text_as_longvarchar)
+				maxsize = ci->drivers.max_longvarchar_size;
 			else
-				maxsize = globals.max_varchar_size;
+				maxsize = ci->drivers.max_varchar_size;
 			break;
 
 		case PG_TYPE_VARCHAR:
 		case PG_TYPE_BPCHAR:
-			maxsize = globals.max_varchar_size;
+			maxsize = ci->drivers.max_varchar_size;
 			break;
 
 		default:
-			if (globals.unknowns_as_longvarchar)
-				maxsize = globals.max_longvarchar_size;
+			if (ci->drivers.unknowns_as_longvarchar)
+				maxsize = ci->drivers.max_longvarchar_size;
 			else
-				maxsize = globals.max_varchar_size;
+				maxsize = ci->drivers.max_varchar_size;
 			break;
 	}
 
diff --git a/src/interfaces/odbc/pgtypes.h b/src/interfaces/odbc/pgtypes.h
index 03cc2babd16..7bd33cf7512 100644
--- a/src/interfaces/odbc/pgtypes.h
+++ b/src/interfaces/odbc/pgtypes.h
@@ -68,7 +68,7 @@ extern Int2 sqlTypes[];
 /*	Defines for pgtype_precision */
 #define PG_STATIC				(-1)
 
-Int4		sqltype_to_pgtype(Int2 fSqlType);
+Int4		sqltype_to_pgtype(StatementClass *stmt, Int2 fSqlType);
 
 Int2		pgtype_to_sqltype(StatementClass *stmt, Int4 type);
 Int2		pgtype_to_ctype(StatementClass *stmt, Int4 type);
diff --git a/src/interfaces/odbc/psqlodbc.c b/src/interfaces/odbc/psqlodbc.c
index 9851af2ee66..ad156379d0a 100644
--- a/src/interfaces/odbc/psqlodbc.c
+++ b/src/interfaces/odbc/psqlodbc.c
@@ -60,7 +60,7 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
 				return FALSE;
 			}
 
-			getGlobalDefaults(DBMS_NAME, ODBCINST_INI, FALSE);
+			getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);
 			break;
 
 		case DLL_THREAD_ATTACH:
@@ -99,7 +99,7 @@ static BOOL
 __attribute__((constructor))
 init(void)
 {
-	getGlobalDefaults(DBMS_NAME, ODBCINST_INI, FALSE);
+	getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);
 	return TRUE;
 }
 
@@ -112,7 +112,7 @@ init(void)
 BOOL
 _init(void)
 {
-	getGlobalDefaults(DBMS_NAME, ODBCINST_INI, FALSE);
+	getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);
 	return TRUE;
 }
 
diff --git a/src/interfaces/odbc/psqlodbc.h b/src/interfaces/odbc/psqlodbc.h
index 542fe7ff596..a6c5d9eda34 100644
--- a/src/interfaces/odbc/psqlodbc.h
+++ b/src/interfaces/odbc/psqlodbc.h
@@ -5,7 +5,7 @@
  *
  * Comments:		See "notice.txt" for copyright and license information.
  *
- * $Id: psqlodbc.h,v 1.46 2001/08/24 14:07:50 petere Exp $
+ * $Id: psqlodbc.h,v 1.47 2001/09/07 06:02:22 inoue Exp $
  *
  */
 
@@ -145,10 +145,6 @@ typedef struct GlobalValues_
 	char		extra_systable_prefixes[MEDIUM_REGISTRY_LEN];
 	char		conn_settings[LARGE_REGISTRY_LEN];
 	char		protocol[SMALL_REGISTRY_LEN];
-
-
-	FILE	   *mylogFP;
-	FILE	   *qlogFP;
 } GLOBAL_VALUES;
 
 typedef struct StatementOptions_
@@ -176,6 +172,7 @@ typedef struct QueryInfo_
 	char	   *cursor;
 } QueryInfo;
 
+void logs_on_off(int cnopen, int, int);
 
 #define PG_TYPE_LO					(-999)		/* hack until permanent
 												 * type available */
diff --git a/src/interfaces/odbc/psqlodbc.rc b/src/interfaces/odbc/psqlodbc.rc
index 85bfcdb2893..aa149ade938 100644
--- a/src/interfaces/odbc/psqlodbc.rc
+++ b/src/interfaces/odbc/psqlodbc.rc
@@ -83,7 +83,7 @@ BEGIN
                     DRV_MSG_LABEL,25,4,238,10
 END
 
-DLG_OPTIONS_DRV DIALOG DISCARDABLE  0, 0, 306, 213
+DLG_OPTIONS_DRV DIALOG DISCARDABLE  0, 0, 306, 226
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Advanced Options (Driver)"
 FONT 10, "Terminal"
@@ -104,34 +104,38 @@ BEGIN
                     BS_AUTOCHECKBOX | WS_TABSTOP,13,47,84,10
     CONTROL         "Cancel as FreeStmt (Exp)",DRV_CANCELASFREESTMT,"Button",
                     BS_AUTOCHECKBOX | WS_TABSTOP,164,50,112,10
-    GROUPBOX        "Unknown Sizes",IDC_STATIC,13,63,175,24
+    CONTROL         "Mylog(Debug ouput",DRV_DEBUG,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,164,63,112,10
+    GROUPBOX        "Unknown Sizes",IDC_STATIC,13,76,175,24
     CONTROL         "Maximum",DRV_UNKNOWN_MAX,"Button",BS_AUTORADIOBUTTON | 
-                    WS_GROUP | WS_TABSTOP,21,71,44,10
+                    WS_GROUP | WS_TABSTOP,21,84,44,10
     CONTROL         "Don't Know",DRV_UNKNOWN_DONTKNOW,"Button",
-                    BS_AUTORADIOBUTTON | WS_TABSTOP,72,71,56,10
+                    BS_AUTORADIOBUTTON | WS_TABSTOP,72,84,56,10
     CONTROL         "Longest",DRV_UNKNOWN_LONGEST,"Button",
-                    BS_AUTORADIOBUTTON | WS_TABSTOP,135,71,44,10
-    GROUPBOX        "Data Type Options",IDC_STATIC,13,91,282,23
+                    BS_AUTORADIOBUTTON | WS_TABSTOP,135,84,44,10
+    GROUPBOX        "Data Type Options",IDC_STATIC,13,104,282,23
     CONTROL         "Text as LongVarChar",DRV_TEXT_LONGVARCHAR,"Button",
-                    BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,102,92,10
+                    BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,115,92,10
     CONTROL         "Unknowns as LongVarChar",DRV_UNKNOWNS_LONGVARCHAR,
-                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,112,102,108,10
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,112,115,108,10
     CONTROL         "Bools as Char",DRV_BOOLS_CHAR,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,225,102,68,10
-    LTEXT           "&Cache Size:",IDC_STATIC,15,120,45,8
-    EDITTEXT        DRV_CACHE_SIZE,61,116,35,12,ES_AUTOHSCROLL
-    LTEXT           "Max &Varchar:",IDC_STATIC,99,120,49,8
-    EDITTEXT        DRV_VARCHAR_SIZE,149,116,35,12,ES_AUTOHSCROLL
-    LTEXT           "Max Lon&gVarChar:",IDC_STATIC,192,120,65,8
-    EDITTEXT        DRV_LONGVARCHAR_SIZE,259,116,35,12,ES_AUTOHSCROLL
-    LTEXT           "SysTable &Prefixes:",IDC_STATIC,23,131,36,20
-    EDITTEXT        DRV_EXTRASYSTABLEPREFIXES,61,137,75,12,ES_AUTOHSCROLL
-    LTEXT           "Connect &Settings:",IDC_STATIC,22,152,35,20
-    EDITTEXT        DRV_CONNSETTINGS,61,153,225,25,ES_MULTILINE | 
+                    WS_TABSTOP,225,115,68,10
+    LTEXT           "&Cache Size:",IDC_STATIC,15,133,45,8
+    EDITTEXT        DRV_CACHE_SIZE,61,129,35,12,ES_AUTOHSCROLL
+    LTEXT           "Max &Varchar:",IDC_STATIC,99,133,49,8
+    EDITTEXT        DRV_VARCHAR_SIZE,149,129,35,12,ES_AUTOHSCROLL
+    LTEXT           "Max Lon&gVarChar:",IDC_STATIC,192,133,65,8
+    EDITTEXT        DRV_LONGVARCHAR_SIZE,259,129,35,12,ES_AUTOHSCROLL
+    LTEXT           "SysTable &Prefixes:",IDC_STATIC,23,144,36,20
+    EDITTEXT        DRV_EXTRASYSTABLEPREFIXES,61,153,75,12,ES_AUTOHSCROLL
+    LTEXT           "Connect &Settings:",IDC_STATIC,22,165,35,20
+    EDITTEXT        DRV_CONNSETTINGS,61,165,225,25,ES_MULTILINE | 
                     ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN
-    DEFPUSHBUTTON   "OK",IDOK,59,188,50,14,WS_GROUP
-    PUSHBUTTON      "Cancel",IDCANCEL,129,188,50,14
-    PUSHBUTTON      "Defaults",IDDEFAULTS,199,188,50,15
+    DEFPUSHBUTTON   "OK",IDOK,59,201,50,14,WS_GROUP
+    PUSHBUTTON      "Cancel",IDCANCEL,129,201,50,14
+    PUSHBUTTON      "Defaults",IDDEFAULTS,199,201,50,15
+    CONTROL         "DSN",DRV_OR_DSN,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT |
+                    BS_NOTIFY | WS_TABSTOP,243,208,30,10
 END
 
 DLG_OPTIONS_DS DIALOG DISCARDABLE  0, 0, 267, 161
@@ -194,7 +198,7 @@ BEGIN
                     DRV_MSG_LABEL,36,5,220,15
 END
 
-DLG_OPTIONS_DRV DIALOG DISCARDABLE  0, 0, 287, 226
+DLG_OPTIONS_DRV DIALOG DISCARDABLE  0, 0, 287, 241
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Advanced Options (Driver)"
 FONT 8, "MS Sans Serif"
@@ -215,34 +219,38 @@ BEGIN
                     BS_AUTOCHECKBOX | WS_TABSTOP,15,50,80,10
     CONTROL         "Cancel as FreeStmt (Exp)",DRV_CANCELASFREESTMT,"Button",
                     BS_AUTOCHECKBOX | WS_TABSTOP,140,50,105,10
-    GROUPBOX        "Unknown Sizes",IDC_STATIC,10,65,175,25
+    CONTROL         "Mylog(Debug ouput)",DRV_DEBUG,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,140,65,112,10
+    GROUPBOX        "Unknown Sizes",IDC_STATIC,10,80,175,25
     CONTROL         "Maximum",DRV_UNKNOWN_MAX,"Button",BS_AUTORADIOBUTTON | 
-                    WS_GROUP | WS_TABSTOP,15,76,45,10
+                    WS_GROUP | WS_TABSTOP,15,91,45,10
     CONTROL         "Don't Know",DRV_UNKNOWN_DONTKNOW,"Button",
-                    BS_AUTORADIOBUTTON | WS_TABSTOP,70,76,53,10
+                    BS_AUTORADIOBUTTON | WS_TABSTOP,70,91,53,10
     CONTROL         "Longest",DRV_UNKNOWN_LONGEST,"Button",
-                    BS_AUTORADIOBUTTON | WS_TABSTOP,130,76,50,10
-    GROUPBOX        "Data Type Options",IDC_STATIC,10,95,270,25
+                    BS_AUTORADIOBUTTON | WS_TABSTOP,130,91,50,10
+    GROUPBOX        "Data Type Options",IDC_STATIC,10,110,270,25
     CONTROL         "Text as LongVarChar",DRV_TEXT_LONGVARCHAR,"Button",
-                    BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,105,80,10
+                    BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,120,80,10
     CONTROL         "Unknowns as LongVarChar",DRV_UNKNOWNS_LONGVARCHAR,
-                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,105,105,100,10
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,105,120,100,10
     CONTROL         "Bools as Char",DRV_BOOLS_CHAR,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,215,105,60,10
-    LTEXT           "&Cache Size:",IDC_STATIC,10,130,40,10
-    EDITTEXT        DRV_CACHE_SIZE,50,130,35,12,ES_AUTOHSCROLL
-    LTEXT           "Max &Varchar:",IDC_STATIC,90,130,45,10
-    EDITTEXT        DRV_VARCHAR_SIZE,135,130,35,12,ES_AUTOHSCROLL
-    LTEXT           "Max Lon&gVarChar:",IDC_STATIC,180,130,60,10
-    EDITTEXT        DRV_LONGVARCHAR_SIZE,240,130,35,12,ES_AUTOHSCROLL
-    LTEXT           "SysTable &Prefixes:",IDC_STATIC,15,145,35,20
-    EDITTEXT        DRV_EXTRASYSTABLEPREFIXES,50,151,75,12,ES_AUTOHSCROLL
-    RTEXT           "Connect &Settings:",IDC_STATIC,10,170,35,20
-    EDITTEXT        DRV_CONNSETTINGS,50,170,225,25,ES_MULTILINE | 
+                    WS_TABSTOP,215,120,60,10
+    LTEXT           "&Cache Size:",IDC_STATIC,10,145,40,10
+    EDITTEXT        DRV_CACHE_SIZE,50,145,35,12,ES_AUTOHSCROLL
+    LTEXT           "Max &Varchar:",IDC_STATIC,90,145,45,10
+    EDITTEXT        DRV_VARCHAR_SIZE,135,145,35,12,ES_AUTOHSCROLL
+    LTEXT           "Max Lon&gVarChar:",IDC_STATIC,180,145,60,10
+    EDITTEXT        DRV_LONGVARCHAR_SIZE,240,145,35,12,ES_AUTOHSCROLL
+    LTEXT           "SysTable &Prefixes:",IDC_STATIC,15,160,35,20
+    EDITTEXT        DRV_EXTRASYSTABLEPREFIXES,50,166,75,12,ES_AUTOHSCROLL
+    RTEXT           "Connect &Settings:",IDC_STATIC,10,185,35,20
+    EDITTEXT        DRV_CONNSETTINGS,50,185,225,25,ES_MULTILINE | 
                     ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN
-    DEFPUSHBUTTON   "OK",IDOK,45,205,50,14,WS_GROUP
-    PUSHBUTTON      "Cancel",IDCANCEL,115,205,50,14
-    PUSHBUTTON      "Defaults",IDDEFAULTS,185,205,50,15
+    DEFPUSHBUTTON   "OK",IDOK,45,220,50,14,WS_GROUP
+    PUSHBUTTON      "Cancel",IDCANCEL,115,220,50,14
+    PUSHBUTTON      "Defaults",IDDEFAULTS,185,220,50,15
+    CONTROL         "DSN",DRV_OR_DSN,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT |
+                    BS_NOTIFY | WS_TABSTOP,243,224,30,10
 END
 
 DLG_OPTIONS_DS DIALOG DISCARDABLE  0, 0, 267, 161
diff --git a/src/interfaces/odbc/qresult.c b/src/interfaces/odbc/qresult.c
index 086f4b87523..e2d7541e362 100644
--- a/src/interfaces/odbc/qresult.c
+++ b/src/interfaces/odbc/qresult.c
@@ -86,7 +86,7 @@ QR_inc_base(QResultClass *self, int base_inc)
  * CLASS QResult
  */
 QResultClass *
-QR_Constructor(void)
+QR_Constructor()
 {
 	QResultClass *rv;
 
@@ -239,6 +239,7 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
 	 */
 	if (conn != NULL)
 	{
+		ConnInfo *ci = &(conn->connInfo);
 		self->conn = conn;
 
 		mylog("QR_fetch_tuples: cursor = '%s', self->cursor=%u\n", (cursor == NULL) ? "" : cursor, self->cursor);
@@ -246,7 +247,7 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
 		if (self->cursor)
 			free(self->cursor);
 
-		if (globals.use_declarefetch)
+		if (ci->drivers.use_declarefetch)
 		{
 			if (!cursor || cursor[0] == '\0')
 			{
@@ -276,13 +277,14 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
 
 		mylog("QR_fetch_tuples: past CI_read_fields: num_fields = %d\n", self->num_fields);
 
-		if (globals.use_declarefetch)
+		if (ci->drivers.use_declarefetch)
 			tuple_size = self->cache_size;
 		else
 			tuple_size = TUPLE_MALLOC_INC;
 
 		/* allocate memory for the tuple cache */
 		mylog("MALLOC: tuple_size = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size);
+		self->count_allocated = 0;
 		self->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size);
 		if (!self->backend_tuples)
 		{
@@ -329,7 +331,7 @@ QR_close(QResultClass *self)
 {
 	QResultClass *res;
 
-	if (globals.use_declarefetch && self->conn && self->cursor)
+	if (self->conn && self->cursor && self->conn->connInfo.drivers.use_declarefetch)
 	{
 		char		buf[64];
 
@@ -399,6 +401,7 @@ QR_next_tuple(QResultClass *self)
 	char		cmdbuffer[ERROR_MSG_LENGTH + 1];
 	char		fetch[128];
 	QueryInfo	qi;
+	ConnInfo	*ci = NULL;
 
 	if (fetch_count < fcount)
 	{
@@ -430,7 +433,8 @@ QR_next_tuple(QResultClass *self)
 
 		if (!self->inTuples)
 		{
-			if (!globals.use_declarefetch)
+			ci = &(self->conn->connInfo);
+			if (!ci->drivers.use_declarefetch)
 			{
 				mylog("next_tuple: ALL_ROWS: done, fcount = %d, fetch_count = %d\n", fcount, fetch_count);
 				self->tupleField = NULL;
@@ -442,10 +446,10 @@ QR_next_tuple(QResultClass *self)
 			{
 				/* not a correction */
 				/* Determine the optimum cache size.  */
-				if (globals.fetch_max % self->rowset_size == 0)
-					fetch_size = globals.fetch_max;
-				else if (self->rowset_size < globals.fetch_max)
-					fetch_size = (globals.fetch_max / self->rowset_size) * self->rowset_size;
+				if (ci->drivers.fetch_max % self->rowset_size == 0)
+					fetch_size = ci->drivers.fetch_max;
+				else if (self->rowset_size < ci->drivers.fetch_max)
+					fetch_size = (ci->drivers.fetch_max / self->rowset_size) * self->rowset_size;
 				else
 					fetch_size = self->rowset_size;
 
@@ -465,13 +469,17 @@ QR_next_tuple(QResultClass *self)
 				self->fetch_count++;
 			}
 
-			if (self->cache_size > self->count_allocated)
-				self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField) * self->cache_size);
-			if (!self->backend_tuples)
+			if (!self->backend_tuples || self->cache_size > self->count_allocated)
 			{
-				self->status = PGRES_FATAL_ERROR;
-				QR_set_message(self, "Out of memory while reading tuples.");
-				return FALSE;
+				self->count_allocated = 0;
+				self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField) * self->cache_size);
+				if (!self->backend_tuples)
+				{
+					self->status = PGRES_FATAL_ERROR;
+					QR_set_message(self, "Out of memory while reading tuples.");
+					return FALSE;
+				}
+				self->count_allocated = self->cache_size;
 			}
 			sprintf(fetch, "fetch %d in %s", fetch_size, self->cursor);
 
@@ -482,10 +490,12 @@ QR_next_tuple(QResultClass *self)
 			qi.result_in = self;
 			qi.cursor = NULL;
 			res = CC_send_query(self->conn, fetch, &qi);
-			if (res == NULL)
+			if (res == NULL || QR_get_aborted(res))
 			{
 				self->status = PGRES_FATAL_ERROR;
 				QR_set_message(self, "Error fetching next group.");
+				if (res)
+					QR_Destructor(res);
 				return FALSE;
 			}
 			self->inTuples = TRUE;
@@ -511,6 +521,7 @@ QR_next_tuple(QResultClass *self)
 
 	sock = CC_get_socket(self->conn);
 	self->tupleField = NULL;
+	ci = &(self->conn->connInfo);
 
 	for (;;)
 	{
@@ -526,7 +537,7 @@ QR_next_tuple(QResultClass *self)
 			case 'B':			/* Tuples in binary format */
 			case 'D':			/* Tuples in ASCII format  */
 
-				if (!globals.use_declarefetch && self->fcount >= self->count_allocated)
+				if (!ci->drivers.use_declarefetch && self->fcount >= self->count_allocated)
 				{
 					int tuple_size = self->count_allocated;
 
diff --git a/src/interfaces/odbc/resource.h b/src/interfaces/odbc/resource.h
index 213f6f5d8c0..5ac559c478d 100644
--- a/src/interfaces/odbc/resource.h
+++ b/src/interfaces/odbc/resource.h
@@ -1,62 +1,64 @@
-/* {{NO_DEPENDENCIES}} */
-/* Microsoft Developer Studio generated include file. */
-/* Used by psqlodbc.rc */
-
-#define IDS_BADDSN						1
-#define IDS_MSGTITLE					2
-#define DLG_OPTIONS_DRV					102
-#define DLG_OPTIONS_DS					103
-#define IDC_DSNAME						400
-#define IDC_DSNAMETEXT					401
-#define IDC_DESC						404
-#define IDC_SERVER						407
-#define IDC_DATABASE					408
-#define DLG_CONFIG						1001
-#define IDC_PORT						1002
-#define IDC_USER						1006
-#define IDC_PASSWORD					1009
-#define DS_READONLY						1011
-#define DS_SHOWOIDCOLUMN				1012
-#define DS_FAKEOIDINDEX					1013
-#define DRV_COMMLOG						1014
-#define DS_PG62							1016
-#define IDC_DATASOURCE					1018
-#define DRV_OPTIMIZER					1019
-#define DS_CONNSETTINGS					1020
-#define IDC_DRIVER						1021
-#define DRV_CONNSETTINGS				1031
-#define DRV_UNIQUEINDEX					1032
-#define DRV_UNKNOWN_MAX					1035
-#define DRV_UNKNOWN_DONTKNOW			1036
-#define DRV_READONLY					1037
-#define IDC_DESCTEXT					1039
-#define DRV_MSG_LABEL					1040
-#define DRV_UNKNOWN_LONGEST				1041
-#define DRV_TEXT_LONGVARCHAR			1043
-#define DRV_UNKNOWNS_LONGVARCHAR		1044
-#define DRV_CACHE_SIZE					1045
-#define DRV_VARCHAR_SIZE				1046
-#define DRV_LONGVARCHAR_SIZE			1047
-#define IDDEFAULTS						1048
-#define DRV_USEDECLAREFETCH				1049
-#define DRV_BOOLS_CHAR					1050
-#define DS_SHOWSYSTEMTABLES				1051
-#define DRV_EXTRASYSTABLEPREFIXES		1051
-#define DS_ROWVERSIONING				1052
-#define DRV_PARSE						1052
-#define DRV_CANCELASFREESTMT			1053
-#define IDC_OPTIONS						1054
-#define DRV_KSQO						1055
-#define DS_PG64							1057
-#define DS_PG63							1058
-
-/* Next default values for new objects */
-
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE		104
-#define _APS_NEXT_COMMAND_VALUE			40001
-#define _APS_NEXT_CONTROL_VALUE			1060
-#define _APS_NEXT_SYMED_VALUE			101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by psqlodbc.rc
+//
+#define IDS_BADDSN                      1
+#define IDS_MSGTITLE                    2
+#define DLG_OPTIONS_DRV                 102
+#define DLG_OPTIONS_DS                  103
+#define IDC_DSNAME                      400
+#define IDC_DSNAMETEXT                  401
+#define IDC_DESC                        404
+#define IDC_SERVER                      407
+#define IDC_DATABASE                    408
+#define DLG_CONFIG                      1001
+#define IDC_PORT                        1002
+#define IDC_USER                        1006
+#define IDC_PASSWORD                    1009
+#define DS_READONLY                     1011
+#define DS_SHOWOIDCOLUMN                1012
+#define DS_FAKEOIDINDEX                 1013
+#define DRV_COMMLOG                     1014
+#define DS_PG62                         1016
+#define IDC_DATASOURCE                  1018
+#define DRV_OPTIMIZER                   1019
+#define DS_CONNSETTINGS                 1020
+#define IDC_DRIVER                      1021
+#define DRV_CONNSETTINGS                1031
+#define DRV_UNIQUEINDEX                 1032
+#define DRV_UNKNOWN_MAX                 1035
+#define DRV_UNKNOWN_DONTKNOW            1036
+#define DRV_READONLY                    1037
+#define IDC_DESCTEXT                    1039
+#define DRV_MSG_LABEL                   1040
+#define DRV_UNKNOWN_LONGEST             1041
+#define DRV_TEXT_LONGVARCHAR            1043
+#define DRV_UNKNOWNS_LONGVARCHAR        1044
+#define DRV_CACHE_SIZE                  1045
+#define DRV_VARCHAR_SIZE                1046
+#define DRV_LONGVARCHAR_SIZE            1047
+#define IDDEFAULTS                      1048
+#define DRV_USEDECLAREFETCH             1049
+#define DRV_BOOLS_CHAR                  1050
+#define DS_SHOWSYSTEMTABLES             1051
+#define DRV_EXTRASYSTABLEPREFIXES       1051
+#define DS_ROWVERSIONING                1052
+#define DRV_PARSE                       1052
+#define DRV_CANCELASFREESTMT            1053
+#define IDC_OPTIONS                     1054
+#define DRV_KSQO                        1055
+#define DS_PG64                         1057
+#define DS_PG63                         1058
+#define DRV_OR_DSN                      1059
+#define DRV_DEBUG			1060
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        105
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1061
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/src/interfaces/odbc/results.c b/src/interfaces/odbc/results.c
index bb1f2975df6..b63a214b816 100644
--- a/src/interfaces/odbc/results.c
+++ b/src/interfaces/odbc/results.c
@@ -38,7 +38,6 @@
 #endif
 #include "pgapifunc.h"
 
-extern GLOBAL_VALUES globals;
 
 
 RETCODE SQL_API
@@ -51,12 +50,14 @@ PGAPI_RowCount(
 	QResultClass *res;
 	char	   *msg,
 			   *ptr;
+	ConnInfo *ci;
 
 	if (!stmt)
 	{
 		SC_log_error(func, "", NULL);
 		return SQL_INVALID_HANDLE;
 	}
+	ci = &(SC_get_conn(stmt)->connInfo);
 	if (stmt->manual_result)
 	{
 		if (pcrow)
@@ -72,7 +73,7 @@ PGAPI_RowCount(
 
 			if (res && pcrow)
 			{
-				*pcrow = globals.use_declarefetch ? -1 : QR_get_num_tuples(res);
+				*pcrow = ci->drivers.use_declarefetch ? -1 : QR_get_num_tuples(res);
 				return SQL_SUCCESS;
 			}
 		}
@@ -119,17 +120,19 @@ PGAPI_NumResultCols(
 	StatementClass *stmt = (StatementClass *) hstmt;
 	QResultClass *result;
 	char		parse_ok;
+	ConnInfo *ci;
 
 	if (!stmt)
 	{
 		SC_log_error(func, "", NULL);
 		return SQL_INVALID_HANDLE;
 	}
+	ci = &(SC_get_conn(stmt)->connInfo);
 
 	SC_clear_error(stmt);
 
 	parse_ok = FALSE;
-	if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
+	if (ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT)
 	{
 		if (stmt->parse_status == STMT_PARSE_NONE)
 		{
@@ -211,7 +214,7 @@ PGAPI_DescribeCol(
 		return SQL_INVALID_HANDLE;
 	}
 
-	ci = &(stmt->hdbc->connInfo);
+	ci = &(SC_get_conn(stmt)->connInfo);
 
 	SC_clear_error(stmt);
 
@@ -223,7 +226,7 @@ PGAPI_DescribeCol(
 	icol--;						/* use zero based column numbers */
 
 	parse_ok = FALSE;
-	if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
+	if (ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT)
 	{
 		if (stmt->parse_status == STMT_PARSE_NONE)
 		{
@@ -288,7 +291,7 @@ PGAPI_DescribeCol(
 		fieldtype = QR_get_field_type(res, icol);
 
 		/* atoi(ci->unknown_sizes) */
-		precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes);
+		precision = pgtype_precision(stmt, fieldtype, icol, ci->drivers.unknown_sizes);
 	}
 
 	mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name);
@@ -400,7 +403,7 @@ PGAPI_ColAttributes(
 		return SQL_INVALID_HANDLE;
 	}
 
-	ci = &(stmt->hdbc->connInfo);
+	ci = &(SC_get_conn(stmt)->connInfo);
 
 	/*
 	 * Dont check for bookmark column.	This is the responsibility of the
@@ -411,14 +414,14 @@ PGAPI_ColAttributes(
 	icol--;
 
 	/* atoi(ci->unknown_sizes); */
-	unknown_sizes = globals.unknown_sizes;
+	unknown_sizes = ci->drivers.unknown_sizes;
 
 	/* not appropriate for SQLColAttributes() */
 	if (unknown_sizes == UNKNOWNS_AS_DONTKNOW)
 		unknown_sizes = UNKNOWNS_AS_MAX;
 
 	parse_ok = FALSE;
-	if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
+	if (ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT)
 	{
 		if (stmt->parse_status == STMT_PARSE_NONE)
 		{
@@ -660,6 +663,7 @@ PGAPI_GetData(
 	void	   *value = NULL;
 	int			result;
 	char		get_bookmark = FALSE;
+	ConnInfo *ci;
 
 	mylog("PGAPI_GetData: enter, stmt=%u\n", stmt);
 
@@ -668,6 +672,7 @@ PGAPI_GetData(
 		SC_log_error(func, "", NULL);
 		return SQL_INVALID_HANDLE;
 	}
+	ci = &(SC_get_conn(stmt)->connInfo);
 	res = stmt->result;
 
 	if (STMT_EXECUTING == stmt->status)
@@ -723,7 +728,7 @@ PGAPI_GetData(
 		}
 	}
 
-	if (stmt->manual_result || !globals.use_declarefetch)
+	if (stmt->manual_result || !ci->drivers.use_declarefetch)
 	{
 		/* make sure we're positioned on a valid row */
 		num_rows = QR_get_num_tuples(res);
@@ -913,6 +918,7 @@ PGAPI_ExtendedFetch(
 	RETCODE		result;
 	char		truncated,
 				error;
+	ConnInfo *ci;
 
 	mylog("PGAPI_ExtendedFetch: stmt=%u\n", stmt);
 
@@ -921,8 +927,9 @@ PGAPI_ExtendedFetch(
 		SC_log_error(func, "", NULL);
 		return SQL_INVALID_HANDLE;
 	}
+	ci = &(SC_get_conn(stmt)->connInfo);
 
-	if (globals.use_declarefetch && !stmt->manual_result)
+	if (ci->drivers.use_declarefetch && !stmt->manual_result)
 	{
 		if (fFetchType != SQL_FETCH_NEXT)
 		{
@@ -1101,7 +1108,7 @@ PGAPI_ExtendedFetch(
 	 * Handle Declare Fetch style specially because the end is not really
 	 * the end...
 	 */
-	if (globals.use_declarefetch && !stmt->manual_result)
+	if (ci->drivers.use_declarefetch && !stmt->manual_result)
 	{
 		if (QR_end_tuples(res))
 			return SQL_NO_DATA_FOUND;
@@ -1183,7 +1190,7 @@ PGAPI_ExtendedFetch(
 	stmt->currTuple = stmt->rowset_start;
 
 	/* For declare/fetch, need to reset cursor to beginning of rowset */
-	if (globals.use_declarefetch && !stmt->manual_result)
+	if (ci->drivers.use_declarefetch && !stmt->manual_result)
 		QR_set_position(res, 0);
 
 	/* Set the number of rows retrieved */
diff --git a/src/interfaces/odbc/setup.c b/src/interfaces/odbc/setup.c
index 2a779b417fc..65f3423cf15 100644
--- a/src/interfaces/odbc/setup.c
+++ b/src/interfaces/odbc/setup.c
@@ -27,7 +27,6 @@
 #define INTFUNC  __stdcall
 
 extern HINSTANCE NEAR s_hModule;/* Saved module handle. */
-extern GLOBAL_VALUES globals;
 
 /* Constants */
 #define MIN(x,y)	  ((x) < (y) ? (x) : (y))
@@ -218,48 +217,48 @@ ConfigDlgProc(HWND hdlg,
 			  WPARAM wParam,
 			  LPARAM lParam)
 {
+	LPSETUPDLG	lpsetupdlg;
+	ConnInfo	*ci;
 	switch (wMsg)
 	{
-			/* Initialize the dialog */
-			case WM_INITDIALOG:
+		/* Initialize the dialog */
+		case WM_INITDIALOG:
+			lpsetupdlg = (LPSETUPDLG) lParam;
+			ci = &lpsetupdlg->ci;
+
+			/* Hide the driver connect message */
+			ShowWindow(GetDlgItem(hdlg, DRV_MSG_LABEL), SW_HIDE);
+
+			SetWindowLong(hdlg, DWL_USER, lParam);
+			CenterDialog(hdlg);		/* Center dialog */
+
+			/*
+			 * NOTE: Values supplied in the attribute string will
+			 * always
+			 */
+			/* override settings in ODBC.INI */
+
+			/* Get the rest of the common attributes */
+			getDSNinfo(ci, CONN_DONT_OVERWRITE);
+
+			/* Fill in any defaults */
+			getDSNdefaults(ci);
+
+			/* Initialize dialog fields */
+			SetDlgStuff(hdlg, ci);
+
+			if (lpsetupdlg->fDefault)
 			{
-				LPSETUPDLG	lpsetupdlg = (LPSETUPDLG) lParam;
-				ConnInfo   *ci = &lpsetupdlg->ci;
-
-				/* Hide the driver connect message */
-				ShowWindow(GetDlgItem(hdlg, DRV_MSG_LABEL), SW_HIDE);
-
-				SetWindowLong(hdlg, DWL_USER, lParam);
-				CenterDialog(hdlg);		/* Center dialog */
-
-				/*
-				 * NOTE: Values supplied in the attribute string will
-				 * always
-				 */
-				/* override settings in ODBC.INI */
-
-				/* Get the rest of the common attributes */
-				getDSNinfo(ci, CONN_DONT_OVERWRITE);
-
-				/* Fill in any defaults */
-				getDSNdefaults(ci);
-
-				/* Initialize dialog fields */
-				SetDlgStuff(hdlg, ci);
-
-				if (lpsetupdlg->fDefault)
-				{
-					EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
-					EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
-				}
-				else
-					SendDlgItemMessage(hdlg, IDC_DSNAME,
-							 EM_LIMITTEXT, (WPARAM) (MAXDSNAME - 1), 0L);
-
-				SendDlgItemMessage(hdlg, IDC_DESC,
-							   EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L);
-				return TRUE;	/* Focus was not set */
+				EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
+				EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
 			}
+			else
+				SendDlgItemMessage(hdlg, IDC_DSNAME,
+						 EM_LIMITTEXT, (WPARAM) (MAXDSNAME - 1), 0L);
+
+			SendDlgItemMessage(hdlg, IDC_DESC,
+						   EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L);
+			return TRUE;	/* Focus was not set */
 
 			/* Process buttons */
 		case WM_COMMAND:
@@ -286,21 +285,17 @@ ConfigDlgProc(HWND hdlg,
 
 					/* Accept results */
 				case IDOK:
-					{
-						LPSETUPDLG	lpsetupdlg;
-
-						lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER);
-						/* Retrieve dialog values */
-						if (!lpsetupdlg->fDefault)
-							GetDlgItemText(hdlg, IDC_DSNAME,
+					lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER);
+					/* Retrieve dialog values */
+					if (!lpsetupdlg->fDefault)
+						GetDlgItemText(hdlg, IDC_DSNAME,
 										   lpsetupdlg->ci.dsn,
 										   sizeof(lpsetupdlg->ci.dsn));
-						/* Get Dialog Values */
-						GetDlgStuff(hdlg, &lpsetupdlg->ci);
+					/* Get Dialog Values */
+					GetDlgStuff(hdlg, &lpsetupdlg->ci);
 
-						/* Update ODBC.INI */
-						SetDSNAttributes(hdlg, lpsetupdlg);
-					}
+					/* Update ODBC.INI */
+					SetDSNAttributes(hdlg, lpsetupdlg);
 
 					/* Return to caller */
 				case IDCANCEL:
@@ -308,22 +303,18 @@ ConfigDlgProc(HWND hdlg,
 					return TRUE;
 
 				case IDC_DRIVER:
+					lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER);
 					DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
-								hdlg, driver_optionsProc, (LPARAM) NULL);
-
+								hdlg, driver_optionsProc, (LPARAM) &lpsetupdlg->ci);
 					return TRUE;
 
 				case IDC_DATASOURCE:
-					{
-						LPSETUPDLG	lpsetupdlg;
+					lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER);
 
-						lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWL_USER);
-
-						DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS),
+					DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS),
 						 hdlg, ds_optionsProc, (LPARAM) &lpsetupdlg->ci);
 
-						return TRUE;
-					}
+					return TRUE;
 			}
 			break;
 	}
diff --git a/src/interfaces/odbc/socket.c b/src/interfaces/odbc/socket.c
index ed3fd2913c6..fbfb5ca9297 100644
--- a/src/interfaces/odbc/socket.c
+++ b/src/interfaces/odbc/socket.c
@@ -13,6 +13,7 @@
  */
 
 #include "socket.h"
+#include "connection.h"
 
 #ifndef WIN32
 #include <stdlib.h>
@@ -41,7 +42,7 @@ SOCK_clear_error(SocketClass *self)
 
 
 SocketClass *
-SOCK_Constructor()
+SOCK_Constructor(const ConnectionClass *conn)
 {
 	SocketClass *rv;
 
@@ -54,14 +55,18 @@ SOCK_Constructor()
 		rv->buffer_filled_out = 0;
 		rv->buffer_read_in = 0;
 
-		rv->buffer_in = (unsigned char *) malloc(globals.socket_buffersize);
+		if (rv)
+			rv->buffer_size = conn->connInfo.drivers.socket_buffersize;
+		else
+			rv->buffer_size = globals.socket_buffersize;
+		rv->buffer_in = (unsigned char *) malloc(rv->buffer_size);
 		if (!rv->buffer_in)
 		{
 			free(rv);
 			return NULL;
 		}
 
-		rv->buffer_out = (unsigned char *) malloc(globals.socket_buffersize);
+		rv->buffer_out = (unsigned char *) malloc(rv->buffer_size);
 		if (!rv->buffer_out)
 		{
 			free(rv->buffer_in);
@@ -79,6 +84,7 @@ SOCK_Constructor()
 void
 SOCK_Destructor(SocketClass *self)
 {
+mylog("SOCK_Destructor\n");
 	if (self->socket != -1)
 	{
 		SOCK_put_char(self, 'X');
@@ -305,9 +311,9 @@ SOCK_get_next_byte(SocketClass *self)
 		 * there are no more bytes left in the buffer so reload the buffer
 		 */
 		self->buffer_read_in = 0;
-		self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, globals.socket_buffersize, 0);
+		self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, self->buffer_size, 0);
 
-		mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, globals.socket_buffersize);
+		mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, self->buffer_size);
 
 		if (self->buffer_filled_in < 0)
 		{
@@ -335,11 +341,11 @@ SOCK_put_next_byte(SocketClass *self, unsigned char next_byte)
 
 	self->buffer_out[self->buffer_filled_out++] = next_byte;
 
-	if (self->buffer_filled_out == globals.socket_buffersize)
+	if (self->buffer_filled_out == self->buffer_size)
 	{
 		/* buffer is full, so write it out */
-		bytes_sent = send(self->socket, (char *) self->buffer_out, globals.socket_buffersize, 0);
-		if (bytes_sent != globals.socket_buffersize)
+		bytes_sent = send(self->socket, (char *) self->buffer_out, self->buffer_size, 0);
+		if (bytes_sent != self->buffer_size)
 		{
 			self->errornumber = SOCKET_WRITE_ERROR;
 			self->errormsg = "Error while writing to the socket.";
diff --git a/src/interfaces/odbc/socket.h b/src/interfaces/odbc/socket.h
index b24be9504d4..f4c7b9e4e43 100644
--- a/src/interfaces/odbc/socket.h
+++ b/src/interfaces/odbc/socket.h
@@ -53,6 +53,7 @@ typedef unsigned int in_addr_t;
 struct SocketClass_
 {
 
+	int			buffer_size;
 	int			buffer_filled_in;
 	int			buffer_filled_out;
 	int			buffer_read_in;
@@ -79,7 +80,7 @@ struct SocketClass_
 
 
 /* Socket prototypes */
-SocketClass *SOCK_Constructor(void);
+SocketClass *SOCK_Constructor(const ConnectionClass *conn);
 void		SOCK_Destructor(SocketClass *self);
 char		SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname);
 void		SOCK_get_n_char(SocketClass *self, char *buffer, int len);
diff --git a/src/interfaces/odbc/statement.c b/src/interfaces/odbc/statement.c
index 891f47df831..bb4fab9bccf 100644
--- a/src/interfaces/odbc/statement.c
+++ b/src/interfaces/odbc/statement.c
@@ -32,7 +32,6 @@
 #endif
 #include "pgapifunc.h"
 
-extern GLOBAL_VALUES globals;
 
 #ifndef WIN32
 #ifndef HAVE_STRICMP
@@ -291,6 +290,7 @@ SC_Constructor(void)
 
 		rv->pre_executing = FALSE;
 		rv->inaccurate_result = FALSE;
+		rv->miscinfo = 0;
 	}
 	return rv;
 }
@@ -560,6 +560,7 @@ SC_pre_execute(StatementClass *self)
 	{
 		mylog("              preprocess: status = READY\n");
 
+		self->miscinfo = 0;
 		if (self->statement_type == STMT_TYPE_SELECT)
 		{
 			char		old_pre_executing = self->pre_executing;
@@ -577,7 +578,7 @@ SC_pre_execute(StatementClass *self)
 				self->status = STMT_PREMATURE;
 			}
 		}
-		else
+		if (!SC_is_pre_executable(self))
 		{
 			self->result = QR_Constructor();
 			QR_set_status(self->result, PGRES_TUPLES_OK);
@@ -718,15 +719,16 @@ SC_fetch(StatementClass *self)
 				lf;
 	Oid			type;
 	char	   *value;
-	ColumnInfoClass *ci;
+	ColumnInfoClass *coli;
 	/* TupleField *tupleField; */
+	ConnInfo *ci = &(SC_get_conn(self)->connInfo);
 
 	self->last_fetch_count = 0;
-	ci = QR_get_fields(res);	/* the column info */
+	coli = QR_get_fields(res);	/* the column info */
 
-	mylog("manual_result = %d, use_declarefetch = %d\n", self->manual_result, globals.use_declarefetch);
+	mylog("manual_result = %d, use_declarefetch = %d\n", self->manual_result, ci->drivers.use_declarefetch);
 
-	if (self->manual_result || !globals.use_declarefetch)
+	if (self->manual_result || !ci->drivers.use_declarefetch)
 	{
 		if (self->currTuple >= QR_get_num_tuples(res) - 1 ||
 			(self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1))
@@ -807,7 +809,7 @@ SC_fetch(StatementClass *self)
 			/* this column has a binding */
 
 			/* type = QR_get_field_type(res, lf); */
-			type = CI_get_oid(ci, lf);	/* speed things up */
+			type = CI_get_oid(coli, lf);	/* speed things up */
 
 			mylog("type = %d\n", type);
 
@@ -816,7 +818,7 @@ SC_fetch(StatementClass *self)
 				value = QR_get_value_manual(res, self->currTuple, lf);
 				mylog("manual_result\n");
 			}
-			else if (globals.use_declarefetch)
+			else if (ci->drivers.use_declarefetch)
 				value = QR_get_value_backend(res, lf);
 			else
 				value = QR_get_value_backend_row(res, self->currTuple, lf);
@@ -895,9 +897,11 @@ SC_execute(StatementClass *self)
 	Int2		oldstatus,
 				numcols;
 	QueryInfo	qi;
+	ConnInfo *ci;
 
 
 	conn = SC_get_conn(self);
+	ci = &(conn->connInfo);
 
 	/* Begin a transaction if one is not already in progress */
 
@@ -910,7 +914,8 @@ SC_execute(StatementClass *self)
 	 * OTHER.
 	 */
 	if (!self->internal && !CC_is_in_trans(conn) &&
-		((globals.use_declarefetch && self->statement_type == STMT_TYPE_SELECT) || (!CC_is_in_autocommit(conn) && self->statement_type != STMT_TYPE_OTHER)))
+	    ((ci->drivers.use_declarefetch && self->statement_type == STMT_TYPE_SELECT) ||
+	     (!CC_is_in_autocommit(conn) && self->statement_type != STMT_TYPE_OTHER)))
 	{
 		mylog("   about to begin a transaction on statement = %u\n", self);
 		res = CC_send_query(conn, "BEGIN", NULL);
@@ -959,7 +964,7 @@ SC_execute(StatementClass *self)
 		/* send the declare/select */
 		self->result = CC_send_query(conn, self->stmt_with_params, NULL);
 
-		if (globals.use_declarefetch && self->result != NULL &&
+		if (ci->drivers.use_declarefetch && self->result != NULL &&
 			QR_command_successful(self->result))
 		{
 			QR_Destructor(self->result);
@@ -970,7 +975,7 @@ SC_execute(StatementClass *self)
 			 */
 			qi.result_in = NULL;
 			qi.cursor = self->cursor_name;
-			qi.row_size = globals.fetch_max;
+			qi.row_size = ci->drivers.fetch_max;
 
 			/*
 			 * Most likely the rowset size will not be set by the
@@ -1075,21 +1080,21 @@ SC_execute(StatementClass *self)
 	    (self->errornumber == STMT_OK ||
 	     self->errornumber == STMT_INFO_ONLY) &&
 	    self->parameters &&
-	    self->parameters[0].buflen > 0 &&
+	    self->parameters[0].buffer &&
 	    self->parameters[0].paramType == SQL_PARAM_OUTPUT)
 	{	/* get the return value of the procedure call */
 		RETCODE	ret;
 		HSTMT hstmt = (HSTMT) self;
-		ret = PGAPI_BindCol(hstmt, 1, self->parameters[0].CType, self->parameters[0].buffer, self->parameters[0].buflen, self->parameters[0].used);
-		if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) 
-			SC_fetch(hstmt);
-		else
-		{
-			self->errornumber = STMT_EXEC_ERROR;
-			self->errormsg = "BindCol to Procedure return failed.";
+		ret = SC_fetch(hstmt);
+		if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
+		{ 
+			ret = PGAPI_GetData(hstmt, 1, self->parameters[0].CType, self->parameters[0].buffer, self->parameters[0].buflen, self->parameters[0].used);
+			if (ret != SQL_SUCCESS) 
+			{
+				self->errornumber = STMT_EXEC_ERROR;
+				self->errormsg = "GetData to Procedure return failed.";
+			}
 		}
-		if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) 
-			PGAPI_BindCol(hstmt, 1, self->parameters[0].CType, NULL, 0, NULL);
 		else
 		{
 			self->errornumber = STMT_EXEC_ERROR;
diff --git a/src/interfaces/odbc/statement.h b/src/interfaces/odbc/statement.h
index 571d13edaca..95ae1437a12 100644
--- a/src/interfaces/odbc/statement.h
+++ b/src/interfaces/odbc/statement.h
@@ -216,10 +216,10 @@ struct StatementClass_
 	int		stmt_size_limit;	
 
 	char		pre_executing;	/* This statement is prematurely executing */
-	char		inaccurate_result;		/* Current status is PREMATURE but
-										 * result is inaccurate */
-	char		errormsg_malloced;		/* Current status is PREMATURE but
+	char		inaccurate_result;	/* Current status is PREMATURE but
 										 * result is inaccurate */
+	char		errormsg_malloced;	/* Current error message is malloed (not in a static variable) ? */
+	char		miscinfo;
 };
 
 #define SC_get_conn(a)	  (a->hdbc)
@@ -229,6 +229,14 @@ struct StatementClass_
 #define STMT_FREE_PARAMS_ALL				0
 #define STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY	1
 
+/*	misc info */
+#define SC_set_pre_executable(a) (a->miscinfo |= 1L)
+#define SC_no_pre_executable(a)	(a->miscinfo &= ~1L)
+#define SC_is_pre_executable(a)	(a->miscinfo & 1L != 0)
+#define SC_set_fetchcursor(a)	(a->miscinfo |= 2L)
+#define SC_no_fetchcursor(a)	(a->miscinfo &= ~2L)
+#define SC_is_fetchcursor(a)	(a->miscinfo & 2L != 0)
+
 /*	Statement prototypes */
 StatementClass *SC_Constructor(void);
 void		InitializeStatementOptions(StatementOptions *opt);
-- 
GitLab