glpsql.c 45 KB

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