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