lemon-project-template-glpk

diff deps/glpk/src/glpsql.c @ 9:33de93886c88

Import GLPK 4.47
author Alpar Juttner <alpar@cs.elte.hu>
date Sun, 06 Nov 2011 20:59:10 +0100
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/deps/glpk/src/glpsql.c	Sun Nov 06 20:59:10 2011 +0100
     1.3 @@ -0,0 +1,1631 @@
     1.4 +/* glpsql.c */
     1.5 +
     1.6 +/***********************************************************************
     1.7 +*  This code is part of GLPK (GNU Linear Programming Kit).
     1.8 +*
     1.9 +*  Author: Heinrich Schuchardt <xypron.glpk@gmx.de>.
    1.10 +*
    1.11 +*  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
    1.12 +*  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
    1.13 +*  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
    1.14 +*  E-mail: <mao@gnu.org>.
    1.15 +*
    1.16 +*  GLPK is free software: you can redistribute it and/or modify it
    1.17 +*  under the terms of the GNU General Public License as published by
    1.18 +*  the Free Software Foundation, either version 3 of the License, or
    1.19 +*  (at your option) any later version.
    1.20 +*
    1.21 +*  GLPK is distributed in the hope that it will be useful, but WITHOUT
    1.22 +*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    1.23 +*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
    1.24 +*  License for more details.
    1.25 +*
    1.26 +*  You should have received a copy of the GNU General Public License
    1.27 +*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
    1.28 +***********************************************************************/
    1.29 +
    1.30 +#ifdef HAVE_CONFIG_H
    1.31 +#include <config.h>
    1.32 +#endif
    1.33 +
    1.34 +#include "glpmpl.h"
    1.35 +#include "glpsql.h"
    1.36 +
    1.37 +#ifdef ODBC_DLNAME
    1.38 +#define HAVE_ODBC
    1.39 +#define libodbc ODBC_DLNAME
    1.40 +#define h_odbc (get_env_ptr()->h_odbc)
    1.41 +#endif
    1.42 +
    1.43 +#ifdef MYSQL_DLNAME
    1.44 +#define HAVE_MYSQL
    1.45 +#define libmysql MYSQL_DLNAME
    1.46 +#define h_mysql (get_env_ptr()->h_mysql)
    1.47 +#endif
    1.48 +
    1.49 +static void *db_iodbc_open_int(TABDCA *dca, int mode, const char
    1.50 +      **sqllines);
    1.51 +static void *db_mysql_open_int(TABDCA *dca, int mode, const char
    1.52 +      **sqllines);
    1.53 +
    1.54 +/**********************************************************************/
    1.55 +
    1.56 +#if defined(HAVE_ODBC) || defined(HAVE_MYSQL)
    1.57 +
    1.58 +#define SQL_FIELD_MAX 100
    1.59 +/* maximal field count */
    1.60 +
    1.61 +#define SQL_FDLEN_MAX 255
    1.62 +/* maximal field length */
    1.63 +
    1.64 +/***********************************************************************
    1.65 +*  NAME
    1.66 +*
    1.67 +*  args_concat - concatenate arguments
    1.68 +*
    1.69 +*  SYNOPSIS
    1.70 +*
    1.71 +*  static char **args_concat(TABDCA *dca);
    1.72 +*
    1.73 +*  DESCRIPTION
    1.74 +*
    1.75 +*  The arguments passed in dca are SQL statements. A SQL statement may
    1.76 +*  be split over multiple arguments. The last argument of a SQL
    1.77 +*  statement will be terminated with a semilocon. Each SQL statement is
    1.78 +*  merged into a single zero terminated string. Boundaries between
    1.79 +*  arguments are replaced by space.
    1.80 +*
    1.81 +*  RETURNS
    1.82 +*
    1.83 +*  Buffer with SQL statements */
    1.84 +
    1.85 +static char **args_concat(TABDCA *dca)
    1.86 +{
    1.87 +   const char  *arg;
    1.88 +   int          i;
    1.89 +   int          j;
    1.90 +   int          j0;
    1.91 +   int          j1;
    1.92 +   int          len;
    1.93 +   int          lentot;
    1.94 +   int          narg;
    1.95 +   int          nline = 0;
    1.96 +   void        *ret;
    1.97 +   char       **sqllines = NULL;
    1.98 +
    1.99 +   narg = mpl_tab_num_args(dca);
   1.100 +   /* The SQL statements start with argument 3. */
   1.101 +   if (narg < 3)
   1.102 +      return NULL;
   1.103 +   /* Count the SQL statements */
   1.104 +   for (j = 3; j <= narg; j++)
   1.105 +   {
   1.106 +      arg = mpl_tab_get_arg(dca, j);
   1.107 +      len = strlen(arg);
   1.108 +      if (arg[len-1] == ';' || j == narg)
   1.109 +        nline ++;
   1.110 +   }
   1.111 +   /* Allocate string buffer. */
   1.112 +   sqllines = (char **) xmalloc((nline+1) * sizeof(char **));
   1.113 +   /* Join arguments */
   1.114 +   sqllines[0] = NULL;
   1.115 +   j0     = 3;
   1.116 +   i      = 0;
   1.117 +   lentot = 0;
   1.118 +   for (j = 3; j <= narg; j++)
   1.119 +   {
   1.120 +      arg = mpl_tab_get_arg(dca, j);
   1.121 +      len = strlen(arg);
   1.122 +      /* add length of part */
   1.123 +      lentot += len;
   1.124 +      /* add length of space separating parts or 0x00 at end of SQL
   1.125 +         statement */
   1.126 +      lentot++;
   1.127 +      if (arg[len-1] == ';' || j == narg)
   1.128 +      {  /* Join arguments for a single SQL statement */
   1.129 +         sqllines[i] = xmalloc(lentot);
   1.130 +         sqllines[i+1] = NULL;
   1.131 +         sqllines[i][0] = 0x00;
   1.132 +         for (j1 = j0; j1 <= j; j1++)
   1.133 +         {  if(j1>j0)
   1.134 +               strcat(sqllines[i], " ");
   1.135 +            strcat(sqllines[i], mpl_tab_get_arg(dca, j1));
   1.136 +         }
   1.137 +         len = strlen(sqllines[i]);
   1.138 +         if (sqllines[i][len-1] == ';')
   1.139 +            sqllines[i][len-1] = 0x00;
   1.140 +         j0 = j+1;
   1.141 +         i++;
   1.142 +         lentot = 0;
   1.143 +      }
   1.144 +   }
   1.145 +   return sqllines;
   1.146 +}
   1.147 +
   1.148 +/***********************************************************************
   1.149 +*  NAME
   1.150 +*
   1.151 +*  free_buffer - free multiline string buffer
   1.152 +*
   1.153 +*  SYNOPSIS
   1.154 +*
   1.155 +*  static void free_buffer(char **buf);
   1.156 +*
   1.157 +*  DESCRIPTION
   1.158 +*
   1.159 +*  buf is a list of strings terminated by NULL.
   1.160 +*  The memory for the strings and for the list is released. */
   1.161 +
   1.162 +static void free_buffer(char **buf)
   1.163 +{  int i;
   1.164 +
   1.165 +   for(i = 0; buf[i] != NULL; i++)
   1.166 +      xfree(buf[i]);
   1.167 +   xfree(buf);
   1.168 +}
   1.169 +
   1.170 +static int db_escaped_string_length(const char* from)
   1.171 +/* length of escaped string */
   1.172 +{
   1.173 +   int         count;
   1.174 +   const char *pointer;
   1.175 +
   1.176 +    for (pointer = from, count = 0; *pointer != (char) '\0'; pointer++,
   1.177 +         count++)
   1.178 +    {
   1.179 +      switch (*pointer)
   1.180 +      {
   1.181 +         case '\'':
   1.182 +            count++;
   1.183 +            break;
   1.184 +      }
   1.185 +    }
   1.186 +
   1.187 +    return count;
   1.188 +}
   1.189 +
   1.190 +static int db_escape_string (char *to, const char *from)
   1.191 +/* escape string*/
   1.192 +{
   1.193 +   const char *source = from;
   1.194 +   char *target = to;
   1.195 +   unsigned int remaining;
   1.196 +
   1.197 +   remaining = strlen(from);
   1.198 +
   1.199 +   if (to == NULL)
   1.200 +     to = (char *) (from + remaining);
   1.201 +
   1.202 +   while (remaining > 0)
   1.203 +   {
   1.204 +      switch (*source)
   1.205 +      {
   1.206 +         case '\'':
   1.207 +            *target = '\'';
   1.208 +            target++;
   1.209 +            *target = '\'';
   1.210 +            break;
   1.211 +
   1.212 +         default:
   1.213 +            *target = *source;
   1.214 +            }
   1.215 +      source++;
   1.216 +      target++;
   1.217 +      remaining--;
   1.218 +      }
   1.219 +
   1.220 +   /* Write the terminating NUL character. */
   1.221 +   *target = '\0';
   1.222 +
   1.223 +   return target - to;
   1.224 +}
   1.225 +
   1.226 +static char *db_generate_select_stmt(TABDCA *dca)
   1.227 +/* generate select statement */
   1.228 +{
   1.229 +   char        *arg;
   1.230 +   char const  *field;
   1.231 +   char        *query;
   1.232 +   int          j;
   1.233 +   int          narg;
   1.234 +   int          nf;
   1.235 +   int          total;
   1.236 +
   1.237 +   total = 50;
   1.238 +   nf = mpl_tab_num_flds(dca);
   1.239 +   narg = mpl_tab_num_args(dca);
   1.240 +   for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++)
   1.241 +   {
   1.242 +      field = mpl_tab_get_name(dca, j);
   1.243 +      total += strlen(field);
   1.244 +      total += 2;
   1.245 +   }
   1.246 +   arg = (char *) mpl_tab_get_arg(dca, narg);
   1.247 +   total += strlen(arg);
   1.248 +   query = xmalloc( total * sizeof(char));
   1.249 +   strcpy (query, "SELECT ");
   1.250 +   for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++)
   1.251 +   {
   1.252 +      field = mpl_tab_get_name(dca, j);
   1.253 +      strcat(query, field);
   1.254 +      if ( j < nf )
   1.255 +         strcat(query, ", ");
   1.256 +   }
   1.257 +   strcat(query, " FROM ");
   1.258 +   strcat(query, arg);
   1.259 +   return query;
   1.260 +}
   1.261 +
   1.262 +static char *db_generate_insert_stmt(TABDCA *dca)
   1.263 +/* generate insert statement */
   1.264 +{
   1.265 +   char        *arg;
   1.266 +   char const  *field;
   1.267 +   char        *query;
   1.268 +   int          j;
   1.269 +   int          narg;
   1.270 +   int          nf;
   1.271 +   int          total;
   1.272 +
   1.273 +   total = 50;
   1.274 +   nf = mpl_tab_num_flds(dca);
   1.275 +   narg = mpl_tab_num_args(dca);
   1.276 +   for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++)
   1.277 +   {
   1.278 +      field = mpl_tab_get_name(dca, j);
   1.279 +      total += strlen(field);
   1.280 +      total += 5;
   1.281 +   }
   1.282 +   arg = (char *) mpl_tab_get_arg(dca, narg);
   1.283 +   total += strlen(arg);
   1.284 +   query = xmalloc( (total+1) * sizeof(char));
   1.285 +   strcpy (query, "INSERT INTO ");
   1.286 +   strcat(query, arg);
   1.287 +   strcat(query, " ( ");
   1.288 +   for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++)
   1.289 +   {
   1.290 +      field = mpl_tab_get_name(dca, j);
   1.291 +      strcat(query, field);
   1.292 +      if ( j < nf )
   1.293 +         strcat(query, ", ");
   1.294 +   }
   1.295 +   strcat(query, " ) VALUES ( ");
   1.296 +   for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++)
   1.297 +   {
   1.298 +      strcat(query, "?");
   1.299 +      if ( j < nf )
   1.300 +         strcat(query, ", ");
   1.301 +   }
   1.302 +   strcat(query, " )");
   1.303 +   return query;
   1.304 +}
   1.305 +
   1.306 +#endif
   1.307 +
   1.308 +/**********************************************************************/
   1.309 +
   1.310 +#ifndef HAVE_ODBC
   1.311 +
   1.312 +void *db_iodbc_open(TABDCA *dca, int mode)
   1.313 +{     xassert(dca == dca);
   1.314 +      xassert(mode == mode);
   1.315 +      xprintf("iODBC table driver not supported\n");
   1.316 +      return NULL;
   1.317 +}
   1.318 +
   1.319 +int db_iodbc_read(TABDCA *dca, void *link)
   1.320 +{     xassert(dca != dca);
   1.321 +      xassert(link != link);
   1.322 +      return 0;
   1.323 +}
   1.324 +
   1.325 +int db_iodbc_write(TABDCA *dca, void *link)
   1.326 +{     xassert(dca != dca);
   1.327 +      xassert(link != link);
   1.328 +      return 0;
   1.329 +}
   1.330 +
   1.331 +int db_iodbc_close(TABDCA *dca, void *link)
   1.332 +{     xassert(dca != dca);
   1.333 +      xassert(link != link);
   1.334 +      return 0;
   1.335 +}
   1.336 +
   1.337 +#else
   1.338 +
   1.339 +#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__)
   1.340 +#include <windows.h>
   1.341 +#endif
   1.342 +
   1.343 +#include <sql.h>
   1.344 +#include <sqlext.h>
   1.345 +
   1.346 +struct db_odbc
   1.347 +{
   1.348 +   int              mode;         /*'R' = Read, 'W' = Write*/
   1.349 +   SQLHDBC          hdbc;         /*connection handle*/
   1.350 +   SQLHENV          henv;         /*environment handle*/
   1.351 +   SQLHSTMT         hstmt;        /*statement handle*/
   1.352 +   SQLSMALLINT      nresultcols;  /* columns in result*/
   1.353 +   SQLULEN          collen[SQL_FIELD_MAX+1];
   1.354 +   SQLLEN           outlen[SQL_FIELD_MAX+1];
   1.355 +   SQLSMALLINT      coltype[SQL_FIELD_MAX+1];
   1.356 +   SQLCHAR          data[SQL_FIELD_MAX+1][SQL_FDLEN_MAX+1];
   1.357 +   SQLCHAR          colname[SQL_FIELD_MAX+1][SQL_FDLEN_MAX+1];
   1.358 +   int              isnumeric[SQL_FIELD_MAX+1];
   1.359 +   int              nf;
   1.360 +   /* number of fields in the csv file */
   1.361 +   int              ref[1+SQL_FIELD_MAX];
   1.362 +   /* ref[k] = k', if k-th field of the csv file corresponds to
   1.363 +      k'-th field in the table statement; if ref[k] = 0, k-th field
   1.364 +      of the csv file is ignored */
   1.365 +   SQLCHAR         *query;
   1.366 +   /* query generated by db_iodbc_open */
   1.367 +};
   1.368 +
   1.369 +SQLRETURN SQL_API dl_SQLAllocHandle (
   1.370 +   SQLSMALLINT           HandleType,
   1.371 +   SQLHANDLE             InputHandle,
   1.372 +   SQLHANDLE            *OutputHandle)
   1.373 +{
   1.374 +      typedef SQLRETURN SQL_API ep_SQLAllocHandle(
   1.375 +         SQLSMALLINT           HandleType,
   1.376 +         SQLHANDLE             InputHandle,
   1.377 +         SQLHANDLE            *OutputHandle);
   1.378 +
   1.379 +      ep_SQLAllocHandle *fn;
   1.380 +      fn = (ep_SQLAllocHandle *) xdlsym(h_odbc, "SQLAllocHandle");
   1.381 +      xassert(fn != NULL);
   1.382 +      return (*fn)(HandleType, InputHandle, OutputHandle);
   1.383 +}
   1.384 +
   1.385 +SQLRETURN SQL_API dl_SQLBindCol (
   1.386 +   SQLHSTMT              StatementHandle,
   1.387 +   SQLUSMALLINT          ColumnNumber,
   1.388 +   SQLSMALLINT           TargetType,
   1.389 +   SQLPOINTER            TargetValue,
   1.390 +   SQLLEN                BufferLength,
   1.391 +   SQLLEN               *StrLen_or_Ind)
   1.392 +{
   1.393 +      typedef SQLRETURN SQL_API ep_SQLBindCol(
   1.394 +         SQLHSTMT              StatementHandle,
   1.395 +         SQLUSMALLINT          ColumnNumber,
   1.396 +         SQLSMALLINT           TargetType,
   1.397 +         SQLPOINTER            TargetValue,
   1.398 +         SQLLEN                BufferLength,
   1.399 +         SQLLEN               *StrLen_or_Ind);
   1.400 +      ep_SQLBindCol *fn;
   1.401 +      fn = (ep_SQLBindCol *) xdlsym(h_odbc, "SQLBindCol");
   1.402 +      xassert(fn != NULL);
   1.403 +      return (*fn)(StatementHandle, ColumnNumber, TargetType,
   1.404 +         TargetValue, BufferLength, StrLen_or_Ind);
   1.405 +}
   1.406 +
   1.407 +SQLRETURN SQL_API dl_SQLCloseCursor (
   1.408 +   SQLHSTMT              StatementHandle)
   1.409 +{
   1.410 +      typedef SQLRETURN SQL_API ep_SQLCloseCursor (
   1.411 +         SQLHSTMT              StatementHandle);
   1.412 +
   1.413 +      ep_SQLCloseCursor *fn;
   1.414 +      fn = (ep_SQLCloseCursor *) xdlsym(h_odbc, "SQLCloseCursor");
   1.415 +      xassert(fn != NULL);
   1.416 +      return (*fn)(StatementHandle);
   1.417 +}
   1.418 +
   1.419 +
   1.420 +SQLRETURN SQL_API dl_SQLDisconnect (
   1.421 +   SQLHDBC               ConnectionHandle)
   1.422 +{
   1.423 +      typedef SQLRETURN SQL_API ep_SQLDisconnect(
   1.424 +         SQLHDBC               ConnectionHandle);
   1.425 +
   1.426 +      ep_SQLDisconnect *fn;
   1.427 +      fn = (ep_SQLDisconnect *) xdlsym(h_odbc, "SQLDisconnect");
   1.428 +      xassert(fn != NULL);
   1.429 +      return (*fn)(ConnectionHandle);
   1.430 +}
   1.431 +
   1.432 +SQLRETURN SQL_API dl_SQLDriverConnect (
   1.433 +   SQLHDBC               hdbc,
   1.434 +   SQLHWND               hwnd,
   1.435 +   SQLCHAR              *szConnStrIn,
   1.436 +   SQLSMALLINT           cbConnStrIn,
   1.437 +   SQLCHAR              *szConnStrOut,
   1.438 +   SQLSMALLINT           cbConnStrOutMax,
   1.439 +   SQLSMALLINT          *pcbConnStrOut,
   1.440 +   SQLUSMALLINT          fDriverCompletion)
   1.441 +{
   1.442 +      typedef SQLRETURN SQL_API ep_SQLDriverConnect(
   1.443 +         SQLHDBC               hdbc,
   1.444 +         SQLHWND               hwnd,
   1.445 +         SQLCHAR             * szConnStrIn,
   1.446 +         SQLSMALLINT           cbConnStrIn,
   1.447 +         SQLCHAR             * szConnStrOut,
   1.448 +         SQLSMALLINT           cbConnStrOutMax,
   1.449 +         SQLSMALLINT         * pcbConnStrOut,
   1.450 +         SQLUSMALLINT          fDriverCompletion);
   1.451 +
   1.452 +      ep_SQLDriverConnect *fn;
   1.453 +      fn = (ep_SQLDriverConnect *) xdlsym(h_odbc, "SQLDriverConnect");
   1.454 +      xassert(fn != NULL);
   1.455 +      return (*fn)(hdbc, hwnd, szConnStrIn, cbConnStrIn, szConnStrOut,
   1.456 +         cbConnStrOutMax, pcbConnStrOut, fDriverCompletion);
   1.457 +}
   1.458 +
   1.459 +SQLRETURN SQL_API dl_SQLEndTran (
   1.460 +   SQLSMALLINT           HandleType,
   1.461 +   SQLHANDLE             Handle,
   1.462 +   SQLSMALLINT           CompletionType)
   1.463 +{
   1.464 +      typedef SQLRETURN SQL_API ep_SQLEndTran (
   1.465 +         SQLSMALLINT           HandleType,
   1.466 +         SQLHANDLE             Handle,
   1.467 +         SQLSMALLINT           CompletionType);
   1.468 +
   1.469 +      ep_SQLEndTran *fn;
   1.470 +      fn = (ep_SQLEndTran *) xdlsym(h_odbc, "SQLEndTran");
   1.471 +      xassert(fn != NULL);
   1.472 +      return (*fn)(HandleType, Handle, CompletionType);
   1.473 +}
   1.474 +
   1.475 +SQLRETURN SQL_API dl_SQLExecDirect (
   1.476 +   SQLHSTMT              StatementHandle,
   1.477 +   SQLCHAR             * StatementText,
   1.478 +   SQLINTEGER            TextLength)
   1.479 +{
   1.480 +      typedef SQLRETURN SQL_API ep_SQLExecDirect (
   1.481 +         SQLHSTMT              StatementHandle,
   1.482 +         SQLCHAR             * StatementText,
   1.483 +         SQLINTEGER            TextLength);
   1.484 +
   1.485 +      ep_SQLExecDirect *fn;
   1.486 +      fn = (ep_SQLExecDirect *) xdlsym(h_odbc, "SQLExecDirect");
   1.487 +      xassert(fn != NULL);
   1.488 +      return (*fn)(StatementHandle, StatementText, TextLength);
   1.489 +}
   1.490 +
   1.491 +SQLRETURN SQL_API dl_SQLFetch (
   1.492 +   SQLHSTMT              StatementHandle)
   1.493 +{
   1.494 +      typedef SQLRETURN SQL_API ep_SQLFetch (
   1.495 +         SQLHSTMT              StatementHandle);
   1.496 +
   1.497 +      ep_SQLFetch *fn;
   1.498 +      fn = (ep_SQLFetch*) xdlsym(h_odbc, "SQLFetch");
   1.499 +      xassert(fn != NULL);
   1.500 +      return (*fn)(StatementHandle);
   1.501 +}
   1.502 +
   1.503 +SQLRETURN SQL_API dl_SQLFreeHandle (
   1.504 +   SQLSMALLINT           HandleType,
   1.505 +   SQLHANDLE             Handle)
   1.506 +{
   1.507 +      typedef SQLRETURN SQL_API ep_SQLFreeHandle (
   1.508 +         SQLSMALLINT           HandleType,
   1.509 +         SQLHANDLE             Handle);
   1.510 +
   1.511 +      ep_SQLFreeHandle *fn;
   1.512 +      fn = (ep_SQLFreeHandle *) xdlsym(h_odbc, "SQLFreeHandle");
   1.513 +      xassert(fn != NULL);
   1.514 +      return (*fn)(HandleType, Handle);
   1.515 +}
   1.516 +
   1.517 +SQLRETURN SQL_API dl_SQLDescribeCol (
   1.518 +   SQLHSTMT              StatementHandle,
   1.519 +   SQLUSMALLINT          ColumnNumber,
   1.520 +   SQLCHAR             * ColumnName,
   1.521 +   SQLSMALLINT           BufferLength,
   1.522 +   SQLSMALLINT         * NameLength,
   1.523 +   SQLSMALLINT         * DataType,
   1.524 +   SQLULEN             * ColumnSize,
   1.525 +   SQLSMALLINT         * DecimalDigits,
   1.526 +   SQLSMALLINT         * Nullable)
   1.527 +{
   1.528 +      typedef SQLRETURN SQL_API ep_SQLDescribeCol (
   1.529 +         SQLHSTMT              StatementHandle,
   1.530 +         SQLUSMALLINT          ColumnNumber,
   1.531 +         SQLCHAR              *ColumnName,
   1.532 +         SQLSMALLINT           BufferLength,
   1.533 +         SQLSMALLINT          *NameLength,
   1.534 +         SQLSMALLINT          *DataType,
   1.535 +         SQLULEN              *ColumnSize,
   1.536 +         SQLSMALLINT          *DecimalDigits,
   1.537 +         SQLSMALLINT          *Nullable);
   1.538 +
   1.539 +      ep_SQLDescribeCol *fn;
   1.540 +      fn = (ep_SQLDescribeCol *) xdlsym(h_odbc, "SQLDescribeCol");
   1.541 +      xassert(fn != NULL);
   1.542 +      return (*fn)(StatementHandle, ColumnNumber, ColumnName,
   1.543 +         BufferLength, NameLength,
   1.544 +         DataType, ColumnSize, DecimalDigits, Nullable);
   1.545 +}
   1.546 +
   1.547 +SQLRETURN SQL_API dl_SQLGetDiagRec (
   1.548 +   SQLSMALLINT           HandleType,
   1.549 +   SQLHANDLE             Handle,
   1.550 +   SQLSMALLINT           RecNumber,
   1.551 +   SQLCHAR              *Sqlstate,
   1.552 +   SQLINTEGER           *NativeError,
   1.553 +   SQLCHAR              *MessageText,
   1.554 +   SQLSMALLINT           BufferLength,
   1.555 +   SQLSMALLINT          *TextLength)
   1.556 +{
   1.557 +      typedef SQLRETURN SQL_API ep_SQLGetDiagRec (
   1.558 +         SQLSMALLINT           HandleType,
   1.559 +         SQLHANDLE             Handle,
   1.560 +         SQLSMALLINT           RecNumber,
   1.561 +         SQLCHAR              *Sqlstate,
   1.562 +         SQLINTEGER           *NativeError,
   1.563 +         SQLCHAR              *MessageText,
   1.564 +         SQLSMALLINT           BufferLength,
   1.565 +         SQLSMALLINT          *TextLength);
   1.566 +
   1.567 +      ep_SQLGetDiagRec *fn;
   1.568 +      fn = (ep_SQLGetDiagRec *) xdlsym(h_odbc, "SQLGetDiagRec");
   1.569 +      xassert(fn != NULL);
   1.570 +      return (*fn)(HandleType, Handle, RecNumber, Sqlstate,
   1.571 +         NativeError, MessageText, BufferLength, TextLength);
   1.572 +}
   1.573 +
   1.574 +SQLRETURN SQL_API dl_SQLGetInfo (
   1.575 +   SQLHDBC               ConnectionHandle,
   1.576 +   SQLUSMALLINT          InfoType,
   1.577 +   SQLPOINTER            InfoValue,
   1.578 +   SQLSMALLINT           BufferLength,
   1.579 +   SQLSMALLINT          *StringLength)
   1.580 +{
   1.581 +      typedef SQLRETURN SQL_API ep_SQLGetInfo (
   1.582 +         SQLHDBC               ConnectionHandle,
   1.583 +         SQLUSMALLINT          InfoType,
   1.584 +         SQLPOINTER            InfoValue,
   1.585 +         SQLSMALLINT           BufferLength,
   1.586 +         SQLSMALLINT          *StringLength);
   1.587 +
   1.588 +      ep_SQLGetInfo *fn;
   1.589 +      fn = (ep_SQLGetInfo *) xdlsym(h_odbc, "SQLGetInfo");
   1.590 +      xassert(fn != NULL);
   1.591 +      return (*fn)(ConnectionHandle, InfoType, InfoValue, BufferLength,
   1.592 +         StringLength);
   1.593 +}
   1.594 +
   1.595 +SQLRETURN SQL_API dl_SQLNumResultCols (
   1.596 +   SQLHSTMT              StatementHandle,
   1.597 +   SQLSMALLINT          *ColumnCount)
   1.598 +{
   1.599 +      typedef SQLRETURN SQL_API ep_SQLNumResultCols (
   1.600 +         SQLHSTMT              StatementHandle,
   1.601 +         SQLSMALLINT          *ColumnCount);
   1.602 +
   1.603 +      ep_SQLNumResultCols *fn;
   1.604 +      fn = (ep_SQLNumResultCols *) xdlsym(h_odbc, "SQLNumResultCols");
   1.605 +      xassert(fn != NULL);
   1.606 +      return (*fn)(StatementHandle, ColumnCount);
   1.607 +}
   1.608 +
   1.609 +SQLRETURN SQL_API dl_SQLSetConnectAttr (
   1.610 +   SQLHDBC               ConnectionHandle,
   1.611 +   SQLINTEGER            Attribute,
   1.612 +   SQLPOINTER            Value,
   1.613 +   SQLINTEGER            StringLength)
   1.614 +{
   1.615 +      typedef SQLRETURN SQL_API ep_SQLSetConnectAttr (
   1.616 +         SQLHDBC               ConnectionHandle,
   1.617 +         SQLINTEGER            Attribute,
   1.618 +         SQLPOINTER            Value,
   1.619 +         SQLINTEGER            StringLength);
   1.620 +
   1.621 +      ep_SQLSetConnectAttr *fn;
   1.622 +     fn = (ep_SQLSetConnectAttr *) xdlsym(h_odbc, "SQLSetConnectAttr");
   1.623 +      xassert(fn != NULL);
   1.624 +      return (*fn)(ConnectionHandle, Attribute, Value, StringLength);
   1.625 +}
   1.626 +
   1.627 +SQLRETURN SQL_API dl_SQLSetEnvAttr (
   1.628 +   SQLHENV               EnvironmentHandle,
   1.629 +   SQLINTEGER            Attribute,
   1.630 +   SQLPOINTER            Value,
   1.631 +   SQLINTEGER            StringLength)
   1.632 +{
   1.633 +      typedef SQLRETURN SQL_API ep_SQLSetEnvAttr (
   1.634 +         SQLHENV               EnvironmentHandle,
   1.635 +         SQLINTEGER            Attribute,
   1.636 +         SQLPOINTER            Value,
   1.637 +         SQLINTEGER            StringLength);
   1.638 +
   1.639 +      ep_SQLSetEnvAttr *fn;
   1.640 +      fn = (ep_SQLSetEnvAttr *) xdlsym(h_odbc, "SQLSetEnvAttr");
   1.641 +      xassert(fn != NULL);
   1.642 +      return (*fn)(EnvironmentHandle, Attribute, Value, StringLength);
   1.643 +}
   1.644 +
   1.645 +static void extract_error(
   1.646 +   char *fn,
   1.647 +   SQLHANDLE handle,
   1.648 +   SQLSMALLINT type);
   1.649 +
   1.650 +static int is_numeric(
   1.651 +    SQLSMALLINT coltype);
   1.652 +
   1.653 +/***********************************************************************
   1.654 +*  NAME
   1.655 +*
   1.656 +*  db_iodbc_open - open connection to ODBC data base
   1.657 +*
   1.658 +*  SYNOPSIS
   1.659 +*
   1.660 +*  #include "glpsql.h"
   1.661 +*  void *db_iodbc_open(TABDCA *dca, int mode);
   1.662 +*
   1.663 +*  DESCRIPTION
   1.664 +*
   1.665 +*  The routine db_iodbc_open opens a connection to an ODBC data base.
   1.666 +*  It then executes the sql statements passed.
   1.667 +*
   1.668 +*  In the case of table read the SELECT statement is executed.
   1.669 +*
   1.670 +*  In the case of table write the INSERT statement is prepared.
   1.671 +*  RETURNS
   1.672 +*
   1.673 +*  The routine returns a pointer to data storage area created. */
   1.674 +void *db_iodbc_open(TABDCA *dca, int mode)
   1.675 +{  void  *ret;
   1.676 +   char **sqllines;
   1.677 +
   1.678 +   sqllines = args_concat(dca);
   1.679 +   if (sqllines == NULL)
   1.680 +   {  xprintf("Missing arguments in table statement.\n"
   1.681 +              "Please, supply table driver, dsn, and query.\n");
   1.682 +      return NULL;
   1.683 +   }
   1.684 +   ret = db_iodbc_open_int(dca, mode, (const char **) sqllines);
   1.685 +   free_buffer(sqllines);
   1.686 +   return ret;
   1.687 +}
   1.688 +
   1.689 +static void *db_iodbc_open_int(TABDCA *dca, int mode, const char
   1.690 +   **sqllines)
   1.691 +{
   1.692 +   struct db_odbc    *sql;
   1.693 +   SQLRETURN          ret;
   1.694 +   SQLCHAR FAR       *dsn;
   1.695 +   SQLCHAR            info[256];
   1.696 +   SQLSMALLINT        colnamelen;
   1.697 +   SQLSMALLINT        nullable;
   1.698 +   SQLSMALLINT        scale;
   1.699 +   const char        *arg;
   1.700 +   int                narg;
   1.701 +   int                i, j;
   1.702 +   int                total;
   1.703 +
   1.704 +   if (libodbc == NULL)
   1.705 +   {
   1.706 +      xprintf("No loader for shared ODBC library available\n");
   1.707 +      return NULL;
   1.708 +   }
   1.709 +
   1.710 +   if (h_odbc == NULL)
   1.711 +   {
   1.712 +      h_odbc = xdlopen(libodbc);
   1.713 +      if (h_odbc == NULL)
   1.714 +      {  xprintf("unable to open library %s\n", libodbc);
   1.715 +         xprintf("%s\n", xerrmsg());
   1.716 +         return NULL;
   1.717 +      }
   1.718 +   }
   1.719 +
   1.720 +   sql = (struct db_odbc *) xmalloc(sizeof(struct db_odbc));
   1.721 +   if (sql == NULL)
   1.722 +         return NULL;
   1.723 +
   1.724 +   sql->mode  = mode;
   1.725 +   sql->hdbc  = NULL;
   1.726 +   sql->henv  = NULL;
   1.727 +   sql->hstmt = NULL;
   1.728 +   sql->query = NULL;
   1.729 +   narg = mpl_tab_num_args(dca);
   1.730 +
   1.731 +   dsn = (SQLCHAR FAR *) mpl_tab_get_arg(dca, 2);
   1.732 +   /* allocate an environment handle */
   1.733 +   ret = dl_SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE,
   1.734 +      &(sql->henv));
   1.735 +   /* set attribute to enable application to run as ODBC 3.0
   1.736 +      application */
   1.737 +   ret = dl_SQLSetEnvAttr(sql->henv, SQL_ATTR_ODBC_VERSION,
   1.738 +      (void *) SQL_OV_ODBC3, 0);
   1.739 +   /* allocate a connection handle */
   1.740 +   ret = dl_SQLAllocHandle(SQL_HANDLE_DBC, sql->henv, &(sql->hdbc));
   1.741 +   /* connect */
   1.742 +   ret = dl_SQLDriverConnect(sql->hdbc, NULL, dsn, SQL_NTS, NULL, 0,
   1.743 +      NULL, SQL_DRIVER_COMPLETE);
   1.744 +   if (SQL_SUCCEEDED(ret))
   1.745 +   {  /* output information about data base connection */
   1.746 +      xprintf("Connected to ");
   1.747 +      dl_SQLGetInfo(sql->hdbc, SQL_DBMS_NAME, (SQLPOINTER)info,
   1.748 +         sizeof(info), NULL);
   1.749 +      xprintf("%s ", info);
   1.750 +      dl_SQLGetInfo(sql->hdbc, SQL_DBMS_VER, (SQLPOINTER)info,
   1.751 +         sizeof(info), NULL);
   1.752 +      xprintf("%s - ", info);
   1.753 +      dl_SQLGetInfo(sql->hdbc, SQL_DATABASE_NAME, (SQLPOINTER)info,
   1.754 +         sizeof(info), NULL);
   1.755 +      xprintf("%s\n", info);
   1.756 +   }
   1.757 +   else
   1.758 +   {  /* describe error */
   1.759 +      xprintf("Failed to connect\n");
   1.760 +      extract_error("SQLDriverConnect", sql->hdbc, SQL_HANDLE_DBC);
   1.761 +      dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc);
   1.762 +      dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv);
   1.763 +      xfree(sql);
   1.764 +      return NULL;
   1.765 +   }
   1.766 +   /* set AUTOCOMMIT on*/
   1.767 +   ret = dl_SQLSetConnectAttr(sql->hdbc, SQL_ATTR_AUTOCOMMIT,
   1.768 +      (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0);
   1.769 +   /* allocate a statement handle */
   1.770 +   ret = dl_SQLAllocHandle(SQL_HANDLE_STMT, sql->hdbc, &(sql->hstmt));
   1.771 +
   1.772 +   /* initialization queries */
   1.773 +   for(j = 0; sqllines[j+1] != NULL; j++)
   1.774 +   {
   1.775 +      sql->query = (SQLCHAR *) sqllines[j];
   1.776 +      xprintf("%s\n", sql->query);
   1.777 +      ret = dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS);
   1.778 +      switch (ret)
   1.779 +      {
   1.780 +         case SQL_SUCCESS:
   1.781 +         case SQL_SUCCESS_WITH_INFO:
   1.782 +         case SQL_NO_DATA_FOUND:
   1.783 +            break;
   1.784 +         default:
   1.785 +            xprintf("db_iodbc_open: Query\n\"%s\"\nfailed.\n",
   1.786 +               sql->query);
   1.787 +            extract_error("SQLExecDirect", sql->hstmt, SQL_HANDLE_STMT);
   1.788 +            dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt);
   1.789 +            dl_SQLDisconnect(sql->hdbc);
   1.790 +            dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc);
   1.791 +            dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv);
   1.792 +            xfree(sql);
   1.793 +            return NULL;
   1.794 +      }
   1.795 +      /* commit statement */
   1.796 +      dl_SQLEndTran(SQL_HANDLE_ENV, sql->henv, SQL_COMMIT);
   1.797 +   }
   1.798 +
   1.799 +   if ( sql->mode == 'R' )
   1.800 +   {  sql->nf = mpl_tab_num_flds(dca);
   1.801 +      for(j = 0; sqllines[j] != NULL; j++)
   1.802 +         arg = sqllines[j];
   1.803 +      total = strlen(arg);
   1.804 +      if (total > 7 && 0 == strncmp(arg, "SELECT ", 7))
   1.805 +      {
   1.806 +         total = strlen(arg);
   1.807 +         sql->query = xmalloc( (total+1) * sizeof(char));
   1.808 +         strcpy (sql->query, arg);
   1.809 +      }
   1.810 +      else
   1.811 +      {
   1.812 +         sql->query = db_generate_select_stmt(dca);
   1.813 +      }
   1.814 +      xprintf("%s\n", sql->query);
   1.815 +      if (dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS) !=
   1.816 +         SQL_SUCCESS)
   1.817 +      {
   1.818 +         xprintf("db_iodbc_open: Query\n\"%s\"\nfailed.\n", sql->query);
   1.819 +         extract_error("SQLExecDirect", sql->hstmt, SQL_HANDLE_STMT);
   1.820 +         dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt);
   1.821 +         dl_SQLDisconnect(sql->hdbc);
   1.822 +         dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc);
   1.823 +         dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv);
   1.824 +         xfree(sql->query);
   1.825 +            xfree(sql);
   1.826 +         return NULL;
   1.827 +      }
   1.828 +      xfree(sql->query);
   1.829 +      /* determine number of result columns */
   1.830 +      ret = dl_SQLNumResultCols(sql->hstmt, &sql->nresultcols);
   1.831 +      total = sql->nresultcols;
   1.832 +      if (total > SQL_FIELD_MAX)
   1.833 +      {  xprintf("db_iodbc_open: Too many fields (> %d) in query.\n"
   1.834 +            "\"%s\"\n", SQL_FIELD_MAX, sql->query);
   1.835 +         dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt);
   1.836 +         dl_SQLDisconnect(sql->hdbc);
   1.837 +         dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc);
   1.838 +         dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv);
   1.839 +         xfree(sql->query);
   1.840 +         return NULL;
   1.841 +      }
   1.842 +      for (i = 1; i <= total; i++)
   1.843 +      {  /* return a set of attributes for a column */
   1.844 +         ret = dl_SQLDescribeCol(sql->hstmt, (SQLSMALLINT) i,
   1.845 +            sql->colname[i], SQL_FDLEN_MAX,
   1.846 +            &colnamelen, &(sql->coltype[i]), &(sql->collen[i]), &scale,
   1.847 +            &nullable);
   1.848 +         sql->isnumeric[i] = is_numeric(sql->coltype[i]);
   1.849 +         /* bind columns to program vars, converting all types to CHAR*/
   1.850 +         if (sql->isnumeric[i])
   1.851 +         {  dl_SQLBindCol(sql->hstmt, i, SQL_DOUBLE, sql->data[i],
   1.852 +               SQL_FDLEN_MAX, &(sql->outlen[i]));
   1.853 +         } else
   1.854 +         {  dl_SQLBindCol(sql->hstmt, i, SQL_CHAR, sql->data[i],
   1.855 +               SQL_FDLEN_MAX, &(sql->outlen[i]));
   1.856 +         }
   1.857 +         for (j = sql->nf; j >= 1; j--)
   1.858 +         {  if (strcmp(mpl_tab_get_name(dca, j), sql->colname[i]) == 0)
   1.859 +            break;
   1.860 +         }
   1.861 +         sql->ref[i] = j;
   1.862 +      }
   1.863 +   }
   1.864 +   else if ( sql->mode == 'W' )
   1.865 +   {  for(j = 0; sqllines[j] != NULL; j++)
   1.866 +         arg = sqllines[j];
   1.867 +      if (  NULL != strchr(arg, '?') )
   1.868 +      {
   1.869 +         total = strlen(arg);
   1.870 +         sql->query = xmalloc( (total+1) * sizeof(char));
   1.871 +         strcpy (sql->query, arg);
   1.872 +         }
   1.873 +      else
   1.874 +      {
   1.875 +         sql->query = db_generate_insert_stmt(dca);
   1.876 +      }
   1.877 +      xprintf("%s\n", sql->query);
   1.878 +   }
   1.879 +   return sql;
   1.880 +}
   1.881 +
   1.882 +int db_iodbc_read(TABDCA *dca, void *link)
   1.883 +{
   1.884 +   struct db_odbc  *sql;
   1.885 +   SQLRETURN        ret;
   1.886 +   char             buf[SQL_FDLEN_MAX+1];
   1.887 +   int              i;
   1.888 +   int              len;
   1.889 +   double           num;
   1.890 +
   1.891 +   sql = (struct db_odbc *) link;
   1.892 +
   1.893 +   xassert(sql != NULL);
   1.894 +   xassert(sql->mode == 'R');
   1.895 +
   1.896 +   ret=dl_SQLFetch(sql->hstmt);
   1.897 +   if (ret== SQL_ERROR)
   1.898 +      return -1;
   1.899 +   if (ret== SQL_NO_DATA_FOUND)
   1.900 +      return -1; /*EOF*/
   1.901 +   for (i=1; i <= sql->nresultcols; i++)
   1.902 +   {
   1.903 +      if (sql->ref[i] > 0)
   1.904 +      {
   1.905 +         len = sql->outlen[i];
   1.906 +         if (len != SQL_NULL_DATA)
   1.907 +         {
   1.908 +            if (sql->isnumeric[i])
   1.909 +            {  mpl_tab_set_num(dca, sql->ref[i],
   1.910 +                               *((const double *) sql->data[i]));
   1.911 +            }
   1.912 +            else
   1.913 +            {  if (len > SQL_FDLEN_MAX)
   1.914 +                  len = SQL_FDLEN_MAX;
   1.915 +               else if (len < 0)
   1.916 +                  len = 0;
   1.917 +               strncpy(buf, (const char *) sql->data[i], len);
   1.918 +               buf[len] = 0x00;
   1.919 +               mpl_tab_set_str(dca, sql->ref[i], strtrim(buf));
   1.920 +            }
   1.921 +         }
   1.922 +      }
   1.923 +   }
   1.924 +   return 0;
   1.925 +}
   1.926 +
   1.927 +int db_iodbc_write(TABDCA *dca, void *link)
   1.928 +{
   1.929 +   struct db_odbc  *sql;
   1.930 +   char            *part;
   1.931 +   char            *query;
   1.932 +   char            *template;
   1.933 +   char             num[50];
   1.934 +   int              k;
   1.935 +   int              len;
   1.936 +   int              nf;
   1.937 +
   1.938 +   sql = (struct db_odbc *) link;
   1.939 +   xassert(sql != NULL);
   1.940 +   xassert(sql->mode == 'W');
   1.941 +
   1.942 +   len      = strlen(sql->query);
   1.943 +   template = (char *) xmalloc( (len + 1) * sizeof(char) );
   1.944 +   strcpy(template, sql->query);
   1.945 +
   1.946 +   nf = mpl_tab_num_flds(dca);
   1.947 +   for (k = 1; k <= nf; k++)
   1.948 +   {     switch (mpl_tab_get_type(dca, k))
   1.949 +      {  case 'N':
   1.950 +            len += 20;
   1.951 +            break;
   1.952 +         case 'S':
   1.953 +            len += db_escaped_string_length(mpl_tab_get_str(dca, k));
   1.954 +            len += 2;
   1.955 +            break;
   1.956 +              default:
   1.957 +                        xassert(dca != dca);
   1.958 +         }
   1.959 +   }
   1.960 +   query = xmalloc( (len + 1 ) * sizeof(char) );
   1.961 +   query[0] = 0x00;
   1.962 +   for (k = 1, part = strtok (template, "?"); (part != NULL);
   1.963 +      part = strtok (NULL, "?"), k++)
   1.964 +   {
   1.965 +      if (k > nf) break;
   1.966 +      strcat( query, part );
   1.967 +      switch (mpl_tab_get_type(dca, k))
   1.968 +      {  case 'N':
   1.969 +#if 0 /* 02/XI-2010 by xypron */
   1.970 +            sprintf(num, "%-18g",mpl_tab_get_num(dca, k));
   1.971 +#else
   1.972 +            sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k));
   1.973 +#endif
   1.974 +            strcat( query, num );
   1.975 +            break;
   1.976 +         case 'S':
   1.977 +            strcat( query, "'");
   1.978 +            db_escape_string( query + strlen(query),
   1.979 +               mpl_tab_get_str(dca, k) );
   1.980 +            strcat( query, "'");
   1.981 +            break;
   1.982 +              default:
   1.983 +                        xassert(dca != dca);
   1.984 +         }
   1.985 +   }
   1.986 +   if (part != NULL)
   1.987 +      strcat(query, part);
   1.988 +   if (dl_SQLExecDirect(sql->hstmt, (SQLCHAR *) query, SQL_NTS)
   1.989 +      != SQL_SUCCESS)
   1.990 +   {
   1.991 +      xprintf("db_iodbc_write: Query\n\"%s\"\nfailed.\n", query);
   1.992 +      extract_error("SQLExecDirect", sql->hdbc, SQL_HANDLE_DBC);
   1.993 +      xfree(query);
   1.994 +      xfree(template);
   1.995 +      return 1;
   1.996 +      }
   1.997 +
   1.998 +   xfree(query);
   1.999 +   xfree(template);
  1.1000 +   return 0;
  1.1001 +}
  1.1002 +
  1.1003 +int db_iodbc_close(TABDCA *dca, void *link)
  1.1004 +{
  1.1005 +   struct db_odbc *sql;
  1.1006 +
  1.1007 +   sql = (struct db_odbc *) link;
  1.1008 +   xassert(sql != NULL);
  1.1009 +   /* Commit */
  1.1010 +   if ( sql->mode == 'W' )
  1.1011 +      dl_SQLEndTran(SQL_HANDLE_ENV, sql->henv, SQL_COMMIT);
  1.1012 +   if ( sql->mode == 'R' )
  1.1013 +      dl_SQLCloseCursor(sql->hstmt);
  1.1014 +
  1.1015 +   dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt);
  1.1016 +   dl_SQLDisconnect(sql->hdbc);
  1.1017 +   dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc);
  1.1018 +   dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv);
  1.1019 +   if ( sql->mode == 'W' )
  1.1020 +      xfree(sql->query);
  1.1021 +   xfree(sql);
  1.1022 +   dca->link = NULL;
  1.1023 +   return 0;
  1.1024 +}
  1.1025 +
  1.1026 +static void extract_error(
  1.1027 +   char *fn,
  1.1028 +   SQLHANDLE handle,
  1.1029 +   SQLSMALLINT type)
  1.1030 +{
  1.1031 +   SQLINTEGER   i = 0;
  1.1032 +   SQLINTEGER   native;
  1.1033 +   SQLCHAR   state[ 7 ];
  1.1034 +   SQLCHAR   text[256];
  1.1035 +   SQLSMALLINT  len;
  1.1036 +   SQLRETURN    ret;
  1.1037 +
  1.1038 +   xprintf("\nThe driver reported the following diagnostics whilst "
  1.1039 +      "running %s\n", fn);
  1.1040 +
  1.1041 +   do
  1.1042 +   {
  1.1043 +      ret = dl_SQLGetDiagRec(type, handle, ++i, state, &native, text,
  1.1044 +         sizeof(text), &len );
  1.1045 +      if (SQL_SUCCEEDED(ret))
  1.1046 +         xprintf("%s:%ld:%ld:%s\n", state, i, native, text);
  1.1047 +   }
  1.1048 +   while( ret == SQL_SUCCESS );
  1.1049 +}
  1.1050 +
  1.1051 +static int is_numeric(SQLSMALLINT coltype)
  1.1052 +{
  1.1053 +   int ret = 0;
  1.1054 +   switch (coltype)
  1.1055 +   {
  1.1056 +      case SQL_DECIMAL:
  1.1057 +      case SQL_NUMERIC:
  1.1058 +      case SQL_SMALLINT:
  1.1059 +      case SQL_INTEGER:
  1.1060 +      case SQL_REAL:
  1.1061 +      case SQL_FLOAT:
  1.1062 +      case SQL_DOUBLE:
  1.1063 +      case SQL_TINYINT:
  1.1064 +      case SQL_BIGINT:
  1.1065 +         ret = 1;
  1.1066 +         break;
  1.1067 +   }
  1.1068 +   return ret;
  1.1069 +}
  1.1070 +
  1.1071 +#endif
  1.1072 +
  1.1073 +/**********************************************************************/
  1.1074 +
  1.1075 +#ifndef HAVE_MYSQL
  1.1076 +
  1.1077 +void *db_mysql_open(TABDCA *dca, int mode)
  1.1078 +{     xassert(dca == dca);
  1.1079 +      xassert(mode == mode);
  1.1080 +      xprintf("MySQL table driver not supported\n");
  1.1081 +      return NULL;
  1.1082 +}
  1.1083 +
  1.1084 +int db_mysql_read(TABDCA *dca, void *link)
  1.1085 +{     xassert(dca != dca);
  1.1086 +      xassert(link != link);
  1.1087 +      return 0;
  1.1088 +}
  1.1089 +
  1.1090 +int db_mysql_write(TABDCA *dca, void *link)
  1.1091 +{     xassert(dca != dca);
  1.1092 +      xassert(link != link);
  1.1093 +      return 0;
  1.1094 +}
  1.1095 +
  1.1096 +int db_mysql_close(TABDCA *dca, void *link)
  1.1097 +{     xassert(dca != dca);
  1.1098 +      xassert(link != link);
  1.1099 +      return 0;
  1.1100 +}
  1.1101 +
  1.1102 +#else
  1.1103 +
  1.1104 +#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__)
  1.1105 +#include <windows.h>
  1.1106 +#endif
  1.1107 +
  1.1108 +#ifdef __CYGWIN__
  1.1109 +#define byte_defined 1
  1.1110 +#endif
  1.1111 +
  1.1112 +#include <my_global.h>
  1.1113 +#include <my_sys.h>
  1.1114 +#include <mysql.h>
  1.1115 +
  1.1116 +struct db_mysql
  1.1117 +{
  1.1118 +   int              mode;  /*'R' = Read, 'W' = Write*/
  1.1119 +   MYSQL           *con;   /*connection*/
  1.1120 +   MYSQL_RES       *res;    /*result*/
  1.1121 +   int              nf;
  1.1122 +   /* number of fields in the csv file */
  1.1123 +   int              ref[1+SQL_FIELD_MAX];
  1.1124 +   /* ref[k] = k', if k-th field of the csv file corresponds to
  1.1125 +      k'-th field in the table statement; if ref[k] = 0, k-th field
  1.1126 +      of the csv file is ignored */
  1.1127 +   char            *query;
  1.1128 +   /* query generated by db_mysql_open */
  1.1129 +};
  1.1130 +
  1.1131 +void STDCALL dl_mysql_close(MYSQL *sock)
  1.1132 +{
  1.1133 +      typedef void STDCALL ep_mysql_close(MYSQL *sock);
  1.1134 +
  1.1135 +      ep_mysql_close *fn;
  1.1136 +      fn = (ep_mysql_close *) xdlsym(h_mysql, "mysql_close");
  1.1137 +      xassert(fn != NULL);
  1.1138 +      return (*fn)(sock);
  1.1139 +}
  1.1140 +
  1.1141 +const char * STDCALL dl_mysql_error(MYSQL *mysql)
  1.1142 +{
  1.1143 +      typedef const char * STDCALL ep_mysql_error(MYSQL *mysql);
  1.1144 +
  1.1145 +      ep_mysql_error *fn;
  1.1146 +      fn = (ep_mysql_error *) xdlsym(h_mysql, "mysql_error");
  1.1147 +      xassert(fn != NULL);
  1.1148 +      return (*fn)(mysql);
  1.1149 +}
  1.1150 +
  1.1151 +MYSQL_FIELD * STDCALL dl_mysql_fetch_fields(MYSQL_RES *res)
  1.1152 +{
  1.1153 +      typedef MYSQL_FIELD * STDCALL
  1.1154 +         ep_mysql_fetch_fields(MYSQL_RES *res);
  1.1155 +
  1.1156 +      ep_mysql_fetch_fields *fn;
  1.1157 +   fn = (ep_mysql_fetch_fields *) xdlsym(h_mysql, "mysql_fetch_fields");
  1.1158 +      xassert(fn != NULL);
  1.1159 +      return (*fn)(res);
  1.1160 +}
  1.1161 +
  1.1162 +unsigned long * STDCALL dl_mysql_fetch_lengths(MYSQL_RES *result)
  1.1163 +{
  1.1164 +      typedef unsigned long * STDCALL
  1.1165 +         ep_mysql_fetch_lengths(MYSQL_RES *result);
  1.1166 +
  1.1167 +      ep_mysql_fetch_lengths *fn;
  1.1168 +      fn = (ep_mysql_fetch_lengths *) xdlsym(h_mysql,
  1.1169 +         "mysql_fetch_lengths");
  1.1170 +      xassert(fn != NULL);
  1.1171 +      return (*fn)(result);
  1.1172 +}
  1.1173 +
  1.1174 +MYSQL_ROW STDCALL dl_mysql_fetch_row(MYSQL_RES *result)
  1.1175 +{
  1.1176 +      typedef MYSQL_ROW STDCALL ep_mysql_fetch_row(MYSQL_RES *result);
  1.1177 +
  1.1178 +      ep_mysql_fetch_row *fn;
  1.1179 +      fn = (ep_mysql_fetch_row *) xdlsym(h_mysql, "mysql_fetch_row");
  1.1180 +      xassert(fn != NULL);
  1.1181 +      return (*fn)(result);
  1.1182 +}
  1.1183 +
  1.1184 +unsigned int STDCALL dl_mysql_field_count(MYSQL *mysql)
  1.1185 +{
  1.1186 +      typedef unsigned int STDCALL ep_mysql_field_count(MYSQL *mysql);
  1.1187 +
  1.1188 +      ep_mysql_field_count *fn;
  1.1189 +     fn = (ep_mysql_field_count *) xdlsym(h_mysql, "mysql_field_count");
  1.1190 +      xassert(fn != NULL);
  1.1191 +      return (*fn)(mysql);
  1.1192 +}
  1.1193 +
  1.1194 +MYSQL * STDCALL dl_mysql_init(MYSQL *mysql)
  1.1195 +{
  1.1196 +      typedef MYSQL * STDCALL ep_mysql_init(MYSQL *mysql);
  1.1197 +
  1.1198 +      ep_mysql_init *fn;
  1.1199 +      fn = (ep_mysql_init *) xdlsym(h_mysql, "mysql_init");
  1.1200 +      xassert(fn != NULL);
  1.1201 +      return (*fn)(mysql);
  1.1202 +}
  1.1203 +
  1.1204 +unsigned int STDCALL dl_mysql_num_fields(MYSQL_RES *res)
  1.1205 +{
  1.1206 +      typedef unsigned int STDCALL ep_mysql_num_fields(MYSQL_RES *res);
  1.1207 +
  1.1208 +      ep_mysql_num_fields *fn;
  1.1209 +      fn = (ep_mysql_num_fields *) xdlsym(h_mysql, "mysql_num_fields");
  1.1210 +      xassert(fn != NULL);
  1.1211 +      return (*fn)(res);
  1.1212 +}
  1.1213 +
  1.1214 +int STDCALL dl_mysql_query(MYSQL *mysql, const char *q)
  1.1215 +{
  1.1216 +      typedef int STDCALL ep_mysql_query(MYSQL *mysql, const char *q);
  1.1217 +
  1.1218 +      ep_mysql_query *fn;
  1.1219 +      fn = (ep_mysql_query *) xdlsym(h_mysql, "mysql_query");
  1.1220 +      xassert(fn != NULL);
  1.1221 +      return (*fn)(mysql, q);
  1.1222 +}
  1.1223 +
  1.1224 +MYSQL * STDCALL dl_mysql_real_connect(MYSQL *mysql, const char *host,
  1.1225 +                                           const char *user,
  1.1226 +                                           const char *passwd,
  1.1227 +                                           const char *db,
  1.1228 +                                           unsigned int port,
  1.1229 +                                           const char *unix_socket,
  1.1230 +                                           unsigned long clientflag)
  1.1231 +{
  1.1232 +      typedef MYSQL * STDCALL ep_mysql_real_connect(MYSQL *mysql,
  1.1233 +            const char *host,
  1.1234 +            const char *user,
  1.1235 +            const char *passwd,
  1.1236 +            const char *db,
  1.1237 +            unsigned int port,
  1.1238 +            const char *unix_socket,
  1.1239 +            unsigned long clientflag);
  1.1240 +
  1.1241 +      ep_mysql_real_connect *fn;
  1.1242 +      fn = (ep_mysql_real_connect *) xdlsym(h_mysql,
  1.1243 +         "mysql_real_connect");
  1.1244 +      xassert(fn != NULL);
  1.1245 +      return (*fn)(mysql, host, user, passwd, db, port, unix_socket,
  1.1246 +         clientflag);
  1.1247 +}
  1.1248 +
  1.1249 +MYSQL_RES * STDCALL dl_mysql_use_result(MYSQL *mysql)
  1.1250 +{
  1.1251 +      typedef MYSQL_RES * STDCALL ep_mysql_use_result(MYSQL *mysql);
  1.1252 +      ep_mysql_use_result *fn;
  1.1253 +      fn = (ep_mysql_use_result *) xdlsym(h_mysql, "mysql_use_result");
  1.1254 +      xassert(fn != NULL);
  1.1255 +      return (*fn)(mysql);
  1.1256 +}
  1.1257 +
  1.1258 +/***********************************************************************
  1.1259 +*  NAME
  1.1260 +*
  1.1261 +*  db_mysql_open - open connection to ODBC data base
  1.1262 +*
  1.1263 +*  SYNOPSIS
  1.1264 +*
  1.1265 +*  #include "glpsql.h"
  1.1266 +*  void *db_mysql_open(TABDCA *dca, int mode);
  1.1267 +*
  1.1268 +*  DESCRIPTION
  1.1269 +*
  1.1270 +*  The routine db_mysql_open opens a connection to a MySQL data base.
  1.1271 +*  It then executes the sql statements passed.
  1.1272 +*
  1.1273 +*  In the case of table read the SELECT statement is executed.
  1.1274 +*
  1.1275 +*  In the case of table write the INSERT statement is prepared.
  1.1276 +*  RETURNS
  1.1277 +*
  1.1278 +*  The routine returns a pointer to data storage area created. */
  1.1279 +
  1.1280 +void *db_mysql_open(TABDCA *dca, int mode)
  1.1281 +{  void  *ret;
  1.1282 +   char **sqllines;
  1.1283 +
  1.1284 +   sqllines = args_concat(dca);
  1.1285 +   if (sqllines == NULL)
  1.1286 +   {  xprintf("Missing arguments in table statement.\n"
  1.1287 +              "Please, supply table driver, dsn, and query.\n");
  1.1288 +      return NULL;
  1.1289 +   }
  1.1290 +   ret = db_mysql_open_int(dca, mode, (const char **) sqllines);
  1.1291 +   free_buffer(sqllines);
  1.1292 +   return ret;
  1.1293 +}
  1.1294 +
  1.1295 +static void *db_mysql_open_int(TABDCA *dca, int mode, const char
  1.1296 +   **sqllines)
  1.1297 +{
  1.1298 +   struct db_mysql *sql = NULL;
  1.1299 +   char            *arg = NULL;
  1.1300 +   const char      *field;
  1.1301 +   MYSQL_FIELD     *fields;
  1.1302 +   char            *keyword;
  1.1303 +   char            *value;
  1.1304 +   char            *query;
  1.1305 +   char            *dsn;
  1.1306 +/* "Server=[server_name];Database=[database_name];UID=[username];*/
  1.1307 +/* PWD=[password];Port=[port]"*/
  1.1308 +   char            *server   = NULL;        /* Server */
  1.1309 +   char            *user     = NULL;        /* UID */
  1.1310 +   char            *password = NULL;        /* PWD */
  1.1311 +   char            *database = NULL;        /* Database */
  1.1312 +   unsigned int     port = 0;               /* Port */
  1.1313 +   int              narg;
  1.1314 +   int              i, j, total;
  1.1315 +
  1.1316 +   if (libmysql == NULL)
  1.1317 +   {
  1.1318 +      xprintf("No loader for shared MySQL library available\n");
  1.1319 +      return NULL;
  1.1320 +   }
  1.1321 +
  1.1322 +   if (h_mysql == NULL)
  1.1323 +   {
  1.1324 +      h_mysql = xdlopen(libmysql);
  1.1325 +      if (h_mysql == NULL)
  1.1326 +      {  xprintf("unable to open library %s\n", libmysql);
  1.1327 +         xprintf("%s\n", xerrmsg());
  1.1328 +         return NULL;
  1.1329 +      }
  1.1330 +   }
  1.1331 +
  1.1332 +   sql = (struct db_mysql *) xmalloc(sizeof(struct db_mysql));
  1.1333 +   if (sql == NULL)
  1.1334 +         return NULL;
  1.1335 +   sql->mode = mode;
  1.1336 +   sql->res = NULL;
  1.1337 +   sql->query = NULL;
  1.1338 +   sql->nf = mpl_tab_num_flds(dca);
  1.1339 +
  1.1340 +   narg = mpl_tab_num_args(dca);
  1.1341 +   if (narg < 3 )
  1.1342 +      xprintf("MySQL driver: string list too short \n");
  1.1343 +
  1.1344 +   /* get connection string*/
  1.1345 +   dsn = (char *) mpl_tab_get_arg(dca, 2);
  1.1346 +      /* copy connection string*/
  1.1347 +   i = strlen(dsn);
  1.1348 +   i++;
  1.1349 +   arg = xmalloc(i * sizeof(char));
  1.1350 +   strcpy(arg, dsn);
  1.1351 +   /*tokenize connection string*/
  1.1352 +   for (i = 1, keyword = strtok (arg, "="); (keyword != NULL);
  1.1353 +      keyword = strtok (NULL, "="), i++)
  1.1354 +   {
  1.1355 +         value = strtok (NULL, ";");
  1.1356 +      if (value==NULL)
  1.1357 +         {
  1.1358 +            xprintf("db_mysql_open: Missing value for keyword %s\n",
  1.1359 +               keyword);
  1.1360 +            xfree(arg);
  1.1361 +            xfree(sql);
  1.1362 +            return NULL;
  1.1363 +      }
  1.1364 +      if (0 == strcmp(keyword, "Server"))
  1.1365 +            server = value;
  1.1366 +      else if (0 == strcmp(keyword, "Database"))
  1.1367 +             database = value;
  1.1368 +      else if (0 == strcmp(keyword, "UID"))
  1.1369 +             user = value;
  1.1370 +      else if (0 == strcmp(keyword, "PWD"))
  1.1371 +             password = value;
  1.1372 +      else if (0 == strcmp(keyword, "Port"))
  1.1373 +             port = (unsigned int) atol(value);
  1.1374 +   }
  1.1375 +   /* Connect to database */
  1.1376 +   sql->con = dl_mysql_init(NULL);
  1.1377 +  if (!dl_mysql_real_connect(sql->con, server, user, password, database,
  1.1378 +      port, NULL, 0))
  1.1379 +   {
  1.1380 +      xprintf("db_mysql_open: Connect failed\n");
  1.1381 +      xprintf("%s\n", dl_mysql_error(sql->con));
  1.1382 +      xfree(arg);
  1.1383 +      xfree(sql);
  1.1384 +      return NULL;
  1.1385 +   }
  1.1386 +   xfree(arg);
  1.1387 +
  1.1388 +   for(j = 0; sqllines[j+1] != NULL; j++)
  1.1389 +   {  query = (char *) sqllines[j];
  1.1390 +      xprintf("%s\n", query);
  1.1391 +      if (dl_mysql_query(sql->con, query))
  1.1392 +      {
  1.1393 +         xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query);
  1.1394 +         xprintf("%s\n",dl_mysql_error(sql->con));
  1.1395 +         dl_mysql_close(sql->con);
  1.1396 +         xfree(sql);
  1.1397 +         return NULL;
  1.1398 +      }
  1.1399 +   }
  1.1400 +
  1.1401 +   if ( sql->mode == 'R' )
  1.1402 +   {  sql->nf = mpl_tab_num_flds(dca);
  1.1403 +      for(j = 0; sqllines[j] != NULL; j++)
  1.1404 +         arg = (char *) sqllines[j];
  1.1405 +      total = strlen(arg);
  1.1406 +      if (total > 7 && 0 == strncmp(arg, "SELECT ", 7))
  1.1407 +      {
  1.1408 +         total = strlen(arg);
  1.1409 +         query = xmalloc( (total+1) * sizeof(char));
  1.1410 +         strcpy (query, arg);
  1.1411 +      }
  1.1412 +      else
  1.1413 +      {
  1.1414 +         query = db_generate_select_stmt(dca);
  1.1415 +      }
  1.1416 +      xprintf("%s\n", query);
  1.1417 +      if (dl_mysql_query(sql->con, query))
  1.1418 +      {
  1.1419 +         xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query);
  1.1420 +         xprintf("%s\n",dl_mysql_error(sql->con));
  1.1421 +         dl_mysql_close(sql->con);
  1.1422 +         xfree(query);
  1.1423 +         xfree(sql);
  1.1424 +         return NULL;
  1.1425 +      }
  1.1426 +      xfree(query);
  1.1427 +      sql->res = dl_mysql_use_result(sql->con);
  1.1428 +      if (sql->res)
  1.1429 +      {
  1.1430 +         /* create references between query results and table fields*/
  1.1431 +         total = dl_mysql_num_fields(sql->res);
  1.1432 +         if (total > SQL_FIELD_MAX)
  1.1433 +         {  xprintf("db_mysql_open: Too many fields (> %d) in query.\n"
  1.1434 +               "\"%s\"\n", SQL_FIELD_MAX, query);
  1.1435 +            xprintf("%s\n",dl_mysql_error(sql->con));
  1.1436 +            dl_mysql_close(sql->con);
  1.1437 +            xfree(query);
  1.1438 +                 xfree(sql);
  1.1439 +            return NULL;
  1.1440 +         }
  1.1441 +         fields = dl_mysql_fetch_fields(sql->res);
  1.1442 +         for (i = 1; i <= total; i++)
  1.1443 +         {
  1.1444 +               for (j = sql->nf; j >= 1; j--)
  1.1445 +            {
  1.1446 +               if (strcmp(mpl_tab_get_name(dca, j), fields[i-1].name)
  1.1447 +                  == 0)
  1.1448 +               break;
  1.1449 +            }
  1.1450 +            sql->ref[i] = j;
  1.1451 +         }
  1.1452 +      }
  1.1453 +      else
  1.1454 +      {
  1.1455 +         if(dl_mysql_field_count(sql->con) == 0)
  1.1456 +            {
  1.1457 +            xprintf("db_mysql_open: Query was not a SELECT\n\"%s\"\n",
  1.1458 +               query);
  1.1459 +            xprintf("%s\n",dl_mysql_error(sql->con));
  1.1460 +            xfree(query);
  1.1461 +            xfree(sql);
  1.1462 +            return NULL;
  1.1463 +         }
  1.1464 +         else
  1.1465 +         {
  1.1466 +            xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query);
  1.1467 +            xprintf("%s\n",dl_mysql_error(sql->con));
  1.1468 +            xfree(query);
  1.1469 +            xfree(sql);
  1.1470 +            return NULL;
  1.1471 +         }
  1.1472 +      }
  1.1473 +   }
  1.1474 +   else if ( sql->mode == 'W' )
  1.1475 +   {  for(j = 0; sqllines[j] != NULL; j++)
  1.1476 +         arg = (char *) sqllines[j];
  1.1477 +      if (  NULL != strchr(arg, '?') )
  1.1478 +      {
  1.1479 +         total = strlen(arg);
  1.1480 +         query = xmalloc( (total+1) * sizeof(char));
  1.1481 +         strcpy (query, arg);
  1.1482 +         }
  1.1483 +      else
  1.1484 +         query = db_generate_insert_stmt(dca);
  1.1485 +      sql->query = query;
  1.1486 +      xprintf("%s\n", query);
  1.1487 +   }
  1.1488 +   return sql;
  1.1489 +}
  1.1490 +
  1.1491 +int db_mysql_read(TABDCA *dca, void *link)
  1.1492 +{  struct db_mysql *sql;
  1.1493 +   char            buf[255+1];
  1.1494 +   char            **row;
  1.1495 +   unsigned long   *lengths;
  1.1496 +   MYSQL_FIELD     *fields;
  1.1497 +   double          num;
  1.1498 +   int             len;
  1.1499 +   unsigned long   num_fields;
  1.1500 +   int             i;
  1.1501 +
  1.1502 +   sql = (struct db_mysql *) link;
  1.1503 +
  1.1504 +   xassert(sql != NULL);
  1.1505 +   xassert(sql->mode == 'R');
  1.1506 +   if (NULL == sql->res)
  1.1507 +   {
  1.1508 +      xprintf("db_mysql_read: no result set available");
  1.1509 +      return 1;
  1.1510 +   }
  1.1511 +   if (NULL==(row = (char **)dl_mysql_fetch_row(sql->res))) {
  1.1512 +       return -1; /*EOF*/
  1.1513 +   }
  1.1514 +   lengths = dl_mysql_fetch_lengths(sql->res);
  1.1515 +   fields = dl_mysql_fetch_fields(sql->res);
  1.1516 +   num_fields = dl_mysql_num_fields(sql->res);
  1.1517 +   for (i=1; i <= num_fields; i++)
  1.1518 +   {
  1.1519 +      if (row[i-1] != NULL)
  1.1520 +      {  len = (size_t) lengths[i-1];
  1.1521 +         if (len > 255)
  1.1522 +            len = 255;
  1.1523 +         strncpy(buf, (const char *) row[i-1], len);
  1.1524 +         buf[len] = 0x00;
  1.1525 +         if (0 != (fields[i-1].flags & NUM_FLAG))
  1.1526 +         {  strspx(buf); /* remove spaces*/
  1.1527 +            if (str2num(buf, &num) != 0)
  1.1528 +            {  xprintf("'%s' cannot be converted to a number.\n", buf);
  1.1529 +               return 1;
  1.1530 +            }
  1.1531 +            if (sql->ref[i] > 0)
  1.1532 +               mpl_tab_set_num(dca, sql->ref[i], num);
  1.1533 +         }
  1.1534 +         else
  1.1535 +         {  if (sql->ref[i] > 0)
  1.1536 +               mpl_tab_set_str(dca, sql->ref[i], strtrim(buf));
  1.1537 +         }
  1.1538 +      }
  1.1539 +   }
  1.1540 +   return 0;
  1.1541 +}
  1.1542 +
  1.1543 +int db_mysql_write(TABDCA *dca, void *link)
  1.1544 +{
  1.1545 +   struct db_mysql *sql;
  1.1546 +   char            *part;
  1.1547 +   char            *query;
  1.1548 +   char            *template;
  1.1549 +   char             num[50];
  1.1550 +   int              k;
  1.1551 +   int              len;
  1.1552 +   int              nf;
  1.1553 +
  1.1554 +   sql = (struct db_mysql *) link;
  1.1555 +   xassert(sql != NULL);
  1.1556 +   xassert(sql->mode == 'W');
  1.1557 +
  1.1558 +   len      = strlen(sql->query);
  1.1559 +   template = (char *) xmalloc( (len + 1) * sizeof(char) );
  1.1560 +   strcpy(template, sql->query);
  1.1561 +
  1.1562 +   nf = mpl_tab_num_flds(dca);
  1.1563 +   for (k = 1; k <= nf; k++)
  1.1564 +   {     switch (mpl_tab_get_type(dca, k))
  1.1565 +      {  case 'N':
  1.1566 +            len += 20;
  1.1567 +            break;
  1.1568 +         case 'S':
  1.1569 +            len += db_escaped_string_length(mpl_tab_get_str(dca, k));
  1.1570 +            len += 2;
  1.1571 +            break;
  1.1572 +              default:
  1.1573 +                        xassert(dca != dca);
  1.1574 +         }
  1.1575 +   }
  1.1576 +   query = xmalloc( (len + 1 ) * sizeof(char) );
  1.1577 +   query[0] = 0x00;
  1.1578 +   for (k = 1, part = strtok (template, "?"); (part != NULL);
  1.1579 +      part = strtok (NULL, "?"), k++)
  1.1580 +   {
  1.1581 +      if (k > nf) break;
  1.1582 +      strcat( query, part );
  1.1583 +      switch (mpl_tab_get_type(dca, k))
  1.1584 +      {  case 'N':
  1.1585 +#if 0 /* 02/XI-2010 by xypron */
  1.1586 +            sprintf(num, "%-18g",mpl_tab_get_num(dca, k));
  1.1587 +#else
  1.1588 +            sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k));
  1.1589 +#endif
  1.1590 +            strcat( query, num );
  1.1591 +            break;
  1.1592 +         case 'S':
  1.1593 +            strcat( query, "'");
  1.1594 +            db_escape_string( query + strlen(query),
  1.1595 +               mpl_tab_get_str(dca, k) );
  1.1596 +            strcat( query, "'");
  1.1597 +            break;
  1.1598 +              default:
  1.1599 +                        xassert(dca != dca);
  1.1600 +         }
  1.1601 +   }
  1.1602 +   if (part != NULL)
  1.1603 +      strcat(query, part);
  1.1604 +   if (dl_mysql_query(sql->con, query))
  1.1605 +   {
  1.1606 +      xprintf("db_mysql_write: Query\n\"%s\"\nfailed.\n", query);
  1.1607 +      xprintf("%s\n",dl_mysql_error(sql->con));
  1.1608 +      xfree(query);
  1.1609 +      xfree(template);
  1.1610 +      return 1;
  1.1611 +      }
  1.1612 +
  1.1613 +   xfree(query);
  1.1614 +   xfree(template);
  1.1615 +   return 0;
  1.1616 +   }
  1.1617 +
  1.1618 +int db_mysql_close(TABDCA *dca, void *link)
  1.1619 +{
  1.1620 +   struct db_mysql *sql;
  1.1621 +
  1.1622 +   sql = (struct db_mysql *) link;
  1.1623 +   xassert(sql != NULL);
  1.1624 +   dl_mysql_close(sql->con);
  1.1625 +   if ( sql->mode == 'W' )
  1.1626 +      xfree(sql->query);
  1.1627 +   xfree(sql);
  1.1628 +   dca->link = NULL;
  1.1629 +   return 0;
  1.1630 +}
  1.1631 +
  1.1632 +#endif
  1.1633 +
  1.1634 +/* eof */