]>
Commit | Line | Data |
---|---|---|
519025e2 | 1 | diff -urN freetds/configure.ac freetds.current/configure.ac |
2 | --- freetds/configure.ac 2008-05-08 00:57:52.000000000 +0200 | |
3 | +++ freetds.current/configure.ac 2008-05-28 15:40:28.000000000 +0200 | |
4 | @@ -1,7 +1,7 @@ | |
5 | dnl Process this file with autoconf to produce a configure script. | |
6 | ||
7 | dnl ------------------------------------------------------------ | |
8 | -dnl $Id$ | |
9 | +dnl $Id$ | |
10 | dnl If you're trying to create a new configure test, try | |
11 | dnl | |
12 | dnl http://autogen.sourceforge.net/conftest.html | |
13 | @@ -240,7 +240,7 @@ | |
14 | ]) | |
15 | AC_CHECK_HEADERS([unistd.h errno.h wchar.h sys/time.h sys/types.h \ | |
16 | sys/param.h sys/stat.h sys/wait.h limits.h locale.h odbcss.h readpassphrase.h \ | |
17 | -signal.h libgen.h poll.h]) | |
18 | +signal.h libgen.h poll.h getopt.h]) | |
19 | if test $tds_mingw = no; then | |
20 | AC_CHECK_HEADERS([sys/socket.h arpa/inet.h netdb.h netinet/in.h \ | |
21 | netinet/tcp.h paths.h sys/ioctl.h langinfo.h]) | |
22 | @@ -347,6 +347,16 @@ | |
23 | ||
24 | TYPE_SOCKLEN_T | |
25 | ||
26 | +AC_MSG_CHECKING([whether getopt has optreset support]) | |
27 | +AC_TRY_LINK([#ifdef HAVE_GETOPT_H | |
28 | +#include <getopt.h> | |
29 | +#endif], [extern int optreset; optreset = 0;], | |
30 | +[AC_MSG_RESULT(yes) | |
31 | +AC_DEFINE(HAVE_GETOPT_OPTRESET, 1, [Define if your getopt(3) defines and uses optreset])], | |
32 | +[AC_MSG_RESULT(no)] | |
33 | +) | |
34 | + | |
35 | + | |
36 | # ------------------------------------------------------------ | |
37 | # Checks for compiler characteristics. | |
38 | # ------------------------------------------------------------ | |
39 | diff -urN freetds/include/cspublic.h freetds.current/include/cspublic.h | |
40 | --- freetds/include/cspublic.h 2007-06-25 11:48:20.000000000 +0200 | |
41 | +++ freetds.current/include/cspublic.h 2008-05-19 16:23:52.000000000 +0200 | |
42 | @@ -34,7 +34,7 @@ | |
43 | #define TDS_STATIC_CAST(type, a) ((type)(a)) | |
44 | #endif | |
45 | ||
46 | -static const char rcsid_cspublic_h[] = "$Id$"; | |
47 | +static const char rcsid_cspublic_h[] = "$Id$"; | |
48 | static const void *const no_unused_cspublic_h_warn[] = { rcsid_cspublic_h, no_unused_cspublic_h_warn }; | |
49 | ||
50 | #define CS_PUBLIC | |
51 | @@ -447,6 +447,9 @@ | |
52 | ||
53 | #define BLK_VERSION_100 CS_VERSION_100 | |
54 | #define BLK_VERSION_110 CS_VERSION_100 | |
55 | +#define BLK_VERSION_120 CS_VERSION_120 | |
56 | +#define BLK_VERSION_125 CS_VERSION_125 | |
57 | +#define BLK_VERSION_150 CS_VERSION_150 | |
58 | ||
59 | #define CS_FORCE_EXIT 300 | |
60 | #define CS_FORCE_CLOSE 301 | |
61 | diff -urN freetds/include/tdsbytes.h freetds.current/include/tdsbytes.h | |
62 | --- freetds/include/tdsbytes.h 2005-08-10 14:06:03.000000000 +0200 | |
63 | +++ freetds.current/include/tdsbytes.h 2008-05-26 14:49:56.000000000 +0200 | |
64 | @@ -20,7 +20,7 @@ | |
65 | #ifndef _tdsbytes_h_ | |
66 | #define _tdsbytes_h_ | |
67 | ||
68 | -/* $Id$ */ | |
69 | +/* $Id$ */ | |
70 | ||
71 | #ifndef _tds_h_ | |
72 | #error tds.h must be included before tdsbytes.h | |
73 | @@ -61,9 +61,9 @@ | |
74 | #define TDS_GET_A2BE(ptr) TDS_GET_UA2BE(ptr) | |
75 | ||
76 | #define TDS_PUT_UA2LE(ptr,val) do {\ | |
77 | - ((TDS_UCHAR*)(ptr))[1] = (val)>>8; ((TDS_UCHAR*)(ptr))[0] = (val); } while(0) | |
78 | + ((TDS_UCHAR*)(ptr))[1] = (TDS_UCHAR)((val)>>8); ((TDS_UCHAR*)(ptr))[0] = (TDS_UCHAR)(val); } while(0) | |
79 | #define TDS_PUT_UA2BE(ptr,val) do {\ | |
80 | - ((TDS_UCHAR*)(ptr))[0] = (val)>>8; ((TDS_UCHAR*)(ptr))[1] = (val); } while(0) | |
81 | + ((TDS_UCHAR*)(ptr))[0] = (TDS_UCHAR)((val)>>8); ((TDS_UCHAR*)(ptr))[1] = (TDS_UCHAR)(val); } while(0) | |
82 | #define TDS_PUT_A2LE(ptr,val) TDS_PUT_UA2LE(ptr,val) | |
83 | #define TDS_PUT_A2BE(ptr,val) TDS_PUT_UA2BE(ptr,val) | |
84 | ||
85 | @@ -78,11 +78,11 @@ | |
86 | #define TDS_GET_A4BE(ptr) TDS_GET_UA4BE(ptr) | |
87 | ||
88 | #define TDS_PUT_UA4LE(ptr,val) do {\ | |
89 | - ((TDS_UCHAR*)(ptr))[3] = (val)>>24; ((TDS_UCHAR*)(ptr))[2] = (val)>>16;\ | |
90 | - ((TDS_UCHAR*)(ptr))[1] = (val)>>8; ((TDS_UCHAR*)(ptr))[0] = (val); } while(0) | |
91 | + ((TDS_UCHAR*)(ptr))[3] = (TDS_UCHAR)((val)>>24); ((TDS_UCHAR*)(ptr))[2] = (TDS_UCHAR)((val)>>16);\ | |
92 | + ((TDS_UCHAR*)(ptr))[1] = (TDS_UCHAR)((val)>>8); ((TDS_UCHAR*)(ptr))[0] = (TDS_UCHAR)(val); } while(0) | |
93 | #define TDS_PUT_UA4BE(ptr,val) do {\ | |
94 | - ((TDS_UCHAR*)(ptr))[0] = (val)>>24; ((TDS_UCHAR*)(ptr))[1] = (val)>>16;\ | |
95 | - ((TDS_UCHAR*)(ptr))[2] = (val)>>8; ((TDS_UCHAR*)(ptr))[3] = (val); } while(0) | |
96 | + ((TDS_UCHAR*)(ptr))[0] = (TDS_UCHAR)((val)>>24); ((TDS_UCHAR*)(ptr))[1] = (TDS_UCHAR)((val)>>16);\ | |
97 | + ((TDS_UCHAR*)(ptr))[2] = (TDS_UCHAR)((val)>>8); ((TDS_UCHAR*)(ptr))[3] = (TDS_UCHAR)(val); } while(0) | |
98 | #define TDS_PUT_A4LE(ptr,val) TDS_PUT_UA4LE(ptr,val) | |
99 | #define TDS_PUT_A4BE(ptr,val) TDS_PUT_UA4BE(ptr,val) | |
100 | ||
101 | diff -urN freetds/include/tds.h freetds.current/include/tds.h | |
102 | --- freetds/include/tds.h 2007-12-27 14:45:22.000000000 +0100 | |
103 | +++ freetds.current/include/tds.h 2008-05-28 00:48:50.000000000 +0200 | |
104 | @@ -20,12 +20,16 @@ | |
105 | #ifndef _tds_h_ | |
106 | #define _tds_h_ | |
107 | ||
108 | -/* $Id$ */ | |
109 | +/* $Id$ */ | |
110 | ||
111 | #include <stdarg.h> | |
112 | #include <stdio.h> | |
113 | #include <time.h> | |
114 | ||
115 | +#if HAVE_ARPA_INET_H | |
116 | +#include <arpa/inet.h> | |
117 | +#endif /* HAVE_ARPA_INET_H */ | |
118 | + | |
119 | /* forward declaration */ | |
120 | typedef struct tdsiconvinfo TDSICONV; | |
121 | typedef struct tds_socket TDSSOCKET; | |
122 | @@ -747,7 +751,7 @@ | |
123 | ||
124 | ||
125 | #define TDS_MAX_CAPABILITY 22 | |
126 | -#define MAXPRECISION 80 | |
127 | +#define MAXPRECISION 77 | |
128 | #define TDS_MAX_CONN 4096 | |
129 | #define TDS_MAX_DYNID_LEN 30 | |
130 | ||
131 | diff -urN freetds/src/apps/freebcp.c freetds.current/src/apps/freebcp.c | |
132 | --- freetds/src/apps/freebcp.c 2006-12-01 22:51:11.000000000 +0100 | |
133 | +++ freetds.current/src/apps/freebcp.c 2008-05-28 22:07:55.000000000 +0200 | |
134 | @@ -45,7 +45,7 @@ | |
135 | #include <sybdb.h> | |
136 | #include "freebcp.h" | |
137 | ||
138 | -static char software_version[] = "$Id$"; | |
139 | +static char software_version[] = "$Id$"; | |
140 | static void *no_unused_var_warn[] = { software_version, no_unused_var_warn }; | |
141 | ||
142 | void pusage(void); | |
143 | @@ -351,6 +351,8 @@ | |
144 | */ | |
145 | ||
146 | login = dblogin(); | |
147 | + if (!login) | |
148 | + return FALSE; | |
149 | ||
150 | DBSETLUSER(login, pdata->user); | |
151 | DBSETLPWD(login, pdata->pass); | |
152 | @@ -372,8 +374,11 @@ | |
153 | ||
154 | if ((*pdbproc = dbopen(login, pdata->server)) == NULL) { | |
155 | fprintf(stderr, "Can't connect to server \"%s\".\n", pdata->server); | |
156 | + dbloginfree(login); | |
157 | return (FALSE); | |
158 | } | |
159 | + dbloginfree(login); | |
160 | + login = NULL; | |
161 | ||
162 | /* set hint if any */ | |
163 | if (pdata->hint) { | |
164 | diff -urN freetds/src/apps/tsql.c freetds.current/src/apps/tsql.c | |
165 | --- freetds/src/apps/tsql.c 2008-01-11 13:46:52.000000000 +0100 | |
166 | +++ freetds.current/src/apps/tsql.c 2008-05-31 10:53:39.000000000 +0200 | |
167 | @@ -85,7 +85,9 @@ | |
168 | #include "tdsconvert.h" | |
169 | #include "replacements.h" | |
170 | ||
171 | -TDS_RCSID(var, "$Id$"); | |
172 | +TDS_RCSID(var, "$Id$"); | |
173 | + | |
174 | +#define TDS_ISSPACE(c) isspace((unsigned char) (c)) | |
175 | ||
176 | enum | |
177 | { | |
178 | @@ -301,6 +303,15 @@ | |
179 | progname, progname); | |
180 | } | |
181 | ||
182 | +static void | |
183 | +reset_getopt(void) | |
184 | +{ | |
185 | +#ifdef HAVE_GETOPT_OPTRESET | |
186 | + optreset = 1; | |
187 | +#endif | |
188 | + optind = 1; | |
189 | +} | |
190 | + | |
191 | /* | |
192 | * The 'GO' command may be followed by options that apply to the batch. | |
193 | * If they don't appear to be right, assume the letters "go" are part of the | |
194 | @@ -324,7 +335,7 @@ | |
195 | s = NULL; | |
196 | ||
197 | *opt_flags = 0; | |
198 | - optind = 0; /* reset getopt */ | |
199 | + reset_getopt(); | |
200 | opterr = 0; /* suppress error messages */ | |
201 | while ((opt = getopt(argc, argv, "fhqtv")) != -1) { | |
202 | switch (opt) { | |
203 | @@ -396,24 +407,24 @@ | |
204 | opt_flags_str = optarg; | |
205 | break; | |
206 | case 'H': | |
207 | - hostname = (char *) malloc(strlen(optarg) + 1); | |
208 | - strcpy(hostname, optarg); | |
209 | + free(hostname); | |
210 | + hostname = strdup(optarg); | |
211 | break; | |
212 | case 'S': | |
213 | - servername = (char *) malloc(strlen(optarg) + 1); | |
214 | - strcpy(servername, optarg); | |
215 | + free(servername); | |
216 | + servername = strdup(optarg); | |
217 | break; | |
218 | case 'U': | |
219 | - username = (char *) malloc(strlen(optarg) + 1); | |
220 | - strcpy(username, optarg); | |
221 | + free(username); | |
222 | + username = strdup(optarg); | |
223 | break; | |
224 | case 'P': | |
225 | - password = (char *) malloc(strlen(optarg) + 1); | |
226 | - strcpy(password, optarg); | |
227 | + free(password); | |
228 | + password = strdup(optarg); | |
229 | break; | |
230 | case 'I': | |
231 | - confile = (char *) malloc(strlen(optarg) + 1); | |
232 | - strcpy(confile, optarg); | |
233 | + free(confile); | |
234 | + confile = strdup(optarg); | |
235 | break; | |
236 | case 'p': | |
237 | port = atoi(optarg); | |
238 | @@ -524,6 +535,7 @@ | |
239 | } | |
240 | ||
241 | /* free up all the memory */ | |
242 | + free(confile); | |
243 | free(hostname); | |
244 | free(username); | |
245 | free(password); | |
246 | @@ -572,6 +584,7 @@ | |
247 | tsql_add_history(s); | |
248 | (*line)++; | |
249 | } | |
250 | + fclose(fp); | |
251 | } | |
252 | ||
253 | extern const char STD_DATETIME_FMT[]; | |
254 | @@ -709,7 +722,7 @@ | |
255 | * The rest of the line may include options that apply to the batch, | |
256 | * and perhaps whitespace. | |
257 | */ | |
258 | - if (0 == strncasecmp(s, "go", 2) && (strlen(s) == 2 || isspace(s[2]))) { | |
259 | + if (0 == strncasecmp(s, "go", 2) && (strlen(s) == 2 || TDS_ISSPACE(s[2]))) { | |
260 | char *go_line = strdup(s); | |
261 | assert(go_line); | |
262 | line = 0; | |
263 | diff -urN freetds/src/dblib/bcp.c freetds.current/src/dblib/bcp.c | |
264 | --- freetds/src/dblib/bcp.c 2008-01-08 16:38:31.000000000 +0100 | |
265 | +++ freetds.current/src/dblib/bcp.c 2008-05-26 14:49:56.000000000 +0200 | |
266 | @@ -71,7 +71,7 @@ | |
267 | } | |
268 | TDS_PBCB; | |
269 | ||
270 | -TDS_RCSID(var, "$Id$"); | |
271 | +TDS_RCSID(var, "$Id$"); | |
272 | ||
273 | #ifdef HAVE_FSEEKO | |
274 | typedef off_t offset_type; | |
275 | @@ -799,11 +799,13 @@ | |
276 | ||
277 | if (dbproc->bcpinfo->direction == DB_QUERYOUT ) { | |
278 | if (tds_submit_query(tds, dbproc->bcpinfo->tablename) == TDS_FAIL) { | |
279 | + fclose(hostfile); | |
280 | return FAIL; | |
281 | } | |
282 | } else { | |
283 | /* TODO quote if needed */ | |
284 | if (tds_submit_queryf(tds, "select * from %s", dbproc->bcpinfo->tablename) == TDS_FAIL) { | |
285 | + fclose(hostfile); | |
286 | return FAIL; | |
287 | } | |
288 | } | |
289 | @@ -1061,6 +1063,7 @@ | |
290 | break; | |
291 | } | |
292 | if( plen != 0 && written != 1 ) { | |
293 | + fclose(hostfile); | |
294 | dbperror(dbproc, SYBEBCWE, errno); | |
295 | return FAIL; | |
296 | } | |
297 | @@ -1073,6 +1076,7 @@ | |
298 | if (buflen > 0) { | |
299 | written = fwrite(hostcol->bcp_column_data->data, buflen, 1, hostfile); | |
300 | if (written < 1) { | |
301 | + fclose(hostfile); | |
302 | dbperror(dbproc, SYBEBCWE, errno); | |
303 | return FAIL; | |
304 | } | |
305 | @@ -1082,6 +1086,7 @@ | |
306 | if (hostcol->terminator && hostcol->term_len > 0) { | |
307 | written = fwrite(hostcol->terminator, hostcol->term_len, 1, hostfile); | |
308 | if (written < 1) { | |
309 | + fclose(hostfile); | |
310 | dbperror(dbproc, SYBEBCWE, errno); | |
311 | return FAIL; | |
312 | } | |
313 | @@ -1094,6 +1099,7 @@ | |
314 | dbperror(dbproc, SYBEBCUC, errno); | |
315 | return (FAIL); | |
316 | } | |
317 | + hostfile = NULL; | |
318 | ||
319 | if (dbproc->hostfileinfo->firstrow > 0 && row_of_query < dbproc->hostfileinfo->firstrow) { | |
320 | /* | |
321 | @@ -1896,8 +1902,10 @@ | |
322 | return FAIL; | |
323 | } | |
324 | ||
325 | - if (_bcp_start_copy_in(dbproc) == FAIL) | |
326 | + if (_bcp_start_copy_in(dbproc) == FAIL) { | |
327 | + fclose(hostfile); | |
328 | return FAIL; | |
329 | + } | |
330 | ||
331 | tds->out_flag = TDS_BULK; | |
332 | tds_set_state(tds, TDS_QUERYING); | |
333 | @@ -1922,6 +1930,7 @@ | |
334 | ||
335 | if (errfile == NULL && dbproc->hostfileinfo->errorfile) { | |
336 | if (!(errfile = fopen(dbproc->hostfileinfo->errorfile, "w"))) { | |
337 | + fclose(hostfile); | |
338 | dbperror(dbproc, SYBEBUOE, 0); | |
339 | return FAIL; | |
340 | } | |
341 | @@ -2003,6 +2012,7 @@ | |
342 | if (tds_process_simple_query(tds) != TDS_SUCCEED) { | |
343 | if (errfile) | |
344 | fclose(errfile); | |
345 | + fclose(hostfile); | |
346 | return FAIL; | |
347 | } | |
348 | ||
349 | diff -urN freetds/src/dblib/dblib.c freetds.current/src/dblib/dblib.c | |
350 | --- freetds/src/dblib/dblib.c 2008-01-02 00:09:46.000000000 +0100 | |
351 | +++ freetds.current/src/dblib/dblib.c 2008-05-26 14:49:56.000000000 +0200 | |
352 | @@ -76,7 +76,7 @@ | |
353 | #include <dmalloc.h> | |
354 | #endif | |
355 | ||
356 | -TDS_RCSID(var, "$Id$"); | |
357 | +TDS_RCSID(var, "$Id$"); | |
358 | ||
359 | static RETCODE _dbresults(DBPROCESS * dbproc); | |
360 | static int _db_get_server_type(int bindtype); | |
361 | @@ -3325,8 +3325,10 @@ | |
362 | computeid = status; | |
363 | ||
364 | for (i = 0;; ++i) { | |
365 | - if (i >= tds->num_comp_info) | |
366 | + if (i >= tds->num_comp_info) { | |
367 | + free(col_printlens); | |
368 | return FAIL; | |
369 | + } | |
370 | resinfo = tds->comp_info[i]; | |
371 | if (resinfo->computeid == computeid) | |
372 | break; | |
373 | diff -urN freetds/src/odbc/odbc.c freetds.current/src/odbc/odbc.c | |
374 | --- freetds/src/odbc/odbc.c 2008-04-30 16:59:32.000000000 +0200 | |
375 | +++ freetds.current/src/odbc/odbc.c 2008-06-18 06:11:39.000000000 +0200 | |
376 | @@ -60,7 +60,7 @@ | |
377 | #include <dmalloc.h> | |
378 | #endif | |
379 | ||
380 | -TDS_RCSID(var, "$Id$"); | |
381 | +TDS_RCSID(var, "$Id$"); | |
382 | ||
383 | static SQLRETURN _SQLAllocConnect(SQLHENV henv, SQLHDBC FAR * phdbc); | |
384 | static SQLRETURN _SQLAllocEnv(SQLHENV FAR * phenv); | |
385 | @@ -3608,10 +3608,6 @@ | |
386 | truncated = 1; | |
387 | stmt->errs.lastrc = SQL_SUCCESS_WITH_INFO; | |
388 | } | |
389 | - } else { | |
390 | - /* TODO change when we code cursors support... */ | |
391 | - /* stop looping, forward cursor support only one row */ | |
392 | - num_rows = 1; | |
393 | } | |
394 | if (drec_ard->sql_desc_octet_length_ptr) | |
395 | *AT_ROW(drec_ard->sql_desc_octet_length_ptr, SQLLEN) = len; | |
396 | @@ -3648,11 +3644,33 @@ | |
397 | SQLRETURN ODBC_API | |
398 | SQLFetch(SQLHSTMT hstmt) | |
399 | { | |
400 | + SQLRETURN ret; | |
401 | + SQLULEN save_sql_desc_array_size; | |
402 | + SQLULEN *save_sql_desc_rows_processed_ptr; | |
403 | + SQLUSMALLINT *save_sql_desc_array_status_ptr; | |
404 | + | |
405 | INIT_HSTMT; | |
406 | ||
407 | tdsdump_log(TDS_DBG_FUNC, "SQLFetch(%p)\n", hstmt); | |
408 | ||
409 | - ODBC_RETURN(stmt, _SQLFetch(stmt, SQL_FETCH_NEXT, 0)); | |
410 | + if (stmt->dbc->env->attr.odbc_version != SQL_OV_ODBC3) { | |
411 | + save_sql_desc_array_size = stmt->ard->header.sql_desc_array_size; | |
412 | + stmt->ard->header.sql_desc_array_size = 1; | |
413 | + save_sql_desc_rows_processed_ptr = stmt->ird->header.sql_desc_rows_processed_ptr; | |
414 | + stmt->ird->header.sql_desc_rows_processed_ptr = NULL; | |
415 | + save_sql_desc_array_status_ptr = stmt->ird->header.sql_desc_array_status_ptr; | |
416 | + stmt->ird->header.sql_desc_array_status_ptr = NULL; | |
417 | + } | |
418 | + | |
419 | + ret = _SQLFetch(stmt, SQL_FETCH_NEXT, 0); | |
420 | + | |
421 | + if (stmt->dbc->env->attr.odbc_version != SQL_OV_ODBC3) { | |
422 | + stmt->ard->header.sql_desc_array_size = save_sql_desc_array_size; | |
423 | + stmt->ird->header.sql_desc_rows_processed_ptr = save_sql_desc_rows_processed_ptr; | |
424 | + stmt->ird->header.sql_desc_array_status_ptr = save_sql_desc_array_status_ptr; | |
425 | + } | |
426 | + | |
427 | + ODBC_RETURN(stmt, ret); | |
428 | } | |
429 | ||
430 | #if (ODBCVER >= 0x0300) | |
431 | @@ -4564,6 +4582,8 @@ | |
432 | SQLLEN dummy_cb; | |
433 | int nSybType; | |
434 | ||
435 | + int extra_bytes = 0; | |
436 | + | |
437 | INIT_HSTMT; | |
438 | ||
439 | tdsdump_log(TDS_DBG_FUNC, "SQLGetData(%p, %u, %d, %p, %d, %p)\n", | |
440 | @@ -4601,42 +4621,140 @@ | |
441 | if (colinfo->column_cur_size < 0) { | |
442 | *pcbValue = SQL_NULL_DATA; | |
443 | } else { | |
444 | + nSybType = tds_get_conversion_type(colinfo->column_type, colinfo->column_size); | |
445 | + if (fCType == SQL_C_DEFAULT) | |
446 | + fCType = odbc_sql_to_c_type_default(stmt->ird->records[icol - 1].sql_desc_concise_type); | |
447 | + if (fCType == SQL_ARD_TYPE) { | |
448 | + if (icol > stmt->ard->header.sql_desc_count) { | |
449 | + odbc_errs_add(&stmt->errs, "07009", NULL); | |
450 | + ODBC_RETURN(stmt, SQL_ERROR); | |
451 | + } | |
452 | + fCType = stmt->ard->records[icol - 1].sql_desc_concise_type; | |
453 | + } | |
454 | + assert(fCType); | |
455 | + | |
456 | src = (TDS_CHAR *) colinfo->column_data; | |
457 | if (is_variable_type(colinfo->column_type)) { | |
458 | - if (colinfo->column_text_sqlgetdatapos > 0 | |
459 | - && colinfo->column_text_sqlgetdatapos >= colinfo->column_cur_size) | |
460 | - ODBC_RETURN(stmt, SQL_NO_DATA); | |
461 | - | |
462 | + int nread = 0; | |
463 | + | |
464 | /* 2003-8-29 check for an old bug -- freddy77 */ | |
465 | assert(colinfo->column_text_sqlgetdatapos >= 0); | |
466 | if (is_blob_type(colinfo->column_type)) | |
467 | src = ((TDSBLOB *) src)->textvalue; | |
468 | - src += colinfo->column_text_sqlgetdatapos; | |
469 | - srclen = colinfo->column_cur_size - colinfo->column_text_sqlgetdatapos; | |
470 | + | |
471 | + if (fCType == SQL_C_CHAR && colinfo->column_text_sqlgetdatapos) { | |
472 | + TDS_CHAR buf[3]; | |
473 | + SQLLEN len; | |
474 | + | |
475 | + switch (nSybType) { | |
476 | + case SYBLONGBINARY: | |
477 | + case SYBBINARY: | |
478 | + case SYBVARBINARY: | |
479 | + case SYBIMAGE: | |
480 | + case XSYBBINARY: | |
481 | + case XSYBVARBINARY: | |
482 | + case TDS_CONVERT_BINARY: | |
483 | + if (colinfo->column_text_sqlgetdatapos % 2) { | |
484 | + nread = (colinfo->column_text_sqlgetdatapos - 1) / 2; | |
485 | + if (nread >= colinfo->column_cur_size) | |
486 | + ODBC_RETURN(stmt, SQL_NO_DATA); | |
487 | + | |
488 | + if (cbValueMax > 2) { | |
489 | + len = convert_tds2sql(context, nSybType, src + nread, 1, fCType, buf, sizeof(buf), NULL); | |
490 | + if (len < 2) { | |
491 | + if (len < 0) | |
492 | + odbc_convert_err_set(&stmt->errs, len); | |
493 | + ODBC_RETURN(stmt, SQL_ERROR); | |
494 | + } | |
495 | + *(TDS_CHAR *) rgbValue = buf[1]; | |
496 | + *((TDS_CHAR *) rgbValue + 1) = 0; | |
497 | + | |
498 | + rgbValue++; | |
499 | + cbValueMax--; | |
500 | + | |
501 | + extra_bytes = 1; | |
502 | + nread++; | |
503 | + | |
504 | + if (nread >= colinfo->column_cur_size) | |
505 | + ODBC_RETURN_(stmt); | |
506 | + } else { | |
507 | + if (cbValueMax) | |
508 | + *(TDS_CHAR *) rgbValue = 0; | |
509 | + odbc_errs_add(&stmt->errs, "01004", "String data, right truncated"); | |
510 | + ODBC_RETURN(stmt, SQL_SUCCESS_WITH_INFO); | |
511 | + } | |
512 | + } else { | |
513 | + nread = colinfo->column_text_sqlgetdatapos / 2; | |
514 | + if (nread >= colinfo->column_cur_size) | |
515 | + ODBC_RETURN(stmt, SQL_NO_DATA); | |
516 | + } | |
517 | + | |
518 | + src += nread; | |
519 | + srclen = colinfo->column_cur_size - nread; | |
520 | + break; | |
521 | + default: | |
522 | + if (colinfo->column_text_sqlgetdatapos >= colinfo->column_cur_size) | |
523 | + ODBC_RETURN(stmt, SQL_NO_DATA); | |
524 | + | |
525 | + src += colinfo->column_text_sqlgetdatapos; | |
526 | + srclen = colinfo->column_cur_size - colinfo->column_text_sqlgetdatapos; | |
527 | + | |
528 | + } | |
529 | + } else if (fCType == SQL_C_BINARY) { | |
530 | + switch (nSybType) { | |
531 | + case SYBCHAR: | |
532 | + case SYBVARCHAR: | |
533 | + case SYBTEXT: | |
534 | + case XSYBCHAR: | |
535 | + case XSYBVARCHAR: | |
536 | + nread = (src[0] == '0' && toupper(src[1]) == 'X')? 2 : 0; | |
537 | + | |
538 | + while ((nread < colinfo->column_cur_size) && (src[nread] == ' ' || src[nread] == '\0')) | |
539 | + nread++; | |
540 | + | |
541 | + nread += colinfo->column_text_sqlgetdatapos * 2; | |
542 | + | |
543 | + if (nread && nread >= colinfo->column_cur_size) | |
544 | + ODBC_RETURN(stmt, SQL_NO_DATA); | |
545 | + | |
546 | + src += nread; | |
547 | + srclen = colinfo->column_cur_size - nread; | |
548 | + break; | |
549 | + default: | |
550 | + if (colinfo->column_text_sqlgetdatapos > 0 | |
551 | + && colinfo->column_text_sqlgetdatapos >= colinfo->column_cur_size) | |
552 | + ODBC_RETURN(stmt, SQL_NO_DATA); | |
553 | + | |
554 | + src += colinfo->column_text_sqlgetdatapos; | |
555 | + srclen = colinfo->column_cur_size - colinfo->column_text_sqlgetdatapos; | |
556 | + } | |
557 | + } else { | |
558 | + if (colinfo->column_text_sqlgetdatapos > 0 | |
559 | + && colinfo->column_text_sqlgetdatapos >= colinfo->column_cur_size) | |
560 | + ODBC_RETURN(stmt, SQL_NO_DATA); | |
561 | + | |
562 | + src += colinfo->column_text_sqlgetdatapos; | |
563 | + srclen = colinfo->column_cur_size - colinfo->column_text_sqlgetdatapos; | |
564 | + } | |
565 | } else { | |
566 | if (colinfo->column_text_sqlgetdatapos > 0 | |
567 | - && colinfo->column_text_sqlgetdatapos >= colinfo->column_cur_size) | |
568 | + && colinfo->column_text_sqlgetdatapos >= colinfo->column_cur_size) | |
569 | ODBC_RETURN(stmt, SQL_NO_DATA); | |
570 | ||
571 | srclen = colinfo->column_cur_size; | |
572 | } | |
573 | - nSybType = tds_get_conversion_type(colinfo->column_type, colinfo->column_size); | |
574 | - if (fCType == SQL_C_DEFAULT) | |
575 | - fCType = odbc_sql_to_c_type_default(stmt->ird->records[icol - 1].sql_desc_concise_type); | |
576 | - if (fCType == SQL_ARD_TYPE) { | |
577 | - if (icol > stmt->ard->header.sql_desc_count) { | |
578 | - odbc_errs_add(&stmt->errs, "07009", NULL); | |
579 | - ODBC_RETURN(stmt, SQL_ERROR); | |
580 | - } | |
581 | - fCType = stmt->ard->records[icol - 1].sql_desc_concise_type; | |
582 | - } | |
583 | - assert(fCType); | |
584 | + | |
585 | *pcbValue = convert_tds2sql(context, nSybType, src, srclen, fCType, (TDS_CHAR *) rgbValue, cbValueMax, NULL); | |
586 | if (*pcbValue < 0) { | |
587 | odbc_convert_err_set(&stmt->errs, *pcbValue); | |
588 | ODBC_RETURN(stmt, SQL_ERROR); | |
589 | } | |
590 | - | |
591 | + | |
592 | + if (extra_bytes) { | |
593 | + colinfo->column_text_sqlgetdatapos += extra_bytes; | |
594 | + *pcbValue += extra_bytes; | |
595 | + } | |
596 | + | |
597 | if (is_variable_type(colinfo->column_type) && (fCType == SQL_C_CHAR || fCType == SQL_C_BINARY)) { | |
598 | /* calc how many bytes was readed */ | |
599 | int readed = cbValueMax; | |
600 | diff -urN freetds/src/odbc/unittests/cursor6.c freetds.current/src/odbc/unittests/cursor6.c | |
601 | --- freetds/src/odbc/unittests/cursor6.c 1970-01-01 01:00:00.000000000 +0100 | |
602 | +++ freetds.current/src/odbc/unittests/cursor6.c 2008-06-06 18:52:23.000000000 +0200 | |
603 | @@ -0,0 +1,140 @@ | |
604 | +#include "common.h" | |
605 | + | |
606 | +/* Test SQLFetchScroll with no binded columns */ | |
607 | + | |
608 | +static char software_version[] = "$Id$"; | |
609 | +static void *no_unused_var_warn[] = { software_version, no_unused_var_warn }; | |
610 | + | |
611 | +static int bind_all = 0; | |
612 | +static int normal_fetch = 0; | |
613 | +static int use_cursors = 1; | |
614 | + | |
615 | +#define CHK(func,params) do { \ | |
616 | + if (func params != SQL_SUCCESS) \ | |
617 | + ODBC_REPORT_ERROR(#func); \ | |
618 | + } while(0) | |
619 | + | |
620 | +static void Test(void) | |
621 | +{ | |
622 | +#define ROWS 5 | |
623 | + struct data_t { | |
624 | + SQLINTEGER i; | |
625 | + SQLLEN ind_i; | |
626 | + char c[20]; | |
627 | + SQLLEN ind_c; | |
628 | + } data[ROWS]; | |
629 | + SQLUSMALLINT statuses[ROWS]; | |
630 | + SQLULEN num_row; | |
631 | + | |
632 | + ResetStatement(); | |
633 | + | |
634 | + /* this should not fail or return warnings */ | |
635 | + if (use_cursors) { | |
636 | + CHK(SQLSetStmtAttr, (Statement, SQL_ATTR_CONCURRENCY, int2ptr(SQL_CONCUR_READ_ONLY), 0)); | |
637 | + CHK(SQLSetStmtAttr, (Statement, SQL_ATTR_CURSOR_TYPE, int2ptr(SQL_CURSOR_STATIC), 0)); | |
638 | + } | |
639 | + CHK(SQLPrepare, (Statement, (SQLCHAR *) "SELECT c, i FROM #cursor6_test", SQL_NTS)); | |
640 | + CHK(SQLExecute, (Statement)); | |
641 | + CHK(SQLSetStmtAttr, (Statement, SQL_ATTR_ROW_BIND_TYPE, int2ptr(sizeof(data[0])), 0)); | |
642 | + CHK(SQLSetStmtAttr, (Statement, SQL_ATTR_ROW_ARRAY_SIZE, int2ptr(ROWS), 0)); | |
643 | + CHK(SQLSetStmtAttr, (Statement, SQL_ATTR_ROW_STATUS_PTR, statuses, 0)); | |
644 | + CHK(SQLSetStmtAttr, (Statement, SQL_ATTR_ROWS_FETCHED_PTR, &num_row, 0)); | |
645 | + if (bind_all) | |
646 | + CHK(SQLBindCol, (Statement, 1, SQL_C_CHAR, &data[0].c, sizeof(data[0].c), &data[0].ind_c)); | |
647 | + CHK(SQLBindCol, (Statement, 2, SQL_C_LONG, &data[0].i, sizeof(data[0].i), &data[0].ind_i)); | |
648 | + | |
649 | +#define FILL(s, n) do { \ | |
650 | + int _n; for (_n = 0; _n < sizeof(s)/sizeof(s[0]); ++_n) s[_n] = n; \ | |
651 | +} while(0) | |
652 | + FILL(statuses, 9876); | |
653 | + num_row = -3; | |
654 | + data[0].i = 0xdeadbeef; | |
655 | + data[1].i = 0xdeadbeef; | |
656 | + if (normal_fetch) | |
657 | + CHK(SQLFetch, (Statement)); | |
658 | + else | |
659 | + CHK(SQLFetchScroll, (Statement, SQL_FETCH_NEXT, 0)); | |
660 | + | |
661 | + /* now check row numbers */ | |
662 | + printf("num_row %d statuses[0] %d statuses[1] %d odbc3 %d\n", (int) num_row, | |
663 | + (int) statuses[0], (int) statuses[1], use_odbc_version3); | |
664 | + | |
665 | + if (use_odbc_version3 || !normal_fetch) { | |
666 | + if (num_row != ROWS || statuses[0] != SQL_ROW_SUCCESS || statuses[1] != SQL_ROW_SUCCESS) { | |
667 | + fprintf(stderr, "result error 1\n"); | |
668 | + exit(1); | |
669 | + } | |
670 | + } else { | |
671 | + if (data[0].i != 1 || data[1].i != 0xdeadbeef) { | |
672 | + fprintf(stderr, "result error 2\n"); | |
673 | + exit(1); | |
674 | + } | |
675 | + } | |
676 | + | |
677 | + FILL(statuses, 8765); | |
678 | + num_row = -3; | |
679 | + if (normal_fetch) | |
680 | + CHK(SQLFetch, (Statement)); | |
681 | + else | |
682 | + CHK(SQLFetchScroll, (Statement, SQL_FETCH_NEXT, 0)); | |
683 | +} | |
684 | + | |
685 | +static void Init(void) | |
686 | +{ | |
687 | + int i; | |
688 | + char sql[128]; | |
689 | + | |
690 | + Command(Statement, "CREATE TABLE #cursor6_test (i INT, c VARCHAR(20))"); | |
691 | + for (i = 1; i <= 10; ++i) { | |
692 | + sprintf(sql, "INSERT INTO #cursor6_test(i,c) VALUES(%d, 'a%db%dc%d')", i, i, i, i); | |
693 | + Command(Statement, sql); | |
694 | + } | |
695 | + | |
696 | +} | |
697 | + | |
698 | +int | |
699 | +main(int argc, char *argv[]) | |
700 | +{ | |
701 | + unsigned char sqlstate[6]; | |
702 | + unsigned char msg[256]; | |
703 | + SQLRETURN retcode; | |
704 | + | |
705 | + use_odbc_version3 = 1; | |
706 | + Connect(); | |
707 | + | |
708 | + retcode = SQLSetConnectAttr(Connection, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_DYNAMIC, SQL_IS_INTEGER); | |
709 | + if (retcode != SQL_SUCCESS) { | |
710 | + CHK(SQLGetDiagRec, (SQL_HANDLE_DBC, Connection, 1, sqlstate, NULL, (SQLCHAR *) msg, sizeof(msg), NULL)); | |
711 | + sqlstate[5] = 0; | |
712 | + if (strcmp((const char*) sqlstate, "S1092") == 0) { | |
713 | + printf("Your connection seems to not support cursors, probably you are using wrong protocol version or Sybase\n"); | |
714 | + Disconnect(); | |
715 | + exit(0); | |
716 | + } | |
717 | + ODBC_REPORT_ERROR("SQLSetConnectAttr"); | |
718 | + } | |
719 | + | |
720 | + Init(); | |
721 | + | |
722 | +#define ALL(n) for (n = 0; n < 2; ++n) | |
723 | + ALL(use_cursors) | |
724 | + ALL(bind_all) | |
725 | + ALL(normal_fetch) | |
726 | + Test(); | |
727 | + | |
728 | + Disconnect(); | |
729 | + | |
730 | + use_odbc_version3 = 0; | |
731 | + | |
732 | + Connect(); | |
733 | + Init(); | |
734 | + | |
735 | + ALL(use_cursors) | |
736 | + ALL(bind_all) | |
737 | + ALL(normal_fetch) | |
738 | + Test(); | |
739 | + | |
740 | + Disconnect(); | |
741 | + | |
742 | + return 0; | |
743 | +} | |
744 | diff -urN freetds/src/odbc/unittests/getdata.c freetds.current/src/odbc/unittests/getdata.c | |
745 | --- freetds/src/odbc/unittests/getdata.c 2008-01-29 11:14:31.000000000 +0100 | |
746 | +++ freetds.current/src/odbc/unittests/getdata.c 2008-06-18 06:11:39.000000000 +0200 | |
747 | @@ -1,6 +1,6 @@ | |
748 | #include "common.h" | |
749 | ||
750 | -static char software_version[] = "$Id$"; | |
751 | +static char software_version[] = "$Id$"; | |
752 | static void *no_unused_var_warn[] = { software_version, no_unused_var_warn }; | |
753 | ||
754 | static char odbc_err[256]; | |
755 | @@ -11,7 +11,14 @@ | |
756 | { | |
757 | memset(odbc_err, 0, sizeof(odbc_err)); | |
758 | memset(odbc_sqlstate, 0, sizeof(odbc_sqlstate)); | |
759 | - if (!SQL_SUCCEEDED(SQLGetDiagRec(SQL_HANDLE_STMT, Statement, 1, (SQLCHAR *) odbc_sqlstate, NULL, (SQLCHAR *) odbc_err, sizeof(odbc_err), NULL))) { | |
760 | + if (!SQL_SUCCEEDED(SQLGetDiagRec(SQL_HANDLE_STMT | |
761 | + , Statement | |
762 | + , 1 | |
763 | + , (SQLCHAR *) odbc_sqlstate | |
764 | + , NULL | |
765 | + , (SQLCHAR *) odbc_err | |
766 | + , sizeof(odbc_err) | |
767 | + , NULL))) { | |
768 | printf("SQLGetDiagRec should not fail\n"); | |
769 | exit(1); | |
770 | } | |
771 | diff -urN freetds/src/odbc/unittests/Makefile.am freetds.current/src/odbc/unittests/Makefile.am | |
772 | --- freetds/src/odbc/unittests/Makefile.am 2008-02-29 10:23:51.000000000 +0100 | |
773 | +++ freetds.current/src/odbc/unittests/Makefile.am 2008-06-06 18:52:23.000000000 +0200 | |
774 | @@ -1,4 +1,4 @@ | |
775 | -# $Id$ | |
776 | +# $Id$ | |
777 | TESTS = \ | |
778 | t0001$(EXEEXT) t0002$(EXEEXT) t0003$(EXEEXT)\ | |
779 | t0004$(EXEEXT) connect$(EXEEXT) print$(EXEEXT)\ | |
780 | @@ -21,7 +21,7 @@ | |
781 | connect2$(EXEEXT) timeout4$(EXEEXT) freeclose$(EXEEXT) \ | |
782 | cursor3$(EXEEXT) cursor4$(EXEEXT) cursor5$(EXEEXT) \ | |
783 | attributes$(EXEEXT) hidden$(EXEEXT) blob1$(EXEEXT) \ | |
784 | - rowset$(EXEEXT) | |
785 | + rowset$(EXEEXT) cursor6$(EXEEXT) | |
786 | ||
787 | check_PROGRAMS = $(TESTS) | |
788 | ||
789 | @@ -81,6 +81,7 @@ | |
790 | hidden_SOURCES = hidden.c common.c common.h | |
791 | blob1_SOURCES = blob1.c common.c common.h | |
792 | rowset_SOURCES = rowset.c common.c common.h | |
793 | +cursor6_SOURCES = cursor6.c common.c common.h | |
794 | ||
795 | AM_CPPFLAGS = -I$(top_srcdir)/include $(ODBC_INC) -DFREETDS_SRCDIR=\"$(srcdir)\" | |
796 | if MINGW32 | |
797 | diff -urN freetds/src/server/server.c freetds.current/src/server/server.c | |
798 | --- freetds/src/server/server.c 2008-01-07 15:07:21.000000000 +0100 | |
799 | +++ freetds.current/src/server/server.c 2008-05-28 23:08:03.000000000 +0200 | |
800 | @@ -30,7 +30,7 @@ | |
801 | #include "tds.h" | |
802 | #include "tdssrv.h" | |
803 | ||
804 | -static char software_version[] = "$Id$"; | |
805 | +static char software_version[] = "$Id$"; | |
806 | static void *no_unused_var_warn[] = { software_version, no_unused_var_warn }; | |
807 | ||
808 | void | |
809 | @@ -117,13 +117,17 @@ | |
810 | const char *msgtext, const char *srvname, const char *procname, int line) | |
811 | { | |
812 | int msgsz; | |
813 | + size_t len; | |
814 | ||
815 | tds_put_byte(tds, TDS_INFO_TOKEN); | |
816 | + if (!procname) | |
817 | + procname = ""; | |
818 | + len = strlen(procname); | |
819 | msgsz = 4 /* msg no */ | |
820 | + 1 /* msg state */ | |
821 | + 1 /* severity */ | |
822 | /* FIXME ucs2 */ | |
823 | - + (IS_TDS7_PLUS(tds) ? 2 : 1) * (strlen(msgtext) + 1 + strlen(srvname) + 1 + strlen(procname)) | |
824 | + + (IS_TDS7_PLUS(tds) ? 2 : 1) * (strlen(msgtext) + 1 + strlen(srvname) + 1 + len) | |
825 | + 1 + 2; /* line number */ | |
826 | tds_put_smallint(tds, msgsz); | |
827 | tds_put_int(tds, msgno); | |
828 | @@ -135,10 +139,10 @@ | |
829 | tds_put_byte(tds, strlen(srvname)); | |
830 | /* FIXME ucs2 */ | |
831 | tds_put_string(tds, srvname, strlen(srvname)); | |
832 | - if (procname && strlen(procname)) { | |
833 | - tds_put_byte(tds, strlen(procname)); | |
834 | + if (len) { | |
835 | + tds_put_byte(tds, len); | |
836 | /* FIXME ucs2 */ | |
837 | - tds_put_string(tds, procname, strlen(procname)); | |
838 | + tds_put_string(tds, procname, len); | |
839 | } else { | |
840 | tds_put_byte(tds, 0); | |
841 | } | |
842 | diff -urN freetds/src/tds/mem.c freetds.current/src/tds/mem.c | |
843 | --- freetds/src/tds/mem.c 2007-12-31 11:06:50.000000000 +0100 | |
844 | +++ freetds.current/src/tds/mem.c 2008-05-26 14:49:56.000000000 +0200 | |
845 | @@ -47,7 +47,7 @@ | |
846 | #include <dmalloc.h> | |
847 | #endif | |
848 | ||
849 | -TDS_RCSID(var, "$Id$"); | |
850 | +TDS_RCSID(var, "$Id$"); | |
851 | ||
852 | static void tds_free_env(TDSSOCKET * tds); | |
853 | static void tds_free_compute_results(TDSSOCKET * tds); | |
854 | @@ -1040,6 +1040,9 @@ | |
855 | void | |
856 | tds_free_connection(TDSCONNECTION * connection) | |
857 | { | |
858 | + if (!connection) | |
859 | + return; | |
860 | + | |
861 | tds_dstr_free(&connection->server_name); | |
862 | tds_dstr_free(&connection->client_host_name); | |
863 | tds_dstr_free(&connection->server_host_name); |