You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1644 lines
45 KiB

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