Skip to content

Commit 3c16d09

Browse files
author
Hiroshi Inoue
committed
The version is now 7.01.0010.
1) Handle parameter array. 2) Allow re-use of the connection handle after SQLDisconnect. 3) Reject NULL if no indicator specified. 4) Improve the handling of '_' in table name. 5) Unify internal begin/commit/abort operations. 6) Change SQLTables() to return null not "" for the table_owner. 7) Fix a bug about parameter handling reported by Benoit Menendez. 8) Add cast in handling ODBC date/time escape sequences. 9) Fix a bug about cache_size handing in declare/fetch mode. [ODBC3.0 related] 10) Improve the handling of descriptor handles(ODBC3.0). 11) Improve the type handling of some types for ODBC3.0. [Thanks to Marcelo Aceto for his useful patches] 12) Allow nested ODBC escape. 13) Allow changing autocommit on/off inside the transaction block. 14) Improve the handling of ODBC scalar functions.
1 parent b6db89a commit 3c16d09

21 files changed

+1263
-600
lines changed

src/interfaces/odbc/bind.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ PGAPI_BindParameter(
134134
stmt->parameters[ipar].EXEC_buffer = NULL;
135135
}
136136

137+
if (pcbValue && stmt->options.param_offset_ptr)
138+
pcbValue += (*stmt->options.param_offset_ptr >> 2);
137139
/* Data at exec macro only valid for C char/binary data */
138140
if (pcbValue && (*pcbValue == SQL_DATA_AT_EXEC ||
139141
*pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET))

src/interfaces/odbc/connection.c

Lines changed: 92 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -309,12 +309,6 @@ CC_Destructor(ConnectionClass *self)
309309

310310
mylog("after CC_Cleanup\n");
311311

312-
#ifdef MULTIBYTE
313-
if (self->client_encoding)
314-
free(self->client_encoding);
315-
if (self->server_encoding)
316-
free(self->server_encoding);
317-
#endif /* MULTIBYTE */
318312
/* Free up statement holders */
319313
if (self->stmts)
320314
{
@@ -323,23 +317,6 @@ CC_Destructor(ConnectionClass *self)
323317
}
324318
mylog("after free statement holders\n");
325319

326-
/* Free cached table info */
327-
if (self->col_info)
328-
{
329-
int i;
330-
331-
for (i = 0; i < self->ntables; i++)
332-
{
333-
if (self->col_info[i]->result) /* Free the SQLColumns
334-
* result structure */
335-
QR_Destructor(self->col_info[i]->result);
336-
337-
free(self->col_info[i]);
338-
}
339-
free(self->col_info);
340-
}
341-
342-
343320
free(self);
344321

345322
mylog("exit CC_Destructor\n");
@@ -380,29 +357,77 @@ CC_clear_error(ConnectionClass *self)
380357
}
381358

382359

360+
/*
361+
* Used to begin a transaction.
362+
*/
363+
char
364+
CC_begin(ConnectionClass *self)
365+
{
366+
char ret = TRUE;
367+
if (!CC_is_in_trans(self))
368+
{
369+
QResultClass *res = CC_send_query(self, "BEGIN", NULL);
370+
mylog("CC_begin: sending BEGIN!\n");
371+
372+
if (res != NULL)
373+
{
374+
ret = (!QR_aborted(res) && QR_command_successful(res));
375+
QR_Destructor(res);
376+
if (ret)
377+
CC_set_in_trans(self);
378+
}
379+
else
380+
ret = FALSE;
381+
}
382+
383+
return ret;
384+
}
385+
386+
/*
387+
* Used to commit a transaction.
388+
* We are almost always in the middle of a transaction.
389+
*/
390+
char
391+
CC_commit(ConnectionClass *self)
392+
{
393+
char ret = FALSE;
394+
if (CC_is_in_trans(self))
395+
{
396+
QResultClass *res = CC_send_query(self, "COMMIT", NULL);
397+
mylog("CC_commit: sending COMMIT!\n");
398+
399+
CC_set_no_trans(self);
400+
401+
if (res != NULL)
402+
{
403+
ret = QR_command_successful(res);
404+
QR_Destructor(res);
405+
}
406+
else
407+
ret = FALSE;
408+
}
409+
410+
return ret;
411+
}
412+
383413
/*
384414
* Used to cancel a transaction.
385415
* We are almost always in the middle of a transaction.
386416
*/
387417
char
388418
CC_abort(ConnectionClass *self)
389419
{
390-
QResultClass *res;
391-
392420
if (CC_is_in_trans(self))
393421
{
394-
res = NULL;
395-
422+
QResultClass *res = CC_send_query(self, "ROLLBACK", NULL);
396423
mylog("CC_abort: sending ABORT!\n");
397424

398-
res = CC_send_query(self, "ABORT", NULL);
399425
CC_set_no_trans(self);
400426

401427
if (res != NULL)
402428
QR_Destructor(res);
403429
else
404430
return FALSE;
405-
406431
}
407432

408433
return TRUE;
@@ -461,6 +486,37 @@ CC_cleanup(ConnectionClass *self)
461486
}
462487
#endif
463488

