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>>
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);
/* 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.
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 */
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
StatementClass *stmt;
RETCODE result;
char *szVersion = "0.0";
+int major, minor;
static char *func = "CC_lookup_pg_version";
mylog( "%s: entering...\n", func);
}
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);
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);
/* 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 {
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;
};
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);
/* Fill in any default parameters if they are not there. */
getDSNdefaults(ci);
+ /* initialize pg_version */
+ CC_initialize_pg_version(conn);
#ifdef WIN32
dialog:
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;
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 */
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 */
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;
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 */
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 |
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";
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];
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
+ conn = (ConnectionClass *) (stmt->hdbc);
ci = &stmt->hdbc->connInfo;
result = SQLAllocStmt( stmt->hdbc, &htbl_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);
/* 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");
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;
}
/* 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);
char useStaticPrecision;
char not_null[MAX_INFO_STRING], relhasrules[MAX_INFO_STRING];
ConnInfo *ci;
+ConnectionClass *conn;
mylog("%s: entering...stmt=%u\n", func, stmt);
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
+ conn = (ConnectionClass *) (stmt->hdbc);
ci = &stmt->hdbc->connInfo;
/* ********************************************************************** */
" 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);
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;
}
*
* 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__
#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"
//
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
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