diff --git a/src/interfaces/odbc/columninfo.c b/src/interfaces/odbc/columninfo.c index fa56824011d58d0959b7f0f97574b20964b594f2..9e5223b83b39b306c98666fd0c8f2d43c50503a0 100644 --- a/src/interfaces/odbc/columninfo.c +++ b/src/interfaces/odbc/columninfo.c @@ -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); diff --git a/src/interfaces/odbc/connection.c b/src/interfaces/odbc/connection.c index fe1344df8abad6b87ae6bda2657789b2e9cd7dc0..98fbca2f794aa4b75059257307f56b9445436d2d 100644 --- a/src/interfaces/odbc/connection.c +++ b/src/interfaces/odbc/connection.c @@ -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); diff --git a/src/interfaces/odbc/connection.h b/src/interfaces/odbc/connection.h index 8251271a05c3ab4c19c02528aa3e8cb8fb062045..8222d98518039bbe4b73b39e6a532ffff237d870 100644 --- a/src/interfaces/odbc/connection.h +++ b/src/interfaces/odbc/connection.h @@ -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); diff --git a/src/interfaces/odbc/drvconn.c b/src/interfaces/odbc/drvconn.c index 332ccc5cbb172aba98e04d1866b55a09666acebf..2cbe6e6a87a639be1148f75d0bcc32d2fec222b6 100644 --- a/src/interfaces/odbc/drvconn.c +++ b/src/interfaces/odbc/drvconn.c @@ -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: diff --git a/src/interfaces/odbc/info.c b/src/interfaces/odbc/info.c index 681c72759d0d38d78d5029a4cf1489577c8121e2..bf43d6522b57b7e5b4f9558f67b9903021a59629 100644 --- a/src/interfaces/odbc/info.c +++ b/src/interfaces/odbc/info.c @@ -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; } diff --git a/src/interfaces/odbc/psqlodbc.h b/src/interfaces/odbc/psqlodbc.h index b0d8539eb79acecb1bae83629521586e99a9e4cb..54fd4e2eeae90918ff5dac3b3381ccc62cb2df0a 100644 --- a/src/interfaces/odbc/psqlodbc.h +++ b/src/interfaces/odbc/psqlodbc.h @@ -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" diff --git a/src/interfaces/odbc/psqlodbc.rc b/src/interfaces/odbc/psqlodbc.rc index 1d934106d3be53ba0860f390fff3f56d555243d1..503b478372a5a25f5120434bf9a433df0845d754 100644 --- a/src/interfaces/odbc/psqlodbc.rc +++ b/src/interfaces/odbc/psqlodbc.rc @@ -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