Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6df395f

Browse files
author
Hiroshi Inoue
committed
1) Add rollback functionality to updatable cursors.
2) Implement some options for SQLGetDescField(). 3) Handle *Inifinity* timestamp for SQL_C_CHAR type output. 4) Separate Unicode conversions from common implementations. 5) Improve internal parse_statement() function.
1 parent 87b0808 commit 6df395f

File tree

17 files changed

+447
-134
lines changed

17 files changed

+447
-134
lines changed

src/interfaces/odbc/bind.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ PGAPI_BindParameter(
6767
opts->parameters[ipar].paramType = fParamType;
6868
opts->parameters[ipar].CType = fCType;
6969
opts->parameters[ipar].SQLType = fSqlType;
70-
opts->parameters[ipar].precision = cbColDef;
71-
opts->parameters[ipar].scale = ibScale;
70+
opts->parameters[ipar].column_size = cbColDef;
71+
opts->parameters[ipar].decimal_digits = ibScale;
7272

7373
/*
7474
* If rebinding a parameter that had data-at-exec stuff in it, then
@@ -276,10 +276,10 @@ PGAPI_DescribeParam(
276276
*pfSqlType = opts->parameters[ipar].SQLType;
277277

278278
if (pcbColDef)
279-
*pcbColDef = opts->parameters[ipar].precision;
279+
*pcbColDef = opts->parameters[ipar].column_size;
280280

281281
if (pibScale)
282-
*pibScale = opts->parameters[ipar].scale;
282+
*pibScale = opts->parameters[ipar].decimal_digits;
283283

284284
if (pfNullable)
285285
*pfNullable = pgtype_nullable(stmt, opts->parameters[ipar].paramType);
@@ -458,8 +458,8 @@ reset_a_parameter_binding(APDFields *self, int ipar)
458458
self->parameters[ipar].EXEC_buffer = NULL;
459459
}
460460
self->parameters[ipar].SQLType = 0;
461-
self->parameters[ipar].precision = 0;
462-
self->parameters[ipar].scale = 0;
461+
self->parameters[ipar].column_size = 0;
462+
self->parameters[ipar].decimal_digits = 0;
463463
self->parameters[ipar].data_at_exec = FALSE;
464464
self->parameters[ipar].lobj_oid = 0;
465465
}

src/interfaces/odbc/bind.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ struct ParameterInfoClass_
4040
Int2 paramType;
4141
Int2 CType;
4242
Int2 SQLType;
43-
UInt4 precision;
44-
Int2 scale;
43+
UInt4 column_size;
44+
Int2 decimal_digits;
4545
Oid lobj_oid;
4646
Int4 *EXEC_used; /* amount of data OR the oid of the large
4747
* object */

src/interfaces/odbc/connection.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ CC_Constructor()
288288
rv->pg_version_minor = 0;
289289
rv->ms_jet = 0;
290290
rv->unicode = 0;
291+
rv->result_uncommitted = 0;
291292
#ifdef MULTIBYTE
292293
rv->client_encoding = NULL;
293294
rv->server_encoding = NULL;
@@ -1110,21 +1111,30 @@ CC_get_error(ConnectionClass *self, int *number, char **message)
11101111
}
11111112

11121113

1113-
void CC_on_commit(ConnectionClass *conn, BOOL set_no_trans)
1114+
void CC_on_commit(ConnectionClass *conn)
11141115
{
11151116
if (CC_is_in_trans(conn))
11161117
{
1117-
if (set_no_trans)
1118-
CC_set_no_trans(conn);
1118+
#ifdef DRIVER_CURSOR_IMPLEMENT
1119+
if (conn->result_uncommitted)
1120+
ProcessRollback(conn, FALSE);
1121+
#endif /* DRIVER_CURSOR_IMPLEMENT */
1122+
CC_set_no_trans(conn);
11191123
}
1124+
conn->result_uncommitted = 0;
11201125
}
11211126
void CC_on_abort(ConnectionClass *conn, BOOL set_no_trans)
11221127
{
11231128
if (CC_is_in_trans(conn))
11241129
{
1130+
#ifdef DRIVER_CURSOR_IMPLEMENT
1131+
if (conn->result_uncommitted)
1132+
ProcessRollback(conn, TRUE);
1133+
#endif /* DRIVER_CURSOR_IMPLEMENT */
11251134
if (set_no_trans)
11261135
CC_set_no_trans(conn);
11271136
}
1137+
conn->result_uncommitted = 0;
11281138
}
11291139

