mirror of
https://github.com/postgres/postgres.git
synced 2025-05-08 07:21:33 +03:00
1) Internal improvements to handle updatable cursors(1st cut).
2) Fix a bug in SQLColAttribute().
This commit is contained in:
parent
f362dcec61
commit
01e322652b
@ -374,7 +374,7 @@ CC_begin(ConnectionClass *self)
|
|||||||
char ret = TRUE;
|
char ret = TRUE;
|
||||||
if (!CC_is_in_trans(self))
|
if (!CC_is_in_trans(self))
|
||||||
{
|
{
|
||||||
QResultClass *res = CC_send_query(self, "BEGIN", NULL, TRUE);
|
QResultClass *res = CC_send_query(self, "BEGIN", NULL, CLEAR_RESULT_ON_ABORT);
|
||||||
mylog("CC_begin: sending BEGIN!\n");
|
mylog("CC_begin: sending BEGIN!\n");
|
||||||
|
|
||||||
if (res != NULL)
|
if (res != NULL)
|
||||||
@ -401,7 +401,7 @@ CC_commit(ConnectionClass *self)
|
|||||||
char ret = FALSE;
|
char ret = FALSE;
|
||||||
if (CC_is_in_trans(self))
|
if (CC_is_in_trans(self))
|
||||||
{
|
{
|
||||||
QResultClass *res = CC_send_query(self, "COMMIT", NULL, TRUE);
|
QResultClass *res = CC_send_query(self, "COMMIT", NULL, CLEAR_RESULT_ON_ABORT);
|
||||||
mylog("CC_commit: sending COMMIT!\n");
|
mylog("CC_commit: sending COMMIT!\n");
|
||||||
|
|
||||||
CC_set_no_trans(self);
|
CC_set_no_trans(self);
|
||||||
@ -427,7 +427,7 @@ CC_abort(ConnectionClass *self)
|
|||||||
{
|
{
|
||||||
if (CC_is_in_trans(self))
|
if (CC_is_in_trans(self))
|
||||||
{
|
{
|
||||||
QResultClass *res = CC_send_query(self, "ROLLBACK", NULL, TRUE);
|
QResultClass *res = CC_send_query(self, "ROLLBACK", NULL, CLEAR_RESULT_ON_ABORT);
|
||||||
mylog("CC_abort: sending ABORT!\n");
|
mylog("CC_abort: sending ABORT!\n");
|
||||||
|
|
||||||
CC_set_no_trans(self);
|
CC_set_no_trans(self);
|
||||||
@ -919,7 +919,7 @@ another_version_retry:
|
|||||||
*/
|
*/
|
||||||
mylog("sending an empty query...\n");
|
mylog("sending an empty query...\n");
|
||||||
|
|
||||||
res = CC_send_query(self, " ", NULL, TRUE);
|
res = CC_send_query(self, " ", NULL, CLEAR_RESULT_ON_ABORT);
|
||||||
if (res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY)
|
if (res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY)
|
||||||
{
|
{
|
||||||
mylog("got no result from the empty query. (probably database does not exist)\n");
|
mylog("got no result from the empty query. (probably database does not exist)\n");
|
||||||
@ -956,7 +956,7 @@ another_version_retry:
|
|||||||
* Multibyte handling is available ?
|
* Multibyte handling is available ?
|
||||||
*/
|
*/
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
if (PG_VERSION_GE(self, 7.0))
|
if (PG_VERSION_GE(self, 6.4))
|
||||||
{
|
{
|
||||||
CC_lookup_characterset(self);
|
CC_lookup_characterset(self);
|
||||||
if (self->errornumber != 0)
|
if (self->errornumber != 0)
|
||||||
@ -977,7 +977,7 @@ another_version_retry:
|
|||||||
if (self->client_encoding)
|
if (self->client_encoding)
|
||||||
free(self->client_encoding);
|
free(self->client_encoding);
|
||||||
self->client_encoding = NULL;
|
self->client_encoding = NULL;
|
||||||
if (res = CC_send_query(self, "set client_encoding to 'UTF8'", NULL, TRUE), res)
|
if (res = CC_send_query(self, "set client_encoding to 'UTF8'", NULL, CLEAR_RESULT_ON_ABORT), res)
|
||||||
{
|
{
|
||||||
self->client_encoding = strdup("UNICODE");
|
self->client_encoding = strdup("UNICODE");
|
||||||
QR_Destructor(res);
|
QR_Destructor(res);
|
||||||
@ -991,7 +991,7 @@ another_version_retry:
|
|||||||
else if (self->unicode)
|
else if (self->unicode)
|
||||||
{
|
{
|
||||||
self->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
|
self->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
|
||||||
self->errormsg = "Unicode isn't supported before 7.0";
|
self->errormsg = "Unicode isn't supported before 6.4";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* UNICODE_SUPPORT */
|
#endif /* UNICODE_SUPPORT */
|
||||||
@ -1128,12 +1128,14 @@ CC_get_error(ConnectionClass *self, int *number, char **message)
|
|||||||
* 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
|
* 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
|
||||||
*/
|
*/
|
||||||
QResultClass *
|
QResultClass *
|
||||||
CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, BOOL clear_result_on_abort)
|
CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
|
||||||
{
|
{
|
||||||
QResultClass *result_in = NULL,
|
QResultClass *result_in = NULL,
|
||||||
*cmdres = NULL,
|
*cmdres = NULL,
|
||||||
*retres = NULL,
|
*retres = NULL,
|
||||||
*res = NULL;
|
*res = NULL;
|
||||||
|
BOOL clear_result_on_abort = ((flag & CLEAR_RESULT_ON_ABORT) != 0),
|
||||||
|
create_keyset = ((flag & CREATE_KEYSET) != 0);
|
||||||
char swallow,
|
char swallow,
|
||||||
*wq;
|
*wq;
|
||||||
int id;
|
int id;
|
||||||
@ -1376,6 +1378,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, BOOL clear_resu
|
|||||||
if (query_completed)
|
if (query_completed)
|
||||||
{
|
{
|
||||||
res->next = QR_Constructor();
|
res->next = QR_Constructor();
|
||||||
|
if (create_keyset)
|
||||||
|
QR_set_haskeyset(res->next);
|
||||||
mylog("send_query: 'T' no result_in: res = %u\n", res->next);
|
mylog("send_query: 'T' no result_in: res = %u\n", res->next);
|
||||||
if (!res->next)
|
if (!res->next)
|
||||||
{
|
{
|
||||||
@ -1392,6 +1396,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, BOOL clear_resu
|
|||||||
}
|
}
|
||||||
if (!used_passed_result_object)
|
if (!used_passed_result_object)
|
||||||
{
|
{
|
||||||
|
if (create_keyset)
|
||||||
|
QR_set_haskeyset(res);
|
||||||
if (!QR_fetch_tuples(res, self, qi ? qi->cursor : NULL))
|
if (!QR_fetch_tuples(res, self, qi ? qi->cursor : NULL))
|
||||||
{
|
{
|
||||||
self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
|
self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
|
||||||
|
@ -305,7 +305,7 @@ char CC_connect(ConnectionClass *self, char do_password);
|
|||||||
char CC_add_statement(ConnectionClass *self, StatementClass *stmt);
|
char CC_add_statement(ConnectionClass *self, StatementClass *stmt);
|
||||||
char CC_remove_statement(ConnectionClass *self, StatementClass *stmt);
|
char CC_remove_statement(ConnectionClass *self, StatementClass *stmt);
|
||||||
char CC_get_error(ConnectionClass *self, int *number, char **message);
|
char CC_get_error(ConnectionClass *self, int *number, char **message);
|
||||||
QResultClass *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, BOOL);
|
QResultClass *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag);
|
||||||
void CC_clear_error(ConnectionClass *self);
|
void CC_clear_error(ConnectionClass *self);
|
||||||
char *CC_create_errormsg(ConnectionClass *self);
|
char *CC_create_errormsg(ConnectionClass *self);
|
||||||
int CC_send_function(ConnectionClass *conn, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *argv, int nargs);
|
int CC_send_function(ConnectionClass *conn, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *argv, int nargs);
|
||||||
@ -316,4 +316,7 @@ void CC_initialize_pg_version(ConnectionClass *conn);
|
|||||||
void CC_log_error(const char *func, const char *desc, const ConnectionClass *self);
|
void CC_log_error(const char *func, const char *desc, const ConnectionClass *self);
|
||||||
int CC_get_max_query_len(const ConnectionClass *self);
|
int CC_get_max_query_len(const ConnectionClass *self);
|
||||||
|
|
||||||
|
/* CC_send_query_options */
|
||||||
|
#define CLEAR_RESULT_ON_ABORT 1L
|
||||||
|
#define CREATE_KEYSET (1L << 1) /* create keyset for updatable curosrs */
|
||||||
#endif
|
#endif
|
||||||
|
@ -1291,6 +1291,7 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
#ifdef DRIVER_CURSOR_IMPLEMENT
|
#ifdef DRIVER_CURSOR_IMPLEMENT
|
||||||
BOOL search_from_pos = FALSE;
|
BOOL search_from_pos = FALSE;
|
||||||
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
||||||
|
Int4 from_pos = -1, where_pos = -1;
|
||||||
|
|
||||||
if (ci->disallow_premature)
|
if (ci->disallow_premature)
|
||||||
prepare_dummy_cursor = stmt->pre_executing;
|
prepare_dummy_cursor = stmt->pre_executing;
|
||||||
@ -1326,7 +1327,11 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
else if (!stmt->ti || stmt->ntab != 1)
|
else if (!stmt->ti || stmt->ntab != 1)
|
||||||
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
|
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
|
||||||
else
|
else
|
||||||
search_from_pos = TRUE;
|
{
|
||||||
|
/** search_from_pos = TRUE; **/
|
||||||
|
from_pos = stmt->from_pos;
|
||||||
|
where_pos = stmt->where_pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
||||||
|
|
||||||
@ -1366,9 +1371,18 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
make_encoded_str(&encstr, conn, old_statement);
|
make_encoded_str(&encstr, conn, old_statement);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (opos = 0; opos < oldstmtlen; opos++)
|
for (opos = 0; opos < oldstmtlen; opos++)
|
||||||
{
|
{
|
||||||
|
if (from_pos == (Int4) opos)
|
||||||
|
{
|
||||||
|
CVT_APPEND_STR(", CTID, OID ");
|
||||||
|
}
|
||||||
|
else if (where_pos == (Int4) opos)
|
||||||
|
{
|
||||||
|
stmt->load_statement = malloc(npos + 1);
|
||||||
|
memcpy(stmt->load_statement, new_statement, npos);
|
||||||
|
stmt->load_statement[npos] = '\0';
|
||||||
|
}
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
oldchar = encoded_byte_check(&encstr, opos);
|
oldchar = encoded_byte_check(&encstr, opos);
|
||||||
if (ENCODE_STATUS(encstr) != 0)
|
if (ENCODE_STATUS(encstr) != 0)
|
||||||
@ -2033,6 +2047,12 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
#ifdef DRIVER_CURSOR_IMPLEMENT
|
#ifdef DRIVER_CURSOR_IMPLEMENT
|
||||||
if (search_from_pos)
|
if (search_from_pos)
|
||||||
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
|
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
|
||||||
|
if (!stmt->load_statement && from_pos >=0)
|
||||||
|
{
|
||||||
|
stmt->load_statement = malloc(npos + 1);
|
||||||
|
memcpy(stmt->load_statement, new_statement, npos);
|
||||||
|
stmt->load_statement[npos] = '\0';
|
||||||
|
}
|
||||||
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
||||||
if (prepare_dummy_cursor && SC_is_pre_executable(stmt))
|
if (prepare_dummy_cursor && SC_is_pre_executable(stmt))
|
||||||
{
|
{
|
||||||
|
@ -245,6 +245,9 @@ PGAPI_StmtError( HSTMT hstmt,
|
|||||||
case STMT_INVALID_CURSOR_STATE_ERROR:
|
case STMT_INVALID_CURSOR_STATE_ERROR:
|
||||||
strcpy(szSqlState, "24000");
|
strcpy(szSqlState, "24000");
|
||||||
break;
|
break;
|
||||||
|
case STMT_ERROR_IN_ROW:
|
||||||
|
strcpy(szSqlState, "01S01");
|
||||||
|
break;
|
||||||
case STMT_OPTION_VALUE_CHANGED:
|
case STMT_OPTION_VALUE_CHANGED:
|
||||||
strcpy(szSqlState, "01S02");
|
strcpy(szSqlState, "01S02");
|
||||||
break;
|
break;
|
||||||
|
@ -94,6 +94,12 @@ PGAPI_Prepare(HSTMT hstmt,
|
|||||||
|
|
||||||
if (self->statement)
|
if (self->statement)
|
||||||
free(self->statement);
|
free(self->statement);
|
||||||
|
if (self->stmt_with_params)
|
||||||
|
free(self->stmt_with_params);
|
||||||
|
self->stmt_with_params = NULL;
|
||||||
|
if (self->load_statement)
|
||||||
|
free(self->load_statement);
|
||||||
|
self->load_statement = NULL;
|
||||||
|
|
||||||
self->statement = make_string(szSqlStr, cbSqlStr, NULL);
|
self->statement = make_string(szSqlStr, cbSqlStr, NULL);
|
||||||
if (!self->statement)
|
if (!self->statement)
|
||||||
@ -141,6 +147,12 @@ PGAPI_ExecDirect(
|
|||||||
|
|
||||||
if (stmt->statement)
|
if (stmt->statement)
|
||||||
free(stmt->statement);
|
free(stmt->statement);
|
||||||
|
if (stmt->stmt_with_params)
|
||||||
|
free(stmt->stmt_with_params);
|
||||||
|
stmt->stmt_with_params = NULL;
|
||||||
|
if (stmt->load_statement)
|
||||||
|
free(stmt->load_statement);
|
||||||
|
stmt->load_statement = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* keep a copy of the un-parametrized statement, in case they try to
|
* keep a copy of the un-parametrized statement, in case they try to
|
||||||
@ -421,7 +433,7 @@ next_param_row:
|
|||||||
BOOL in_trans = CC_is_in_trans(conn);
|
BOOL in_trans = CC_is_in_trans(conn);
|
||||||
BOOL issued_begin = FALSE,
|
BOOL issued_begin = FALSE,
|
||||||
begin_included = FALSE;
|
begin_included = FALSE;
|
||||||
QResultClass *res;
|
QResultClass *res, *curres;
|
||||||
|
|
||||||
if (strnicmp(stmt->stmt_with_params, "BEGIN;", 6) == 0)
|
if (strnicmp(stmt->stmt_with_params, "BEGIN;", 6) == 0)
|
||||||
begin_included = TRUE;
|
begin_included = TRUE;
|
||||||
@ -436,7 +448,7 @@ next_param_row:
|
|||||||
}
|
}
|
||||||
/* we are now in a transaction */
|
/* we are now in a transaction */
|
||||||
CC_set_in_trans(conn);
|
CC_set_in_trans(conn);
|
||||||
res = CC_send_query(conn, stmt->stmt_with_params, NULL, TRUE);
|
res = CC_send_query(conn, stmt->stmt_with_params, NULL, CLEAR_RESULT_ON_ABORT);
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
CC_abort(conn);
|
CC_abort(conn);
|
||||||
@ -445,6 +457,9 @@ next_param_row:
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
SC_set_Result(stmt, res);
|
SC_set_Result(stmt, res);
|
||||||
|
for (curres = res; !curres->num_fields; curres = curres->next)
|
||||||
|
;
|
||||||
|
SC_set_Curres(stmt, curres);
|
||||||
if (CC_is_in_autocommit(conn))
|
if (CC_is_in_autocommit(conn))
|
||||||
{
|
{
|
||||||
if (issued_begin)
|
if (issued_begin)
|
||||||
@ -518,7 +533,7 @@ PGAPI_Transact(
|
|||||||
{
|
{
|
||||||
mylog("PGAPI_Transact: sending on conn %d '%s'\n", conn, stmt_string);
|
mylog("PGAPI_Transact: sending on conn %d '%s'\n", conn, stmt_string);
|
||||||
|
|
||||||
res = CC_send_query(conn, stmt_string, NULL, TRUE);
|
res = CC_send_query(conn, stmt_string, NULL, CLEAR_RESULT_ON_ABORT);
|
||||||
CC_set_no_trans(conn);
|
CC_set_no_trans(conn);
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
|
@ -2858,7 +2858,7 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
|
|||||||
return ret;
|
return ret;
|
||||||
if (!conn->server_encoding)
|
if (!conn->server_encoding)
|
||||||
{
|
{
|
||||||
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, TRUE), res)
|
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, CLEAR_RESULT_ON_ABORT), res)
|
||||||
{
|
{
|
||||||
if (QR_get_num_tuples(res) > 0)
|
if (QR_get_num_tuples(res) > 0)
|
||||||
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
|
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
|
||||||
@ -2868,11 +2868,11 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
|
|||||||
if (!conn->server_encoding)
|
if (!conn->server_encoding)
|
||||||
return ret;
|
return ret;
|
||||||
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
|
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
|
||||||
bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
|
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
|
||||||
if (!bError && continueExec)
|
if (!bError && continueExec)
|
||||||
{
|
{
|
||||||
sprintf(query, "select OID from pg_class where relname = '%s'", serverTableName);
|
sprintf(query, "select OID from pg_class where relname = '%s'", serverTableName);
|
||||||
if (res = CC_send_query(conn, query, NULL, TRUE), res)
|
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
|
||||||
{
|
{
|
||||||
if (QR_get_num_tuples(res) > 0)
|
if (QR_get_num_tuples(res) > 0)
|
||||||
strcpy(saveoid, QR_get_value_backend_row(res, 0, 0));
|
strcpy(saveoid, QR_get_value_backend_row(res, 0, 0));
|
||||||
@ -2891,11 +2891,11 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
|
|||||||
}
|
}
|
||||||
/* restore the client encoding */
|
/* restore the client encoding */
|
||||||
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
|
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
|
||||||
bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
|
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
|
||||||
if (bError || !continueExec)
|
if (bError || !continueExec)
|
||||||
return ret;
|
return ret;
|
||||||
sprintf(query, "select relname from pg_class where OID = %s", saveoid);
|
sprintf(query, "select relname from pg_class where OID = %s", saveoid);
|
||||||
if (res = CC_send_query(conn, query, NULL, TRUE), res)
|
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
|
||||||
{
|
{
|
||||||
if (QR_get_num_tuples(res) > 0)
|
if (QR_get_num_tuples(res) > 0)
|
||||||
{
|
{
|
||||||
@ -2922,7 +2922,7 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
|
|||||||
return ret;
|
return ret;
|
||||||
if (!conn->server_encoding)
|
if (!conn->server_encoding)
|
||||||
{
|
{
|
||||||
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, TRUE), res)
|
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, CLEAR_RESULT_ON_ABORT), res)
|
||||||
{
|
{
|
||||||
if (QR_get_num_tuples(res) > 0)
|
if (QR_get_num_tuples(res) > 0)
|
||||||
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
|
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
|
||||||
@ -2932,13 +2932,13 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
|
|||||||
if (!conn->server_encoding)
|
if (!conn->server_encoding)
|
||||||
return ret;
|
return ret;
|
||||||
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
|
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
|
||||||
bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
|
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
|
||||||
if (!bError && continueExec)
|
if (!bError && continueExec)
|
||||||
{
|
{
|
||||||
sprintf(query, "select attrelid, attnum from pg_class, pg_attribute "
|
sprintf(query, "select attrelid, attnum from pg_class, pg_attribute "
|
||||||
"where relname = '%s' and attrelid = pg_class.oid "
|
"where relname = '%s' and attrelid = pg_class.oid "
|
||||||
"and attname = '%s'", serverTableName, serverColumnName);
|
"and attname = '%s'", serverTableName, serverColumnName);
|
||||||
if (res = CC_send_query(conn, query, NULL, TRUE), res)
|
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
|
||||||
{
|
{
|
||||||
if (QR_get_num_tuples(res) > 0)
|
if (QR_get_num_tuples(res) > 0)
|
||||||
{
|
{
|
||||||
@ -2960,11 +2960,11 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
|
|||||||
}
|
}
|
||||||
/* restore the cleint encoding */
|
/* restore the cleint encoding */
|
||||||
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
|
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
|
||||||
bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
|
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
|
||||||
if (bError || !continueExec)
|
if (bError || !continueExec)
|
||||||
return ret;
|
return ret;
|
||||||
sprintf(query, "select attname from pg_attribute where attrelid = %s and attnum = %s", saveattrelid, saveattnum);
|
sprintf(query, "select attname from pg_attribute where attrelid = %s and attnum = %s", saveattrelid, saveattnum);
|
||||||
if (res = CC_send_query(conn, query, NULL, TRUE), res)
|
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
|
||||||
{
|
{
|
||||||
if (QR_get_num_tuples(res) > 0)
|
if (QR_get_num_tuples(res) > 0)
|
||||||
{
|
{
|
||||||
@ -3790,7 +3790,7 @@ PGAPI_Procedures(
|
|||||||
" case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc");
|
" case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc");
|
||||||
my_strcat(proc_query, " where proname like '%.*s'", szProcName, cbProcName);
|
my_strcat(proc_query, " where proname like '%.*s'", szProcName, cbProcName);
|
||||||
|
|
||||||
if (res = CC_send_query(conn, proc_query, NULL, TRUE), !res)
|
if (res = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !res)
|
||||||
{
|
{
|
||||||
stmt->errornumber = STMT_EXEC_ERROR;
|
stmt->errornumber = STMT_EXEC_ERROR;
|
||||||
stmt->errormsg = "PGAPI_Procedures query error";
|
stmt->errormsg = "PGAPI_Procedures query error";
|
||||||
@ -3927,7 +3927,7 @@ PGAPI_TablePrivileges(
|
|||||||
my_strcat(proc_query, " relname like '%.*s' and", esc_table_name, escTbnamelen);
|
my_strcat(proc_query, " relname like '%.*s' and", esc_table_name, escTbnamelen);
|
||||||
}
|
}
|
||||||
strcat(proc_query, " pg_user.usesysid = relowner");
|
strcat(proc_query, " pg_user.usesysid = relowner");
|
||||||
if (res = CC_send_query(conn, proc_query, NULL, TRUE), !res)
|
if (res = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !res)
|
||||||
{
|
{
|
||||||
stmt->errornumber = STMT_EXEC_ERROR;
|
stmt->errornumber = STMT_EXEC_ERROR;
|
||||||
stmt->errormsg = "PGAPI_TablePrivileges query error";
|
stmt->errormsg = "PGAPI_TablePrivileges query error";
|
||||||
@ -3935,7 +3935,7 @@ PGAPI_TablePrivileges(
|
|||||||
}
|
}
|
||||||
strncpy_null(proc_query, "select usename, usesysid, usesuper from pg_user", sizeof(proc_query));
|
strncpy_null(proc_query, "select usename, usesysid, usesuper from pg_user", sizeof(proc_query));
|
||||||
tablecount = QR_get_num_tuples(res);
|
tablecount = QR_get_num_tuples(res);
|
||||||
if (allures = CC_send_query(conn, proc_query, NULL, TRUE), !allures)
|
if (allures = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !allures)
|
||||||
{
|
{
|
||||||
QR_Destructor(res);
|
QR_Destructor(res);
|
||||||
stmt->errornumber = STMT_EXEC_ERROR;
|
stmt->errornumber = STMT_EXEC_ERROR;
|
||||||
@ -3983,7 +3983,7 @@ PGAPI_TablePrivileges(
|
|||||||
char *grolist, *uid, *delm;
|
char *grolist, *uid, *delm;
|
||||||
|
|
||||||
snprintf(proc_query, sizeof(proc_query) - 1, "select grolist from pg_group where groname = '%s'", user);
|
snprintf(proc_query, sizeof(proc_query) - 1, "select grolist from pg_group where groname = '%s'", user);
|
||||||
if (gres = CC_send_query(conn, proc_query, NULL, TRUE))
|
if (gres = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT))
|
||||||
{
|
{
|
||||||
grolist = QR_get_value_backend_row(gres, 0, 0);
|
grolist = QR_get_value_backend_row(gres, 0, 0);
|
||||||
if (grolist && grolist[0] == '{')
|
if (grolist && grolist[0] == '{')
|
||||||
|
@ -47,14 +47,15 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
|
|||||||
break;
|
break;
|
||||||
case SQL_KEYSET_CURSOR_ATTRIBUTES1:
|
case SQL_KEYSET_CURSOR_ATTRIBUTES1:
|
||||||
len = 4;
|
len = 4;
|
||||||
value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE
|
value = 0;
|
||||||
|
if (ci->updatable_cursors || ci->drivers.lie)
|
||||||
|
value |= (SQL_CA1_NEXT | SQL_CA1_ABSOLUTE
|
||||||
| SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK
|
| SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK
|
||||||
| SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION
|
| SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION
|
||||||
| SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE
|
| SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE
|
||||||
| SQL_CA1_POS_REFRESH;
|
| SQL_CA1_POS_REFRESH);
|
||||||
if (ci->drivers.lie)
|
if (ci->drivers.lie)
|
||||||
value |=
|
value |= (SQL_CA1_BULK_ADD
|
||||||
( SQL_CA1_BULK_ADD
|
|
||||||
| SQL_CA1_BULK_UPDATE_BY_BOOKMARK
|
| SQL_CA1_BULK_UPDATE_BY_BOOKMARK
|
||||||
| SQL_CA1_BULK_DELETE_BY_BOOKMARK
|
| SQL_CA1_BULK_DELETE_BY_BOOKMARK
|
||||||
| SQL_CA1_BULK_FETCH_BY_BOOKMARK
|
| SQL_CA1_BULK_FETCH_BY_BOOKMARK
|
||||||
@ -68,13 +69,14 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
|
|||||||
break;
|
break;
|
||||||
case SQL_KEYSET_CURSOR_ATTRIBUTES2:
|
case SQL_KEYSET_CURSOR_ATTRIBUTES2:
|
||||||
len = 4;
|
len = 4;
|
||||||
value = SQL_CA2_OPT_ROWVER_CONCURRENCY
|
value = 0;
|
||||||
|
if (ci->updatable_cursors || ci->drivers.lie)
|
||||||
|
value |= (SQL_CA2_OPT_ROWVER_CONCURRENCY
|
||||||
| SQL_CA2_SENSITIVITY_ADDITIONS
|
| SQL_CA2_SENSITIVITY_ADDITIONS
|
||||||
| SQL_CA2_SENSITIVITY_DELETIONS
|
| SQL_CA2_SENSITIVITY_DELETIONS
|
||||||
| SQL_CA2_SENSITIVITY_UPDATES;
|
| SQL_CA2_SENSITIVITY_UPDATES);
|
||||||
if (ci->drivers.lie)
|
if (ci->drivers.lie)
|
||||||
value |=
|
value |= (SQL_CA2_READ_ONLY_CONCURRENCY
|
||||||
( SQL_CA2_READ_ONLY_CONCURRENCY
|
|
||||||
| SQL_CA2_LOCK_CONCURRENCY
|
| SQL_CA2_LOCK_CONCURRENCY
|
||||||
| SQL_CA2_OPT_VALUES_CONCURRENCY
|
| SQL_CA2_OPT_VALUES_CONCURRENCY
|
||||||
| SQL_CA2_MAX_ROWS_SELECT
|
| SQL_CA2_MAX_ROWS_SELECT
|
||||||
@ -95,16 +97,19 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
|
|||||||
len = 4;
|
len = 4;
|
||||||
value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE
|
value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE
|
||||||
| SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK
|
| SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK
|
||||||
| SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION
|
| SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION;
|
||||||
| SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE
|
if (ci->updatable_cursors)
|
||||||
| SQL_CA1_POS_REFRESH;
|
value |= (SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE
|
||||||
|
| SQL_CA1_POS_REFRESH);
|
||||||
break;
|
break;
|
||||||
case SQL_STATIC_CURSOR_ATTRIBUTES2:
|
case SQL_STATIC_CURSOR_ATTRIBUTES2:
|
||||||
len = 4;
|
len = 4;
|
||||||
value = SQL_CA2_OPT_ROWVER_CONCURRENCY
|
value = 0;
|
||||||
|
if (ci->updatable_cursors)
|
||||||
|
value |= (SQL_CA2_OPT_ROWVER_CONCURRENCY
|
||||||
| SQL_CA2_SENSITIVITY_ADDITIONS
|
| SQL_CA2_SENSITIVITY_ADDITIONS
|
||||||
| SQL_CA2_SENSITIVITY_DELETIONS
|
| SQL_CA2_SENSITIVITY_DELETIONS
|
||||||
| SQL_CA2_SENSITIVITY_UPDATES;
|
| SQL_CA2_SENSITIVITY_UPDATES);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_ODBC_INTERFACE_CONFORMANCE:
|
case SQL_ODBC_INTERFACE_CONFORMANCE:
|
||||||
|
@ -300,7 +300,7 @@ CC_lookup_cs_new(ConnectionClass *self)
|
|||||||
char *encstr = NULL;
|
char *encstr = NULL;
|
||||||
QResultClass *res;
|
QResultClass *res;
|
||||||
|
|
||||||
res = CC_send_query(self, "select pg_client_encoding()", NULL, TRUE);
|
res = CC_send_query(self, "select pg_client_encoding()", NULL, CLEAR_RESULT_ON_ABORT);
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
char *enc = QR_get_value_backend_row(res, 0, 0);
|
char *enc = QR_get_value_backend_row(res, 0, 0);
|
||||||
|
@ -419,177 +419,17 @@ SQLSetConnectAttr(HDBC ConnectionHandle,
|
|||||||
return PGAPI_SetConnectOption(ConnectionHandle, (UWORD) Attribute, (UDWORD) Value);
|
return PGAPI_SetConnectOption(ConnectionHandle, (UWORD) Attribute, (UDWORD) Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RETCODE SQL_API
|
|
||||||
ARDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|
||||||
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
|
|
||||||
{
|
|
||||||
RETCODE ret = SQL_SUCCESS;
|
|
||||||
PTR tptr;
|
|
||||||
switch (FieldIdentifier)
|
|
||||||
{
|
|
||||||
case SQL_DESC_ARRAY_SIZE:
|
|
||||||
stmt->options.rowset_size = (SQLUINTEGER) Value;
|
|
||||||
break;
|
|
||||||
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
||||||
stmt->options.row_operation_ptr = Value;
|
|
||||||
break;
|
|
||||||
case SQL_DESC_BIND_OFFSET_PTR:
|
|
||||||
stmt->options.row_offset_ptr = Value;
|
|
||||||
break;
|
|
||||||
case SQL_DESC_BIND_TYPE:
|
|
||||||
stmt->options.bind_size = (SQLUINTEGER) Value;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SQL_DESC_DATA_PTR:
|
|
||||||
if (!RecNumber)
|
|
||||||
stmt->bookmark.buffer = Value;
|
|
||||||
else
|
|
||||||
stmt->bindings[RecNumber - 1].buffer = Value;
|
|
||||||
break;
|
|
||||||
case SQL_DESC_INDICATOR_PTR:
|
|
||||||
if (!RecNumber)
|
|
||||||
tptr = stmt->bookmark.used;
|
|
||||||
else
|
|
||||||
tptr = stmt->bindings[RecNumber - 1].used;
|
|
||||||
if (Value != tptr)
|
|
||||||
{
|
|
||||||
ret = SQL_ERROR;
|
|
||||||
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
|
|
||||||
stmt->errormsg = "INDICATOR != OCTET_LENGTH_PTR";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SQL_DESC_OCTET_LENGTH_PTR:
|
|
||||||
if (!RecNumber)
|
|
||||||
stmt->bookmark.used = Value;
|
|
||||||
else
|
|
||||||
stmt->bindings[RecNumber - 1].used = Value;
|
|
||||||
break;
|
|
||||||
default:ret = SQL_ERROR;
|
|
||||||
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
|
|
||||||
stmt->errormsg = "not implemedted yet";
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static RETCODE SQL_API
|
|
||||||
APDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|
||||||
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
|
|
||||||
{
|
|
||||||
RETCODE ret = SQL_SUCCESS;
|
|
||||||
switch (FieldIdentifier)
|
|
||||||
{
|
|
||||||
case SQL_DESC_ARRAY_SIZE:
|
|
||||||
stmt->options.paramset_size = (SQLUINTEGER) Value;
|
|
||||||
break;
|
|
||||||
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
||||||
stmt->options.param_operation_ptr = Value;
|
|
||||||
break;
|
|
||||||
case SQL_DESC_BIND_OFFSET_PTR:
|
|
||||||
stmt->options.param_offset_ptr = Value;
|
|
||||||
break;
|
|
||||||
case SQL_DESC_BIND_TYPE:
|
|
||||||
stmt->options.param_bind_type = (SQLUINTEGER) Value;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SQL_DESC_DATA_PTR:
|
|
||||||
if (stmt->parameters_allocated < RecNumber)
|
|
||||||
PGAPI_BindParameter(stmt, RecNumber, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
||||||
stmt->parameters[RecNumber - 1].buffer = Value;
|
|
||||||
break;
|
|
||||||
case SQL_DESC_INDICATOR_PTR:
|
|
||||||
if (stmt->parameters_allocated < RecNumber ||
|
|
||||||
Value != stmt->parameters[RecNumber - 1].used)
|
|
||||||
{
|
|
||||||
ret = SQL_ERROR;
|
|
||||||
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
|
|
||||||
stmt->errormsg = "INDICATOR != OCTET_LENGTH_PTR";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SQL_DESC_OCTET_LENGTH_PTR:
|
|
||||||
if (stmt->parameters_allocated < RecNumber)
|
|
||||||
PGAPI_BindParameter(stmt, RecNumber, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
||||||
stmt->parameters[RecNumber - 1].used = Value;
|
|
||||||
break;
|
|
||||||
default:ret = SQL_ERROR;
|
|
||||||
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static RETCODE SQL_API
|
|
||||||
IRDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|
||||||
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
|
|
||||||
{
|
|
||||||
RETCODE ret = SQL_SUCCESS;
|
|
||||||
switch (FieldIdentifier)
|
|
||||||
{
|
|
||||||
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
||||||
stmt->options.rowStatusArray = (SQLUSMALLINT *) Value;
|
|
||||||
break;
|
|
||||||
case SQL_DESC_ROWS_PROCESSED_PTR:
|
|
||||||
stmt->options.rowsFetched = (SQLUINTEGER *) Value;
|
|
||||||
break;
|
|
||||||
default:ret = SQL_ERROR;
|
|
||||||
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static RETCODE SQL_API
|
|
||||||
IPDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|
||||||
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
|
|
||||||
{
|
|
||||||
RETCODE ret = SQL_SUCCESS;
|
|
||||||
switch (FieldIdentifier)
|
|
||||||
{
|
|
||||||
case SQL_DESC_ARRAY_STATUS_PTR:
|
|
||||||
stmt->options.param_status_ptr = (SQLUSMALLINT *) Value;
|
|
||||||
break;
|
|
||||||
case SQL_DESC_ROWS_PROCESSED_PTR:
|
|
||||||
stmt->options.param_processed_ptr = (SQLUINTEGER *) Value;
|
|
||||||
break;
|
|
||||||
default:ret = SQL_ERROR;
|
|
||||||
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* new function */
|
/* new function */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLSetDescField(SQLHDESC DescriptorHandle,
|
SQLSetDescField(SQLHDESC DescriptorHandle,
|
||||||
SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
|
SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
|
||||||
PTR Value, SQLINTEGER BufferLength)
|
PTR Value, SQLINTEGER BufferLength)
|
||||||
{
|
{
|
||||||
RETCODE ret = SQL_SUCCESS;
|
RETCODE ret;
|
||||||
HSTMT hstmt;
|
|
||||||
SQLUINTEGER descType;
|
|
||||||
StatementClass *stmt;
|
|
||||||
static const char *func = "SQLSetDescField";
|
|
||||||
|
|
||||||
mylog("[[SQLSetDescField]] h=%u rec=%d field=%d val=%x\n", DescriptorHandle, RecNumber, FieldIdentifier, Value);
|
mylog("[[SQLSetDescField]] h=%u rec=%d field=%d val=%x\n", DescriptorHandle, RecNumber, FieldIdentifier, Value);
|
||||||
hstmt = statementHandleFromDescHandle(DescriptorHandle, &descType);
|
ret = PGAPI_SetDescField(DescriptorHandle, RecNumber, FieldIdentifier,
|
||||||
mylog("stmt=%x type=%d\n", hstmt, descType);
|
Value, BufferLength);
|
||||||
stmt = (StatementClass *) hstmt;
|
|
||||||
switch (descType)
|
|
||||||
{
|
|
||||||
case SQL_ATTR_APP_ROW_DESC:
|
|
||||||
ret = ARDSetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength);
|
|
||||||
break;
|
|
||||||
case SQL_ATTR_APP_PARAM_DESC:
|
|
||||||
ret = APDSetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength);
|
|
||||||
break;
|
|
||||||
case SQL_ATTR_IMP_ROW_DESC:
|
|
||||||
ret = IRDSetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength);
|
|
||||||
break;
|
|
||||||
case SQL_ATTR_IMP_PARAM_DESC:
|
|
||||||
ret = IPDSetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength);
|
|
||||||
break;
|
|
||||||
default:ret = SQL_ERROR;
|
|
||||||
stmt->errornumber = STMT_INTERNAL_ERROR;
|
|
||||||
stmt->errormsg = "Error not implemented";
|
|
||||||
}
|
|
||||||
if (ret == SQL_ERROR)
|
|
||||||
SC_log_error(func, "", stmt);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,7 +442,7 @@ SQLSetDescRec(SQLHDESC DescriptorHandle,
|
|||||||
PTR Data, SQLINTEGER *StringLength,
|
PTR Data, SQLINTEGER *StringLength,
|
||||||
SQLINTEGER *Indicator)
|
SQLINTEGER *Indicator)
|
||||||
{
|
{
|
||||||
const char *func = "SQLSetDescField";
|
const char *func = "SQLSetDescRec";
|
||||||
|
|
||||||
mylog("[[SQLSetDescRec]]\n");
|
mylog("[[SQLSetDescRec]]\n");
|
||||||
mylog("Error not implemented\n");
|
mylog("Error not implemented\n");
|
||||||
|
@ -39,6 +39,7 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
static char *func = "set_statement_option";
|
static char *func = "set_statement_option";
|
||||||
char changed = FALSE;
|
char changed = FALSE;
|
||||||
ConnInfo *ci = NULL;
|
ConnInfo *ci = NULL;
|
||||||
|
UDWORD setval;
|
||||||
|
|
||||||
if (conn)
|
if (conn)
|
||||||
ci = &(conn->connInfo);
|
ci = &(conn->connInfo);
|
||||||
@ -63,22 +64,21 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
* positioned update isn't supported so cursor concurrency is
|
* positioned update isn't supported so cursor concurrency is
|
||||||
* read-only
|
* read-only
|
||||||
*/
|
*/
|
||||||
mylog("SetStmtOption(): SQL_CONCURRENCY = %d\n", vParam);
|
mylog("SetStmtOption(): SQL_CONCURRENCY = %d ", vParam);
|
||||||
if (ci->drivers.lie || vParam == SQL_CONCUR_READ_ONLY || vParam == SQL_CONCUR_ROWVER)
|
setval = SQL_CONCUR_READ_ONLY;
|
||||||
{
|
if (SQL_CONCUR_READ_ONLY == vParam)
|
||||||
if (conn)
|
;
|
||||||
conn->stmtOptions.scroll_concurrency = vParam;
|
if (ci->drivers.lie)
|
||||||
if (stmt)
|
setval = vParam;
|
||||||
stmt->options.scroll_concurrency = vParam;
|
else if (ci->updatable_cursors)
|
||||||
}
|
setval = SQL_CONCUR_ROWVER;
|
||||||
else
|
if (conn)
|
||||||
{
|
conn->stmtOptions.scroll_concurrency = setval;
|
||||||
if (conn)
|
else if (stmt)
|
||||||
conn->stmtOptions.scroll_concurrency = SQL_CONCUR_ROWVER;
|
stmt->options.scroll_concurrency = setval;
|
||||||
if (stmt)
|
if (setval != vParam)
|
||||||
stmt->options.scroll_concurrency = SQL_CONCUR_ROWVER;
|
|
||||||
changed = TRUE;
|
changed = TRUE;
|
||||||
}
|
mylog("-> %d\n", setval);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_CURSOR_TYPE:
|
case SQL_CURSOR_TYPE:
|
||||||
@ -87,47 +87,24 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
* if declare/fetch, then type can only be forward. otherwise,
|
* if declare/fetch, then type can only be forward. otherwise,
|
||||||
* it can only be forward or static.
|
* it can only be forward or static.
|
||||||
*/
|
*/
|
||||||
mylog("SetStmtOption(): SQL_CURSOR_TYPE = %d\n", vParam);
|
mylog("SetStmtOption(): SQL_CURSOR_TYPE = %d ", vParam);
|
||||||
|
setval = SQL_CURSOR_FORWARD_ONLY;
|
||||||
if (ci->drivers.lie)
|
if (ci->drivers.lie)
|
||||||
{
|
setval = vParam;
|
||||||
if (conn)
|
else if (ci->drivers.use_declarefetch)
|
||||||
conn->stmtOptions.cursor_type = vParam;
|
;
|
||||||
if (stmt)
|
else if (SQL_CURSOR_STATIC == vParam)
|
||||||
stmt->options.cursor_type = vParam;
|
setval = vParam;
|
||||||
}
|
/** else if (SQL_CURSOR_KEYSET_DRIVEN == vParam && ci->updatable)
|
||||||
else
|
setval = vParam; **/
|
||||||
{
|
|
||||||
if (ci->drivers.use_declarefetch)
|
|
||||||
{
|
|
||||||
if (conn)
|
|
||||||
conn->stmtOptions.cursor_type = SQL_CURSOR_FORWARD_ONLY;
|
|
||||||
if (stmt)
|
|
||||||
stmt->options.cursor_type = SQL_CURSOR_FORWARD_ONLY;
|
|
||||||
|
|
||||||
if (vParam != SQL_CURSOR_FORWARD_ONLY)
|
if (conn)
|
||||||
changed = TRUE;
|
conn->stmtOptions.cursor_type = setval;
|
||||||
}
|
else if (stmt)
|
||||||
else
|
stmt->options.cursor_type = setval;
|
||||||
{
|
if (setval != vParam)
|
||||||
if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC)
|
changed = TRUE;
|
||||||
{
|
mylog("-> %d\n", setval);
|
||||||
if (conn)
|
|
||||||
conn->stmtOptions.cursor_type = vParam; /* valid type */
|
|
||||||
if (stmt)
|
|
||||||
stmt->options.cursor_type = vParam; /* valid type */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (conn)
|
|
||||||
conn->stmtOptions.cursor_type = SQL_CURSOR_STATIC;
|
|
||||||
if (stmt)
|
|
||||||
stmt->options.cursor_type = SQL_CURSOR_STATIC;
|
|
||||||
|
|
||||||
changed = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_KEYSET_SIZE: /* ignored, but saved and returned */
|
case SQL_KEYSET_SIZE: /* ignored, but saved and returned */
|
||||||
|
@ -297,7 +297,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
in_distinct = FALSE,
|
in_distinct = FALSE,
|
||||||
in_on = FALSE,
|
in_on = FALSE,
|
||||||
in_from = FALSE,
|
in_from = FALSE,
|
||||||
from_found = FALSE,
|
|
||||||
in_where = FALSE,
|
in_where = FALSE,
|
||||||
in_table = FALSE;
|
in_table = FALSE;
|
||||||
char in_field = FALSE,
|
char in_field = FALSE,
|
||||||
@ -309,7 +308,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
i,
|
i,
|
||||||
k = 0,
|
k = 0,
|
||||||
n,
|
n,
|
||||||
first_where = 0,
|
|
||||||
blevel = 0;
|
blevel = 0;
|
||||||
FIELD_INFO **fi;
|
FIELD_INFO **fi;
|
||||||
TABLE_INFO **ti;
|
TABLE_INFO **ti;
|
||||||
@ -318,6 +316,7 @@ parse_statement(StatementClass *stmt)
|
|||||||
HSTMT hcol_stmt;
|
HSTMT hcol_stmt;
|
||||||
StatementClass *col_stmt;
|
StatementClass *col_stmt;
|
||||||
RETCODE result;
|
RETCODE result;
|
||||||
|
BOOL updatable = TRUE;
|
||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
@ -327,6 +326,8 @@ parse_statement(StatementClass *stmt)
|
|||||||
|
|
||||||
stmt->nfld = 0;
|
stmt->nfld = 0;
|
||||||
stmt->ntab = 0;
|
stmt->ntab = 0;
|
||||||
|
stmt->from_pos = -1;
|
||||||
|
stmt->where_pos = -1;
|
||||||
|
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
while (pptr = ptr, (ptr = getNextToken(conn->ccsc, pptr, token, sizeof(token), &delim, "e, &dquote, &numeric)) != NULL)
|
while (pptr = ptr, (ptr = getNextToken(conn->ccsc, pptr, token, sizeof(token), &delim, "e, &dquote, &numeric)) != NULL)
|
||||||
@ -343,6 +344,7 @@ parse_statement(StatementClass *stmt)
|
|||||||
if (!stricmp(token, "distinct"))
|
if (!stricmp(token, "distinct"))
|
||||||
{
|
{
|
||||||
in_distinct = TRUE;
|
in_distinct = TRUE;
|
||||||
|
updatable = FALSE;
|
||||||
|
|
||||||
mylog("DISTINCT\n");
|
mylog("DISTINCT\n");
|
||||||
continue;
|
continue;
|
||||||
@ -359,11 +361,11 @@ parse_statement(StatementClass *stmt)
|
|||||||
{
|
{
|
||||||
in_select = FALSE;
|
in_select = FALSE;
|
||||||
in_from = TRUE;
|
in_from = TRUE;
|
||||||
if (!from_found &&
|
if (stmt->from_pos < 0 &&
|
||||||
(!strnicmp(pptr, "from", 4)))
|
(!strnicmp(pptr, "from", 4)))
|
||||||
{
|
{
|
||||||
mylog("First ");
|
mylog("First ");
|
||||||
from_found = TRUE;
|
stmt->from_pos = pptr - stmt->statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
mylog("FROM\n");
|
mylog("FROM\n");
|
||||||
@ -384,9 +386,13 @@ parse_statement(StatementClass *stmt)
|
|||||||
in_from = FALSE;
|
in_from = FALSE;
|
||||||
in_where = TRUE;
|
in_where = TRUE;
|
||||||
|
|
||||||
if (!first_where &&
|
if (!stricmp(token, "where"))
|
||||||
(!stricmp(token, "where")))
|
{
|
||||||
first_where = ptr - stmt->statement;
|
if (stmt->where_pos < 0)
|
||||||
|
stmt->where_pos = pptr - stmt->statement;
|
||||||
|
}
|
||||||
|
else if (stricmp(token, "order"))
|
||||||
|
updatable = FALSE;
|
||||||
|
|
||||||
mylog("WHERE...\n");
|
mylog("WHERE...\n");
|
||||||
break;
|
break;
|
||||||
@ -733,6 +739,10 @@ parse_statement(StatementClass *stmt)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Call SQLColumns for each table and store the result */
|
/* Call SQLColumns for each table and store the result */
|
||||||
|
if (stmt->ntab > 1)
|
||||||
|
updatable = FALSE;
|
||||||
|
else if (stmt->from_pos < 0)
|
||||||
|
updatable = FALSE;
|
||||||
for (i = 0; i < stmt->ntab; i++)
|
for (i = 0; i < stmt->ntab; i++)
|
||||||
{
|
{
|
||||||
/* See if already got it */
|
/* See if already got it */
|
||||||
@ -828,9 +838,11 @@ parse_statement(StatementClass *stmt)
|
|||||||
*/
|
*/
|
||||||
for (i = 0; i < stmt->nfld;)
|
for (i = 0; i < stmt->nfld;)
|
||||||
{
|
{
|
||||||
|
fi[i]->updatable = updatable;
|
||||||
/* Dont worry about functions or quotes */
|
/* Dont worry about functions or quotes */
|
||||||
if (fi[i]->func || fi[i]->quote || fi[i]->numeric)
|
if (fi[i]->func || fi[i]->quote || fi[i]->numeric)
|
||||||
{
|
{
|
||||||
|
fi[i]->updatable = FALSE;
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -928,6 +940,7 @@ parse_statement(StatementClass *stmt)
|
|||||||
mylog("about to copy at %d\n", n + i);
|
mylog("about to copy at %d\n", n + i);
|
||||||
|
|
||||||
getColInfo(the_ti->col_info, fi[n + i], n);
|
getColInfo(the_ti->col_info, fi[n + i], n);
|
||||||
|
fi[n + i]->updatable = updatable;
|
||||||
|
|
||||||
mylog("done copying\n");
|
mylog("done copying\n");
|
||||||
}
|
}
|
||||||
@ -945,24 +958,29 @@ parse_statement(StatementClass *stmt)
|
|||||||
else if (fi[i]->ti)
|
else if (fi[i]->ti)
|
||||||
{
|
{
|
||||||
if (!searchColInfo(fi[i]->ti->col_info, fi[i]))
|
if (!searchColInfo(fi[i]->ti->col_info, fi[i]))
|
||||||
|
{
|
||||||
parse = FALSE;
|
parse = FALSE;
|
||||||
|
fi[i]->updatable = FALSE;
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't know the table -- search all tables in "from" list */
|
/* Don't know the table -- search all tables in "from" list */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
parse = FALSE;
|
|
||||||
for (k = 0; k < stmt->ntab; k++)
|
for (k = 0; k < stmt->ntab; k++)
|
||||||
{
|
{
|
||||||
if (searchColInfo(ti[k]->col_info, fi[i]))
|
if (searchColInfo(ti[k]->col_info, fi[i]))
|
||||||
{
|
{
|
||||||
fi[i]->ti = ti[k]; /* now know the table */
|
fi[i]->ti = ti[k]; /* now know the table */
|
||||||
parse = TRUE;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (k >= stmt->ntab)
|
||||||
|
{
|
||||||
|
parse = FALSE;
|
||||||
|
fi[i]->updatable = FALSE;
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*
|
||||||
* $Id: psqlodbc.h,v 1.59 2002/03/11 10:25:57 inoue Exp $
|
* $Id: psqlodbc.h,v 1.60 2002/03/14 05:42:03 inoue Exp $
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -166,6 +166,7 @@ typedef struct TupleListClass_ TupleListClass;
|
|||||||
typedef struct EnvironmentClass_ EnvironmentClass;
|
typedef struct EnvironmentClass_ EnvironmentClass;
|
||||||
typedef struct TupleNode_ TupleNode;
|
typedef struct TupleNode_ TupleNode;
|
||||||
typedef struct TupleField_ TupleField;
|
typedef struct TupleField_ TupleField;
|
||||||
|
typedef struct KeySet_ KeySet;
|
||||||
|
|
||||||
typedef struct col_info COL_INFO;
|
typedef struct col_info COL_INFO;
|
||||||
typedef struct lo_arg LO_ARG;
|
typedef struct lo_arg LO_ARG;
|
||||||
|
@ -5,7 +5,7 @@ SQLAllocEnv @2
|
|||||||
SQLAllocStmt @3
|
SQLAllocStmt @3
|
||||||
SQLBindCol @4
|
SQLBindCol @4
|
||||||
SQLCancel @5
|
SQLCancel @5
|
||||||
SQLColAttributes @6
|
; SQLColAttributes @6 */
|
||||||
SQLConnect @7
|
SQLConnect @7
|
||||||
SQLDescribeCol @8
|
SQLDescribeCol @8
|
||||||
SQLDisconnect @9
|
SQLDisconnect @9
|
||||||
|
@ -5,7 +5,7 @@ SQLAllocEnv @2
|
|||||||
SQLAllocStmt @3
|
SQLAllocStmt @3
|
||||||
SQLBindCol @4
|
SQLBindCol @4
|
||||||
SQLCancel @5
|
SQLCancel @5
|
||||||
SQLColAttributes @6
|
; SQLColAttributes @6
|
||||||
SQLConnect @7
|
SQLConnect @7
|
||||||
SQLDescribeCol @8
|
SQLDescribeCol @8
|
||||||
SQLDisconnect @9
|
SQLDisconnect @9
|
||||||
|
@ -121,6 +121,8 @@ QR_Constructor()
|
|||||||
|
|
||||||
rv->cache_size = 0;
|
rv->cache_size = 0;
|
||||||
rv->rowset_size = 1;
|
rv->rowset_size = 1;
|
||||||
|
rv->haskeyset = 0;
|
||||||
|
rv->keyset = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mylog("exit QR_Constructor\n");
|
mylog("exit QR_Constructor\n");
|
||||||
@ -221,6 +223,11 @@ QR_free_memory(QResultClass *self)
|
|||||||
free(self->backend_tuples);
|
free(self->backend_tuples);
|
||||||
self->backend_tuples = NULL;
|
self->backend_tuples = NULL;
|
||||||
}
|
}
|
||||||
|
if (self->keyset)
|
||||||
|
{
|
||||||
|
free(self->keyset);
|
||||||
|
self->keyset = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
self->fcount = 0;
|
self->fcount = 0;
|
||||||
|
|
||||||
@ -296,6 +303,8 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
|
|||||||
mylog("MALLOC: tuple_size = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size);
|
mylog("MALLOC: tuple_size = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size);
|
||||||
self->count_allocated = 0;
|
self->count_allocated = 0;
|
||||||
self->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size);
|
self->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size);
|
||||||
|
if (self->haskeyset)
|
||||||
|
self->keyset = (KeySet *) calloc(sizeof(KeySet), tuple_size);
|
||||||
if (!self->backend_tuples)
|
if (!self->backend_tuples)
|
||||||
{
|
{
|
||||||
self->status = PGRES_FATAL_ERROR;
|
self->status = PGRES_FATAL_ERROR;
|
||||||
@ -347,7 +356,7 @@ QR_close(QResultClass *self)
|
|||||||
sprintf(buf, "close %s", self->cursor);
|
sprintf(buf, "close %s", self->cursor);
|
||||||
mylog("QResult: closing cursor: '%s'\n", buf);
|
mylog("QResult: closing cursor: '%s'\n", buf);
|
||||||
|
|
||||||
res = CC_send_query(self->conn, buf, NULL, TRUE);
|
res = CC_send_query(self->conn, buf, NULL, CLEAR_RESULT_ON_ABORT);
|
||||||
|
|
||||||
self->inTuples = FALSE;
|
self->inTuples = FALSE;
|
||||||
self->currTuple = -1;
|
self->currTuple = -1;
|
||||||
@ -482,6 +491,8 @@ QR_next_tuple(QResultClass *self)
|
|||||||
QR_set_message(self, "Out of memory while reading tuples.");
|
QR_set_message(self, "Out of memory while reading tuples.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
if (self->haskeyset)
|
||||||
|
self->keyset = (KeySet *) realloc(self->keyset, sizeof(KeySet) * self->cache_size);
|
||||||
self->count_allocated = self->cache_size;
|
self->count_allocated = self->cache_size;
|
||||||
}
|
}
|
||||||
sprintf(fetch, "fetch %d in %s", fetch_size, self->cursor);
|
sprintf(fetch, "fetch %d in %s", fetch_size, self->cursor);
|
||||||
@ -492,7 +503,7 @@ QR_next_tuple(QResultClass *self)
|
|||||||
qi.row_size = self->cache_size;
|
qi.row_size = self->cache_size;
|
||||||
qi.result_in = self;
|
qi.result_in = self;
|
||||||
qi.cursor = NULL;
|
qi.cursor = NULL;
|
||||||
res = CC_send_query(self->conn, fetch, &qi, TRUE);
|
res = CC_send_query(self->conn, fetch, &qi, CLEAR_RESULT_ON_ABORT);
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
{
|
{
|
||||||
self->status = PGRES_FATAL_ERROR;
|
self->status = PGRES_FATAL_ERROR;
|
||||||
@ -552,6 +563,8 @@ QR_next_tuple(QResultClass *self)
|
|||||||
QR_set_message(self, "Out of memory while reading tuples.");
|
QR_set_message(self, "Out of memory while reading tuples.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
if (self->haskeyset)
|
||||||
|
self->keyset = (KeySet *) realloc(self->keyset, sizeof(KeySet) * tuple_size);
|
||||||
self->count_allocated = tuple_size;
|
self->count_allocated = tuple_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,6 +639,7 @@ QR_read_tuple(QResultClass *self, char binary)
|
|||||||
{
|
{
|
||||||
Int2 field_lf;
|
Int2 field_lf;
|
||||||
TupleField *this_tuplefield;
|
TupleField *this_tuplefield;
|
||||||
|
KeySet *this_keyset = NULL;
|
||||||
char bmp,
|
char bmp,
|
||||||
bitmap[MAX_FIELDS]; /* Max. len of the bitmap */
|
bitmap[MAX_FIELDS]; /* Max. len of the bitmap */
|
||||||
Int2 bitmaplen; /* len of the bitmap in bytes */
|
Int2 bitmaplen; /* len of the bitmap in bytes */
|
||||||
@ -639,6 +653,11 @@ QR_read_tuple(QResultClass *self, char binary)
|
|||||||
|
|
||||||
/* set the current row to read the fields into */
|
/* set the current row to read the fields into */
|
||||||
this_tuplefield = self->backend_tuples + (self->fcount * num_fields);
|
this_tuplefield = self->backend_tuples + (self->fcount * num_fields);
|
||||||
|
if (self->haskeyset)
|
||||||
|
{
|
||||||
|
this_keyset = self->keyset + self->fcount;
|
||||||
|
this_keyset->status = 0;
|
||||||
|
}
|
||||||
|
|
||||||
bitmaplen = (Int2) num_fields / BYTELEN;
|
bitmaplen = (Int2) num_fields / BYTELEN;
|
||||||
if ((num_fields % BYTELEN) > 0)
|
if ((num_fields % BYTELEN) > 0)
|
||||||
@ -709,6 +728,15 @@ QR_read_tuple(QResultClass *self, char binary)
|
|||||||
else
|
else
|
||||||
bmp <<= 1;
|
bmp <<= 1;
|
||||||
}
|
}
|
||||||
|
if (this_keyset)
|
||||||
|
{
|
||||||
|
if (this_tuplefield[num_fields - 2].value)
|
||||||
|
sscanf(this_tuplefield[num_fields - 2].value, "(%u,%hu)",
|
||||||
|
&this_keyset->blocknum, &this_keyset->offset);
|
||||||
|
if (this_tuplefield[num_fields - 1].value)
|
||||||
|
sscanf(this_tuplefield[num_fields - 1].value, "%u",
|
||||||
|
&this_keyset->oid);
|
||||||
|
}
|
||||||
self->currTuple++;
|
self->currTuple++;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,9 @@ struct QResultClass_
|
|||||||
char inTuples; /* is a fetch of rows from the backend in
|
char inTuples; /* is a fetch of rows from the backend in
|
||||||
* progress? */
|
* progress? */
|
||||||
char aborted; /* was aborted? */
|
char aborted; /* was aborted? */
|
||||||
|
char haskeyset; /* this result contains keyset ? */
|
||||||
|
KeySet *keyset;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define QR_get_fields(self) (self->fields)
|
#define QR_get_fields(self) (self->fields)
|
||||||
@ -102,6 +105,7 @@ struct QResultClass_
|
|||||||
#define QR_set_status(self, condition) ( self->status = condition )
|
#define QR_set_status(self, condition) ( self->status = condition )
|
||||||
#define QR_set_message(self, message_) ( self->message = message_)
|
#define QR_set_message(self, message_) ( self->message = message_)
|
||||||
#define QR_set_aborted(self, aborted_) ( self->aborted = aborted_)
|
#define QR_set_aborted(self, aborted_) ( self->aborted = aborted_)
|
||||||
|
#define QR_set_haskeyset(self) (self->haskeyset = TRUE)
|
||||||
|
|
||||||
#define QR_get_message(self) (self->message)
|
#define QR_get_message(self) (self->message)
|
||||||
#define QR_get_command(self) (self->command)
|
#define QR_get_command(self) (self->command)
|
||||||
|
@ -160,8 +160,7 @@ PGAPI_NumResultCols(
|
|||||||
|
|
||||||
*pccol = QR_NumResultCols(result);
|
*pccol = QR_NumResultCols(result);
|
||||||
/* updatable cursors */
|
/* updatable cursors */
|
||||||
if (ci->updatable_cursors &&
|
if (result->keyset)
|
||||||
stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)
|
|
||||||
*pccol -= 2;
|
*pccol -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,7 +432,7 @@ PGAPI_ColAttributes(
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if (ODBCVER >= 0x0300)
|
#if (ODBCVER >= 0x0300)
|
||||||
if (0 == icol) /* bookmark column */
|
if (0 == icol && SQL_DESC_COUNT != fDescType) /* bookmark column */
|
||||||
{
|
{
|
||||||
switch (fDescType)
|
switch (fDescType)
|
||||||
{
|
{
|
||||||
@ -473,7 +472,11 @@ PGAPI_ColAttributes(
|
|||||||
* Column Count is a special case. The Column number is ignored
|
* Column Count is a special case. The Column number is ignored
|
||||||
* in this case.
|
* in this case.
|
||||||
*/
|
*/
|
||||||
|
#if (ODBCVER >= 0x0300)
|
||||||
|
if (fDescType == SQL_DESC_COUNT)
|
||||||
|
#else
|
||||||
if (fDescType == SQL_COLUMN_COUNT)
|
if (fDescType == SQL_COLUMN_COUNT)
|
||||||
|
#endif /* ODBCVER */
|
||||||
{
|
{
|
||||||
if (pfDesc)
|
if (pfDesc)
|
||||||
*pfDesc = cols;
|
*pfDesc = cols;
|
||||||
@ -539,6 +542,8 @@ PGAPI_ColAttributes(
|
|||||||
}
|
}
|
||||||
|
|
||||||
field_type = QR_get_field_type(SC_get_Curres(stmt), col_idx);
|
field_type = QR_get_field_type(SC_get_Curres(stmt), col_idx);
|
||||||
|
if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[col_idx])
|
||||||
|
fi = stmt->fi[col_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
mylog("colAttr: col %d field_type = %d\n", col_idx, field_type);
|
mylog("colAttr: col %d field_type = %d\n", col_idx, field_type);
|
||||||
@ -549,6 +554,7 @@ PGAPI_ColAttributes(
|
|||||||
value = pgtype_auto_increment(stmt, field_type);
|
value = pgtype_auto_increment(stmt, field_type);
|
||||||
if (value == -1) /* non-numeric becomes FALSE (ODBC Doc) */
|
if (value == -1) /* non-numeric becomes FALSE (ODBC Doc) */
|
||||||
value = FALSE;
|
value = FALSE;
|
||||||
|
inolog("AUTO_INCREMENT=%d\n", value);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -581,9 +587,8 @@ PGAPI_ColAttributes(
|
|||||||
|
|
||||||
#if (ODBCVER >= 0x0300)
|
#if (ODBCVER >= 0x0300)
|
||||||
case SQL_DESC_NAME:
|
case SQL_DESC_NAME:
|
||||||
#else
|
|
||||||
case SQL_COLUMN_NAME:
|
|
||||||
#endif /* ODBCVER */
|
#endif /* ODBCVER */
|
||||||
|
case SQL_COLUMN_NAME:
|
||||||
p = fi ? (fi->alias[0] ? fi->alias : fi->name) : QR_get_fieldname(SC_get_Curres(stmt), col_idx);
|
p = fi ? (fi->alias[0] ? fi->alias : fi->name) : QR_get_fieldname(SC_get_Curres(stmt), col_idx);
|
||||||
|
|
||||||
mylog("PGAPI_ColAttr: COLUMN_NAME = '%s'\n", p);
|
mylog("PGAPI_ColAttr: COLUMN_NAME = '%s'\n", p);
|
||||||
@ -597,14 +602,15 @@ PGAPI_ColAttributes(
|
|||||||
|
|
||||||
case SQL_COLUMN_MONEY: /* == SQL_DESC_FIXED_PREC_SCALE */
|
case SQL_COLUMN_MONEY: /* == SQL_DESC_FIXED_PREC_SCALE */
|
||||||
value = pgtype_money(stmt, field_type);
|
value = pgtype_money(stmt, field_type);
|
||||||
|
inolog("COLUMN_MONEY=%d\n", value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if (ODBCVER >= 0x0300)
|
#if (ODBCVER >= 0x0300)
|
||||||
case SQL_DESC_NULLABLE:
|
case SQL_DESC_NULLABLE:
|
||||||
#else
|
|
||||||
case SQL_COLUMN_NULLABLE:
|
|
||||||
#endif /* ODBCVER */
|
#endif /* ODBCVER */
|
||||||
|
case SQL_COLUMN_NULLABLE:
|
||||||
value = fi ? fi->nullable : pgtype_nullable(stmt, field_type);
|
value = fi ? fi->nullable : pgtype_nullable(stmt, field_type);
|
||||||
|
inolog("COLUMN_NULLABLE=%d\n", value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_OWNER_NAME: /* == SQL_DESC_SCHEMA_NAME */
|
case SQL_COLUMN_OWNER_NAME: /* == SQL_DESC_SCHEMA_NAME */
|
||||||
@ -623,6 +629,7 @@ PGAPI_ColAttributes(
|
|||||||
|
|
||||||
case SQL_COLUMN_SCALE:
|
case SQL_COLUMN_SCALE:
|
||||||
value = pgtype_scale(stmt, field_type, col_idx);
|
value = pgtype_scale(stmt, field_type, col_idx);
|
||||||
|
inolog("COLUMN_SCALE=%d\n", value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_SEARCHABLE: /* SQL_DESC_SEARCHABLE */
|
case SQL_COLUMN_SEARCHABLE: /* SQL_DESC_SEARCHABLE */
|
||||||
@ -637,6 +644,7 @@ PGAPI_ColAttributes(
|
|||||||
|
|
||||||
case SQL_COLUMN_TYPE: /* == SQL_DESC_CONCISE_TYPE */
|
case SQL_COLUMN_TYPE: /* == SQL_DESC_CONCISE_TYPE */
|
||||||
value = pgtype_to_sqltype(stmt, field_type);
|
value = pgtype_to_sqltype(stmt, field_type);
|
||||||
|
inolog("COLUMN_TYPE=%d\n", value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_TYPE_NAME: /* == SQL_DESC_TYPE_NAME */
|
case SQL_COLUMN_TYPE_NAME: /* == SQL_DESC_TYPE_NAME */
|
||||||
@ -658,7 +666,7 @@ PGAPI_ColAttributes(
|
|||||||
* if (field_type == PG_TYPE_OID) pfDesc = SQL_ATTR_READONLY;
|
* if (field_type == PG_TYPE_OID) pfDesc = SQL_ATTR_READONLY;
|
||||||
* else
|
* else
|
||||||
*/
|
*/
|
||||||
value = SQL_ATTR_WRITE;
|
value = fi ? (fi->updatable ? SQL_ATTR_WRITE : SQL_ATTR_READONLY) : SQL_ATTR_READWRITE_UNKNOWN;
|
||||||
|
|
||||||
mylog("PGAPI_ColAttr: UPDATEABLE = %d\n", value);
|
mylog("PGAPI_ColAttr: UPDATEABLE = %d\n", value);
|
||||||
break;
|
break;
|
||||||
@ -1292,9 +1300,17 @@ PGAPI_ExtendedFetch(
|
|||||||
if (result == SQL_ERROR)
|
if (result == SQL_ERROR)
|
||||||
*(rgfRowStatus + i) = SQL_ROW_ERROR;
|
*(rgfRowStatus + i) = SQL_ROW_ERROR;
|
||||||
#ifdef DRIVER_CURSOR_IMPLEMENT
|
#ifdef DRIVER_CURSOR_IMPLEMENT
|
||||||
/* this should be refined */
|
else if (res->keyset)
|
||||||
else if (result > 10 && result < 20)
|
{
|
||||||
*(rgfRowStatus + i) = result - 10;
|
UWORD pstatus = res->keyset[stmt->currTuple].status & KEYSET_INFO_PUBLIC;
|
||||||
|
if (pstatus != 0)
|
||||||
|
{
|
||||||
|
rgfRowStatus[i] = pstatus;
|
||||||
|
res->keyset[stmt->currTuple].status &= (~KEYSET_INFO_PUBLIC);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rgfRowStatus[i] = SQL_ROW_SUCCESS;
|
||||||
|
}
|
||||||
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
||||||
else
|
else
|
||||||
*(rgfRowStatus + i) = SQL_ROW_SUCCESS;
|
*(rgfRowStatus + i) = SQL_ROW_SUCCESS;
|
||||||
@ -1347,7 +1363,7 @@ PGAPI_MoreResults(
|
|||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
if (stmt && (res = SC_get_Curres(stmt)))
|
if (stmt && (res = SC_get_Curres(stmt)))
|
||||||
SC_get_Curres(stmt) = res->next;
|
SC_set_Curres(stmt, res->next);
|
||||||
if (SC_get_Curres(stmt))
|
if (SC_get_Curres(stmt))
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
return SQL_NO_DATA_FOUND;
|
return SQL_NO_DATA_FOUND;
|
||||||
@ -1358,28 +1374,61 @@ PGAPI_MoreResults(
|
|||||||
/*
|
/*
|
||||||
* Stuff for updatable cursors.
|
* Stuff for updatable cursors.
|
||||||
*/
|
*/
|
||||||
|
static const char *getOidValue(const QResultClass *res, int index)
|
||||||
|
{
|
||||||
|
return QR_get_value_backend_row(res, index, QR_NumResultCols(res) - 1);
|
||||||
|
}
|
||||||
|
static UInt4 getOid(const QResultClass *res, int index)
|
||||||
|
{
|
||||||
|
return res->keyset[index].oid;
|
||||||
|
}
|
||||||
|
static const char *getTidValue(const QResultClass *res, int index)
|
||||||
|
{
|
||||||
|
return QR_get_value_backend_row(res, index, QR_NumResultCols(res) - 2);
|
||||||
|
}
|
||||||
|
static void getTid(const QResultClass *res, int index, UInt4 *blocknum, UInt2 *offset)
|
||||||
|
{
|
||||||
|
*blocknum = res->keyset[index].blocknum;
|
||||||
|
*offset = res->keyset[index].offset;
|
||||||
|
}
|
||||||
|
static void KeySetSet(const QResultClass *res, int index)
|
||||||
|
{
|
||||||
|
int num_fields = res->num_fields;
|
||||||
|
TupleField *tuple = res->backend_tuples + num_fields * index;
|
||||||
|
KeySet *keyset = res->keyset + index;
|
||||||
|
|
||||||
|
sscanf(tuple[num_fields - 2].value, "(%u,%hu)",
|
||||||
|
&keyset->blocknum, &keyset->offset);
|
||||||
|
sscanf(tuple[num_fields - 1].value, "%u", &keyset->oid);
|
||||||
|
}
|
||||||
|
|
||||||
static QResultClass *
|
static QResultClass *
|
||||||
positioned_load(StatementClass *stmt, BOOL latest, int res_cols, UInt4 oid, const char *tidval)
|
positioned_load(StatementClass *stmt, BOOL latest, int res_cols, UInt4 oid, const char *tidval)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
QResultClass *qres;
|
QResultClass *qres;
|
||||||
char selstr[4096];
|
char *selstr;
|
||||||
|
UInt4 len;
|
||||||
|
|
||||||
sprintf(selstr, "select");
|
len = strlen(stmt->load_statement);
|
||||||
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 (tidval)
|
||||||
{
|
{
|
||||||
|
len += 100;
|
||||||
|
selstr = malloc(len);
|
||||||
if (latest)
|
if (latest)
|
||||||
sprintf(selstr, "%s ctid = currtid2('%s', '%s') and",
|
sprintf(selstr, "%s where ctid = currtid2('%s', '%s') and oid = %u", stmt->load_statement, stmt->ti[0]->name, tidval, oid);
|
||||||
selstr, stmt->ti[0]->name, tidval);
|
else
|
||||||
else
|
sprintf(selstr, "%s where ctid = '%s' and oid = %u", stmt->load_statement, tidval, oid);
|
||||||
sprintf(selstr, "%s ctid = '%s' and", selstr, tidval);
|
|
||||||
}
|
}
|
||||||
sprintf(selstr, "%s oid = %u", selstr, oid),
|
else
|
||||||
mylog("selstr=%s\n", selstr);
|
{
|
||||||
qres = CC_send_query(SC_get_conn(stmt), selstr, NULL, TRUE);
|
len += 20;
|
||||||
|
selstr = malloc(len);
|
||||||
|
sprintf(selstr, "%s where oid = %u", stmt->load_statement, oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
mylog("selstr=%s\n", selstr);
|
||||||
|
qres = CC_send_query(SC_get_conn(stmt), selstr, NULL, CLEAR_RESULT_ON_ABORT);
|
||||||
|
free(selstr);
|
||||||
return qres;
|
return qres;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1388,14 +1437,12 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
|
|||||||
{
|
{
|
||||||
int i,
|
int i,
|
||||||
res_cols;
|
res_cols;
|
||||||
UWORD rcnt,
|
UWORD rcnt, global_ridx, offset;
|
||||||
global_ridx;
|
UInt4 oid, blocknum;
|
||||||
UInt4 oid;
|
|
||||||
QResultClass *res,
|
QResultClass *res,
|
||||||
*qres;
|
*qres;
|
||||||
RETCODE ret = SQL_ERROR;
|
RETCODE ret = SQL_ERROR;
|
||||||
char *tidval,
|
char tidval[32];
|
||||||
*oidval;
|
|
||||||
|
|
||||||
mylog("positioned load fi=%x ti=%x\n", stmt->fi, stmt->ti);
|
mylog("positioned load fi=%x ti=%x\n", stmt->fi, stmt->ti);
|
||||||
rcnt = 0;
|
rcnt = 0;
|
||||||
@ -1412,15 +1459,18 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
|
|||||||
}
|
}
|
||||||
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 (!(oid = getOid(res, global_ridx)))
|
||||||
|
return SQL_SUCCESS_WITH_INFO;
|
||||||
|
getTid(res, global_ridx, &blocknum, &offset);
|
||||||
|
sprintf(tidval, "(%u, %u)", blocknum, offset);
|
||||||
|
/*if (!(oidval = getOidValue(res, global_ridx)))
|
||||||
return SQL_SUCCESS_WITH_INFO;
|
return SQL_SUCCESS_WITH_INFO;
|
||||||
sscanf(oidval, "%u", &oid);
|
sscanf(oidval, "%u", &oid);
|
||||||
tidval = QR_get_value_backend_row(res, global_ridx, res_cols - 2);
|
tidval = getTidValue(res, global_ridx);*/
|
||||||
res_cols -= 2;
|
res_cols -= 2;
|
||||||
if (qres = positioned_load(stmt, TRUE, res_cols, oid, tidval), qres)
|
if (qres = positioned_load(stmt, TRUE, res_cols, oid, tidval), qres)
|
||||||
{
|
{
|
||||||
TupleField *tupleo,
|
TupleField *tupleo, *tuplen;
|
||||||
*tuplen;
|
|
||||||
|
|
||||||
rcnt = QR_get_num_tuples(qres);
|
rcnt = QR_get_num_tuples(qres);
|
||||||
tupleo = res->backend_tuples + res->num_fields * global_ridx;
|
tupleo = res->backend_tuples + res->num_fields * global_ridx;
|
||||||
@ -1437,6 +1487,13 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
|
|||||||
tupleo[i].value = tuplen[i].value;
|
tupleo[i].value = tuplen[i].value;
|
||||||
tuplen[i].value = NULL;
|
tuplen[i].value = NULL;
|
||||||
}
|
}
|
||||||
|
if (res->keyset)
|
||||||
|
{
|
||||||
|
if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type &&
|
||||||
|
strcmp(tupleo[res->num_fields - 2].value, tidval))
|
||||||
|
res->keyset[global_ridx].status |= SQL_ROW_UPDATED;
|
||||||
|
KeySetSet(res, global_ridx);
|
||||||
|
}
|
||||||
ret = SQL_SUCCESS;
|
ret = SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1450,6 +1507,7 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
|
|||||||
free(tupleo[res_cols + 1].value);
|
free(tupleo[res_cols + 1].value);
|
||||||
tupleo[res_cols + 1].value = NULL;
|
tupleo[res_cols + 1].value = NULL;
|
||||||
tupleo[res_cols + 1].len = 0;
|
tupleo[res_cols + 1].len = 0;
|
||||||
|
res->keyset[global_ridx].status |= SQL_ROW_DELETED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QR_Destructor(qres);
|
QR_Destructor(qres);
|
||||||
@ -1481,8 +1539,7 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
|
|||||||
}
|
}
|
||||||
if (qres = positioned_load(stmt, TRUE, QR_NumResultCols(res) - 2, oid, tidval), qres)
|
if (qres = positioned_load(stmt, TRUE, QR_NumResultCols(res) - 2, oid, tidval), qres)
|
||||||
{
|
{
|
||||||
TupleField *tupleo,
|
TupleField *tupleo, *tuplen;
|
||||||
*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);
|
||||||
@ -1507,6 +1564,8 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
|
|||||||
QR_Destructor(qres);
|
QR_Destructor(qres);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
if (res->haskeyset)
|
||||||
|
res->keyset = (KeySet *) realloc(res->keyset, sizeof(KeySet) * tuple_size);
|
||||||
res->count_allocated = tuple_size;
|
res->count_allocated = tuple_size;
|
||||||
}
|
}
|
||||||
tupleo = res->backend_tuples + res->num_fields * res->fcount;
|
tupleo = res->backend_tuples + res->num_fields * res->fcount;
|
||||||
@ -1517,6 +1576,7 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
|
|||||||
tupleo[i].value = tuplen[i].value;
|
tupleo[i].value = tuplen[i].value;
|
||||||
tuplen[i].value = NULL;
|
tuplen[i].value = NULL;
|
||||||
}
|
}
|
||||||
|
KeySetSet(res, res->fcount);
|
||||||
res->fcount++;
|
res->fcount++;
|
||||||
ret = SQL_SUCCESS;
|
ret = SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1533,12 +1593,12 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static RETCODE SQL_API
|
static RETCODE SQL_API
|
||||||
irow_update(RETCODE ret, StatementClass *stmt, UWORD irow)
|
irow_update(RETCODE ret, StatementClass *stmt, StatementClass *ustmt, UWORD irow)
|
||||||
{
|
{
|
||||||
if (ret != SQL_ERROR)
|
if (ret != SQL_ERROR)
|
||||||
{
|
{
|
||||||
int updcnt;
|
int updcnt;
|
||||||
const char *cmdstr = QR_get_command(SC_get_Curres(stmt));
|
const char *cmdstr = QR_get_command(SC_get_Curres(ustmt));
|
||||||
|
|
||||||
if (cmdstr &&
|
if (cmdstr &&
|
||||||
sscanf(cmdstr, "UPDATE %d", &updcnt) == 1)
|
sscanf(cmdstr, "UPDATE %d", &updcnt) == 1)
|
||||||
@ -1580,9 +1640,8 @@ SC_pos_update(StatementClass *stmt,
|
|||||||
BindInfoClass *bindings = stmt->bindings;
|
BindInfoClass *bindings = stmt->bindings;
|
||||||
char updstr[4096];
|
char updstr[4096];
|
||||||
RETCODE ret;
|
RETCODE ret;
|
||||||
char *tidval,
|
UInt4 oid, offset, blocknum;
|
||||||
*oidval;
|
UInt2 pgoffset;
|
||||||
UInt4 offset;
|
|
||||||
Int4 *used;
|
Int4 *used;
|
||||||
|
|
||||||
mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, SC_get_Curres(stmt)->base, stmt->fi, stmt->ti);
|
mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, SC_get_Curres(stmt)->base, stmt->fi, stmt->ti);
|
||||||
@ -1597,12 +1656,14 @@ SC_pos_update(StatementClass *stmt,
|
|||||||
}
|
}
|
||||||
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 = getOidValue(res, global_ridx)))*/
|
||||||
|
if (!(oid = getOid(res, global_ridx)))
|
||||||
{
|
{
|
||||||
stmt->errormsg = "The row is already deleted";
|
stmt->errormsg = "The row is already deleted";
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
tidval = QR_get_value_backend_row(res, global_ridx, res_cols - 2);
|
/*tidval = getTidValue(res, global_ridx);*/
|
||||||
|
getTid(res, global_ridx, &blocknum, &pgoffset);
|
||||||
|
|
||||||
sprintf(updstr, "update \"%s\" set", stmt->ti[0]->name);
|
sprintf(updstr, "update \"%s\" set", stmt->ti[0]->name);
|
||||||
num_cols = stmt->nfld;
|
num_cols = stmt->nfld;
|
||||||
@ -1635,8 +1696,10 @@ SC_pos_update(StatementClass *stmt,
|
|||||||
int res_cols = QR_NumResultCols(res);
|
int res_cols = QR_NumResultCols(res);
|
||||||
StatementClass *qstmt;
|
StatementClass *qstmt;
|
||||||
|
|
||||||
sprintf(updstr, "%s where ctid = '%s' and oid = %s", updstr,
|
/*sprintf(updstr, "%s where ctid = '%s' and oid = %s", updstr,
|
||||||
tidval, oidval);
|
tidval, oidval);*/
|
||||||
|
sprintf(updstr, "%s where ctid = '(%u, %u)' and oid = %u", updstr,
|
||||||
|
blocknum, pgoffset, oid);
|
||||||
mylog("updstr=%s\n", updstr);
|
mylog("updstr=%s\n", updstr);
|
||||||
if (PGAPI_AllocStmt(SC_get_conn(stmt), &hstmt) != SQL_SUCCESS)
|
if (PGAPI_AllocStmt(SC_get_conn(stmt), &hstmt) != SQL_SUCCESS)
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
@ -1676,11 +1739,13 @@ SC_pos_update(StatementClass *stmt,
|
|||||||
stmt->errormsg = "SetPos with data_at_exec not yet supported";
|
stmt->errormsg = "SetPos with data_at_exec not yet supported";
|
||||||
ret = SQL_ERROR;
|
ret = SQL_ERROR;
|
||||||
}
|
}
|
||||||
ret = irow_update(ret, qstmt, irow);
|
ret = irow_update(ret, stmt, qstmt, irow);
|
||||||
PGAPI_FreeStmt(hstmt, SQL_DROP);
|
PGAPI_FreeStmt(hstmt, SQL_DROP);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ret = SQL_SUCCESS_WITH_INFO;
|
ret = SQL_SUCCESS_WITH_INFO;
|
||||||
|
if (SQL_SUCCESS == ret && res->keyset)
|
||||||
|
res->keyset[global_ridx].status |= (SQL_ROW_UPDATED | DRV_SELF_UPDATED);
|
||||||
#if (ODBCVER >= 0x0300)
|
#if (ODBCVER >= 0x0300)
|
||||||
if (stmt->options.rowStatusArray)
|
if (stmt->options.rowStatusArray)
|
||||||
{
|
{
|
||||||
@ -1689,9 +1754,8 @@ SC_pos_update(StatementClass *stmt,
|
|||||||
case SQL_SUCCESS:
|
case SQL_SUCCESS:
|
||||||
stmt->options.rowStatusArray[irow] = SQL_ROW_UPDATED;
|
stmt->options.rowStatusArray[irow] = SQL_ROW_UPDATED;
|
||||||
break;
|
break;
|
||||||
case SQL_SUCCESS_WITH_INFO:
|
default:
|
||||||
stmt->options.rowStatusArray[irow] = SQL_ROW_SUCCESS_WITH_INFO;
|
stmt->options.rowStatusArray[irow] = ret;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* ODBCVER */
|
#endif /* ODBCVER */
|
||||||
@ -1703,13 +1767,13 @@ SC_pos_delete(StatementClass *stmt,
|
|||||||
UWORD irow)
|
UWORD irow)
|
||||||
{
|
{
|
||||||
int res_cols;
|
int res_cols;
|
||||||
UWORD global_ridx;
|
UWORD global_ridx, offset;
|
||||||
QResultClass *res,
|
QResultClass *res, *qres;
|
||||||
*qres;
|
|
||||||
BindInfoClass *bindings = stmt->bindings;
|
BindInfoClass *bindings = stmt->bindings;
|
||||||
char dltstr[4096];
|
char dltstr[4096];
|
||||||
RETCODE ret;
|
RETCODE ret;
|
||||||
char *oidval;
|
/*const char *oidval;*/
|
||||||
|
UInt4 oid, blocknum;
|
||||||
|
|
||||||
mylog("POS DELETE fi=%x ti=%x\n", stmt->fi, stmt->ti);
|
mylog("POS DELETE fi=%x ti=%x\n", stmt->fi, stmt->ti);
|
||||||
if (!(res = SC_get_Curres(stmt)))
|
if (!(res = SC_get_Curres(stmt)))
|
||||||
@ -1723,18 +1787,20 @@ SC_pos_delete(StatementClass *stmt,
|
|||||||
}
|
}
|
||||||
res_cols = QR_NumResultCols(res);
|
res_cols = QR_NumResultCols(res);
|
||||||
global_ridx = irow + stmt->rowset_start;
|
global_ridx = irow + stmt->rowset_start;
|
||||||
if (!(oidval = QR_get_value_backend_row(res, global_ridx, res_cols - 1)))
|
/* if (!(oidval = getOidValue(res, global_ridx)))*/
|
||||||
|
if (!(oid = getOid(res, global_ridx)))
|
||||||
{
|
{
|
||||||
stmt->errormsg = "The row is already deleted";
|
stmt->errormsg = "The row is already deleted";
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
sprintf(dltstr, "delete from \"%s\" where ctid = '%s' and oid = %s",
|
getTid(res, global_ridx, &blocknum, &offset);
|
||||||
stmt->ti[0]->name,
|
/*sprintf(dltstr, "delete from \"%s\" where ctid = '%s' and oid = %s",*/
|
||||||
QR_get_value_backend_row(SC_get_Curres(stmt), global_ridx, res_cols - 2),
|
sprintf(dltstr, "delete from \"%s\" where ctid = '(%u, %u)' and oid = %u",
|
||||||
oidval);
|
stmt->ti[0]->name, blocknum, offset, oid);
|
||||||
|
|
||||||
mylog("dltstr=%s\n", dltstr);
|
mylog("dltstr=%s\n", dltstr);
|
||||||
qres = CC_send_query(SC_get_conn(stmt), dltstr, NULL, TRUE);
|
qres = CC_send_query(SC_get_conn(stmt), dltstr, NULL, CLEAR_RESULT_ON_ABORT);
|
||||||
|
ret = SQL_SUCCESS;
|
||||||
if (qres && QR_command_successful(qres))
|
if (qres && QR_command_successful(qres))
|
||||||
{
|
{
|
||||||
int dltcnt;
|
int dltcnt;
|
||||||
@ -1769,6 +1835,8 @@ SC_pos_delete(StatementClass *stmt,
|
|||||||
}
|
}
|
||||||
if (qres)
|
if (qres)
|
||||||
QR_Destructor(qres);
|
QR_Destructor(qres);
|
||||||
|
if (SQL_SUCCESS == ret && res->keyset)
|
||||||
|
res->keyset[global_ridx].status |= (SQL_ROW_DELETED | DRV_SELF_DELETED);
|
||||||
#if (ODBCVER >= 0x0300)
|
#if (ODBCVER >= 0x0300)
|
||||||
if (stmt->options.rowStatusArray)
|
if (stmt->options.rowStatusArray)
|
||||||
{
|
{
|
||||||
@ -1777,9 +1845,8 @@ SC_pos_delete(StatementClass *stmt,
|
|||||||
case SQL_SUCCESS:
|
case SQL_SUCCESS:
|
||||||
stmt->options.rowStatusArray[irow] = SQL_ROW_DELETED;
|
stmt->options.rowStatusArray[irow] = SQL_ROW_DELETED;
|
||||||
break;
|
break;
|
||||||
case SQL_SUCCESS_WITH_INFO:
|
default:
|
||||||
stmt->options.rowStatusArray[irow] = SQL_ROW_SUCCESS_WITH_INFO;
|
stmt->options.rowStatusArray[irow] = ret;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* ODBCVER */
|
#endif /* ODBCVER */
|
||||||
@ -1787,13 +1854,13 @@ SC_pos_delete(StatementClass *stmt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static RETCODE SQL_API
|
static RETCODE SQL_API
|
||||||
irow_insert(RETCODE ret, StatementClass *stmt, int addpos)
|
irow_insert(RETCODE ret, StatementClass *stmt, StatementClass *istmt, int addpos)
|
||||||
{
|
{
|
||||||
if (ret != SQL_ERROR)
|
if (ret != SQL_ERROR)
|
||||||
{
|
{
|
||||||
int addcnt;
|
int addcnt;
|
||||||
UInt4 oid;
|
UInt4 oid;
|
||||||
const char *cmdstr = QR_get_command(SC_get_Curres(stmt));
|
const char *cmdstr = QR_get_command(SC_get_Curres(istmt));
|
||||||
|
|
||||||
if (cmdstr &&
|
if (cmdstr &&
|
||||||
sscanf(cmdstr, "INSERT %u %d", &oid, &addcnt) == 2 &&
|
sscanf(cmdstr, "INSERT %u %d", &oid, &addcnt) == 2 &&
|
||||||
@ -1802,12 +1869,14 @@ irow_insert(RETCODE ret, StatementClass *stmt, int addpos)
|
|||||||
SC_pos_newload(stmt, oid, NULL);
|
SC_pos_newload(stmt, oid, NULL);
|
||||||
if (stmt->bookmark.buffer)
|
if (stmt->bookmark.buffer)
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
UInt4 offset = stmt->options.row_offset_ptr ? *stmt->options.row_offset_ptr : 0;
|
||||||
|
|
||||||
sprintf(buf, "%ld", addpos);
|
sprintf(buf, "%ld", addpos + 1);
|
||||||
copy_and_convert_field(stmt, 0, buf,
|
copy_and_convert_field(stmt, 0, buf,
|
||||||
SQL_C_ULONG, stmt->bookmark.buffer,
|
SQL_C_ULONG, stmt->bookmark.buffer + offset,
|
||||||
0, stmt->bookmark.used);
|
0, stmt->bookmark.used ? stmt->bookmark.used
|
||||||
|
+ (offset >> 2) : NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1882,6 +1951,7 @@ SC_pos_add(StatementClass *stmt,
|
|||||||
}
|
}
|
||||||
if (add_cols > 0)
|
if (add_cols > 0)
|
||||||
{
|
{
|
||||||
|
int brow_save;
|
||||||
|
|
||||||
sprintf(addstr, "%s) values (", addstr);
|
sprintf(addstr, "%s) values (", addstr);
|
||||||
for (i = 0; i < add_cols; i++)
|
for (i = 0; i < add_cols; i++)
|
||||||
@ -1907,11 +1977,16 @@ SC_pos_add(StatementClass *stmt,
|
|||||||
stmt->errormsg = "SetPos with data_at_exec not yet supported";
|
stmt->errormsg = "SetPos with data_at_exec not yet supported";
|
||||||
ret = SQL_ERROR;
|
ret = SQL_ERROR;
|
||||||
}
|
}
|
||||||
ret = irow_insert(ret, qstmt, res->fcount);
|
brow_save = stmt->bind_row;
|
||||||
|
stmt->bind_row = irow;
|
||||||
|
ret = irow_insert(ret, stmt, qstmt, res->fcount);
|
||||||
|
stmt->bind_row = brow_save;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ret = SQL_SUCCESS_WITH_INFO;
|
ret = SQL_SUCCESS_WITH_INFO;
|
||||||
PGAPI_FreeStmt(hstmt, SQL_DROP);
|
PGAPI_FreeStmt(hstmt, SQL_DROP);
|
||||||
|
if (SQL_SUCCESS == ret && res->keyset)
|
||||||
|
res->keyset[res->fcount - 1].status |= DRV_SELF_ADDED;
|
||||||
#if (ODBCVER >= 0x0300)
|
#if (ODBCVER >= 0x0300)
|
||||||
if (stmt->options.rowStatusArray)
|
if (stmt->options.rowStatusArray)
|
||||||
{
|
{
|
||||||
@ -1920,9 +1995,8 @@ SC_pos_add(StatementClass *stmt,
|
|||||||
case SQL_SUCCESS:
|
case SQL_SUCCESS:
|
||||||
stmt->options.rowStatusArray[irow] = SQL_ROW_ADDED;
|
stmt->options.rowStatusArray[irow] = SQL_ROW_ADDED;
|
||||||
break;
|
break;
|
||||||
case SQL_SUCCESS_WITH_INFO:
|
default:
|
||||||
stmt->options.rowStatusArray[irow] = SQL_ROW_SUCCESS_WITH_INFO;
|
stmt->options.rowStatusArray[irow] = ret;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* ODBCVER */
|
#endif /* ODBCVER */
|
||||||
@ -1947,6 +2021,7 @@ PGAPI_SetPos(
|
|||||||
UWORD fLock)
|
UWORD fLock)
|
||||||
{
|
{
|
||||||
static char *func = "PGAPI_SetPos";
|
static char *func = "PGAPI_SetPos";
|
||||||
|
RETCODE ret;
|
||||||
StatementClass *stmt = (StatementClass *) hstmt;
|
StatementClass *stmt = (StatementClass *) hstmt;
|
||||||
QResultClass *res;
|
QResultClass *res;
|
||||||
int num_cols,
|
int num_cols,
|
||||||
@ -1960,7 +2035,7 @@ PGAPI_SetPos(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DRIVER_CURSOR_IMPLEMENT
|
#ifdef DRIVER_CURSOR_IMPLEMENT
|
||||||
mylog("SetPos fOption=%d irow=%d lock=%d currt=%d\n", fOption, irow, fLock, stmt->currTuple);
|
mylog("%s fOption=%d irow=%d lock=%d currt=%d\n", func, fOption, irow, fLock, stmt->currTuple);
|
||||||
if (stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)
|
if (stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)
|
||||||
;
|
;
|
||||||
else
|
else
|
||||||
@ -1982,12 +2057,40 @@ PGAPI_SetPos(
|
|||||||
}
|
}
|
||||||
num_cols = QR_NumResultCols(res);
|
num_cols = QR_NumResultCols(res);
|
||||||
|
|
||||||
if (irow == 0)
|
if (irow == 0) /* bulk operation */
|
||||||
{
|
{
|
||||||
stmt->errornumber = STMT_ROW_OUT_OF_RANGE;
|
int processed;
|
||||||
stmt->errormsg = "Driver does not support Bulk operations.";
|
|
||||||
SC_log_error(func, "", stmt);
|
if (SQL_POSITION == fOption)
|
||||||
return SQL_ERROR;
|
{
|
||||||
|
stmt->errornumber = STMT_ROW_OUT_OF_RANGE;
|
||||||
|
stmt->errormsg = "Bulk Fresh operations not allowed.";
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
ret = SQL_SUCCESS;
|
||||||
|
for (i = 0, processed = 0; i < stmt->options.rowset_size; i++)
|
||||||
|
{
|
||||||
|
#if (ODBCVER >= 0x0300)
|
||||||
|
if (!stmt->options.row_operation_ptr || stmt->options.row_operation_ptr[i] == SQL_ROW_PROCEED)
|
||||||
|
{
|
||||||
|
#endif /* ODBCVER */
|
||||||
|
if (ret = PGAPI_SetPos(hstmt, (UWORD) (i + 1), fOption, fLock), SQL_ERROR == ret)
|
||||||
|
break;
|
||||||
|
processed++;
|
||||||
|
#if (ODBCVER >= 0x0300)
|
||||||
|
}
|
||||||
|
#endif /* ODBCVER */
|
||||||
|
}
|
||||||
|
if (processed > 0 && SQL_ERROR == ret)
|
||||||
|
{
|
||||||
|
processed++;
|
||||||
|
ret = SQL_SUCCESS_WITH_INFO;
|
||||||
|
stmt->errornumber = STMT_ERROR_IN_ROW;
|
||||||
|
}
|
||||||
|
if (stmt->options.rowsFetched)
|
||||||
|
*stmt->options.rowsFetched = processed;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (irow > stmt->last_fetch_count)
|
if (irow > stmt->last_fetch_count)
|
||||||
|
@ -242,6 +242,7 @@ SC_Constructor(void)
|
|||||||
|
|
||||||
rv->statement = NULL;
|
rv->statement = NULL;
|
||||||
rv->stmt_with_params = NULL;
|
rv->stmt_with_params = NULL;
|
||||||
|
rv->load_statement = NULL;
|
||||||
rv->stmt_size_limit = -1;
|
rv->stmt_size_limit = -1;
|
||||||
rv->statement_type = STMT_TYPE_UNKNOWN;
|
rv->statement_type = STMT_TYPE_UNKNOWN;
|
||||||
|
|
||||||
@ -318,6 +319,8 @@ SC_Destructor(StatementClass *self)
|
|||||||
free(self->stmt_with_params);
|
free(self->stmt_with_params);
|
||||||
self->stmt_with_params = NULL;
|
self->stmt_with_params = NULL;
|
||||||
}
|
}
|
||||||
|
if (self->load_statement)
|
||||||
|
free(self->load_statement);
|
||||||
|
|
||||||
SC_free_params(self, STMT_FREE_PARAMS_ALL);
|
SC_free_params(self, STMT_FREE_PARAMS_ALL);
|
||||||
|
|
||||||
@ -548,6 +551,12 @@ SC_recycle_statement(StatementClass *self)
|
|||||||
* SQLParamData/SQLPutData is called.
|
* SQLParamData/SQLPutData is called.
|
||||||
*/
|
*/
|
||||||
SC_free_params(self, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY);
|
SC_free_params(self, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY);
|
||||||
|
if (self->stmt_with_params)
|
||||||
|
free(self->stmt_with_params);
|
||||||
|
self->stmt_with_params = NULL;
|
||||||
|
if (self->load_statement)
|
||||||
|
free(self->load_statement);
|
||||||
|
self->load_statement = NULL;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -635,12 +644,16 @@ SC_create_errormsg(StatementClass *self)
|
|||||||
QResultClass *res = SC_get_Curres(self);
|
QResultClass *res = SC_get_Curres(self);
|
||||||
ConnectionClass *conn = self->hdbc;
|
ConnectionClass *conn = self->hdbc;
|
||||||
int pos;
|
int pos;
|
||||||
|
BOOL detailmsg = FALSE;
|
||||||
static char msg[4096];
|
static char msg[4096];
|
||||||
|
|
||||||
msg[0] = '\0';
|
msg[0] = '\0';
|
||||||
|
|
||||||
if (res && res->message)
|
if (res && res->message)
|
||||||
|
{
|
||||||
strcpy(msg, res->message);
|
strcpy(msg, res->message);
|
||||||
|
detailmsg = TRUE;
|
||||||
|
}
|
||||||
else if (self->errormsg)
|
else if (self->errormsg)
|
||||||
strcpy(msg, self->errormsg);
|
strcpy(msg, self->errormsg);
|
||||||
|
|
||||||
@ -660,10 +673,10 @@ SC_create_errormsg(StatementClass *self)
|
|||||||
{
|
{
|
||||||
SocketClass *sock = conn->sock;
|
SocketClass *sock = conn->sock;
|
||||||
|
|
||||||
if (conn->errormsg && conn->errormsg[0] != '\0')
|
if (!detailmsg && conn->errormsg && conn->errormsg[0] != '\0')
|
||||||
{
|
{
|
||||||
pos = strlen(msg);
|
pos = strlen(msg);
|
||||||
/*sprintf(&msg[pos], ";\n%s", conn->errormsg);*/
|
sprintf(&msg[pos], ";\n%s", conn->errormsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock && sock->errormsg && sock->errormsg[0] != '\0')
|
if (sock && sock->errormsg && sock->errormsg[0] != '\0')
|
||||||
@ -722,9 +735,6 @@ SC_fetch(StatementClass *self)
|
|||||||
int retval,
|
int retval,
|
||||||
result;
|
result;
|
||||||
|
|
||||||
#ifdef DRIVER_CURSOR_IMPLEMENT
|
|
||||||
int updret;
|
|
||||||
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
|
||||||
Int2 num_cols,
|
Int2 num_cols,
|
||||||
lf;
|
lf;
|
||||||
Oid type;
|
Oid type;
|
||||||
@ -799,20 +809,13 @@ SC_fetch(StatementClass *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DRIVER_CURSOR_IMPLEMENT
|
#ifdef DRIVER_CURSOR_IMPLEMENT
|
||||||
updret = 0;
|
|
||||||
if (self->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)
|
if (self->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)
|
||||||
{
|
{
|
||||||
if (!QR_get_value_backend_row(res, self->currTuple, num_cols - 1))
|
|
||||||
updret = SQL_ROW_DELETED;
|
|
||||||
num_cols -= 2;
|
num_cols -= 2;
|
||||||
}
|
}
|
||||||
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
||||||
if (self->options.retrieve_data == SQL_RD_OFF) /* data isn't required */
|
if (self->options.retrieve_data == SQL_RD_OFF) /* data isn't required */
|
||||||
#ifdef DRIVER_CURSOR_IMPLEMENT
|
|
||||||
return updret ? updret + 10 : SQL_SUCCESS;
|
|
||||||
#else
|
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
|
||||||
for (lf = 0; lf < num_cols; lf++)
|
for (lf = 0; lf < num_cols; lf++)
|
||||||
{
|
{
|
||||||
mylog("fetch: cols=%d, lf=%d, self = %u, self->bindings = %u, buffer[] = %u\n", num_cols, lf, self, self->bindings, self->bindings[lf].buffer);
|
mylog("fetch: cols=%d, lf=%d, self = %u, self->bindings = %u, buffer[] = %u\n", num_cols, lf, self, self->bindings, self->bindings[lf].buffer);
|
||||||
@ -893,10 +896,6 @@ SC_fetch(StatementClass *self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DRIVER_CURSOR_IMPLEMENT
|
|
||||||
if (updret)
|
|
||||||
result = updret + 10;
|
|
||||||
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -955,11 +954,12 @@ SC_execute(StatementClass *self)
|
|||||||
if (self->statement_type == STMT_TYPE_SELECT)
|
if (self->statement_type == STMT_TYPE_SELECT)
|
||||||
{
|
{
|
||||||
char fetch[128];
|
char fetch[128];
|
||||||
|
UDWORD qflag = (SQL_CONCUR_ROWVER == self->options.scroll_concurrency ? CREATE_KEYSET : 0);
|
||||||
|
|
||||||
mylog(" Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);
|
mylog(" Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);
|
||||||
|
|
||||||
/* send the declare/select */
|
/* send the declare/select */
|
||||||
res = CC_send_query(conn, self->stmt_with_params, NULL, FALSE);
|
res = CC_send_query(conn, self->stmt_with_params, NULL, qflag);
|
||||||
if (SC_is_fetchcursor(self) && res != NULL &&
|
if (SC_is_fetchcursor(self) && res != NULL &&
|
||||||
QR_command_successful(res))
|
QR_command_successful(res))
|
||||||
{
|
{
|
||||||
@ -982,7 +982,7 @@ SC_execute(StatementClass *self)
|
|||||||
*/
|
*/
|
||||||
sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name);
|
sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name);
|
||||||
|
|
||||||
res = CC_send_query(conn, fetch, &qi, FALSE);
|
res = CC_send_query(conn, fetch, &qi, qflag);
|
||||||
}
|
}
|
||||||
mylog(" done sending the query:\n");
|
mylog(" done sending the query:\n");
|
||||||
}
|
}
|
||||||
@ -990,7 +990,7 @@ SC_execute(StatementClass *self)
|
|||||||
{
|
{
|
||||||
/* not a SELECT statement so don't use a cursor */
|
/* not a SELECT statement so don't use a cursor */
|
||||||
mylog(" it's NOT a select statement: stmt=%u\n", self);
|
mylog(" it's NOT a select statement: stmt=%u\n", self);
|
||||||
res = CC_send_query(conn, self->stmt_with_params, NULL, FALSE);
|
res = CC_send_query(conn, self->stmt_with_params, NULL, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We shouldn't send COMMIT. Postgres backend does the autocommit
|
* We shouldn't send COMMIT. Postgres backend does the autocommit
|
||||||
|
@ -76,6 +76,7 @@ typedef enum
|
|||||||
#define STMT_BAD_ERROR 27
|
#define STMT_BAD_ERROR 27
|
||||||
#define STMT_INVALID_OPTION_IDENTIFIER 28
|
#define STMT_INVALID_OPTION_IDENTIFIER 28
|
||||||
#define STMT_RETURN_NULL_WITHOUT_INDICATOR 29
|
#define STMT_RETURN_NULL_WITHOUT_INDICATOR 29
|
||||||
|
#define STMT_ERROR_IN_ROW 30
|
||||||
|
|
||||||
/* statement types */
|
/* statement types */
|
||||||
enum
|
enum
|
||||||
@ -135,6 +136,7 @@ typedef struct
|
|||||||
char quote;
|
char quote;
|
||||||
char dquote;
|
char dquote;
|
||||||
char numeric;
|
char numeric;
|
||||||
|
char updatable;
|
||||||
char dot[MAX_TABLE_LEN + 1];
|
char dot[MAX_TABLE_LEN + 1];
|
||||||
char name[MAX_COLUMN_LEN + 1];
|
char name[MAX_COLUMN_LEN + 1];
|
||||||
char alias[MAX_COLUMN_LEN + 1];
|
char alias[MAX_COLUMN_LEN + 1];
|
||||||
@ -219,11 +221,15 @@ struct StatementClass_
|
|||||||
char miscinfo;
|
char miscinfo;
|
||||||
SWORD errorpos;
|
SWORD errorpos;
|
||||||
SWORD error_recsize;
|
SWORD error_recsize;
|
||||||
|
char *load_statement; /* to (re)load updatable individual rows */
|
||||||
|
Int4 from_pos;
|
||||||
|
Int4 where_pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SC_get_conn(a) (a->hdbc)
|
#define SC_get_conn(a) (a->hdbc)
|
||||||
#define SC_set_Result(a, b) (a->result = a->curres = b)
|
#define SC_set_Result(a, b) (a->result = a->curres = b)
|
||||||
#define SC_get_Result(a) (a->result)
|
#define SC_get_Result(a) (a->result)
|
||||||
|
#define SC_set_Curres(a, b) (a->curres = b)
|
||||||
#define SC_get_Curres(a) (a->curres)
|
#define SC_get_Curres(a) (a->curres)
|
||||||
|
|
||||||
/* options for SC_free_params() */
|
/* options for SC_free_params() */
|
||||||
|
@ -30,6 +30,19 @@ struct TupleNode_
|
|||||||
TupleField tuple[1];
|
TupleField tuple[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* keyset(TID + OID) info */
|
||||||
|
struct KeySet_
|
||||||
|
{
|
||||||
|
UWORD status;
|
||||||
|
UWORD offset;
|
||||||
|
UDWORD blocknum;
|
||||||
|
UDWORD oid;
|
||||||
|
};
|
||||||
|
#define KEYSET_INFO_PUBLIC 0x0f
|
||||||
|
#define DRV_SELF_ADDED (1L << 4)
|
||||||
|
#define DRV_SELF_DELETED (1L << 5)
|
||||||
|
#define DRV_SELF_UPDATED (1L << 6)
|
||||||
|
|
||||||
/* These macros are wrappers for the corresponding set_tuplefield functions
|
/* These macros are wrappers for the corresponding set_tuplefield functions
|
||||||
but these handle automatic NULL determination and call set_tuplefield_null()
|
but these handle automatic NULL determination and call set_tuplefield_null()
|
||||||
if appropriate for the datatype (used by SQLGetTypeInfo).
|
if appropriate for the datatype (used by SQLGetTypeInfo).
|
||||||
|
Loading…
x
Reference in New Issue
Block a user