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 DBPROCESS *dbproc;
32 :
33 10 : TEST_MAIN()
34 : {
35 : LOGINREC *login;
36 : char in_file[30];
37 : unsigned int n;
38 :
39 10 : setbuf(stdout, NULL);
40 10 : setbuf(stderr, NULL);
41 :
42 10 : set_malloc_options();
43 :
44 10 : read_login_info(argc, argv);
45 10 : printf("Starting %s\n", argv[0]);
46 10 : dbsetversion(DBVERSION_100);
47 10 : dbinit();
48 :
49 10 : dberrhandle(syb_err_handler);
50 10 : dbmsghandle(syb_msg_handler);
51 :
52 10 : printf("About to logon\n");
53 :
54 10 : login = dblogin();
55 10 : BCP_SETL(login, TRUE);
56 10 : DBSETLPWD(login, PASSWORD);
57 10 : DBSETLUSER(login, USER);
58 10 : DBSETLAPP(login, "t0016");
59 10 : DBSETLCHARSET(login, "utf8");
60 :
61 10 : dbproc = dbopen(login, SERVER);
62 10 : if (strlen(DATABASE)) {
63 10 : dbuse(dbproc, DATABASE);
64 : }
65 10 : dbloginfree(login);
66 10 : printf("After logon\n");
67 :
68 10 : strcpy(in_file, INFILE_NAME);
69 140 : for (n = 1; n <= 100; ++n) {
70 140 : test_file(in_file);
71 140 : sprintf(in_file, "%s_%d", INFILE_NAME, n);
72 140 : if (sql_reopen(in_file) != SUCCEED)
73 : break;
74 : }
75 :
76 10 : dbclose(dbproc);
77 10 : dbexit();
78 :
79 10 : printf("dblib %s on %s\n", (failed ? "failed!" : "okay"), __FILE__);
80 10 : return failed ? 1 : 0;
81 : }
82 :
83 : static bool got_error = false;
84 :
85 : static int
86 16 : ignore_msg_handler(DBPROCESS * dbproc TDS_UNUSED, DBINT msgno TDS_UNUSED, int state TDS_UNUSED, int severity TDS_UNUSED,
87 : char *text TDS_UNUSED, char *server TDS_UNUSED, char *proc TDS_UNUSED, int line TDS_UNUSED)
88 : {
89 16 : got_error = true;
90 16 : return 0;
91 : }
92 :
93 : static int
94 16 : ignore_err_handler(DBPROCESS * dbproc TDS_UNUSED, int severity TDS_UNUSED, int dberr TDS_UNUSED,
95 : int oserr TDS_UNUSED, char *dberrstr TDS_UNUSED, char *oserrstr TDS_UNUSED)
96 : {
97 16 : got_error = true;
98 16 : return INT_CANCEL;
99 : }
100 :
101 : static char line1[1024*16];
102 : static char line2[1024*16];
103 :
104 : static void
105 140 : test_file(const char *fn)
106 : {
107 : int i;
108 : RETCODE ret;
109 140 : int num_cols = 0;
110 140 : const char *out_file = "t0016.out";
111 140 : const char *err_file = "t0016.err";
112 : DBINT rows_copied;
113 140 : unsigned num_rows = 2;
114 :
115 : FILE *input_file;
116 :
117 : char in_file[256];
118 140 : snprintf(in_file, sizeof(in_file), "%s/%s.in", FREETDS_SRCDIR, fn);
119 :
120 140 : input_file = fopen(in_file, "rb");
121 140 : if (!input_file) {
122 0 : sprintf(in_file, "%s.in", fn);
123 0 : input_file = fopen(in_file, "rb");
124 : }
125 140 : if (!input_file) {
126 0 : fprintf(stderr, "could not open %s\n", in_file);
127 0 : exit(1);
128 : }
129 140 : num_rows = count_file_rows(input_file);
130 140 : fclose(input_file);
131 :
132 140 : dberrhandle(ignore_err_handler);
133 140 : dbmsghandle(ignore_msg_handler);
134 :
135 140 : printf("Creating table '%s'\n", TABLE_NAME);
136 140 : got_error = false;
137 140 : sql_cmd(dbproc);
138 140 : dbsqlexec(dbproc);
139 414 : while (dbresults(dbproc) != NO_MORE_RESULTS)
140 134 : continue;
141 :
142 140 : dberrhandle(syb_err_handler);
143 140 : dbmsghandle(syb_msg_handler);
144 :
145 140 : if (got_error)
146 16 : return;
147 :
148 124 : ret = sql_cmd(dbproc);
149 124 : printf("return from dbcmd = %d\n", ret);
150 :
151 124 : ret = dbsqlexec(dbproc);
152 124 : printf("return from dbsqlexec = %d\n", ret);
153 :
154 124 : if (dbresults(dbproc) != FAIL) {
155 124 : num_cols = dbnumcols(dbproc);
156 124 : printf("Number of columns = %d\n", num_cols);
157 :
158 124 : while (dbnextrow(dbproc) != NO_MORE_ROWS) {
159 : }
160 : }
161 :
162 : /* BCP in */
163 :
164 124 : printf("bcp_init with in_file as '%s'\n", in_file);
165 124 : ret = bcp_init(dbproc, TABLE_NAME, in_file, (char*) err_file, DB_IN);
166 124 : if (ret != SUCCEED)
167 0 : failure("bcp_init failed\n");
168 :
169 124 : printf("return from bcp_init = %d\n", ret);
170 :
171 124 : ret = bcp_columns(dbproc, num_cols);
172 124 : if (ret != SUCCEED)
173 0 : failure("bcp_columns failed\n");
174 124 : printf("return from bcp_columns = %d\n", ret);
175 :
176 720 : for (i = 1; i < num_cols; i++) {
177 596 : if ((ret = bcp_colfmt(dbproc, i, SYBCHAR, 0, -1, (BYTE *) "\t", sizeof(char), i)) == FAIL)
178 0 : failure("return from bcp_colfmt = %d\n", ret);
179 : }
180 :
181 124 : if ((ret = bcp_colfmt(dbproc, num_cols, SYBCHAR, 0, -1, (BYTE *) "\n", sizeof(char), num_cols)) == FAIL)
182 0 : failure("return from bcp_colfmt = %d\n", ret);
183 :
184 :
185 124 : ret = bcp_exec(dbproc, &rows_copied);
186 124 : if (ret != SUCCEED || rows_copied != num_rows)
187 0 : failure("bcp_exec failed\n");
188 :
189 124 : printf("%d rows copied in\n", rows_copied);
190 :
191 : /* BCP out */
192 :
193 124 : rows_copied = 0;
194 124 : ret = bcp_init(dbproc, TABLE_NAME, (char *) out_file, (char *) err_file, DB_OUT);
195 124 : if (ret != SUCCEED)
196 0 : failure("bcp_int failed\n");
197 :
198 124 : printf("select\n");
199 124 : sql_cmd(dbproc);
200 124 : dbsqlexec(dbproc);
201 :
202 124 : if (dbresults(dbproc) != FAIL) {
203 124 : num_cols = dbnumcols(dbproc);
204 124 : while (dbnextrow(dbproc) != NO_MORE_ROWS) {
205 : }
206 : }
207 :
208 124 : ret = bcp_columns(dbproc, num_cols);
209 :
210 720 : for (i = 1; i < num_cols; i++) {
211 596 : if ((ret = bcp_colfmt(dbproc, i, SYBCHAR, 0, -1, (BYTE *) "\t", sizeof(char), i)) == FAIL)
212 0 : failure("return from bcp_colfmt = %d\n", ret);
213 : }
214 :
215 124 : if ((ret = bcp_colfmt(dbproc, num_cols, SYBCHAR, 0, -1, (BYTE *) "\n", sizeof(char), num_cols)) == FAIL)
216 0 : failure("return from bcp_colfmt = %d\n", ret);
217 :
218 124 : ret = bcp_exec(dbproc, &rows_copied);
219 124 : if (ret != SUCCEED || rows_copied != num_rows)
220 0 : failure("bcp_exec failed\n");
221 :
222 124 : printf("%d rows copied out\n", rows_copied);
223 :
224 124 : printf("Dropping table '%s'\n", TABLE_NAME);
225 124 : sql_cmd(dbproc);
226 124 : dbsqlexec(dbproc);
227 372 : while (dbresults(dbproc) != NO_MORE_RESULTS)
228 124 : continue;
229 :
230 124 : if (failed)
231 : return;
232 :
233 124 : if (compare_files(in_file, out_file))
234 124 : printf("Input and output files are equal\n");
235 : else
236 0 : failed = true;
237 : }
238 :
239 : static size_t
240 1208 : fgets_raw(char *s, int len, FILE *f)
241 : {
242 1208 : char *p = s;
243 :
244 724630 : while (len > 1) {
245 723422 : int c = getc(f);
246 723422 : if (c == EOF) {
247 388 : if (ferror(f))
248 : return 0;
249 : break;
250 : }
251 723034 : *p++ = c;
252 723034 : --len;
253 723034 : if (c == '\n')
254 : break;
255 : }
256 1208 : if (len > 0)
257 1208 : *p = 0;
258 1208 : return p - s;
259 : }
260 :
261 : static bool
262 124 : compare_files(const char *fn1, const char *fn2)
263 : {
264 124 : bool equal = true;
265 : FILE *f1, *f2;
266 : size_t s1, s2;
267 :
268 : /* check input and output should be the same */
269 124 : f1 = fopen(fn1, "r");
270 124 : f2 = fopen(fn2, "r");
271 124 : if (f1 != NULL && f2 != NULL) {
272 : int line = 1;
273 :
274 260 : for (;; ++line) {
275 644 : s1 = fgets_raw(line1, sizeof(line1), f1);
276 384 : s2 = fgets_raw(line2, sizeof(line2), f2);
277 :
278 : /* EOF or error of one */
279 384 : if (!!s1 != !!s2) {
280 0 : equal = false;
281 0 : failure("error reading a file or EOF of a file\n");
282 0 : break;
283 : }
284 :
285 : /* EOF or error of both */
286 384 : if (!s1) {
287 124 : if (feof(f1) && feof(f2))
288 : break;
289 0 : equal = false;
290 0 : failure("error reading a file\n");
291 0 : break;
292 : }
293 :
294 260 : if (s1 != s2 || memcmp(line1, line2, s1) != 0) {
295 0 : equal = false;
296 0 : failure("File different at line %d\n"
297 : " input: %s"
298 : " output: %s",
299 : line, line1, line2);
300 : }
301 : }
302 : } else {
303 0 : equal = false;
304 0 : failure("error opening files\n");
305 : }
306 124 : if (f1)
307 124 : fclose(f1);
308 124 : if (f2)
309 124 : fclose(f2);
310 :
311 124 : return equal;
312 : }
313 :
314 : static unsigned
315 140 : count_file_rows(FILE *f)
316 : {
317 : size_t s;
318 140 : unsigned rows = 1;
319 140 : char last = '\n';
320 :
321 140 : assert(f);
322 :
323 440 : while ((s = fgets_raw(line1, sizeof(line1), f)) != 0) {
324 300 : last = line1[s-1];
325 300 : if (last == '\n')
326 300 : ++rows;
327 : }
328 140 : if (last == '\n')
329 140 : --rows;
330 140 : assert(!ferror(f));
331 140 : return rows;
332 : }
|