Skip to content

Commit 01e3226

Browse files
author
Hiroshi Inoue
committed
1) Internal improvements to handle updatable cursors(1st cut).
2) Fix a bug in SQLColAttribute().
1 parent f362dce commit 01e3226

20 files changed

+414
-372
lines changed

src/interfaces/odbc/connection.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ CC_begin(ConnectionClass *self)
374374
char ret = TRUE;
375375
if (!CC_is_in_trans(self))
376376
{
377-
QResultClass *res = CC_send_query(self, "BEGIN", NULL, TRUE);
377+
QResultClass *res = CC_send_query(self, "BEGIN", NULL, CLEAR_RESULT_ON_ABORT);
378378
mylog("CC_begin: sending BEGIN!\n");
379379

380380
if (res != NULL)
@@ -401,7 +401,7 @@ CC_commit(ConnectionClass *self)
401401
char ret = FALSE;
402402
if (CC_is_in_trans(self))
403403
{
404-
QResultClass *res = CC_send_query(self, "COMMIT", NULL, TRUE);
404+
QResultClass *res = CC_send_query(self, "COMMIT", NULL, CLEAR_RESULT_ON_ABORT);
405405
mylog("CC_commit: sending COMMIT!\n");
406406

407407
CC_set_no_trans(self);
@@ -427,7 +427,7 @@ CC_abort(ConnectionClass *self)
427427
{
428428
if (CC_is_in_trans(self))
429429
{
430-
QResultClass *res = CC_send_query(self, "ROLLBACK", NULL, TRUE);
430+
QResultClass *res = CC_send_query(self, "ROLLBACK", NULL, CLEAR_RESULT_ON_ABORT);
431431
mylog("CC_abort: sending ABORT!\n");
432432

433433
CC_set_no_trans(self);
@@ -919,7 +919,7 @@ CC_connect(ConnectionClass *self, char do_password)
919919
*/
920920
mylog("sending an empty query...\n");
921921

922-
res = CC_send_query(self, " ", NULL, TRUE);
922+
res = CC_send_query(self, " ", NULL, CLEAR_RESULT_ON_ABORT);
923923
if (res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY)
924924
{
925925
mylog("got no result from the empty query. (probably database does not exist)\n");
@@ -956,7 +956,7 @@ CC_connect(ConnectionClass *self, char do_password)
956956
* Multibyte handling is available ?
957957
*/
958958
#ifdef MULTIBYTE
959-
if (PG_VERSION_GE(self, 7.0))
959+
if (PG_VERSION_GE(self, 6.4))
960960
{
961961
CC_lookup_characterset(self);
962962
if (self->errornumber != 0)
@@ -977,7 +977,7 @@ CC_connect(ConnectionClass *self, char do_password)
977977
if (self->client_encoding)
978978
free(self->client_encoding);
979979
self->client_encoding = NULL;
980-
if (res = CC_send_query(self, "set client_encoding to 'UTF8'", NULL, TRUE), res)
980+
if (res = CC_send_query(self, "set client_encoding to 'UTF8'", NULL, CLEAR_RESULT_ON_ABORT), res)
981981
{
982982
self->client_encoding = strdup("UNICODE");
983983
QR_Destructor(res);
@@ -991,7 +991,7 @@ CC_connect(ConnectionClass *self, char do_password)
991991
else if (self->unicode)
992992
{
993993
self->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
994-
self->errormsg = "Unicode isn't supported before 7.0";
994+
self->errormsg = "Unicode isn't supported before 6.4";
995995
return 0;
996996
}
997997
#endif /* UNICODE_SUPPORT */
@@ -1128,12 +1128,14 @@ CC_get_error(ConnectionClass *self, int *number, char **message)
11281128
* 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
11291129
*/
11301130
QResultClass *
1131-
CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, BOOL clear_result_on_abort)
1131+
CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
11321132
{
11331133
QResultClass *result_in = NULL,
11341134
*cmdres = NULL,
11351135
*retres = NULL,
11361136
*res = NULL;
1137+
BOOL clear_result_on_abort = ((flag & CLEAR_RESULT_ON_ABORT) != 0),
1138+
create_keyset = ((flag & CREATE_KEYSET) != 0);
11371139
char swallow,
11381140
*wq;
11391141
int id;
@@ -1376,6 +1378,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, BOOL clear_resu
13761378
if (query_completed)
13771379
{
13781380
res->next = QR_Constructor();
1381+
if (create_keyset)
1382+
QR_set_haskeyset(res->next);
13791383
mylog("send_query: 'T' no result_in: res = %u\n", res->next);
13801384
if (!res->next)
13811385
{
@@ -1392,6 +1396,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, BOOL clear_resu
13921396
}
13931397
if (!used_passed_result_object)
13941398
{
1399+
if (create_keyset)
1400+
QR_set_haskeyset(res);
13951401
if (!QR_fetch_tuples(res, self, qi ? qi->cursor : NULL))
13961402
{
13971403
self->errornumber = CONNECTION_COULD_NOT_RECEIVE;

src/interfaces/odbc/connection.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ char CC_connect(ConnectionClass *self, char do_password);
305305
char CC_add_statement(ConnectionClass *self, StatementClass *stmt);
306306
char CC_remove_statement(ConnectionClass *self, StatementClass *stmt);
307307
char CC_get_error(ConnectionClass *self, int *number, char **message);
308-
QResultClass *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, BOOL);
308+
QResultClass *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag);
309309
void CC_clear_error(ConnectionClass *self);
310310
char *CC_create_errormsg(ConnectionClass *self);
311311
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);
316316
void CC_log_error(const char *func, const char *desc, const ConnectionClass *self);
317317
int CC_get_max_query_len(const ConnectionClass *self);
318318

319+
/* CC_send_query_options */
320+
#define CLEAR_RESULT_ON_ABORT 1L
321+
#define CREATE_KEYSET (1L << 1) /* create keyset for updatable curosrs */
319322
#endif

src/interfaces/odbc/convert.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,7 @@ copy_statement_with_parameters(StatementClass *stmt)
12911291
#ifdef DRIVER_CURSOR_IMPLEMENT
12921292
BOOL search_from_pos = FALSE;
12931293
#endif /* DRIVER_CURSOR_IMPLEMENT */
1294+
Int4 from_pos = -1, where_pos = -1;
12941295

12951296
if (ci->disallow_premature)
12961297
prepare_dummy_cursor = stmt->pre_executing;
@@ -1326,7 +1327,11 @@ copy_statement_with_parameters(StatementClass *stmt)
13261327
else if (!stmt->ti || stmt->ntab != 1)
13271328
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
13281329
else
1329-
search_from_pos = TRUE;
1330+
{
1331+
/** search_from_pos = TRUE; **/
1332+
from_pos = stmt->from_pos;
1333+
where_pos = stmt->where_pos;
1334+
}
13301335
}
13311336
#endif /* DRIVER_CURSOR_IMPLEMENT */
13321337

@@ -1366,9 +1371,18 @@ copy_statement_with_parameters(StatementClass *stmt)
13661371
#ifdef MULTIBYTE
13671372
make_encoded_str(&encstr, conn, old_statement);
13681373
#endif
1369-
13701374
for (opos = 0; opos < oldstmtlen; opos++)
13711375
{
1376+
if (from_pos == (Int4) opos)
1377+
{
1378+
CVT_APPEND_STR(", CTID, OID ");
1379+
}
1380+
else if (where_pos == (Int4) opos)
1381+
{
1382+
stmt->load_statement = malloc(npos + 1);
1383+
memcpy(stmt->load_statement, new_statement, npos);
1384+
stmt->load_statement[npos] = '\0';
1385+
}
13721386
#ifdef MULTIBYTE
13731387
oldchar = encoded_byte_check(&encstr, opos);
13741388
if (ENCODE_STATUS(encstr) != 0)
@@ -2033,6 +2047,12 @@ copy_statement_with_parameters(StatementClass *stmt)
20332047
#ifdef DRIVER_CURSOR_IMPLEMENT
20342048
if (search_from_pos)
20352049
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
2050+
if (!stmt->load_statement && from_pos >=0)
2051+
{
2052+
stmt->load_statement = malloc(npos + 1);
2053+
memcpy(stmt->load_statement, new_statement, npos);
2054+
stmt->load_statement[npos] = '\0';
2055+
}
20362056
#endif /* DRIVER_CURSOR_IMPLEMENT */
20372057
if (prepare_dummy_cursor && SC_is_pre_executable(stmt))
20382058
{

src/interfaces/odbc/environ.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ PGAPI_StmtError( HSTMT hstmt,
245245
case STMT_INVALID_CURSOR_STATE_ERROR:
246246
strcpy(szSqlState, "24000");
247247
break;
248+
case STMT_ERROR_IN_ROW:
249+
strcpy(szSqlState, "01S01");
250+
break;
248251
case STMT_OPTION_VALUE_CHANGED:
249252
strcpy(szSqlState, "01S02");
250253
break;

src/interfaces/odbc/execute.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ PGAPI_Prepare(HSTMT hstmt,
9494

9595
if (self->statement)
9696
free(self->statement);
97+
if (self->stmt_with_params)
98+
free(self->stmt_with_params);
99+
self->stmt_with_params = NULL;
100+
if (self->load_statement)
101+
free(self->load_statement);
102+
self->load_statement = NULL;
97103

98104
self->statement = make_string(szSqlStr, cbSqlStr, NULL);
99105
if (!self->statement)
@@ -141,6 +147,12 @@ PGAPI_ExecDirect(
141147

142148
if (stmt->statement)
143149
free(stmt->statement);
150+
if (stmt->stmt_with_params)
151+
free(stmt->stmt_with_params);
152+
stmt->stmt_with_params = NULL;
153+
if (stmt->load_statement)
154+
free(stmt->load_statement);
155+
stmt->load_statement = NULL;
144156

145157
/*
146158
* keep a copy of the un-parametrized statement, in case they try to
@@ -421,7 +433,7 @@ PGAPI_Execute(
421433
BOOL in_trans = CC_is_in_trans(conn);
422434
BOOL issued_begin = FALSE,
423435
begin_included = FALSE;
424-
QResultClass *res;
436+
QResultClass *res, *curres;
425437

426438
if (strnicmp(stmt->stmt_with_params, "BEGIN;", 6) == 0)
427439
begin_included = TRUE;
@@ -436,7 +448,7 @@ PGAPI_Execute(
436448
}
437449
/* we are now in a transaction */
438450
CC_set_in_trans(conn);
439-
res = CC_send_query(conn, stmt->stmt_with_params, NULL, TRUE);
451+
res = CC_send_query(conn, stmt->stmt_with_params, NULL, CLEAR_RESULT_ON_ABORT);
440452
if (!res)
441453
{
442454
CC_abort(conn);
@@ -445,6 +457,9 @@ PGAPI_Execute(
445457
return SQL_ERROR;
446458
}
447459
SC_set_Result(stmt, res);
460+
for (curres = res; !curres->num_fields; curres = curres->next)
461+
;
462+
SC_set_Curres(stmt, curres);
448463
if (CC_is_in_autocommit(conn))
449464
{
450465
if (issued_begin)
@@ -518,7 +533,7 @@ PGAPI_Transact(
518533
{
519534
mylog("PGAPI_Transact: sending on conn %d '%s'\n", conn, stmt_string);
520535

521-
res = CC_send_query(conn, stmt_string, NULL, TRUE);
536+
res = CC_send_query(conn, stmt_string, NULL, CLEAR_RESULT_ON_ABORT);
522537
CC_set_no_trans(conn);
523538

524539
if (!res)

src/interfaces/odbc/info.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2858,7 +2858,7 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
28582858
return ret;
28592859
if (!conn->server_encoding)
28602860
{
2861-
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, TRUE), res)
2861+
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, CLEAR_RESULT_ON_ABORT), res)
28622862
{
28632863
if (QR_get_num_tuples(res) > 0)
28642864
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
@@ -2868,11 +2868,11 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
28682868
if (!conn->server_encoding)
28692869
return ret;
28702870
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
2871-
bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
2871+
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
28722872
if (!bError && continueExec)
28732873
{
28742874
sprintf(query, "select OID from pg_class where relname = '%s'", serverTableName);
2875-
if (res = CC_send_query(conn, query, NULL, TRUE), res)
2875+
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
28762876
{
28772877
if (QR_get_num_tuples(res) > 0)
28782878
strcpy(saveoid, QR_get_value_backend_row(res, 0, 0));
@@ -2891,11 +2891,11 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
28912891
}
28922892
/* restore the client encoding */
28932893
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
2894-
bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
2894+
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
28952895
if (bError || !continueExec)
28962896
return ret;
28972897
sprintf(query, "select relname from pg_class where OID = %s", saveoid);
2898-
if (res = CC_send_query(conn, query, NULL, TRUE), res)
2898+
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
28992899
{
29002900
if (QR_get_num_tuples(res) > 0)
29012901
{
@@ -2922,7 +2922,7 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
29222922
return ret;
29232923
if (!conn->server_encoding)
29242924
{
2925-
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, TRUE), res)
2925+
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, CLEAR_RESULT_ON_ABORT), res)
29262926
{
29272927
if (QR_get_num_tuples(res) > 0)
29282928
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
@@ -2932,13 +2932,13 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
29322932
if (!conn->server_encoding)
29332933
return ret;
29342934
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
2935-
bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
2935+
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
29362936
if (!bError && continueExec)
29372937
{
29382938
sprintf(query, "select attrelid, attnum from pg_class, pg_attribute "
29392939
"where relname = '%s' and attrelid = pg_class.oid "
29402940
"and attname = '%s'", serverTableName, serverColumnName);
2941-
if (res = CC_send_query(conn, query, NULL, TRUE), res)
2941+
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
29422942
{
29432943
if (QR_get_num_tuples(res) > 0)
29442944
{
@@ -2960,11 +2960,11 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
29602960
}
29612961
/* restore the cleint encoding */
29622962
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
2963-
bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
2963+
bError = (CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT) == NULL);
29642964
if (bError || !continueExec)
29652965
return ret;
29662966
sprintf(query, "select attname from pg_attribute where attrelid = %s and attnum = %s", saveattrelid, saveattnum);
2967-
if (res = CC_send_query(conn, query, NULL, TRUE), res)
2967+
if (res = CC_send_query(conn, query, NULL, CLEAR_RESULT_ON_ABORT), res)
29682968
{
29692969
if (QR_get_num_tuples(res) > 0)
29702970
{
@@ -3790,7 +3790,7 @@ PGAPI_Procedures(
37903790
" case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc");
37913791
my_strcat(proc_query, " where proname like '%.*s'", szProcName, cbProcName);
37923792

3793-
if (res = CC_send_query(conn, proc_query, NULL, TRUE), !res)
3793+
if (res = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !res)
37943794
{
37953795
stmt->errornumber = STMT_EXEC_ERROR;
37963796
stmt->errormsg = "PGAPI_Procedures query error";
@@ -3927,15 +3927,15 @@ PGAPI_TablePrivileges(
39273927
my_strcat(proc_query, " relname like '%.*s' and", esc_table_name, escTbnamelen);
39283928
}
39293929
strcat(proc_query, " pg_user.usesysid = relowner");
3930-
if (res = CC_send_query(conn, proc_query, NULL, TRUE), !res)
3930+
if (res = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !res)
39313931
{
39323932
stmt->errornumber = STMT_EXEC_ERROR;
39333933
stmt->errormsg = "PGAPI_TablePrivileges query error";
39343934
return SQL_ERROR;
39353935
}
39363936
strncpy_null(proc_query, "select usename, usesysid, usesuper from pg_user", sizeof(proc_query));
39373937
tablecount = QR_get_num_tuples(res);
3938-
if (allures = CC_send_query(conn, proc_query, NULL, TRUE), !allures)
3938+
if (allures = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !allures)
39393939
{
39403940
QR_Destructor(res);
39413941
stmt->errornumber = STMT_EXEC_ERROR;
@@ -3983,7 +3983,7 @@ PGAPI_TablePrivileges(
39833983
char *grolist, *uid, *delm;
39843984

39853985
snprintf(proc_query, sizeof(proc_query) - 1, "select grolist from pg_group where groname = '%s'", user);
3986-
if (gres = CC_send_query(conn, proc_query, NULL, TRUE))
3986+
if (gres = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT))
39873987
{
39883988
grolist = QR_get_value_backend_row(gres, 0, 0);
39893989
if (grolist && grolist[0] == '{')

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy