Line data Source code
1 : /*
2 : * Purpose: Test bcp in and out, and specifically bcp_colfmt()
3 : * Functions: bcp_colfmt bcp_columns bcp_exec bcp_init
4 : */
5 :
6 : #include "common.h"
7 :
8 : #include <freetds/bool.h>
9 : #include <freetds/replacements.h>
10 :
11 : static bool failed = false;
12 :
13 : static void
14 0 : failure(const char *fmt, ...)
15 : {
16 : va_list ap;
17 :
18 0 : failed = true;
19 :
20 0 : va_start(ap, fmt);
21 0 : vfprintf(stderr, fmt, ap);
22 0 : va_end(ap);
23 0 : }
24 :
25 : #define INFILE_NAME "t0016"
26 : #define TABLE_NAME "#dblib0016"
27 :
28 : static void test_file(const char *fn);
29 : static bool compare_files(const char *fn1, const char *fn2);
30 : static unsigned count_file_rows(FILE *f);
31 : static size_t fgets_raw(char *s, int len, FILE * f);
32 : static DBPROCESS *dbproc;
33 :
34 10 : TEST_MAIN()
35 : {
36 : LOGINREC *login;
37 : char in_file[30];
38 : unsigned int n;
39 :
40 10 : setbuf(stdout, NULL);
41 10 : setbuf(stderr, NULL);
42 :
43 10 : set_malloc_options();
44 :
45 10 : read_login_info(argc, argv);
46 10 : printf("Starting %s\n", argv[0]);
47 10 : dbsetversion(DBVERSION_100);
48 10 : dbinit();
49 :
50 10 : dberrhandle(syb_err_handler);
51 10 : dbmsghandle(syb_msg_handler);
52 :
53 10 : printf("About to logon\n");
54 :
55 10 : login = dblogin();
56 10 : BCP_SETL(login, TRUE);
57 10 : DBSETLPWD(login, PASSWORD);
58 10 : DBSETLUSER(login, USER);
59 10 : DBSETLAPP(login, "t0016");
60 10 : DBSETLCHARSET(login, "utf8");
61 :
62 10 : dbproc = dbopen(login, SERVER);
63 10 : if (strlen(DATABASE)) {
64 10 : dbuse(dbproc, DATABASE);
65 : }
66 10 : dbloginfree(login);
67 10 : printf("After logon\n");
68 :
69 : /* First testcase already had SQL opened by read_login_info() */
70 10 : strcpy(in_file, INFILE_NAME);
71 :
72 : /* Execute all testcases (carry on even if one fails) */
73 190 : for (n = 1; n <= 100; ++n) {
74 190 : test_file(in_file);
75 190 : sprintf(in_file, "%s_%d", INFILE_NAME, n);
76 190 : if (sql_reopen(in_file) != SUCCEED) {
77 10 : printf("===== End of t0016 subtests =====\n");
78 10 : break;
79 : }
80 : }
81 :
82 10 : dbclose(dbproc);
83 10 : dbexit();
84 :
85 10 : printf("dblib %s on %s\n", (failed ? "failed!" : "okay"), __FILE__);
86 10 : return failed ? 1 : 0;
87 : }
88 :
89 : static bool got_error = false;
90 :
91 : static int
92 48 : ignore_msg_handler(DBPROCESS * dbproc TDS_UNUSED, DBINT msgno TDS_UNUSED, int state TDS_UNUSED, int severity TDS_UNUSED,
93 : char *text TDS_UNUSED, char *server TDS_UNUSED, char *proc TDS_UNUSED, int line TDS_UNUSED)
94 : {
95 48 : got_error = true;
96 48 : return 0;
97 : }
98 :
99 : static int
100 48 : ignore_err_handler(DBPROCESS * dbproc TDS_UNUSED, int severity TDS_UNUSED, int dberr TDS_UNUSED,
101 : int oserr TDS_UNUSED, char *dberrstr TDS_UNUSED, char *oserrstr TDS_UNUSED)
102 : {
103 48 : got_error = true;
104 48 : return INT_CANCEL;
105 : }
106 :
107 : static char line1[1024*16];
108 : static char line2[1024*16];
109 :
110 : static void
111 190 : test_file(const char *fn)
112 : {
113 : int i;
114 : RETCODE ret;
115 190 : int num_cols = 0;
116 190 : const char *out_file = "t0016.out";
117 190 : const char *err_file = "t0016.err";
118 : DBINT rows_copied;
119 190 : unsigned num_rows = 2;
120 : char table_name[64];
121 : char hints[64];
122 :
123 : FILE *input_file;
124 :
125 : char sql_file[256];
126 : char in_file[256];
127 : char exp_file[256];
128 :
129 190 : snprintf(sql_file, sizeof(sql_file), "%s/%s.sql", FREETDS_SRCDIR, fn);
130 190 : snprintf(in_file, sizeof(in_file), "%s/%s.in", FREETDS_SRCDIR, fn);
131 190 : snprintf(exp_file, sizeof(exp_file), "%s/%s.exp", FREETDS_SRCDIR, fn);
132 :
133 190 : strlcpy(table_name, TABLE_NAME, sizeof(table_name));
134 190 : hints[0] = 0;
135 :
136 190 : printf("===== %s =====\n", fn);
137 190 : input_file = fopen(in_file, "r");
138 190 : if (!input_file) {
139 0 : sprintf(in_file, "%s.in", fn);
140 0 : sprintf(exp_file, "%s.exp", fn);
141 0 : input_file = fopen(in_file, "rb");
142 : }
143 190 : if (!input_file) {
144 0 : fprintf(stderr, "could not open %s\n", in_file);
145 0 : exit(1);
146 : }
147 190 : num_rows = count_file_rows(input_file);
148 190 : fclose(input_file);
149 :
150 190 : input_file = fopen(exp_file, "r");
151 190 : if (!input_file)
152 170 : strcpy(exp_file, in_file);
153 : else
154 20 : fclose(input_file);
155 :
156 190 : input_file = fopen(sql_file, "r");
157 190 : assert(input_file);
158 : for (;;) {
159 : const char *param;
160 210 : size_t len = fgets_raw(line1, sizeof(line1), input_file);
161 :
162 210 : if (len && line1[len - 1] == '\n')
163 210 : line1[len - 1] = '\0';
164 210 : if (len == 0 || strncmp(line1, "-- PARAM:", 9) != 0)
165 : break;
166 20 : param = line1 + 9;
167 20 : if (strncmp(param, "table ", 6) == 0) {
168 10 : param += 6;
169 10 : strlcpy(table_name, param, sizeof(table_name));
170 10 : } else if (strncmp(param, "hints ", 6) == 0) {
171 10 : param += 6;
172 10 : strlcpy(hints, param, sizeof(hints));
173 : } else {
174 0 : fprintf(stderr, "invalid parameter: %s\n", param);
175 0 : exit(1);
176 : }
177 : }
178 190 : fclose(input_file);
179 :
180 190 : dberrhandle(ignore_err_handler);
181 190 : dbmsghandle(ignore_msg_handler);
182 :
183 190 : printf("Creating table '%s'\n", table_name);
184 190 : got_error = false;
185 190 : sql_cmd(dbproc);
186 190 : dbsqlexec(dbproc);
187 598 : while (dbresults(dbproc) != NO_MORE_RESULTS)
188 218 : continue;
189 :
190 190 : dberrhandle(syb_err_handler);
191 190 : dbmsghandle(syb_msg_handler);
192 :
193 190 : if (got_error) {
194 36 : printf("Skipping %s due to table creation failure.\n", fn);
195 36 : return;
196 : }
197 :
198 154 : ret = sql_cmd(dbproc);
199 154 : printf("return from dbcmd = %d\n", ret);
200 :
201 154 : ret = dbsqlexec(dbproc);
202 154 : printf("return from dbsqlexec = %d\n", ret);
203 :
204 154 : if (dbresults(dbproc) != FAIL) {
205 154 : num_cols = dbnumcols(dbproc);
206 154 : printf("Number of columns = %d\n", num_cols);
207 :
208 308 : while (dbnextrow(dbproc) != NO_MORE_ROWS)
209 0 : continue;
210 : }
211 :
212 : /* BCP in */
213 :
214 154 : printf("bcp_init with in_file as '%s'\n", in_file);
215 154 : ret = bcp_init(dbproc, table_name, in_file, (char*) err_file, DB_IN);
216 154 : if (ret != SUCCEED)
217 0 : failure("bcp_init failed\n");
218 :
219 154 : if (hints[0])
220 2 : bcp_options(dbproc, BCPHINTS, (BYTE *) hints, strlen(hints));
221 :
222 154 : printf("return from bcp_init = %d\n", ret);
223 :
224 154 : ret = bcp_columns(dbproc, num_cols);
225 154 : if (ret != SUCCEED)
226 0 : failure("bcp_columns failed\n");
227 154 : printf("return from bcp_columns = %d\n", ret);
228 :
229 824 : for (i = 1; i < num_cols; i++) {
230 670 : if ((ret = bcp_colfmt(dbproc, i, SYBCHAR, 0, -1, (BYTE *) "\t", sizeof(char), i)) == FAIL)
231 0 : failure("return from bcp_colfmt = %d\n", ret);
232 : }
233 :
234 154 : if ((ret = bcp_colfmt(dbproc, num_cols, SYBCHAR, 0, -1, (BYTE *) "\n", sizeof(char), num_cols)) == FAIL)
235 0 : failure("return from bcp_colfmt = %d\n", ret);
236 :
237 :
238 154 : ret = bcp_exec(dbproc, &rows_copied);
239 154 : if (ret != SUCCEED || rows_copied != num_rows)
240 0 : failure("bcp_exec failed\n");
241 :
242 154 : printf("%d rows copied in\n", rows_copied);
243 :
244 : /* BCP out */
245 :
246 154 : rows_copied = 0;
247 154 : ret = bcp_init(dbproc, table_name, (char *) out_file, (char *) err_file, DB_OUT);
248 154 : if (ret != SUCCEED)
249 0 : failure("bcp_int failed\n");
250 :
251 154 : printf("select\n");
252 154 : sql_cmd(dbproc);
253 154 : dbsqlexec(dbproc);
254 :
255 154 : if (dbresults(dbproc) != FAIL) {
256 154 : num_cols = dbnumcols(dbproc);
257 308 : while (dbnextrow(dbproc) != NO_MORE_ROWS)
258 0 : continue;
259 : }
260 :
261 154 : ret = bcp_columns(dbproc, num_cols);
262 :
263 824 : for (i = 1; i < num_cols; i++) {
264 670 : if ((ret = bcp_colfmt(dbproc, i, SYBCHAR, 0, -1, (BYTE *) "\t", sizeof(char), i)) == FAIL)
265 0 : failure("return from bcp_colfmt = %d\n", ret);
266 : }
267 :
268 154 : if ((ret = bcp_colfmt(dbproc, num_cols, SYBCHAR, 0, -1, (BYTE *) "\n", sizeof(char), num_cols)) == FAIL)
269 0 : failure("return from bcp_colfmt = %d\n", ret);
270 :
271 154 : ret = bcp_exec(dbproc, &rows_copied);
272 154 : if (ret != SUCCEED || rows_copied != num_rows)
273 0 : failure("bcp_exec failed\n");
274 :
275 154 : printf("%d rows copied out\n", rows_copied);
276 :
277 154 : printf("Dropping table '%s'\n", table_name);
278 154 : sql_cmd(dbproc);
279 154 : dbsqlexec(dbproc);
280 466 : while (dbresults(dbproc) != NO_MORE_RESULTS)
281 158 : continue;
282 :
283 154 : if (failed)
284 : return;
285 :
286 154 : if (compare_files(exp_file, out_file))
287 154 : printf("Input and output files are equal\n");
288 : else
289 0 : failed = true;
290 : }
291 :
292 : static size_t
293 1910 : fgets_raw(char *s, int len, FILE *f)
294 : {
295 1910 : char *p = s;
296 :
297 767832 : while (len > 1) {
298 765922 : int c = getc(f);
299 765922 : if (c == EOF) {
300 498 : if (ferror(f))
301 : return 0;
302 : break;
303 : }
304 765424 : *p++ = c;
305 765424 : --len;
306 765424 : if (c == '\n')
307 : break;
308 : }
309 1910 : if (len > 0)
310 1910 : *p = 0;
311 1910 : return p - s;
312 : }
313 :
314 : static bool
315 154 : compare_files(const char *fn1, const char *fn2)
316 : {
317 154 : bool equal = true;
318 : FILE *f1, *f2;
319 : size_t s1, s2;
320 :
321 : /* check input and output should be the same */
322 154 : f1 = fopen(fn1, "r");
323 154 : f2 = fopen(fn2, "r");
324 154 : if (f1 != NULL && f2 != NULL) {
325 : int line = 1;
326 :
327 366 : for (;; ++line) {
328 886 : s1 = fgets_raw(line1, sizeof(line1), f1);
329 520 : s2 = fgets_raw(line2, sizeof(line2), f2);
330 :
331 : /* EOF or error of one */
332 520 : if (!!s1 != !!s2) {
333 0 : equal = false;
334 0 : failure("error reading a file or EOF of a file\n");
335 0 : break;
336 : }
337 :
338 : /* EOF or error of both */
339 520 : if (!s1) {
340 154 : if (feof(f1) && feof(f2))
341 : break;
342 0 : equal = false;
343 0 : failure("error reading a file\n");
344 0 : break;
345 : }
346 :
347 366 : if (s1 != s2 || memcmp(line1, line2, s1) != 0) {
348 0 : equal = false;
349 0 : failure("File different at line %d\n"
350 : " input: %s"
351 : " output: %s",
352 : line, line1, line2);
353 : }
354 : }
355 : } else {
356 0 : equal = false;
357 0 : failure("error opening files\n");
358 : }
359 154 : if (f1)
360 154 : fclose(f1);
361 154 : if (f2)
362 154 : fclose(f2);
363 :
364 154 : return equal;
365 : }
366 :
367 : static unsigned
368 190 : count_file_rows(FILE *f)
369 : {
370 : size_t s;
371 190 : unsigned rows = 1;
372 190 : char last = '\n';
373 :
374 190 : assert(f);
375 :
376 660 : while ((s = fgets_raw(line1, sizeof(line1), f)) != 0) {
377 470 : last = line1[s-1];
378 470 : if (last == '\n')
379 470 : ++rows;
380 : }
381 190 : if (last == '\n')
382 190 : --rows;
383 190 : assert(!ferror(f));
384 190 : return rows;
385 : }
|