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