]> granicus.if.org Git - postgresql/commitdiff
Improved version handling introduced by Dave Page.
authorHiroshi Inoue <inoue@tpf.co.jp>
Tue, 6 Feb 2001 02:21:12 +0000 (02:21 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Tue, 6 Feb 2001 02:21:12 +0000 (02:21 +0000)
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>>

src/interfaces/odbc/columninfo.c
src/interfaces/odbc/connection.c
src/interfaces/odbc/connection.h
src/interfaces/odbc/drvconn.c
src/interfaces/odbc/info.c
src/interfaces/odbc/psqlodbc.h
src/interfaces/odbc/psqlodbc.rc

index fa56824011d58d0959b7f0f97574b20964b594f2..9e5223b83b39b306c98666fd0c8f2d43c50503a0 100644 (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);
index fe1344df8abad6b87ae6bda2657789b2e9cd7dc0..98fbca2f794aa4b75059257307f56b9445436d2d 100644 (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);
index 8251271a05c3ab4c19c02528aa3e8cb8fb062045..8222d98518039bbe4b73b39e6a532ffff237d870 100644 (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);
 
 
index 332ccc5cbb172aba98e04d1866b55a09666acebf..2cbe6e6a87a639be1148f75d0bcc32d2fec222b6 100644 (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:
index 681c72759d0d38d78d5029a4cf1489577c8121e2..bf43d6522b57b7e5b4f9558f67b9903021a59629 100644 (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;
     }
 
index b0d8539eb79acecb1bae83629521586e99a9e4cb..54fd4e2eeae90918ff5dac3b3381ccc62cb2df0a 100644 (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"
index 1d934106d3be53ba0860f390fff3f56d555243d1..503b478372a5a25f5120434bf9a433df0845d754 100644 (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