/[eiffelstudio]/branches/eth/eve/Src/library/store/dbms/rdbms/odbc/Clib/odbc.c
ViewVC logotype

Contents of /branches/eth/eve/Src/library/store/dbms/rdbms/odbc/Clib/odbc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 88121 - (show annotations)
Fri Dec 16 14:42:24 2011 UTC (7 years, 10 months ago) by jasonw
File MIME type: text/plain
File size: 89099 byte(s)
<<Merged from trunk#88120.>>
1 /*
2 --|----------------------------------------------------------------
3 --| EiffelStore: library of reusable components for ISE Eiffel 3.
4 --| Copyright (C) 1995, Interactive Software Engineering Inc.
5 --| All rights reserved. Duplication and distribution prohibited.
6 --|
7 --| 270 Storke Road, Suite 7, Goleta, CA 93117 USA
8 --| Telephone 805-685-1006
9 --| Fax 805-685-6869
10 --| Electronic mail <info@eiffel.com>
11 --| Customer support e-mail <support@eiffel.com>
12 --|----------------------------------------------------------------
13
14 Date: "$Date$";
15 Revision: "$Revision$";
16 Product: "EiffelStore";
17 Database: "ODBC"
18 */
19 #define tWARN_MSG 1
20 #define tDEBUG 1
21 #define tPRN 1
22 #define tTEST 1
23
24 #include "eif_eiffel.h"
25
26 #ifdef EIF_WINDOWS
27 #include <windows.h>
28 #else
29 #define UNIX
30 #endif
31
32 #include <stdio.h>
33 #include <string.h>
34 #include "odbc.h"
35 #include <ctype.h>
36
37 /*
38 ** Data used by a single connection
39 */
40 typedef struct con_context_ {
41 /* ODBC connection handle, A connection consists of a driver and a data source.
42 * A connection handle identifies each connection. The connection handle defines not only which driver to use
43 * but which data source to use with that driver. */
44 HDBC hdbc;
45 ODBCSQLDA *odbc_descriptor[MAX_DESCRIPTOR];
46 short flag[MAX_DESCRIPTOR];
47 SQLHSTMT hstmt[MAX_DESCRIPTOR];
48 SQLLEN *pcbValue[MAX_DESCRIPTOR]; /* Used by SQLBindParameter. Pointers to a buffer for the parameter's length. */
49 SQLLEN *odbc_indicator[MAX_DESCRIPTOR];
50 RETCODE rc; /* Return code */
51 TIMESTAMP_STRUCT odbc_date; /* Date data for temporary use */
52 /* Messages: Are not exported to Eiffel due to
53 * merge with Oracle variables when using both files.
54 * Wrapping functions are used.*/
55 SQLTCHAR *error_message;
56 SQLTCHAR *warn_message;
57 int error_number;
58 short odbc_tranNumber; /* number of transaction opened at present */
59 int default_precision;
60 int default_scale;
61 } CON_CONTEXT;
62
63
64 void odbc_error_handler (CON_CONTEXT *con, HSTMT,int);
65 void odbc_clear_error (void *);
66 void odbc_unhide_qualifier(SQLTCHAR *);
67 SQLSMALLINT odbc_c_type(SQLSMALLINT odbc_type);
68
69 EIF_NATURAL_64 strhextoval(SQL_NUMERIC_STRUCT *NumStr);
70 rt_private SQLTCHAR *sqlstrcpy(SQLTCHAR *strDestination, int pos, const char *strSource);
71 rt_private int find_name (SQLTCHAR *buf, SQLTCHAR * sqlStat);
72 void setup_result_space (void *con, int no_desc);
73 void free_sqldata (ODBCSQLDA *dap);
74 int odbc_first_descriptor_available (void *con);
75 rt_private void change_to_low(SQLTCHAR *buf, size_t length);
76 void odbc_fetch_connection_info (void *con);
77
78 /* Safe allocation and memory reset */\
79 #define ODBC_SAFE_CLEAN_ALLOC(p,function,size) \
80 ODBC_SAFE_ALLOC(p,function); \
81 if (p) {memset (p, 0, size);}
82
83 /*
84 SQLTXTCMP - SQL text cmp
85 SQLTXTCPY - SQL text copy
86 ATSTXTCPY - ASCII to SQL text copy
87 SQLTXTCAT - SQL text cat
88 ATSTXTCAT - ASCII to SQL text cat
89 */
90
91 #define SQLTXTCMP(x1,x2) (memcmp(x1, x2, TXTLEN(x2)*sizeof(SQLTCHAR)))
92 #define SQLTXTCPY(s1,s2) (memcpy(s1, s2, (TXTLEN(s2)+1)*sizeof(SQLTCHAR)))
93 #define ATSTXTCPY(s1,s2) (sqlstrcpy(s1, 0, s2))
94 #define SQLTXTCAT(s1,s2) (SQLTXTCPY((SQLTCHAR *)s1+TXTLEN(s1), s2))
95 #define ATSTXTCAT(s1,s2) (sqlstrcpy(s1, (int)(TXTLEN(s1)), s2))
96
97 #define TXTC(x) ((SQLTCHAR) x)
98
99 /* Global ODBC environment,
100 * for the moment we only allow single environment in one process.
101 * Mutex is needed later for multithreading support.
102 */
103 HENV henv = NULL;
104 short number_connection;
105
106 SQLTCHAR odbc_qualifier[DB_MAX_QUALIFIER_LEN];
107 SQLTCHAR odbc_owner[DB_MAX_USER_NAME_LEN];
108 SQLTCHAR idQuoter[DB_QUOTER_LEN];
109 SQLTCHAR quaNameSep[DB_NAME_SEP_LEN];
110 long odbc_case;
111 long odbc_info_schema;
112 SQLTCHAR storedProc[2];
113 SQLTCHAR CreateStoredProc[DB_MAX_NAME_LEN];
114 SQLTCHAR dbmsName[DB_MAX_NAME_LEN];
115 SQLTCHAR dbmsVer[DB_MAX_NAME_LEN];
116
117 /* each function return 0 in case of success */
118 /* and database error code ( >= 1) else */
119
120 /*****************************************************************/
121 /* initialise ODBC c-module */
122 /*****************************************************************/
123
124 void *c_odbc_make (int m_size)
125 {
126 CON_CONTEXT *l_res;
127 int count;
128
129 ODBC_SAFE_ALLOC(l_res, (CON_CONTEXT *) malloc (sizeof (CON_CONTEXT)));
130 memset (l_res, 0, sizeof (CON_CONTEXT));
131 number_connection++;
132
133 /* Allocate memory for error and warning message */
134 ODBC_SAFE_ALLOC(l_res->error_message, (SQLTCHAR *) malloc (sizeof (SQLTCHAR) * (m_size + ERROR_MESSAGE_SIZE)));
135 ODBC_SAFE_ALLOC(l_res->warn_message, (SQLTCHAR *) malloc (sizeof (SQLTCHAR) * (m_size + WARN_MESSAGE_SIZE)));
136
137 if (!henv)
138 {
139 /* Even though the error message is not related to current connection,
140 * but the global environment handle.
141 * We still store the message in it due to the way on Eiffel side of
142 * retrieving error message.
143 */
144 l_res->rc = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
145 if (l_res->rc) {
146 odbc_error_handler(l_res, NULL,10);
147 return l_res;
148 }
149 }
150 l_res->rc = SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,0);
151 if (l_res->rc) {
152 odbc_error_handler(l_res, NULL,910);
153 return l_res;
154 }
155
156 for (count = 0; count < MAX_DESCRIPTOR; count++) {
157 l_res->odbc_descriptor[count] = NULL;
158 }
159 return l_res;
160 }
161
162
163 /*****************************************************************/
164 /* A descriptor is used to store a row fetched by FETCH command. */
165 /* Whenever perform a SELECT statement, allocate a new descriptor*/
166 /* by int_new_descriptor(), the descriptor is freed when the */
167 /* SELECT statement terminates. */
168 /*****************************************************************/
169
170 /*****************************************************************/
171 /* */
172 /* ROUTINE DESCRIPTION */
173 /* */
174 /* NAME: odbc_new_descriptor() */
175 /* DESCRIPTION: */
176 /* This routine allocate a DESCRIPTOR in the following way: */
177 /* 1. find a free cell in vector 'descriptor' to store a pointer */
178 /* to ODBCSQLDA */
179 /* 2. allocate a minimum space for the ODBCSQLDA(with space for */
180 /* only one table field). The space will be adjusted later(in */
181 /* odbc_init_order(), when the ODBCSQLDA will be actually used*/
182 /* and enough information has obtained for allocating proper */
183 /* size of memory space). */
184 /* */
185 /*****************************************************************/
186 int odbc_new_descriptor (void *con)
187 {
188 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
189 int result = odbc_first_descriptor_available (con);
190
191 if (result != NO_MORE_DESCRIPTOR)
192 {
193 l_con->rc = SQLAllocHandle (SQL_HANDLE_STMT, l_con->hdbc, &(l_con->hstmt[result]));
194 if (l_con->rc) {
195 odbc_error_handler(con, NULL, 0);
196 return NO_MORE_DESCRIPTOR;
197 }
198
199 /* malloc area for the descriptor and then initialize it */
200 /* Initially allocate head size plus one var size.
201 * Previously we set odbc_descriptor[result] as arbitary pointer 0x1 which is not good */
202 ODBC_SAFE_ALLOC(l_con->odbc_descriptor[result], (ODBCSQLDA *) calloc(IISQDA_HEAD_SIZE + IISQDA_VAR_SIZE, 1));
203 SetVarNum(l_con->odbc_descriptor[result], 1);
204 ODBC_C_FREE (l_con->pcbValue[result]);
205 l_con->pcbValue[result] = NULL;
206 ODBC_C_FREE (l_con->odbc_indicator[result]);
207 l_con->odbc_indicator[result] = NULL;
208 l_con->flag[result] = ODBC_SQL;
209 }
210 else {
211 odbc_error_handler(con, NULL, 201);
212 ATSTXTCPY(l_con->error_message, " No available descriptor\n");
213 }
214 return result;
215 }
216
217 /*****************************************************************/
218 /* */
219 /* ROUTINE DESCRIPTION */
220 /* NAME: odbc_first_descriptor_available() */
221 /* DESCRIPTION: */
222 /* The routine decide if there free cell in vector 'descriptor'*/
223 /*If exist, return the index of the cell in the vector, otherwise*/
224 /*return NO_MORE_DESCRIPTOR. */
225 /* */
226 /*****************************************************************/
227 int odbc_first_descriptor_available (void *con)
228 {
229 int no_descriptor;
230 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
231
232 for (no_descriptor = 0;
233 no_descriptor < MAX_DESCRIPTOR &&
234 l_con->odbc_descriptor[no_descriptor] != NULL;
235 no_descriptor++)
236 {
237 /* empty */
238 }
239
240 if (no_descriptor < MAX_DESCRIPTOR)
241 {
242 return no_descriptor;
243 }
244 else
245 {
246 return NO_MORE_DESCRIPTOR;
247 }
248 }
249
250 /*****************************************************************/
251 /* */
252 /* ROUTINE DESCRIPTION */
253 /* */
254 /* NAME: odbc_available_descriptor() */
255 /* DESCRIPTION: */
256 /* To decide if there is free cell in vector 'descriptor', */
257 /* if answer is YES, return 1; otherwise return 0. */
258 /* */
259 /*****************************************************************/
260 int odbc_available_descriptor (void *con)
261 {
262 return odbc_first_descriptor_available (con) != NO_MORE_DESCRIPTOR;
263 }
264
265 /*****************************************************************/
266 /* */
267 /* ROUTINE DESCRIPTION */
268 /* */
269 /* NAME: odbc_max_descriptor() */
270 /* DESCRIPTION: */
271 /* Return the max number of cells in vector 'descriptor'. */
272 /* */
273 /*****************************************************************/
274 int odbc_max_descriptor ()
275 {
276 return MAX_DESCRIPTOR;
277 }
278
279 /*****************************************************************/
280 /* The following functions perform SQL statement in 2 ways: */
281 /* 1. immediately ---- a mode to perform Insert, Update and */
282 /* Delete. */
283 /* 2. dynamicly ---- a mode to perform all kinds of operations*/
284 /*****************************************************************/
285
286 /*****************************************************************/
287 /* */
288 /* ROUTINE DESCRIPTION */
289 /* */
290 /* NAME: odbc_pre_immediate(int no_desc, int argNum) */
291 /* PARAMETERS: no_desc - the descriptor number for the statement */
292 /* argNum - the number of the arguments of the */
293 /* statement */
294 /* DESCRIPTION: */
295 /* In IMMEDIATE EXECUTE mode, if the performed SQL statement is*/
296 /* a call to a stored procedure, allocate some area used by the */
297 /* stored procedure. */
298 /* */
299 /*****************************************************************/
300 void odbc_pre_immediate(void *con, int no_desc, int argNum)
301 {
302 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
303
304 odbc_clear_error(con);
305
306 if (no_desc < 0 || no_desc > MAX_DESCRIPTOR) {
307 odbc_error_handler(con, NULL, 202);
308 ATSTXTCAT(l_con->error_message, "\nInvalid Descriptor Number!");
309 return;
310 }
311 if (argNum > 0) {
312 /* Reset memory to be safe */
313 ODBC_SAFE_ALLOC(l_con->pcbValue[no_desc], (SQLLEN *) calloc(argNum, sizeof(SQLLEN)));
314 } else {
315 ODBC_C_FREE (l_con->pcbValue[no_desc]);
316 l_con->pcbValue[no_desc] = NULL;
317 }
318 }
319
320 /*****************************************************************/
321 /* */
322 /* ROUTINE DESCRIPTION */
323 /* */
324 /* NAME: odbc_exec_immediate(order) */
325 /* PARAMETERS: order - a SQL statement to be performed. */
326 /* DESCRIPTION: */
327 /* In IMMEDIATE EXECUTE mode perform the SQL statement, and */
328 /* then check if there is warning message for the execution, */
329 /* and finally return error number. */
330 /* */
331 /*****************************************************************/
332 void odbc_exec_immediate (void *con, int no_desc, SQLTCHAR *order)
333 {
334 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
335
336 odbc_unhide_qualifier(order);
337 l_con->odbc_tranNumber = 1;
338 l_con->warn_message[0] = (SQLTCHAR)0;
339
340 l_con->rc = SQLExecDirect(l_con->hstmt[no_desc], order, SQL_NTS);
341 free_sqldata (l_con->odbc_descriptor[no_desc]);
342 l_con->odbc_descriptor[no_desc] = NULL;
343 if (l_con->rc) {
344 odbc_error_handler(con, l_con->hstmt[no_desc], 2);
345 }
346 l_con->rc = SQLFreeHandle (SQL_HANDLE_STMT, l_con->hstmt[no_desc]);
347 if (l_con->rc) {
348 odbc_error_handler(con, l_con->hstmt[no_desc],3);
349 }
350 free_sqldata (l_con->odbc_descriptor[no_desc]);
351 l_con->odbc_descriptor[no_desc] = NULL;
352 if (l_con->pcbValue[no_desc] != NULL) {
353 ODBC_C_FREE(l_con->pcbValue[no_desc]);
354 l_con->pcbValue[no_desc] = NULL;
355 }
356 }
357
358 /*****************************************************************/
359 /* */
360 /* ROUTINE DESCRIPTION */
361 /* */
362 /* NAME: odbc_init_order(no_des, order) */
363 /* PARAMETERS: order - a SQL statement to be performed. */
364 /* no_des- index in descriptor vector. */
365 /* DESCRIPTION: */
366 /* In DYNAMICALLY EXECUTE mode perform the SQL statement. But */
367 /* this routine only get things ready for dynamic execution: */
368 /* 1. get the SQL statement PREPAREd; and check if there are */
369 /* warning message for the SQL statement; */
370 /* 2. DESCRIBE the SQL statement and get enough information to */
371 /* allocate enough memory space for the corresponding */
372 /* ODBCSQLDA. */
373 /* 3. return error number. */
374 /* */
375 /*****************************************************************/
376 void odbc_init_order (void *con, int no_desc, SQLTCHAR *order, int argNum)
377 {
378 int is_as_primary = 0;
379 size_t order_count, buf_count;
380 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
381
382 #define COMPARED_BTYES (9 * sizeof (SQLTCHAR))
383 #define COMPARED_LENGTH (9)
384
385 SQLTCHAR tmpBuf[DB_MAX_TABLE_LEN + 1];
386 SQLTCHAR sqltab[30];
387 SQLTCHAR sqlcol[30];
388 SQLTCHAR sqlproc[30];
389 SQLTCHAR sqlpk[30];
390 SQLTCHAR sqlfk[30];
391 SQLTCHAR sqlfk_as_primary[30];
392
393 ATSTXTCPY(sqltab, "sqltables");
394 ATSTXTCPY(sqlcol, "sqlcolumns");
395 ATSTXTCPY(sqlproc, "sqlprocedu");
396 ATSTXTCPY(sqlpk, "sqlprimary");
397 ATSTXTCPY(sqlfk, "sqlforeign");
398 ATSTXTCPY(sqlfk_as_primary, "sqlforeignkeysprimary");
399
400
401 if (no_desc < 0 || no_desc > MAX_DESCRIPTOR) {
402 odbc_error_handler(con, NULL, 203);
403 ATSTXTCAT(l_con->error_message, "\nInvalid Descriptor Number!");
404 return;
405 }
406 odbc_unhide_qualifier(order);
407 l_con->odbc_tranNumber = 1;
408 odbc_clear_error(con);
409 l_con->warn_message[0] = (SQLTCHAR)0;
410
411
412 l_con->flag[no_desc] = ODBC_SQL;
413 order_count = TXTLEN(order);
414 buf_count = (DB_MAX_TABLE_LEN > order_count ? order_count : DB_MAX_TABLE_LEN);
415
416 if (order_count >= COMPARED_LENGTH) {
417 memcpy(tmpBuf, order, buf_count * sizeof (SQLTCHAR));
418 tmpBuf[buf_count] = (SQLTCHAR)0;
419 change_to_low(tmpBuf, buf_count);
420 if (memcmp(tmpBuf, sqltab, COMPARED_BTYES) == 0)
421 {
422 l_con->flag[no_desc] = ODBC_CATALOG_TAB;
423 if (find_name (tmpBuf, order))
424 {
425 if (TXTLEN(odbc_qualifier) > 0 && TXTLEN(odbc_owner) > 0)
426 l_con->rc = SQLTables(l_con->hstmt[no_desc], odbc_qualifier, SQL_NTS, odbc_owner, SQL_NTS, tmpBuf, SQL_NTS, NULL, 0);
427 if (TXTLEN(odbc_qualifier) == 0 && TXTLEN(odbc_owner) > 0)
428 l_con->rc = SQLTables(l_con->hstmt[no_desc], NULL, 0, odbc_owner, SQL_NTS, tmpBuf, SQL_NTS, NULL, 0);
429 if (TXTLEN(odbc_qualifier) > 0 && TXTLEN(odbc_owner) == 0)
430 l_con->rc = SQLTables(l_con->hstmt[no_desc], odbc_qualifier, SQL_NTS, NULL, 0, tmpBuf, SQL_NTS, NULL, 0);
431 if (TXTLEN(odbc_qualifier) == 0 && TXTLEN(odbc_owner) == 0)
432 l_con->rc = SQLTables(l_con->hstmt[no_desc], NULL, 0, NULL, 0, tmpBuf, SQL_NTS, NULL, 0);
433 }
434 else
435 {
436 l_con->rc = SQLTables(l_con->hstmt[no_desc], NULL, 0, NULL, 0, NULL, 0, NULL, 0);
437 odbc_qualifier[0] = (SQLTCHAR)0;
438 odbc_owner[0] =(SQLTCHAR)0;
439 }
440 }
441 else
442 {
443 if (memcmp(tmpBuf, sqlcol, COMPARED_BTYES) == 0)
444 {
445 l_con->flag[no_desc] = ODBC_CATALOG_COL;
446 if (find_name (tmpBuf, order)) {
447 l_con->rc = SQLColumns(l_con->hstmt[no_desc], NULL, 0, NULL, 0, tmpBuf, SQL_NTS, NULL, 0);
448 } else {
449 l_con->rc = SQLColumns(l_con->hstmt[no_desc], NULL, 0, NULL, 0, NULL, 0, NULL, 0);
450 }
451 }
452 else
453 {
454 if (memcmp(tmpBuf, sqlproc, COMPARED_BTYES) == 0)
455 {
456 l_con->flag[no_desc] = ODBC_CATALOG_PROC;
457 if (find_name (tmpBuf, order)){
458 l_con->rc = SQLProcedures(l_con->hstmt[no_desc], NULL, 0, NULL, 0, tmpBuf, SQL_NTS);
459 }
460 else{
461 l_con->rc = SQLProcedures(l_con->hstmt[no_desc], NULL, 0, NULL, 0, NULL, 0);
462 }
463 }
464 else
465 {
466 if (memcmp(tmpBuf, sqlpk, COMPARED_BTYES) == 0)
467 {
468 l_con->flag[no_desc] = ODBC_PK;
469 if (find_name (tmpBuf, order)) {
470 l_con->rc = SQLPrimaryKeys(l_con->hstmt[no_desc], NULL, 0, NULL, 0, tmpBuf, SQL_NTS);
471 }
472 else {
473 l_con->rc = SQLPrimaryKeys(l_con->hstmt[no_desc], NULL, 0, NULL, 0, NULL, 0);
474 }
475 }
476 else {
477 if (memcmp(tmpBuf, sqlfk, COMPARED_BTYES) == 0) {
478 is_as_primary = (memcmp(tmpBuf, sqlfk_as_primary, 21) ? 0 : 1);
479 l_con->flag[no_desc] = ODBC_FK;
480 find_name (tmpBuf, order);
481 /* Now let's find what type of primary keys we are looking for. */
482 if (is_as_primary) {
483 l_con->rc = SQLForeignKeys(l_con->hstmt[no_desc], NULL, 0, NULL, 0, tmpBuf, SQL_NTS, NULL, 0, NULL, 0, NULL, 0);
484 } else {
485 l_con->rc = SQLForeignKeys(l_con->hstmt[no_desc], NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, tmpBuf, SQL_NTS);
486 }
487 }
488 }
489 }
490 }
491 }
492 }
493
494 if (l_con->rc) {
495 odbc_error_handler(con, l_con->hstmt[no_desc],100);
496 if (l_con->error_number) {
497 free_sqldata (l_con->odbc_descriptor[no_desc]);
498 l_con->odbc_descriptor[no_desc] = NULL;
499 l_con->rc = SQLFreeHandle (SQL_HANDLE_STMT, l_con->hstmt[no_desc]);
500 }
501 }
502
503
504
505 if (l_con->flag[no_desc] == ODBC_SQL) {
506 /* Process general ODBC SQL statements */
507
508 l_con->rc = SQLPrepare(l_con->hstmt[no_desc], order, SQL_NTS);
509 if (l_con->rc) {
510 odbc_error_handler(con, l_con->hstmt[no_desc],4);
511 if (l_con->error_number) {
512 free_sqldata (l_con->odbc_descriptor[no_desc]);
513 l_con->odbc_descriptor[no_desc] = NULL;
514 l_con->rc = SQLFreeHandle (SQL_HANDLE_STMT, l_con->hstmt[no_desc]);
515 return;
516 }
517 }
518 }
519
520 if (argNum > 0) {
521 /* Reset memory to be safe */
522 ODBC_SAFE_ALLOC(l_con->pcbValue[no_desc], (SQLLEN *) calloc(argNum, sizeof(SQLLEN)));
523 } else {
524 ODBC_C_FREE (l_con->pcbValue[no_desc]);
525 l_con->pcbValue[no_desc] = NULL;
526 }
527 }
528
529 /*****************************************************************/
530 /* */
531 /* ROUTINE DESCRIPTION */
532 /* */
533 /* NAME: odbc_start_order(no_des) */
534 /* PARAMETERS: no_des- index in descriptor vector. */
535 /* DESCRIPTION: */
536 /* Finish execution of a SQL statement in DYNAMIC EXECUTION */
537 /* mode: */
538 /* 1. if the PREPAREd SQL statement is a NON_SELECT statement, */
539 /* just EXECUTE it; otherwise, DEFINE a CURSOR for it and */
540 /* OPEN the CURSOR. In the process, if error occurs, do some*/
541 /* clearence; */
542 /* 3. return error number. */
543 /* */
544 /*****************************************************************/
545
546 void odbc_start_order (void *con, int no_desc)
547 {
548 short colNum = 0;
549 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
550
551 /* Added by Jacques. 5/14/98 */
552 SQLTCHAR szCatalog[DB_REP_LEN], szSchema[DB_REP_LEN];
553 SQLTCHAR szTableName[DB_REP_LEN], szColumnName[DB_REP_LEN];
554 SQLTCHAR szTypeName[DB_REP_LEN];
555 SQLINTEGER ColumnSize, BufferLength;
556 SQLSMALLINT DataType, DecimalDigits, NumPrecRadix, Nullable;
557
558 SQLLEN cbCatalog, cbSchema, cbTableName, cbColumnName;
559 SQLLEN cbDataType, cbTypeName, cbColumnSize, cbBufferLength;
560 SQLLEN cbDecimalDigits, cbNumPrecRadix, cbNullable;
561
562 if (l_con->flag[no_desc] == ODBC_CATALOG_COL) {
563 SQLBindCol(l_con->hstmt, 1, SQL_C_TCHAR, szCatalog, DB_REP_LEN,&cbCatalog);
564 SQLBindCol(l_con->hstmt, 2, SQL_C_TCHAR, szSchema, DB_REP_LEN, &cbSchema);
565 SQLBindCol(l_con->hstmt, 3, SQL_C_TCHAR, szTableName, DB_REP_LEN,&cbTableName);
566 SQLBindCol(l_con->hstmt, 4, SQL_C_TCHAR, szColumnName, DB_REP_LEN, &cbColumnName);
567 SQLBindCol(l_con->hstmt, 5, SQL_C_SSHORT, &DataType, 0, &cbDataType);
568 SQLBindCol(l_con->hstmt, 6, SQL_C_TCHAR, szTypeName, DB_REP_LEN, &cbTypeName);
569 SQLBindCol(l_con->hstmt, 7, SQL_C_SLONG, &ColumnSize, 0, &cbColumnSize);
570 SQLBindCol(l_con->hstmt, 8, SQL_C_SLONG, &BufferLength, 0, &cbBufferLength);
571 SQLBindCol(l_con->hstmt, 9, SQL_C_SSHORT, &DecimalDigits, 0, &cbDecimalDigits);
572 SQLBindCol(l_con->hstmt, 10, SQL_C_SSHORT, &NumPrecRadix, 0, &cbNumPrecRadix);
573 SQLBindCol(l_con->hstmt, 11, SQL_C_SSHORT, &Nullable, 0, &cbNullable);
574 while(1) {
575 l_con->rc = SQLFetch(l_con->hstmt);
576 if (l_con->rc == SQL_ERROR || l_con->rc == SQL_SUCCESS_WITH_INFO) {
577 odbc_error_handler(con, l_con->hstmt[no_desc],7);
578 if (l_con->error_number > 0) {
579 free_sqldata (l_con->odbc_descriptor[no_desc]);
580 l_con->odbc_descriptor[no_desc] = NULL;
581 if (l_con->pcbValue[no_desc] != NULL) {
582 ODBC_C_FREE(l_con->pcbValue[no_desc]);
583 l_con->pcbValue[no_desc] = NULL;
584 }
585 l_con->rc = SQLFreeHandle (SQL_HANDLE_STMT, l_con->hstmt[no_desc]);
586 return;
587 }
588 }
589 if (l_con->rc == SQL_SUCCESS || l_con->rc == SQL_SUCCESS_WITH_INFO){
590 l_con->rc = SQLNumResultCols(l_con->hstmt[no_desc], &colNum);
591 if (l_con->rc) {
592 odbc_error_handler(con, l_con->hstmt[no_desc],5);
593 if (l_con->error_number) {
594 free_sqldata (l_con->odbc_descriptor[no_desc]);
595 l_con->odbc_descriptor[no_desc] = NULL;
596 if (l_con->pcbValue[no_desc] != NULL) {
597 ODBC_C_FREE(l_con->pcbValue[no_desc]);
598 l_con->pcbValue[no_desc] = NULL;
599 }
600 l_con->rc = SQLFreeHandle (SQL_HANDLE_STMT, l_con->hstmt[no_desc]);
601 return;
602 }
603 }
604
605 }
606 else if (l_con->rc == SQL_ROW_UPDATED) {
607 break;
608 }
609 else if (l_con->rc == SQL_ROW_DELETED) {
610 break;
611 }
612 else if (l_con->rc == SQL_ROW_ADDED) {
613 break;
614 }
615 else if (l_con->rc == SQL_ROW_NOROW) {
616 break;
617 }
618 else {
619 break;
620 }
621 }
622 }
623
624
625
626 if (l_con->flag[no_desc] == ODBC_SQL) {
627 /* Process general ODBC SQL statements */
628 l_con->rc = SQLExecute(l_con->hstmt[no_desc]);
629 if (l_con->rc) {
630 odbc_error_handler(con, l_con->hstmt[no_desc],7);
631 if (l_con->error_number > 0) {
632 free_sqldata (l_con->odbc_descriptor[no_desc]);
633 l_con->odbc_descriptor[no_desc] = NULL;
634 if (l_con->pcbValue[no_desc] != NULL) {
635 ODBC_C_FREE(l_con->pcbValue[no_desc]);
636 l_con->pcbValue[no_desc] = NULL;
637 }
638 l_con->rc = SQLFreeHandle (SQL_HANDLE_STMT, l_con->hstmt[no_desc]);
639 return;
640 }
641 }
642 }
643 setup_result_space (con, no_desc);
644 }
645
646 /* Setup/describe result space and fill some necessary info. */
647 void setup_result_space (void *con, int no_desc)
648 {
649 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
650 ODBCSQLDA *dap=l_con->odbc_descriptor[no_desc];
651 SQLSMALLINT colNum = 0;
652 SQLSMALLINT oldVarNum = 0;
653 SQLSMALLINT i;
654 SQLULEN l_length;
655 SQLSMALLINT type;
656 SQLSMALLINT indColName;
657 SQLSMALLINT tmpScale;
658 SQLSMALLINT tmpNullable;
659 char *dataBuf;
660 SQLHDESC hdesc = NULL;
661
662 /* Save old val numbers */
663 oldVarNum = GetVarNum(dap);
664
665 /* Get the old number of var */
666 l_con->rc = SQLNumResultCols(l_con->hstmt[no_desc], &colNum);
667 if (l_con->rc) {
668 odbc_error_handler(con, l_con->hstmt[no_desc],5);
669 if (l_con->error_number) {
670 free_sqldata (l_con->odbc_descriptor[no_desc]);
671 l_con->odbc_descriptor[no_desc] = NULL;
672 if (l_con->pcbValue[no_desc] != NULL) {
673 ODBC_C_FREE(l_con->pcbValue[no_desc]);
674 l_con->pcbValue[no_desc] = NULL;
675 }
676 l_con->rc = SQLFreeHandle (SQL_HANDLE_STMT, l_con->hstmt[no_desc]);
677 return;
678 }
679 }
680
681
682 if (colNum > DB_MAX_COLS) {
683 if (l_con->error_number) {
684 ATSTXTCAT(l_con->error_message, "\n Number of selected columns exceed max number(300) ");
685 }
686 else {
687 ATSTXTCPY(l_con->error_message, "\n Number of selected columns exceed max number(300) ");
688 l_con->error_number = -DB_TOO_MANY_COL;
689 }
690 free_sqldata (l_con->odbc_descriptor[no_desc]);
691 l_con->odbc_descriptor[no_desc] = NULL;
692 if (l_con->pcbValue[no_desc] != NULL) {
693 ODBC_C_FREE(l_con->pcbValue[no_desc]);
694 l_con->pcbValue[no_desc] = NULL;
695 }
696 l_con->rc = SQLFreeHandle (SQL_HANDLE_STMT, l_con->hstmt[no_desc]);
697 return;
698 }
699
700 if (colNum > 0)
701 i = colNum;
702 else
703 i = 1;
704 /* Reallocate the DESCRIPTOR area. */
705 ODBC_SAFE_ALLOC(l_con->odbc_descriptor[no_desc], (ODBCSQLDA *) realloc(l_con->odbc_descriptor[no_desc], IISQDA_HEAD_SIZE + i * IISQDA_VAR_SIZE));
706 /* If there is resizing, we only clean up the new space, because some memory referenced by old space for var can be reused.*/
707 if (i > oldVarNum) {
708 memset (l_con->odbc_descriptor[no_desc]->sqlvar + oldVarNum, 0, (i - oldVarNum) * IISQDA_VAR_SIZE);
709 }
710
711 dap = l_con->odbc_descriptor[no_desc];
712 SetVarNum(dap,i);
713 SetColNum(dap, colNum);
714
715 /* For numeric type */
716 SQLGetStmtAttr(l_con->hstmt[no_desc], SQL_ATTR_APP_ROW_DESC, &hdesc, 0, NULL);
717
718 for (i=0; i < colNum && !l_con->error_number; i++) {
719 /* fill in the describing information for each column, and calculate */
720 /* the total length of the data buffer */
721 l_con->rc = SQLDescribeCol(
722 l_con->hstmt[no_desc],
723 (SQLSMALLINT) i+1,
724 (dap->sqlvar)[i].sqlname.sqlnamec,
725 DB_MAX_NAME_LEN,
726 &indColName,
727 &((dap->sqlvar)[i].sqltype),
728 &((dap->sqlvar)[i].sqllen),
729 &tmpScale,
730 &tmpNullable);
731 if (l_con->rc)
732 odbc_error_handler(con, l_con->hstmt[no_desc],6);
733 if (l_con->error_number == 0) {
734 (dap->sqlvar)[i].sqlname.sqlnamec[indColName] = (SQLTCHAR)0;
735 (dap->sqlvar)[i].sqlname.sqlnamel = TXTLEN((dap->sqlvar)[i].sqlname.sqlnamec);
736 dap->sqlvar[i].c_type = odbc_c_type(dap->sqlvar[i].sqltype);
737 type = dap->sqlvar[i].c_type;
738 switch(type) {
739 /* case SQL_C_DATE: */
740 case SQL_C_TYPE_DATE:
741 SetDbColLength(dap, i, sizeof(DATE_STRUCT));
742 break;
743 /* case SQL_C_TIME: */
744 case SQL_C_TYPE_TIME:
745 SetDbColLength(dap, i, sizeof(TIME_STRUCT));
746 break;
747 /* case SQL_C_TIMESTAMP: */
748 case SQL_C_TYPE_TIMESTAMP:
749 SetDbColLength(dap, i, sizeof(TIMESTAMP_STRUCT));
750 break;
751 case SQL_C_STINYINT:
752 SetDbColLength(dap, i, DB_SIZEOF_CHAR);
753 break;
754 case SQL_C_SSHORT:
755 SetDbColLength(dap, i, DB_SIZEOF_SHORT);
756 break;
757 case SQL_C_SLONG:
758 SetDbColLength(dap, i, DB_SIZEOF_LONG);
759 break;
760 case SQL_C_SBIGINT:
761 SetDbColLength(dap, i, DB_SIZEOF_BIGINT);
762 break;
763 case SQL_C_FLOAT:
764 SetDbColLength(dap, i, DB_SIZEOF_REAL);
765 break;
766 case SQL_C_DOUBLE:
767 SetDbColLength(dap, i, DB_SIZEOF_DOUBLE);
768 break;
769 case SQL_C_TCHAR:
770 SetDbColLength(dap, i, sizeof (SQLTCHAR) * GetDbColLength(dap, i));
771 break;
772 case SQL_C_NUMERIC:
773 SQLSetDescField (hdesc,i+1,SQL_DESC_TYPE,(SQLPOINTER)SQL_C_NUMERIC,0);
774 SQLSetDescField (hdesc,i+1,SQL_DESC_PRECISION,(SQLPOINTER) l_con->default_precision,0); /* presision of 64bits */
775 SQLSetDescField (hdesc,i+1,SQL_DESC_SCALE,(SQLPOINTER) l_con->default_scale,0); /* presision of 64bits */
776 SetDbColLength(dap, i, sizeof (SQL_NUMERIC_STRUCT));
777 break;
778 case SQL_C_GUID:
779 SetDbColLength(dap, i, sizeof (SQLGUID));
780 break;
781 default:
782 break;
783 }
784 type = GetDbColType(dap, i);
785 switch (type) {
786 case SQL_LONGVARBINARY:
787 case SQL_LONGVARCHAR:
788 case SQL_WLONGVARCHAR:
789 case SQL_SS_XML:
790 SetDbColLength(dap, i, DB_MAX_STRING_LEN);
791 break;
792 }
793 }
794 }
795
796
797 if (l_con->error_number) {
798 free_sqldata(dap);
799 l_con->odbc_descriptor[no_desc] = NULL;
800 if (l_con->pcbValue[no_desc] != NULL) {
801 ODBC_C_FREE(l_con->pcbValue[no_desc]);
802 l_con->pcbValue[no_desc] = NULL;
803 }
804 l_con->rc = SQLFreeHandle (SQL_HANDLE_STMT, l_con->hstmt[no_desc]);
805 return;
806 }
807
808 if (colNum) {
809 /* Allocate for each column the buffer that will hold its value. */
810 for (i=0; i<colNum; i++) {
811 l_length = GetDbColLength(dap, i);
812 /* The underlying API will require an extra character for the null terminating character
813 * of string data. */
814 if ((GetDbCType(dap, i) == SQL_C_WCHAR) || (GetDbCType(dap, i) == SQL_C_CHAR)) {
815 l_length = l_length + sizeof(TCHAR);
816 }
817 dataBuf = GetDbColPtr(dap, i);
818 ODBC_SAFE_ALLOC(dataBuf, (char *) realloc(dataBuf, l_length));
819 SetDbColPtr(dap, i, dataBuf);
820 }
821 }
822
823 /* allocate buffer for INDICATORs of the output fields, reuse old memory if possible. */
824 ODBC_SAFE_ALLOC(l_con->odbc_indicator[no_desc], (SQLLEN *) realloc(l_con->odbc_indicator[no_desc], (colNum+1)*sizeof(SQLLEN)));
825 }
826
827
828 /*****************************************************************/
829 /* */
830 /* ROUTINE DESCRIPTION */
831 /* */
832 /* NAME: odbc_terminate_order(no_des) */
833 /* PARAMETERS: no_des- index in descriptor vector. */
834 /* DESCRIPTION: */
835 /* A SQL has been performed in DYNAMIC EXECUTION mode, so the */
836 /* routine is to do some clearence: */
837 /* 1. if the DYNAMICLLY EXECUTED SQL statement is a NON_SELECT */
838 /* statement, just free the memory for ODBCSQLDA and clear the*/
839 /* cell in 'descriptor' to NULL; otherwise, CLOSE the CURSOR*/
840 /* and then do the same clearence. */
841 /* 2. return error number. */
842 /* */
843 /*****************************************************************/
844 void odbc_terminate_order (void *con, int no_des)
845 {
846 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
847 ODBCSQLDA *dap = l_con->odbc_descriptor[no_des];
848
849 if (dap) {
850 free_sqldata (dap);
851 l_con->odbc_descriptor[no_des] = NULL;
852 ODBC_C_FREE (l_con->odbc_indicator[no_des]);
853 l_con->odbc_indicator[no_des] = NULL;
854 if (l_con->pcbValue[no_des] != NULL) {
855 ODBC_C_FREE(l_con->pcbValue[no_des]);
856 l_con->pcbValue[no_des] = NULL;
857 }
858 l_con->rc = SQLFreeHandle (SQL_HANDLE_STMT, l_con->hstmt[no_des]);
859 }
860 }
861
862 /* Free the whole ODBCSQLDA pointed by `dap' */
863 void free_sqldata (ODBCSQLDA *dap)
864 {
865 int i;
866 char *data_buffer;
867
868 int colNum;
869
870 if (dap) {
871 colNum = GetColNum(dap);
872 if (colNum) {
873 for (i=0; i < colNum; i++) {
874 data_buffer = GetDbColPtr(dap,i);
875 ODBC_C_FREE(data_buffer);
876 }
877 }
878 ODBC_C_FREE(dap);
879 }
880 }
881 /*****************************************************************/
882 /* */
883 /* ROUTINE DESCRIPTION */
884 /* */
885 /* NAME: odbc_close_cursor(no_des) */
886 /* PARAMETERS: no_des- index in descriptor vector. */
887 /* DESCRIPTION: */
888 /* A SQL has been performed in DYNAMIC EXECUTION mode, so the */
889 /* routine is to do some clearence: */
890 /* 1. if the DYNAMICLLY EXECUTED SQL statement is a NON_SELECT */
891 /* statement, just free the memory for ODBCSQLDA and clear the*/
892 /* cell in 'descriptor' to NULL; otherwise, CLOSE the CURSOR*/
893 /* and then do the same clearence. */
894 /* 2. return error number. */
895 /* */
896 /*****************************************************************/
897 void odbc_close_cursor (void *con, int no_des)
898 {
899 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
900 l_con->rc = SQLFreeStmt(l_con->hstmt[no_des], SQL_CLOSE);
901 }
902
903 /*****************************************************************/
904 /* */
905 /* ROUTINE DESCRIPTION */
906 /* */
907 /* NAME: odbc_next_row(no_des) */
908 /* PARAMETERS: no_des- index in descriptor vector. */
909 /* DESCRIPTION: */
910 /* A SELECT statement is now being executed in DYNAMIC EXECU- */
911 /* TION mode, the routine is to FETCH a new tuple from database*/
912 /* and if a new tuple is fetched, return 1 otherwise return 0. */
913 /* */
914 /*****************************************************************/
915
916 int odbc_next_row (void *con, int no_des)
917 /* move to the next row of selection */
918 /* return 0 if there is a next row, 1 if no row left */
919 {
920 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
921 ODBCSQLDA *dap = l_con->odbc_descriptor[no_des];
922 short colNum = GetColNum(dap);
923 UWORD i;
924
925
926 odbc_clear_error (con);
927 l_con->rc = SQLFetch(l_con->hstmt[no_des]);
928 if (l_con->rc && l_con->rc != NO_MORE_ROWS) {
929 SQLTCHAR tmpSQLSTATE[6];
930 if
931 (SQLGetDiagRec(SQL_HANDLE_STMT, l_con->hstmt[no_des], 1, tmpSQLSTATE,
932 NULL, NULL, 0, NULL) != SQL_NO_DATA)
933 {
934 /* If `tmpSQLSTATE' is 24000, we try to go to next result set. */
935 if
936 ((tmpSQLSTATE[0] == TXTC('2')) && (tmpSQLSTATE[1] == TXTC('4')) && (tmpSQLSTATE[2] == TXTC('0')) &&
937 (tmpSQLSTATE[3] == TXTC('0')) && (tmpSQLSTATE[4] == TXTC('0')))
938 {
939 l_con->rc = SQLMoreResults(l_con->hstmt[no_des]);
940
941 while (l_con->rc != SQL_SUCCESS && l_con->rc != SQL_SUCCESS_WITH_INFO && l_con->rc != SQL_NO_DATA && l_con->rc != SQL_ERROR)
942 {
943 l_con->rc = SQLMoreResults(l_con->hstmt[no_des]);
944 };
945 if (l_con->rc != SQL_NO_DATA && l_con->rc != SQL_ERROR)
946 {
947 setup_result_space (con, no_des);
948 dap = l_con->odbc_descriptor[no_des];
949 colNum = GetColNum(dap);
950 l_con->rc = SQLFetch(l_con->hstmt[no_des]);
951 }
952 if (l_con->rc == SQL_NO_DATA)
953 {
954 /* We do the same thing later as SQLFetch returns NO_MORE_ROWS
955 * if SQLMoreResults returns SQL_NO_DATA
956 */
957 l_con->rc = NO_MORE_ROWS;
958 }
959 }
960 }
961 if (l_con->rc && l_con->rc != NO_MORE_ROWS)
962 {
963 odbc_error_handler(con, l_con->hstmt[no_des],8);
964 if (l_con->error_number) {
965 odbc_terminate_order(con, no_des);
966 return 1;
967 }
968 }
969 }
970
971
972 if (l_con->rc == NO_MORE_ROWS) /* NO_MORE_ROWS */ {
973 return 1;
974 }
975 else {
976 for (i=0; i<colNum && l_con->error_number == 0; i++) {
977 SQLULEN old_length = GetDbColLength(dap, i);
978 char *l_buffer = GetDbColPtr(dap, i);
979 SQLULEN l_terminator_size = 0;
980 l_con->odbc_indicator[no_des][i] = 0;
981 /* String data have an extra character for the null terminating character. */
982 if ((GetDbCType(dap, i) == SQL_C_WCHAR) || (GetDbCType(dap, i) == SQL_C_CHAR)) {
983 l_terminator_size = sizeof(TCHAR);
984 old_length += l_terminator_size;
985 }
986 if (GetDbCType(dap, i) == SQL_C_NUMERIC){
987 /* Use SQL_ARD_TYPE to force the driver to use data in the row descriptor */
988 l_con->rc = SQLGetData(l_con->hstmt[no_des], i+1, SQL_ARD_TYPE, l_buffer, old_length, &(l_con->odbc_indicator[no_des][i]));
989 } else {
990 l_con->rc = SQLGetData(l_con->hstmt[no_des], i+1, GetDbCType(dap, i), l_buffer, old_length, &(l_con->odbc_indicator[no_des][i]));
991 }
992 if (l_con->rc) {
993 /* Check if it failed because we did not have enough space to store the data. */
994 if (l_con->rc == SQL_SUCCESS_WITH_INFO) {
995 SQLTCHAR tmpSQLSTATE[6];
996 if
997 (SQLGetDiagRec(SQL_HANDLE_STMT, l_con->hstmt[no_des], 1, tmpSQLSTATE,
998 NULL, NULL, 0, NULL) != SQL_NO_DATA)
999 {
1000 /* If `tmpSQLSTATE' is 01004 then we just make our buffer bigger and
1001 * reissue the call. */
1002 if
1003 ((tmpSQLSTATE[0] == TXTC('0')) && (tmpSQLSTATE[1] == TXTC('1')) && (tmpSQLSTATE[2] == TXTC('0')) &&
1004 (tmpSQLSTATE[3] == TXTC('0')) && (tmpSQLSTATE[4] == TXTC('4')))
1005 {
1006 SQLULEN additional_length;
1007 /* We remove the null character from the previous call made to SQLGetData
1008 * because when data is truncated SQLGetData it always add the null character.*/
1009 old_length -= l_terminator_size;
1010 if (l_con->odbc_indicator[no_des][i] == SQL_NO_TOTAL) {
1011 additional_length = DB_MAX_STRING_LEN;
1012 } else {
1013 additional_length = l_con->odbc_indicator[no_des][i] - old_length + l_terminator_size;
1014 }
1015 /* Reuse old memory if possible */
1016 ODBC_SAFE_ALLOC(l_buffer, (char *) realloc (l_buffer, old_length + additional_length));
1017 SetDbColPtr(dap, i, l_buffer);
1018 SetDbColLength(dap, i, old_length + additional_length - l_terminator_size);
1019 /* Reissue the call, this time starting from the end of `l_buffer' since we want to get
1020 * the remaining data. */
1021 l_con->rc = SQLGetData(l_con->hstmt[no_des], i+1, GetDbCType(dap, i), l_buffer + old_length,
1022 additional_length, NULL);
1023 }
1024 }
1025 }
1026 }
1027 if (l_con->rc) {
1028 SQLTCHAR SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
1029 SQLINTEGER NativeError;
1030 SQLSMALLINT MsgLen;
1031
1032 /* Get the status records. */
1033 if ((SQLGetDiagRec(SQL_HANDLE_STMT, l_con->hstmt[no_des], 1, SqlState, &NativeError,
1034 Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA) {
1035 /* DisplayError(SqlState,NativeError,Msg,MsgLen); */
1036 }
1037
1038 odbc_error_handler(con, l_con->hstmt[no_des],9);
1039 }
1040 }
1041 if (l_con->error_number)
1042 return 1;
1043 else
1044 return 0;
1045 }
1046 }
1047 /*****************************************************************/
1048 /* */
1049 /* ROUTINE DESCRIPTION */
1050 /* */
1051 /* NAME: odbc_support_proc() */
1052 /* DESCRIPTION: */
1053 /* to determine if the current ODBC Data Source/Driver support */
1054 /* stored procedure: 1-- yes, 0 -- no */
1055 /* */
1056 /*****************************************************************/
1057
1058 int odbc_support_proc() {
1059 return *storedProc == TXTC('Y') || *storedProc == TXTC('y');
1060 }
1061
1062 /*****************************************************************/
1063 /* */
1064 /* ROUTINE DESCRIPTION */
1065 /* */
1066 /* NAME: odbc_support_create_proc() */
1067 /* DESCRIPTION: */
1068 /* to determine if the current ODBC Data Source/Driver support */
1069 /* stored procedure creation: 1-- yes, 0-- no */
1070 /* */
1071 /*****************************************************************/
1072
1073 int odbc_support_create_proc() {
1074 int i;
1075 int j;
1076 SQLTCHAR tmpStr[DB_MAX_NAME_LEN];
1077
1078 ATSTXTCPY (tmpStr, "stored procedure");
1079 i = SQLTXTCMP(CreateStoredProc, tmpStr);
1080 ATSTXTCPY (tmpStr, "Stored Procedure");
1081 j = SQLTXTCMP(CreateStoredProc, tmpStr);
1082 if (i==0||j==0)
1083 return 1;
1084 else
1085 return 0;
1086 }
1087
1088 /*****************************************************************/
1089 /* */
1090 /* ROUTINE DESCRIPTION */
1091 /* */
1092 /* NAME: odbc_support_infomation_schema() */
1093 /* DESCRIPTION: */
1094 /* to determine if the current ODBC Data Source/Driver support */
1095 /* stored procedure table INFORMATION_SCHEMA: 1-- yes, 0-- no */
1096 /* */
1097 /*****************************************************************/
1098 int odbc_support_information_schema() {
1099 return odbc_info_schema == SQL_IC_MIXED;
1100 }
1101
1102
1103 /*****************************************************************/
1104 /* */
1105 /* ROUTINE DESCRIPTION */
1106 /* */
1107 /* NAME: odbc_driver_name() */
1108 /* DESCRIPTION: */
1109 /* return the name of the driver */
1110 /* */
1111 /*****************************************************************/
1112
1113 SQLTCHAR * odbc_driver_name() {
1114 return dbmsName;
1115 }
1116
1117 /*****************************************************************/
1118 /* */
1119 /* ROUTINE DESCRIPTION */
1120 /* */
1121 /* NAME: odbc_inseneitive_upper() */
1122 /* odbc_insensitive_lower() */
1123 /* odbc_insensitive_mixed() */
1124 /* odbc_sensitive_mixed() */
1125 /* DESCRIPTION: */
1126 /* Decide if the underlying driver is sensitive to upper/lower */
1127 /* cases, and what format is stored in database. */
1128 /* */
1129 /*****************************************************************/
1130 int odbc_insensitive_upper() {
1131 return odbc_case == SQL_IC_UPPER;
1132 }
1133
1134
1135 int odbc_insensitive_lower() {
1136 return odbc_case == SQL_IC_LOWER;
1137 }
1138
1139 int odbc_sensitive_mixed() {
1140 /* Values for odbc_case should be either SQL_IC_UPPER, SQL_IC_LOWER, SQL_IC_MIXED
1141 * or SQL_IC_SENSITIVE. If it is SQL_IC_UNKNOWN (that is to say none of the above), then we consider
1142 * it is case sensitive. */
1143 return (odbc_case == SQL_IC_SENSITIVE) || (odbc_case == SQL_IC_UNKNOWN);
1144 }
1145
1146 int odbc_insensitive_mixed() {
1147 return odbc_case == SQL_IC_MIXED;
1148 }
1149
1150 void odbc_set_parameter(void *con, int no_desc, int seri, int dir, int eifType, int collen, int value_count, void *value) {
1151
1152 SQLUSMALLINT seriNumber = (SQLUSMALLINT)seri;
1153 SQLSMALLINT direction = (SQLSMALLINT)dir;
1154 SQLLEN len;
1155 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1156 SQL_NUMERIC_STRUCT *l_num;
1157
1158 l_con->pcbValue[no_desc][seriNumber-1] = len = value_count;
1159 l_con->rc = 0;
1160 direction = SQL_PARAM_INPUT;
1161 switch (eifType) {
1162 case CHARACTER_TYPE:
1163 case STRING_TYPE:
1164 l_con->rc = SQLBindParameter(l_con->hstmt[no_desc], seriNumber, direction, SQL_C_CHAR, SQL_CHAR, value_count, DB_SIZEOF_CHAR, value, value_count, &(l_con->pcbValue[no_desc][seriNumber-1]));
1165 break;
1166 case WSTRING_TYPE:
1167 l_con->rc = SQLBindParameter(l_con->hstmt[no_desc], seriNumber, direction, SQL_C_WCHAR, SQL_WCHAR, value_count, DB_SIZEOF_WCHAR, value, 0, &(l_con->pcbValue[no_desc][seriNumber-1]));
1168 break;
1169 case INTEGER_TYPE:
1170 l_con->rc = SQLBindParameter(l_con->hstmt[no_desc], seriNumber, direction, SQL_C_SLONG, SQL_INTEGER, value_count, DB_SIZEOF_INT, value, 0, &(l_con->pcbValue[no_desc][seriNumber-1]));
1171 break;
1172 case INTEGER_16_TYPE:
1173 l_con->rc = SQLBindParameter(l_con->hstmt[no_desc], seriNumber, direction, SQL_C_SSHORT, SQL_SMALLINT, value_count, DB_SIZEOF_SHORT, value, 0, &(l_con->pcbValue[no_desc][seriNumber-1]));
1174 break;
1175 case INTEGER_64_TYPE:
1176 l_con->rc = SQLBindParameter(l_con->hstmt[no_desc], seriNumber, direction, SQL_C_SBIGINT, SQL_BIGINT, value_count, DB_SIZEOF_BIGINT, value, 0, &(l_con->pcbValue[no_desc][seriNumber-1]));
1177 break;
1178 case FLOAT_TYPE:
1179 /* See example: http://msdn.microsoft.com/en-us/library/ms710963%28v=VS.85%29.aspx */
1180 l_con->rc = SQLBindParameter(l_con->hstmt[no_desc], seriNumber, direction, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, value, 0, &(l_con->pcbValue[no_desc][seriNumber-1]));
1181 break;
1182 case REAL_TYPE:
1183 /* See example: http://msdn.microsoft.com/en-us/library/ms710963%28v=VS.85%29.aspx */
1184 l_con->rc = SQLBindParameter(l_con->hstmt[no_desc], seriNumber, direction, SQL_C_FLOAT, SQL_REAL, 0, 0, value, 0, &(l_con->pcbValue[no_desc][seriNumber-1]));
1185 break;
1186 case BOOLEAN_TYPE:
1187 l_con->rc = SQLBindParameter(l_con->hstmt[no_desc], seriNumber, direction, SQL_C_BIT, SQL_BIT, value_count, DB_SIZEOF_INT, value, 0, &(l_con->pcbValue[no_desc][seriNumber-1]));
1188 break;
1189 case DATE_TYPE:
1190 len = l_con->pcbValue[no_desc][seriNumber-1] = sizeof(TIMESTAMP_STRUCT);
1191 l_con->rc = SQLBindParameter(l_con->hstmt[no_desc], seriNumber, direction, SQL_C_TIMESTAMP, SQL_TYPE_TIMESTAMP, 23, 3, value, 0, &(l_con->pcbValue[no_desc][seriNumber-1]));
1192 break;
1193 case DECIMAL_TYPE:
1194 l_num = (SQL_NUMERIC_STRUCT *)value;
1195 l_con->rc = SQLBindParameter(l_con->hstmt[no_desc], seriNumber, direction, SQL_C_NUMERIC, SQL_DECIMAL, l_con->default_precision, l_con->default_scale, value, 0, &(l_con->pcbValue[no_desc][seriNumber-1]));
1196 break;
1197 default:
1198 odbc_error_handler(con, NULL, 204);
1199 ATSTXTCAT(l_con->error_message, "\nInvalid Data Type in odbc_set_parameter");
1200 odbc_error_handler(con, NULL, 110);
1201 return;
1202 }
1203 if (l_con->rc) {
1204 odbc_error_handler(con, l_con->hstmt[no_desc], l_con->rc);
1205 return;
1206 }
1207 }
1208
1209 /*****************************************************************/
1210 /* */
1211 /* ROUTINE DESCRIPTION */
1212 /* */
1213 /* NAME: odbc_set_col_flag() */
1214 /* PARAMETER: no_desc - the index of descriptor */
1215 /* DESCRIPTION: */
1216 /* to indicate the statement for descriptor 'no_desc' is to */
1217 /* get column(s) (of a special table or whole data source). */
1218 /* */
1219 /*****************************************************************/
1220 void odbc_set_col_flag(void *con, int no_desc) {
1221 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1222 l_con->flag[no_desc] = ODBC_CATALOG_COL;
1223 }
1224
1225 /*****************************************************************/
1226 /* */
1227 /* ROUTINE DESCRIPTION */
1228 /* */
1229 /* NAME: odbc_set_tab_flag() */
1230 /* PARAMETER: no_desc - the index of descriptor */
1231 /* DESCRIPTION: */
1232 /* to indicate the statement for descriptor 'no_desc' is to */
1233 /* get table(s) in the current Data Source. */
1234 /* */
1235 /*****************************************************************/
1236 void odbc_set_tab_flag(void *con, int no_desc) {
1237 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1238 l_con->flag[no_desc] = ODBC_CATALOG_TAB;
1239 }
1240
1241 /*****************************************************************/
1242 /* */
1243 /* ROUTINE DESCRIPTION */
1244 /* */
1245 /* NAME: odbc_set_proc_flag() */
1246 /* PARAMETER: no_desc - the index of descriptor */
1247 /* DESCRIPTION: */
1248 /* to indicate the statement for descriptor 'no_desc' is to */
1249 /* get stored procedure(s) in the current Data Source. */
1250 /* */
1251 /*****************************************************************/
1252 void odbc_set_proc_flag(void *con, int no_desc) {
1253 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1254 l_con->flag[no_desc] = ODBC_CATALOG_PROC;
1255 }
1256
1257 /*****************************************************************/
1258 /* */
1259 /* ROUTINE DESCRIPTION */
1260 /* */
1261 /* NAME: odbc_hide_qualifier */
1262 /* PARAMETER: buf -- the content of a SQL command */
1263 /* DESCRIPTION: */
1264 /* When "qualifier" is used to identify an database object, */
1265 /* we have to hide ":" in the qualifier first, otherwise, it */
1266 /* will be misinterpreted by feature SQL_SCAN::parse. */
1267 /* */
1268 /*****************************************************************/
1269 SQLTCHAR *odbc_hide_qualifier(SQLTCHAR *buf) {
1270 size_t i;
1271 size_t len = TXTLEN(buf);
1272
1273 for (i=0; i < len; i++) {
1274 if (buf[i] == TXTC(':') && i > 0 && ((buf[i-1] >= TXTC('a') && buf[i-1] <= TXTC('z')) || (buf[i-1] >=TXTC('A') && buf[i-1] <= TXTC('Z'))))
1275 buf[i] = 0x1 ;
1276 }
1277 return buf;
1278 }
1279
1280 /*****************************************************************/
1281 /* */
1282 /* ROUTINE DESCRIPTION */
1283 /* */
1284 /* NAME: odbc_unhide_qualifier */
1285 /* PARAMETER: buf -- the content of a SQL command */
1286 /* DESCRIPTION: */
1287 /* When "qualifier" is used to identify an database object, */
1288 /* we have to hide ":" in the qualifier first, otherwise, it */
1289 /* will be misinterpreted by feature SQL_SCAN::parse. After */
1290 /* the command has been parsed, we should recover the original */
1291 /* ":" in the qualifier. */
1292 /* */
1293 /*****************************************************************/
1294 void odbc_unhide_qualifier(SQLTCHAR *buf) {
1295 size_t i;
1296 size_t len = TXTLEN(buf);
1297
1298 for (i=0; i < len; i++) {
1299 if (buf[i] == 0x1 && i > 0 && ((buf[i-1] >= TXTC('a') && buf[i-1] <= TXTC('z')) || (buf[i-1] >=TXTC('A') && buf[i-1] <= TXTC('Z'))))
1300 buf[i] = TXTC(':') ;
1301 }
1302 }
1303
1304 /*****************************************************************/
1305 /* */
1306 /* ROUTINE DESCRIPTION */
1307 /* */
1308 /* NAME: odbc_qualifier_quoter */
1309 /* DESCRIPTION: */
1310 /* Return the string used to quote identifiers in SQL command, */
1311 /* For example, if the quoter is `, and we want to select on */
1312 /* table "my table", we should express the query as: */
1313 /* select * from `My table` */
1314 /* */
1315 /*****************************************************************/
1316 SQLTCHAR *odbc_identifier_quoter() {
1317 return idQuoter;
1318 }
1319
1320 /*****************************************************************/
1321 /* */
1322 /* ROUTINE DESCRIPTION */
1323 /* */
1324 /* NAME: odbc_qualifier_seperator */
1325 /* DESCRIPTION: */
1326 /* When "qualifier" and "owner" are used to identifier a */
1327 /* database object, they should be seperated by a string called */
1328 /* "qualifier seperator". */
1329 /* */
1330 /*****************************************************************/
1331 SQLTCHAR *odbc_qualifier_seperator() {
1332 return quaNameSep;
1333 }
1334
1335 /*****************************************************************/
1336 /* */
1337 /* ROUTINE DESCRIPTION */
1338 /* */
1339 /* NAME: odbc_set_qualifier */
1340 /* PARAMETER: qfy -- the content of qualifier */
1341 /* DESCRIPTION: */
1342 /* Set qualifier to a global variable. The function is used */
1343 /* to implement command "SQLTable(tanle_name)" conviently. */
1344 /* */
1345 /*****************************************************************/
1346 void odbc_set_qualifier(SQLTCHAR *qfy) {
1347 if (qfy == NULL)
1348 odbc_qualifier[0] = (SQLTCHAR)0;
1349 else
1350 SQLTXTCPY(odbc_qualifier, qfy);
1351 }
1352
1353 /*****************************************************************/
1354 /* */
1355 /* ROUTINE DESCRIPTION */
1356 /* */
1357 /* NAME: odbc_set_owner */
1358 /* PARAMETER: owner- the owner */
1359 /* DESCRIPTION: */
1360 /* Set owner to a global variable. The function is used */
1361 /* to implement command "SQLTable(tanle_name)" conviently. */
1362 /* */
1363 /*****************************************************************/
1364 void odbc_set_owner(SQLTCHAR *owner) {
1365 if (owner == NULL)
1366 odbc_owner[0] = (SQLTCHAR)0;
1367 else
1368 SQLTXTCPY(odbc_owner, owner);
1369
1370 }
1371
1372 /*****************************************************************/
1373 /* */
1374 /* ROUTINE DESCRIPTION */
1375 /* */
1376 /* NAME: odbc_unset_catalog_flag() */
1377 /* PARAMETER: no_desc - the index of descriptor */
1378 /* DESCRIPTION: */
1379 /* to indicate the statement for descriptor 'no_desc' is a */
1380 /* general ODBC SQL statement. */
1381 /* */
1382 /*****************************************************************/
1383 void odbc_unset_catalog_flag(void *con, int no_desc) {
1384 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1385 l_con->flag[no_desc] = ODBC_SQL;
1386 }
1387
1388 /*****************************************************************/
1389 /*The following are the function related with DATABASE CONTROL */
1390 /*****************************************************************/
1391
1392 /*****************************************************************/
1393 /* */
1394 /* ROUTINE DESCRIPTION */
1395 /* */
1396 /* NAME: odbc_connect(name,passwd,role,rolePassWd,group,baseName) */
1397 /* PARAMETERS: */
1398 /* name - data base user name. */
1399 /* passwd - data base user's password(no use for ODBC ). */
1400 /* role - data base role name. */
1401 /* rolePassWd - data base role's password. */
1402 /* group - data base group name. */
1403 /* baseName - the ODBC data base which will be used in the */
1404 /* current connection. */
1405 /* DESCRIPTION: */
1406 /* Connect to an ODBC database. */
1407 /* NOTE: Only the name is mandatory. */
1408 /* */
1409 /*****************************************************************/
1410 void odbc_connect (void *con, SQLTCHAR *name, SQLTCHAR *passwd, SQLTCHAR *dsn)
1411 {
1412 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1413
1414 odbc_clear_error (con);
1415
1416 l_con->rc = SQLAllocHandle(SQL_HANDLE_DBC,henv, &l_con->hdbc);
1417 if (l_con->rc) {
1418 odbc_error_handler(con, NULL,11);
1419 return;
1420 }
1421
1422 l_con->rc = SQLConnect(l_con->hdbc, dsn, SQL_NTS, name, SQL_NTS, passwd, SQL_NTS);
1423 if (l_con->rc<0) {
1424 odbc_error_handler(con, NULL,12);
1425 l_con->rc = SQLFreeHandle(SQL_HANDLE_DBC,l_con->hdbc);
1426 return;
1427 }
1428
1429 odbc_fetch_connection_info (con);
1430
1431 }
1432
1433 /*****************************************************************/
1434 /*The following are the function related with DATABASE CONTROL */
1435 /*****************************************************************/
1436
1437 /*****************************************************************/
1438 /* */
1439 /* ROUTINE DESCRIPTION */
1440 /* */
1441 /* NAME: odbc_connect_by_string(a_string) */
1442 /* PARAMETERS: */
1443 /* a_string - connect string. */
1444 /* current connection. */
1445 /* DESCRIPTION: */
1446 /* Connect to an ODBC database. */
1447 /* */
1448 /*****************************************************************/
1449 void odbc_connect_by_connection_string (void *con, SQLTCHAR *a_string)
1450 {
1451 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1452
1453 odbc_clear_error (con);
1454
1455 l_con->rc = SQLAllocHandle(SQL_HANDLE_DBC,henv, &l_con->hdbc);
1456 if (l_con->rc) {
1457 odbc_error_handler(con, NULL,11);
1458 return;
1459 }
1460
1461 l_con->rc = SQLDriverConnect( // SQL_NULL_HDBC
1462 l_con->hdbc,
1463 NULL,
1464 a_string,
1465 (SQLSMALLINT)sqlstrlen(a_string),
1466 NULL,
1467 0,
1468 NULL,
1469 SQL_DRIVER_NOPROMPT);
1470 if (l_con->rc<0) {
1471 odbc_error_handler(con, NULL,12);
1472 l_con->rc = SQLFreeHandle(SQL_HANDLE_DBC,l_con->hdbc);
1473 return;
1474 }
1475
1476 odbc_fetch_connection_info (con);
1477
1478 }
1479
1480 /*****************************************************************/
1481 /* */
1482 /* ROUTINE DESCRIPTION */
1483 /* */
1484 /* NAME: odbc_get_connection_info() */
1485 /* DESCRIPTION: */
1486 /* Get connection info after connection */
1487 /* */
1488 /*****************************************************************/
1489
1490 void odbc_fetch_connection_info (void *con)
1491 {
1492 SQLSMALLINT indColName;
1493 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1494
1495 l_con->rc = SQLGetInfo(l_con->hdbc, SQL_PROCEDURES, dbmsName, sizeof(dbmsName), &indColName);
1496 SQLTXTCPY(storedProc, dbmsName);
1497 l_con->rc = SQLGetInfo(l_con->hdbc, SQL_PROCEDURE_TERM, dbmsName, sizeof(dbmsName), &indColName);
1498 SQLTXTCPY(CreateStoredProc, dbmsName);
1499 l_con->rc = SQLGetInfo(l_con->hdbc, SQL_DBMS_NAME, dbmsName, sizeof(dbmsName), &indColName);
1500 l_con->rc = SQLGetInfo(l_con->hdbc, SQL_DBMS_VER, dbmsVer, sizeof(dbmsVer), &indColName);
1501 l_con->rc = SQLGetInfo(l_con->hdbc, SQL_IDENTIFIER_QUOTE_CHAR, idQuoter, sizeof(idQuoter), &indColName);
1502 l_con->rc = SQLGetInfo(l_con->hdbc, SQL_QUOTED_IDENTIFIER_CASE, &odbc_case, sizeof(odbc_case), &indColName);
1503 l_con->rc = SQLGetInfo(l_con->hdbc, SQL_INFO_SCHEMA_VIEWS, &odbc_info_schema, sizeof(odbc_info_schema), &indColName);
1504
1505 if (indColName == 1 && idQuoter[0] == TXTC(' ')) {
1506 idQuoter[0] = (SQLTCHAR)0;
1507 } else {
1508 idQuoter[indColName] = (SQLTCHAR)0;
1509 }
1510
1511 l_con->rc = SQLGetInfo(l_con->hdbc, SQL_CATALOG_NAME_SEPARATOR, quaNameSep, sizeof(quaNameSep), &indColName);
1512 if (indColName == 1 && quaNameSep[0] == TXTC(' ')) {
1513 quaNameSep[0] = (SQLTCHAR)0;
1514 } else {
1515 quaNameSep[indColName] = (SQLTCHAR)0;
1516 }
1517 }
1518
1519 /*****************************************************************/
1520 /* */
1521 /* ROUTINE DESCRIPTION */
1522 /* */
1523 /* NAME: odbc_disconnect() */
1524 /* DESCRIPTION: */
1525 /* Disconnect the current connection with an ODBC database. */
1526 /* */
1527 /*****************************************************************/
1528 void odbc_disconnect (void *con)
1529 {
1530 int count;
1531 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1532
1533 odbc_clear_error (con);
1534
1535 /* Call SQLEndTran on connection level rather than environment level.
1536 * Because we don't want to EndTran on other connections in current enviroment */
1537 l_con->rc = SQLEndTran(SQL_HANDLE_DBC, l_con->hdbc, SQL_COMMIT);
1538 if (l_con->rc) {
1539 odbc_error_handler(con, NULL,13);
1540 }
1541 for (count = 0; count < MAX_DESCRIPTOR; count++)
1542 {
1543 odbc_terminate_order(con, count);
1544 }
1545
1546 l_con->rc = SQLDisconnect(l_con->hdbc);
1547 if (l_con->rc) {
1548 odbc_error_handler(con, NULL,14);
1549 }
1550
1551 /* odbc_tranNumber was originally set to 0 only if l_con->number_connection <= 1:
1552 * this is not consistent with EiffelStore so all transactions are ended
1553 * when disconnecting. Anyway, odbc_tranNumber <= 1.
1554 * Cedric */
1555 l_con->odbc_tranNumber = 0;
1556 }
1557
1558 /*****************************************************************/
1559 /* */
1560 /* ROUTINE DESCRIPTION */
1561 /* */
1562 /* NAME: odbc_free_connection() */
1563 /* DESCRIPTION: */
1564 /* Free odbc connection, if there is no more connection, */
1565 /* free the odbc environment. */
1566 /* */
1567 /*****************************************************************/
1568 void odbc_free_connection (void *con)
1569 {
1570 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1571
1572 /* Error is not accessible by Eiffel */
1573 SQLFreeHandle (SQL_HANDLE_DBC, l_con->hdbc);
1574 number_connection--;
1575
1576 ODBC_C_FREE (l_con->error_message);
1577 ODBC_C_FREE (l_con->warn_message);
1578 ODBC_C_FREE (l_con);
1579
1580 /* When there is no connection any more, we free the environment handle */
1581 if (number_connection <= 0) {
1582 /* Error is not accessible by Eiffel */
1583 SQLFreeHandle (SQL_HANDLE_ENV, henv);
1584 }
1585 }
1586
1587 /*****************************************************************/
1588 /* */
1589 /* ROUTINE DESCRIPTION */
1590 /* */
1591 /* NAME: odbc_rollback() */
1592 /* DESCRIPTION: */
1593 /* Roll back the current transaction . */
1594 /* */
1595 /*****************************************************************/
1596 void odbc_rollback (void *con)
1597 {
1598 int count;
1599 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1600
1601 odbc_clear_error (con);
1602 l_con->rc = SQLEndTran(SQL_HANDLE_DBC, l_con->hdbc, SQL_ROLLBACK);
1603 if (l_con->rc) {
1604 odbc_error_handler(con, NULL,17);
1605 }
1606 /* Command ROLLBACK closes all open cursors; discards all statements */
1607 /* that were prepared in the current transaction. */
1608 for (count = 0; count < MAX_DESCRIPTOR; count++)
1609 {
1610 odbc_terminate_order(con, count);
1611 }
1612 l_con->odbc_tranNumber = 0;
1613
1614 l_con->rc = SQLSetConnectOption(l_con->hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON);
1615 if (l_con->rc) {
1616 odbc_error_handler(con, NULL, 12);
1617 }
1618 }
1619
1620 /*****************************************************************/
1621 /* */
1622 /* ROUTINE DESCRIPTION */
1623 /* */
1624 /* NAME: odbc_commit() */
1625 /* DESCRIPTION: */
1626 /* Commit the current transaction. */
1627 /* */
1628 /*****************************************************************/
1629 void odbc_commit (void *con)
1630 {
1631 int count;
1632 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1633
1634 odbc_clear_error (con);
1635 l_con->rc = SQLEndTran(SQL_HANDLE_DBC, l_con->hdbc, SQL_COMMIT);
1636 if (l_con->rc) {
1637 odbc_error_handler(con, NULL,18);
1638 }
1639 /* Command COMMIT closes all open cursors; discards all statements */
1640 /* that were prepared in the current transaction. */
1641 for (count = 0; count < MAX_DESCRIPTOR; count++)
1642 {
1643 odbc_terminate_order(con, count);
1644 }
1645 l_con->odbc_tranNumber = 0;
1646
1647 l_con->rc = SQLSetConnectOption(l_con->hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON);
1648 if (l_con->rc) {
1649 odbc_error_handler(con, NULL, 12);
1650 }
1651 }
1652
1653 /*****************************************************************/
1654 /* */
1655 /* ROUTINE DESCRIPTION */
1656 /* */
1657 /* NAME: odbc_begin() */
1658 /* DESCRIPTION: */
1659 /* Begin a data base transaction. */
1660 /* */
1661 /*****************************************************************/
1662 void odbc_begin (void *con)
1663 {
1664 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1665 odbc_clear_error (con);
1666
1667 l_con->rc = SQLSetConnectOption(l_con->hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
1668 if (l_con->rc) {
1669 odbc_error_handler(con, NULL, 12);
1670 }
1671 }
1672
1673 /*****************************************************************/
1674 /* */
1675 /* ROUTINE DESCRIPTION */
1676 /* */
1677 /* NAME: odbc_trancount() */
1678 /* DESCRIPTION: */
1679 /* Return the number of transactions now active. */
1680 /* */
1681 /*****************************************************************/
1682 int odbc_trancount (void *con)
1683 {
1684 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1685 return l_con->odbc_tranNumber;
1686 }
1687
1688 /*****************************************************************/
1689 /* The following functions are used to get data from structure */
1690 /* ODBCSQLDA filled by FETCH clause. */
1691 /*****************************************************************/
1692 /* */
1693 void cut_tail_blank(SQLTCHAR *buf) {
1694 size_t j;
1695
1696 if (buf != NULL) {
1697 for(j=TXTLEN(buf)-1;j>=0 && buf[j]==TXTC(' '); j--);
1698 j++;
1699 buf[j] = (SQLTCHAR)0;
1700 }
1701 }
1702
1703 /*****************************************************************/
1704 /* Set precision and scale when reading from the decimal from ODBC */
1705 /*****************************************************************/
1706 /* */
1707 void odbc_set_decimal_presicion_and_scale (void *con, int precision, int scale)
1708 {
1709 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1710 l_con->default_precision = precision;
1711 l_con->default_scale = scale;
1712 }
1713
1714 int odbc_get_count (void *con, int no_des)
1715 {
1716 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1717 if (l_con->odbc_descriptor[no_des] == NULL)
1718 return -1;
1719
1720 return GetColNum(l_con->odbc_descriptor[no_des]);
1721 }
1722
1723 size_t odbc_put_col_name (void *con, int no_des, int index, SQLTCHAR *result)
1724 {
1725 size_t size;
1726 int i = index - 1;
1727 SQLTCHAR buf[DB_MAX_NAME_LEN+1];
1728 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1729
1730 size = (((l_con->odbc_descriptor[no_des])->sqlvar)[i]).sqlname.sqlnamel;
1731 memcpy(buf, (((l_con->odbc_descriptor[no_des])->sqlvar)[i]).sqlname.sqlnamec, size * sizeof (SQLTCHAR));
1732 buf[size] = (SQLTCHAR)0;
1733 cut_tail_blank(buf);
1734 size = TXTLEN(buf);
1735 memcpy(result, buf, size * sizeof (SQLTCHAR));
1736 return(size);
1737 }
1738
1739 SQLULEN odbc_get_col_len (void *con, int no_des, int index)
1740 {
1741 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1742 int i = index - 1;
1743 SQLULEN length = GetDbColLength(l_con->odbc_descriptor[no_des], i);
1744
1745 return length;
1746 }
1747
1748 SQLULEN odbc_get_data_len (void *con, int no_des, int index)
1749 {
1750 int i = index - 1;
1751 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1752 int type = GetDbCType(l_con->odbc_descriptor[no_des], i);
1753 SQLULEN length = GetDbColLength(l_con->odbc_descriptor[no_des], i);
1754
1755 switch (type)
1756 {
1757 case SQL_C_TCHAR:
1758 if (l_con->odbc_indicator[no_des][i] == SQL_NULL_DATA) {
1759 return 0;
1760 }
1761 else {
1762 return l_con->odbc_indicator[no_des][i];
1763 }
1764 case SQL_C_GUID:
1765 return 36; /* Length of this format: "958F6235-7877-433A-A1A7-809913122C1E" */
1766 default:
1767 return length;
1768 }
1769 }
1770
1771 int odbc_conv_type (int typeCode)
1772 {
1773 int type=typeCode;
1774
1775 switch (type) {
1776 case SQL_CHAR:
1777 case SQL_VARCHAR:
1778 case SQL_LONGVARCHAR:
1779 case SQL_BINARY:
1780 case SQL_VARBINARY:
1781 case SQL_LONGVARBINARY:
1782 case SQL_SS_XML:
1783 case SQL_C_GUID:
1784 return STRING_TYPE;
1785 case SQL_WCHAR:
1786 case SQL_WVARCHAR:
1787 case SQL_WLONGVARCHAR:
1788 return WSTRING_TYPE;
1789 case SQL_DECIMAL:
1790 case SQL_NUMERIC:
1791 return DECIMAL_TYPE;
1792 case SQL_FLOAT:
1793 case SQL_DOUBLE:
1794 return FLOAT_TYPE;
1795 case SQL_REAL:
1796 return REAL_TYPE;
1797 case SQL_TINYINT:
1798 case SQL_SMALLINT:
1799 return INTEGER_16_TYPE;
1800 case SQL_INTEGER:
1801 return INTEGER_TYPE;
1802 case SQL_BIGINT:
1803 return INTEGER_64_TYPE;
1804 case SQL_BIT:
1805 return BOOLEAN_TYPE;
1806 case SQL_DATE:
1807 case SQL_TYPE_DATE:
1808 case SQL_TIME:
1809 case SQL_TYPE_TIME:
1810 case SQL_TIMESTAMP:
1811 case SQL_TYPE_TIMESTAMP:
1812 return DATE_TYPE;
1813 default:
1814 return UNKNOWN_TYPE;
1815 }
1816 }
1817
1818 int odbc_get_col_type (void *con, int no_des, int index)
1819 {
1820 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1821 int i = index - 1;
1822
1823 return odbc_conv_type (GetDbColType(l_con->odbc_descriptor[no_des], i));
1824 }
1825
1826 SQLULEN odbc_put_data (void *con, int no_des, int index, char **result)
1827 {
1828 int i = index -1;
1829 SQLGUID *g;
1830 SQLLEN odbc_tmp_indicator;
1831 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1832 ODBCSQLDA * dap = l_con->odbc_descriptor[no_des];
1833 int data_type = GetDbCType (dap, i);
1834
1835 odbc_tmp_indicator = l_con->odbc_indicator[no_des][i];
1836 if (odbc_tmp_indicator == SQL_NULL_DATA) {
1837 return 0;
1838 }
1839
1840 switch (data_type) {
1841 case SQL_C_GUID:
1842 g = (SQLGUID *)GetDbColPtr(dap, i);
1843 /* We allocate 37 because `sprintf' will add a null terminating character. */
1844 *result = (char *)malloc(37);
1845 sprintf (*result,
1846 "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1847 (unsigned long) g->Data1,
1848 g->Data2, g->Data3,
1849 g->Data4[0], g->Data4[1], g->Data4[2], g->Data4[3],
1850 g->Data4[4], g->Data4[5], g->Data4[6], g->Data4[7]);
1851 return 36; /* Length of format "958F6235-7877-433A-A1A7-809913122C1E" */
1852 default:
1853 *result = malloc(odbc_tmp_indicator);
1854 memcpy(*result, GetDbColPtr(dap, i), odbc_tmp_indicator);
1855 return(odbc_tmp_indicator);
1856 }
1857 }
1858
1859 SQLINTEGER odbc_get_integer_data (void *con, int no_des, int index)
1860 {
1861 int i = index - 1;
1862 int result;
1863 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1864 ODBCSQLDA * dbp = l_con->odbc_descriptor[no_des];
1865 long lint;
1866 int data_type;
1867
1868 data_type = GetDbCType(dbp, i);
1869
1870 if (l_con->odbc_indicator[no_des][i] == SQL_NULL_DATA) {
1871 /* the retrieved value is NULL, we use 0 to be NULL value */
1872 return 0;
1873 }
1874
1875 switch (data_type) {
1876 case SQL_C_SLONG:
1877 memcpy((char *)(&lint), GetDbColPtr(dbp, i), DB_SIZEOF_LONG);
1878 result = lint;
1879 return result;
1880 default:
1881 ATSTXTCAT(l_con->error_message, "\nError INTEGER type or data length in odbc_get_integer_data. ");
1882 if (l_con->error_number) {
1883 return 0;
1884 }
1885 else {
1886 l_con->error_number = -DB_ERROR-1;
1887 return 0;
1888 }
1889 }
1890 }
1891
1892 SQLSMALLINT odbc_get_integer_16_data (void *con, int no_des, int index)
1893 {
1894 int i = index - 1;
1895 SQLSMALLINT result;
1896 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1897 ODBCSQLDA * dbp = l_con->odbc_descriptor[no_des];
1898 SQLSMALLINT sint = 0;
1899 int data_type;
1900
1901 data_type = GetDbCType(dbp, i);
1902
1903 if (l_con->odbc_indicator[no_des][i] == SQL_NULL_DATA) {
1904 /* the retrieved value is NULL, we use 0 to be NULL value */
1905 return 0;
1906 }
1907
1908 switch (data_type) {
1909 case SQL_C_STINYINT:
1910 result = *((char *)(dbp->sqlvar)[i].sqldata);
1911 return result;
1912 case SQL_C_SSHORT:
1913 memcpy((char *)(&sint), GetDbColPtr(dbp, i), DB_SIZEOF_SHORT);
1914 result = sint;
1915 return result;
1916 default:
1917 ATSTXTCAT(l_con->error_message, "\nError INTEGER_16 type or data length in odbc_get_integer_data. ");
1918 if (l_con->error_number) {
1919 return 0;
1920 }
1921 else {
1922 l_con->error_number = -DB_ERROR-1;
1923 return 0;
1924 }
1925 }
1926 }
1927
1928 EIF_INTEGER_64 odbc_get_integer_64_data (void *con, int no_des, int index)
1929 {
1930 int i = index - 1;
1931 EIF_INTEGER_64 result;
1932 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1933 ODBCSQLDA * dbp = l_con->odbc_descriptor[no_des];
1934 EIF_INTEGER_64 bint;
1935 int data_type;
1936
1937 data_type = GetDbCType(dbp, i);
1938
1939 if (l_con->odbc_indicator[no_des][i] == SQL_NULL_DATA) {
1940 /* the retrieved value is NULL, we use 0 to be NULL value */
1941 return 0;
1942 }
1943
1944 switch (data_type) {
1945 case SQL_C_SBIGINT:
1946 memcpy((char *)(&bint), GetDbColPtr(dbp, i), DB_SIZEOF_BIGINT);
1947 result = bint;
1948 return result;
1949 default:
1950 ATSTXTCAT(l_con->error_message, "\nError INTEGER_64 type or data length in odbc_get_integer_data. ");
1951 if (l_con->error_number) {
1952 return 0;
1953 }
1954 else {
1955 l_con->error_number = -DB_ERROR-1;
1956 return 0;
1957 }
1958 }
1959 }
1960
1961 int odbc_get_boolean_data (void *con, int no_des, int index)
1962 {
1963 int i = index - 1;
1964 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1965 ODBCSQLDA * dbp = l_con->odbc_descriptor[no_des];
1966 int data_type = GetDbCType (dbp,i);
1967
1968 if (data_type == SQL_C_BIT) {
1969 if (l_con->odbc_indicator[no_des][i] == SQL_NULL_DATA) {
1970 /* the retrived value is NULL, we use false to be NULL value */
1971 return 0;
1972 }
1973 return *((char *)(GetDbColPtr(dbp, i))) != 0;
1974 }
1975 ATSTXTCAT(l_con->error_message, "\nError BOOLEAN type in odbc_get_boolean_data. ");
1976 if (l_con->error_number) {
1977 return 0;
1978 }
1979 else {
1980 l_con->error_number = -DB_ERROR-2;
1981 return 0;
1982 }
1983 }
1984
1985 double odbc_get_float_data (void *con, int no_des, int index)
1986 {
1987 int i = index - 1;
1988 double result_double;
1989 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
1990 ODBCSQLDA * dbp = l_con->odbc_descriptor[no_des];
1991 SQL_NUMERIC_STRUCT NumStr;
1992 int j,sign =1;
1993 EIF_NATURAL_64 myvalue, divisor;
1994 double final_val;
1995 int data_type;
1996
1997 data_type = GetDbCType (dbp, i);
1998
1999 if ( data_type == SQL_C_DOUBLE ) {
2000 if (l_con->odbc_indicator[no_des][i] == SQL_NULL_DATA) {
2001 /* the retrieved value is NULL, we use 0.0 to be NULL value and we indicate it*/
2002 return 0.0;
2003 }
2004 memcpy((char *)(&result_double), GetDbColPtr(dbp, i), DB_SIZEOF_DOUBLE);
2005 /* result = *(double *)(dbp->sqlvar)[i].sqldata; */
2006 return result_double;
2007 } else if (data_type == SQL_C_NUMERIC){
2008 if (l_con->odbc_indicator[no_des][i] == SQL_NULL_DATA) {
2009 /* the retrieved value is NULL, we use 0.0 to be NULL value and we indicate it*/
2010 return 0.0;
2011 }
2012 memcpy((char *)(&NumStr), GetDbColPtr(dbp, i), sizeof (SQL_NUMERIC_STRUCT));
2013 myvalue = strhextoval(&NumStr);
2014 divisor = 1;
2015 if(NumStr.scale > 0){
2016 for (j=0;j< NumStr.scale; j++)
2017 divisor = divisor * 10;
2018 }
2019 final_val = myvalue /(double) divisor;
2020 if(!NumStr.sign)
2021 sign = -1;
2022 else
2023 sign = 1;
2024 final_val *= sign;
2025 return final_val;
2026 }
2027 ATSTXTCAT(l_con->error_message, "\nError FLOAT type in odbc_get_float_data. ");
2028 if (l_con->error_number) {
2029 return 0.0;
2030 }
2031 else {
2032 l_con->error_number = -DB_ERROR-3;
2033 return 0.0;
2034 }
2035 }
2036
2037 float odbc_get_real_data (void *con, int no_des, int index)
2038 {
2039 int i = index - 1;
2040 float result_real;
2041 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
2042 ODBCSQLDA * dbp = l_con->odbc_descriptor[no_des];
2043 int data_type;
2044
2045 data_type = GetDbCType (dbp, i);
2046 if (data_type == SQL_C_FLOAT) {
2047 if (l_con->odbc_indicator[no_des][i] == SQL_NULL_DATA) {
2048 /* the retrieved value is NULL, we use 0.0 to be NULL value */
2049 return 0.0;
2050 }
2051 memcpy((char *)(&result_real), GetDbColPtr(dbp, i), DB_SIZEOF_REAL);
2052 /* result_real = *(float *)(dbp->sqlvar)[i].sqldata; */
2053 return result_real;
2054 }
2055 ATSTXTCAT(l_con->error_message, "\nError REAL type in odbc_get_real_data. ");
2056 if (l_con->error_number) {
2057 return 0.0;
2058 }
2059 else {
2060 l_con->error_number = -DB_ERROR-4;
2061 return 0.0;
2062 }
2063 }
2064
2065 /* The following function tell whether the retrieved data is null or not */
2066 int odbc_is_null_data(void *con, int no_des, int index)
2067 {
2068 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
2069 return (l_con->odbc_indicator[no_des][index-1] == SQL_NULL_DATA);
2070 }
2071
2072 /*****************************************************************/
2073 /* The following function deal with the DATE data of ODBC */
2074 /*****************************************************************/
2075
2076 int odbc_get_date_data (void *con, int no_des, int index)
2077 {
2078 int i = index - 1;
2079 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
2080 ODBCSQLDA * dbp = l_con->odbc_descriptor[no_des];
2081 DATE_STRUCT *dateP;
2082 TIMESTAMP_STRUCT *stampP;
2083 TIME_STRUCT *timeP;
2084 int data_type;
2085
2086 data_type = GetDbCType(dbp, i);
2087 /* if (data_type == SQL_C_DATE || data_type == SQL_C_TIMESTAMP || data_type == SQL_C_TIME) */
2088 if (data_type == SQL_C_TYPE_DATE || data_type == SQL_C_TYPE_TIMESTAMP || data_type == SQL_C_TYPE_TIME)
2089 {
2090 if (l_con->odbc_indicator[no_des][i] == SQL_NULL_DATA) {
2091 /* the retrived value is NULL, we use 01/01/1991 0:0:0 to be NULL value
2092 l_con->odbc_date.year = 1991;
2093 l_con->odbc_date.month = 1;
2094 l_con->odbc_date.day = 1;
2095 l_con->odbc_date.hour = 0;
2096 l_con->odbc_date.minute = 0;
2097 l_con->odbc_date.second = 0;
2098 */
2099 return 0;
2100 }
2101 /* if (data_type == SQL_C_DATE) { */
2102 if (data_type == SQL_C_TYPE_DATE) {
2103 dateP = (DATE_STRUCT *)(GetDbColPtr(dbp, i));
2104 l_con->odbc_date.year = dateP->year;
2105 l_con->odbc_date.month = dateP->month;
2106 l_con->odbc_date.day = dateP->day;
2107 l_con->odbc_date.hour = 0;
2108 l_con->odbc_date.minute = 0;
2109 l_con->odbc_date.second = 0;
2110 return 1;
2111 }
2112 /* if (data_type == SQL_C_TIMESTAMP) { */
2113 if (data_type == SQL_C_TYPE_TIMESTAMP) {
2114 stampP = (TIMESTAMP_STRUCT *)(GetDbColPtr(dbp, i));
2115 l_con->odbc_date.year = stampP->year;
2116 l_con->odbc_date.month = stampP->month;
2117 l_con->odbc_date.day = stampP->day;
2118 l_con->odbc_date.hour = stampP->hour;
2119 l_con->odbc_date.minute = stampP->minute;
2120 l_con->odbc_date.second = stampP->second;
2121 return 1;
2122 }
2123 /* if (data_type == SQL_C_TIME) { */
2124 if (data_type == SQL_C_TYPE_TIME) {
2125 timeP = (TIME_STRUCT *)(GetDbColPtr(dbp, i));
2126 l_con->odbc_date.year = 1991;
2127 l_con->odbc_date.month = 1;
2128 l_con->odbc_date.day = 1;
2129 l_con->odbc_date.hour = timeP->hour;
2130 l_con->odbc_date.minute = timeP->minute;
2131 l_con->odbc_date.second = timeP->second;
2132 return 1;
2133 }
2134
2135 }
2136 ATSTXTCAT(l_con->error_message, "\nError DATE type in odbc_get_date_data. ");
2137 if (l_con->error_number) {
2138 return 0;
2139 }
2140 else {
2141 l_con->error_number = -DB_ERROR-5;
2142 return 0;
2143 }
2144 }
2145
2146 int odbc_get_decimal (void *con, int no_des, int index, void *p)
2147 {
2148 int i = index - 1;
2149 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
2150 ODBCSQLDA * dbp = l_con->odbc_descriptor[no_des];
2151 int data_type;
2152
2153 data_type = GetDbCType(dbp, i);
2154 if (data_type == SQL_C_NUMERIC) {
2155 memcpy((char *)p, GetDbColPtr(dbp, i), sizeof (SQL_NUMERIC_STRUCT));
2156 return 1;
2157 }
2158
2159 ATSTXTCAT(l_con->error_message, "\nError DECIMAL type in odbc_get_decimal. ");
2160 if (l_con->error_number) {
2161 return 0;
2162 }
2163 else {
2164 l_con->error_number = -DB_ERROR-5;
2165 return 0;
2166 }
2167 }
2168
2169 int odbc_get_year(void *con)
2170 {
2171 return ((CON_CONTEXT *)con)->odbc_date.year;
2172 }
2173
2174 int odbc_get_month(void *con)
2175 {
2176 return ((CON_CONTEXT *)con)->odbc_date.month;
2177 }
2178
2179 int odbc_get_day(void *con)
2180 {
2181 return ((CON_CONTEXT *)con)->odbc_date.day;
2182 }
2183
2184 int odbc_get_hour(void *con)
2185 {
2186 return ((CON_CONTEXT *)con)->odbc_date.hour;
2187 }
2188
2189 int odbc_get_min(void *con)
2190 {
2191 return ((CON_CONTEXT *)con)->odbc_date.minute;
2192 }
2193
2194 int odbc_get_sec(void *con)
2195 {
2196 return ((CON_CONTEXT *)con)->odbc_date.second;
2197 }
2198
2199 size_t odbc_str_len(SQLTCHAR *val) {
2200 return TXTLEN(val);
2201 }
2202
2203 /*****************************************************************/
2204 /* The following functions are related with the error processing*/
2205 /*****************************************************************/
2206
2207 int odbc_get_error_code (void *con)
2208 {
2209 return ((CON_CONTEXT *)con)->error_number;
2210 }
2211
2212 SQLTCHAR * odbc_get_error_message (void *con)
2213 {
2214 return ((CON_CONTEXT *)con)->error_message;
2215 }
2216
2217 SQLTCHAR * odbc_get_warn_message (void *con)
2218 {
2219 return ((CON_CONTEXT *)con)->warn_message;
2220 }
2221
2222 void odbc_clear_error (void *con)
2223 {
2224 CON_CONTEXT *l_con = (CON_CONTEXT *)con;
2225 l_con->error_number = 0;
2226 l_con->error_message[0] = (SQLTCHAR)0;
2227 l_con->warn_message[0] = (SQLTCHAR)0;
2228 }
2229
2230 void odbc_error_handler(CON_CONTEXT *con, HSTMT h_err_stmt, int code) {
2231 SQLINTEGER nErr;
2232 SQLTCHAR msg[MAX_ERROR_MSG +1];
2233 SQLTCHAR tmpMsg[2 * MAX_ERROR_MSG];
2234 SQLSMALLINT cbMsg;
2235 SQLTCHAR tmpSQLSTATE[6];
2236 SQLSMALLINT msg_number;
2237 CON_CONTEXT *l_con = con;
2238 char charBuf[255];
2239
2240 if (h_err_stmt == NULL) {
2241 l_con->error_number = DB_ERROR;
2242 sprintf(charBuf, "ODBC ERROR: <%d>, Inter code: <%d>\n", l_con->error_number, code);
2243 ATSTXTCPY(msg, charBuf);
2244 SQLTXTCPY(l_con->error_message, msg);
2245
2246 if (code == 12) {
2247 ATSTXTCAT(l_con->error_message, "\n Can't Connect to the assigned Data Source!");
2248 ATSTXTCAT(l_con->error_message, "\n The name may be misspelled or \n The data source is being used by someone else exclusively!");
2249 }
2250 return ;
2251 }
2252
2253 switch(l_con->rc) {
2254 case SQL_INVALID_HANDLE:
2255 l_con->error_number = DB_SQL_INVALID_HANDLE;
2256 sprintf(charBuf, "ODBC ERROR: <%d>, Inter code: <%d>", l_con->error_number, code);
2257 ATSTXTCPY(msg, charBuf);
2258 SQLTXTCAT(l_con->error_message, msg);
2259 ATSTXTCAT(l_con->error_message, "\n An Application programming error occurred: maybe passed ");
2260 ATSTXTCAT(l_con->error_message, "\n invalid environment, connection or statement handle to ");
2261 ATSTXTCAT(l_con->error_message, "\n Driver Manager of ODBC. \n");
2262
2263 break;
2264 case SQL_ERROR:
2265 l_con->error_number = DB_SQL_ERROR;
2266 sprintf(charBuf, "ODBC ERROR: <%d>, Inter code: <%d>", l_con->error_number, code);
2267 ATSTXTCPY(msg, charBuf);
2268 SQLTXTCAT(l_con->error_message, msg);
2269 msg_number = 1;
2270 while (SQLGetDiagRec(SQL_HANDLE_STMT, h_err_stmt, msg_number++, tmpSQLSTATE, &nErr, msg, sizeof(msg), &cbMsg) != SQL_NO_DATA) {
2271 sprintf (charBuf, "\n Native Err#=%d , SQLSTATE=", (int) nErr);
2272 ATSTXTCPY (tmpMsg, charBuf);
2273 SQLTXTCAT (tmpMsg, tmpSQLSTATE);
2274 ATSTXTCAT (tmpMsg, ", Error_Info='");
2275 SQLTXTCAT (tmpMsg, msg);
2276 ATSTXTCAT (tmpMsg, "'");
2277
2278 if (TXTLEN(l_con->error_message) + TXTLEN(tmpMsg) + 8 > ERROR_MESSAGE_SIZE) {
2279 if (TXTLEN(l_con->error_message) + 8 <= ERROR_MESSAGE_SIZE) {
2280 ATSTXTCAT(l_con->error_message, "......");
2281 }
2282 }
2283 else {
2284 SQLTXTCAT(l_con->error_message, tmpMsg);
2285 }
2286 }
2287 ATSTXTCAT(l_con->error_message, "\n");
2288 break;
2289 case SQL_SUCCESS_WITH_INFO:
2290 sprintf (charBuf, "\nODBC WARNING Inter code: <%d>", code);
2291 ATSTXTCPY (msg, charBuf);
2292 SQLTXTCAT(l_con->warn_message, msg);
2293 msg_number = 1;
2294 while (SQLGetDiagRec(SQL_HANDLE_STMT, h_err_stmt, msg_number++, tmpSQLSTATE, &nErr, msg, sizeof(msg), &cbMsg) != SQL_NO_DATA) {
2295 sprintf (charBuf, "\n Native Err#=%d , SQLSTATE=", (int) nErr);
2296 ATSTXTCPY (tmpMsg, charBuf);
2297 SQLTXTCAT (tmpMsg, tmpSQLSTATE);
2298 ATSTXTCAT (tmpMsg, ", Error_Info='");
2299 SQLTXTCAT (tmpMsg, msg);
2300 ATSTXTCAT (tmpMsg, "'");
2301
2302 if (TXTLEN(l_con->warn_message) + TXTLEN(tmpMsg) + 8 > WARN_MESSAGE_SIZE) {
2303 if (TXTLEN(l_con->warn_message) + 8 <= WARN_MESSAGE_SIZE) {
2304 ATSTXTCAT(l_con->warn_message, "......");
2305 }
2306 }
2307 else {
2308 SQLTXTCAT(l_con->warn_message, tmpMsg);
2309 }
2310 }
2311 ATSTXTCAT(l_con->warn_message,"\n");
2312 break;
2313 default:
2314 sprintf (charBuf, "\nODBC WARNING Inter code: <%d>", code);
2315 ATSTXTCPY (msg, charBuf);
2316 SQLTXTCAT(l_con->warn_message, msg);
2317 break;
2318 }
2319 }
2320
2321 /* make a copy of a string */
2322 SQLTCHAR *odbc_str_from_str(SQLTCHAR *ptr) {
2323 SQLTCHAR *val;
2324 ODBC_SAFE_ALLOC(val, (SQLTCHAR *) malloc(TXTLEN(ptr) + sizeof (SQLTCHAR)));
2325 SQLTXTCPY(val, ptr);
2326 return val;
2327 }
2328
2329 SQLSMALLINT odbc_c_type(SQLSMALLINT odbc_type) {
2330 switch(odbc_type) {
2331 case SQL_CHAR:
2332 case SQL_VARCHAR:
2333 case SQL_LONGVARCHAR:
2334 case SQL_SS_XML:
2335 return SQL_C_CHAR;
2336 case SQL_WCHAR:
2337 case SQL_WVARCHAR:
2338 case SQL_WLONGVARCHAR:
2339 return SQL_C_WCHAR;
2340 /* case SQL_DATE: */
2341 case SQL_TYPE_DATE:
2342 /* return SQL_C_DATE; */
2343 return SQL_C_TYPE_DATE;
2344 /* case SQL_TIME: */
2345 case SQL_TYPE_TIME:
2346 /* return SQL_C_TIME; */
2347 return SQL_C_TYPE_TIME;
2348 /* case SQL_TIMESTAMP:*/
2349 case SQL_TYPE_TIMESTAMP:
2350 /* return SQL_C_TIMESTAMP; */
2351 return SQL_C_TYPE_TIMESTAMP;
2352 case SQL_BIT:
2353 return SQL_C_BIT;
2354 case SQL_TINYINT:
2355 return SQL_C_STINYINT;
2356 case SQL_SMALLINT:
2357 return SQL_C_SSHORT;
2358 case SQL_INTEGER:
2359 return SQL_C_SLONG;
2360 case SQL_BIGINT:
2361 return SQL_C_SBIGINT;
2362 case SQL_REAL:
2363 return SQL_C_FLOAT;
2364 case SQL_DOUBLE:
2365 case SQL_FLOAT:
2366 return SQL_C_DOUBLE;
2367 case SQL_DECIMAL:
2368 case SQL_NUMERIC:
2369 return SQL_C_NUMERIC;
2370 case SQL_BINARY:
2371 case SQL_VARBINARY:
2372 case SQL_LONGVARBINARY:
2373 return SQL_C_BINARY;
2374 case SQL_GUID:
2375 return SQL_C_GUID;
2376 default:
2377 return SQL_C_DEFAULT;
2378 }
2379 }
2380
2381 rt_private void change_to_low (SQLTCHAR *buf, size_t length) {
2382 /* Do not care about non-ASCII characters. */
2383 size_t i = length;
2384 for (i = length; i >= 0 && i <= length; i--)
2385 buf[i] = (buf[i] > 0xFF) ? buf[i] : (SQLTCHAR) tolower(buf[i]);
2386 }
2387
2388 size_t sqlstrlen(const SQLTCHAR *str)
2389 {
2390 int i;
2391 for (i=0; str[i]!=(SQLTCHAR)0; i++){};
2392 return (size_t)i;
2393 }
2394
2395 /* Copy ASCII chars from strSource into wide strDestination, starting from `pos' of strDestination. */
2396 /* Note: `pos' must be valid to strDestination */
2397 rt_private SQLTCHAR *sqlstrcpy(SQLTCHAR *strDestination, int pos, const char *strSource)
2398 {
2399 int i;
2400 for (i=0;strSource[i]!=(char)0;i++)
2401 {
2402 strDestination[i+pos] = (SQLTCHAR)strSource[i];
2403 }
2404 strDestination[i+pos] = (SQLTCHAR)0;
2405 return strDestination;
2406 }
2407
2408 /* Find name paranthesed in `sqlStat', copy the name into `buf' */
2409 /* Return: non-zero if found */
2410 rt_private int find_name (SQLTCHAR *buf, SQLTCHAR * sqlStat)
2411 {
2412 int i, j;
2413 for (i=COMPARED_LENGTH; sqlStat[i] != TXTC('(') && sqlStat[i] != (SQLTCHAR)0; i++);
2414 if (sqlStat[i] == TXTC('('))
2415 i++;
2416 j = i;
2417 for (; sqlStat[i] != TXTC('\'') && sqlStat[i] != (SQLTCHAR)0; i++);
2418 if (sqlStat[i] == (SQLTCHAR)0)
2419 i = j;
2420 else
2421 i++;
2422 for (j=0; sqlStat[i] != TXTC(')') && sqlStat[i] != (SQLTCHAR)0 && sqlStat[i] != TXTC('\''); i++, j++) {
2423 buf[j] = sqlStat[i];
2424 }
2425 buf[j] = (SQLTCHAR)0;
2426 return j;
2427 }
2428
2429 EIF_NATURAL_64 strhextoval(SQL_NUMERIC_STRUCT *NumStr)
2430 {
2431 EIF_NATURAL_64 val,value,last,current,a,b;
2432 int i=1;
2433
2434 val=0;value=0;last=1;a=0;b=0;
2435
2436 for(i=0;i<=15;i++){
2437 current = (EIF_NATURAL_64) NumStr->val[i];
2438 a= current % 16; /* Obtain LSD */
2439 b= current / 16; /* Obtain MSD */
2440
2441 value += last* a;
2442 last = last * 16;
2443 value += last* b;
2444 last = last * 16;
2445 }
2446 return value;
2447 }

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.23