COIN-OR::LEMON - Graph Library

source: glpk-cmake/src/glpsql.c @ 1:c445c931472f

Last change on this file since 1:c445c931472f was 1:c445c931472f, checked in by Alpar Juttner <alpar@…>, 10 years ago

Import glpk-4.45

  • Generated files and doc/notes are removed
File size: 44.8 KB
Line 
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
46static void *db_iodbc_open_int(TABDCA *dca, int mode, const char
47      **sqllines);
48static 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
82static 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      lentot += len;
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++)
126         {  if(j1>j0)
127               strcat(sqllines[i], " ");
128            strcat(sqllines[i], mpl_tab_get_arg(dca, j1));
129         }
130         len = strlen(sqllines[i]);
131         if (sqllines[i][len-1] == ';')
132            sqllines[i][len-1] = 0x00;
133         j0 = j+1;
134         i++;
135         lentot = 0;
136      }
137   }
138   return sqllines;
139}
140
141/***********************************************************************
142*  NAME
143*
144*  free_buffer - free multiline string buffer
145*
146*  SYNOPSIS
147*
148*  static void free_buffer(char **buf);
149*
150*  DESCRIPTION
151*
152*  buf is a list of strings terminated by NULL.
153*  The memory for the strings and for the list is released. */
154
155static void free_buffer(char **buf)
156{  int i;
157
158   for(i = 0; buf[i] != NULL; i++)
159      xfree(buf[i]);
160   xfree(buf);
161}
162
163static int db_escaped_string_length(const char* from)
164/* length of escaped string */
165{
166   int         count;
167   const char *pointer;
168
169    for (pointer = from, count = 0; *pointer != (char) '\0'; pointer++,
170         count++)
171    {
172      switch (*pointer)
173      {
174         case '\'':
175            count++;
176            break;
177      }
178    }
179
180    return count;
181}
182
183static int db_escape_string (char *to, const char *from)
184/* escape string*/
185{
186   const char *source = from;
187   char *target = to;
188   unsigned int remaining;
189
190   remaining = strlen(from);
191
192   if (to == NULL)
193     to = (char *) (from + remaining);
194
195   while (remaining > 0)
196   {
197      switch (*source)
198      {
199         case '\'':
200            *target = '\'';
201            target++;
202            *target = '\'';
203            break;
204
205         default:
206            *target = *source;
207            }
208      source++;
209      target++;
210      remaining--;
211      }
212
213   /* Write the terminating NUL character. */
214   *target = '\0';
215
216   return target - to;
217}
218
219static char *db_generate_select_stmt(TABDCA *dca)
220/* generate select statement */
221{
222   char        *arg;
223   char const  *field;
224   char        *query;
225   int          j;
226   int          narg;
227   int          nf;
228   int          total;
229
230   total = 50;
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++)
234   {
235      field = mpl_tab_get_name(dca, j);
236      total += strlen(field);
237      total += 2;
238   }
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++)
244   {
245      field = mpl_tab_get_name(dca, j);
246      strcat(query, field);
247      if ( j < nf )
248         strcat(query, ", ");
249   }
250   strcat(query, " FROM ");
251   strcat(query, arg);
252   return query;
253}
254
255static char *db_generate_insert_stmt(TABDCA *dca)
256/* generate insert statement */
257{
258   char        *arg;
259   char const  *field;
260   char        *query;
261   int          j;
262   int          narg;
263   int          nf;
264   int          total;
265
266   total = 50;
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++)
270   {
271      field = mpl_tab_get_name(dca, j);
272      total += strlen(field);
273      total += 5;
274   }
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 ");
279   strcat(query, arg);
280   strcat(query, " ( ");
281   for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++)
282   {
283      field = mpl_tab_get_name(dca, j);
284      strcat(query, field);
285      if ( j < nf )
286         strcat(query, ", ");
287   }
288   strcat(query, " ) VALUES ( ");
289   for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++)
290   {
291      strcat(query, "?");
292      if ( j < nf )
293         strcat(query, ", ");
294   }
295   strcat(query, " )");
296   return query;
297}
298
299#endif
300
301/**********************************************************************/
302
303#ifndef HAVE_ODBC
304
305void *db_iodbc_open(TABDCA *dca, int mode)
306{     xassert(dca == dca);
307      xassert(mode == mode);
308      xprintf("iODBC table driver not supported\n");
309      return NULL;
310}
311
312int db_iodbc_read(TABDCA *dca, void *link)
313{     xassert(dca != dca);
314      xassert(link != link);
315      return 0;
316}
317
318int db_iodbc_write(TABDCA *dca, void *link)
319{     xassert(dca != dca);
320      xassert(link != link);
321      return 0;
322}
323
324int db_iodbc_close(TABDCA *dca, void *link)
325{     xassert(dca != dca);
326      xassert(link != link);
327      return 0;
328}
329
330#else
331
332#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__)
333#include <windows.h>
334#endif
335
336#include <sql.h>
337#include <sqlext.h>
338
339struct db_odbc
340{
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];
352   int              nf;
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 */
358   SQLCHAR         *query;
359   /* query generated by db_iodbc_open */
360};
361
362SQLRETURN SQL_API dl_SQLAllocHandle (
363   SQLSMALLINT           HandleType,
364   SQLHANDLE             InputHandle,
365   SQLHANDLE            *OutputHandle)
366{
367      typedef SQLRETURN SQL_API ep_SQLAllocHandle(
368         SQLSMALLINT           HandleType,
369         SQLHANDLE             InputHandle,
370         SQLHANDLE            *OutputHandle);
371
372      ep_SQLAllocHandle *fn;
373      fn = (ep_SQLAllocHandle *) xdlsym(h_odbc, "SQLAllocHandle");
374      xassert(fn != NULL);
375      return (*fn)(HandleType, InputHandle, OutputHandle);
376}
377
378SQLRETURN SQL_API dl_SQLBindCol (
379   SQLHSTMT              StatementHandle,
380   SQLUSMALLINT          ColumnNumber,
381   SQLSMALLINT           TargetType,
382   SQLPOINTER            TargetValue,
383   SQLLEN                BufferLength,
384   SQLLEN               *StrLen_or_Ind)
385{
386      typedef SQLRETURN SQL_API ep_SQLBindCol(
387         SQLHSTMT              StatementHandle,
388         SQLUSMALLINT          ColumnNumber,
389         SQLSMALLINT           TargetType,
390         SQLPOINTER            TargetValue,
391         SQLLEN                BufferLength,
392         SQLLEN               *StrLen_or_Ind);
393      ep_SQLBindCol *fn;
394      fn = (ep_SQLBindCol *) xdlsym(h_odbc, "SQLBindCol");
395      xassert(fn != NULL);
396      return (*fn)(StatementHandle, ColumnNumber, TargetType,
397         TargetValue, BufferLength, StrLen_or_Ind);
398}
399
400SQLRETURN SQL_API dl_SQLCloseCursor (
401   SQLHSTMT              StatementHandle)
402{
403      typedef SQLRETURN SQL_API ep_SQLCloseCursor (
404         SQLHSTMT              StatementHandle);
405
406      ep_SQLCloseCursor *fn;
407      fn = (ep_SQLCloseCursor *) xdlsym(h_odbc, "SQLCloseCursor");
408      xassert(fn != NULL);
409      return (*fn)(StatementHandle);
410}
411
412
413SQLRETURN SQL_API dl_SQLDisconnect (
414   SQLHDBC               ConnectionHandle)
415{
416      typedef SQLRETURN SQL_API ep_SQLDisconnect(
417         SQLHDBC               ConnectionHandle);
418
419      ep_SQLDisconnect *fn;
420      fn = (ep_SQLDisconnect *) xdlsym(h_odbc, "SQLDisconnect");
421      xassert(fn != NULL);
422      return (*fn)(ConnectionHandle);
423}
424
425SQLRETURN SQL_API dl_SQLDriverConnect (
426   SQLHDBC               hdbc,
427   SQLHWND               hwnd,
428   SQLCHAR              *szConnStrIn,
429   SQLSMALLINT           cbConnStrIn,
430   SQLCHAR              *szConnStrOut,
431   SQLSMALLINT           cbConnStrOutMax,
432   SQLSMALLINT          *pcbConnStrOut,
433   SQLUSMALLINT          fDriverCompletion)
434{
435      typedef SQLRETURN SQL_API ep_SQLDriverConnect(
436         SQLHDBC               hdbc,
437         SQLHWND               hwnd,
438         SQLCHAR             * szConnStrIn,
439         SQLSMALLINT           cbConnStrIn,
440         SQLCHAR             * szConnStrOut,
441         SQLSMALLINT           cbConnStrOutMax,
442         SQLSMALLINT         * pcbConnStrOut,
443         SQLUSMALLINT          fDriverCompletion);
444
445      ep_SQLDriverConnect *fn;
446      fn = (ep_SQLDriverConnect *) xdlsym(h_odbc, "SQLDriverConnect");
447      xassert(fn != NULL);
448      return (*fn)(hdbc, hwnd, szConnStrIn, cbConnStrIn, szConnStrOut,
449         cbConnStrOutMax, pcbConnStrOut, fDriverCompletion);
450}
451
452SQLRETURN SQL_API dl_SQLEndTran (
453   SQLSMALLINT           HandleType,
454   SQLHANDLE             Handle,
455   SQLSMALLINT           CompletionType)
456{
457      typedef SQLRETURN SQL_API ep_SQLEndTran (
458         SQLSMALLINT           HandleType,
459         SQLHANDLE             Handle,
460         SQLSMALLINT           CompletionType);
461
462      ep_SQLEndTran *fn;
463      fn = (ep_SQLEndTran *) xdlsym(h_odbc, "SQLEndTran");
464      xassert(fn != NULL);
465      return (*fn)(HandleType, Handle, CompletionType);
466}
467
468SQLRETURN SQL_API dl_SQLExecDirect (
469   SQLHSTMT              StatementHandle,
470   SQLCHAR             * StatementText,
471   SQLINTEGER            TextLength)
472{
473      typedef SQLRETURN SQL_API ep_SQLExecDirect (
474         SQLHSTMT              StatementHandle,
475         SQLCHAR             * StatementText,
476         SQLINTEGER            TextLength);
477
478      ep_SQLExecDirect *fn;
479      fn = (ep_SQLExecDirect *) xdlsym(h_odbc, "SQLExecDirect");
480      xassert(fn != NULL);
481      return (*fn)(StatementHandle, StatementText, TextLength);
482}
483
484SQLRETURN SQL_API dl_SQLFetch (
485   SQLHSTMT              StatementHandle)
486{
487      typedef SQLRETURN SQL_API ep_SQLFetch (
488         SQLHSTMT              StatementHandle);
489
490      ep_SQLFetch *fn;
491      fn = (ep_SQLFetch*) xdlsym(h_odbc, "SQLFetch");
492      xassert(fn != NULL);
493      return (*fn)(StatementHandle);
494}
495
496SQLRETURN SQL_API dl_SQLFreeHandle (
497   SQLSMALLINT           HandleType,
498   SQLHANDLE             Handle)
499{
500      typedef SQLRETURN SQL_API ep_SQLFreeHandle (
501         SQLSMALLINT           HandleType,
502         SQLHANDLE             Handle);
503
504      ep_SQLFreeHandle *fn;
505      fn = (ep_SQLFreeHandle *) xdlsym(h_odbc, "SQLFreeHandle");
506      xassert(fn != NULL);
507      return (*fn)(HandleType, Handle);
508}
509
510SQLRETURN 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)
520{
521      typedef SQLRETURN SQL_API ep_SQLDescribeCol (
522         SQLHSTMT              StatementHandle,
523         SQLUSMALLINT          ColumnNumber,
524         SQLCHAR              *ColumnName,
525         SQLSMALLINT           BufferLength,
526         SQLSMALLINT          *NameLength,
527         SQLSMALLINT          *DataType,
528         SQLULEN              *ColumnSize,
529         SQLSMALLINT          *DecimalDigits,
530         SQLSMALLINT          *Nullable);
531
532      ep_SQLDescribeCol *fn;
533      fn = (ep_SQLDescribeCol *) xdlsym(h_odbc, "SQLDescribeCol");
534      xassert(fn != NULL);
535      return (*fn)(StatementHandle, ColumnNumber, ColumnName,
536         BufferLength, NameLength,
537         DataType, ColumnSize, DecimalDigits, Nullable);
538}
539
540SQLRETURN SQL_API dl_SQLGetDiagRec (
541   SQLSMALLINT           HandleType,
542   SQLHANDLE             Handle,
543   SQLSMALLINT           RecNumber,
544   SQLCHAR              *Sqlstate,
545   SQLINTEGER           *NativeError,
546   SQLCHAR              *MessageText,
547   SQLSMALLINT           BufferLength,
548   SQLSMALLINT          *TextLength)
549{
550      typedef SQLRETURN SQL_API ep_SQLGetDiagRec (
551         SQLSMALLINT           HandleType,
552         SQLHANDLE             Handle,
553         SQLSMALLINT           RecNumber,
554         SQLCHAR              *Sqlstate,
555         SQLINTEGER           *NativeError,
556         SQLCHAR              *MessageText,
557         SQLSMALLINT           BufferLength,
558         SQLSMALLINT          *TextLength);
559
560      ep_SQLGetDiagRec *fn;
561      fn = (ep_SQLGetDiagRec *) xdlsym(h_odbc, "SQLGetDiagRec");
562      xassert(fn != NULL);
563      return (*fn)(HandleType, Handle, RecNumber, Sqlstate,
564         NativeError, MessageText, BufferLength, TextLength);
565}
566
567SQLRETURN SQL_API dl_SQLGetInfo (
568   SQLHDBC               ConnectionHandle,
569   SQLUSMALLINT          InfoType,
570   SQLPOINTER            InfoValue,
571   SQLSMALLINT           BufferLength,
572   SQLSMALLINT          *StringLength)
573{
574      typedef SQLRETURN SQL_API ep_SQLGetInfo (
575         SQLHDBC               ConnectionHandle,
576         SQLUSMALLINT          InfoType,
577         SQLPOINTER            InfoValue,
578         SQLSMALLINT           BufferLength,
579         SQLSMALLINT          *StringLength);
580
581      ep_SQLGetInfo *fn;
582      fn = (ep_SQLGetInfo *) xdlsym(h_odbc, "SQLGetInfo");
583      xassert(fn != NULL);
584      return (*fn)(ConnectionHandle, InfoType, InfoValue, BufferLength,
585         StringLength);
586}
587
588SQLRETURN SQL_API dl_SQLNumResultCols (
589   SQLHSTMT              StatementHandle,
590   SQLSMALLINT          *ColumnCount)
591{
592      typedef SQLRETURN SQL_API ep_SQLNumResultCols (
593         SQLHSTMT              StatementHandle,
594         SQLSMALLINT          *ColumnCount);
595
596      ep_SQLNumResultCols *fn;
597      fn = (ep_SQLNumResultCols *) xdlsym(h_odbc, "SQLNumResultCols");
598      xassert(fn != NULL);
599      return (*fn)(StatementHandle, ColumnCount);
600}
601
602SQLRETURN SQL_API dl_SQLSetConnectAttr (
603   SQLHDBC               ConnectionHandle,
604   SQLINTEGER            Attribute,
605   SQLPOINTER            Value,
606   SQLINTEGER            StringLength)
607{
608      typedef SQLRETURN SQL_API ep_SQLSetConnectAttr (
609         SQLHDBC               ConnectionHandle,
610         SQLINTEGER            Attribute,
611         SQLPOINTER            Value,
612         SQLINTEGER            StringLength);
613
614      ep_SQLSetConnectAttr *fn;
615     fn = (ep_SQLSetConnectAttr *) xdlsym(h_odbc, "SQLSetConnectAttr");
616      xassert(fn != NULL);
617      return (*fn)(ConnectionHandle, Attribute, Value, StringLength);
618}
619
620SQLRETURN SQL_API dl_SQLSetEnvAttr (
621   SQLHENV               EnvironmentHandle,
622   SQLINTEGER            Attribute,
623   SQLPOINTER            Value,
624   SQLINTEGER            StringLength)
625{
626      typedef SQLRETURN SQL_API ep_SQLSetEnvAttr (
627         SQLHENV               EnvironmentHandle,
628         SQLINTEGER            Attribute,
629         SQLPOINTER            Value,
630         SQLINTEGER            StringLength);
631
632      ep_SQLSetEnvAttr *fn;
633      fn = (ep_SQLSetEnvAttr *) xdlsym(h_odbc, "SQLSetEnvAttr");
634      xassert(fn != NULL);
635      return (*fn)(EnvironmentHandle, Attribute, Value, StringLength);
636}
637
638static void extract_error(
639   char *fn,
640   SQLHANDLE handle,
641   SQLSMALLINT type);
642
643static int is_numeric(
644    SQLSMALLINT coltype);
645
646/***********************************************************************
647*  NAME
648*
649*  db_iodbc_open - open connection to ODBC data base
650*
651*  SYNOPSIS
652*
653*  #include "glpsql.h"
654*  void *db_iodbc_open(TABDCA *dca, int mode);
655*
656*  DESCRIPTION
657*
658*  The routine db_iodbc_open opens a connection to an ODBC data base.
659*  It then executes the sql statements passed.
660*
661*  In the case of table read the SELECT statement is executed.
662*
663*  In the case of table write the INSERT statement is prepared.
664*  RETURNS
665*
666*  The routine returns a pointer to data storage area created. */
667void *db_iodbc_open(TABDCA *dca, int mode)
668{  void  *ret;
669   char **sqllines;
670
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");
675      return NULL;
676   }
677   ret = db_iodbc_open_int(dca, mode, (const char **) sqllines);
678   free_buffer(sqllines);
679   return ret;
680}
681
682static void *db_iodbc_open_int(TABDCA *dca, int mode, const char
683   **sqllines)
684{
685   struct db_odbc    *sql;
686   SQLRETURN          ret;
687   SQLCHAR FAR       *dsn;
688   SQLCHAR            info[256];
689   SQLSMALLINT        colnamelen;
690   SQLSMALLINT        nullable;
691   SQLSMALLINT        scale;
692   const char        *arg;
693   int                narg;
694   int                i, j;
695   int                total;
696
697   if (libodbc == NULL)
698   {
699      xprintf("No loader for shared ODBC library available\n");
700      return NULL;
701   }
702
703   if (h_odbc == NULL)
704   {
705      h_odbc = xdlopen(libodbc);
706      if (h_odbc == NULL)
707      {  xprintf("unable to open library %s\n", libodbc);
708         xprintf("%s\n", xerrmsg());
709         return NULL;
710      }
711   }
712
713   sql = (struct db_odbc *) xmalloc(sizeof(struct db_odbc));
714   if (sql == NULL)
715         return NULL;
716
717   sql->mode  = mode;
718   sql->hdbc  = NULL;
719   sql->henv  = NULL;
720   sql->hstmt = NULL;
721   sql->query = NULL;
722   narg = mpl_tab_num_args(dca);
723
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,
727      &(sql->henv));
728   /* set attribute to enable application to run as ODBC 3.0
729      application */
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));
734   /* connect */
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,
741         sizeof(info), NULL);
742      xprintf("%s ", info);
743      dl_SQLGetInfo(sql->hdbc, SQL_DBMS_VER, (SQLPOINTER)info,
744         sizeof(info), NULL);
745      xprintf("%s - ", info);
746      dl_SQLGetInfo(sql->hdbc, SQL_DATABASE_NAME, (SQLPOINTER)info,
747         sizeof(info), NULL);
748      xprintf("%s\n", info);
749   }
750   else
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);
756      xfree(sql);
757      return NULL;
758   }
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));
764
765   /* initialization queries */
766   for(j = 0; sqllines[j+1] != NULL; j++)
767   {
768      sql->query = (SQLCHAR *) sqllines[j];
769      xprintf("%s\n", sql->query);
770      ret = dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS);
771      switch (ret)
772      {
773         case SQL_SUCCESS:
774         case SQL_SUCCESS_WITH_INFO:
775         case SQL_NO_DATA_FOUND:
776            break;
777         default:
778            xprintf("db_iodbc_open: Query\n\"%s\"\nfailed.\n",
779               sql->query);
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);
785            xfree(sql);
786            return NULL;
787      }
788      /* commit statement */
789      dl_SQLEndTran(SQL_HANDLE_ENV, sql->henv, SQL_COMMIT);
790   }
791
792   if ( sql->mode == 'R' )
793   {  sql->nf = mpl_tab_num_flds(dca);
794      for(j = 0; sqllines[j] != NULL; j++)
795         arg = sqllines[j];
796      total = strlen(arg);
797      if (total > 7 && 0 == strncmp(arg, "SELECT ", 7))
798      {
799         total = strlen(arg);
800         sql->query = xmalloc( (total+1) * sizeof(char));
801         strcpy (sql->query, arg);
802      }
803      else
804      {
805         sql->query = db_generate_select_stmt(dca);
806      }
807      xprintf("%s\n", sql->query);
808      if (dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS) !=
809         SQL_SUCCESS)
810      {
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);
817         xfree(sql->query);
818            xfree(sql);
819         return NULL;
820      }
821      xfree(sql->query);
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);
832         xfree(sql->query);
833         return NULL;
834      }
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,
840            &nullable);
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)
847            break;
848         }
849         sql->ref[i] = j;
850      }
851   }
852   else if ( sql->mode == 'W' )
853   {  for(j = 0; sqllines[j] != NULL; j++)
854         arg = sqllines[j];
855      if (  NULL != strchr(arg, '?') )
856      {
857         total = strlen(arg);
858         sql->query = xmalloc( (total+1) * sizeof(char));
859         strcpy (sql->query, arg);
860         }
861      else
862      {
863         sql->query = db_generate_insert_stmt(dca);
864      }
865      xprintf("%s\n", sql->query);
866   }
867   return sql;
868}
869
870int db_iodbc_read(TABDCA *dca, void *link)
871{
872   struct db_odbc  *sql;
873   SQLRETURN        ret;
874   char             buf[SQL_FDLEN_MAX+1];
875   int              i;
876   int              len;
877   double           num;
878
879   sql = (struct db_odbc *) link;
880
881   xassert(sql != NULL);
882   xassert(sql->mode == 'R');
883
884   ret=dl_SQLFetch(sql->hstmt);
885   if (ret== SQL_ERROR)
886      return -1;
887   if (ret== SQL_NO_DATA_FOUND)
888      return -1; /*EOF*/
889   for (i=1; i <= sql->nresultcols; i++)
890   {
891      if (sql->ref[i] > 0)
892      {
893         len = sql->outlen[i];
894         if (len != SQL_NULL_DATA)
895         {
896            if (len > SQL_FDLEN_MAX)
897               len = SQL_FDLEN_MAX;
898            else if (len < 0)
899               len = 0;
900            strncpy(buf, (const char *) sql->data[i], len);
901            buf[len] = 0x00;
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",
906                     buf);
907                  return 1;
908               }
909               mpl_tab_set_num(dca, sql->ref[i], num);
910            }
911            else
912            {  mpl_tab_set_str(dca, sql->ref[i], strtrim(buf));
913            }
914         }
915      }
916   }
917   return 0;
918}
919
920int db_iodbc_write(TABDCA *dca, void *link)
921{
922   struct db_odbc  *sql;
923   char            *part;
924   char            *query;
925   char            *template;
926   char             num[50];
927   int              k;
928   int              len;
929   int              nf;
930
931   sql = (struct db_odbc *) link;
932   xassert(sql != NULL);
933   xassert(sql->mode == 'W');
934
935   len      = strlen(sql->query);
936   template = (char *) xmalloc( (len + 1) * sizeof(char) );
937   strcpy(template, sql->query);
938
939   nf = mpl_tab_num_flds(dca);
940   for (k = 1; k <= nf; k++)
941   {     switch (mpl_tab_get_type(dca, k))
942      {  case 'N':
943            len += 20;
944            break;
945         case 'S':
946            len += db_escaped_string_length(mpl_tab_get_str(dca, k));
947            len += 2;
948            break;
949              default:
950                        xassert(dca != dca);
951         }
952   }
953   query = xmalloc( (len + 1 ) * sizeof(char) );
954   query[0] = 0x00;
955   for (k = 1, part = strtok (template, "?"); (part != NULL);
956      part = strtok (NULL, "?"), k++)
957   {
958      if (k > nf) break;
959      strcat( query, part );
960      switch (mpl_tab_get_type(dca, k))
961      {  case 'N':
962#if 0 /* 02/XI-2010 by xypron */
963            sprintf(num, "%-18g",mpl_tab_get_num(dca, k));
964#else
965            sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k));
966#endif
967            strcat( query, num );
968            break;
969         case 'S':
970            strcat( query, "'");
971            db_escape_string( query + strlen(query),
972               mpl_tab_get_str(dca, k) );
973            strcat( query, "'");
974            break;
975              default:
976                        xassert(dca != dca);
977         }
978   }
979   if (part != NULL)
980      strcat(query, part);
981   if (dl_SQLExecDirect(sql->hstmt, (SQLCHAR *) query, SQL_NTS)
982      != SQL_SUCCESS)
983   {
984      xprintf("db_iodbc_write: Query\n\"%s\"\nfailed.\n", query);
985      extract_error("SQLExecDirect", sql->hdbc, SQL_HANDLE_DBC);
986      xfree(query);
987      xfree(template);
988      return 1;
989      }
990
991   xfree(query);
992   xfree(template);
993   return 0;
994}
995
996int db_iodbc_close(TABDCA *dca, void *link)
997{
998   struct db_odbc *sql;
999
1000   sql = (struct db_odbc *) link;
1001   xassert(sql != NULL);
1002   /* Commit */
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);
1007
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' )
1013      xfree(sql->query);
1014   xfree(sql);
1015   dca->link = NULL;
1016   return 0;
1017}
1018
1019static void extract_error(
1020   char *fn,
1021   SQLHANDLE handle,
1022   SQLSMALLINT type)
1023{
1024   SQLINTEGER   i = 0;
1025   SQLINTEGER   native;
1026   SQLCHAR   state[ 7 ];
1027   SQLCHAR   text[256];
1028   SQLSMALLINT  len;
1029   SQLRETURN    ret;
1030
1031   xprintf("\nThe driver reported the following diagnostics whilst "
1032      "running %s\n", fn);
1033
1034   do
1035   {
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);
1040   }
1041   while( ret == SQL_SUCCESS );
1042}
1043
1044static int is_numeric(SQLSMALLINT coltype)
1045{
1046   int ret = 0;
1047   switch (coltype)
1048   {
1049      case SQL_DECIMAL:
1050      case SQL_NUMERIC:
1051      case SQL_SMALLINT:
1052      case SQL_INTEGER:
1053      case SQL_REAL:
1054      case SQL_FLOAT:
1055      case SQL_DOUBLE:
1056      case SQL_TINYINT:
1057      case SQL_BIGINT:
1058         ret = 1;
1059         break;
1060   }
1061   return ret;
1062}
1063
1064#endif
1065
1066/**********************************************************************/
1067
1068#ifndef HAVE_MYSQL
1069
1070void *db_mysql_open(TABDCA *dca, int mode)
1071{     xassert(dca == dca);
1072      xassert(mode == mode);
1073      xprintf("MySQL table driver not supported\n");
1074      return NULL;
1075}
1076
1077int db_mysql_read(TABDCA *dca, void *link)
1078{     xassert(dca != dca);
1079      xassert(link != link);
1080      return 0;
1081}
1082
1083int db_mysql_write(TABDCA *dca, void *link)
1084{     xassert(dca != dca);
1085      xassert(link != link);
1086      return 0;
1087}
1088
1089int db_mysql_close(TABDCA *dca, void *link)
1090{     xassert(dca != dca);
1091      xassert(link != link);
1092      return 0;
1093}
1094
1095#else
1096
1097#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__)
1098#include <windows.h>
1099#endif
1100
1101#ifdef __CYGWIN__
1102#define byte_defined 1
1103#endif
1104
1105#include <my_global.h>
1106#include <my_sys.h>
1107#include <mysql.h>
1108
1109struct db_mysql
1110{
1111   int              mode;  /*'R' = Read, 'W' = Write*/
1112   MYSQL           *con;   /*connection*/
1113   MYSQL_RES       *res;    /*result*/
1114   int              nf;
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 */
1120   char            *query;
1121   /* query generated by db_mysql_open */
1122};
1123
1124void STDCALL dl_mysql_close(MYSQL *sock)
1125{
1126      typedef void STDCALL ep_mysql_close(MYSQL *sock);
1127
1128      ep_mysql_close *fn;
1129      fn = (ep_mysql_close *) xdlsym(h_mysql, "mysql_close");
1130      xassert(fn != NULL);
1131      return (*fn)(sock);
1132}
1133
1134const char * STDCALL dl_mysql_error(MYSQL *mysql)
1135{
1136      typedef const char * STDCALL ep_mysql_error(MYSQL *mysql);
1137
1138      ep_mysql_error *fn;
1139      fn = (ep_mysql_error *) xdlsym(h_mysql, "mysql_error");
1140      xassert(fn != NULL);
1141      return (*fn)(mysql);
1142}
1143
1144MYSQL_FIELD * STDCALL dl_mysql_fetch_fields(MYSQL_RES *res)
1145{
1146      typedef MYSQL_FIELD * STDCALL
1147         ep_mysql_fetch_fields(MYSQL_RES *res);
1148
1149      ep_mysql_fetch_fields *fn;
1150   fn = (ep_mysql_fetch_fields *) xdlsym(h_mysql, "mysql_fetch_fields");
1151      xassert(fn != NULL);
1152      return (*fn)(res);
1153}
1154
1155unsigned long * STDCALL dl_mysql_fetch_lengths(MYSQL_RES *result)
1156{
1157      typedef unsigned long * STDCALL
1158         ep_mysql_fetch_lengths(MYSQL_RES *result);
1159
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);
1165}
1166
1167MYSQL_ROW STDCALL dl_mysql_fetch_row(MYSQL_RES *result)
1168{
1169      typedef MYSQL_ROW STDCALL ep_mysql_fetch_row(MYSQL_RES *result);
1170
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);
1175}
1176
1177unsigned int STDCALL dl_mysql_field_count(MYSQL *mysql)
1178{
1179      typedef unsigned int STDCALL ep_mysql_field_count(MYSQL *mysql);
1180
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);
1185}
1186
1187MYSQL * STDCALL dl_mysql_init(MYSQL *mysql)
1188{
1189      typedef MYSQL * STDCALL ep_mysql_init(MYSQL *mysql);
1190
1191      ep_mysql_init *fn;
1192      fn = (ep_mysql_init *) xdlsym(h_mysql, "mysql_init");
1193      xassert(fn != NULL);
1194      return (*fn)(mysql);
1195}
1196
1197unsigned int STDCALL dl_mysql_num_fields(MYSQL_RES *res)
1198{
1199      typedef unsigned int STDCALL ep_mysql_num_fields(MYSQL_RES *res);
1200
1201      ep_mysql_num_fields *fn;
1202      fn = (ep_mysql_num_fields *) xdlsym(h_mysql, "mysql_num_fields");
1203      xassert(fn != NULL);
1204      return (*fn)(res);
1205}
1206
1207int STDCALL dl_mysql_query(MYSQL *mysql, const char *q)
1208{
1209      typedef int STDCALL ep_mysql_query(MYSQL *mysql, const char *q);
1210
1211      ep_mysql_query *fn;
1212      fn = (ep_mysql_query *) xdlsym(h_mysql, "mysql_query");
1213      xassert(fn != NULL);
1214      return (*fn)(mysql, q);
1215}
1216
1217MYSQL * STDCALL dl_mysql_real_connect(MYSQL *mysql, const char *host,
1218                                           const char *user,
1219                                           const char *passwd,
1220                                           const char *db,
1221                                           unsigned int port,
1222                                           const char *unix_socket,
1223                                           unsigned long clientflag)
1224{
1225      typedef MYSQL * STDCALL ep_mysql_real_connect(MYSQL *mysql,
1226            const char *host,
1227            const char *user,
1228            const char *passwd,
1229            const char *db,
1230            unsigned int port,
1231            const char *unix_socket,
1232            unsigned long clientflag);
1233
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,
1239         clientflag);
1240}
1241
1242MYSQL_RES * STDCALL dl_mysql_use_result(MYSQL *mysql)
1243{
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);
1249}
1250
1251/***********************************************************************
1252*  NAME
1253*
1254*  db_mysql_open - open connection to ODBC data base
1255*
1256*  SYNOPSIS
1257*
1258*  #include "glpsql.h"
1259*  void *db_mysql_open(TABDCA *dca, int mode);
1260*
1261*  DESCRIPTION
1262*
1263*  The routine db_mysql_open opens a connection to a MySQL data base.
1264*  It then executes the sql statements passed.
1265*
1266*  In the case of table read the SELECT statement is executed.
1267*
1268*  In the case of table write the INSERT statement is prepared.
1269*  RETURNS
1270*
1271*  The routine returns a pointer to data storage area created. */
1272
1273void *db_mysql_open(TABDCA *dca, int mode)
1274{  void  *ret;
1275   char **sqllines;
1276
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");
1281      return NULL;
1282   }
1283   ret = db_mysql_open_int(dca, mode, (const char **) sqllines);
1284   free_buffer(sqllines);
1285   return ret;
1286}
1287
1288static void *db_mysql_open_int(TABDCA *dca, int mode, const char
1289   **sqllines)
1290{
1291   struct db_mysql *sql = NULL;
1292   char            *arg = NULL;
1293   const char      *field;
1294   MYSQL_FIELD     *fields;
1295   char            *keyword;
1296   char            *value;
1297   char            *query;
1298   char            *dsn;
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 */
1306   int              narg;
1307   int              i, j, total;
1308
1309   if (libmysql == NULL)
1310   {
1311      xprintf("No loader for shared MySQL library available\n");
1312      return NULL;
1313   }
1314
1315   if (h_mysql == NULL)
1316   {
1317      h_mysql = xdlopen(libmysql);
1318      if (h_mysql == NULL)
1319      {  xprintf("unable to open library %s\n", libmysql);
1320         xprintf("%s\n", xerrmsg());
1321         return NULL;
1322      }
1323   }
1324
1325   sql = (struct db_mysql *) xmalloc(sizeof(struct db_mysql));
1326   if (sql == NULL)
1327         return NULL;
1328   sql->mode = mode;
1329   sql->res = NULL;
1330   sql->query = NULL;
1331   sql->nf = mpl_tab_num_flds(dca);
1332
1333   narg = mpl_tab_num_args(dca);
1334   if (narg < 3 )
1335      xprintf("MySQL driver: string list too short \n");
1336
1337   /* get connection string*/
1338   dsn = (char *) mpl_tab_get_arg(dca, 2);
1339      /* copy connection string*/
1340   i = strlen(dsn);
1341   i++;
1342   arg = xmalloc(i * sizeof(char));
1343   strcpy(arg, dsn);
1344   /*tokenize connection string*/
1345   for (i = 1, keyword = strtok (arg, "="); (keyword != NULL);
1346      keyword = strtok (NULL, "="), i++)
1347   {
1348         value = strtok (NULL, ";");
1349      if (value==NULL)
1350         {
1351            xprintf("db_mysql_open: Missing value for keyword %s\n",
1352               keyword);
1353            xfree(arg);
1354            xfree(sql);
1355            return NULL;
1356      }
1357      if (0 == strcmp(keyword, "Server"))
1358            server = value;
1359      else if (0 == strcmp(keyword, "Database"))
1360             database = value;
1361      else if (0 == strcmp(keyword, "UID"))
1362             user = value;
1363      else if (0 == strcmp(keyword, "PWD"))
1364             password = value;
1365      else if (0 == strcmp(keyword, "Port"))
1366             port = (unsigned int) atol(value);
1367   }
1368   /* Connect to database */
1369   sql->con = dl_mysql_init(NULL);
1370  if (!dl_mysql_real_connect(sql->con, server, user, password, database,
1371      port, NULL, 0))
1372   {
1373      xprintf("db_mysql_open: Connect failed\n");
1374      xprintf("%s\n", dl_mysql_error(sql->con));
1375      xfree(arg);
1376      xfree(sql);
1377      return NULL;
1378   }
1379   xfree(arg);
1380
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))
1385      {
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);
1389         xfree(sql);
1390         return NULL;
1391      }
1392   }
1393
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))
1400      {
1401         total = strlen(arg);
1402         query = xmalloc( (total+1) * sizeof(char));
1403         strcpy (query, arg);
1404      }
1405      else
1406      {
1407         query = db_generate_select_stmt(dca);
1408      }
1409      xprintf("%s\n", query);
1410      if (dl_mysql_query(sql->con, query))
1411      {
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);
1415         xfree(query);
1416         xfree(sql);
1417         return NULL;
1418      }
1419      xfree(query);
1420      sql->res = dl_mysql_use_result(sql->con);
1421      if (sql->res)
1422      {
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);
1430            xfree(query);
1431                 xfree(sql);
1432            return NULL;
1433         }
1434         fields = dl_mysql_fetch_fields(sql->res);
1435         for (i = 1; i <= total; i++)
1436         {
1437               for (j = sql->nf; j >= 1; j--)
1438            {
1439               if (strcmp(mpl_tab_get_name(dca, j), fields[i-1].name)
1440                  == 0)
1441               break;
1442            }
1443            sql->ref[i] = j;
1444         }
1445      }
1446      else
1447      {
1448         if(dl_mysql_field_count(sql->con) == 0)
1449            {
1450            xprintf("db_mysql_open: Query was not a SELECT\n\"%s\"\n",
1451               query);
1452            xprintf("%s\n",dl_mysql_error(sql->con));
1453            xfree(query);
1454            xfree(sql);
1455            return NULL;
1456         }
1457         else
1458         {
1459            xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query);
1460            xprintf("%s\n",dl_mysql_error(sql->con));
1461            xfree(query);
1462            xfree(sql);
1463            return NULL;
1464         }
1465      }
1466   }
1467   else if ( sql->mode == 'W' )
1468   {  for(j = 0; sqllines[j] != NULL; j++)
1469         arg = (char *) sqllines[j];
1470      if (  NULL != strchr(arg, '?') )
1471      {
1472         total = strlen(arg);
1473         query = xmalloc( (total+1) * sizeof(char));
1474         strcpy (query, arg);
1475         }
1476      else
1477         query = db_generate_insert_stmt(dca);
1478      sql->query = query;
1479      xprintf("%s\n", query);
1480   }
1481   return sql;
1482}
1483
1484int db_mysql_read(TABDCA *dca, void *link)
1485{  struct db_mysql *sql;
1486   char            buf[255+1];
1487   char            **row;
1488   unsigned long   *lengths;
1489   MYSQL_FIELD     *fields;
1490   double          num;
1491   int             len;
1492   unsigned long   num_fields;
1493   int             i;
1494
1495   sql = (struct db_mysql *) link;
1496
1497   xassert(sql != NULL);
1498   xassert(sql->mode == 'R');
1499   if (NULL == sql->res)
1500   {
1501      xprintf("db_mysql_read: no result set available");
1502      return 1;
1503   }
1504   if (NULL==(row = (char **)dl_mysql_fetch_row(sql->res))) {
1505       return -1; /*EOF*/
1506   }
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++)
1511   {
1512      if (row[i-1] != NULL)
1513      {  len = (size_t) lengths[i-1];
1514         if (len > 255)
1515            len = 255;
1516         strncpy(buf, (const char *) row[i-1], len);
1517         buf[len] = 0x00;
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);
1522               return 1;
1523            }
1524            if (sql->ref[i] > 0)
1525               mpl_tab_set_num(dca, sql->ref[i], num);
1526         }
1527         else
1528         {  if (sql->ref[i] > 0)
1529               mpl_tab_set_str(dca, sql->ref[i], strtrim(buf));
1530         }
1531      }
1532   }
1533   return 0;
1534}
1535
1536int db_mysql_write(TABDCA *dca, void *link)
1537{
1538   struct db_mysql *sql;
1539   char            *part;
1540   char            *query;
1541   char            *template;
1542   char             num[50];
1543   int              k;
1544   int              len;
1545   int              nf;
1546
1547   sql = (struct db_mysql *) link;
1548   xassert(sql != NULL);
1549   xassert(sql->mode == 'W');
1550
1551   len      = strlen(sql->query);
1552   template = (char *) xmalloc( (len + 1) * sizeof(char) );
1553   strcpy(template, sql->query);
1554
1555   nf = mpl_tab_num_flds(dca);
1556   for (k = 1; k <= nf; k++)
1557   {     switch (mpl_tab_get_type(dca, k))
1558      {  case 'N':
1559            len += 20;
1560            break;
1561         case 'S':
1562            len += db_escaped_string_length(mpl_tab_get_str(dca, k));
1563            len += 2;
1564            break;
1565              default:
1566                        xassert(dca != dca);
1567         }
1568   }
1569   query = xmalloc( (len + 1 ) * sizeof(char) );
1570   query[0] = 0x00;
1571   for (k = 1, part = strtok (template, "?"); (part != NULL);
1572      part = strtok (NULL, "?"), k++)
1573   {
1574      if (k > nf) break;
1575      strcat( query, part );
1576      switch (mpl_tab_get_type(dca, k))
1577      {  case 'N':
1578#if 0 /* 02/XI-2010 by xypron */
1579            sprintf(num, "%-18g",mpl_tab_get_num(dca, k));
1580#else
1581            sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k));
1582#endif
1583            strcat( query, num );
1584            break;
1585         case 'S':
1586            strcat( query, "'");
1587            db_escape_string( query + strlen(query),
1588               mpl_tab_get_str(dca, k) );
1589            strcat( query, "'");
1590            break;
1591              default:
1592                        xassert(dca != dca);
1593         }
1594   }
1595   if (part != NULL)
1596      strcat(query, part);
1597   if (dl_mysql_query(sql->con, query))
1598   {
1599      xprintf("db_mysql_write: Query\n\"%s\"\nfailed.\n", query);
1600      xprintf("%s\n",dl_mysql_error(sql->con));
1601      xfree(query);
1602      xfree(template);
1603      return 1;
1604      }
1605
1606   xfree(query);
1607   xfree(template);
1608   return 0;
1609   }
1610
1611int db_mysql_close(TABDCA *dca, void *link)
1612{
1613   struct db_mysql *sql;
1614
1615   sql = (struct db_mysql *) link;
1616   xassert(sql != NULL);
1617   dl_mysql_close(sql->con);
1618   if ( sql->mode == 'W' )
1619      xfree(sql->query);
1620   xfree(sql);
1621   dca->link = NULL;
1622   return 0;
1623}
1624
1625#endif
1626
1627/* eof */
Note: See TracBrowser for help on using the repository browser.