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() ...@@ -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)); ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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_ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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 */
......
/*------- /*-------
* 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( ...@@ -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: ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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 */
/* /*
......
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