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