lemon-project-template-glpk
comparison deps/glpk/src/glpsql.c @ 9:33de93886c88
Import GLPK 4.47
author | Alpar Juttner <alpar@cs.elte.hu> |
---|---|
date | Sun, 06 Nov 2011 20:59:10 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1caf1621ff6f |
---|---|
1 /* glpsql.c */ | |
2 | |
3 /*********************************************************************** | |
4 * This code is part of GLPK (GNU Linear Programming Kit). | |
5 * | |
6 * Author: Heinrich Schuchardt <xypron.glpk@gmx.de>. | |
7 * | |
8 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, | |
9 * 2009, 2010 Andrew Makhorin, Department for Applied Informatics, | |
10 * Moscow Aviation Institute, Moscow, Russia. All rights reserved. | |
11 * E-mail: <mao@gnu.org>. | |
12 * | |
13 * GLPK is free software: you can redistribute it and/or modify it | |
14 * under the terms of the GNU General Public License as published by | |
15 * the Free Software Foundation, either version 3 of the License, or | |
16 * (at your option) any later version. | |
17 * | |
18 * GLPK is distributed in the hope that it will be useful, but WITHOUT | |
19 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
21 * License for more details. | |
22 * | |
23 * You should have received a copy of the GNU General Public License | |
24 * along with GLPK. If not, see <http://www.gnu.org/licenses/>. | |
25 ***********************************************************************/ | |
26 | |
27 #ifdef HAVE_CONFIG_H | |
28 #include <config.h> | |
29 #endif | |
30 | |
31 #include "glpmpl.h" | |
32 #include "glpsql.h" | |
33 | |
34 #ifdef ODBC_DLNAME | |
35 #define HAVE_ODBC | |
36 #define libodbc ODBC_DLNAME | |
37 #define h_odbc (get_env_ptr()->h_odbc) | |
38 #endif | |
39 | |
40 #ifdef MYSQL_DLNAME | |
41 #define HAVE_MYSQL | |
42 #define libmysql MYSQL_DLNAME | |
43 #define h_mysql (get_env_ptr()->h_mysql) | |
44 #endif | |
45 | |
46 static void *db_iodbc_open_int(TABDCA *dca, int mode, const char | |
47 **sqllines); | |
48 static void *db_mysql_open_int(TABDCA *dca, int mode, const char | |
49 **sqllines); | |
50 | |
51 /**********************************************************************/ | |
52 | |
53 #if defined(HAVE_ODBC) || defined(HAVE_MYSQL) | |
54 | |
55 #define SQL_FIELD_MAX 100 | |
56 /* maximal field count */ | |
57 | |
58 #define SQL_FDLEN_MAX 255 | |
59 /* maximal field length */ | |
60 | |
61 /*********************************************************************** | |
62 * NAME | |
63 * | |
64 * args_concat - concatenate arguments | |
65 * | |
66 * SYNOPSIS | |
67 * | |
68 * static char **args_concat(TABDCA *dca); | |
69 * | |
70 * DESCRIPTION | |
71 * | |
72 * The arguments passed in dca are SQL statements. A SQL statement may | |
73 * be split over multiple arguments. The last argument of a SQL | |
74 * statement will be terminated with a semilocon. Each SQL statement is | |
75 * merged into a single zero terminated string. Boundaries between | |
76 * arguments are replaced by space. | |
77 * | |
78 * RETURNS | |
79 * | |
80 * Buffer with SQL statements */ | |
81 | |
82 static char **args_concat(TABDCA *dca) | |
83 { | |
84 const char *arg; | |
85 int i; | |
86 int j; | |
87 int j0; | |
88 int j1; | |
89 int len; | |
90 int lentot; | |
91 int narg; | |
92 int nline = 0; | |
93 void *ret; | |
94 char **sqllines = NULL; | |
95 | |
96 narg = mpl_tab_num_args(dca); | |
97 /* The SQL statements start with argument 3. */ | |
98 if (narg < 3) | |
99 return NULL; | |
100 /* Count the SQL statements */ | |
101 for (j = 3; j <= narg; j++) | |
102 { | |
103 arg = mpl_tab_get_arg(dca, j); | |
104 len = strlen(arg); | |
105 if (arg[len-1] == ';' || j == narg) | |
106 nline ++; | |
107 } | |
108 /* Allocate string buffer. */ | |
109 sqllines = (char **) xmalloc((nline+1) * sizeof(char **)); | |
110 /* Join arguments */ | |
111 sqllines[0] = NULL; | |
112 j0 = 3; | |
113 i = 0; | |
114 lentot = 0; | |
115 for (j = 3; j <= narg; j++) | |
116 { | |
117 arg = mpl_tab_get_arg(dca, j); | |
118 len = strlen(arg); | |
119 /* add length of part */ | |
120 lentot += len; | |
121 /* add length of space separating parts or 0x00 at end of SQL | |
122 statement */ | |
123 lentot++; | |
124 if (arg[len-1] == ';' || j == narg) | |
125 { /* Join arguments for a single SQL statement */ | |
126 sqllines[i] = xmalloc(lentot); | |
127 sqllines[i+1] = NULL; | |
128 sqllines[i][0] = 0x00; | |
129 for (j1 = j0; j1 <= j; j1++) | |
130 { if(j1>j0) | |
131 strcat(sqllines[i], " "); | |
132 strcat(sqllines[i], mpl_tab_get_arg(dca, j1)); | |
133 } | |
134 len = strlen(sqllines[i]); | |
135 if (sqllines[i][len-1] == ';') | |
136 sqllines[i][len-1] = 0x00; | |
137 j0 = j+1; | |
138 i++; | |
139 lentot = 0; | |
140 } | |
141 } | |
142 return sqllines; | |
143 } | |
144 | |
145 /*********************************************************************** | |
146 * NAME | |
147 * | |
148 * free_buffer - free multiline string buffer | |
149 * | |
150 * SYNOPSIS | |
151 * | |
152 * static void free_buffer(char **buf); | |
153 * | |
154 * DESCRIPTION | |
155 * | |
156 * buf is a list of strings terminated by NULL. | |
157 * The memory for the strings and for the list is released. */ | |
158 | |
159 static void free_buffer(char **buf) | |
160 { int i; | |
161 | |
162 for(i = 0; buf[i] != NULL; i++) | |
163 xfree(buf[i]); | |
164 xfree(buf); | |
165 } | |
166 | |
167 static int db_escaped_string_length(const char* from) | |
168 /* length of escaped string */ | |
169 { | |
170 int count; | |
171 const char *pointer; | |
172 | |
173 for (pointer = from, count = 0; *pointer != (char) '\0'; pointer++, | |
174 count++) | |
175 { | |
176 switch (*pointer) | |
177 { | |
178 case '\'': | |
179 count++; | |
180 break; | |
181 } | |
182 } | |
183 | |
184 return count; | |
185 } | |
186 | |
187 static int db_escape_string (char *to, const char *from) | |
188 /* escape string*/ | |
189 { | |
190 const char *source = from; | |
191 char *target = to; | |
192 unsigned int remaining; | |
193 | |
194 remaining = strlen(from); | |
195 | |
196 if (to == NULL) | |
197 to = (char *) (from + remaining); | |
198 | |
199 while (remaining > 0) | |
200 { | |
201 switch (*source) | |
202 { | |
203 case '\'': | |
204 *target = '\''; | |
205 target++; | |
206 *target = '\''; | |
207 break; | |
208 | |
209 default: | |
210 *target = *source; | |
211 } | |
212 source++; | |
213 target++; | |
214 remaining--; | |
215 } | |
216 | |
217 /* Write the terminating NUL character. */ | |
218 *target = '\0'; | |
219 | |
220 return target - to; | |
221 } | |
222 | |
223 static char *db_generate_select_stmt(TABDCA *dca) | |
224 /* generate select statement */ | |
225 { | |
226 char *arg; | |
227 char const *field; | |
228 char *query; | |
229 int j; | |
230 int narg; | |
231 int nf; | |
232 int total; | |
233 | |
234 total = 50; | |
235 nf = mpl_tab_num_flds(dca); | |
236 narg = mpl_tab_num_args(dca); | |
237 for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) | |
238 { | |
239 field = mpl_tab_get_name(dca, j); | |
240 total += strlen(field); | |
241 total += 2; | |
242 } | |
243 arg = (char *) mpl_tab_get_arg(dca, narg); | |
244 total += strlen(arg); | |
245 query = xmalloc( total * sizeof(char)); | |
246 strcpy (query, "SELECT "); | |
247 for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) | |
248 { | |
249 field = mpl_tab_get_name(dca, j); | |
250 strcat(query, field); | |
251 if ( j < nf ) | |
252 strcat(query, ", "); | |
253 } | |
254 strcat(query, " FROM "); | |
255 strcat(query, arg); | |
256 return query; | |
257 } | |
258 | |
259 static char *db_generate_insert_stmt(TABDCA *dca) | |
260 /* generate insert statement */ | |
261 { | |
262 char *arg; | |
263 char const *field; | |
264 char *query; | |
265 int j; | |
266 int narg; | |
267 int nf; | |
268 int total; | |
269 | |
270 total = 50; | |
271 nf = mpl_tab_num_flds(dca); | |
272 narg = mpl_tab_num_args(dca); | |
273 for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) | |
274 { | |
275 field = mpl_tab_get_name(dca, j); | |
276 total += strlen(field); | |
277 total += 5; | |
278 } | |
279 arg = (char *) mpl_tab_get_arg(dca, narg); | |
280 total += strlen(arg); | |
281 query = xmalloc( (total+1) * sizeof(char)); | |
282 strcpy (query, "INSERT INTO "); | |
283 strcat(query, arg); | |
284 strcat(query, " ( "); | |
285 for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) | |
286 { | |
287 field = mpl_tab_get_name(dca, j); | |
288 strcat(query, field); | |
289 if ( j < nf ) | |
290 strcat(query, ", "); | |
291 } | |
292 strcat(query, " ) VALUES ( "); | |
293 for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) | |
294 { | |
295 strcat(query, "?"); | |
296 if ( j < nf ) | |
297 strcat(query, ", "); | |
298 } | |
299 strcat(query, " )"); | |
300 return query; | |
301 } | |
302 | |
303 #endif | |
304 | |
305 /**********************************************************************/ | |
306 | |
307 #ifndef HAVE_ODBC | |
308 | |
309 void *db_iodbc_open(TABDCA *dca, int mode) | |
310 { xassert(dca == dca); | |
311 xassert(mode == mode); | |
312 xprintf("iODBC table driver not supported\n"); | |
313 return NULL; | |
314 } | |
315 | |
316 int db_iodbc_read(TABDCA *dca, void *link) | |
317 { xassert(dca != dca); | |
318 xassert(link != link); | |
319 return 0; | |
320 } | |
321 | |
322 int db_iodbc_write(TABDCA *dca, void *link) | |
323 { xassert(dca != dca); | |
324 xassert(link != link); | |
325 return 0; | |
326 } | |
327 | |
328 int db_iodbc_close(TABDCA *dca, void *link) | |
329 { xassert(dca != dca); | |
330 xassert(link != link); | |
331 return 0; | |
332 } | |
333 | |
334 #else | |
335 | |
336 #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__) | |
337 #include <windows.h> | |
338 #endif | |
339 | |
340 #include <sql.h> | |
341 #include <sqlext.h> | |
342 | |
343 struct db_odbc | |
344 { | |
345 int mode; /*'R' = Read, 'W' = Write*/ | |
346 SQLHDBC hdbc; /*connection handle*/ | |
347 SQLHENV henv; /*environment handle*/ | |
348 SQLHSTMT hstmt; /*statement handle*/ | |
349 SQLSMALLINT nresultcols; /* columns in result*/ | |
350 SQLULEN collen[SQL_FIELD_MAX+1]; | |
351 SQLLEN outlen[SQL_FIELD_MAX+1]; | |
352 SQLSMALLINT coltype[SQL_FIELD_MAX+1]; | |
353 SQLCHAR data[SQL_FIELD_MAX+1][SQL_FDLEN_MAX+1]; | |
354 SQLCHAR colname[SQL_FIELD_MAX+1][SQL_FDLEN_MAX+1]; | |
355 int isnumeric[SQL_FIELD_MAX+1]; | |
356 int nf; | |
357 /* number of fields in the csv file */ | |
358 int ref[1+SQL_FIELD_MAX]; | |
359 /* ref[k] = k', if k-th field of the csv file corresponds to | |
360 k'-th field in the table statement; if ref[k] = 0, k-th field | |
361 of the csv file is ignored */ | |
362 SQLCHAR *query; | |
363 /* query generated by db_iodbc_open */ | |
364 }; | |
365 | |
366 SQLRETURN SQL_API dl_SQLAllocHandle ( | |
367 SQLSMALLINT HandleType, | |
368 SQLHANDLE InputHandle, | |
369 SQLHANDLE *OutputHandle) | |
370 { | |
371 typedef SQLRETURN SQL_API ep_SQLAllocHandle( | |
372 SQLSMALLINT HandleType, | |
373 SQLHANDLE InputHandle, | |
374 SQLHANDLE *OutputHandle); | |
375 | |
376 ep_SQLAllocHandle *fn; | |
377 fn = (ep_SQLAllocHandle *) xdlsym(h_odbc, "SQLAllocHandle"); | |
378 xassert(fn != NULL); | |
379 return (*fn)(HandleType, InputHandle, OutputHandle); | |
380 } | |
381 | |
382 SQLRETURN SQL_API dl_SQLBindCol ( | |
383 SQLHSTMT StatementHandle, | |
384 SQLUSMALLINT ColumnNumber, | |
385 SQLSMALLINT TargetType, | |
386 SQLPOINTER TargetValue, | |
387 SQLLEN BufferLength, | |
388 SQLLEN *StrLen_or_Ind) | |
389 { | |
390 typedef SQLRETURN SQL_API ep_SQLBindCol( | |
391 SQLHSTMT StatementHandle, | |
392 SQLUSMALLINT ColumnNumber, | |
393 SQLSMALLINT TargetType, | |
394 SQLPOINTER TargetValue, | |
395 SQLLEN BufferLength, | |
396 SQLLEN *StrLen_or_Ind); | |
397 ep_SQLBindCol *fn; | |
398 fn = (ep_SQLBindCol *) xdlsym(h_odbc, "SQLBindCol"); | |
399 xassert(fn != NULL); | |
400 return (*fn)(StatementHandle, ColumnNumber, TargetType, | |
401 TargetValue, BufferLength, StrLen_or_Ind); | |
402 } | |
403 | |
404 SQLRETURN SQL_API dl_SQLCloseCursor ( | |
405 SQLHSTMT StatementHandle) | |
406 { | |
407 typedef SQLRETURN SQL_API ep_SQLCloseCursor ( | |
408 SQLHSTMT StatementHandle); | |
409 | |
410 ep_SQLCloseCursor *fn; | |
411 fn = (ep_SQLCloseCursor *) xdlsym(h_odbc, "SQLCloseCursor"); | |
412 xassert(fn != NULL); | |
413 return (*fn)(StatementHandle); | |
414 } | |
415 | |
416 | |
417 SQLRETURN SQL_API dl_SQLDisconnect ( | |
418 SQLHDBC ConnectionHandle) | |
419 { | |
420 typedef SQLRETURN SQL_API ep_SQLDisconnect( | |
421 SQLHDBC ConnectionHandle); | |
422 | |
423 ep_SQLDisconnect *fn; | |
424 fn = (ep_SQLDisconnect *) xdlsym(h_odbc, "SQLDisconnect"); | |
425 xassert(fn != NULL); | |
426 return (*fn)(ConnectionHandle); | |
427 } | |
428 | |
429 SQLRETURN SQL_API dl_SQLDriverConnect ( | |
430 SQLHDBC hdbc, | |
431 SQLHWND hwnd, | |
432 SQLCHAR *szConnStrIn, | |
433 SQLSMALLINT cbConnStrIn, | |
434 SQLCHAR *szConnStrOut, | |
435 SQLSMALLINT cbConnStrOutMax, | |
436 SQLSMALLINT *pcbConnStrOut, | |
437 SQLUSMALLINT fDriverCompletion) | |
438 { | |
439 typedef SQLRETURN SQL_API ep_SQLDriverConnect( | |
440 SQLHDBC hdbc, | |
441 SQLHWND hwnd, | |
442 SQLCHAR * szConnStrIn, | |
443 SQLSMALLINT cbConnStrIn, | |
444 SQLCHAR * szConnStrOut, | |
445 SQLSMALLINT cbConnStrOutMax, | |
446 SQLSMALLINT * pcbConnStrOut, | |
447 SQLUSMALLINT fDriverCompletion); | |
448 | |
449 ep_SQLDriverConnect *fn; | |
450 fn = (ep_SQLDriverConnect *) xdlsym(h_odbc, "SQLDriverConnect"); | |
451 xassert(fn != NULL); | |
452 return (*fn)(hdbc, hwnd, szConnStrIn, cbConnStrIn, szConnStrOut, | |
453 cbConnStrOutMax, pcbConnStrOut, fDriverCompletion); | |
454 } | |
455 | |
456 SQLRETURN SQL_API dl_SQLEndTran ( | |
457 SQLSMALLINT HandleType, | |
458 SQLHANDLE Handle, | |
459 SQLSMALLINT CompletionType) | |
460 { | |
461 typedef SQLRETURN SQL_API ep_SQLEndTran ( | |
462 SQLSMALLINT HandleType, | |
463 SQLHANDLE Handle, | |
464 SQLSMALLINT CompletionType); | |
465 | |
466 ep_SQLEndTran *fn; | |
467 fn = (ep_SQLEndTran *) xdlsym(h_odbc, "SQLEndTran"); | |
468 xassert(fn != NULL); | |
469 return (*fn)(HandleType, Handle, CompletionType); | |
470 } | |
471 | |
472 SQLRETURN SQL_API dl_SQLExecDirect ( | |
473 SQLHSTMT StatementHandle, | |
474 SQLCHAR * StatementText, | |
475 SQLINTEGER TextLength) | |
476 { | |
477 typedef SQLRETURN SQL_API ep_SQLExecDirect ( | |
478 SQLHSTMT StatementHandle, | |
479 SQLCHAR * StatementText, | |
480 SQLINTEGER TextLength); | |
481 | |
482 ep_SQLExecDirect *fn; | |
483 fn = (ep_SQLExecDirect *) xdlsym(h_odbc, "SQLExecDirect"); | |
484 xassert(fn != NULL); | |
485 return (*fn)(StatementHandle, StatementText, TextLength); | |
486 } | |
487 | |
488 SQLRETURN SQL_API dl_SQLFetch ( | |
489 SQLHSTMT StatementHandle) | |
490 { | |
491 typedef SQLRETURN SQL_API ep_SQLFetch ( | |
492 SQLHSTMT StatementHandle); | |
493 | |
494 ep_SQLFetch *fn; | |
495 fn = (ep_SQLFetch*) xdlsym(h_odbc, "SQLFetch"); | |
496 xassert(fn != NULL); | |
497 return (*fn)(StatementHandle); | |
498 } | |
499 | |
500 SQLRETURN SQL_API dl_SQLFreeHandle ( | |
501 SQLSMALLINT HandleType, | |
502 SQLHANDLE Handle) | |
503 { | |
504 typedef SQLRETURN SQL_API ep_SQLFreeHandle ( | |
505 SQLSMALLINT HandleType, | |
506 SQLHANDLE Handle); | |
507 | |
508 ep_SQLFreeHandle *fn; | |
509 fn = (ep_SQLFreeHandle *) xdlsym(h_odbc, "SQLFreeHandle"); | |
510 xassert(fn != NULL); | |
511 return (*fn)(HandleType, Handle); | |
512 } | |
513 | |
514 SQLRETURN SQL_API dl_SQLDescribeCol ( | |
515 SQLHSTMT StatementHandle, | |
516 SQLUSMALLINT ColumnNumber, | |
517 SQLCHAR * ColumnName, | |
518 SQLSMALLINT BufferLength, | |
519 SQLSMALLINT * NameLength, | |
520 SQLSMALLINT * DataType, | |
521 SQLULEN * ColumnSize, | |
522 SQLSMALLINT * DecimalDigits, | |
523 SQLSMALLINT * Nullable) | |
524 { | |
525 typedef SQLRETURN SQL_API ep_SQLDescribeCol ( | |
526 SQLHSTMT StatementHandle, | |
527 SQLUSMALLINT ColumnNumber, | |
528 SQLCHAR *ColumnName, | |
529 SQLSMALLINT BufferLength, | |
530 SQLSMALLINT *NameLength, | |
531 SQLSMALLINT *DataType, | |
532 SQLULEN *ColumnSize, | |
533 SQLSMALLINT *DecimalDigits, | |
534 SQLSMALLINT *Nullable); | |
535 | |
536 ep_SQLDescribeCol *fn; | |
537 fn = (ep_SQLDescribeCol *) xdlsym(h_odbc, "SQLDescribeCol"); | |
538 xassert(fn != NULL); | |
539 return (*fn)(StatementHandle, ColumnNumber, ColumnName, | |
540 BufferLength, NameLength, | |
541 DataType, ColumnSize, DecimalDigits, Nullable); | |
542 } | |
543 | |
544 SQLRETURN SQL_API dl_SQLGetDiagRec ( | |
545 SQLSMALLINT HandleType, | |
546 SQLHANDLE Handle, | |
547 SQLSMALLINT RecNumber, | |
548 SQLCHAR *Sqlstate, | |
549 SQLINTEGER *NativeError, | |
550 SQLCHAR *MessageText, | |
551 SQLSMALLINT BufferLength, | |
552 SQLSMALLINT *TextLength) | |
553 { | |
554 typedef SQLRETURN SQL_API ep_SQLGetDiagRec ( | |
555 SQLSMALLINT HandleType, | |
556 SQLHANDLE Handle, | |
557 SQLSMALLINT RecNumber, | |
558 SQLCHAR *Sqlstate, | |
559 SQLINTEGER *NativeError, | |
560 SQLCHAR *MessageText, | |
561 SQLSMALLINT BufferLength, | |
562 SQLSMALLINT *TextLength); | |
563 | |
564 ep_SQLGetDiagRec *fn; | |
565 fn = (ep_SQLGetDiagRec *) xdlsym(h_odbc, "SQLGetDiagRec"); | |
566 xassert(fn != NULL); | |
567 return (*fn)(HandleType, Handle, RecNumber, Sqlstate, | |
568 NativeError, MessageText, BufferLength, TextLength); | |
569 } | |
570 | |
571 SQLRETURN SQL_API dl_SQLGetInfo ( | |
572 SQLHDBC ConnectionHandle, | |
573 SQLUSMALLINT InfoType, | |
574 SQLPOINTER InfoValue, | |
575 SQLSMALLINT BufferLength, | |
576 SQLSMALLINT *StringLength) | |
577 { | |
578 typedef SQLRETURN SQL_API ep_SQLGetInfo ( | |
579 SQLHDBC ConnectionHandle, | |
580 SQLUSMALLINT InfoType, | |
581 SQLPOINTER InfoValue, | |
582 SQLSMALLINT BufferLength, | |
583 SQLSMALLINT *StringLength); | |
584 | |
585 ep_SQLGetInfo *fn; | |
586 fn = (ep_SQLGetInfo *) xdlsym(h_odbc, "SQLGetInfo"); | |
587 xassert(fn != NULL); | |
588 return (*fn)(ConnectionHandle, InfoType, InfoValue, BufferLength, | |
589 StringLength); | |
590 } | |
591 | |
592 SQLRETURN SQL_API dl_SQLNumResultCols ( | |
593 SQLHSTMT StatementHandle, | |
594 SQLSMALLINT *ColumnCount) | |
595 { | |
596 typedef SQLRETURN SQL_API ep_SQLNumResultCols ( | |
597 SQLHSTMT StatementHandle, | |
598 SQLSMALLINT *ColumnCount); | |
599 | |
600 ep_SQLNumResultCols *fn; | |
601 fn = (ep_SQLNumResultCols *) xdlsym(h_odbc, "SQLNumResultCols"); | |
602 xassert(fn != NULL); | |
603 return (*fn)(StatementHandle, ColumnCount); | |
604 } | |
605 | |
606 SQLRETURN SQL_API dl_SQLSetConnectAttr ( | |
607 SQLHDBC ConnectionHandle, | |
608 SQLINTEGER Attribute, | |
609 SQLPOINTER Value, | |
610 SQLINTEGER StringLength) | |
611 { | |
612 typedef SQLRETURN SQL_API ep_SQLSetConnectAttr ( | |
613 SQLHDBC ConnectionHandle, | |
614 SQLINTEGER Attribute, | |
615 SQLPOINTER Value, | |
616 SQLINTEGER StringLength); | |
617 | |
618 ep_SQLSetConnectAttr *fn; | |
619 fn = (ep_SQLSetConnectAttr *) xdlsym(h_odbc, "SQLSetConnectAttr"); | |
620 xassert(fn != NULL); | |
621 return (*fn)(ConnectionHandle, Attribute, Value, StringLength); | |
622 } | |
623 | |
624 SQLRETURN SQL_API dl_SQLSetEnvAttr ( | |
625 SQLHENV EnvironmentHandle, | |
626 SQLINTEGER Attribute, | |
627 SQLPOINTER Value, | |
628 SQLINTEGER StringLength) | |
629 { | |
630 typedef SQLRETURN SQL_API ep_SQLSetEnvAttr ( | |
631 SQLHENV EnvironmentHandle, | |
632 SQLINTEGER Attribute, | |
633 SQLPOINTER Value, | |
634 SQLINTEGER StringLength); | |
635 | |
636 ep_SQLSetEnvAttr *fn; | |
637 fn = (ep_SQLSetEnvAttr *) xdlsym(h_odbc, "SQLSetEnvAttr"); | |
638 xassert(fn != NULL); | |
639 return (*fn)(EnvironmentHandle, Attribute, Value, StringLength); | |
640 } | |
641 | |
642 static void extract_error( | |
643 char *fn, | |
644 SQLHANDLE handle, | |
645 SQLSMALLINT type); | |
646 | |
647 static int is_numeric( | |
648 SQLSMALLINT coltype); | |
649 | |
650 /*********************************************************************** | |
651 * NAME | |
652 * | |
653 * db_iodbc_open - open connection to ODBC data base | |
654 * | |
655 * SYNOPSIS | |
656 * | |
657 * #include "glpsql.h" | |
658 * void *db_iodbc_open(TABDCA *dca, int mode); | |
659 * | |
660 * DESCRIPTION | |
661 * | |
662 * The routine db_iodbc_open opens a connection to an ODBC data base. | |
663 * It then executes the sql statements passed. | |
664 * | |
665 * In the case of table read the SELECT statement is executed. | |
666 * | |
667 * In the case of table write the INSERT statement is prepared. | |
668 * RETURNS | |
669 * | |
670 * The routine returns a pointer to data storage area created. */ | |
671 void *db_iodbc_open(TABDCA *dca, int mode) | |
672 { void *ret; | |
673 char **sqllines; | |
674 | |
675 sqllines = args_concat(dca); | |
676 if (sqllines == NULL) | |
677 { xprintf("Missing arguments in table statement.\n" | |
678 "Please, supply table driver, dsn, and query.\n"); | |
679 return NULL; | |
680 } | |
681 ret = db_iodbc_open_int(dca, mode, (const char **) sqllines); | |
682 free_buffer(sqllines); | |
683 return ret; | |
684 } | |
685 | |
686 static void *db_iodbc_open_int(TABDCA *dca, int mode, const char | |
687 **sqllines) | |
688 { | |
689 struct db_odbc *sql; | |
690 SQLRETURN ret; | |
691 SQLCHAR FAR *dsn; | |
692 SQLCHAR info[256]; | |
693 SQLSMALLINT colnamelen; | |
694 SQLSMALLINT nullable; | |
695 SQLSMALLINT scale; | |
696 const char *arg; | |
697 int narg; | |
698 int i, j; | |
699 int total; | |
700 | |
701 if (libodbc == NULL) | |
702 { | |
703 xprintf("No loader for shared ODBC library available\n"); | |
704 return NULL; | |
705 } | |
706 | |
707 if (h_odbc == NULL) | |
708 { | |
709 h_odbc = xdlopen(libodbc); | |
710 if (h_odbc == NULL) | |
711 { xprintf("unable to open library %s\n", libodbc); | |
712 xprintf("%s\n", xerrmsg()); | |
713 return NULL; | |
714 } | |
715 } | |
716 | |
717 sql = (struct db_odbc *) xmalloc(sizeof(struct db_odbc)); | |
718 if (sql == NULL) | |
719 return NULL; | |
720 | |
721 sql->mode = mode; | |
722 sql->hdbc = NULL; | |
723 sql->henv = NULL; | |
724 sql->hstmt = NULL; | |
725 sql->query = NULL; | |
726 narg = mpl_tab_num_args(dca); | |
727 | |
728 dsn = (SQLCHAR FAR *) mpl_tab_get_arg(dca, 2); | |
729 /* allocate an environment handle */ | |
730 ret = dl_SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, | |
731 &(sql->henv)); | |
732 /* set attribute to enable application to run as ODBC 3.0 | |
733 application */ | |
734 ret = dl_SQLSetEnvAttr(sql->henv, SQL_ATTR_ODBC_VERSION, | |
735 (void *) SQL_OV_ODBC3, 0); | |
736 /* allocate a connection handle */ | |
737 ret = dl_SQLAllocHandle(SQL_HANDLE_DBC, sql->henv, &(sql->hdbc)); | |
738 /* connect */ | |
739 ret = dl_SQLDriverConnect(sql->hdbc, NULL, dsn, SQL_NTS, NULL, 0, | |
740 NULL, SQL_DRIVER_COMPLETE); | |
741 if (SQL_SUCCEEDED(ret)) | |
742 { /* output information about data base connection */ | |
743 xprintf("Connected to "); | |
744 dl_SQLGetInfo(sql->hdbc, SQL_DBMS_NAME, (SQLPOINTER)info, | |
745 sizeof(info), NULL); | |
746 xprintf("%s ", info); | |
747 dl_SQLGetInfo(sql->hdbc, SQL_DBMS_VER, (SQLPOINTER)info, | |
748 sizeof(info), NULL); | |
749 xprintf("%s - ", info); | |
750 dl_SQLGetInfo(sql->hdbc, SQL_DATABASE_NAME, (SQLPOINTER)info, | |
751 sizeof(info), NULL); | |
752 xprintf("%s\n", info); | |
753 } | |
754 else | |
755 { /* describe error */ | |
756 xprintf("Failed to connect\n"); | |
757 extract_error("SQLDriverConnect", sql->hdbc, SQL_HANDLE_DBC); | |
758 dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); | |
759 dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); | |
760 xfree(sql); | |
761 return NULL; | |
762 } | |
763 /* set AUTOCOMMIT on*/ | |
764 ret = dl_SQLSetConnectAttr(sql->hdbc, SQL_ATTR_AUTOCOMMIT, | |
765 (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0); | |
766 /* allocate a statement handle */ | |
767 ret = dl_SQLAllocHandle(SQL_HANDLE_STMT, sql->hdbc, &(sql->hstmt)); | |
768 | |
769 /* initialization queries */ | |
770 for(j = 0; sqllines[j+1] != NULL; j++) | |
771 { | |
772 sql->query = (SQLCHAR *) sqllines[j]; | |
773 xprintf("%s\n", sql->query); | |
774 ret = dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS); | |
775 switch (ret) | |
776 { | |
777 case SQL_SUCCESS: | |
778 case SQL_SUCCESS_WITH_INFO: | |
779 case SQL_NO_DATA_FOUND: | |
780 break; | |
781 default: | |
782 xprintf("db_iodbc_open: Query\n\"%s\"\nfailed.\n", | |
783 sql->query); | |
784 extract_error("SQLExecDirect", sql->hstmt, SQL_HANDLE_STMT); | |
785 dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); | |
786 dl_SQLDisconnect(sql->hdbc); | |
787 dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); | |
788 dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); | |
789 xfree(sql); | |
790 return NULL; | |
791 } | |
792 /* commit statement */ | |
793 dl_SQLEndTran(SQL_HANDLE_ENV, sql->henv, SQL_COMMIT); | |
794 } | |
795 | |
796 if ( sql->mode == 'R' ) | |
797 { sql->nf = mpl_tab_num_flds(dca); | |
798 for(j = 0; sqllines[j] != NULL; j++) | |
799 arg = sqllines[j]; | |
800 total = strlen(arg); | |
801 if (total > 7 && 0 == strncmp(arg, "SELECT ", 7)) | |
802 { | |
803 total = strlen(arg); | |
804 sql->query = xmalloc( (total+1) * sizeof(char)); | |
805 strcpy (sql->query, arg); | |
806 } | |
807 else | |
808 { | |
809 sql->query = db_generate_select_stmt(dca); | |
810 } | |
811 xprintf("%s\n", sql->query); | |
812 if (dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS) != | |
813 SQL_SUCCESS) | |
814 { | |
815 xprintf("db_iodbc_open: Query\n\"%s\"\nfailed.\n", sql->query); | |
816 extract_error("SQLExecDirect", sql->hstmt, SQL_HANDLE_STMT); | |
817 dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); | |
818 dl_SQLDisconnect(sql->hdbc); | |
819 dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); | |
820 dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); | |
821 xfree(sql->query); | |
822 xfree(sql); | |
823 return NULL; | |
824 } | |
825 xfree(sql->query); | |
826 /* determine number of result columns */ | |
827 ret = dl_SQLNumResultCols(sql->hstmt, &sql->nresultcols); | |
828 total = sql->nresultcols; | |
829 if (total > SQL_FIELD_MAX) | |
830 { xprintf("db_iodbc_open: Too many fields (> %d) in query.\n" | |
831 "\"%s\"\n", SQL_FIELD_MAX, sql->query); | |
832 dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); | |
833 dl_SQLDisconnect(sql->hdbc); | |
834 dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); | |
835 dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); | |
836 xfree(sql->query); | |
837 return NULL; | |
838 } | |
839 for (i = 1; i <= total; i++) | |
840 { /* return a set of attributes for a column */ | |
841 ret = dl_SQLDescribeCol(sql->hstmt, (SQLSMALLINT) i, | |
842 sql->colname[i], SQL_FDLEN_MAX, | |
843 &colnamelen, &(sql->coltype[i]), &(sql->collen[i]), &scale, | |
844 &nullable); | |
845 sql->isnumeric[i] = is_numeric(sql->coltype[i]); | |
846 /* bind columns to program vars, converting all types to CHAR*/ | |
847 if (sql->isnumeric[i]) | |
848 { dl_SQLBindCol(sql->hstmt, i, SQL_DOUBLE, sql->data[i], | |
849 SQL_FDLEN_MAX, &(sql->outlen[i])); | |
850 } else | |
851 { dl_SQLBindCol(sql->hstmt, i, SQL_CHAR, sql->data[i], | |
852 SQL_FDLEN_MAX, &(sql->outlen[i])); | |
853 } | |
854 for (j = sql->nf; j >= 1; j--) | |
855 { if (strcmp(mpl_tab_get_name(dca, j), sql->colname[i]) == 0) | |
856 break; | |
857 } | |
858 sql->ref[i] = j; | |
859 } | |
860 } | |
861 else if ( sql->mode == 'W' ) | |
862 { for(j = 0; sqllines[j] != NULL; j++) | |
863 arg = sqllines[j]; | |
864 if ( NULL != strchr(arg, '?') ) | |
865 { | |
866 total = strlen(arg); | |
867 sql->query = xmalloc( (total+1) * sizeof(char)); | |
868 strcpy (sql->query, arg); | |
869 } | |
870 else | |
871 { | |
872 sql->query = db_generate_insert_stmt(dca); | |
873 } | |
874 xprintf("%s\n", sql->query); | |
875 } | |
876 return sql; | |
877 } | |
878 | |
879 int db_iodbc_read(TABDCA *dca, void *link) | |
880 { | |
881 struct db_odbc *sql; | |
882 SQLRETURN ret; | |
883 char buf[SQL_FDLEN_MAX+1]; | |
884 int i; | |
885 int len; | |
886 double num; | |
887 | |
888 sql = (struct db_odbc *) link; | |
889 | |
890 xassert(sql != NULL); | |
891 xassert(sql->mode == 'R'); | |
892 | |
893 ret=dl_SQLFetch(sql->hstmt); | |
894 if (ret== SQL_ERROR) | |
895 return -1; | |
896 if (ret== SQL_NO_DATA_FOUND) | |
897 return -1; /*EOF*/ | |
898 for (i=1; i <= sql->nresultcols; i++) | |
899 { | |
900 if (sql->ref[i] > 0) | |
901 { | |
902 len = sql->outlen[i]; | |
903 if (len != SQL_NULL_DATA) | |
904 { | |
905 if (sql->isnumeric[i]) | |
906 { mpl_tab_set_num(dca, sql->ref[i], | |
907 *((const double *) sql->data[i])); | |
908 } | |
909 else | |
910 { if (len > SQL_FDLEN_MAX) | |
911 len = SQL_FDLEN_MAX; | |
912 else if (len < 0) | |
913 len = 0; | |
914 strncpy(buf, (const char *) sql->data[i], len); | |
915 buf[len] = 0x00; | |
916 mpl_tab_set_str(dca, sql->ref[i], strtrim(buf)); | |
917 } | |
918 } | |
919 } | |
920 } | |
921 return 0; | |
922 } | |
923 | |
924 int db_iodbc_write(TABDCA *dca, void *link) | |
925 { | |
926 struct db_odbc *sql; | |
927 char *part; | |
928 char *query; | |
929 char *template; | |
930 char num[50]; | |
931 int k; | |
932 int len; | |
933 int nf; | |
934 | |
935 sql = (struct db_odbc *) link; | |
936 xassert(sql != NULL); | |
937 xassert(sql->mode == 'W'); | |
938 | |
939 len = strlen(sql->query); | |
940 template = (char *) xmalloc( (len + 1) * sizeof(char) ); | |
941 strcpy(template, sql->query); | |
942 | |
943 nf = mpl_tab_num_flds(dca); | |
944 for (k = 1; k <= nf; k++) | |
945 { switch (mpl_tab_get_type(dca, k)) | |
946 { case 'N': | |
947 len += 20; | |
948 break; | |
949 case 'S': | |
950 len += db_escaped_string_length(mpl_tab_get_str(dca, k)); | |
951 len += 2; | |
952 break; | |
953 default: | |
954 xassert(dca != dca); | |
955 } | |
956 } | |
957 query = xmalloc( (len + 1 ) * sizeof(char) ); | |
958 query[0] = 0x00; | |
959 for (k = 1, part = strtok (template, "?"); (part != NULL); | |
960 part = strtok (NULL, "?"), k++) | |
961 { | |
962 if (k > nf) break; | |
963 strcat( query, part ); | |
964 switch (mpl_tab_get_type(dca, k)) | |
965 { case 'N': | |
966 #if 0 /* 02/XI-2010 by xypron */ | |
967 sprintf(num, "%-18g",mpl_tab_get_num(dca, k)); | |
968 #else | |
969 sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k)); | |
970 #endif | |
971 strcat( query, num ); | |
972 break; | |
973 case 'S': | |
974 strcat( query, "'"); | |
975 db_escape_string( query + strlen(query), | |
976 mpl_tab_get_str(dca, k) ); | |
977 strcat( query, "'"); | |
978 break; | |
979 default: | |
980 xassert(dca != dca); | |
981 } | |
982 } | |
983 if (part != NULL) | |
984 strcat(query, part); | |
985 if (dl_SQLExecDirect(sql->hstmt, (SQLCHAR *) query, SQL_NTS) | |
986 != SQL_SUCCESS) | |
987 { | |
988 xprintf("db_iodbc_write: Query\n\"%s\"\nfailed.\n", query); | |
989 extract_error("SQLExecDirect", sql->hdbc, SQL_HANDLE_DBC); | |
990 xfree(query); | |
991 xfree(template); | |
992 return 1; | |
993 } | |
994 | |
995 xfree(query); | |
996 xfree(template); | |
997 return 0; | |
998 } | |
999 | |
1000 int db_iodbc_close(TABDCA *dca, void *link) | |
1001 { | |
1002 struct db_odbc *sql; | |
1003 | |
1004 sql = (struct db_odbc *) link; | |
1005 xassert(sql != NULL); | |
1006 /* Commit */ | |
1007 if ( sql->mode == 'W' ) | |
1008 dl_SQLEndTran(SQL_HANDLE_ENV, sql->henv, SQL_COMMIT); | |
1009 if ( sql->mode == 'R' ) | |
1010 dl_SQLCloseCursor(sql->hstmt); | |
1011 | |
1012 dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); | |
1013 dl_SQLDisconnect(sql->hdbc); | |
1014 dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); | |
1015 dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); | |
1016 if ( sql->mode == 'W' ) | |
1017 xfree(sql->query); | |
1018 xfree(sql); | |
1019 dca->link = NULL; | |
1020 return 0; | |
1021 } | |
1022 | |
1023 static void extract_error( | |
1024 char *fn, | |
1025 SQLHANDLE handle, | |
1026 SQLSMALLINT type) | |
1027 { | |
1028 SQLINTEGER i = 0; | |
1029 SQLINTEGER native; | |
1030 SQLCHAR state[ 7 ]; | |
1031 SQLCHAR text[256]; | |
1032 SQLSMALLINT len; | |
1033 SQLRETURN ret; | |
1034 | |
1035 xprintf("\nThe driver reported the following diagnostics whilst " | |
1036 "running %s\n", fn); | |
1037 | |
1038 do | |
1039 { | |
1040 ret = dl_SQLGetDiagRec(type, handle, ++i, state, &native, text, | |
1041 sizeof(text), &len ); | |
1042 if (SQL_SUCCEEDED(ret)) | |
1043 xprintf("%s:%ld:%ld:%s\n", state, i, native, text); | |
1044 } | |
1045 while( ret == SQL_SUCCESS ); | |
1046 } | |
1047 | |
1048 static int is_numeric(SQLSMALLINT coltype) | |
1049 { | |
1050 int ret = 0; | |
1051 switch (coltype) | |
1052 { | |
1053 case SQL_DECIMAL: | |
1054 case SQL_NUMERIC: | |
1055 case SQL_SMALLINT: | |
1056 case SQL_INTEGER: | |
1057 case SQL_REAL: | |
1058 case SQL_FLOAT: | |
1059 case SQL_DOUBLE: | |
1060 case SQL_TINYINT: | |
1061 case SQL_BIGINT: | |
1062 ret = 1; | |
1063 break; | |
1064 } | |
1065 return ret; | |
1066 } | |
1067 | |
1068 #endif | |
1069 | |
1070 /**********************************************************************/ | |
1071 | |
1072 #ifndef HAVE_MYSQL | |
1073 | |
1074 void *db_mysql_open(TABDCA *dca, int mode) | |
1075 { xassert(dca == dca); | |
1076 xassert(mode == mode); | |
1077 xprintf("MySQL table driver not supported\n"); | |
1078 return NULL; | |
1079 } | |
1080 | |
1081 int db_mysql_read(TABDCA *dca, void *link) | |
1082 { xassert(dca != dca); | |
1083 xassert(link != link); | |
1084 return 0; | |
1085 } | |
1086 | |
1087 int db_mysql_write(TABDCA *dca, void *link) | |
1088 { xassert(dca != dca); | |
1089 xassert(link != link); | |
1090 return 0; | |
1091 } | |
1092 | |
1093 int db_mysql_close(TABDCA *dca, void *link) | |
1094 { xassert(dca != dca); | |
1095 xassert(link != link); | |
1096 return 0; | |
1097 } | |
1098 | |
1099 #else | |
1100 | |
1101 #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__) | |
1102 #include <windows.h> | |
1103 #endif | |
1104 | |
1105 #ifdef __CYGWIN__ | |
1106 #define byte_defined 1 | |
1107 #endif | |
1108 | |
1109 #include <my_global.h> | |
1110 #include <my_sys.h> | |
1111 #include <mysql.h> | |
1112 | |
1113 struct db_mysql | |
1114 { | |
1115 int mode; /*'R' = Read, 'W' = Write*/ | |
1116 MYSQL *con; /*connection*/ | |
1117 MYSQL_RES *res; /*result*/ | |
1118 int nf; | |
1119 /* number of fields in the csv file */ | |
1120 int ref[1+SQL_FIELD_MAX]; | |
1121 /* ref[k] = k', if k-th field of the csv file corresponds to | |
1122 k'-th field in the table statement; if ref[k] = 0, k-th field | |
1123 of the csv file is ignored */ | |
1124 char *query; | |
1125 /* query generated by db_mysql_open */ | |
1126 }; | |
1127 | |
1128 void STDCALL dl_mysql_close(MYSQL *sock) | |
1129 { | |
1130 typedef void STDCALL ep_mysql_close(MYSQL *sock); | |
1131 | |
1132 ep_mysql_close *fn; | |
1133 fn = (ep_mysql_close *) xdlsym(h_mysql, "mysql_close"); | |
1134 xassert(fn != NULL); | |
1135 return (*fn)(sock); | |
1136 } | |
1137 | |
1138 const char * STDCALL dl_mysql_error(MYSQL *mysql) | |
1139 { | |
1140 typedef const char * STDCALL ep_mysql_error(MYSQL *mysql); | |
1141 | |
1142 ep_mysql_error *fn; | |
1143 fn = (ep_mysql_error *) xdlsym(h_mysql, "mysql_error"); | |
1144 xassert(fn != NULL); | |
1145 return (*fn)(mysql); | |
1146 } | |
1147 | |
1148 MYSQL_FIELD * STDCALL dl_mysql_fetch_fields(MYSQL_RES *res) | |
1149 { | |
1150 typedef MYSQL_FIELD * STDCALL | |
1151 ep_mysql_fetch_fields(MYSQL_RES *res); | |
1152 | |
1153 ep_mysql_fetch_fields *fn; | |
1154 fn = (ep_mysql_fetch_fields *) xdlsym(h_mysql, "mysql_fetch_fields"); | |
1155 xassert(fn != NULL); | |
1156 return (*fn)(res); | |
1157 } | |
1158 | |
1159 unsigned long * STDCALL dl_mysql_fetch_lengths(MYSQL_RES *result) | |
1160 { | |
1161 typedef unsigned long * STDCALL | |
1162 ep_mysql_fetch_lengths(MYSQL_RES *result); | |
1163 | |
1164 ep_mysql_fetch_lengths *fn; | |
1165 fn = (ep_mysql_fetch_lengths *) xdlsym(h_mysql, | |
1166 "mysql_fetch_lengths"); | |
1167 xassert(fn != NULL); | |
1168 return (*fn)(result); | |
1169 } | |
1170 | |
1171 MYSQL_ROW STDCALL dl_mysql_fetch_row(MYSQL_RES *result) | |
1172 { | |
1173 typedef MYSQL_ROW STDCALL ep_mysql_fetch_row(MYSQL_RES *result); | |
1174 | |
1175 ep_mysql_fetch_row *fn; | |
1176 fn = (ep_mysql_fetch_row *) xdlsym(h_mysql, "mysql_fetch_row"); | |
1177 xassert(fn != NULL); | |
1178 return (*fn)(result); | |
1179 } | |
1180 | |
1181 unsigned int STDCALL dl_mysql_field_count(MYSQL *mysql) | |
1182 { | |
1183 typedef unsigned int STDCALL ep_mysql_field_count(MYSQL *mysql); | |
1184 | |
1185 ep_mysql_field_count *fn; | |
1186 fn = (ep_mysql_field_count *) xdlsym(h_mysql, "mysql_field_count"); | |
1187 xassert(fn != NULL); | |
1188 return (*fn)(mysql); | |
1189 } | |
1190 | |
1191 MYSQL * STDCALL dl_mysql_init(MYSQL *mysql) | |
1192 { | |
1193 typedef MYSQL * STDCALL ep_mysql_init(MYSQL *mysql); | |
1194 | |
1195 ep_mysql_init *fn; | |
1196 fn = (ep_mysql_init *) xdlsym(h_mysql, "mysql_init"); | |
1197 xassert(fn != NULL); | |
1198 return (*fn)(mysql); | |
1199 } | |
1200 | |
1201 unsigned int STDCALL dl_mysql_num_fields(MYSQL_RES *res) | |
1202 { | |
1203 typedef unsigned int STDCALL ep_mysql_num_fields(MYSQL_RES *res); | |
1204 | |
1205 ep_mysql_num_fields *fn; | |
1206 fn = (ep_mysql_num_fields *) xdlsym(h_mysql, "mysql_num_fields"); | |
1207 xassert(fn != NULL); | |
1208 return (*fn)(res); | |
1209 } | |
1210 | |
1211 int STDCALL dl_mysql_query(MYSQL *mysql, const char *q) | |
1212 { | |
1213 typedef int STDCALL ep_mysql_query(MYSQL *mysql, const char *q); | |
1214 | |
1215 ep_mysql_query *fn; | |
1216 fn = (ep_mysql_query *) xdlsym(h_mysql, "mysql_query"); | |
1217 xassert(fn != NULL); | |
1218 return (*fn)(mysql, q); | |
1219 } | |
1220 | |
1221 MYSQL * STDCALL dl_mysql_real_connect(MYSQL *mysql, const char *host, | |
1222 const char *user, | |
1223 const char *passwd, | |
1224 const char *db, | |
1225 unsigned int port, | |
1226 const char *unix_socket, | |
1227 unsigned long clientflag) | |
1228 { | |
1229 typedef MYSQL * STDCALL ep_mysql_real_connect(MYSQL *mysql, | |
1230 const char *host, | |
1231 const char *user, | |
1232 const char *passwd, | |
1233 const char *db, | |
1234 unsigned int port, | |
1235 const char *unix_socket, | |
1236 unsigned long clientflag); | |
1237 | |
1238 ep_mysql_real_connect *fn; | |
1239 fn = (ep_mysql_real_connect *) xdlsym(h_mysql, | |
1240 "mysql_real_connect"); | |
1241 xassert(fn != NULL); | |
1242 return (*fn)(mysql, host, user, passwd, db, port, unix_socket, | |
1243 clientflag); | |
1244 } | |
1245 | |
1246 MYSQL_RES * STDCALL dl_mysql_use_result(MYSQL *mysql) | |
1247 { | |
1248 typedef MYSQL_RES * STDCALL ep_mysql_use_result(MYSQL *mysql); | |
1249 ep_mysql_use_result *fn; | |
1250 fn = (ep_mysql_use_result *) xdlsym(h_mysql, "mysql_use_result"); | |
1251 xassert(fn != NULL); | |
1252 return (*fn)(mysql); | |
1253 } | |
1254 | |
1255 /*********************************************************************** | |
1256 * NAME | |
1257 * | |
1258 * db_mysql_open - open connection to ODBC data base | |
1259 * | |
1260 * SYNOPSIS | |
1261 * | |
1262 * #include "glpsql.h" | |
1263 * void *db_mysql_open(TABDCA *dca, int mode); | |
1264 * | |
1265 * DESCRIPTION | |
1266 * | |
1267 * The routine db_mysql_open opens a connection to a MySQL data base. | |
1268 * It then executes the sql statements passed. | |
1269 * | |
1270 * In the case of table read the SELECT statement is executed. | |
1271 * | |
1272 * In the case of table write the INSERT statement is prepared. | |
1273 * RETURNS | |
1274 * | |
1275 * The routine returns a pointer to data storage area created. */ | |
1276 | |
1277 void *db_mysql_open(TABDCA *dca, int mode) | |
1278 { void *ret; | |
1279 char **sqllines; | |
1280 | |
1281 sqllines = args_concat(dca); | |
1282 if (sqllines == NULL) | |
1283 { xprintf("Missing arguments in table statement.\n" | |
1284 "Please, supply table driver, dsn, and query.\n"); | |
1285 return NULL; | |
1286 } | |
1287 ret = db_mysql_open_int(dca, mode, (const char **) sqllines); | |
1288 free_buffer(sqllines); | |
1289 return ret; | |
1290 } | |
1291 | |
1292 static void *db_mysql_open_int(TABDCA *dca, int mode, const char | |
1293 **sqllines) | |
1294 { | |
1295 struct db_mysql *sql = NULL; | |
1296 char *arg = NULL; | |
1297 const char *field; | |
1298 MYSQL_FIELD *fields; | |
1299 char *keyword; | |
1300 char *value; | |
1301 char *query; | |
1302 char *dsn; | |
1303 /* "Server=[server_name];Database=[database_name];UID=[username];*/ | |
1304 /* PWD=[password];Port=[port]"*/ | |
1305 char *server = NULL; /* Server */ | |
1306 char *user = NULL; /* UID */ | |
1307 char *password = NULL; /* PWD */ | |
1308 char *database = NULL; /* Database */ | |
1309 unsigned int port = 0; /* Port */ | |
1310 int narg; | |
1311 int i, j, total; | |
1312 | |
1313 if (libmysql == NULL) | |
1314 { | |
1315 xprintf("No loader for shared MySQL library available\n"); | |
1316 return NULL; | |
1317 } | |
1318 | |
1319 if (h_mysql == NULL) | |
1320 { | |
1321 h_mysql = xdlopen(libmysql); | |
1322 if (h_mysql == NULL) | |
1323 { xprintf("unable to open library %s\n", libmysql); | |
1324 xprintf("%s\n", xerrmsg()); | |
1325 return NULL; | |
1326 } | |
1327 } | |
1328 | |
1329 sql = (struct db_mysql *) xmalloc(sizeof(struct db_mysql)); | |
1330 if (sql == NULL) | |
1331 return NULL; | |
1332 sql->mode = mode; | |
1333 sql->res = NULL; | |
1334 sql->query = NULL; | |
1335 sql->nf = mpl_tab_num_flds(dca); | |
1336 | |
1337 narg = mpl_tab_num_args(dca); | |
1338 if (narg < 3 ) | |
1339 xprintf("MySQL driver: string list too short \n"); | |
1340 | |
1341 /* get connection string*/ | |
1342 dsn = (char *) mpl_tab_get_arg(dca, 2); | |
1343 /* copy connection string*/ | |
1344 i = strlen(dsn); | |
1345 i++; | |
1346 arg = xmalloc(i * sizeof(char)); | |
1347 strcpy(arg, dsn); | |
1348 /*tokenize connection string*/ | |
1349 for (i = 1, keyword = strtok (arg, "="); (keyword != NULL); | |
1350 keyword = strtok (NULL, "="), i++) | |
1351 { | |
1352 value = strtok (NULL, ";"); | |
1353 if (value==NULL) | |
1354 { | |
1355 xprintf("db_mysql_open: Missing value for keyword %s\n", | |
1356 keyword); | |
1357 xfree(arg); | |
1358 xfree(sql); | |
1359 return NULL; | |
1360 } | |
1361 if (0 == strcmp(keyword, "Server")) | |
1362 server = value; | |
1363 else if (0 == strcmp(keyword, "Database")) | |
1364 database = value; | |
1365 else if (0 == strcmp(keyword, "UID")) | |
1366 user = value; | |
1367 else if (0 == strcmp(keyword, "PWD")) | |
1368 password = value; | |
1369 else if (0 == strcmp(keyword, "Port")) | |
1370 port = (unsigned int) atol(value); | |
1371 } | |
1372 /* Connect to database */ | |
1373 sql->con = dl_mysql_init(NULL); | |
1374 if (!dl_mysql_real_connect(sql->con, server, user, password, database, | |
1375 port, NULL, 0)) | |
1376 { | |
1377 xprintf("db_mysql_open: Connect failed\n"); | |
1378 xprintf("%s\n", dl_mysql_error(sql->con)); | |
1379 xfree(arg); | |
1380 xfree(sql); | |
1381 return NULL; | |
1382 } | |
1383 xfree(arg); | |
1384 | |
1385 for(j = 0; sqllines[j+1] != NULL; j++) | |
1386 { query = (char *) sqllines[j]; | |
1387 xprintf("%s\n", query); | |
1388 if (dl_mysql_query(sql->con, query)) | |
1389 { | |
1390 xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query); | |
1391 xprintf("%s\n",dl_mysql_error(sql->con)); | |
1392 dl_mysql_close(sql->con); | |
1393 xfree(sql); | |
1394 return NULL; | |
1395 } | |
1396 } | |
1397 | |
1398 if ( sql->mode == 'R' ) | |
1399 { sql->nf = mpl_tab_num_flds(dca); | |
1400 for(j = 0; sqllines[j] != NULL; j++) | |
1401 arg = (char *) sqllines[j]; | |
1402 total = strlen(arg); | |
1403 if (total > 7 && 0 == strncmp(arg, "SELECT ", 7)) | |
1404 { | |
1405 total = strlen(arg); | |
1406 query = xmalloc( (total+1) * sizeof(char)); | |
1407 strcpy (query, arg); | |
1408 } | |
1409 else | |
1410 { | |
1411 query = db_generate_select_stmt(dca); | |
1412 } | |
1413 xprintf("%s\n", query); | |
1414 if (dl_mysql_query(sql->con, query)) | |
1415 { | |
1416 xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query); | |
1417 xprintf("%s\n",dl_mysql_error(sql->con)); | |
1418 dl_mysql_close(sql->con); | |
1419 xfree(query); | |
1420 xfree(sql); | |
1421 return NULL; | |
1422 } | |
1423 xfree(query); | |
1424 sql->res = dl_mysql_use_result(sql->con); | |
1425 if (sql->res) | |
1426 { | |
1427 /* create references between query results and table fields*/ | |
1428 total = dl_mysql_num_fields(sql->res); | |
1429 if (total > SQL_FIELD_MAX) | |
1430 { xprintf("db_mysql_open: Too many fields (> %d) in query.\n" | |
1431 "\"%s\"\n", SQL_FIELD_MAX, query); | |
1432 xprintf("%s\n",dl_mysql_error(sql->con)); | |
1433 dl_mysql_close(sql->con); | |
1434 xfree(query); | |
1435 xfree(sql); | |
1436 return NULL; | |
1437 } | |
1438 fields = dl_mysql_fetch_fields(sql->res); | |
1439 for (i = 1; i <= total; i++) | |
1440 { | |
1441 for (j = sql->nf; j >= 1; j--) | |
1442 { | |
1443 if (strcmp(mpl_tab_get_name(dca, j), fields[i-1].name) | |
1444 == 0) | |
1445 break; | |
1446 } | |
1447 sql->ref[i] = j; | |
1448 } | |
1449 } | |
1450 else | |
1451 { | |
1452 if(dl_mysql_field_count(sql->con) == 0) | |
1453 { | |
1454 xprintf("db_mysql_open: Query was not a SELECT\n\"%s\"\n", | |
1455 query); | |
1456 xprintf("%s\n",dl_mysql_error(sql->con)); | |
1457 xfree(query); | |
1458 xfree(sql); | |
1459 return NULL; | |
1460 } | |
1461 else | |
1462 { | |
1463 xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query); | |
1464 xprintf("%s\n",dl_mysql_error(sql->con)); | |
1465 xfree(query); | |
1466 xfree(sql); | |
1467 return NULL; | |
1468 } | |
1469 } | |
1470 } | |
1471 else if ( sql->mode == 'W' ) | |
1472 { for(j = 0; sqllines[j] != NULL; j++) | |
1473 arg = (char *) sqllines[j]; | |
1474 if ( NULL != strchr(arg, '?') ) | |
1475 { | |
1476 total = strlen(arg); | |
1477 query = xmalloc( (total+1) * sizeof(char)); | |
1478 strcpy (query, arg); | |
1479 } | |
1480 else | |
1481 query = db_generate_insert_stmt(dca); | |
1482 sql->query = query; | |
1483 xprintf("%s\n", query); | |
1484 } | |
1485 return sql; | |
1486 } | |
1487 | |
1488 int db_mysql_read(TABDCA *dca, void *link) | |
1489 { struct db_mysql *sql; | |
1490 char buf[255+1]; | |
1491 char **row; | |
1492 unsigned long *lengths; | |
1493 MYSQL_FIELD *fields; | |
1494 double num; | |
1495 int len; | |
1496 unsigned long num_fields; | |
1497 int i; | |
1498 | |
1499 sql = (struct db_mysql *) link; | |
1500 | |
1501 xassert(sql != NULL); | |
1502 xassert(sql->mode == 'R'); | |
1503 if (NULL == sql->res) | |
1504 { | |
1505 xprintf("db_mysql_read: no result set available"); | |
1506 return 1; | |
1507 } | |
1508 if (NULL==(row = (char **)dl_mysql_fetch_row(sql->res))) { | |
1509 return -1; /*EOF*/ | |
1510 } | |
1511 lengths = dl_mysql_fetch_lengths(sql->res); | |
1512 fields = dl_mysql_fetch_fields(sql->res); | |
1513 num_fields = dl_mysql_num_fields(sql->res); | |
1514 for (i=1; i <= num_fields; i++) | |
1515 { | |
1516 if (row[i-1] != NULL) | |
1517 { len = (size_t) lengths[i-1]; | |
1518 if (len > 255) | |
1519 len = 255; | |
1520 strncpy(buf, (const char *) row[i-1], len); | |
1521 buf[len] = 0x00; | |
1522 if (0 != (fields[i-1].flags & NUM_FLAG)) | |
1523 { strspx(buf); /* remove spaces*/ | |
1524 if (str2num(buf, &num) != 0) | |
1525 { xprintf("'%s' cannot be converted to a number.\n", buf); | |
1526 return 1; | |
1527 } | |
1528 if (sql->ref[i] > 0) | |
1529 mpl_tab_set_num(dca, sql->ref[i], num); | |
1530 } | |
1531 else | |
1532 { if (sql->ref[i] > 0) | |
1533 mpl_tab_set_str(dca, sql->ref[i], strtrim(buf)); | |
1534 } | |
1535 } | |
1536 } | |
1537 return 0; | |
1538 } | |
1539 | |
1540 int db_mysql_write(TABDCA *dca, void *link) | |
1541 { | |
1542 struct db_mysql *sql; | |
1543 char *part; | |
1544 char *query; | |
1545 char *template; | |
1546 char num[50]; | |
1547 int k; | |
1548 int len; | |
1549 int nf; | |
1550 | |
1551 sql = (struct db_mysql *) link; | |
1552 xassert(sql != NULL); | |
1553 xassert(sql->mode == 'W'); | |
1554 | |
1555 len = strlen(sql->query); | |
1556 template = (char *) xmalloc( (len + 1) * sizeof(char) ); | |
1557 strcpy(template, sql->query); | |
1558 | |
1559 nf = mpl_tab_num_flds(dca); | |
1560 for (k = 1; k <= nf; k++) | |
1561 { switch (mpl_tab_get_type(dca, k)) | |
1562 { case 'N': | |
1563 len += 20; | |
1564 break; | |
1565 case 'S': | |
1566 len += db_escaped_string_length(mpl_tab_get_str(dca, k)); | |
1567 len += 2; | |
1568 break; | |
1569 default: | |
1570 xassert(dca != dca); | |
1571 } | |
1572 } | |
1573 query = xmalloc( (len + 1 ) * sizeof(char) ); | |
1574 query[0] = 0x00; | |
1575 for (k = 1, part = strtok (template, "?"); (part != NULL); | |
1576 part = strtok (NULL, "?"), k++) | |
1577 { | |
1578 if (k > nf) break; | |
1579 strcat( query, part ); | |
1580 switch (mpl_tab_get_type(dca, k)) | |
1581 { case 'N': | |
1582 #if 0 /* 02/XI-2010 by xypron */ | |
1583 sprintf(num, "%-18g",mpl_tab_get_num(dca, k)); | |
1584 #else | |
1585 sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k)); | |
1586 #endif | |
1587 strcat( query, num ); | |
1588 break; | |
1589 case 'S': | |
1590 strcat( query, "'"); | |
1591 db_escape_string( query + strlen(query), | |
1592 mpl_tab_get_str(dca, k) ); | |
1593 strcat( query, "'"); | |
1594 break; | |
1595 default: | |
1596 xassert(dca != dca); | |
1597 } | |
1598 } | |
1599 if (part != NULL) | |
1600 strcat(query, part); | |
1601 if (dl_mysql_query(sql->con, query)) | |
1602 { | |
1603 xprintf("db_mysql_write: Query\n\"%s\"\nfailed.\n", query); | |
1604 xprintf("%s\n",dl_mysql_error(sql->con)); | |
1605 xfree(query); | |
1606 xfree(template); | |
1607 return 1; | |
1608 } | |
1609 | |
1610 xfree(query); | |
1611 xfree(template); | |
1612 return 0; | |
1613 } | |
1614 | |
1615 int db_mysql_close(TABDCA *dca, void *link) | |
1616 { | |
1617 struct db_mysql *sql; | |
1618 | |
1619 sql = (struct db_mysql *) link; | |
1620 xassert(sql != NULL); | |
1621 dl_mysql_close(sql->con); | |
1622 if ( sql->mode == 'W' ) | |
1623 xfree(sql->query); | |
1624 xfree(sql); | |
1625 dca->link = NULL; | |
1626 return 0; | |
1627 } | |
1628 | |
1629 #endif | |
1630 | |
1631 /* eof */ |