489+
self->status = CONN_NOT_CONNECTED;
490+
self->transact_status = CONN_IN_AUTOCOMMIT;
491+
memset(&self->connInfo, 0, sizeof(ConnInfo));
492+
#ifdef DRIVER_CURSOR_IMPLEMENT
493+
self->connInfo.updatable_cursors = 1;
494+
#endif /* DRIVER_CURSOR_IMPLEMENT */
495+
memcpy(&(self->connInfo.drivers), &globals, sizeof(globals));
496+
#ifdef MULTIBYTE
497+
if (self->client_encoding)
498+
free(self->client_encoding);
499+
self->client_encoding = NULL;
500+
if (self->server_encoding)
501+
free(self->server_encoding);
502+
self->server_encoding = NULL;
503+
#endif /* MULTIBYTE */
504+
/* Free cached table info */
505+
if (self->col_info)
506+
{
507+
int i;
508+
509+
for (i = 0; i < self->ntables; i++)
510+
{
511+
if (self->col_info[i]->result) /* Free the SQLColumns result structure */
512+
QR_Destructor(self->col_info[i]->result);
513+
514+
free(self->col_info[i]);
515+
}
516+
free(self->col_info);
517+
self->col_info = NULL;
518+
}
519+
self->ntables = 0;
464520
mylog("exit CC_Cleanup\n");
465521
return TRUE;
466522
}
@@ -516,7 +572,6 @@ md5_auth_send(ConnectionClass *self, const char *salt)
516572
ConnInfo *ci = &(self->connInfo);
517573
SocketClass *sock = self->sock;
518574

519-
mylog("MD5 user=%s password=%s\n", ci->username, ci->password);
520575
if (!(pwd1 = malloc(MD5_PASSWD_LEN + 1)))
521576
return 1;
522577
if (!EncryptMD5(ci->password, ci->username, strlen(ci->username), pwd1))
@@ -601,9 +656,10 @@ CC_connect(ConnectionClass *self, char do_password)
601656
ci->drivers.conn_settings,
602657
encoding ? encoding : "");
603658
#else
604-
qlog(" extra_systable_prefixes='%s', conn_settings='%s'\n",
659+
qlog(" extra_systable_prefixes='%s', conn_settings='%s', protocol='%s'\n",
605660
ci->drivers.extra_systable_prefixes,
606-
ci->drivers.conn_settings);
661+
ci->drivers.conn_settings,
662+
ci->protocol);
607663
#endif
608664

609665
if (self->status != CONN_NOT_CONNECTED)
@@ -1037,7 +1093,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
10371093
ReadyToReturn,
10381094
tuples_return = FALSE,
10391095
query_completed = FALSE,
1040-
before_64 = PG_VERSION_LT(self, 6.4);
1096+
before_64 = PG_VERSION_LT(self, 6.4),
1097+
used_passed_result_object = FALSE;
10411098

10421099
/* ERROR_MSG_LENGTH is suffcient */
10431100
static char msgbuffer[ERROR_MSG_LENGTH + 1];
@@ -1289,6 +1346,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
12891346
else
12901347
{ /* next fetch, so reuse an existing result */
12911348

1349+
used_passed_result_object = TRUE;
12921350
/*
12931351
* called from QR_next_tuple and must return
12941352
* immediately.
@@ -1373,9 +1431,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
13731431
QR_Destructor(res);
13741432
if (result_in && retres != result_in)
13751433
{
1376-
if (qi && qi->result_in)
1377-
;
1378-
else
1434+
if (!used_passed_result_object)
13791435
QR_Destructor(result_in);
13801436
}
13811437
return retres;

src/interfaces/odbc/connection.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,8 @@ ConnectionClass *CC_Constructor(void);
292292
char CC_Destructor(ConnectionClass *self);
293293
int CC_cursor_count(ConnectionClass *self);
294294
char CC_cleanup(ConnectionClass *self);
295+
char CC_begin(ConnectionClass *self);
296+
char CC_commit(ConnectionClass *self);
295297
char CC_abort(ConnectionClass *self);
296298
int CC_set_translation(ConnectionClass *self);
297299
char CC_connect(ConnectionClass *self, char do_password);

0 commit comments

Comments
 (0)