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