1 /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Brian Bruns
3 * Copyright (C) 2011 Frediano Ziglio
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <ctype.h>
25
26 #if HAVE_ERRNO_H
27 #include <errno.h>
28 #endif /* HAVE_ERRNO_H */
29
30 #if HAVE_STDLIB_H
31 #include <stdlib.h>
32 #endif /* HAVE_STDLIB_H */
33
34 /* These should be in stdlib */
35 #ifndef EXIT_SUCCESS
36 #define EXIT_SUCCESS 0
37 #endif
38 #ifndef EXIT_FAILURE
39 #define EXIT_FAILURE 1
40 #endif
41
42 #if HAVE_STRING_H
43 #include <string.h>
44 #endif /* HAVE_STRING_H */
45
46 #if HAVE_STRINGS_H
47 #include <strings.h>
48 #endif /* HAVE_STRINGS_H */
49
50 #if HAVE_UNISTD_H
51 #include <unistd.h>
52 #endif
53
54 #if HAVE_LOCALE_H
55 #include <locale.h>
56 #endif
57
58 #include <freetds/tds.h>
59 #include <freetds/utils.h>
60 #include <freetds/replacements.h>
61 #include <sybfront.h>
62 #include <sybdb.h>
63 #include "freebcp.h"
64
65 void pusage(void);
66 int process_parameters(int, char **, struct pd *);
67 static int unescape(char arg[]);
68 int login_to_database(struct pd *, DBPROCESS **);
69
70 int file_character(BCPPARAMDATA * pdata, DBPROCESS * dbproc, DBINT dir);
71 int file_native(BCPPARAMDATA * pdata, DBPROCESS * dbproc, DBINT dir);
72 int file_formatted(BCPPARAMDATA * pdata, DBPROCESS * dbproc, DBINT dir);
73 int setoptions (DBPROCESS * dbproc, BCPPARAMDATA * params);
74
75 int err_handler(DBPROCESS * dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr);
76 int msg_handler(DBPROCESS * dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname,
77 int line);
78 static int set_bcp_hints(BCPPARAMDATA *pdata, DBPROCESS *pdbproc);
79
80 int
main(int argc,char ** argv)81 main(int argc, char **argv)
82 {
83 BCPPARAMDATA params;
84 DBPROCESS *dbproc;
85 int ok = FALSE;
86
87 setlocale(LC_ALL, "");
88
89 #ifdef __VMS
90 /* Convert VMS-style arguments to Unix-style */
91 parse_vms_args(&argc, &argv);
92 #endif
93
94 memset(¶ms, '\0', sizeof(params));
95
96 params.textsize = 4096; /* our default text size is 4K */
97
98 if (process_parameters(argc, argv, ¶ms) == FALSE) {
99 exit(EXIT_FAILURE);
100 }
101 if (getenv("FREEBCP")) {
102 fprintf(stderr, "User name: \"%s\"\n", params.user);
103 }
104
105
106 if (login_to_database(¶ms, &dbproc) == FALSE) {
107 exit(EXIT_FAILURE);
108 }
109
110 if (!setoptions(dbproc, ¶ms))
111 return FALSE;
112
113 if (params.cflag) { /* character format file */
114 ok = file_character(¶ms, dbproc, params.direction);
115 } else if (params.nflag) { /* native format file */
116 ok = file_native(¶ms, dbproc, params.direction);
117 } else if (params.fflag) { /* formatted file */
118 ok = file_formatted(¶ms, dbproc, params.direction);
119 } else {
120 ok = FALSE;
121 }
122
123 exit((ok == TRUE) ? EXIT_SUCCESS : EXIT_FAILURE);
124
125 return 0;
126 }
127
128
unescape(char arg[])129 static int unescape(char arg[])
130 {
131 char *p = arg, *next;
132 char escaped;
133 while ((next = strchr(p, '\\')) != NULL) {
134
135 p = next;
136
137 switch (p[1]) {
138 case '0':
139 escaped = '\0';
140 break;
141 case 't':
142 escaped = '\t';
143 break;
144 case 'r':
145 escaped = '\r';
146 break;
147 case 'n':
148 escaped = '\n';
149 break;
150 case '\\':
151 escaped = '\\';
152 break;
153 default:
154 ++p;
155 continue;
156 }
157
158 /* Overwrite the backslash with the intended character, and shift everything down one */
159 *p++ = escaped;
160 memmove(p, p+1, 1 + strlen(p+1));
161 }
162 return strchr(p, 0) - arg;
163 }
164
165 int
process_parameters(int argc,char ** argv,BCPPARAMDATA * pdata)166 process_parameters(int argc, char **argv, BCPPARAMDATA *pdata)
167 {
168 extern char *optarg;
169 extern int optind;
170 extern int optopt;
171
172 int ch;
173
174 if (argc < 6) {
175 pusage();
176 return (FALSE);
177 }
178
179 /*
180 * Set some defaults and read the table, file, and direction arguments.
181 */
182 pdata->firstrow = 0;
183 pdata->lastrow = 0;
184 pdata->batchsize = 1000;
185 pdata->maxerrors = 10;
186
187 /* argument 1 - the database object */
188 pdata->dbobject = strdup(argv[1]);
189 if (pdata->dbobject == NULL) {
190 fprintf(stderr, "Out of memory!\n");
191 return FALSE;
192 }
193
194 /* argument 2 - the direction */
195 strlcpy(pdata->dbdirection, argv[2], sizeof(pdata->dbdirection));
196
197 if (strcasecmp(pdata->dbdirection, "in") == 0) {
198 pdata->direction = DB_IN;
199 } else if (strcasecmp(pdata->dbdirection, "out") == 0) {
200 pdata->direction = DB_OUT;
201 } else if (strcasecmp(pdata->dbdirection, "queryout") == 0) {
202 pdata->direction = DB_QUERYOUT;
203 } else {
204 fprintf(stderr, "Copy direction must be either 'in', 'out' or 'queryout'.\n");
205 return (FALSE);
206 }
207
208 /* argument 3 - the datafile name */
209 free(pdata->hostfilename);
210 pdata->hostfilename = strdup(argv[3]);
211
212 /*
213 * Get the rest of the arguments
214 */
215 optind = 4; /* start processing options after table, direction, & filename */
216 while ((ch = getopt(argc, argv, "m:f:e:F:L:b:t:r:U:P:i:I:S:h:T:A:o:O:0:C:ncEdvVD:")) != -1) {
217 switch (ch) {
218 case 'v':
219 case 'V':
220 printf("freebcp version %s\n", TDS_VERSION_NO);
221 return FALSE;
222 break;
223 case 'm':
224 pdata->mflag++;
225 pdata->maxerrors = atoi(optarg);
226 break;
227 case 'f':
228 pdata->fflag++;
229 free(pdata->formatfile);
230 pdata->formatfile = strdup(optarg);
231 break;
232 case 'e':
233 pdata->eflag++;
234 pdata->errorfile = strdup(optarg);
235 break;
236 case 'F':
237 pdata->Fflag++;
238 pdata->firstrow = atoi(optarg);
239 break;
240 case 'L':
241 pdata->Lflag++;
242 pdata->lastrow = atoi(optarg);
243 break;
244 case 'b':
245 pdata->bflag++;
246 pdata->batchsize = atoi(optarg);
247 break;
248 case 'n':
249 pdata->nflag++;
250 break;
251 case 'c':
252 pdata->cflag++;
253 break;
254 case 'E':
255 pdata->Eflag++;
256 break;
257 case 'd':
258 tdsdump_open("stderr");
259 break;
260 case 't':
261 pdata->tflag++;
262 pdata->fieldterm = strdup(optarg);
263 pdata->fieldtermlen = unescape(pdata->fieldterm);
264 break;
265 case 'r':
266 pdata->rflag++;
267 pdata->rowterm = strdup(optarg);
268 pdata->rowtermlen = unescape(pdata->rowterm);
269 break;
270 case 'U':
271 pdata->Uflag++;
272 pdata->user = strdup(optarg);
273 break;
274 case 'P':
275 pdata->Pflag++;
276 pdata->pass = tds_getpassarg(optarg);
277 break;
278 case 'i':
279 free(pdata->inputfile);
280 pdata->inputfile = strdup(optarg);
281 break;
282 case 'I':
283 pdata->Iflag++;
284 free(pdata->interfacesfile);
285 pdata->interfacesfile = strdup(optarg);
286 break;
287 case 'S':
288 pdata->Sflag++;
289 pdata->server = strdup(optarg);
290 break;
291 case 'D':
292 pdata->dbname = strdup(optarg);
293 break;
294 case 'h':
295 pdata->hint = strdup(optarg);
296 break;
297 case 'o':
298 free(pdata->outputfile);
299 pdata->outputfile = strdup(optarg);
300 break;
301 case 'O':
302 case '0':
303 pdata->options = strdup(optarg);
304 break;
305 case 'T':
306 pdata->Tflag++;
307 pdata->textsize = atoi(optarg);
308 break;
309 case 'A':
310 pdata->Aflag++;
311 pdata->packetsize = atoi(optarg);
312 break;
313 case 'C':
314 pdata->charset = strdup(optarg);
315 break;
316 case '?':
317 default:
318 pusage();
319 return (FALSE);
320 }
321 }
322
323 /*
324 * Check for required/disallowed option combinations
325 * If no username is provided, rely on domain login.
326 */
327
328 /* Server */
329 if (!pdata->Sflag) {
330 if ((pdata->server = getenv("DSQUERY")) != NULL) {
331 pdata->server = strdup(pdata->server); /* can be freed */
332 pdata->Sflag++;
333 } else {
334 fprintf(stderr, "-S must be supplied.\n");
335 return (FALSE);
336 }
337 }
338
339 /* Only one of these can be specified */
340 if (pdata->cflag + pdata->nflag + pdata->fflag != 1) {
341 fprintf(stderr, "Exactly one of options -c, -n, -f must be supplied.\n");
342 return (FALSE);
343 }
344
345 /* Character mode file: fill in default values */
346 if (pdata->cflag) {
347
348 if (!pdata->tflag || !pdata->fieldterm) { /* field terminator not specified */
349 pdata->fieldterm = "\t";
350 pdata->fieldtermlen = 1;
351 }
352 if (!pdata->rflag || !pdata->rowterm) { /* row terminator not specified */
353 pdata->rowterm = "\n";
354 pdata->rowtermlen = 1;
355 }
356 }
357
358 /*
359 * Override stdin and/or stdout if requested.
360 */
361
362 /* FIXME -- Since we don't implement prompting for field data types when neither -c nor -n
363 * is specified, redirecting stdin doesn't do much yet.
364 */
365 if (pdata->inputfile) {
366 if (freopen(pdata->inputfile, "rb", stdin) == NULL) {
367 fprintf(stderr, "%s: unable to open %s: %s\n", "freebcp", pdata->inputfile, strerror(errno));
368 exit(EXIT_FAILURE);
369 }
370 }
371
372 if (pdata->outputfile) {
373 if (freopen(pdata->outputfile, "wb", stdout) == NULL) {
374 fprintf(stderr, "%s: unable to open %s: %s\n", "freebcp", pdata->outputfile, strerror(errno));
375 exit(EXIT_FAILURE);
376 }
377 }
378
379 return (TRUE);
380
381 }
382
383 int
login_to_database(BCPPARAMDATA * pdata,DBPROCESS ** pdbproc)384 login_to_database(BCPPARAMDATA * pdata, DBPROCESS ** pdbproc)
385 {
386 LOGINREC *login;
387
388 /* Initialize DB-Library. */
389
390 if (dbinit() == FAIL)
391 return (FALSE);
392
393 /*
394 * Install the user-supplied error-handling and message-handling
395 * routines. They are defined at the bottom of this source file.
396 */
397
398 dberrhandle(err_handler);
399 dbmsghandle(msg_handler);
400
401 /* If the interfaces file was specified explicitly, set it. */
402 if (pdata->interfacesfile != NULL)
403 dbsetifile(pdata->interfacesfile);
404
405 /*
406 * Allocate and initialize the LOGINREC structure to be used
407 * to open a connection to SQL Server.
408 */
409
410 login = dblogin();
411 if (!login)
412 return FALSE;
413
414 if (pdata->user)
415 DBSETLUSER(login, pdata->user);
416 if (pdata->pass) {
417 DBSETLPWD(login, pdata->pass);
418 memset(pdata->pass, 0, strlen(pdata->pass));
419 }
420
421 DBSETLAPP(login, "FreeBCP");
422 if (pdata->charset)
423 DBSETLCHARSET(login, pdata->charset);
424
425 if (pdata->Aflag && pdata->packetsize > 0) {
426 DBSETLPACKET(login, pdata->packetsize);
427 }
428
429 if (pdata->dbname)
430 DBSETLDBNAME(login, pdata->dbname);
431
432 /* Enable bulk copy for this connection. */
433
434 BCP_SETL(login, TRUE);
435
436 /*
437 * Get a connection to the database.
438 */
439
440 if ((*pdbproc = dbopen(login, pdata->server)) == NULL) {
441 fprintf(stderr, "Can't connect to server \"%s\".\n", pdata->server);
442 dbloginfree(login);
443 return (FALSE);
444 }
445 dbloginfree(login);
446 login = NULL;
447
448 return (TRUE);
449
450 }
451
452 int
file_character(BCPPARAMDATA * pdata,DBPROCESS * dbproc,DBINT dir)453 file_character(BCPPARAMDATA * pdata, DBPROCESS * dbproc, DBINT dir)
454 {
455 DBINT li_rowsread = 0;
456 int i;
457 int li_numcols = 0;
458 RETCODE ret_code = 0;
459
460 if (FAIL == bcp_init(dbproc, pdata->dbobject, pdata->hostfilename, pdata->errorfile, dir))
461 return FALSE;
462
463 if (!set_bcp_hints(pdata, dbproc))
464 return FALSE;
465
466 if (pdata->Eflag) {
467
468 bcp_control(dbproc, BCPKEEPIDENTITY, 1);
469
470 if (dbfcmd(dbproc, "set identity_insert %s on", pdata->dbobject) == FAIL) {
471 fprintf(stderr, "dbfcmd failed\n");
472 return FALSE;
473 }
474
475 if (dbsqlexec(dbproc) == FAIL) {
476 fprintf(stderr, "dbsqlexec failed\n");
477 return FALSE;
478 }
479
480 while (NO_MORE_RESULTS != dbresults(dbproc))
481 continue;
482 }
483
484 bcp_control(dbproc, BCPFIRST, pdata->firstrow);
485 bcp_control(dbproc, BCPLAST, pdata->lastrow);
486 bcp_control(dbproc, BCPMAXERRS, pdata->maxerrors);
487
488 if (dir == DB_QUERYOUT) {
489 if (dbfcmd(dbproc, "SET FMTONLY ON %s SET FMTONLY OFF", pdata->dbobject) == FAIL) {
490 fprintf(stderr, "dbfcmd failed\n");
491 return FALSE;
492 }
493 } else {
494 if (dbfcmd(dbproc, "SET FMTONLY ON select * from %s SET FMTONLY OFF", pdata->dbobject) == FAIL) {
495 fprintf(stderr, "dbfcmd failed\n");
496 return FALSE;
497 }
498 }
499
500 if (dbsqlexec(dbproc) == FAIL) {
501 fprintf(stderr, "dbsqlexec failed\n");
502 return FALSE;
503 }
504
505 while (NO_MORE_RESULTS != (ret_code = dbresults(dbproc))) {
506 if (ret_code == SUCCEED && li_numcols == 0) {
507 li_numcols = dbnumcols(dbproc);
508 }
509 }
510
511 if (0 == li_numcols) {
512 fprintf(stderr, "Error in dbnumcols\n");
513 return FALSE;
514 }
515
516 if (bcp_columns(dbproc, li_numcols) == FAIL) {
517 fprintf(stderr, "Error in bcp_columns.\n");
518 return FALSE;
519 }
520
521 for (i = 1; i < li_numcols; ++i) {
522 if (bcp_colfmt(dbproc, i, SYBCHAR, 0, -1, (const BYTE *) pdata->fieldterm,
523 pdata->fieldtermlen, i) == FAIL) {
524 fprintf(stderr, "Error in bcp_colfmt col %d\n", i);
525 return FALSE;
526 }
527 }
528
529 if (bcp_colfmt(dbproc, li_numcols, SYBCHAR, 0, -1, (const BYTE *) pdata->rowterm,
530 pdata->rowtermlen, li_numcols) == FAIL) {
531 fprintf(stderr, "Error in bcp_colfmt col %d\n", li_numcols);
532 return FALSE;
533 }
534
535 bcp_control(dbproc, BCPBATCH, pdata->batchsize);
536
537 printf("\nStarting copy...\n");
538
539 if (FAIL == bcp_exec(dbproc, &li_rowsread)) {
540 fprintf(stderr, "bcp copy %s failed\n", (dir == DB_IN) ? "in" : "out");
541 return FALSE;
542 }
543
544 printf("%d rows copied.\n", li_rowsread);
545
546 return TRUE;
547 }
548
549 int
file_native(BCPPARAMDATA * pdata,DBPROCESS * dbproc,DBINT dir)550 file_native(BCPPARAMDATA * pdata, DBPROCESS * dbproc, DBINT dir)
551 {
552 DBINT li_rowsread = 0;
553 int i;
554 int li_numcols = 0;
555 int li_coltype;
556 RETCODE ret_code = 0;
557
558 if (FAIL == bcp_init(dbproc, pdata->dbobject, pdata->hostfilename, pdata->errorfile, dir))
559 return FALSE;
560
561 if (!set_bcp_hints(pdata, dbproc))
562 return FALSE;
563
564 if (pdata->Eflag) {
565
566 bcp_control(dbproc, BCPKEEPIDENTITY, 1);
567
568 if (dbfcmd(dbproc, "set identity_insert %s on", pdata->dbobject) == FAIL) {
569 fprintf(stderr, "dbfcmd failed\n");
570 return FALSE;
571 }
572
573 if (dbsqlexec(dbproc) == FAIL) {
574 fprintf(stderr, "dbsqlexec failed\n");
575 return FALSE;
576 }
577
578 while (NO_MORE_RESULTS != dbresults(dbproc))
579 continue;
580 }
581
582 bcp_control(dbproc, BCPFIRST, pdata->firstrow);
583 bcp_control(dbproc, BCPLAST, pdata->lastrow);
584 bcp_control(dbproc, BCPMAXERRS, pdata->maxerrors);
585
586 if (dir == DB_QUERYOUT) {
587 if (dbfcmd(dbproc, "SET FMTONLY ON %s SET FMTONLY OFF", pdata->dbobject) == FAIL) {
588 fprintf(stderr, "dbfcmd failed\n");
589 return FALSE;
590 }
591 } else {
592 if (dbfcmd(dbproc, "SET FMTONLY ON select * from %s SET FMTONLY OFF", pdata->dbobject) == FAIL) {
593 fprintf(stderr, "dbfcmd failed\n");
594 return FALSE;
595 }
596 }
597
598 if (dbsqlexec(dbproc) == FAIL) {
599 fprintf(stderr, "dbsqlexec failed\n");
600 return FALSE;
601 }
602
603 while (NO_MORE_RESULTS != (ret_code = dbresults(dbproc))) {
604 if (ret_code == SUCCEED && li_numcols == 0) {
605 li_numcols = dbnumcols(dbproc);
606 }
607 }
608
609 if (0 == li_numcols) {
610 fprintf(stderr, "Error in dbnumcols\n");
611 return FALSE;
612 }
613
614 if (bcp_columns(dbproc, li_numcols) == FAIL) {
615 fprintf(stderr, "Error in bcp_columns.\n");
616 return FALSE;
617 }
618
619 for (i = 1; i <= li_numcols; i++) {
620 li_coltype = dbcoltype(dbproc, i);
621
622 if (bcp_colfmt(dbproc, i, li_coltype, -1, -1, NULL, -1, i) == FAIL) {
623 fprintf(stderr, "Error in bcp_colfmt col %d\n", i);
624 return FALSE;
625 }
626 }
627
628 printf("\nStarting copy...\n\n");
629
630
631 if (FAIL == bcp_exec(dbproc, &li_rowsread)) {
632 fprintf(stderr, "bcp copy %s failed\n", (dir == DB_IN) ? "in" : "out");
633 return FALSE;
634 }
635
636 printf("%d rows copied.\n", li_rowsread);
637
638 return TRUE;
639 }
640
641 int
file_formatted(BCPPARAMDATA * pdata,DBPROCESS * dbproc,DBINT dir)642 file_formatted(BCPPARAMDATA * pdata, DBPROCESS * dbproc, DBINT dir)
643 {
644
645 int li_rowsread;
646
647 if (FAIL == bcp_init(dbproc, pdata->dbobject, pdata->hostfilename, pdata->errorfile, dir))
648 return FALSE;
649
650 if (!set_bcp_hints(pdata, dbproc))
651 return FALSE;
652
653 if (pdata->Eflag) {
654
655 bcp_control(dbproc, BCPKEEPIDENTITY, 1);
656
657 if (dbfcmd(dbproc, "set identity_insert %s on", pdata->dbobject) == FAIL) {
658 fprintf(stderr, "dbfcmd failed\n");
659 return FALSE;
660 }
661
662 if (dbsqlexec(dbproc) == FAIL) {
663 fprintf(stderr, "dbsqlexec failed\n");
664 return FALSE;
665 }
666
667 while (NO_MORE_RESULTS != dbresults(dbproc))
668 continue;
669 }
670
671 bcp_control(dbproc, BCPFIRST, pdata->firstrow);
672 bcp_control(dbproc, BCPLAST, pdata->lastrow);
673 bcp_control(dbproc, BCPMAXERRS, pdata->maxerrors);
674
675 if (FAIL == bcp_readfmt(dbproc, pdata->formatfile))
676 return FALSE;
677
678 printf("\nStarting copy...\n\n");
679
680
681 if (FAIL == bcp_exec(dbproc, &li_rowsread)) {
682 fprintf(stderr, "bcp copy %s failed\n", (dir == DB_IN) ? "in" : "out");
683 return FALSE;
684 }
685
686 printf("%d rows copied.\n", li_rowsread);
687
688 return TRUE;
689 }
690
691
692 int
setoptions(DBPROCESS * dbproc,BCPPARAMDATA * params)693 setoptions(DBPROCESS * dbproc, BCPPARAMDATA * params)
694 {
695 RETCODE fOK;
696
697 if (dbfcmd(dbproc, "set textsize %d ", params->textsize) == FAIL) {
698 fprintf(stderr, "setoptions() could not set textsize at %s:%d\n", __FILE__, __LINE__);
699 return FALSE;
700 }
701
702 /*
703 * If the option is a filename, read the SQL text from the file.
704 * Else pass the option verbatim to the server.
705 */
706 if (params->options) {
707 FILE *optFile;
708 char optBuf[256];
709
710 if ((optFile = fopen(params->options, "r")) == NULL) {
711 if (dbcmd(dbproc, params->options) == FAIL) {
712 fprintf(stderr, "setoptions() failed preparing options at %s:%d\n", __FILE__, __LINE__);
713 return FALSE;
714 }
715 } else {
716 while (fgets (optBuf, sizeof(optBuf), optFile) != NULL) {
717 if (dbcmd(dbproc, optBuf) == FAIL) {
718 fprintf(stderr, "setoptions() failed preparing options at %s:%d\n", __FILE__, __LINE__);
719 fclose(optFile);
720 return FALSE;
721 }
722 }
723 if (!feof (optFile)) {
724 perror("freebcp");
725 fprintf(stderr, "error reading options file \"%s\" at %s:%d\n", params->options, __FILE__, __LINE__);
726 fclose(optFile);
727 return FALSE;
728 }
729 fclose(optFile);
730 }
731 }
732
733 if (dbsqlexec(dbproc) == FAIL) {
734 fprintf(stderr, "setoptions() failed sending options at %s:%d\n", __FILE__, __LINE__);
735 return FALSE;
736 }
737
738 while ((fOK = dbresults(dbproc)) == SUCCEED) {
739 while ((fOK = dbnextrow(dbproc)) == REG_ROW)
740 continue;
741 if (fOK == FAIL) {
742 fprintf(stderr, "setoptions() failed sending options at %s:%d\n", __FILE__, __LINE__);
743 return FALSE;
744 }
745 }
746 if (fOK == FAIL) {
747 fprintf(stderr, "setoptions() failed sending options at %s:%d\n", __FILE__, __LINE__);
748 return FALSE;
749 }
750
751 return TRUE;
752 }
753
754 static int
set_bcp_hints(BCPPARAMDATA * pdata,DBPROCESS * pdbproc)755 set_bcp_hints(BCPPARAMDATA *pdata, DBPROCESS *pdbproc)
756 {
757 /* set hint if any */
758 if (pdata->hint) {
759 if (bcp_options(pdbproc, BCPHINTS, (BYTE *) pdata->hint, strlen(pdata->hint)) != SUCCEED) {
760 fprintf(stderr, "db-lib: Unable to set hint \"%s\"\n", pdata->hint);
761 return FALSE;
762 }
763 }
764 return TRUE;
765 }
766
767 void
pusage(void)768 pusage(void)
769 {
770 fprintf(stderr, "usage: freebcp [[database_name.]owner.]table_name|query {in | out | queryout } datafile\n");
771 fprintf(stderr, " [-m maxerrors] [-f formatfile] [-e errfile]\n");
772 fprintf(stderr, " [-F firstrow] [-L lastrow] [-b batchsize]\n");
773 fprintf(stderr, " [-n] [-c] [-t field_terminator] [-r row_terminator]\n");
774 fprintf(stderr, " [-U username] [-P password] [-I interfaces_file] [-S server] [-D database]\n");
775 fprintf(stderr, " [-v] [-d] [-h \"hint [,...]\" [-O \"set connection_option on|off, ...]\"\n");
776 fprintf(stderr, " [-A packet size] [-T text or image size] [-E]\n");
777 fprintf(stderr, " [-i input_file] [-o output_file]\n");
778 fprintf(stderr, " \n");
779 fprintf(stderr, "example: freebcp testdb.dbo.inserttest in inserttest.txt -S mssql -U guest -P password -c\n");
780 }
781
782 int
err_handler(DBPROCESS * dbproc,int severity,int dberr,int oserr,char * dberrstr,char * oserrstr)783 err_handler(DBPROCESS * dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
784 {
785 static int sent = 0;
786
787 if (dberr == SYBEBBCI) { /* Batch successfully bulk copied to the server */
788 int batch = bcp_getbatchsize(dbproc);
789 printf("%d rows sent to SQL Server.\n", sent += batch);
790 return INT_CANCEL;
791 }
792
793 if (dberr) {
794 fprintf(stderr, "Msg %d, Level %d\n", dberr, severity);
795 fprintf(stderr, "%s\n\n", dberrstr);
796 }
797
798 else {
799 fprintf(stderr, "DB-LIBRARY error:\n\t");
800 fprintf(stderr, "%s\n", dberrstr);
801 }
802
803 return INT_CANCEL;
804 }
805
806 int
msg_handler(DBPROCESS * dbproc,DBINT msgno,int msgstate,int severity,char * msgtext,char * srvname,char * procname,int line)807 msg_handler(DBPROCESS * dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line)
808 {
809 /*
810 * If it's a database change message, we'll ignore it.
811 * Also ignore language change message.
812 */
813 if (msgno == 5701 || msgno == 5703)
814 return (0);
815
816 fprintf(stderr, "Msg %ld, Level %d, State %d\n", (long) msgno, severity, msgstate);
817
818 if (strlen(srvname) > 0)
819 fprintf(stderr, "Server '%s', ", srvname);
820 if (strlen(procname) > 0)
821 fprintf(stderr, "Procedure '%s', ", procname);
822 if (line > 0)
823 fprintf(stderr, "Line %d", line);
824
825 fprintf(stderr, "\n\t%s\n", msgtext);
826
827 return (0);
828 }
829