]> granicus.if.org Git - postgresql/commitdiff
1) Avoid an overflow of connection string for Access(Microsoft Jet).
authorHiroshi Inoue <inoue@tpf.co.jp>
Fri, 21 Sep 2001 07:51:52 +0000 (07:51 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Fri, 21 Sep 2001 07:51:52 +0000 (07:51 +0000)
2) Change to retry lower version in case of "Unsupported frontend
procotol".

src/interfaces/odbc/connection.c
src/interfaces/odbc/connection.h
src/interfaces/odbc/dlg_specific.c
src/interfaces/odbc/dlg_specific.h
src/interfaces/odbc/drvconn.c
src/interfaces/odbc/info.c
src/interfaces/odbc/options.c
src/interfaces/odbc/results.c

index c5d9ab6ab82896f609f4fba074f32caf99c04d7f..7dc3fde0b259c04a9a2e8bd0377b605873a10a8e 100644 (file)
@@ -252,7 +252,10 @@ CC_Constructor()
                rv->transact_status = CONN_IN_AUTOCOMMIT;               /* autocommit by default */
 
                memset(&rv->connInfo, 0, sizeof(ConnInfo));
-memcpy(&(rv->connInfo.drivers), &globals, sizeof(globals));
+#ifdef DRIVER_CURSOR_IMPLEMENT
+               rv->connInfo.updatable_cursors = 1;
+#endif /* DRIVER_CURSOR_IMPLEMENT */
+               memcpy(&(rv->connInfo.drivers), &globals, sizeof(globals));
                rv->sock = SOCK_Constructor(rv);
                if (!rv->sock)
                        return NULL;
@@ -278,6 +281,7 @@ memcpy(&(rv->connInfo.drivers), &globals, sizeof(globals));
                rv->pg_version_number = .0;
                rv->pg_version_major = 0;
                rv->pg_version_minor = 0;
+               rv->ms_jet = 0;
 #ifdef MULTIBYTE
                rv->client_encoding = NULL;
                rv->server_encoding = NULL;
@@ -586,6 +590,7 @@ CC_connect(ConnectionClass *self, char do_password)
 
                mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s', database = '%s', username = '%s', password='%s'\n", ci->dsn, ci->server, ci->port, ci->database, ci->username, ci->password);
 
+another_version_retry:
                /*
                 * If the socket was closed for some reason (like a SQLDisconnect,
                 * but no SQLFreeConnect then create a socket now.
@@ -690,6 +695,18 @@ CC_connect(ConnectionClass *self, char do_password)
                                        self->errornumber = CONN_INVALID_AUTHENTICATION;
                                        self->errormsg = msgbuffer;
                                        qlog("ERROR from backend during authentication: '%s'\n", self->errormsg);
+                                       if (strncmp(msgbuffer, "Unsupported frontend protocol", 29) == 0)
+                                       {       /* retry older version */
+                                               if (PROTOCOL_63(ci))
+                                                       strcpy(ci->protocol, PG62);
+                                               else
+                                                       strcpy(ci->protocol, PG63);
+                                               SOCK_Destructor(sock);
+                                               self->sock = (SocketClass *) 0;
+                                               CC_initialize_pg_version(self);
+                                               goto another_version_retry;
+                                       }
+                       
                                        return 0;
                                case 'R':
 
index fc77bc8a7b490b5bf95a8b809236a31c1d6d6445..fc3560d35225b6264ff7d255476361a090677fab 100644 (file)
@@ -160,6 +160,7 @@ typedef struct
        char            translation_option[SMALL_REGISTRY_LEN];
        char            focus_password;
        char            disallow_premature;
+       char            updatable_cursors;
        GLOBAL_VALUES   drivers; /* moved from driver's option */
 } ConnInfo;
 
@@ -274,6 +275,7 @@ struct ConnectionClass_
        float           pg_version_number;
        Int2            pg_version_major;
        Int2            pg_version_minor;
+       char            ms_jet;
 #ifdef MULTIBYTE
        char            *client_encoding;
        char            *server_encoding;
index aaf9432c4fe64c86493c582c50b50f07fd351c80..c02f633fdb3dec8c78415f1ac7b9bb413902c88b 100644 (file)
@@ -510,6 +510,7 @@ makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
        char            got_dsn = (ci->dsn[0] != '\0');
        char            encoded_conn_settings[LARGE_REGISTRY_LEN];
        UWORD           hlen;
