lemon-project-template-glpk

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

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