1. SQLStatistics now returns indices based on expression also.
2. Add a TEST button on the setup dialog.
# Process this file with autoconf to produce a configure script.
-AC_INIT(psqlodbc, 08.02.0102, [pgsql-odbc@postgresql.org])
+AC_INIT(psqlodbc, 08.02.0105, [pgsql-odbc@postgresql.org])
AC_PREREQ(2.52)
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([bind.c])
AM_CONDITIONAL(enable_unicode, [test x"$enable_unicode" = xyes])
AC_CHECK_FUNCS(strtoul strtoll)
+PGAC_STRUCT_ADDRINFO
+# If `struct addrinfo' exists, define HAVE_STRUCT_ADDRINFO.
# to implement the thread-safe driver
PGAC_ARG_BOOL(enable, pthreads, no,
[Define _REENTRANT for several plaforms])
AC_CHECK_LIB(pthreads, pthread_create, [],
[AC_CHECK_LIB(pthread, pthread_create)])
- AC_CHECK_FUNCS(localtime_r strtok_r pthread_mutexattr_settype)
+ AC_CHECK_FUNCS(localtime_r strtok_r strerror_r pthread_mutexattr_settype)
if test x"$ac_cv_func_pthread_mutexattr_settype" = xyes; then
AC_TRY_COMPILE([#include <pthread.h>],
[ int i = PTHREAD_MUTEX_RECURSIVE;],
[ int i = PTHREAD_MUTEX_RECURSIVE_NP;],
[AC_DEFINE(PG_RECURSIVE_MUTEXATTR, PTHREAD_MUTEX_RECURSIVE_NP, [Define if you have PTHREAD_MUTEX_RECURSIVE_NP])])])
fi
+ PGAC_FUNC_STRERROR_R_INT
])
AC_PROG_CC
SocketClass *sock = self->sock;
size_t pos;
char msg[4096];
+ const char *sockerrmsg;
mylog("enter CC_create_errormsg\n");
mylog("msg = '%s'\n", msg);
- if (sock && sock->errormsg && sock->errormsg[0] != '\0')
+ if (sock && NULL != (sockerrmsg = SOCK_get_errmsg(sock)) && '\0' != sockerrmsg[0])
{
pos = strlen(msg);
- snprintf(&msg[pos], sizeof(msg) - pos, ";\n%s", sock->errormsg);
+ snprintf(&msg[pos], sizeof(msg) - pos, ";\n%s", sockerrmsg);
}
mylog("exit CC_create_errormsg\n");
{
SocketClass *sock = self->sock;
- qlog(" socket=%d, reverse=%d, errornumber=%d, errormsg='%s'\n", sock->socket, sock->reverse, sock->errornumber, nullcheck(sock->errormsg));
+ qlog(" socket=%d, reverse=%d, errornumber=%d, errormsg='%s'\n", sock->socket, sock->reverse, sock->errornumber, nullcheck(SOCK_get_errmsg(sock)));
qlog(" buffer_in=%u, buffer_out=%u\n", sock->buffer_in, sock->buffer_out);
qlog(" buffer_filled_in=%d, buffer_filled_out=%d, buffer_read_in=%d\n", sock->buffer_filled_in, sock->buffer_filled_out, sock->buffer_read_in);
}
/* This is for internal use by SQLStatistics() */
case PG_TYPE_INT2VECTOR:
+ if (SQL_C_DEFAULT == fCType)
{
- int nval,
- i;
+ int i, nval, maxc;
const char *vp;
-
/* this is an array of eight integers */
- short *short_array = (short *) rgbValueBindRow;
+ short *short_array = (short *) rgbValueBindRow, shortv;
- len = INDEX_KEYS_STORAGE_COUNT * 2;
+ maxc = 0;
+ if (NULL != short_array)
+ maxc = (int) cbValueMax / sizeof(short);
vp = value;
nval = 0;
mylog("index=(");
- for (i = 0; i < INDEX_KEYS_STORAGE_COUNT; i++)
+ for (i = 0;; i++)
{
- if (sscanf(vp, "%hd", &short_array[i]) != 1)
+ if (sscanf(vp, "%hi", &shortv) != 1)
+ break;
+ mylog(" %hi", shortv);
+ if (0 == shortv && PG_VERSION_LT(conn, 7.2))
break;
-
- mylog(" %d", short_array[i]);
nval++;
+ if (nval < maxc)
+ short_array[i + 1] = shortv;
/* skip the current token */
while ((*vp != '\0') && (!isspace((UCHAR) *vp)))
if (*vp == '\0')
break;
}
- mylog(") nval = %d\n", nval);
-
- for (i = nval; i < INDEX_KEYS_STORAGE_COUNT; i++)
- short_array[i] = 0;
-
-#if 0
- sscanf(value, "%hd %hd %hd %hd %hd %hd %hd %hd",
- &short_array[0],
- &short_array[1],
- &short_array[2],
- &short_array[3],
- &short_array[4],
- &short_array[5],
- &short_array[6],
- &short_array[7]);
-#endif
+ mylog(") nval = %i\n", nval);
+ if (maxc > 0)
+ short_array[0] = nval;
/* There is no corresponding fCType for this. */
+ len = (nval + 1) * sizeof(short);
if (pcbValue)
*((SQLLEN *) pcbValueBindRow) = len;
- return COPY_OK; /* dont go any further or the data will be
+ if (len <= cbValueMax)
+ return COPY_OK; /* dont go any further or the data will be
* trashed */
+ else
+ return COPY_RESULT_TRUNCATED;
}
+ break;
/*
* This is a large object OID, which is used to store
* parameter marker -- the data has already been sent to
* the large object
*/
- sprintf(param_string, "%d", lobj_oid);
+ sprintf(param_string, "%u", lobj_oid);
lastadd = "::lo";
CVT_APPEND_STR(qb, param_string);
ShowWindow(GetDlgItem(hdlg, IDC_DESCTEXT), SW_HIDE);
ShowWindow(GetDlgItem(hdlg, IDC_DESC), SW_HIDE);
ShowWindow(GetDlgItem(hdlg, IDC_DRIVER), SW_HIDE);
+ ShowWindow(GetDlgItem(hdlg, IDC_TEST), SW_HIDE);
+ if ('\0' != ci->server[0])
+ EnableWindow(GetDlgItem(hdlg, IDC_SERVER), FALSE);
+ if ('\0' != ci->port[0])
+ EnableWindow(GetDlgItem(hdlg, IDC_PORT), FALSE);
SetWindowLongPtr(hdlg, DWLP_USER, lParam); /* Save the ConnInfo for
* the "OK" */
#ifdef WIN32
if (ci->drivers.cancel_as_freestmt)
{
+ typedef SQLRETURN (SQL_API *SQLAPIPROC)();
HMODULE hmodule;
- FARPROC addr;
+ SQLAPIPROC addr;
hmodule = GetModuleHandle("ODBC32");
- addr = GetProcAddress(hmodule, "SQLFreeStmt");
+ addr = (SQLAPIPROC) GetProcAddress(hmodule, "SQLFreeStmt");
ret = addr((char *) (stmt->phstmt) - 96, SQL_CLOSE);
}
else
else
set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], NULL_STRING);
set_tuplefield_string(&tuple[COLUMNS_TABLE_NAME], table_name);
- set_tuplefield_string(&tuple[COLUMNS_COLUMN_NAME], "oid");
+ set_tuplefield_string(&tuple[COLUMNS_COLUMN_NAME], OID_NAME);
sqltype = pgtype_to_concise_type(stmt, the_type, PG_STATIC);
set_tuplefield_int2(&tuple[COLUMNS_DATA_TYPE], sqltype);
set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], "OID");
tuple = QR_AddNew(res);
set_tuplefield_int2(&tuple[0], SQL_SCOPE_SESSION);
- set_tuplefield_string(&tuple[1], "oid");
+ set_tuplefield_string(&tuple[1], OID_NAME);
set_tuplefield_int2(&tuple[2], pgtype_to_concise_type(stmt, the_type, PG_STATIC));
set_tuplefield_string(&tuple[3], pgtype_to_name(stmt, the_type, TRUE));
set_tuplefield_int4(&tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
RETCODE ret = SQL_ERROR, result;
char *escSchemaName = NULL, *table_name = NULL, *escTableName = NULL;
char index_name[MAX_INFO_STRING];
- short fields_vector[INDEX_KEYS_STORAGE_COUNT];
+ short fields_vector[INDEX_KEYS_STORAGE_COUNT + 1];
char isunique[10],
isclustered[10],
ishash[MAX_INFO_STRING];
char buf[256];
SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName, field_number;
const char *szSchemaName;
- BOOL unknownf;
+ OID ioid;
mylog("%s: entering...stmt=%p scnm=%p len=%d\n", func, stmt, NULL_IF_NULL(szTableOwner), cbTableOwner);
escSchemaName = simpleCatalogEscape(table_schemaname, SQL_NTS, NULL, conn);
snprintf(index_query, sizeof(index_query), "select c.relname, i.indkey, i.indisunique"
", i.indisclustered, a.amname, c.relhasrules, n.nspname"
+ ", c.oid"
" from pg_catalog.pg_index i, pg_catalog.pg_class c,"
" pg_catalog.pg_class d, pg_catalog.pg_am a,"
" pg_catalog.pg_namespace n"
}
else
snprintf(index_query, sizeof(index_query), "select c.relname, i.indkey, i.indisunique"
- ", i.indisclustered, a.amname, c.relhasrules"
+ ", i.indisclustered, a.amname, c.relhasrules, c.oid"
" from pg_index i, pg_class c, pg_class d, pg_am a"
" where d.relname = '%s'"
" and d.oid = i.indrelid"
}
/* bind the vector column */
result = PGAPI_BindCol(hindx_stmt, 2, SQL_C_DEFAULT,
- fields_vector, INDEX_KEYS_STORAGE_COUNT * 2, &fields_vector_len);
+ fields_vector, sizeof(fields_vector), &fields_vector_len);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column
goto cleanup;
}
+ result = PGAPI_BindCol(hindx_stmt, 8, SQL_C_ULONG,
+ &ioid, sizeof(ioid), NULL);
+ if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+ {
+ SC_error_copy(stmt, indx_stmt, TRUE);
+ goto cleanup;
+ }
+
relhasrules[0] = '0';
result = PGAPI_Fetch(hindx_stmt);
/* fake index of OID */
set_tuplefield_int2(&tuple[STATS_TYPE], (Int2) SQL_INDEX_OTHER);
set_tuplefield_int2(&tuple[STATS_SEQ_IN_INDEX], (Int2) 1);
- set_tuplefield_string(&tuple[STATS_COLUMN_NAME], "oid");
+ set_tuplefield_string(&tuple[STATS_COLUMN_NAME], OID_NAME);
set_tuplefield_string(&tuple[STATS_COLLATION], "A");
set_tuplefield_null(&tuple[STATS_CARDINALITY]);
set_tuplefield_null(&tuple[STATS_PAGES]);
if (fUnique == SQL_INDEX_ALL ||
(fUnique == SQL_INDEX_UNIQUE && atoi(isunique)))
{
- i = 0;
+ int colcnt, attnum;
+
/* add a row in this table for each field in the index */
- while (i < INDEX_KEYS_STORAGE_COUNT && fields_vector[i] != 0)
+ colcnt = fields_vector[0];
+ for (i = 1; i <= colcnt; i++)
{
tuple = QR_AddNew(res);
(!strncmp(ishash, "hash", 4)) ? SQL_INDEX_HASHED : SQL_INDEX_OTHER));
set_tuplefield_int2(&tuple[STATS_SEQ_IN_INDEX], (Int2) (i + 1));
- if (fields_vector[i] == OID_ATTNUM)
+ attnum = fields_vector[i];
+ if (OID_ATTNUM == attnum)
{
- set_tuplefield_string(&tuple[STATS_COLUMN_NAME], "oid");
+ set_tuplefield_string(&tuple[STATS_COLUMN_NAME], OID_NAME);
mylog("%s: column name = oid\n", func);
}
+ else if (0 == attnum)
+ {
+ char cmd[64];
+
+ QResultClass *res;
+
+ snprintf(cmd, sizeof(cmd), "select pg_get_indexdef(%u, %d, true)", ioid, i);
+ res = CC_send_query(conn, cmd, NULL, IGNORE_ABORT_ON_CONN, stmt);
+ if (QR_command_maybe_successful(res))
+ set_tuplefield_string(&tuple[STATS_COLUMN_NAME], QR_get_value_backend_row(res, 0, 0));
+ QR_Destructor(res);
+ }
else
{
int j, matchidx;
+ BOOL unknownf = TRUE;
- unknownf = TRUE;
- if (fields_vector[i] >= 0)
+ if (attnum > 0)
{
for (j = 0; j < total_columns; j++)
{
- if (fields_vector[i] == column_names[j].pnum)
+ if (attnum == column_names[j].pnum)
{
matchidx = j;
unknownf = FALSE;
set_tuplefield_null(&tuple[STATS_CARDINALITY]);
set_tuplefield_null(&tuple[STATS_PAGES]);
set_tuplefield_null(&tuple[STATS_FILTER_CONDITION]);
- i++;
}
}
#else
#define MYLOGDIR "c:"
#endif /* WIN32 */
-extern void mylog(char *fmt,...);
+extern void mylog(const char *fmt,...);
extern void forcelog(const char *fmt,...);
#else /* MY_LOG */
void
generate_filename(const char *dirname, const char *prefix, char *filename)
{
+#ifdef WIN32
int pid = 0;
-#ifndef WIN32
+ pid = _getpid();
+#else
+ pid_t pid = 0;
struct passwd *ptr = 0;
ptr = getpwuid(getuid());
-#endif
pid = getpid();
+#endif
if (dirname == 0 || filename == 0)
return;
LEAVE_MYLOG_CS;
}
+#ifdef WIN32
+#define LOGGING_PROCESS_TIME
+#endif /* WIN32 */
#ifdef LOGGING_PROCESS_TIME
#include <mmsystem.h>
static DWORD start_time = 0;
#ifdef MY_LOG
static FILE *MLOGFP = NULL;
void
-mylog(char *fmt,...)
+mylog(const char *fmt,...)
{
va_list args;
char filebuf[80];
LTEXT "In the original form, Japanese patch Hiroshi-saito",
IDC_STATIC,35,198,295,8
PUSHBUTTON "\8aÇ\97\9d",IDC_MANAGEDSN,295,10,50,14
+ PUSHBUTTON "\83e\83X\83g",IDC_TEST,296,30,51,14
END
DLG_OPTIONS_DRV DIALOG DISCARDABLE 0, 0, 350, 241
EDITTEXT IDC_USER,57,69,72,12,ES_AUTOHSCROLL
RTEXT "Pass&word",IDC_STATIC,154,72,34,9
EDITTEXT IDC_PASSWORD,192,70,72,12,ES_PASSWORD | ES_AUTOHSCROLL
- DEFPUSHBUTTON "OK",IDOK,12,114,44,15,WS_GROUP
- PUSHBUTTON "Cancel",IDCANCEL,66,114,44,15
- GROUPBOX "Options",IDC_OPTIONS,121,101,177,35,BS_LEFT
- PUSHBUTTON "Datasource",IDC_DATASOURCE,128,115,50,14
- PUSHBUTTON "Global",IDC_DRIVER,184,115,50,14
+// DEFPUSHBUTTON "OK",IDOK,12,114,44,15,WS_GROUP
+// PUSHBUTTON "Cancel",IDCANCEL,66,114,44,15
+// GROUPBOX "Options",IDC_OPTIONS,121,101,177,35,BS_LEFT
+// PUSHBUTTON "Datasource",IDC_DATASOURCE,128,115,50,14
+// PUSHBUTTON "Global",IDC_DRIVER,184,115,50,14
LTEXT "Please supply any missing information required to connect.",
DRV_MSG_LABEL,12,5,249,10
- PUSHBUTTON "Manage DSN",IDC_MANAGEDSN,240,115,52,14
+// PUSHBUTTON "Manage DSN",IDC_MANAGEDSN,240,115,52,14
+
+ GROUPBOX "Options",IDC_OPTIONS,5,100,177,35,BS_LEFT
+ PUSHBUTTON "Datasource",IDC_DATASOURCE,12,114,50,14
+ PUSHBUTTON "Global",IDC_DRIVER,67,114,50,14
+ PUSHBUTTON "Manage DSN",IDC_MANAGEDSN,122,114,52,14
+
+ PUSHBUTTON "Test",IDC_TEST,254,103,44,15
+ DEFPUSHBUTTON "OK",IDOK,203,121,44,15,WS_GROUP
+ PUSHBUTTON "Cancel",IDCANCEL,254,121,44,15
END
DLG_OPTIONS_DRV DIALOG DISCARDABLE 0, 0, 287, 231
#define DS_STATEMENT_ROLLBACK 1082
#define DRV_DTCLOG 1083
#define DS_EXTRA_OPTIONS 1084
+#define IDC_TEST 1085
// Next default values for new objects
//
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 105
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1085
+#define _APS_NEXT_CONTROL_VALUE 1086
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
#include <string.h>
#include <stdlib.h>
#include "resource.h"
+#include "pgapifunc.h"
#include "dlg_specific.h"
#include "win_setup.h"
EndDialog(hdlg, wParam);
return TRUE;
+ case IDC_TEST:
+ {
+ lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWLP_USER);
+ if (NULL != lpsetupdlg)
+ {
+ ConnectionClass *conn=CC_Constructor();
+ char szMsg[SQL_MAX_MESSAGE_LENGTH];
+
+ /* Get Dialog Values */
+ GetDlgStuff(hdlg, &lpsetupdlg->ci);
+ if (conn)
+ {
+ char *emsg;
+
+ memcpy(&conn->connInfo, &lpsetupdlg->ci, sizeof(ConnInfo));
+ if (CC_connect(conn, AUTH_REQ_OK, NULL) > 0)
+ {
+ strncpy(szMsg, "Connection successful", sizeof(szMsg));
+ emsg = szMsg;
+ }
+ else
+ {
+ int errnum;
+
+ CC_get_error(conn, &errnum, &emsg);
+ }
+ MessageBox(lpsetupdlg->hwndParent, emsg, "Connection Test", MB_ICONEXCLAMATION | MB_OK);
+ CC_Destructor(conn);
+ return TRUE;
+ }
+ }
+ break;
+ }
case IDC_DATASOURCE:
lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWLP_USER);
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
{
int gerrno = SOCK_ERRNO;
s->errornumber = _no;
- s->errormsg = (char *) _msg;
+ if (NULL != s->_errormsg_)
+ free(s->_errormsg_);
+ if (NULL != _msg)
+ s->_errormsg_ = strdup(_msg);
+ else
+ s->_errormsg_ = NULL;
mylog("(%d)%s ERRNO=%d\n", _no, _msg, gerrno);
}
SOCK_clear_error(SocketClass *self)
{
self->errornumber = 0;
- self->errormsg = NULL;
+ if (NULL != self->_errormsg_)
+ free(self->_errormsg_);
+ self->_errormsg_ = NULL;
}
free(rv);
return NULL;
}
- rv->errormsg = NULL;
+ rv->_errormsg_ = NULL;
rv->errornumber = 0;
rv->reverse = FALSE;
}
if (self->buffer_out)
free(self->buffer_out);
+ if (self->_errormsg_)
+ free(self->_errormsg_);
free(self);
}
static getnameinfo_func getnameinfo_ptr = getnameinfo;
#endif /* _MSC_VER */
+static BOOL format_sockerr(char *errmsg, size_t buflen, int errnum, const char *cmd, const char *host, int portno)
+{
+ BOOL ret = FALSE;
+
+#ifdef WIN32
+ if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL,
+ errnum, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ errmsg, (DWORD)buflen, NULL))
+ ret = TRUE;
+#else
+#if defined(POSIX_MULTITHREAD_SUPPORT) && defined(HAVE_STRERROR_R)
+#ifdef STRERROR_R_INT
+ if (0 == strerror_r(errnum, errmsg, buflen))
+ ret = TRUE;
+#else
+ const char *pchar;
+
+ pchar = (const char *) strerror_r(errnum, errmsg, buflen);
+ if (NULL != pchar)
+ {
+ if (pchar != errmsg)
+ strncpy(errmsg, pchar, buflen);
+ ret = TRUE;
+ }
+#endif /* STRERROR_R_INT */
+#else
+ strncpy(errmsg, strerror(errnum), buflen);
+ ret = TRUE;
+#endif /* POSIX_MULTITHREAD_SUPPORT */
+#endif /* WIN32 */
+ if (ret)
+ {
+ size_t tlen = strlen(errmsg);
+ errmsg += tlen;
+ buflen -= tlen;
+ snprintf(errmsg, buflen, " [%s:%d]", host, portno);
+ }
+ else
+ snprintf(errmsg, buflen, "%s failed for [%s:%d] ", cmd, host, portno);
+ return ret;
+}
+
char
SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname, long timeout)
{
getnameinfo_ptr((struct sockaddr *) &(self->sadr_area),
self->sadr_len, host, sizeof(host),
NULL, 0, NI_NUMERICHOST);
- snprintf(errmsg, sizeof(errmsg), "connect getsockopt val %d addr=%s\n", optval, host);
+ /* snprintf(errmsg, sizeof(errmsg), "connect getsockopt val %d addr=%s\n", optval, host); */
+ format_sockerr(errmsg, sizeof(errmsg), optval, "connect", host, port);
mylog(errmsg);
- SOCK_set_error(self, SOCKET_COULD_NOT_CONNECT, "Could not connect to remote server.");
+ SOCK_set_error(self, SOCKET_COULD_NOT_CONNECT, errmsg);
}
else
retval = 1;
unsigned int pversion;
int reslen;
- char *errormsg;
+ char *_errormsg_;
int errornumber;
int sadr_len;
struct sockaddr_storage sadr_area; /* Used for various connections */
/* error functions */
#define SOCK_get_errcode(self) (self ? self->errornumber : SOCKET_CLOSED)
-#define SOCK_get_errmsg(self) (self ? self->errormsg : "socket closed")
+#define SOCK_get_errmsg(self) (self ? self->_errormsg_ : "socket closed")
/*
* code taken from postgres libpq et al.
if (conn && !msgend)
{
SocketClass *sock = conn->sock;
+ const char *sockerrmsg;
if (!resmsg && (wmsg = CC_get_errormsg(conn)) && wmsg[0] != '\0')
{
snprintf(&msg[pos], sizeof(msg) - pos, ";\n%s", CC_get_errormsg(conn));
}
- if (sock && sock->errormsg && sock->errormsg[0] != '\0')
+ if (sock && NULL != (sockerrmsg = SOCK_get_errmsg(sock)) && '\0' != sockerrmsg[0])
{
pos = strlen(msg);
- snprintf(&msg[pos], sizeof(msg) - pos, ";\n%s", sock->errormsg);
+ snprintf(&msg[pos], sizeof(msg) - pos, ";\n%s", sockerrmsg);
}
ermsg = msg;
}
#ifndef __VERSION_H__
#define __VERSION_H__
-#define POSTGRESDRIVERVERSION "08.02.0104"
-#define POSTGRES_RESOURCE_VERSION "08.02.0104\0"
-#define PG_DRVFILE_VERSION 8,2,01,04
+#define POSTGRESDRIVERVERSION "08.02.0105"
+#define POSTGRES_RESOURCE_VERSION "08.02.0105\0"
+#define PG_DRVFILE_VERSION 8,2,01,05
#endif
BSC32_SBRS= \
LINK32=link.exe
-LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib XOleHlp.lib /nologo /dll
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib XOleHlp.lib winmm.lib /nologo /dll
!IF "$(ANSI_VERSION)" == "yes"
DEF_FILE= "psqlodbca.def"
!ELSE