3 /***********************************************************************
4 * This code is part of GLPK (GNU Linear Programming Kit).
6 * Author: Heinrich Schuchardt <xypron.glpk@gmx.de>.
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>.
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.
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.
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 ***********************************************************************/
36 #define libodbc ODBC_DLNAME
37 #define h_odbc (get_env_ptr()->h_odbc)
42 #define libmysql MYSQL_DLNAME
43 #define h_mysql (get_env_ptr()->h_mysql)
46 static void *db_iodbc_open_int(TABDCA *dca, int mode, const char
48 static void *db_mysql_open_int(TABDCA *dca, int mode, const char
51 /**********************************************************************/
53 #if defined(HAVE_ODBC) || defined(HAVE_MYSQL)
55 #define SQL_FIELD_MAX 100
56 /* maximal field count */
58 #define SQL_FDLEN_MAX 255
59 /* maximal field length */
61 /***********************************************************************
64 * args_concat - concatenate arguments
68 * static char **args_concat(TABDCA *dca);
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.
80 * Buffer with SQL statements */
82 static char **args_concat(TABDCA *dca)
94 char **sqllines = NULL;
96 narg = mpl_tab_num_args(dca);
97 /* The SQL statements start with argument 3. */
100 /* Count the SQL statements */
101 for (j = 3; j <= narg; j++)
103 arg = mpl_tab_get_arg(dca, j);
105 if (arg[len-1] == ';' || j == narg)
108 /* Allocate string buffer. */
109 sqllines = (char **) xmalloc((nline+1) * sizeof(char **));
115 for (j = 3; j <= narg; j++)
117 arg = mpl_tab_get_arg(dca, j);
120 if (arg[len-1] == ';' || j == narg)
121 { /* Join arguments for a single SQL statement */
122 sqllines[i] = xmalloc(lentot+1);
123 sqllines[i+1] = NULL;
124 sqllines[i][0] = 0x00;
125 for (j1 = j0; j1 <= j; j1++)
127 strcat(sqllines[i], " ");
128 strcat(sqllines[i], mpl_tab_get_arg(dca, j1));
130 len = strlen(sqllines[i]);
131 if (sqllines[i][len-1] == ';')
132 sqllines[i][len-1] = 0x00;
141 /***********************************************************************
144 * free_buffer - free multiline string buffer
148 * static void free_buffer(char **buf);
152 * buf is a list of strings terminated by NULL.
153 * The memory for the strings and for the list is released. */
155 static void free_buffer(char **buf)
158 for(i = 0; buf[i] != NULL; i++)
163 static int db_escaped_string_length(const char* from)
164 /* length of escaped string */
169 for (pointer = from, count = 0; *pointer != (char) '\0'; pointer++,
183 static int db_escape_string (char *to, const char *from)
186 const char *source = from;
188 unsigned int remaining;
190 remaining = strlen(from);
193 to = (char *) (from + remaining);
195 while (remaining > 0)
213 /* Write the terminating NUL character. */
219 static char *db_generate_select_stmt(TABDCA *dca)
220 /* generate select statement */
231 nf = mpl_tab_num_flds(dca);
232 narg = mpl_tab_num_args(dca);
233 for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++)
235 field = mpl_tab_get_name(dca, j);
236 total += strlen(field);
239 arg = (char *) mpl_tab_get_arg(dca, narg);
240 total += strlen(arg);
241 query = xmalloc( total * sizeof(char));
242 strcpy (query, "SELECT ");
243 for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++)
245 field = mpl_tab_get_name(dca, j);
246 strcat(query, field);
250 strcat(query, " FROM ");
255 static char *db_generate_insert_stmt(TABDCA *dca)
256 /* generate insert statement */
267 nf = mpl_tab_num_flds(dca);
268 narg = mpl_tab_num_args(dca);
269 for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++)
271 field = mpl_tab_get_name(dca, j);
272 total += strlen(field);
275 arg = (char *) mpl_tab_get_arg(dca, narg);
276 total += strlen(arg);
277 query = xmalloc( (total+1) * sizeof(char));
278 strcpy (query, "INSERT INTO ");
280 strcat(query, " ( ");
281 for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++)
283 field = mpl_tab_get_name(dca, j);
284 strcat(query, field);
288 strcat(query, " ) VALUES ( ");
289 for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++)
301 /**********************************************************************/
305 void *db_iodbc_open(TABDCA *dca, int mode)
306 { xassert(dca == dca);
307 xassert(mode == mode);
308 xprintf("iODBC table driver not supported\n");
312 int db_iodbc_read(TABDCA *dca, void *link)
313 { xassert(dca != dca);
314 xassert(link != link);
318 int db_iodbc_write(TABDCA *dca, void *link)
319 { xassert(dca != dca);
320 xassert(link != link);
324 int db_iodbc_close(TABDCA *dca, void *link)
325 { xassert(dca != dca);
326 xassert(link != link);
332 #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__)
341 int mode; /*'R' = Read, 'W' = Write*/
342 SQLHDBC hdbc; /*connection handle*/
343 SQLHENV henv; /*environment handle*/
344 SQLHSTMT hstmt; /*statement handle*/
345 SQLSMALLINT nresultcols; /* columns in result*/
346 SQLULEN collen[SQL_FIELD_MAX+1];
347 SQLLEN outlen[SQL_FIELD_MAX+1];
348 SQLSMALLINT coltype[SQL_FIELD_MAX+1];
349 SQLCHAR data[SQL_FIELD_MAX+1][SQL_FDLEN_MAX+1];
350 SQLCHAR colname[SQL_FIELD_MAX+1][SQL_FDLEN_MAX+1];
351 int isnumeric[SQL_FIELD_MAX+1];
353 /* number of fields in the csv file */
354 int ref[1+SQL_FIELD_MAX];
355 /* ref[k] = k', if k-th field of the csv file corresponds to
356 k'-th field in the table statement; if ref[k] = 0, k-th field
357 of the csv file is ignored */
359 /* query generated by db_iodbc_open */
362 SQLRETURN SQL_API dl_SQLAllocHandle (
363 SQLSMALLINT HandleType,
364 SQLHANDLE InputHandle,
365 SQLHANDLE *OutputHandle)
367 typedef SQLRETURN SQL_API ep_SQLAllocHandle(
368 SQLSMALLINT HandleType,
369 SQLHANDLE InputHandle,
370 SQLHANDLE *OutputHandle);
372 ep_SQLAllocHandle *fn;
373 fn = (ep_SQLAllocHandle *) xdlsym(h_odbc, "SQLAllocHandle");
375 return (*fn)(HandleType, InputHandle, OutputHandle);
378 SQLRETURN SQL_API dl_SQLBindCol (
379 SQLHSTMT StatementHandle,
380 SQLUSMALLINT ColumnNumber,
381 SQLSMALLINT TargetType,
382 SQLPOINTER TargetValue,
384 SQLLEN *StrLen_or_Ind)
386 typedef SQLRETURN SQL_API ep_SQLBindCol(
387 SQLHSTMT StatementHandle,
388 SQLUSMALLINT ColumnNumber,
389 SQLSMALLINT TargetType,
390 SQLPOINTER TargetValue,
392 SQLLEN *StrLen_or_Ind);
394 fn = (ep_SQLBindCol *) xdlsym(h_odbc, "SQLBindCol");
396 return (*fn)(StatementHandle, ColumnNumber, TargetType,
397 TargetValue, BufferLength, StrLen_or_Ind);
400 SQLRETURN SQL_API dl_SQLCloseCursor (
401 SQLHSTMT StatementHandle)
403 typedef SQLRETURN SQL_API ep_SQLCloseCursor (
404 SQLHSTMT StatementHandle);
406 ep_SQLCloseCursor *fn;
407 fn = (ep_SQLCloseCursor *) xdlsym(h_odbc, "SQLCloseCursor");
409 return (*fn)(StatementHandle);
413 SQLRETURN SQL_API dl_SQLDisconnect (
414 SQLHDBC ConnectionHandle)
416 typedef SQLRETURN SQL_API ep_SQLDisconnect(
417 SQLHDBC ConnectionHandle);
419 ep_SQLDisconnect *fn;
420 fn = (ep_SQLDisconnect *) xdlsym(h_odbc, "SQLDisconnect");
422 return (*fn)(ConnectionHandle);
425 SQLRETURN SQL_API dl_SQLDriverConnect (
428 SQLCHAR *szConnStrIn,
429 SQLSMALLINT cbConnStrIn,
430 SQLCHAR *szConnStrOut,
431 SQLSMALLINT cbConnStrOutMax,
432 SQLSMALLINT *pcbConnStrOut,
433 SQLUSMALLINT fDriverCompletion)
435 typedef SQLRETURN SQL_API ep_SQLDriverConnect(
438 SQLCHAR * szConnStrIn,
439 SQLSMALLINT cbConnStrIn,
440 SQLCHAR * szConnStrOut,
441 SQLSMALLINT cbConnStrOutMax,
442 SQLSMALLINT * pcbConnStrOut,
443 SQLUSMALLINT fDriverCompletion);
445 ep_SQLDriverConnect *fn;
446 fn = (ep_SQLDriverConnect *) xdlsym(h_odbc, "SQLDriverConnect");
448 return (*fn)(hdbc, hwnd, szConnStrIn, cbConnStrIn, szConnStrOut,
449 cbConnStrOutMax, pcbConnStrOut, fDriverCompletion);
452 SQLRETURN SQL_API dl_SQLEndTran (
453 SQLSMALLINT HandleType,
455 SQLSMALLINT CompletionType)
457 typedef SQLRETURN SQL_API ep_SQLEndTran (
458 SQLSMALLINT HandleType,
460 SQLSMALLINT CompletionType);
463 fn = (ep_SQLEndTran *) xdlsym(h_odbc, "SQLEndTran");
465 return (*fn)(HandleType, Handle, CompletionType);
468 SQLRETURN SQL_API dl_SQLExecDirect (
469 SQLHSTMT StatementHandle,
470 SQLCHAR * StatementText,
471 SQLINTEGER TextLength)
473 typedef SQLRETURN SQL_API ep_SQLExecDirect (
474 SQLHSTMT StatementHandle,
475 SQLCHAR * StatementText,
476 SQLINTEGER TextLength);
478 ep_SQLExecDirect *fn;
479 fn = (ep_SQLExecDirect *) xdlsym(h_odbc, "SQLExecDirect");
481 return (*fn)(StatementHandle, StatementText, TextLength);
484 SQLRETURN SQL_API dl_SQLFetch (
485 SQLHSTMT StatementHandle)
487 typedef SQLRETURN SQL_API ep_SQLFetch (
488 SQLHSTMT StatementHandle);
491 fn = (ep_SQLFetch*) xdlsym(h_odbc, "SQLFetch");
493 return (*fn)(StatementHandle);
496 SQLRETURN SQL_API dl_SQLFreeHandle (
497 SQLSMALLINT HandleType,
500 typedef SQLRETURN SQL_API ep_SQLFreeHandle (
501 SQLSMALLINT HandleType,
504 ep_SQLFreeHandle *fn;
505 fn = (ep_SQLFreeHandle *) xdlsym(h_odbc, "SQLFreeHandle");
507 return (*fn)(HandleType, Handle);
510 SQLRETURN SQL_API dl_SQLDescribeCol (
511 SQLHSTMT StatementHandle,
512 SQLUSMALLINT ColumnNumber,
513 SQLCHAR * ColumnName,
514 SQLSMALLINT BufferLength,
515 SQLSMALLINT * NameLength,
516 SQLSMALLINT * DataType,
517 SQLULEN * ColumnSize,
518 SQLSMALLINT * DecimalDigits,
519 SQLSMALLINT * Nullable)
521 typedef SQLRETURN SQL_API ep_SQLDescribeCol (
522 SQLHSTMT StatementHandle,
523 SQLUSMALLINT ColumnNumber,
525 SQLSMALLINT BufferLength,
526 SQLSMALLINT *NameLength,
527 SQLSMALLINT *DataType,
529 SQLSMALLINT *DecimalDigits,
530 SQLSMALLINT *Nullable);
532 ep_SQLDescribeCol *fn;
533 fn = (ep_SQLDescribeCol *) xdlsym(h_odbc, "SQLDescribeCol");
535 return (*fn)(StatementHandle, ColumnNumber, ColumnName,
536 BufferLength, NameLength,
537 DataType, ColumnSize, DecimalDigits, Nullable);
540 SQLRETURN SQL_API dl_SQLGetDiagRec (
541 SQLSMALLINT HandleType,
543 SQLSMALLINT RecNumber,
545 SQLINTEGER *NativeError,
546 SQLCHAR *MessageText,
547 SQLSMALLINT BufferLength,
548 SQLSMALLINT *TextLength)
550 typedef SQLRETURN SQL_API ep_SQLGetDiagRec (
551 SQLSMALLINT HandleType,
553 SQLSMALLINT RecNumber,
555 SQLINTEGER *NativeError,
556 SQLCHAR *MessageText,
557 SQLSMALLINT BufferLength,
558 SQLSMALLINT *TextLength);
560 ep_SQLGetDiagRec *fn;
561 fn = (ep_SQLGetDiagRec *) xdlsym(h_odbc, "SQLGetDiagRec");
563 return (*fn)(HandleType, Handle, RecNumber, Sqlstate,
564 NativeError, MessageText, BufferLength, TextLength);
567 SQLRETURN SQL_API dl_SQLGetInfo (
568 SQLHDBC ConnectionHandle,
569 SQLUSMALLINT InfoType,
570 SQLPOINTER InfoValue,
571 SQLSMALLINT BufferLength,
572 SQLSMALLINT *StringLength)
574 typedef SQLRETURN SQL_API ep_SQLGetInfo (
575 SQLHDBC ConnectionHandle,
576 SQLUSMALLINT InfoType,
577 SQLPOINTER InfoValue,
578 SQLSMALLINT BufferLength,
579 SQLSMALLINT *StringLength);
582 fn = (ep_SQLGetInfo *) xdlsym(h_odbc, "SQLGetInfo");
584 return (*fn)(ConnectionHandle, InfoType, InfoValue, BufferLength,
588 SQLRETURN SQL_API dl_SQLNumResultCols (
589 SQLHSTMT StatementHandle,
590 SQLSMALLINT *ColumnCount)
592 typedef SQLRETURN SQL_API ep_SQLNumResultCols (
593 SQLHSTMT StatementHandle,
594 SQLSMALLINT *ColumnCount);
596 ep_SQLNumResultCols *fn;
597 fn = (ep_SQLNumResultCols *) xdlsym(h_odbc, "SQLNumResultCols");
599 return (*fn)(StatementHandle, ColumnCount);
602 SQLRETURN SQL_API dl_SQLSetConnectAttr (
603 SQLHDBC ConnectionHandle,
604 SQLINTEGER Attribute,
606 SQLINTEGER StringLength)
608 typedef SQLRETURN SQL_API ep_SQLSetConnectAttr (
609 SQLHDBC ConnectionHandle,
610 SQLINTEGER Attribute,
612 SQLINTEGER StringLength);
614 ep_SQLSetConnectAttr *fn;
615 fn = (ep_SQLSetConnectAttr *) xdlsym(h_odbc, "SQLSetConnectAttr");
617 return (*fn)(ConnectionHandle, Attribute, Value, StringLength);
620 SQLRETURN SQL_API dl_SQLSetEnvAttr (
621 SQLHENV EnvironmentHandle,
622 SQLINTEGER Attribute,
624 SQLINTEGER StringLength)
626 typedef SQLRETURN SQL_API ep_SQLSetEnvAttr (
627 SQLHENV EnvironmentHandle,
628 SQLINTEGER Attribute,
630 SQLINTEGER StringLength);
632 ep_SQLSetEnvAttr *fn;
633 fn = (ep_SQLSetEnvAttr *) xdlsym(h_odbc, "SQLSetEnvAttr");
635 return (*fn)(EnvironmentHandle, Attribute, Value, StringLength);
638 static void extract_error(
643 static int is_numeric(
644 SQLSMALLINT coltype);
646 /***********************************************************************
649 * db_iodbc_open - open connection to ODBC data base
653 * #include "glpsql.h"
654 * void *db_iodbc_open(TABDCA *dca, int mode);
658 * The routine db_iodbc_open opens a connection to an ODBC data base.
659 * It then executes the sql statements passed.
661 * In the case of table read the SELECT statement is executed.
663 * In the case of table write the INSERT statement is prepared.
666 * The routine returns a pointer to data storage area created. */
667 void *db_iodbc_open(TABDCA *dca, int mode)
671 sqllines = args_concat(dca);
672 if (sqllines == NULL)
673 { xprintf("Missing arguments in table statement.\n"
674 "Please, supply table driver, dsn, and query.\n");
677 ret = db_iodbc_open_int(dca, mode, (const char **) sqllines);
678 free_buffer(sqllines);
682 static void *db_iodbc_open_int(TABDCA *dca, int mode, const char
689 SQLSMALLINT colnamelen;
690 SQLSMALLINT nullable;
699 xprintf("No loader for shared ODBC library available\n");
705 h_odbc = xdlopen(libodbc);
707 { xprintf("unable to open library %s\n", libodbc);
708 xprintf("%s\n", xerrmsg());
713 sql = (struct db_odbc *) xmalloc(sizeof(struct db_odbc));
722 narg = mpl_tab_num_args(dca);
724 dsn = (SQLCHAR FAR *) mpl_tab_get_arg(dca, 2);
725 /* allocate an environment handle */
726 ret = dl_SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE,
728 /* set attribute to enable application to run as ODBC 3.0
730 ret = dl_SQLSetEnvAttr(sql->henv, SQL_ATTR_ODBC_VERSION,
731 (void *) SQL_OV_ODBC3, 0);
732 /* allocate a connection handle */
733 ret = dl_SQLAllocHandle(SQL_HANDLE_DBC, sql->henv, &(sql->hdbc));
735 ret = dl_SQLDriverConnect(sql->hdbc, NULL, dsn, SQL_NTS, NULL, 0,
736 NULL, SQL_DRIVER_COMPLETE);
737 if (SQL_SUCCEEDED(ret))
738 { /* output information about data base connection */
739 xprintf("Connected to ");
740 dl_SQLGetInfo(sql->hdbc, SQL_DBMS_NAME, (SQLPOINTER)info,
742 xprintf("%s ", info);
743 dl_SQLGetInfo(sql->hdbc, SQL_DBMS_VER, (SQLPOINTER)info,
745 xprintf("%s - ", info);
746 dl_SQLGetInfo(sql->hdbc, SQL_DATABASE_NAME, (SQLPOINTER)info,
748 xprintf("%s\n", info);
751 { /* describe error */
752 xprintf("Failed to connect\n");
753 extract_error("SQLDriverConnect", sql->hdbc, SQL_HANDLE_DBC);
754 dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc);
755 dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv);
759 /* set AUTOCOMMIT on*/
760 ret = dl_SQLSetConnectAttr(sql->hdbc, SQL_ATTR_AUTOCOMMIT,
761 (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0);
762 /* allocate a statement handle */
763 ret = dl_SQLAllocHandle(SQL_HANDLE_STMT, sql->hdbc, &(sql->hstmt));
765 /* initialization queries */
766 for(j = 0; sqllines[j+1] != NULL; j++)
768 sql->query = (SQLCHAR *) sqllines[j];
769 xprintf("%s\n", sql->query);
770 ret = dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS);
774 case SQL_SUCCESS_WITH_INFO:
775 case SQL_NO_DATA_FOUND:
778 xprintf("db_iodbc_open: Query\n\"%s\"\nfailed.\n",
780 extract_error("SQLExecDirect", sql->hstmt, SQL_HANDLE_STMT);
781 dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt);
782 dl_SQLDisconnect(sql->hdbc);
783 dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc);
784 dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv);
788 /* commit statement */
789 dl_SQLEndTran(SQL_HANDLE_ENV, sql->henv, SQL_COMMIT);
792 if ( sql->mode == 'R' )
793 { sql->nf = mpl_tab_num_flds(dca);
794 for(j = 0; sqllines[j] != NULL; j++)
797 if (total > 7 && 0 == strncmp(arg, "SELECT ", 7))
800 sql->query = xmalloc( (total+1) * sizeof(char));
801 strcpy (sql->query, arg);
805 sql->query = db_generate_select_stmt(dca);
807 xprintf("%s\n", sql->query);
808 if (dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS) !=
811 xprintf("db_iodbc_open: Query\n\"%s\"\nfailed.\n", sql->query);
812 extract_error("SQLExecDirect", sql->hstmt, SQL_HANDLE_STMT);
813 dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt);
814 dl_SQLDisconnect(sql->hdbc);
815 dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc);
816 dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv);
822 /* determine number of result columns */
823 ret = dl_SQLNumResultCols(sql->hstmt, &sql->nresultcols);
824 total = sql->nresultcols;
825 if (total > SQL_FIELD_MAX)
826 { xprintf("db_iodbc_open: Too many fields (> %d) in query.\n"
827 "\"%s\"\n", SQL_FIELD_MAX, sql->query);
828 dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt);
829 dl_SQLDisconnect(sql->hdbc);
830 dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc);
831 dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv);
835 for (i = 1; i <= total; i++)
836 { /* return a set of attributes for a column */
837 ret = dl_SQLDescribeCol(sql->hstmt, (SQLSMALLINT) i,
838 sql->colname[i], SQL_FDLEN_MAX,
839 &colnamelen, &(sql->coltype[i]), &(sql->collen[i]), &scale,
841 sql->isnumeric[i] = is_numeric(sql->coltype[i]);
842 /* bind columns to program vars, converting all types to CHAR*/
843 dl_SQLBindCol(sql->hstmt, i, SQL_CHAR, sql->data[i],
844 SQL_FDLEN_MAX, &(sql->outlen[i]));
845 for (j = sql->nf; j >= 1; j--)
846 { if (strcmp(mpl_tab_get_name(dca, j), sql->colname[i]) == 0)
852 else if ( sql->mode == 'W' )
853 { for(j = 0; sqllines[j] != NULL; j++)
855 if ( NULL != strchr(arg, '?') )
858 sql->query = xmalloc( (total+1) * sizeof(char));
859 strcpy (sql->query, arg);
863 sql->query = db_generate_insert_stmt(dca);
865 xprintf("%s\n", sql->query);
870 int db_iodbc_read(TABDCA *dca, void *link)
874 char buf[SQL_FDLEN_MAX+1];
879 sql = (struct db_odbc *) link;
881 xassert(sql != NULL);
882 xassert(sql->mode == 'R');
884 ret=dl_SQLFetch(sql->hstmt);
887 if (ret== SQL_NO_DATA_FOUND)
889 for (i=1; i <= sql->nresultcols; i++)
893 len = sql->outlen[i];
894 if (len != SQL_NULL_DATA)
896 if (len > SQL_FDLEN_MAX)
900 strncpy(buf, (const char *) sql->data[i], len);
902 if (0 != (sql->isnumeric[i]))
903 { strspx(buf); /* remove spaces*/
904 if (str2num(buf, &num) != 0)
905 { xprintf("'%s' cannot be converted to a number.\n",
909 mpl_tab_set_num(dca, sql->ref[i], num);
912 { mpl_tab_set_str(dca, sql->ref[i], strtrim(buf));
920 int db_iodbc_write(TABDCA *dca, void *link)
931 sql = (struct db_odbc *) link;
932 xassert(sql != NULL);
933 xassert(sql->mode == 'W');
935 len = strlen(sql->query);
936 template = (char *) xmalloc( (len + 1) * sizeof(char) );
937 strcpy(template, sql->query);
939 nf = mpl_tab_num_flds(dca);
940 for (k = 1; k <= nf; k++)
941 { switch (mpl_tab_get_type(dca, k))
946 len += db_escaped_string_length(mpl_tab_get_str(dca, k));
953 query = xmalloc( (len + 1 ) * sizeof(char) );
955 for (k = 1, part = strtok (template, "?"); (part != NULL);
956 part = strtok (NULL, "?"), k++)
959 strcat( query, part );
960 switch (mpl_tab_get_type(dca, k))
962 #if 0 /* 02/XI-2010 by xypron */
963 sprintf(num, "%-18g",mpl_tab_get_num(dca, k));
965 sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k));
967 strcat( query, num );
971 db_escape_string( query + strlen(query),
972 mpl_tab_get_str(dca, k) );
981 if (dl_SQLExecDirect(sql->hstmt, (SQLCHAR *) query, SQL_NTS)
984 xprintf("db_iodbc_write: Query\n\"%s\"\nfailed.\n", query);
985 extract_error("SQLExecDirect", sql->hdbc, SQL_HANDLE_DBC);
996 int db_iodbc_close(TABDCA *dca, void *link)
1000 sql = (struct db_odbc *) link;
1001 xassert(sql != NULL);
1003 if ( sql->mode == 'W' )
1004 dl_SQLEndTran(SQL_HANDLE_ENV, sql->henv, SQL_COMMIT);
1005 if ( sql->mode == 'R' )
1006 dl_SQLCloseCursor(sql->hstmt);
1008 dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt);
1009 dl_SQLDisconnect(sql->hdbc);
1010 dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc);
1011 dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv);
1012 if ( sql->mode == 'W' )
1019 static void extract_error(
1031 xprintf("\nThe driver reported the following diagnostics whilst "
1032 "running %s\n", fn);
1036 ret = dl_SQLGetDiagRec(type, handle, ++i, state, &native, text,
1037 sizeof(text), &len );
1038 if (SQL_SUCCEEDED(ret))
1039 xprintf("%s:%ld:%ld:%s\n", state, i, native, text);
1041 while( ret == SQL_SUCCESS );
1044 static int is_numeric(SQLSMALLINT coltype)
1066 /**********************************************************************/
1070 void *db_mysql_open(TABDCA *dca, int mode)
1071 { xassert(dca == dca);
1072 xassert(mode == mode);
1073 xprintf("MySQL table driver not supported\n");
1077 int db_mysql_read(TABDCA *dca, void *link)
1078 { xassert(dca != dca);
1079 xassert(link != link);
1083 int db_mysql_write(TABDCA *dca, void *link)
1084 { xassert(dca != dca);
1085 xassert(link != link);
1089 int db_mysql_close(TABDCA *dca, void *link)
1090 { xassert(dca != dca);
1091 xassert(link != link);
1097 #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__)
1098 #include <windows.h>
1102 #define byte_defined 1
1105 #include <my_global.h>
1111 int mode; /*'R' = Read, 'W' = Write*/
1112 MYSQL *con; /*connection*/
1113 MYSQL_RES *res; /*result*/
1115 /* number of fields in the csv file */
1116 int ref[1+SQL_FIELD_MAX];
1117 /* ref[k] = k', if k-th field of the csv file corresponds to
1118 k'-th field in the table statement; if ref[k] = 0, k-th field
1119 of the csv file is ignored */
1121 /* query generated by db_mysql_open */
1124 void STDCALL dl_mysql_close(MYSQL *sock)
1126 typedef void STDCALL ep_mysql_close(MYSQL *sock);
1129 fn = (ep_mysql_close *) xdlsym(h_mysql, "mysql_close");
1130 xassert(fn != NULL);
1134 const char * STDCALL dl_mysql_error(MYSQL *mysql)
1136 typedef const char * STDCALL ep_mysql_error(MYSQL *mysql);
1139 fn = (ep_mysql_error *) xdlsym(h_mysql, "mysql_error");
1140 xassert(fn != NULL);
1141 return (*fn)(mysql);
1144 MYSQL_FIELD * STDCALL dl_mysql_fetch_fields(MYSQL_RES *res)
1146 typedef MYSQL_FIELD * STDCALL
1147 ep_mysql_fetch_fields(MYSQL_RES *res);
1149 ep_mysql_fetch_fields *fn;
1150 fn = (ep_mysql_fetch_fields *) xdlsym(h_mysql, "mysql_fetch_fields");
1151 xassert(fn != NULL);
1155 unsigned long * STDCALL dl_mysql_fetch_lengths(MYSQL_RES *result)
1157 typedef unsigned long * STDCALL
1158 ep_mysql_fetch_lengths(MYSQL_RES *result);
1160 ep_mysql_fetch_lengths *fn;
1161 fn = (ep_mysql_fetch_lengths *) xdlsym(h_mysql,
1162 "mysql_fetch_lengths");
1163 xassert(fn != NULL);
1164 return (*fn)(result);
1167 MYSQL_ROW STDCALL dl_mysql_fetch_row(MYSQL_RES *result)
1169 typedef MYSQL_ROW STDCALL ep_mysql_fetch_row(MYSQL_RES *result);
1171 ep_mysql_fetch_row *fn;
1172 fn = (ep_mysql_fetch_row *) xdlsym(h_mysql, "mysql_fetch_row");
1173 xassert(fn != NULL);
1174 return (*fn)(result);
1177 unsigned int STDCALL dl_mysql_field_count(MYSQL *mysql)
1179 typedef unsigned int STDCALL ep_mysql_field_count(MYSQL *mysql);
1181 ep_mysql_field_count *fn;
1182 fn = (ep_mysql_field_count *) xdlsym(h_mysql, "mysql_field_count");
1183 xassert(fn != NULL);
1184 return (*fn)(mysql);
1187 MYSQL * STDCALL dl_mysql_init(MYSQL *mysql)
1189 typedef MYSQL * STDCALL ep_mysql_init(MYSQL *mysql);
1192 fn = (ep_mysql_init *) xdlsym(h_mysql, "mysql_init");
1193 xassert(fn != NULL);
1194 return (*fn)(mysql);
1197 unsigned int STDCALL dl_mysql_num_fields(MYSQL_RES *res)
1199 typedef unsigned int STDCALL ep_mysql_num_fields(MYSQL_RES *res);
1201 ep_mysql_num_fields *fn;
1202 fn = (ep_mysql_num_fields *) xdlsym(h_mysql, "mysql_num_fields");
1203 xassert(fn != NULL);
1207 int STDCALL dl_mysql_query(MYSQL *mysql, const char *q)
1209 typedef int STDCALL ep_mysql_query(MYSQL *mysql, const char *q);
1212 fn = (ep_mysql_query *) xdlsym(h_mysql, "mysql_query");
1213 xassert(fn != NULL);
1214 return (*fn)(mysql, q);
1217 MYSQL * STDCALL dl_mysql_real_connect(MYSQL *mysql, const char *host,
1222 const char *unix_socket,
1223 unsigned long clientflag)
1225 typedef MYSQL * STDCALL ep_mysql_real_connect(MYSQL *mysql,
1231 const char *unix_socket,
1232 unsigned long clientflag);
1234 ep_mysql_real_connect *fn;
1235 fn = (ep_mysql_real_connect *) xdlsym(h_mysql,
1236 "mysql_real_connect");
1237 xassert(fn != NULL);
1238 return (*fn)(mysql, host, user, passwd, db, port, unix_socket,
1242 MYSQL_RES * STDCALL dl_mysql_use_result(MYSQL *mysql)
1244 typedef MYSQL_RES * STDCALL ep_mysql_use_result(MYSQL *mysql);
1245 ep_mysql_use_result *fn;
1246 fn = (ep_mysql_use_result *) xdlsym(h_mysql, "mysql_use_result");
1247 xassert(fn != NULL);
1248 return (*fn)(mysql);
1251 /***********************************************************************
1254 * db_mysql_open - open connection to ODBC data base
1258 * #include "glpsql.h"
1259 * void *db_mysql_open(TABDCA *dca, int mode);
1263 * The routine db_mysql_open opens a connection to a MySQL data base.
1264 * It then executes the sql statements passed.
1266 * In the case of table read the SELECT statement is executed.
1268 * In the case of table write the INSERT statement is prepared.
1271 * The routine returns a pointer to data storage area created. */
1273 void *db_mysql_open(TABDCA *dca, int mode)
1277 sqllines = args_concat(dca);
1278 if (sqllines == NULL)
1279 { xprintf("Missing arguments in table statement.\n"
1280 "Please, supply table driver, dsn, and query.\n");
1283 ret = db_mysql_open_int(dca, mode, (const char **) sqllines);
1284 free_buffer(sqllines);
1288 static void *db_mysql_open_int(TABDCA *dca, int mode, const char
1291 struct db_mysql *sql = NULL;
1294 MYSQL_FIELD *fields;
1299 /* "Server=[server_name];Database=[database_name];UID=[username];*/
1300 /* PWD=[password];Port=[port]"*/
1301 char *server = NULL; /* Server */
1302 char *user = NULL; /* UID */
1303 char *password = NULL; /* PWD */
1304 char *database = NULL; /* Database */
1305 unsigned int port = 0; /* Port */
1309 if (libmysql == NULL)
1311 xprintf("No loader for shared MySQL library available\n");
1315 if (h_mysql == NULL)
1317 h_mysql = xdlopen(libmysql);
1318 if (h_mysql == NULL)
1319 { xprintf("unable to open library %s\n", libmysql);
1320 xprintf("%s\n", xerrmsg());
1325 sql = (struct db_mysql *) xmalloc(sizeof(struct db_mysql));
1331 sql->nf = mpl_tab_num_flds(dca);
1333 narg = mpl_tab_num_args(dca);
1335 xprintf("MySQL driver: string list too short \n");
1337 /* get connection string*/
1338 dsn = (char *) mpl_tab_get_arg(dca, 2);
1339 /* copy connection string*/
1342 arg = xmalloc(i * sizeof(char));
1344 /*tokenize connection string*/
1345 for (i = 1, keyword = strtok (arg, "="); (keyword != NULL);
1346 keyword = strtok (NULL, "="), i++)
1348 value = strtok (NULL, ";");
1351 xprintf("db_mysql_open: Missing value for keyword %s\n",
1357 if (0 == strcmp(keyword, "Server"))
1359 else if (0 == strcmp(keyword, "Database"))
1361 else if (0 == strcmp(keyword, "UID"))
1363 else if (0 == strcmp(keyword, "PWD"))
1365 else if (0 == strcmp(keyword, "Port"))
1366 port = (unsigned int) atol(value);
1368 /* Connect to database */
1369 sql->con = dl_mysql_init(NULL);
1370 if (!dl_mysql_real_connect(sql->con, server, user, password, database,
1373 xprintf("db_mysql_open: Connect failed\n");
1374 xprintf("%s\n", dl_mysql_error(sql->con));
1381 for(j = 0; sqllines[j+1] != NULL; j++)
1382 { query = (char *) sqllines[j];
1383 xprintf("%s\n", query);
1384 if (dl_mysql_query(sql->con, query))
1386 xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query);
1387 xprintf("%s\n",dl_mysql_error(sql->con));
1388 dl_mysql_close(sql->con);
1394 if ( sql->mode == 'R' )
1395 { sql->nf = mpl_tab_num_flds(dca);
1396 for(j = 0; sqllines[j] != NULL; j++)
1397 arg = (char *) sqllines[j];
1398 total = strlen(arg);
1399 if (total > 7 && 0 == strncmp(arg, "SELECT ", 7))
1401 total = strlen(arg);
1402 query = xmalloc( (total+1) * sizeof(char));
1403 strcpy (query, arg);
1407 query = db_generate_select_stmt(dca);
1409 xprintf("%s\n", query);
1410 if (dl_mysql_query(sql->con, query))
1412 xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query);
1413 xprintf("%s\n",dl_mysql_error(sql->con));
1414 dl_mysql_close(sql->con);
1420 sql->res = dl_mysql_use_result(sql->con);
1423 /* create references between query results and table fields*/
1424 total = dl_mysql_num_fields(sql->res);
1425 if (total > SQL_FIELD_MAX)
1426 { xprintf("db_mysql_open: Too many fields (> %d) in query.\n"
1427 "\"%s\"\n", SQL_FIELD_MAX, query);
1428 xprintf("%s\n",dl_mysql_error(sql->con));
1429 dl_mysql_close(sql->con);
1434 fields = dl_mysql_fetch_fields(sql->res);
1435 for (i = 1; i <= total; i++)
1437 for (j = sql->nf; j >= 1; j--)
1439 if (strcmp(mpl_tab_get_name(dca, j), fields[i-1].name)
1448 if(dl_mysql_field_count(sql->con) == 0)
1450 xprintf("db_mysql_open: Query was not a SELECT\n\"%s\"\n",
1452 xprintf("%s\n",dl_mysql_error(sql->con));
1459 xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query);
1460 xprintf("%s\n",dl_mysql_error(sql->con));
1467 else if ( sql->mode == 'W' )
1468 { for(j = 0; sqllines[j] != NULL; j++)
1469 arg = (char *) sqllines[j];
1470 if ( NULL != strchr(arg, '?') )
1472 total = strlen(arg);
1473 query = xmalloc( (total+1) * sizeof(char));
1474 strcpy (query, arg);
1477 query = db_generate_insert_stmt(dca);
1479 xprintf("%s\n", query);
1484 int db_mysql_read(TABDCA *dca, void *link)
1485 { struct db_mysql *sql;
1488 unsigned long *lengths;
1489 MYSQL_FIELD *fields;
1492 unsigned long num_fields;
1495 sql = (struct db_mysql *) link;
1497 xassert(sql != NULL);
1498 xassert(sql->mode == 'R');
1499 if (NULL == sql->res)
1501 xprintf("db_mysql_read: no result set available");
1504 if (NULL==(row = (char **)dl_mysql_fetch_row(sql->res))) {
1507 lengths = dl_mysql_fetch_lengths(sql->res);
1508 fields = dl_mysql_fetch_fields(sql->res);
1509 num_fields = dl_mysql_num_fields(sql->res);
1510 for (i=1; i <= num_fields; i++)
1512 if (row[i-1] != NULL)
1513 { len = (size_t) lengths[i-1];
1516 strncpy(buf, (const char *) row[i-1], len);
1518 if (0 != (fields[i-1].flags & NUM_FLAG))
1519 { strspx(buf); /* remove spaces*/
1520 if (str2num(buf, &num) != 0)
1521 { xprintf("'%s' cannot be converted to a number.\n", buf);
1524 if (sql->ref[i] > 0)
1525 mpl_tab_set_num(dca, sql->ref[i], num);
1528 { if (sql->ref[i] > 0)
1529 mpl_tab_set_str(dca, sql->ref[i], strtrim(buf));
1536 int db_mysql_write(TABDCA *dca, void *link)
1538 struct db_mysql *sql;
1547 sql = (struct db_mysql *) link;
1548 xassert(sql != NULL);
1549 xassert(sql->mode == 'W');
1551 len = strlen(sql->query);
1552 template = (char *) xmalloc( (len + 1) * sizeof(char) );
1553 strcpy(template, sql->query);
1555 nf = mpl_tab_num_flds(dca);
1556 for (k = 1; k <= nf; k++)
1557 { switch (mpl_tab_get_type(dca, k))
1562 len += db_escaped_string_length(mpl_tab_get_str(dca, k));
1566 xassert(dca != dca);
1569 query = xmalloc( (len + 1 ) * sizeof(char) );
1571 for (k = 1, part = strtok (template, "?"); (part != NULL);
1572 part = strtok (NULL, "?"), k++)
1575 strcat( query, part );
1576 switch (mpl_tab_get_type(dca, k))
1578 #if 0 /* 02/XI-2010 by xypron */
1579 sprintf(num, "%-18g",mpl_tab_get_num(dca, k));
1581 sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k));
1583 strcat( query, num );
1586 strcat( query, "'");
1587 db_escape_string( query + strlen(query),
1588 mpl_tab_get_str(dca, k) );
1589 strcat( query, "'");
1592 xassert(dca != dca);
1596 strcat(query, part);
1597 if (dl_mysql_query(sql->con, query))
1599 xprintf("db_mysql_write: Query\n\"%s\"\nfailed.\n", query);
1600 xprintf("%s\n",dl_mysql_error(sql->con));
1611 int db_mysql_close(TABDCA *dca, void *link)
1613 struct db_mysql *sql;
1615 sql = (struct db_mysql *) link;
1616 xassert(sql != NULL);
1617 dl_mysql_close(sql->con);
1618 if ( sql->mode == 'W' )