COIN-OR::LEMON - Graph Library

source: lemon-project-template-glpk/deps/glpk/src/glpsql.c @ 9:33de93886c88

subpack-glpk
Last change on this file since 9:33de93886c88 was 9:33de93886c88, checked in by Alpar Juttner <alpar@…>, 13 years ago

Import GLPK 4.47

File size: 45.0 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      /* 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
159static 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
167static 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
187static 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
223static 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
259static 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
309void *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
316int db_iodbc_read(TABDCA *dca, void *link)
317{     xassert(dca != dca);
318      xassert(link != link);
319      return 0;
320}
321
322int db_iodbc_write(TABDCA *dca, void *link)
323{     xassert(dca != dca);
324      xassert(link != link);
325      return 0;
326}
327
328int 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
343struct 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
366SQLRETURN 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
382SQLRETURN 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
404SQLRETURN 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
417SQLRETURN 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
429SQLRETURN 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
456SQLRETURN 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
472SQLRETURN 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
488SQLRETURN 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
500SQLRETURN 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
514SQLRETURN 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
544SQLRETURN 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
571SQLRETURN 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
592SQLRETURN 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
606SQLRETURN 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
624SQLRETURN 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
642static void extract_error(
643   char *fn,
644   SQLHANDLE handle,
645   SQLSMALLINT type);
646
647static 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. */
671void *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
686static 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
879int 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
924int 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
1000int 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
1023static 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
1048static 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
1074void *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
1081int db_mysql_read(TABDCA *dca, void *link)
1082{     xassert(dca != dca);
1083      xassert(link != link);
1084      return 0;
1085}
1086
1087int db_mysql_write(TABDCA *dca, void *link)
1088{     xassert(dca != dca);
1089      xassert(link != link);
1090      return 0;
1091}
1092
1093int 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
1113struct 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
1128void 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
1138const 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
1148MYSQL_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
1159unsigned 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
1171MYSQL_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
1181unsigned 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
1191MYSQL * 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
1201unsigned 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
1211int 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
1221MYSQL * 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
1246MYSQL_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
1277void *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
1292static 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
1488int 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
1540int 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
1615int 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 */
Note: See TracBrowser for help on using the repository browser.