Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)