+       BOOL            abbrev = (len <= 400);
 
        /* fundamental info */
        sprintf(connect_string, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;PWD=%s",
@@ -524,8 +525,9 @@ makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
        encode(ci->conn_settings, encoded_conn_settings);
 
        /* extra info */
-       hlen = strlen(connect_string),
-       sprintf(&connect_string[hlen],
+       hlen = strlen(connect_string);
+       if (!abbrev)
+               sprintf(&connect_string[hlen],
                        ";READONLY=%s;PROTOCOL=%s;FAKEOIDINDEX=%s;SHOWOIDCOLUMN=%s;ROWVERSIONING=%s;SHOWSYSTEMTABLES=%s;CONNSETTINGS=%s;FETCH=%d;SOCKET=%d;UNKNOWNSIZES=%d;MAXVARCHARSIZE=%d;MAXLONGVARCHARSIZE=%d;DEBUG=%d;COMMLOG=%d;OPTIMIZER=%d;KSQO=%d;USEDECLAREFETCH=%d;TEXTASLONGVARCHAR=%d;UNKNOWNSASLONGVARCHAR=%d;BOOLSASCHAR=%d;PARSE=%d;CANCELASFREESTMT=%d;EXTRASYSTABLEPREFIXES=%s",
                        ci->onlyread,
                        ci->protocol,
@@ -551,7 +553,7 @@ makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
                        ci->drivers.cancel_as_freestmt,
                        ci->drivers.extra_systable_prefixes);
        /* Abbrebiation is needed ? */
-       if (strlen(connect_string) >= len)
+       if (abbrev || strlen(connect_string) >= len)
                sprintf(&connect_string[hlen],
                        ";A0=%s;A1=%s;A2=%s;A3=%s;A4=%s;A5=%s;A6=%s;A7=%d;A8=%d;A9=%d;B0=%d;B1=%d;B2=%d;B3=%d;B4=%d;B5=%d;B6=%d;B7=%d;B8=%d;B9=%d;C0=%d;C1=%d;C2=%s",
                        ci->onlyread,
@@ -630,7 +632,10 @@ copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
        else if (stricmp(attribute, INI_DISALLOWPREMATURE) == 0 || stricmp(attribute, "C3") == 0)
        {
                ci->disallow_premature = atoi(value);
-               /* strcpy(ci->conn_settings, value); */
+       }
+       else if (stricmp(attribute, INI_UPDATABLECURSORS) == 0 || stricmp(attribute, "C4") == 0)
+       {
+               ci->updatable_cursors = atoi(value);
        }
 
        mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s',conn_settings='%s',disallow_premature=%d)\n", ci->dsn, ci->server, ci->database, ci->username, ci->password, ci->port, ci->onlyread, ci->protocol, ci->conn_settings, ci->disallow_premature);
@@ -803,6 +808,12 @@ getDSNinfo(ConnInfo *ci, char overwrite)
                ci->disallow_premature = atoi(temp);
        }
 
+       if (ci->updatable_cursors == 0 || overwrite)
+       {
+               SQLGetPrivateProfileString(DSN, INI_UPDATABLECURSORS, "", temp, sizeof(temp), ODBC_INI);
+               ci->updatable_cursors = atoi(temp);
+       }
+
        /* Allow override of odbcinst.ini parameters here */
        getCommonDefaults(DSN, ODBC_INI, ci);
 
@@ -916,6 +927,11 @@ writeDSNinfo(const ConnInfo *ci)
                                                                 INI_DISALLOWPREMATURE,
                                                                 temp,
                                                                 ODBC_INI);
+       sprintf(temp, "%d", ci->updatable_cursors); 
+       SQLWritePrivateProfileString(DSN,
+                                                                INI_UPDATABLECURSORS,
+                                                                temp,
+                                                                ODBC_INI);
 }
 
 
index 8d37eb8a91a1faa9e75608853fe02fcf983f2460..6fc04ad2fb966b8b1ab8a955bf535767d1e8923b 100644 (file)
@@ -96,6 +96,7 @@
 #define INI_TRANSLATIONDLL                             "TranslationDLL"
 #define INI_TRANSLATIONOPTION                  "TranslationOption"
 #define INI_DISALLOWPREMATURE                  "DisallowPremature"
+#define INI_UPDATABLECURSORS                   "UpdatableCursors"
 
 
 /*     Connection Defaults */
