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