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