index 80f1d69b7d649602581ab4dfd68899cb2e7816bf..781bdd54903eb16f4175912a944d9757dc3f5006 100644 (file)
@@ -1,5 +1,5 @@
 /*-------
* Module:                     drvconn.c
 Module:                      drvconn.c
  *
  * Description:                This module contains only routines related to
  *                                     implementing SQLDriverConnect.
@@ -88,6 +88,7 @@ PGAPI_DriverConnect(
        int                     retval;
        char            password_required = FALSE;
        int                     len = 0;
+       SWORD           lenStrout;
 
 
        mylog("%s: entering...\n", func);
@@ -211,7 +212,10 @@ dialog:
         */
        result = SQL_SUCCESS;
 
-       makeConnectString(connStrOut, ci, cbConnStrOutMax);
+       lenStrout = cbConnStrOutMax;
+       if (conn->ms_jet && lenStrout > 255)
+               lenStrout = 255; 
+       makeConnectString(connStrOut, ci, lenStrout);
        len = strlen(connStrOut);
 
        if (szConnStrOut)
index 431a9b1d14017c3f96153bed2e8810c27d2a5e99..6ff0d0b12e47482a5a67dd5a5cd4a88845771a09 100644 (file)
@@ -166,19 +166,17 @@ PGAPI_GetInfo(
                case SQL_CURSOR_COMMIT_BEHAVIOR:                /* ODBC 1.0 */
                        len = 2;
                        value = SQL_CB_CLOSE;
-#ifdef DRIVER_CURSOR_IMPLEMENT
-                       if (!ci->drivers.use_declarefetch)
-                               value = SQL_CB_PRESERVE;
-#endif /* DRIVER_CURSOR_IMPLEMENT */
+                       if (ci->updatable_cursors)
+                               if (!ci->drivers.use_declarefetch)
+                                       value = SQL_CB_PRESERVE;
                        break;
 
                case SQL_CURSOR_ROLLBACK_BEHAVIOR:              /* ODBC 1.0 */
                        len = 2;
                        value = SQL_CB_CLOSE;
-#ifdef DRIVER_CURSOR_IMPLEMENT
-                       if (!ci->drivers.use_declarefetch)
-                               value = SQL_CB_PRESERVE;
-#endif /* DRIVER_CURSOR_IMPLEMENT */
+                       if (ci->updatable_cursors)
+                               if (!ci->drivers.use_declarefetch)
+                                       value = SQL_CB_PRESERVE;
                        break;
 
                case SQL_DATA_SOURCE_NAME:              /* ODBC 1.0 */
@@ -235,7 +233,7 @@ PGAPI_GetInfo(
                                if (dver[0])
                                {
                                        int     major, minor;
-                                       mylog("REIGISTRY_ODBC_VER = %s\n", dver)
+                                       mylog("REGISTRY_ODBC_VER = %s\n", dver)
 ;
                                        if (sscanf(dver, "%x.%x", &major, &minor) >= 2)
                                        {
@@ -524,6 +522,8 @@ PGAPI_GetInfo(
                case SQL_POS_OPERATIONS:                /* ODBC 2.0 */
                        len = 4;
                        value = ci->drivers.lie ? (SQL_POS_POSITION | SQL_POS_REFRESH | SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD) : (SQL_POS_POSITION | SQL_POS_REFRESH);
+                       if (ci->updatable_cursors)
+                               value |= (SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD);
                        break;
 
                case SQL_POSITIONED_STATEMENTS: /* ODBC 2.0 */
@@ -571,7 +571,7 @@ PGAPI_GetInfo(
                         * Driver doesn't support keyset-driven or mixed cursors, so
                         * not much point in saying row updates are supported
                         */
-                       p = ci->drivers.lie ? "Y" : "N";
+                       p = (ci->drivers.lie || ci->updatable_cursors) ? "Y" : "N";
                        break;
 
                case SQL_SCROLL_CONCURRENCY:    /* ODBC 1.0 */
@@ -579,7 +579,10 @@ PGAPI_GetInfo(
                        value = ci->drivers.lie ? (SQL_SCCO_READ_ONLY |
                                                                   SQL_SCCO_LOCK |
                                                                   SQL_SCCO_OPT_ROWVER |
-                                                        SQL_SCCO_OPT_VALUES) : (SQL_SCCO_READ_ONLY);
+                                                        SQL_SCCO_OPT_VALUES) :
+ (SQL_SCCO_READ_ONLY);
+                       if (ci->updatable_cursors)
+                               value |= SQL_SCCO_OPT_ROWVER;
                        break;
 
                case SQL_SCROLL_OPTIONS:                /* ODBC 1.0 */
@@ -588,7 +591,10 @@ PGAPI_GetInfo(
                                                                   SQL_SO_STATIC |
                                                                   SQL_SO_KEYSET_DRIVEN |
                                                                   SQL_SO_DYNAMIC |
-                                                                  SQL_SO_MIXED) : (ci->drivers.use_declarefetch ? SQL_SO_FORWARD_ONLY : (SQL_SO_FORWARD_ONLY | SQL_SO_STATIC));
+                                                                  SQL_SO_MIXED)
+ : (ci->drivers.use_declarefetch ? SQL_SO_FORWARD_ONLY : (SQL_SO_FORWARD_ONLY | SQL_SO_STATIC));
+                       if (ci->updatable_cursors)
+                               value |= 0; /* SQL_SO_KEYSET_DRIVEN in the furure */
                        break;
 
                case SQL_SEARCH_PATTERN_ESCAPE: /* ODBC 1.0 */
@@ -606,6 +612,8 @@ PGAPI_GetInfo(
                case SQL_STATIC_SENSITIVITY:    /* ODBC 2.0 */
                        len = 4;
                        value = ci->drivers.lie ? (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES) : 0;
+                       if (ci->updatable_cursors)
+                               value |= (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES);
                        break;
 
                case SQL_STRING_FUNCTIONS:              /* ODBC 1.0 */
index aa18bb1615c62faf03ecfef9de1ef08f6460e4d4..a9a0a287fbd350046bf3a3a436de7a5ee2db97c8 100644 (file)
@@ -412,6 +412,15 @@ PGAPI_SetConnectOption(
                                conn->errormsg = "Unknown connect option (Set)";
                                conn->errornumber = CONN_UNSUPPORTED_OPTION;
                                sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
+                               if (fOption == 30002 && vParam)
+                               {
+                                       if (strcmp((char *) vParam, "Microsoft Jet") == 0)
+                                       {
+                                               conn->errornumber = 0;
+                                               conn->ms_jet = 1;
+                                               return SQL_SUCCESS;
+                                       }
+                               }
                                CC_log_error(func, option, conn);
                                return SQL_ERROR;
                        }
index 3cfe5fb74b147eda27792391f23fae5775bec20c..2475eeef9e3b0be7632a7487f743adb61de02f82 100644 (file)
@@ -164,12 +164,12 @@ PGAPI_NumResultCols(
                }
 
                *pccol = QR_NumResultCols(result);
-#ifdef DRIVER_CURSOR_IMPLEMENT
-               if (stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)
+               /* updatable cursors */
+               if (ci->updatable_cursors &&
+                   stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)
                {
                        *pccol -= 2;
                }
-#endif /* DRIVER_CURSOR_IMPLEMENT */
        }
 
        return SQL_SUCCESS;
@@ -1224,13 +1224,46 @@ PGAPI_MoreResults(
 
 
 #ifdef DRIVER_CURSOR_IMPLEMENT
+/*
+ *     Stuff for updatable cursors. 
+ */
+static QResultClass *
+positioned_load(StatementClass *stmt, BOOL latest, int res_cols, UInt4 oid, const char *tidval)
+{
+       int     i;
+       QResultClass    *qres;
+       char    selstr[4096];
+
+       sprintf(selstr, "select");
+       for (i = 0; i < res_cols; i++)
+               sprintf(selstr, "%s \"%s\",", selstr, stmt->fi[i]->name);
+       sprintf(selstr, "%s CTID, OID from \"%s\" where", selstr, stmt->ti[0]->name);
+       if (tidval)
+       {
+               if (latest)
+                       sprintf(selstr, "%s ctid = currtid2('%s', '%s') and",
+                               selstr, stmt->ti[0]->name, tidval);
+               else
+                       sprintf(selstr, "%s ctid = '%s' and", selstr, tidval);
+       }
+       sprintf(selstr, "%s oid = %u", selstr, oid), 
+       mylog("selstr=%s\n", selstr);
+       qres = CC_send_query(SC_get_conn(stmt), selstr, NULL);
+       if (qres && QR_aborted(qres))
+       {
+               QR_Destructor(qres);
+               qres = (QResultClass *) 0;
+       }
+       return qres;
+}
+
 RETCODE SQL_API
 SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
 {
        int     i, res_cols;
        UWORD   rcnt, global_ridx;
+       UInt4   oid;
        QResultClass    *res, *qres;
-       char    selstr[4096];
        RETCODE ret = SQL_ERROR;
        char    *tidval, *oidval;
 
@@ -1247,22 +1280,16 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
                stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
                return SQL_ERROR;
        }
-       strcpy(selstr, "select");
        global_ridx = irow + stmt->rowset_start;
        res_cols = QR_NumResultCols(res);
        if (!(oidval = QR_get_value_backend_row(res, global_ridx, res_cols - 1)))
        {
                return SQL_SUCCESS_WITH_INFO;
-       } 
+       }
+       sscanf(oidval, "%u", &oid); 
        tidval = QR_get_value_backend_row(res, global_ridx, res_cols - 2);
        res_cols -= 2;
-       for (i = 0; i < res_cols; i++)
-               sprintf(selstr, "%s \"%s\",", selstr, stmt->fi[i]->name);
-       sprintf(selstr, "%s CTID, OID from \"%s\" where ctid = currtid2('%s', '%s') and oid = %s",
-               selstr, stmt->ti[0]->name, stmt->ti[0]->name, tidval, oidval), 
-       mylog("selstr=%s\n", selstr);
-       qres = CC_send_query(SC_get_conn(stmt), selstr, NULL);
-       if (qres && QR_command_successful(qres))
+       if (qres = positioned_load(stmt, TRUE, res_cols, oid, tidval), qres)
        {
                TupleField      *tupleo, *tuplen;
 
@@ -1296,22 +1323,20 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
                                tupleo[res_cols + 1].len = 0;
                        }
                }
+               QR_Destructor(qres);
        }
        else if (stmt->errornumber == 0)
                stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
-       if (qres)
-               QR_Destructor(qres);
        if (count)
                *count = rcnt;
        return ret;
 }
 
 RETCODE SQL_API
-SC_pos_newload(StatementClass *stmt, Int4 oid, const char *tidval)
+SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
 {
-       int     i, res_cols;
+       int     i;
        QResultClass    *res, *qres;
-       char    selstr[4096];
        RETCODE ret = SQL_ERROR;
 
        mylog("positioned new fi=%x ti=%x\n", stmt->fi, stmt->ti);
@@ -1324,20 +1349,8 @@ SC_pos_newload(StatementClass *stmt, Int4 oid, const char *tidval)
                stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
                return SQL_ERROR;
        }
-       sprintf(selstr, "select");
-       res_cols = QR_NumResultCols(res);
-       res_cols -= 2;
-       for (i = 0; i < res_cols; i++)
-               sprintf(selstr, "%s \"%s\",", selstr, stmt->fi[i]->name);
-       sprintf(selstr, "%s CTID, OID from \"%s\" where", selstr, stmt->ti[0]->name);
-       if (tidval)
-               sprintf(selstr, "%s ctid = currtid2('%s', '%s') and",
-                       selstr, stmt->ti[0]->name, tidval);
-       sprintf(selstr, "%s oid = %u", selstr, oid), 
-       mylog("selstr=%s\n", selstr);
-       qres = CC_send_query(SC_get_conn(stmt), selstr, NULL);
-       if (qres && QR_command_successful(qres))
-       {
+       if (qres = positioned_load(stmt, TRUE, QR_NumResultCols(res) - 2, oid, tidval), qres)
+       { 
                TupleField      *tupleo, *tuplen;
                int     count = QR_get_num_tuples(qres);
                QR_set_position(qres, 0);
@@ -1380,10 +1393,9 @@ SC_pos_newload(StatementClass *stmt, Int4 oid, const char *tidval)
                        stmt->errormsg = "the content was changed before updation";
                        ret = SQL_SUCCESS_WITH_INFO;
                }
+               QR_Destructor(qres);
                /*stmt->currTuple = stmt->rowset_start + irow;*/
        }
-       if (qres)
-               QR_Destructor(qres);
        return ret;
 }
 
@@ -1666,7 +1678,7 @@ SC_pos_add(StatementClass *stmt,
                else
                {
                        int     addcnt;
-                       Int4    oid;
+                       UInt4   oid;
                        const char *cmdstr = QR_get_command(qstmt->result);
                        if (cmdstr &&
                            sscanf(cmdstr, "INSERT %u %d", &oid, &addcnt) == 2 &&
@@ -1696,6 +1708,9 @@ SC_pos_add(StatementClass *stmt,
        PGAPI_FreeStmt(hstmt, SQL_DROP);
        return ret;
 }
+/*
+ *     Stuff for updatable cursors end. 
+ */
 #endif /* DRIVER_CURSOR_IMPLEMENT */
 
 /*