Skip to content

Commit a80771f

Browse files
author
Byron Nikolaidis
committed
Update to v.0246
1 parent fd262da commit a80771f

20 files changed

+814
-394
lines changed

src/interfaces/odbc/bind.c

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,12 @@ RETCODE SQL_API SQLBindParameter(
3737
SDWORD FAR *pcbValue)
3838
{
3939
StatementClass *stmt = (StatementClass *) hstmt;
40+
char *func="SQLBindParameter";
4041

41-
if( ! stmt)
42+
if( ! stmt) {
43+
SC_log_error(func, "", NULL);
4244
return SQL_INVALID_HANDLE;
45+
}
4346

4447
if(stmt->parameters_allocated < ipar) {
4548
ParameterInfoClass *old_parameters;
@@ -52,6 +55,7 @@ StatementClass *stmt = (StatementClass *) hstmt;
5255
if ( ! stmt->parameters) {
5356
stmt->errornumber = STMT_NO_MEMORY_ERROR;
5457
stmt->errormsg = "Could not allocate memory for statement parameters";
58+
SC_log_error(func, "", stmt);
5559
return SQL_ERROR;
5660
}
5761

@@ -133,53 +137,51 @@ RETCODE SQL_API SQLBindCol(
133137
SDWORD FAR *pcbValue)
134138
{
135139
StatementClass *stmt = (StatementClass *) hstmt;
136-
Int2 numcols;
140+
Int2 numcols = 0;
141+
char *func="SQLBindCol";
137142

138143
mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol);
139144

140-
if ( ! stmt)
145+
if ( ! stmt) {
146+
SC_log_error(func, "", NULL);
141147
return SQL_INVALID_HANDLE;
148+
}
142149

143150
if (icol < 1) {
144151
/* currently we do not support bookmarks */
145152
stmt->errormsg = "Bookmarks are not currently supported.";
146153
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
154+
SC_log_error(func, "", stmt);
147155
return SQL_ERROR;
148156
}
149157

150-
icol--; /* use zero based col numbers */
151-
152158
SC_clear_error(stmt);
153159

154-
if( ! stmt->result) {
155-
stmt->errormsg = "Can't bind columns with a NULL query result structure.";
156-
stmt->errornumber = STMT_SEQUENCE_ERROR;
157-
return SQL_ERROR;
158-
}
159-
160160
if( stmt->status == STMT_EXECUTING) {
161161
stmt->errormsg = "Can't bind columns while statement is still executing.";
162162
stmt->errornumber = STMT_SEQUENCE_ERROR;
163+
SC_log_error(func, "", stmt);
163164
return SQL_ERROR;
164165
}
165166

166-
numcols = QR_NumResultCols(stmt->result);
167-
168-
mylog("SQLBindCol: numcols = %d\n", numcols);
169-
170-
if (icol >= numcols) {
171-
stmt->errornumber = STMT_COLNUM_ERROR;
172-
stmt->errormsg = "Column number too big";
173-
return SQL_ERROR;
174-
}
167+
// allocate enough bindings if not already done
168+
// Most likely, execution of a statement would have setup the
169+
// necessary bindings. But some apps call BindCol before any
170+
// statement is executed.
171+
if ( icol > stmt->bindings_allocated)
172+
extend_bindings(stmt, icol);
175173

174+
// check to see if the bindings were allocated
176175
if ( ! stmt->bindings) {
177-
stmt->errormsg = "Bindings were not allocated properly.";
178-
stmt->errornumber = STMT_SEQUENCE_ERROR;
176+
stmt->errormsg = "Could not allocate memory for bindings.";
177+
stmt->errornumber = STMT_NO_MEMORY_ERROR;
178+
SC_log_error(func, "", stmt);
179179
return SQL_ERROR;
180180
}
181181

182-
if ((cbValueMax == 0) || (rgbValue == NULL)) {
182+
icol--; /* use zero based col numbers from here out */
183+
184+
if (rgbValue == NULL) {
183185
/* we have to unbind the column */
184186
stmt->bindings[icol].buflen = 0;
185187
stmt->bindings[icol].buffer = NULL;
@@ -216,13 +218,17 @@ RETCODE SQL_API SQLDescribeParam(
216218
SWORD FAR *pfNullable)
217219
{
218220
StatementClass *stmt = (StatementClass *) hstmt;
221+
char *func = "SQLDescribeParam";
219222

220-
if( ! stmt)
223+
if( ! stmt) {
224+
SC_log_error(func, "", NULL);
221225
return SQL_INVALID_HANDLE;
226+
}
222227

223228
if( (ipar < 1) || (ipar > stmt->parameters_allocated) ) {
224229
stmt->errormsg = "Invalid parameter number for SQLDescribeParam.";
225230
stmt->errornumber = STMT_BAD_PARAMETER_NUMBER_ERROR;
231+
SC_log_error(func, "", stmt);
226232
return SQL_ERROR;
227233
}
228234

@@ -254,6 +260,9 @@ RETCODE SQL_API SQLParamOptions(
254260
UDWORD crow,
255261
UDWORD FAR *pirow)
256262
{
263+
char *func = "SQLParamOptions";
264+
265+
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
257266
return SQL_ERROR;
258267
}
259268

@@ -273,21 +282,26 @@ RETCODE SQL_API SQLNumParams(
273282
StatementClass *stmt = (StatementClass *) hstmt;
274283
char in_quote = FALSE;
275284
unsigned int i;
285+
char *func = "SQLNumParams";
276286

277-
278-
if(!stmt)
287+
if(!stmt) {
288+
SC_log_error(func, "", NULL);
279289
return SQL_INVALID_HANDLE;
290+
}
280291

281292
if (pcpar)
282293
*pcpar = 0;
283-
else
294+
else {
295+
SC_log_error(func, "pcpar was null", stmt);
284296
return SQL_ERROR;
297+
}
285298

286299

287300
if(!stmt->statement) {
288301
// no statement has been allocated
289302
stmt->errormsg = "SQLNumParams called with no statement ready.";
290303
stmt->errornumber = STMT_SEQUENCE_ERROR;
304+
SC_log_error(func, "", stmt);
291305
return SQL_ERROR;
292306
} else {
293307

@@ -341,6 +355,14 @@ mylog("in extend_bindings: stmt=%u, bindings_allocated=%d, num_columns=%d\n", st
341355
if(stmt->bindings_allocated < num_columns) {
342356

343357
new_bindings = create_empty_bindings(num_columns);
358+
if ( ! new_bindings) {
359+
if (stmt->bindings) {
360+
free(stmt->bindings);
361+
stmt->bindings = NULL;
362+
}
363+
stmt->bindings_allocated = 0;
364+
return;
365+
}
344366

345367
if(stmt->bindings) {
346368
for(i=0; i<stmt->bindings_allocated; i++)
@@ -349,18 +371,17 @@ mylog("in extend_bindings: stmt=%u, bindings_allocated=%d, num_columns=%d\n", st
349371
free(stmt->bindings);
350372
}
351373

352-
stmt->bindings = new_bindings; // null indicates error
374+
stmt->bindings = new_bindings;
353375
stmt->bindings_allocated = num_columns;
354376

355-
} else {
356-
/* if we have too many, make sure the extra ones are emptied out */
357-
/* so we don't accidentally try to use them for anything */
358-
for(i = num_columns; i < stmt->bindings_allocated; i++) {
359-
stmt->bindings[i].buflen = 0;
360-
stmt->bindings[i].buffer = NULL;
361-
stmt->bindings[i].used = NULL;
362-
}
363-
}
377+
}
378+
// There is no reason to zero out extra bindings if there are
379+
// more than needed. If an app has allocated extra bindings,
380+
// let it worry about it by unbinding those columns.
381+
382+
// SQLBindCol(1..) ... SQLBindCol(10...) # got 10 bindings
383+
// SQLExecDirect(...) # returns 5 cols
384+
// SQLExecDirect(...) # returns 10 cols (now OK)
364385

365386
mylog("exit extend_bindings\n");
366387
}

src/interfaces/odbc/connection.c

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ RETCODE SQL_API SQLAllocConnect(
3535
{
3636
EnvironmentClass *env = (EnvironmentClass *)henv;
3737
ConnectionClass *conn;
38-
38+
char *func="SQLAllocConnect";
3939

4040
conn = CC_Constructor();
4141
mylog("**** SQLAllocConnect: henv = %u, conn = %u\n", henv, conn);
@@ -44,6 +44,7 @@ ConnectionClass *conn;
4444
env->errormsg = "Couldn't allocate memory for Connection object.";
4545
env->errornumber = ENV_ALLOC_ERROR;
4646
*phdbc = SQL_NULL_HDBC;
47+
EN_log_error(func, "", env);
4748
return SQL_ERROR;
4849
}
4950

@@ -52,6 +53,7 @@ ConnectionClass *conn;
5253
env->errornumber = ENV_ALLOC_ERROR;
5354
CC_Destructor(conn);
5455
*phdbc = SQL_NULL_HDBC;
56+
EN_log_error(func, "", env);
5557
return SQL_ERROR;
5658
}
5759

@@ -74,9 +76,12 @@ RETCODE SQL_API SQLConnect(
7476
{
7577
ConnectionClass *conn = (ConnectionClass *) hdbc;
7678
ConnInfo *ci;
79+
char *func = "SQLConnect";
7780

78-
if ( ! conn)
81+
if ( ! conn) {
82+
CC_log_error(func, "", NULL);
7983
return SQL_INVALID_HANDLE;
84+
}
8085

8186
ci = &conn->connInfo;
8287

@@ -96,9 +101,11 @@ ConnInfo *ci;
96101

97102
qlog("conn = %u, SQLConnect(DSN='%s', UID='%s', PWD='%s')\n", ci->dsn, ci->username, ci->password);
98103

99-
if ( CC_connect(conn, FALSE) <= 0)
104+
if ( CC_connect(conn, FALSE) <= 0) {
100105
// Error messages are filled in
106+
CC_log_error(func, "Error on CC_connect", conn);
101107
return SQL_ERROR;
108+
}
102109

103110
return SQL_SUCCESS;
104111
}
@@ -123,17 +130,21 @@ RETCODE SQL_API SQLDisconnect(
123130
HDBC hdbc)
124131
{
125132
ConnectionClass *conn = (ConnectionClass *) hdbc;
133+
char *func = "SQLDisconnect";
126134

127135
mylog("**** in SQLDisconnect\n");
128136

129-
if ( ! conn)
137+
if ( ! conn) {
138+
CC_log_error(func, "", NULL);
130139
return SQL_INVALID_HANDLE;
140+
}
131141

132142
qlog("conn=%u, SQLDisconnect\n", conn);
133143

134144
if (conn->status == CONN_EXECUTING) {
135145
conn->errornumber = CONN_IN_USE;
136146
conn->errormsg = "A transaction is currently being executed";
147+
CC_log_error(func, "", conn);
137148
return SQL_ERROR;
138149
}
139150

@@ -155,16 +166,20 @@ RETCODE SQL_API SQLFreeConnect(
155166
HDBC hdbc)
156167
{
157168
ConnectionClass *conn = (ConnectionClass *) hdbc;
169+
char *func = "SQLFreeConnect";
158170

159171
mylog("**** in SQLFreeConnect: hdbc=%u\n", hdbc);
160172

161-
if ( ! conn)
173+
if ( ! conn) {
174+
CC_log_error(func, "", NULL);
162175
return SQL_INVALID_HANDLE;
176+
}
163177

164178
/* Remove the connection from the environment */
165179
if ( ! EN_remove_connection(conn->henv, conn)) {
166180
conn->errornumber = CONN_IN_USE;
167181
conn->errormsg = "A transaction is currently being executed";
182+
CC_log_error(func, "", conn);
168183
return SQL_ERROR;
169184
}
170185

@@ -577,8 +592,9 @@ char salt[2];
577592
/******* Send any initial settings *********/
578593
/**********************************************/
579594

580-
if ( ! CC_send_settings(self))
581-
return 0;
595+
// The Unix iodbc errors out on this call because it allocates a statement
596+
// before the connection is established. Therefore, don't check for error here.
597+
CC_send_settings(self);
582598

583599
CC_lookup_lo(self); /* a hack to get the oid of our large object oid type */
584600

@@ -1155,6 +1171,27 @@ RETCODE result;
11551171
result = SQLFreeStmt(hstmt, SQL_DROP);
11561172
}
11571173

1174+
void
1175+
CC_log_error(char *func, char *desc, ConnectionClass *self)
1176+
{
1177+
if (self) {
1178+
qlog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);
1179+
qlog(" ------------------------------------------------------------\n");
1180+
qlog(" henv=%u, conn=%u, status=%u, num_stmts=%d\n", self->henv, self, self->status, self->num_stmts);
1181+
qlog(" sock=%u, stmts=%u, lobj_type=%d\n", self->sock, self->stmts, self->lobj_type);
1182+
1183+
qlog(" ---------------- Socket Info -------------------------------\n");
1184+
if (self->sock) {
1185+
SocketClass *sock = self->sock;
1186+
qlog(" socket=%d, reverse=%d, errornumber=%d, errormsg='%s'\n", sock->socket, sock->reverse, sock->errornumber, sock->errormsg);
1187+
qlog(" buffer_in=%u, buffer_out=%u\n", sock->buffer_in, sock->buffer_out);
1188+
qlog(" buffer_filled_in=%d, buffer_filled_out=%d, buffer_read_in=%d\n", sock->buffer_filled_in, sock->buffer_filled_out, sock->buffer_read_in);
1189+
}
1190+
}
1191+
else
1192+
qlog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
1193+
}
1194+
11581195
/*
11591196
void
11601197
CC_test(ConnectionClass *self)
@@ -1165,23 +1202,28 @@ SDWORD pcbValue;
11651202
UDWORD pcrow;
11661203
UWORD rgfRowStatus;
11671204
char buf[255];
1205+
SDWORD buflen;
1206+
DATE_STRUCT *ds;
11681207
11691208
result = SQLAllocStmt( self, &hstmt1);
11701209
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
11711210
return;
11721211
}
11731212
1174-
result = SQLExtendedFetch(hstmt1, SQL_FETCH_ABSOLUTE, -2, &pcrow, &rgfRowStatus);
1175-
SQLGetData(hstmt1, 1, SQL_C_CHAR, buf, sizeof(buf), &pcbValue);
1176-
qlog("FETCH_ABSOLUTE, -2: result=%d, Col1 = '%s'\n", result, buf);
1213+
result = SQLExecDirect(hstmt1, "select * from cpar", SQL_NTS);
1214+
qlog("exec result = %d\n", result);
1215+
1216+
result = SQLBindCol(hstmt1, 2, SQL_C_DATE, buf, 0, &buflen);
1217+
qlog("bind result = %d\n", result);
11771218
11781219
result = SQLFetch(hstmt1);
11791220
while (result != SQL_NO_DATA_FOUND) {
1221+
ds = (DATE_STRUCT *) buf;
1222+
qlog("fetch on stmt1: result=%d, buflen=%d: year=%d, month=%d, day=%d\n", result, buflen, ds->year, ds->month, ds->day);
1223+
11801224
result = SQLFetch(hstmt1);
1181-
qlog("fetch on stmt1\n");
11821225
}
11831226
SQLFreeStmt(hstmt1, SQL_DROP);
11841227
11851228
}
11861229
*/
1187-

src/interfaces/odbc/connection.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ typedef struct {
133133
// char unknown_sizes[SMALL_REGISTRY_LEN];
134134
char fake_oid_index[SMALL_REGISTRY_LEN];
135135
char show_oid_column[SMALL_REGISTRY_LEN];
136+
char row_versioning[SMALL_REGISTRY_LEN];
136137
char show_system_tables[SMALL_REGISTRY_LEN];
137138
char focus_password;
138139
} ConnInfo;
@@ -188,5 +189,6 @@ char *CC_create_errormsg(ConnectionClass *self);
188189
int CC_send_function(ConnectionClass *conn, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *argv, int nargs);
189190
char CC_send_settings(ConnectionClass *self);
190191
void CC_lookup_lo(ConnectionClass *conn);
192+
void CC_log_error(char *func, char *desc, ConnectionClass *self);
191193

192194
#endif

0 commit comments

Comments
 (0)