11301140
/*
@@ -1293,11 +1303,11 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
12931303
}
12941304
}
12951305
else if (strnicmp(cmdbuffer, "COMMIT", 6) == 0)
1296-
CC_on_commit(self, TRUE);
1306+
CC_on_commit(self);
12971307
else if (strnicmp(cmdbuffer, "ROLLBACK", 8) == 0)
12981308
CC_on_abort(self, TRUE);
12991309
else if (strnicmp(cmdbuffer, "END", 3) == 0)
1300-
CC_on_commit(self, TRUE);
1310+
CC_on_commit(self);
13011311
else if (strnicmp(cmdbuffer, "ABORT", 5) == 0)
13021312
CC_on_abort(self, TRUE);
13031313

src/interfaces/odbc/connection.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ struct ConnectionClass_
272272
Int2 pg_version_minor;
273273
char ms_jet;
274274
char unicode;
275+
char result_uncommitted;
275276
#ifdef MULTIBYTE
276277
char *client_encoding;
277278
char *server_encoding;
@@ -318,8 +319,9 @@ void CC_lookup_pg_version(ConnectionClass *conn);
318319
void CC_initialize_pg_version(ConnectionClass *conn);
319320
void CC_log_error(const char *func, const char *desc, const ConnectionClass *self);
320321
int CC_get_max_query_len(const ConnectionClass *self);
321-
void CC_on_commit(ConnectionClass *conn, BOOL set_no_trans);
322+
void CC_on_commit(ConnectionClass *conn);
322323
void CC_on_abort(ConnectionClass *conn, BOOL set_no_trans);
324+
void ProcessRollback(ConnectionClass *conn, BOOL undo);
323325

324326
/* CC_send_query_options */
325327
#define CLEAR_RESULT_ON_ABORT 1L

src/interfaces/odbc/convert.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,16 @@ stime2timestamp(const SIMPLE_TIME *st, char *str, BOOL bZone, BOOL precision)
265265
int i;
266266

