mirror of
https://github.com/mdbtools/mdbtools.git
synced 2025-06-28 15:39:02 +08:00
ODBC build fixes
* Require SQLGetPrivateProfileString in ODBC libraries * Attempt to fix reported deadlock with unixODBC by rearranging functions
This commit is contained in:
parent
acbace242c
commit
362938f17c
17
configure.ac
17
configure.ac
@ -68,7 +68,7 @@ AM_CONDITIONAL(SQL, test x$sql = xtrue)
|
||||
AC_SUBST(SQL)
|
||||
AC_SUBST(LFLAGS)
|
||||
|
||||
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes -Werror"
|
||||
CFLAGS="$CFLAGS -Wall -Werror"
|
||||
AS_CASE([$host],
|
||||
[*mingw*|*cygwin*], [LDFLAGS="$LDFLAGS -no-undefined"], [])
|
||||
AS_CASE([$host],
|
||||
@ -104,10 +104,8 @@ if test "$with_iodbc"; then
|
||||
|
||||
OLDLDFLAGS=$LDFLAGS
|
||||
LDFLAGS="$LDFLAGS $ODBC_LIBS"
|
||||
AC_CHECK_LIB(iodbcinst, SQLGetPrivateProfileString,
|
||||
[ODBC_LIBS="$ODBC_LIBS -liodbcinst"
|
||||
AC_DEFINE_UNQUOTED(HAVE_SQLGETPRIVATEPROFILESTRING, 1,
|
||||
[Define to 1 if you have the SQLGetPrivateProfileString function.])])
|
||||
AC_CHECK_LIB(iodbcinst, SQLGetPrivateProfileString, [FOO=bar],
|
||||
AC_MSG_ERROR([Could not find SQLGetPrivateProfileString in -liodbcinst]))
|
||||
LDFLAGS=$OLDLDFLAGS
|
||||
fi
|
||||
|
||||
@ -127,10 +125,8 @@ if test "$with_unixodbc"; then
|
||||
|
||||
OLDLDFLAGS=$LDFLAGS
|
||||
LDFLAGS="$LDFLAGS $ODBC_LIBS"
|
||||
AC_CHECK_LIB(odbcinst, SQLGetPrivateProfileString,
|
||||
[ODBC_LIBS="$ODBC_LIBS -lodbcinst"
|
||||
AC_DEFINE_UNQUOTED(HAVE_SQLGETPRIVATEPROFILESTRING, 1,
|
||||
[Define to 1 if you have the SQLGetPrivateProfileString function.])])
|
||||
AC_CHECK_LIB(odbcinst, SQLGetPrivateProfileString, [ODBC_LIBS="$ODBC_LIBS -lodbcinst"],
|
||||
AC_MSG_ERROR([Could not find SQLGetPrivateProfileString in -lodbcinst]))
|
||||
LDFLAGS=$OLDLDFLAGS
|
||||
fi
|
||||
|
||||
@ -146,6 +142,9 @@ if test "x$HAVE_ODBC" = "xtrue"; then
|
||||
OPTDIRS="$OPTDIRS odbc"
|
||||
fi
|
||||
|
||||
dnl Turn on -Wstrict-prototypes here because AC_CHECK_LIB is dumb
|
||||
CFLAGS="$CFLAGS -Wstrict-prototypes"
|
||||
|
||||
dnl Conditionally build odbc wide version
|
||||
AM_CONDITIONAL(ICONV, test "$am_cv_func_iconv" = "yes")
|
||||
|
||||
|
@ -2,8 +2,8 @@ AUTOMAKE_OPTIONS = subdir-objects
|
||||
noinst_PROGRAMS = unittest
|
||||
lib_LTLIBRARIES = libmdbodbc.la
|
||||
AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(ODBC_CFLAGS)
|
||||
libmdbodbc_la_SOURCES = odbc.c connectparams.c mdbodbc.h connectparams.h
|
||||
libmdbodbc_la_LIBADD = ../libmdb/libmdb.la ../sql/libmdbsql.la
|
||||
libmdbodbc_la_SOURCES = odbc.c connectparams.c
|
||||
libmdbodbc_la_LIBADD = ../libmdb/libmdb.la ../sql/libmdbsql.la $(ODBC_LIBS)
|
||||
libmdbodbc_la_LDFLAGS = -avoid-version -export-symbols-regex '^(SQL|ODBCINST)'
|
||||
if FAKE_GLIB
|
||||
libmdbodbc_la_SOURCES += ../libmdb/fakeglib.c
|
||||
@ -15,5 +15,5 @@ libmdbodbcW_la_LIBADD = $(libmdbodbc_la_LIBADD) @LIBICONV@
|
||||
libmdbodbcW_la_LDFLAGS = $(libmdbodbc_la_LDFLAGS)
|
||||
libmdbodbcW_la_CFLAGS = $(AM_CFLAGS) -D ENABLE_ODBC_W=1
|
||||
endif
|
||||
LIBS = $(GLIB_LIBS) $(ODBC_LIBS)
|
||||
LIBS = $(GLIB_LIBS)
|
||||
unittest_LDADD = libmdbodbc.la ../libmdb/libmdb.la ../sql/libmdbsql.la
|
||||
|
@ -23,6 +23,11 @@
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
#ifdef UNIXODBC
|
||||
#include <odbcinstext.h>
|
||||
#else
|
||||
#include <odbcinst.h>
|
||||
#endif
|
||||
#include "connectparams.h"
|
||||
|
||||
/*
|
||||
@ -42,20 +47,6 @@
|
||||
static char line[max_line];
|
||||
|
||||
static guint HashFunction (gconstpointer key);
|
||||
#if HAVE_SQLGETPRIVATEPROFILESTRING
|
||||
#include <sqltypes.h>
|
||||
extern int SQLGetPrivateProfileString( LPCSTR lpszSection,
|
||||
LPCSTR lpszEntry,
|
||||
LPCSTR lpszDefault,
|
||||
LPSTR lpszRetBuffer,
|
||||
int cbRetBuffer,
|
||||
LPCSTR lpszFilename);
|
||||
#else
|
||||
static GString* GetIniFileName (void);
|
||||
static int FileExists (const gchar* name);
|
||||
static int FindSection (FILE* stream, const char* section);
|
||||
static int GetNextItem (FILE* stream, char** name, char** value);
|
||||
#endif //HAVE_SQLGETPRIVATEPROFILESTRING
|
||||
|
||||
static void visit (gpointer key, gpointer value, gpointer user_data);
|
||||
static void cleanup (gpointer key, gpointer value, gpointer user_data);
|
||||
@ -98,95 +89,18 @@ void FreeConnectParams (ConnectParams* params)
|
||||
}
|
||||
}
|
||||
|
||||
#if !HAVE_SQLGETPRIVATEPROFILESTRING
|
||||
static int LoadDSN (
|
||||
const gchar* iniFileName, const gchar* dsnName, GHashTable* table)
|
||||
{
|
||||
FILE* stream;
|
||||
gchar* name;
|
||||
gchar* value;
|
||||
|
||||
|
||||
if ((stream = fopen (iniFileName, "r" )) != NULL )
|
||||
{
|
||||
if (!FindSection (stream, dsnName))
|
||||
{
|
||||
g_printerr ("Couldn't find DSN %s in %s\n", dsnName, iniFileName);
|
||||
fclose (stream);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (GetNextItem (stream, &name, &value))
|
||||
{
|
||||
g_hash_table_insert (table, g_strdup (name), g_strdup (value));
|
||||
}
|
||||
}
|
||||
|
||||
fclose( stream );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the settings for the specified ODBC DSN
|
||||
*/
|
||||
gboolean LookupDSN (ConnectParams* params, const gchar* dsnName)
|
||||
{
|
||||
if (!params) {
|
||||
fprintf(stderr,"LookupDSN: no parameters, returning FALSE\n");
|
||||
return FALSE;
|
||||
}
|
||||
/*
|
||||
* Set the DSN name property
|
||||
*/
|
||||
/* params->dsnName = g_string_assign (params->dsnName, dsnName); */
|
||||
/*
|
||||
* Search for the ODBC ini file
|
||||
*/
|
||||
if (!(params->iniFileName = GetIniFileName ())) {
|
||||
fprintf(stderr,"LookupDSN: GetIniFileName returned FALSE\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!LoadDSN (params->iniFileName->str, dsnName, params->table)) {
|
||||
fprintf(stderr,"LookupDSN: LoadDSN returned FALSE\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
/*
|
||||
* Get the value of a given ODBC Connection Parameter
|
||||
*/
|
||||
|
||||
gchar* GetConnectParam (ConnectParams* params, const gchar* paramName)
|
||||
{
|
||||
if (!params || !params->table)
|
||||
return NULL;
|
||||
|
||||
return g_hash_table_lookup (params->table, paramName);
|
||||
}
|
||||
|
||||
#else
|
||||
gboolean LookupDSN (ConnectParams* params, const gchar* dsnName)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
gchar* GetConnectParam (ConnectParams* params, const gchar* paramName)
|
||||
{
|
||||
static char tmp[FILENAME_MAX];
|
||||
|
||||
/* use old servername */
|
||||
tmp[0] = '\0';
|
||||
if (SQLGetPrivateProfileString(params->dsnName->str, paramName, "", tmp, FILENAME_MAX, "odbc.ini") > 0) {
|
||||
if (SQLGetPrivateProfileString(params->dsnName->str, paramName, "", tmp, sizeof(tmp), "odbc.ini") > 0) {
|
||||
return tmp;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
#endif /* !HAVE_SQLGETPRIVATEPROFILESTRING */
|
||||
|
||||
/*
|
||||
* Apply a connection string to the ODBC Parameter Settings
|
||||
@ -379,135 +293,6 @@ static guint HashFunction (gconstpointer key)
|
||||
return value;
|
||||
}
|
||||
|
||||
#if !HAVE_SQLGETPRIVATEPROFILESTRING
|
||||
static GString* GetIniFileName ()
|
||||
{
|
||||
char* setting;
|
||||
GString* iniFileName = g_string_new ("");
|
||||
/*
|
||||
* First, try the ODBCINI environment variable
|
||||
*/
|
||||
if ((setting = getenv ("ODBCINI")) != NULL)
|
||||
{
|
||||
g_string_assign (iniFileName, getenv ("ODBCINI"));
|
||||
|
||||
if (FileExists (iniFileName->str))
|
||||
return iniFileName;
|
||||
|
||||
g_string_assign (iniFileName, "");
|
||||
}
|
||||
/*
|
||||
* Second, try the HOME environment variable
|
||||
*/
|
||||
if ((setting = getenv ("HOME")) != NULL)
|
||||
{
|
||||
g_string_assign (iniFileName, setting);
|
||||
iniFileName = g_string_append (iniFileName, "/.odbc.ini");
|
||||
|
||||
if (FileExists (iniFileName->str))
|
||||
return iniFileName;
|
||||
|
||||
g_string_assign (iniFileName, "");
|
||||
}
|
||||
/*
|
||||
* As a last resort, try SYS_ODBC_INI
|
||||
*/
|
||||
g_string_assign (iniFileName, SYS_ODBC_INI);
|
||||
if (FileExists (iniFileName->str))
|
||||
return iniFileName;
|
||||
|
||||
g_string_assign (iniFileName, "");
|
||||
|
||||
return iniFileName;
|
||||
}
|
||||
|
||||
static int FileExists (const gchar* name)
|
||||
{
|
||||
struct stat fileStat;
|
||||
|
||||
return (stat (name, &fileStat) == 0);
|
||||
}
|
||||
|
||||
static int FindSection (FILE* stream, const char* section)
|
||||
{
|
||||
char* s;
|
||||
char sectionPattern[max_line];
|
||||
int len;
|
||||
|
||||
strcpy (sectionPattern, "[");
|
||||
strcat (sectionPattern, section);
|
||||
strcat (sectionPattern, "]");
|
||||
|
||||
s = fgets (line, max_line, stream);
|
||||
while (s != NULL)
|
||||
{
|
||||
/*
|
||||
* Get rid of the newline character
|
||||
*/
|
||||
len = strlen (line);
|
||||
if (len > 0) line[strlen (line) - 1] = '\0';
|
||||
/*
|
||||
* look for the section header
|
||||
*/
|
||||
if (strcmp (line, sectionPattern) == 0)
|
||||
return 1;
|
||||
|
||||
s = fgets (line, max_line, stream);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GetNextItem (FILE* stream, char** name, char** value)
|
||||
{
|
||||
char* s;
|
||||
int len;
|
||||
char equals[] = "="; /* used for seperator for strtok */
|
||||
char* token;
|
||||
|
||||
if (name == NULL || value == NULL)
|
||||
{
|
||||
g_printerr ("GetNextItem, invalid parameters");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = fgets (line, max_line, stream);
|
||||
if (s == NULL)
|
||||
{
|
||||
//perror ("fgets");
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Get rid of the newline character
|
||||
*/
|
||||
len = strlen (line);
|
||||
if (len > 0) line[strlen (line) - 1] = '\0';
|
||||
/*
|
||||
* Extract name from name = value
|
||||
*/
|
||||
if ((token = strtok (line, equals)) == NULL) return 0;
|
||||
|
||||
len = strlen (token);
|
||||
while (len > 0 && isspace(token[len-1]))
|
||||
{
|
||||
len--;
|
||||
token[len] = '\0';
|
||||
}
|
||||
*name = token;
|
||||
/*
|
||||
* extract value from name = value
|
||||
*/
|
||||
token = strtok (NULL, equals);
|
||||
if (token == NULL) return 0;
|
||||
while (*token && isspace(token[0]))
|
||||
token++;
|
||||
|
||||
*value = token;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif //!HAVE_SQLGETPRIVATEPROFILESTRING
|
||||
|
||||
static void visit (gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
FILE* output = (FILE*) user_data;
|
||||
@ -522,7 +307,6 @@ static void cleanup (gpointer key, gpointer value, gpointer user_data)
|
||||
|
||||
|
||||
#ifdef UNIXODBC
|
||||
#include <odbcinstext.h>
|
||||
|
||||
int
|
||||
ODBCINSTGetProperties(HODBCINSTPROPERTY hLastProperty)
|
||||
|
@ -200,7 +200,6 @@ SQLRETURN SQL_API SQLDriverConnect(
|
||||
SQLSMALLINT *pcbConnStrOut,
|
||||
SQLUSMALLINT fDriverCompletion)
|
||||
{
|
||||
char* dsn = NULL;
|
||||
char* database = NULL;
|
||||
ConnectParams* params;
|
||||
SQLRETURN ret;
|
||||
@ -210,11 +209,7 @@ SQLRETURN SQL_API SQLDriverConnect(
|
||||
|
||||
params = ((struct _hdbc*) hdbc)->params;
|
||||
|
||||
if ((dsn = ExtractDSN (params, (gchar*)szConnStrIn))) {
|
||||
if (!LookupDSN (params, dsn)){
|
||||
LogError ("Could not find DSN in odbc.ini");
|
||||
return SQL_ERROR;
|
||||
}
|
||||
if (ExtractDSN(params, (gchar*)szConnStrIn)) {
|
||||
SetConnectString (params, (gchar*)szConnStrIn);
|
||||
if (!(database = GetConnectParam (params, "Database"))){
|
||||
LogError ("Could not find Database parameter in '%s'", szConnStrIn);
|
||||
@ -471,7 +466,6 @@ SQLRETURN SQL_API SQLSetEnvAttr (
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
SQLRETURN SQL_API SQLBindParameter(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT ipar,
|
||||
@ -491,26 +485,6 @@ SQLRETURN SQL_API SQLBindParameter(
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLAllocHandle(
|
||||
SQLSMALLINT HandleType,
|
||||
SQLHANDLE InputHandle,
|
||||
SQLHANDLE * OutputHandle)
|
||||
{
|
||||
TRACE("SQLAllocHandle");
|
||||
switch(HandleType) {
|
||||
case SQL_HANDLE_STMT:
|
||||
return SQLAllocStmt(InputHandle,OutputHandle);
|
||||
break;
|
||||
case SQL_HANDLE_DBC:
|
||||
return SQLAllocConnect(InputHandle,OutputHandle);
|
||||
break;
|
||||
case SQL_HANDLE_ENV:
|
||||
return SQLAllocEnv(OutputHandle);
|
||||
break;
|
||||
}
|
||||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLAllocConnect(
|
||||
SQLHENV henv,
|
||||
SQLHDBC *phdbc)
|
||||
@ -563,6 +537,27 @@ SQLRETURN SQL_API SQLAllocStmt(
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLAllocHandle(
|
||||
SQLSMALLINT HandleType,
|
||||
SQLHANDLE InputHandle,
|
||||
SQLHANDLE * OutputHandle)
|
||||
{
|
||||
SQLRETURN retval = SQL_ERROR;
|
||||
TRACE("SQLAllocHandle");
|
||||
switch(HandleType) {
|
||||
case SQL_HANDLE_STMT:
|
||||
retval = SQLAllocStmt(InputHandle,OutputHandle);
|
||||
break;
|
||||
case SQL_HANDLE_DBC:
|
||||
retval = SQLAllocConnect(InputHandle,OutputHandle);
|
||||
break;
|
||||
case SQL_HANDLE_ENV:
|
||||
retval = SQLAllocEnv(OutputHandle);
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLBindCol(
|
||||
SQLHSTMT hstmt,
|
||||
SQLUSMALLINT icol,
|
||||
@ -639,12 +634,7 @@ SQLRETURN SQL_API SQLConnect(
|
||||
|
||||
params->dsnName = g_string_assign (params->dsnName, (gchar*)szDSN);
|
||||
|
||||
if (!LookupDSN (params, (gchar*)szDSN))
|
||||
{
|
||||
LogError ("Could not find DSN in odbc.ini");
|
||||
return SQL_ERROR;
|
||||
}
|
||||
else if (!(database = GetConnectParam (params, "Database")))
|
||||
if (!(database = GetConnectParam (params, "Database")))
|
||||
{
|
||||
LogError ("Could not find Database parameter in '%s'", szDSN);
|
||||
return SQL_ERROR;
|
||||
@ -1101,25 +1091,6 @@ SQLRETURN SQL_API SQLFetch(
|
||||
}
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLFreeHandle(
|
||||
SQLSMALLINT HandleType,
|
||||
SQLHANDLE Handle)
|
||||
{
|
||||
TRACE("SQLFreeHandle");
|
||||
switch(HandleType) {
|
||||
case SQL_HANDLE_STMT:
|
||||
SQLFreeStmt(Handle,SQL_DROP);
|
||||
break;
|
||||
case SQL_HANDLE_DBC:
|
||||
SQLFreeConnect(Handle);
|
||||
break;
|
||||
case SQL_HANDLE_ENV:
|
||||
SQLFreeEnv(Handle);
|
||||
break;
|
||||
}
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLFreeConnect(
|
||||
SQLHDBC hdbc)
|
||||
{
|
||||
@ -1189,6 +1160,26 @@ SQLRETURN SQL_API SQLFreeStmt(
|
||||
return SQL_SUCCESS;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLFreeHandle(
|
||||
SQLSMALLINT HandleType,
|
||||
SQLHANDLE Handle)
|
||||
{
|
||||
SQLRETURN retval = SQL_ERROR;
|
||||
TRACE("SQLFreeHandle");
|
||||
switch(HandleType) {
|
||||
case SQL_HANDLE_STMT:
|
||||
retval = SQLFreeStmt(Handle,SQL_DROP);
|
||||
break;
|
||||
case SQL_HANDLE_DBC:
|
||||
retval = SQLFreeConnect(Handle);
|
||||
break;
|
||||
case SQL_HANDLE_ENV:
|
||||
retval = SQLFreeEnv(Handle);
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
SQLRETURN SQL_API SQLGetStmtAttr (
|
||||
SQLHSTMT StatementHandle,
|
||||
SQLINTEGER Attribute,
|
||||
|
Loading…
Reference in New Issue
Block a user