Commit 39dc8ff6 authored by Hiroshi Inoue's avatar Hiroshi Inoue

1) Avoid an overflow of connection string for Access(Microsoft Jet).

2) Change to retry lower version in case of "Unsupported frontend
procotol".
parent 6f33c179
......@@ -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':
......
......@@ -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;
......
......@@ -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,7 +525,8 @@ makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
encode(ci->conn_settings, encoded_conn_settings);
/* extra info */
hlen = strlen(connect_string),
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,
......@@ -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);
}
......
......@@ -96,6 +96,7 @@
#define INI_TRANSLATIONDLL "TranslationDLL"
#define INI_TRANSLATIONOPTION "TranslationOption"
#define INI_DISALLOWPREMATURE "DisallowPremature"
#define INI_UPDATABLECURSORS "UpdatableCursors"
/* Connection Defaults */
......
/*-------
* 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)
......
......@@ -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->updatable_cursors)
if (!ci->drivers.use_declarefetch)
value = SQL_CB_PRESERVE;
#endif /* DRIVER_CURSOR_IMPLEMENT */
break;
case SQL_CURSOR_ROLLBACK_BEHAVIOR: /* ODBC 1.0 */
len = 2;
value = SQL_CB_CLOSE;
#ifdef DRIVER_CURSOR_IMPLEMENT
if (ci->updatable_cursors)
if (!ci->drivers.use_declarefetch)
value = SQL_CB_PRESERVE;
#endif /* DRIVER_CURSOR_IMPLEMENT */
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 */
......
......@@ -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;
}
......
......@@ -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,19 +1349,7 @@ 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);
......@@ -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 */
/*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment