Skip to content

Commit f42360d

Browse files
mmcnabb-vmsfreddy77
authored andcommitted
Refactor FreeBCP main loop to reduce code duplication
1 parent de2210b commit f42360d

File tree

1 file changed

+69
-104
lines changed

1 file changed

+69
-104
lines changed

src/apps/freebcp.c

Lines changed: 69 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,22 @@
6666

6767
#include "freebcp.h"
6868

69+
enum
70+
{
71+
BCPFORMAT_NONE, BCPFORMAT_CHARACTER, BCPFORMAT_NATIVE, BCPFORMAT_FORMATTED
72+
};
73+
typedef int BCPFORMAT;
74+
6975
int tdsdump_open(const char *filename);
7076

7177
static void pusage(void);
7278
static int process_parameters(int, char **, BCPPARAMDATA *);
7379
static int unescape(char arg[]);
7480
static int login_to_database(BCPPARAMDATA * pdata, DBPROCESS ** pdbproc);
7581

76-
static int file_character(BCPPARAMDATA * pdata, DBPROCESS * dbproc, DBINT dir);
77-
static int file_native(BCPPARAMDATA * pdata, DBPROCESS * dbproc, DBINT dir);
78-
static int file_formatted(BCPPARAMDATA * pdata, DBPROCESS * dbproc, DBINT dir);
7982
static int setoptions(DBPROCESS * dbproc, BCPPARAMDATA * params);
80-
83+
static BCPFORMAT get_format(BCPPARAMDATA * params);
84+
static int file_process(BCPPARAMDATA * pdata, DBPROCESS * dbproc, DBINT dir);
8185
static int err_handler(DBPROCESS * dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr);
8286
static int msg_handler(DBPROCESS * dbproc TDS_UNUSED, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname,
8387
char *procname, int line);
@@ -116,21 +120,27 @@ main(int argc, char **argv)
116120
if (!setoptions(dbproc, &params))
117121
return FALSE;
118122

119-
if (params.cflag) { /* character format file */
120-
ok = file_character(&params, dbproc, params.direction);
121-
} else if (params.nflag) { /* native format file */
122-
ok = file_native(&params, dbproc, params.direction);
123-
} else if (params.fflag) { /* formatted file */
124-
ok = file_formatted(&params, dbproc, params.direction);
125-
} else {
126-
ok = FALSE;
127-
}
123+
ok = file_process(&params, dbproc, params.direction);
128124

129125
exit((ok == TRUE) ? EXIT_SUCCESS : EXIT_FAILURE);
130126

131127
return 0;
132128
}
133129

130+
static BCPFORMAT
131+
get_format(BCPPARAMDATA *params)
132+
{
133+
if (params->cflag)
134+
return BCPFORMAT_CHARACTER;
135+
136+
if (params->nflag)
137+
return BCPFORMAT_NATIVE;
138+
139+
if (params->fflag)
140+
return BCPFORMAT_FORMATTED;
141+
142+
return BCPFORMAT_NONE;
143+
}
134144

135145
static int unescape(char arg[])
136146
{
@@ -478,62 +488,39 @@ login_to_database(BCPPARAMDATA *pdata, DBPROCESS **pdbproc)
478488

479489
}
480490

481-
static int
482-
file_character(BCPPARAMDATA *pdata, DBPROCESS *dbproc, DBINT dir)
491+
static RETCODE
492+
format_column(BCPPARAMDATA *pdata, DBPROCESS *dbproc, BCPFORMAT file_format, int i, int is_last_column)
483493
{
484-
DBINT li_rowsread = 0;
485-
int i;
486-
int li_numcols = 0;
487-
488-
if (FAIL == bcp_init(dbproc, pdata->dbobject, pdata->hostfilename, pdata->errorfile, dir))
489-
return FALSE;
494+
int li_coltype = SYBCHAR;
495+
int host_prefixlen = 0;
496+
char *host_term = NULL;
497+
int host_termlen = -1;
490498

491-
if (!set_bcp_hints(pdata, dbproc))
492-
return FALSE;
493-
494-
bcp_control(dbproc, BCPFIRST, pdata->firstrow);
495-
bcp_control(dbproc, BCPLAST, pdata->lastrow);
496-
bcp_control(dbproc, BCPMAXERRS, pdata->maxerrors);
497-
498-
/* Reformat columns to SYBCHAR instead of native type, and add column and row terminator strings */
499-
li_numcols = bcp_gethostcolcount(dbproc);
500-
for (i = 1; i < li_numcols; ++i) {
501-
if (bcp_colfmt(dbproc, i, SYBCHAR, 0, -1, (const BYTE *) pdata->fieldterm,
502-
pdata->fieldtermlen, i) == FAIL) {
503-
fprintf(stderr, "Error in bcp_colfmt col %d\n", i);
504-
return FALSE;
505-
}
506-
}
507-
508-
if (bcp_colfmt(dbproc, li_numcols, SYBCHAR, 0, -1, (const BYTE *) pdata->rowterm,
509-
pdata->rowtermlen, li_numcols) == FAIL) {
510-
fprintf(stderr, "Error in bcp_colfmt col %d\n", li_numcols);
511-
return FALSE;
512-
}
513-
514-
bcp_control(dbproc, BCPBATCH, pdata->batchsize);
515-
if (!process_Eflag(pdata, dbproc))
516-
return FALSE;
517-
518-
printf("\nStarting copy...\n");
519-
520-
if (FAIL == bcp_exec(dbproc, &li_rowsread)) {
521-
fprintf(stderr, "bcp copy %s failed\n", (dir == DB_IN) ? "in" : "out");
522-
return FALSE;
499+
if (file_format == BCPFORMAT_NATIVE) {
500+
li_coltype = dbcoltype(dbproc, i);
501+
host_prefixlen = -1;
502+
} else if (is_last_column) {
503+
host_term = pdata->rowterm;
504+
host_termlen = pdata->rowtermlen;
505+
} else {
506+
host_term = pdata->fieldterm;
507+
host_termlen = pdata->fieldtermlen;
523508
}
524509

525-
printf("%d rows copied.\n", li_rowsread);
526-
527-
return TRUE;
510+
return bcp_colfmt(dbproc, i, li_coltype, host_prefixlen, -1, (const BYTE *) host_term, host_termlen, i);
528511
}
529512

530513
static int
531-
file_native(BCPPARAMDATA *pdata, DBPROCESS *dbproc, DBINT dir)
514+
file_process(BCPPARAMDATA *pdata, DBPROCESS *dbproc, DBINT dir)
532515
{
533516
DBINT li_rowsread = 0;
534517
int i;
535-
int li_numcols = 0;
536-
int li_coltype;
518+
int li_numcols;
519+
520+
BCPFORMAT file_format = get_format(pdata);
521+
522+
if (file_format == BCPFORMAT_NONE)
523+
return FALSE;
537524

538525
if (FAIL == bcp_init(dbproc, pdata->dbobject, pdata->hostfilename, pdata->errorfile, dir))
539526
return FALSE;
@@ -545,61 +532,39 @@ file_native(BCPPARAMDATA *pdata, DBPROCESS *dbproc, DBINT dir)
545532
bcp_control(dbproc, BCPLAST, pdata->lastrow);
546533
bcp_control(dbproc, BCPMAXERRS, pdata->maxerrors);
547534

548-
li_numcols = bcp_gethostcolcount(dbproc);
549-
550-
/* The data file does not use TDS nullable types. It uses non-nullable
551-
* representations, and a Length prefix if the target column was nullable.
552-
* The length prefix typically takes value 0 or -1 to indicate a null.
553-
*/
554-
for (i = 1; i <= li_numcols; i++) {
555-
li_coltype = dbcoltype(dbproc, i);
556-
557-
if (bcp_colfmt(dbproc, i, li_coltype, -1, -1, NULL, -1, i) == FAIL) {
558-
fprintf(stderr, "Error in bcp_colfmt col %d\n", i);
535+
switch (file_format) {
536+
case BCPFORMAT_FORMATTED:
537+
if (FAIL == bcp_readfmt(dbproc, pdata->formatfile))
559538
return FALSE;
539+
break;
540+
541+
/* The data file does not use TDS nullable types. It uses non-nullable
542+
* representations, and a Length prefix if the target column was nullable.
543+
* The length prefix typically takes value 0 or -1 to indicate a null.
544+
* So, we need to check format of all columns.
545+
*/
546+
case BCPFORMAT_NATIVE:
547+
case BCPFORMAT_CHARACTER:
548+
li_numcols = bcp_gethostcolcount(dbproc);
549+
for (i = 1; i <= li_numcols; ++i) {
550+
if (format_column(pdata, dbproc, file_format, i, i == li_numcols) == FAIL) {
551+
fprintf(stderr, "Error in bcp_colfmt col %d\n", i);
552+
return FALSE;
553+
}
560554
}
555+
break;
561556
}
562557

563-
if (!process_Eflag(pdata, dbproc))
564-
return FALSE;
565-
566-
printf("\nStarting copy...\n\n");
567-
568-
if (FAIL == bcp_exec(dbproc, &li_rowsread)) {
569-
fprintf(stderr, "bcp copy %s failed\n", (dir == DB_IN) ? "in" : "out");
570-
return FALSE;
571-
}
572-
573-
printf("%d rows copied.\n", li_rowsread);
574-
575-
return TRUE;
576-
}
577-
578-
static int
579-
file_formatted(BCPPARAMDATA *pdata, DBPROCESS *dbproc, DBINT dir)
580-
{
581-
582-
int li_rowsread;
583-
584-
if (FAIL == bcp_init(dbproc, pdata->dbobject, pdata->hostfilename, pdata->errorfile, dir))
585-
return FALSE;
586-
587-
if (!set_bcp_hints(pdata, dbproc))
588-
return FALSE;
558+
if (file_format == BCPFORMAT_CHARACTER)
559+
bcp_control(dbproc, BCPBATCH, pdata->batchsize);
589560

561+
/* note: process_Eflag frees data needed by format_column() for NATIVE type,
562+
* so call this after the column loop. */
590563
if (!process_Eflag(pdata, dbproc))
591564
return FALSE;
592565

593-
bcp_control(dbproc, BCPFIRST, pdata->firstrow);
594-
bcp_control(dbproc, BCPLAST, pdata->lastrow);
595-
bcp_control(dbproc, BCPMAXERRS, pdata->maxerrors);
596-
597-
if (FAIL == bcp_readfmt(dbproc, pdata->formatfile))
598-
return FALSE;
599-
600566
printf("\nStarting copy...\n\n");
601567

602-
603568
if (FAIL == bcp_exec(dbproc, &li_rowsread)) {
604569
fprintf(stderr, "bcp copy %s failed\n", (dir == DB_IN) ? "in" : "out");
605570
return FALSE;

0 commit comments

Comments
 (0)