1) Avoid an overflow of connection string for Access(Microsoft Jet).
2) Change to retry lower version in case of "Unsupported frontend procotol".
This commit is contained in:
parent
6f33c179b9
commit
39dc8ff64f
@ -252,7 +252,10 @@ CC_Constructor()
|
|||||||
rv->transact_status = CONN_IN_AUTOCOMMIT; /* autocommit by default */
|
rv->transact_status = CONN_IN_AUTOCOMMIT; /* autocommit by default */
|
||||||
|
|
||||||
memset(&rv->connInfo, 0, sizeof(ConnInfo));
|
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);
|
rv->sock = SOCK_Constructor(rv);
|
||||||
if (!rv->sock)
|
if (!rv->sock)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -278,6 +281,7 @@ memcpy(&(rv->connInfo.drivers), &globals, sizeof(globals));
|
|||||||
rv->pg_version_number = .0;
|
rv->pg_version_number = .0;
|
||||||
rv->pg_version_major = 0;
|
rv->pg_version_major = 0;
|
||||||
rv->pg_version_minor = 0;
|
rv->pg_version_minor = 0;
|
||||||
|
rv->ms_jet = 0;
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
rv->client_encoding = NULL;
|
rv->client_encoding = NULL;
|
||||||
rv->server_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);
|
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,
|
* If the socket was closed for some reason (like a SQLDisconnect,
|
||||||
* but no SQLFreeConnect then create a socket now.
|
* 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->errornumber = CONN_INVALID_AUTHENTICATION;
|
||||||
self->errormsg = msgbuffer;
|
self->errormsg = msgbuffer;
|
||||||
qlog("ERROR from backend during authentication: '%s'\n", self->errormsg);
|
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;
|
return 0;
|
||||||
case 'R':
|
case 'R':
|
||||||
|
|
||||||
|
@ -160,6 +160,7 @@ typedef struct
|
|||||||
char translation_option[SMALL_REGISTRY_LEN];
|
char translation_option[SMALL_REGISTRY_LEN];
|
||||||
char focus_password;
|
char focus_password;
|
||||||
char disallow_premature;
|
char disallow_premature;
|
||||||
|
char updatable_cursors;
|
||||||
GLOBAL_VALUES drivers; /* moved from driver's option */
|
GLOBAL_VALUES drivers; /* moved from driver's option */
|
||||||
} ConnInfo;
|
} ConnInfo;
|
||||||
|
|
||||||
@ -274,6 +275,7 @@ struct ConnectionClass_
|
|||||||
float pg_version_number;
|
float pg_version_number;
|
||||||
Int2 pg_version_major;
|
Int2 pg_version_major;
|
||||||
Int2 pg_version_minor;
|
Int2 pg_version_minor;
|
||||||
|
char ms_jet;
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
char *client_encoding;
|
char *client_encoding;
|
||||||
char *server_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 got_dsn = (ci->dsn[0] != '\0');
|
||||||
char encoded_conn_settings[LARGE_REGISTRY_LEN];
|
char encoded_conn_settings[LARGE_REGISTRY_LEN];
|
||||||
UWORD hlen;
|
UWORD hlen;
|
||||||
|
BOOL abbrev = (len <= 400);
|
||||||
|
|
||||||
/* fundamental info */
|
/* fundamental info */
|
||||||
sprintf(connect_string, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;PWD=%s",
|
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);
|
encode(ci->conn_settings, encoded_conn_settings);
|
||||||
|
|
||||||
/* extra info */
|
/* extra info */
|
||||||
hlen = strlen(connect_string),
|
hlen = strlen(connect_string);
|
||||||
sprintf(&connect_string[hlen],
|
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",
|
";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->onlyread,
|
||||||
ci->protocol,
|
ci->protocol,
|
||||||
@ -551,7 +553,7 @@ makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
|
|||||||
ci->drivers.cancel_as_freestmt,
|
ci->drivers.cancel_as_freestmt,
|
||||||
ci->drivers.extra_systable_prefixes);
|
ci->drivers.extra_systable_prefixes);
|
||||||
/* Abbrebiation is needed ? */
|
/* Abbrebiation is needed ? */
|
||||||
if (strlen(connect_string) >= len)
|
if (abbrev || strlen(connect_string) >= len)
|
||||||
sprintf(&connect_string[hlen],
|
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",
|
";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,
|
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)
|
else if (stricmp(attribute, INI_DISALLOWPREMATURE) == 0 || stricmp(attribute, "C3") == 0)
|
||||||
{
|
{
|
||||||
ci->disallow_premature = atoi(value);
|
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);
|
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);
|
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 */
|
/* Allow override of odbcinst.ini parameters here */
|
||||||
getCommonDefaults(DSN, ODBC_INI, ci);
|
getCommonDefaults(DSN, ODBC_INI, ci);
|
||||||
|
|
||||||
@ -916,6 +927,11 @@ writeDSNinfo(const ConnInfo *ci)
|
|||||||
INI_DISALLOWPREMATURE,
|
INI_DISALLOWPREMATURE,
|
||||||
temp,
|
temp,
|
||||||
ODBC_INI);
|
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_TRANSLATIONDLL "TranslationDLL"
|
||||||
#define INI_TRANSLATIONOPTION "TranslationOption"
|
#define INI_TRANSLATIONOPTION "TranslationOption"
|
||||||
#define INI_DISALLOWPREMATURE "DisallowPremature"
|
#define INI_DISALLOWPREMATURE "DisallowPremature"
|
||||||
|
#define INI_UPDATABLECURSORS "UpdatableCursors"
|
||||||
|
|
||||||
|
|
||||||
/* Connection Defaults */
|
/* Connection Defaults */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*-------
|
/*-------
|
||||||
* Module: drvconn.c
|
Module: drvconn.c
|
||||||
*
|
*
|
||||||
* Description: This module contains only routines related to
|
* Description: This module contains only routines related to
|
||||||
* implementing SQLDriverConnect.
|
* implementing SQLDriverConnect.
|
||||||
@ -88,6 +88,7 @@ PGAPI_DriverConnect(
|
|||||||
int retval;
|
int retval;
|
||||||
char password_required = FALSE;
|
char password_required = FALSE;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
SWORD lenStrout;
|
||||||
|
|
||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
@ -211,7 +212,10 @@ dialog:
|
|||||||
*/
|
*/
|
||||||
result = SQL_SUCCESS;
|
result = SQL_SUCCESS;
|
||||||
|
|
||||||
makeConnectString(connStrOut, ci, cbConnStrOutMax);
|
lenStrout = cbConnStrOutMax;
|
||||||
|
if (conn->ms_jet && lenStrout > 255)
|
||||||
|
lenStrout = 255;
|
||||||
|
makeConnectString(connStrOut, ci, lenStrout);
|
||||||
len = strlen(connStrOut);
|
len = strlen(connStrOut);
|
||||||
|
|
||||||
if (szConnStrOut)
|
if (szConnStrOut)
|
||||||
|
@ -166,19 +166,17 @@ PGAPI_GetInfo(
|
|||||||
case SQL_CURSOR_COMMIT_BEHAVIOR: /* ODBC 1.0 */
|
case SQL_CURSOR_COMMIT_BEHAVIOR: /* ODBC 1.0 */
|
||||||
len = 2;
|
len = 2;
|
||||||
value = SQL_CB_CLOSE;
|
value = SQL_CB_CLOSE;
|
||||||
#ifdef DRIVER_CURSOR_IMPLEMENT
|
if (ci->updatable_cursors)
|
||||||
if (!ci->drivers.use_declarefetch)
|
if (!ci->drivers.use_declarefetch)
|
||||||
value = SQL_CB_PRESERVE;
|
value = SQL_CB_PRESERVE;
|
||||||
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_CURSOR_ROLLBACK_BEHAVIOR: /* ODBC 1.0 */
|
case SQL_CURSOR_ROLLBACK_BEHAVIOR: /* ODBC 1.0 */
|
||||||
len = 2;
|
len = 2;
|
||||||
value = SQL_CB_CLOSE;
|
value = SQL_CB_CLOSE;
|
||||||
#ifdef DRIVER_CURSOR_IMPLEMENT
|
if (ci->updatable_cursors)
|
||||||
if (!ci->drivers.use_declarefetch)
|
if (!ci->drivers.use_declarefetch)
|
||||||
value = SQL_CB_PRESERVE;
|
value = SQL_CB_PRESERVE;
|
||||||
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_DATA_SOURCE_NAME: /* ODBC 1.0 */
|
case SQL_DATA_SOURCE_NAME: /* ODBC 1.0 */
|
||||||
@ -235,7 +233,7 @@ PGAPI_GetInfo(
|
|||||||
if (dver[0])
|
if (dver[0])
|
||||||
{
|
{
|
||||||
int major, minor;
|
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)
|
if (sscanf(dver, "%x.%x", &major, &minor) >= 2)
|
||||||
{
|
{
|
||||||
@ -524,6 +522,8 @@ PGAPI_GetInfo(
|
|||||||
case SQL_POS_OPERATIONS: /* ODBC 2.0 */
|
case SQL_POS_OPERATIONS: /* ODBC 2.0 */
|
||||||
len = 4;
|
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);
|
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;
|
break;
|
||||||
|
|
||||||
case SQL_POSITIONED_STATEMENTS: /* ODBC 2.0 */
|
case SQL_POSITIONED_STATEMENTS: /* ODBC 2.0 */
|
||||||
@ -571,7 +571,7 @@ PGAPI_GetInfo(
|
|||||||
* Driver doesn't support keyset-driven or mixed cursors, so
|
* Driver doesn't support keyset-driven or mixed cursors, so
|
||||||
* not much point in saying row updates are supported
|
* 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;
|
break;
|
||||||
|
|
||||||
case SQL_SCROLL_CONCURRENCY: /* ODBC 1.0 */
|
case SQL_SCROLL_CONCURRENCY: /* ODBC 1.0 */
|
||||||
@ -579,7 +579,10 @@ PGAPI_GetInfo(
|
|||||||
value = ci->drivers.lie ? (SQL_SCCO_READ_ONLY |
|
value = ci->drivers.lie ? (SQL_SCCO_READ_ONLY |
|
||||||
SQL_SCCO_LOCK |
|
SQL_SCCO_LOCK |
|
||||||
SQL_SCCO_OPT_ROWVER |
|
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;
|
break;
|
||||||
|
|
||||||
case SQL_SCROLL_OPTIONS: /* ODBC 1.0 */
|
case SQL_SCROLL_OPTIONS: /* ODBC 1.0 */
|
||||||
@ -588,7 +591,10 @@ PGAPI_GetInfo(
|
|||||||
SQL_SO_STATIC |
|
SQL_SO_STATIC |
|
||||||
SQL_SO_KEYSET_DRIVEN |
|
SQL_SO_KEYSET_DRIVEN |
|
||||||
SQL_SO_DYNAMIC |
|
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;
|
break;
|
||||||
|
|
||||||
case SQL_SEARCH_PATTERN_ESCAPE: /* ODBC 1.0 */
|
case SQL_SEARCH_PATTERN_ESCAPE: /* ODBC 1.0 */
|
||||||
@ -606,6 +612,8 @@ PGAPI_GetInfo(
|
|||||||
case SQL_STATIC_SENSITIVITY: /* ODBC 2.0 */
|
case SQL_STATIC_SENSITIVITY: /* ODBC 2.0 */
|
||||||
len = 4;
|
len = 4;
|
||||||
value = ci->drivers.lie ? (SQL_SS_ADDITIONS | SQL_SS_DELETIONS | SQL_SS_UPDATES) : 0;
|
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;
|
break;
|
||||||
|
|
||||||
case SQL_STRING_FUNCTIONS: /* ODBC 1.0 */
|
case SQL_STRING_FUNCTIONS: /* ODBC 1.0 */
|
||||||
|
@ -412,6 +412,15 @@ PGAPI_SetConnectOption(
|
|||||||
conn->errormsg = "Unknown connect option (Set)";
|
conn->errormsg = "Unknown connect option (Set)";
|
||||||
conn->errornumber = CONN_UNSUPPORTED_OPTION;
|
conn->errornumber = CONN_UNSUPPORTED_OPTION;
|
||||||
sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
|
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);
|
CC_log_error(func, option, conn);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -164,12 +164,12 @@ PGAPI_NumResultCols(
|
|||||||
}
|
}
|
||||||
|
|
||||||
*pccol = QR_NumResultCols(result);
|
*pccol = QR_NumResultCols(result);
|
||||||
#ifdef DRIVER_CURSOR_IMPLEMENT
|
/* updatable cursors */
|
||||||
if (stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)
|
if (ci->updatable_cursors &&
|
||||||
|
stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)
|
||||||
{
|
{
|
||||||
*pccol -= 2;
|
*pccol -= 2;
|
||||||
}
|
}
|
||||||
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
@ -1224,13 +1224,46 @@ PGAPI_MoreResults(
|
|||||||
|
|
||||||
|
|
||||||
#ifdef DRIVER_CURSOR_IMPLEMENT
|
#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
|
RETCODE SQL_API
|
||||||
SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
|
SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
|
||||||
{
|
{
|
||||||
int i, res_cols;
|
int i, res_cols;
|
||||||
UWORD rcnt, global_ridx;
|
UWORD rcnt, global_ridx;
|
||||||
|
UInt4 oid;
|
||||||
QResultClass *res, *qres;
|
QResultClass *res, *qres;
|
||||||
char selstr[4096];
|
|
||||||
RETCODE ret = SQL_ERROR;
|
RETCODE ret = SQL_ERROR;
|
||||||
char *tidval, *oidval;
|
char *tidval, *oidval;
|
||||||
|
|
||||||
@ -1247,22 +1280,16 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
|
|||||||
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
|
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
strcpy(selstr, "select");
|
|
||||||
global_ridx = irow + stmt->rowset_start;
|
global_ridx = irow + stmt->rowset_start;
|
||||||
res_cols = QR_NumResultCols(res);
|
res_cols = QR_NumResultCols(res);
|
||||||
if (!(oidval = QR_get_value_backend_row(res, global_ridx, res_cols - 1)))
|
if (!(oidval = QR_get_value_backend_row(res, global_ridx, res_cols - 1)))
|
||||||
{
|
{
|
||||||
return SQL_SUCCESS_WITH_INFO;
|
return SQL_SUCCESS_WITH_INFO;
|
||||||
}
|
}
|
||||||
|
sscanf(oidval, "%u", &oid);
|
||||||
tidval = QR_get_value_backend_row(res, global_ridx, res_cols - 2);
|
tidval = QR_get_value_backend_row(res, global_ridx, res_cols - 2);
|
||||||
res_cols -= 2;
|
res_cols -= 2;
|
||||||
for (i = 0; i < res_cols; i++)
|
if (qres = positioned_load(stmt, TRUE, res_cols, oid, tidval), qres)
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
TupleField *tupleo, *tuplen;
|
TupleField *tupleo, *tuplen;
|
||||||
|
|
||||||
@ -1296,22 +1323,20 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
|
|||||||
tupleo[res_cols + 1].len = 0;
|
tupleo[res_cols + 1].len = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
QR_Destructor(qres);
|
||||||
}
|
}
|
||||||
else if (stmt->errornumber == 0)
|
else if (stmt->errornumber == 0)
|
||||||
stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
|
stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
|
||||||
if (qres)
|
|
||||||
QR_Destructor(qres);
|
|
||||||
if (count)
|
if (count)
|
||||||
*count = rcnt;
|
*count = rcnt;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
RETCODE SQL_API
|
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;
|
QResultClass *res, *qres;
|
||||||
char selstr[4096];
|
|
||||||
RETCODE ret = SQL_ERROR;
|
RETCODE ret = SQL_ERROR;
|
||||||
|
|
||||||
mylog("positioned new fi=%x ti=%x\n", stmt->fi, stmt->ti);
|
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;
|
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
sprintf(selstr, "select");
|
if (qres = positioned_load(stmt, TRUE, QR_NumResultCols(res) - 2, oid, tidval), qres)
|
||||||
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))
|
|
||||||
{
|
|
||||||
TupleField *tupleo, *tuplen;
|
TupleField *tupleo, *tuplen;
|
||||||
int count = QR_get_num_tuples(qres);
|
int count = QR_get_num_tuples(qres);
|
||||||
QR_set_position(qres, 0);
|
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";
|
stmt->errormsg = "the content was changed before updation";
|
||||||
ret = SQL_SUCCESS_WITH_INFO;
|
ret = SQL_SUCCESS_WITH_INFO;
|
||||||
}
|
}
|
||||||
|
QR_Destructor(qres);
|
||||||
/*stmt->currTuple = stmt->rowset_start + irow;*/
|
/*stmt->currTuple = stmt->rowset_start + irow;*/
|
||||||
}
|
}
|
||||||
if (qres)
|
|
||||||
QR_Destructor(qres);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1666,7 +1678,7 @@ SC_pos_add(StatementClass *stmt,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
int addcnt;
|
int addcnt;
|
||||||
Int4 oid;
|
UInt4 oid;
|
||||||
const char *cmdstr = QR_get_command(qstmt->result);
|
const char *cmdstr = QR_get_command(qstmt->result);
|
||||||
if (cmdstr &&
|
if (cmdstr &&
|
||||||
sscanf(cmdstr, "INSERT %u %d", &oid, &addcnt) == 2 &&
|
sscanf(cmdstr, "INSERT %u %d", &oid, &addcnt) == 2 &&
|
||||||
@ -1696,6 +1708,9 @@ SC_pos_add(StatementClass *stmt,
|
|||||||
PGAPI_FreeStmt(hstmt, SQL_DROP);
|
PGAPI_FreeStmt(hstmt, SQL_DROP);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Stuff for updatable cursors end.
|
||||||
|
*/
|
||||||
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user