Improved version handling introduced by Dave Page.

The driver version is 07.01.0002 now.
1) initialized pg_version by DSN's protocol info
   so that we could always use pg_version info
   once a connection is established (pg_version()
   didn't exist before 6.4). PROTOCOL_XX() macros
   are removed(except from connection.[ch]).
2) provided a few macros to encapsulate connection's
   version info and replaced existent comparison
   stuff by those macros.
3) change SQLTables() so that 7.1 servers could show
   views.


In addtion, the following patch from Dave Page is applied.

  This patch fixes a bug in SQLGetInfo for SQL_DBMS_VER which corrupted the
  driver version string. The driver version number has also been incremented
  to 07.01.0002.

  Regards, Dave. <<odbc.diff>>
This commit is contained in:
Hiroshi Inoue 2001-02-06 02:21:12 +00:00
parent 300e28888f
commit 5d08521fcd
7 changed files with 117 additions and 28 deletions

View File

@ -81,7 +81,7 @@ ConnInfo *ci;
new_adtsize = (Int2) SOCK_get_int(sock, 2);
/* If 6.4 protocol, then read the atttypmod field */
if ( ! PROTOCOL_63(ci) && ! PROTOCOL_62(ci)) {
if (PG_VERSION_GE(conn, 6.4)) {
mylog("READING ATTTYPMOD\n");
new_atttypmod = (Int4) SOCK_get_int(sock, 4);

View File

@ -98,6 +98,8 @@ static char *func = "SQLConnect";
/* get the values for the DSN from the registry */
getDSNinfo(ci, CONN_OVERWRITE);
/* initialize pg_version from connInfo.protocol */
CC_initialize_pg_version(conn);
/* override values from DSN info with UID and authStr(pwd)
This only occurs if the values are actually there.
@ -253,6 +255,10 @@ ConnectionClass *rv;
rv->translation_handle = NULL;
rv->DataSourceToDriver = NULL;
rv->DriverToDataSource = NULL;
memset(rv->pg_version, 0, sizeof(rv->pg_version));
rv->pg_version_number = .0;
rv->pg_version_major = 0;
rv->pg_version_minor = 0;
/* Initialize statement options to defaults */
@ -1365,6 +1371,28 @@ static char *func = "CC_lookup_lo";
result = SQLFreeStmt(hstmt, SQL_DROP);
}
/* This function initializes the version of PostgreSQL from
connInfo.protocol that we're connected to.
h-inoue 01-2-2001
*/
void
CC_initialize_pg_version(ConnectionClass *self)
{
strcpy(self->pg_version, self->connInfo.protocol);
if (PROTOCOL_62(&self->connInfo)) {
self->pg_version_number = (float) 6.2;
self->pg_version_major = 6;
self->pg_version_minor = 2;
} else if (PROTOCOL_63(&self->connInfo)) {
self->pg_version_number = (float) 6.3;
self->pg_version_major = 6;
self->pg_version_minor = 3;
} else {
self->pg_version_number = (float) 6.4;
self->pg_version_major = 6;
self->pg_version_minor = 4;
}
}
/* This function gets the version of PostgreSQL that we're connected to.
This is used to return the correct info in SQLGetInfo
DJP - 25-1-2001
@ -1376,6 +1404,7 @@ HSTMT hstmt;
StatementClass *stmt;
RETCODE result;
char *szVersion = "0.0";
int major, minor;
static char *func = "CC_lookup_pg_version";
mylog( "%s: entering...\n", func);
@ -1389,6 +1418,7 @@ static char *func = "CC_lookup_pg_version";
}
stmt = (StatementClass *) hstmt;
/* get the server's version if possible */
result = SQLExecDirect(hstmt, "select version()", SQL_NTS);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
SQLFreeStmt(hstmt, SQL_DROP);
@ -1407,10 +1437,13 @@ static char *func = "CC_lookup_pg_version";
return;
}
/* There's proably a nicer way of doing this... */
/* Extract the Major and Minor numbers from the string. */
/* This assumes the string starts 'Postgresql X.X' */
sprintf(szVersion, "%c.%c", self->pg_version[11], self->pg_version[13]);
if (sscanf(self->pg_version, "%*s %d.%d", &major, &minor) >= 2) {
sprintf(szVersion, "%d.%d", major, minor);
self->pg_version_major = major;
self->pg_version_minor = minor;
}
self->pg_version_number = (float) atof(szVersion);
mylog("Got the PostgreSQL version string: '%s'\n", self->pg_version);

View File

@ -163,6 +163,41 @@ typedef struct {
/* Macro to determine is the connection using 6.3 protocol? */
#define PROTOCOL_63(conninfo_) (strncmp((conninfo_)->protocol, PG63, strlen(PG63)) == 0)
/*
* Macros to compare the server's version with a specified version
* 1st parameter: pointer to a ConnectionClass object
* 2nd parameter: major version number
* 3rd parameter: minor version number
*/
#define SERVER_VERSION_GT(conn, major, minor) \
((conn)->pg_version_major > major || \
((conn)->pg_version_major == major && (conn)->pg_version_minor > minor))
#define SERVER_VERSION_GE(conn, major, minor) \
((conn)->pg_version_major > major || \
((conn)->pg_version_major == major && (conn)->pg_version_minor >= minor))
#define SERVER_VERSION_EQ(conn, major, minor) \
((conn)->pg_version_major == major && (conn)->pg_version_minor == minor)
#define SERVER_VERSION_LE(conn, major, minor) (! SERVER_VERSION_GT(conn, major, minor))
#define SERVER_VERSION_LT(conn, major, minor) (! SERVER_VERSION_GE(conn, major, minor))
/*#if ! defined(HAVE_CONFIG_H) || defined(HAVE_STRINGIZE)*/
#define STRING_AFTER_DOT(string) (strchr(#string, '.') + 1)
/*#else
#define STRING_AFTER_DOT(str) (strchr("str", '.') + 1)
#endif*/
/*
* Simplified macros to compare the server's version with a
* specified version
* Note: Never pass a variable as the second parameter.
* It must be a decimal constant of the form %d.%d .
*/
#define PG_VERSION_GT(conn, ver) \
(SERVER_VERSION_GT(conn, (int) ver, atoi(STRING_AFTER_DOT(ver))))
#define PG_VERSION_GE(conn, ver) \
(SERVER_VERSION_GE(conn, (int) ver, atoi(STRING_AFTER_DOT(ver))))
#define PG_VERSION_EQ(conn, ver) \
(SERVER_VERSION_EQ(conn, (int) ver, atoi(STRING_AFTER_DOT(ver))))
#define PG_VERSION_LE(conn, ver) (! PG_VERSION_GT(conn, ver))
#define PG_VERSION_LT(conn, ver) (! PG_VERSION_GE(conn, ver))
/* This is used to store cached table information in the connection */
struct col_info {
@ -223,6 +258,8 @@ struct ConnectionClass_ {
char errormsg_created; /* has an informative error msg been created? */
char pg_version[MAX_INFO_STRING]; /* Version of PostgreSQL we're connected to - DJP 25-1-2001 */
float pg_version_number;
Int2 pg_version_major;
Int2 pg_version_minor;
};
@ -258,6 +295,7 @@ int CC_send_function(ConnectionClass *conn, int fnid, void *result_buf, int *act
char CC_send_settings(ConnectionClass *self);
void CC_lookup_lo(ConnectionClass *conn);
void CC_lookup_pg_version(ConnectionClass *conn);
void CC_initialize_pg_version(ConnectionClass *conn);
void CC_log_error(char *func, char *desc, ConnectionClass *self);

View File

@ -113,6 +113,8 @@ int len = 0;
/* Fill in any default parameters if they are not there. */
getDSNdefaults(ci);
/* initialize pg_version */
CC_initialize_pg_version(conn);
#ifdef WIN32
dialog:

View File

@ -69,7 +69,7 @@ RETCODE SQL_API SQLGetInfo(
static char *func = "SQLGetInfo";
ConnectionClass *conn = (ConnectionClass *) hdbc;
ConnInfo *ci;
char *p = NULL;
char *p = NULL, tmp[MAX_INFO_STRING];
int len = 0, value = 0;
RETCODE result;
@ -193,9 +193,8 @@ RETCODE result;
case SQL_DBMS_VER: /* ODBC 1.0 */
/* The ODBC spec wants ##.##.#### ...whatever... so prepend the driver */
/* version number to the dbms version string */
p = POSTGRESDRIVERVERSION;
strcat(p, " ");
strcat(p, conn->pg_version);
sprintf(tmp, "%s %s", POSTGRESDRIVERVERSION, conn->pg_version);
p = tmp;
break;
case SQL_DEFAULT_TXN_ISOLATION: /* ODBC 1.0 */
@ -255,7 +254,7 @@ RETCODE result;
case SQL_IDENTIFIER_QUOTE_CHAR: /* ODBC 1.0 */
/* the character used to quote "identifiers" */
p = PROTOCOL_62(ci) ? " " : "\"";
p = PG_VERSION_LE(conn, 6.2) ? " " : "\"";
break;
case SQL_KEYWORDS: /* ODBC 2.0 */
@ -341,7 +340,7 @@ RETCODE result;
case SQL_MAX_ROW_SIZE: /* ODBC 2.0 */
len = 4;
if (conn->pg_version_number >= (float) 7.1) { /* Large Rowa in 7.1+ */
if (PG_VERSION_GE(conn, 7.1)) { /* Large Rowa in 7.1+ */
value = MAX_ROW_SIZE;
} else { /* Without the Toaster we're limited to the blocksize */
value = BLCKSZ;
@ -358,11 +357,13 @@ RETCODE result;
case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */
/* maybe this should be 0? */
len = 4;
if (conn->pg_version_number >= (float) 7.0) { /* Long Queries in 7.0+ */
if (PG_VERSION_GE(conn, 7.0)) { /* Long Queries in 7.0+ */
value = MAX_STATEMENT_LEN;
} else { /* Prior to 7.0 we used 2*BLCKSZ */
} else if (PG_VERSION_GE(conn, 6.5)) /* Prior to 7.0 we used 2*BLCKSZ */
value = (2*BLCKSZ);
}
else /* Prior to 6.5 we used BLCKSZ */
value = BLCKSZ;
break;
case SQL_MAX_TABLE_NAME_LEN: /* ODBC 1.0 */
@ -431,7 +432,7 @@ RETCODE result;
case SQL_OJ_CAPABILITIES: /* ODBC 2.01 */
len = 4;
if (conn->pg_version_number >= (float) 7.1) { /* OJs in 7.1+ */
if (PG_VERSION_GE(conn, 7.1)) { /* OJs in 7.1+ */
value = (SQL_OJ_LEFT |
SQL_OJ_RIGHT |
SQL_OJ_FULL |
@ -445,11 +446,11 @@ RETCODE result;
break;
case SQL_ORDER_BY_COLUMNS_IN_SELECT: /* ODBC 2.0 */
p = (PROTOCOL_62(ci) || PROTOCOL_63(ci)) ? "Y" : "N";
p = (PG_VERSION_LE(conn, 6.3)) ? "Y" : "N";
break;
case SQL_OUTER_JOINS: /* ODBC 1.0 */
if (conn->pg_version_number >= (float) 7.1) { /* OJs in 7.1+ */
if (PG_VERSION_GE(conn, 7.1)) { /* OJs in 7.1+ */
p = "Y";
} else { /* OJs not in <7.1 */
p = "N";
@ -937,7 +938,8 @@ HSTMT htbl_stmt;
RETCODE result;
char *tableType;
char tables_query[STD_STATEMENT_LEN];
char table_name[MAX_INFO_STRING], table_owner[MAX_INFO_STRING], relhasrules[MAX_INFO_STRING];
char table_name[MAX_INFO_STRING], table_owner[MAX_INFO_STRING], relkind_or_hasrules[MAX_INFO_STRING];
ConnectionClass *conn;
ConnInfo *ci;
char *prefix[32], prefixes[MEDIUM_REGISTRY_LEN];
char *table_type[32], table_types[MAX_INFO_STRING];
@ -955,6 +957,7 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
conn = (ConnectionClass *) (stmt->hdbc);
ci = &stmt->hdbc->connInfo;
result = SQLAllocStmt( stmt->hdbc, &htbl_stmt);
@ -970,8 +973,14 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
/* Create the query to find out the tables */
/* ********************************************************************** */
strcpy(tables_query, "select relname, usename, relhasrules from pg_class, pg_user");
strcat(tables_query, " where relkind = 'r'");
if (PG_VERSION_GE(conn, 7.1)) { /* view is represented by its relkind since 7.1 */
strcpy(tables_query, "select relname, usename, relkind from pg_class, pg_user");
strcat(tables_query, " where relkind in ('r', 'v')");
}
else {
strcpy(tables_query, "select relname, usename, relhasrules from pg_class, pg_user");
strcat(tables_query, " where relkind = 'r'");
}
my_strcat(tables_query, " and usename like '%.*s'", szTableOwner, cbTableOwner);
my_strcat(tables_query, " and relname like '%.*s'", szTableName, cbTableName);
@ -1039,6 +1048,9 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
/* match users */
if (PG_VERSION_LT(conn, 7.1)) /* filter out large objects in older versions */
strcat(tables_query, " and relname !~ '^xinv[0-9]+'");
strcat(tables_query, " and usesysid = relowner");
strcat(tables_query, " order by relname");
@ -1073,7 +1085,7 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
return SQL_ERROR;
}
result = SQLBindCol(htbl_stmt, 3, SQL_C_CHAR,
relhasrules, MAX_INFO_STRING, NULL);
relkind_or_hasrules, MAX_INFO_STRING, NULL);
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
stmt->errormsg = tbl_stmt->errormsg;
stmt->errornumber = tbl_stmt->errornumber;
@ -1131,7 +1143,10 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
}
/* Determine if the table name is a view */
view = (relhasrules[0] == '1');
if (PG_VERSION_GE(conn, 7.1)) /* view is represented by its relkind since 7.1 */
view = (relkind_or_hasrules[0] == 'v');
else
view = (relkind_or_hasrules[0] == '1');
/* It must be a regular table */
regular_table = ( ! systable && ! view);
@ -1214,6 +1229,7 @@ Int4 field_type, the_type, field_length, mod_length, precision;
char useStaticPrecision;
char not_null[MAX_INFO_STRING], relhasrules[MAX_INFO_STRING];
ConnInfo *ci;
ConnectionClass *conn;
mylog("%s: entering...stmt=%u\n", func, stmt);
@ -1226,6 +1242,7 @@ ConnInfo *ci;
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
conn = (ConnectionClass *) (stmt->hdbc);
ci = &stmt->hdbc->connInfo;
/* ********************************************************************** */
@ -1236,7 +1253,7 @@ ConnInfo *ci;
" from pg_user u, pg_class c, pg_attribute a, pg_type t"
" where u.usesysid = c.relowner"
" and c.oid= a.attrelid and a.atttypid = t.oid and (a.attnum > 0)",
PROTOCOL_62(ci) ? "a.attlen" : "a.atttypmod");
PG_VERSION_LE(conn, 6.2) ? "a.attlen" : "a.atttypmod");
my_strcat(columns_query, " and c.relname like '%.*s'", szTableName, cbTableName);
my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
@ -2315,7 +2332,6 @@ Int2 result_cols;
stmt->errormsg = "Couldn't allocate memory for SQLForeignKeys result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
SQLFreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}

View File

@ -6,7 +6,7 @@
*
* Comments: See "notice.txt" for copyright and license information.
*
* $Id: psqlodbc.h,v 1.29 2001/01/26 22:41:59 momjian Exp $
* $Id: psqlodbc.h,v 1.30 2001/02/06 02:21:12 inoue Exp $
*/
#ifndef __PSQLODBC_H__
@ -41,7 +41,7 @@ typedef UInt4 Oid;
#define DRIVERNAME "PostgreSQL ODBC"
#define DBMS_NAME "PostgreSQL"
#define POSTGRESDRIVERVERSION "07.01.0001"
#define POSTGRESDRIVERVERSION "07.01.0002"
#ifdef WIN32
#define DRIVER_FILE_NAME "PSQLODBC.DLL"

View File

@ -204,8 +204,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 7,1,0,1
PRODUCTVERSION 7,1,0,1
FILEVERSION 7,1,0,2
PRODUCTVERSION 7,1,0,2
FILEFLAGSMASK 0x3L
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -223,14 +223,14 @@ BEGIN
VALUE "Comments", "PostgreSQL ODBC driver\0"
VALUE "CompanyName", "Insight Distribution Systems\0"
VALUE "FileDescription", "PostgreSQL Driver\0"
VALUE "FileVersion", " 07.01.0001\0"
VALUE "FileVersion", " 07.01.0002\0"
VALUE "InternalName", "psqlodbc\0"
VALUE "LegalCopyright", "\0"
VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation. Microsoft® is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0"
VALUE "OriginalFilename", "psqlodbc.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "Microsoft Open Database Connectivity\0"
VALUE "ProductVersion", " 07.01.0001\0"
VALUE "ProductVersion", " 07.01.0002\0"
VALUE "SpecialBuild", "\0"
END
END