267267
precstr[0] = '\0';
268+
if (st->infinity > 0)
269+
{
270+
strcpy(str, "Infinity");
271+
return TRUE;
272+
}
273+
else if (st->infinity < 0)
274+
{
275+
strcpy(str, "-Infinity");
276+
return TRUE;
277+
}
268278
if (precision && st->fr)
269279
{
270280
sprintf(precstr, ".%09d", st->fr);
@@ -447,6 +457,27 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
447457
case PG_TYPE_DATETIME:
448458
case PG_TYPE_TIMESTAMP:
449459
st.fr = 0;
460+
st.infinity = 0;
461+
if (strnicmp(value, "infinity", 8) == 0)
462+
{
463+
st.infinity = 1;
464+
st.m = 12;
465+
st.d = 31;
466+
st.y = 9999;
467+
st.hh = 24;
468+
st.mm = 0;
469+
st.ss = 0;
470+
}
471+
if (strnicmp(value, "-infinity", 9) == 0)
472+
{
473+
st.infinity = -1;
474+
st.m = 0;
475+
st.d = 0;
476+
st.y = 0;
477+
st.hh = 0;
478+
st.mm = 0;
479+
st.ss = 0;
480+
}
450481
if (strnicmp(value, "invalid", 7) != 0)
451482
{
452483
BOOL bZone = (field_type != PG_TYPE_TIMESTAMP_NO_TMZONE && PG_VERSION_GE(SC_get_conn(stmt), 7.2));
@@ -2495,7 +2526,7 @@ convert_money(const char *s, char *sout, size_t soutmax)
24952526
* It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value
24962527
*/
24972528
char
2498-
parse_datetime(char *buf, SIMPLE_TIME *st)
2529+
parse_datetime(const char *buf, SIMPLE_TIME *st)
24992530
{
25002531
int y,
25012532
m,

src/interfaces/odbc/convert.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
typedef struct
2727
{
28+
int infinity;
2829
int m;
2930
int d;
3031
int y;
@@ -42,7 +43,7 @@ int copy_statement_with_parameters(StatementClass *stmt);
4243
int convert_escape(const char *value, StatementClass *stmt,
4344
int *npos, int *stsize, const char **val_resume);
4445
BOOL convert_money(const char *s, char *sout, size_t soutmax);
45-
char parse_datetime(char *buf, SIMPLE_TIME *st);
46+
char parse_datetime(const char *buf, SIMPLE_TIME *st);
4647
int convert_linefeeds(const char *s, char *dst, size_t max, BOOL convlf, BOOL *changed);
4748
int convert_special_chars(const char *si, char *dst, int used, BOOL convlf,int ccsc);
4849

src/interfaces/odbc/descriptor.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Comments: See "notice.txt" for copyright and license information.
77
*
8-
* $Id: descriptor.h,v 1.1 2002/03/28 08:08:02 inoue Exp $
8+
* $Id: descriptor.h,v 1.2 2002/04/01 03:01:14 inoue Exp $
99
*
1010
*/
1111

@@ -92,5 +92,8 @@ void IRDFields_free(IRDFields *self);
9292
void IPDFields_free(IPDFields *self);
9393
void ARD_unbind_cols(ARDFields *self, BOOL freeall);
9494
void APD_free_params(APDFields *self, char option);
95+
#if (ODBCVER >= 0x0300)
96+
void Desc_set_error(SQLHDESC hdesc, int errornumber, const char * errormsg);
97+
#endif /* ODBCVER */
9598

9699
#endif

src/interfaces/odbc/odbcapi30.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ SQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
235235
SQLSMALLINT *StringLength)
236236
{
237237
mylog("[[SQLGetDiagField]] Handle=(%u,%x) Rec=%d Id=%d\n", HandleType, Handle, RecNumber, DiagIdentifier);
238-
return SQL_ERROR;
238+
return PGAPI_GetDiagField(HandleType, Handle, RecNumber, DiagIdentifier,
239+
DiagInfo, BufferLength, StringLength);
239240
}
240241

241242
/* SQLError -> SQLDiagRec */

src/interfaces/odbc/odbcapi30w.c

Lines changed: 88 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,25 @@ SQLSetDescFieldW(SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber,
8989
mylog("[SQLSetDescFieldW]");
9090
if (BufferLength > 0)
9191
{
92-
uval = ucs2_to_utf8(Value, BufferLength / 2, &vallen);
93-
val_alloced = TRUE;
92+
switch (FieldIdentifier)
93+
{
94+
case SQL_DESC_BASE_COLUMN_NAME:
95+
case SQL_DESC_BASE_TABLE_NAME:
96+
case SQL_DESC_CATALOG_NAME:
97+
case SQL_DESC_LABEL:
98+
case SQL_DESC_LITERAL_PREFIX:
99+
case SQL_DESC_LITERAL_SUFFIX:
100+
case SQL_DESC_LOCAL_TYPE_NAME:
101+
case SQL_DESC_NAME:
102+
case SQL_DESC_SCHEMA_NAME:
103+
case SQL_DESC_TABLE_NAME:
104+
case SQL_DESC_TYPE_NAME:
105+
uval = ucs2_to_utf8(Value, BufferLength / 2, &vallen);
106+
val_alloced = TRUE;
107+
break;
108+
}
94109
}
95-
else
110+
if (!val_alloced)
96111
{
97112
uval = Value;
98113
vallen = BufferLength;
@@ -109,11 +124,49 @@ SQLGetDescFieldW(SQLHDESC hdesc, SQLSMALLINT iRecord, SQLSMALLINT iField,
109124
SQLINTEGER *pcbValue)
110125
{
111126
RETCODE ret;
112-
char *qstr = NULL, *mtxt = NULL;
127+
BOOL alloced = FALSE;
128+
SQLINTEGER blen, bMax, *pcbV;
129+
char *rgbV = NULL;
113130

114131
mylog("[SQLGetDescFieldW]");
115-
ret = PGAPI_GetDescField(hdesc, iRecord, iField, rgbValue,
116-
cbValueMax, pcbValue);
132+
switch (iField)
133+
{
134+
case SQL_DESC_BASE_COLUMN_NAME:
135+
case SQL_DESC_BASE_TABLE_NAME:
136+
case SQL_DESC_CATALOG_NAME:
137+
case SQL_DESC_LABEL:
138+
case SQL_DESC_LITERAL_PREFIX:
139+
case SQL_DESC_LITERAL_SUFFIX:
140+
case SQL_DESC_LOCAL_TYPE_NAME:
141+
case SQL_DESC_NAME:
142+
case SQL_DESC_SCHEMA_NAME:
143+
case SQL_DESC_TABLE_NAME:
144+
case SQL_DESC_TYPE_NAME:
145+
alloced = TRUE;
146+
bMax = cbValueMax * 3 / 2;
147+
rgbV = malloc(bMax + 1);
148+
pcbV = &blen;
149+
break;
150+
default:
151+
rgbV = rgbValue;
152+
bMax = cbValueMax;
153+
pcbV = pcbValue;
154+
break;
155+
}
156+
ret = PGAPI_GetDescField(hdesc, iRecord, iField, rgbV, bMax, pcbV);
157+
if (alloced)
158+
{
159+
blen = utf8_to_ucs2(rgbV, blen, (SQLWCHAR *) rgbValue, cbValueMax / 2);
160+
if (SQL_SUCCESS == ret && blen * 2 > cbValueMax)
161+
{
162+
ret = SQL_SUCCESS_WITH_INFO;
163+
Desc_set_error(hdesc, STMT_TRUNCATED, "The buffer was too small for the rgbDesc.");
164+
}
165+
if (pcbValue)
166+
*pcbValue = blen * 2;
167+
free(rgbV);
168+
}
169+
117170
return ret;
118171
}
119172

@@ -171,6 +224,9 @@ RETCODE SQL_API SQLColAttributeW(
171224
SQLINTEGER *pfDesc)
172225
{
173226
RETCODE ret;
227+
BOOL alloced = FALSE;
228+
SQLSMALLINT *rgbL, blen, bMax;
229+
char *rgbD = NULL;
174230

175231
mylog("[SQLColAttributeW]");
176232
switch (fDescType)
@@ -187,11 +243,35 @@ RETCODE SQL_API SQLColAttributeW(
187243
case SQL_DESC_TABLE_NAME:
188244
case SQL_DESC_TYPE_NAME:
189245
case SQL_COLUMN_NAME:
246+
alloced = TRUE;
247+
bMax = cbDescMax * 3 / 2;
248+
rgbD = malloc(bMax + 1);
249+
rgbL = &blen;
190250
break;
251+
default:
252+
rgbD = rgbDesc;
253+
bMax = cbDescMax;
254+
rgbL = pcbDesc;
255+
break;
191256
}
192257

193-
ret = PGAPI_ColAttributes(hstmt, icol, fDescType, rgbDesc,
194-
cbDescMax, pcbDesc, pfDesc);
258+
ret = PGAPI_ColAttributes(hstmt, icol, fDescType, rgbD,
259+
bMax, rgbL, pfDesc);
260+
if (alloced)
261+
{
262+
blen = utf8_to_ucs2(rgbD, blen, (SQLWCHAR *) rgbDesc, cbDescMax / 2);
263+
if (SQL_SUCCESS == ret && blen * 2 > cbDescMax)
264+
{
265+
StatementClass *stmt = (StatementClass *) hstmt;
266+
267+
ret = SQL_SUCCESS_WITH_INFO;
268+
stmt->errornumber = STMT_TRUNCATED;
269+
stmt->errormsg = "The buffer was too small for the rgbDesc.";
270+
}
271+
if (pcbDesc)
272+
*pcbDesc = blen * 2;
273+
free(rgbD);
274+
}
195275

196276
return ret;
197277
}

0 commit comments

Comments
 (0)