00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #if HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023
00024 #include <stdio.h>
00025 #include <assert.h>
00026
00027 #if HAVE_STRING_H
00028 #include <string.h>
00029 #endif
00030
00031 #if HAVE_STDLIB_H
00032 #include <stdlib.h>
00033 #endif
00034
00035 #if HAVE_UNISTD_H
00036 #include <unistd.h>
00037 #endif
00038
00039 #include "tds.h"
00040 #include "tdsiconv.h"
00041 #include "tdsconvert.h"
00042 #include "replacements.h"
00043 #include "sybfront.h"
00044 #include "sybdb.h"
00045 #include "syberror.h"
00046 #include "dblib.h"
00047
00048 #ifdef DMALLOC
00049 #include <dmalloc.h>
00050 #endif
00051
00052 #define HOST_COL_CONV_ERROR 1
00053 #define HOST_COL_NULL_ERROR 2
00054
00055 #define BCP_REC_FETCH_DATA 1
00056 #define BCP_REC_NOFETCH_DATA 0
00057
00058 #ifndef MAX
00059 #define MAX(a,b) ( (a) > (b) ? (a) : (b) )
00060 #endif
00061
00062 typedef struct _pbcb
00063 {
00064 char *pb;
00065 int cb;
00066 unsigned int from_malloc;
00067 }
00068 TDS_PBCB;
00069
00070 TDS_RCSID(var, "$Id: bcp.c 174668 2009-10-29 19:44:31Z ivanovp $");
00071
00072 #ifdef HAVE_FSEEKO
00073 typedef off_t offset_type;
00074 #else
00075 #define fseeko(f,o,w) fseek(f,o,w)
00076 #define ftello(f) ftell(f)
00077 typedef long offset_type;
00078 #endif
00079
00080 static RETCODE _bcp_send_bcp_record(DBPROCESS * dbproc, int behaviour);
00081 static RETCODE _bcp_build_bulk_insert_stmt(TDSSOCKET *, TDS_PBCB *, TDSCOLUMN *, int);
00082 static RETCODE _bcp_free_storage(DBPROCESS * dbproc);
00083 static void _bcp_free_columns(DBPROCESS * dbproc);
00084 static RETCODE _bcp_get_col_data(DBPROCESS * dbproc, TDSCOLUMN *bindcol);
00085 static RETCODE _bcp_send_colmetadata(DBPROCESS *);
00086 static RETCODE _bcp_start_copy_in(DBPROCESS *);
00087 static RETCODE _bcp_start_new_batch(DBPROCESS *);
00088
00089 static int rtrim(char *, int);
00090 static offset_type _bcp_measure_terminated_field(FILE * hostfile, BYTE * terminator, int term_len);
00091 static RETCODE _bcp_read_hostfile(DBPROCESS * dbproc, FILE * hostfile, int *row_error);
00092 static int _bcp_readfmt_colinfo(DBPROCESS * dbproc, char *buf, BCP_HOSTCOLINFO * ci);
00093 static RETCODE _bcp_get_term_var(BYTE * pdata, BYTE * term, int term_len);
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 RETCODE
00118 bcp_init(DBPROCESS * dbproc, const char *tblname, const char *hfile, const char *errfile, int direction)
00119 {
00120 TDSRESULTINFO *resinfo;
00121 TDSRESULTINFO *bindinfo;
00122 TDSCOLUMN *curcol;
00123
00124 TDS_INT result_type;
00125 int i, rc;
00126
00127 if (dbproc == NULL) {
00128 dbperror(dbproc, SYBENULL, 0);
00129 return (FAIL);
00130 }
00131
00132
00133
00134 _bcp_free_storage(dbproc);
00135
00136
00137
00138
00139 #define SYBETDSVER -100
00140 if (dbproc->tds_socket->major_version < 5) {
00141 dbperror(dbproc, SYBETDSVER, 0);
00142 return (FAIL);
00143 }
00144
00145 if (tblname == NULL) {
00146 dbperror(dbproc, SYBEBCITBNM, 0);
00147 return (FAIL);
00148 }
00149
00150
00151 if (strlen(tblname) > 92) {
00152 dbperror(dbproc, SYBEBCITBLEN, 0);
00153 return (FAIL);
00154 }
00155
00156 if (direction != DB_IN && direction != DB_OUT && direction != DB_QUERYOUT) {
00157 dbperror(dbproc, SYBEBDIO, 0);
00158 return (FAIL);
00159 }
00160
00161 if (hfile != NULL) {
00162
00163 dbproc->hostfileinfo = calloc(1, sizeof(BCP_HOSTFILEINFO));
00164
00165 if (dbproc->hostfileinfo == NULL)
00166 goto memory_error;
00167 if ((dbproc->hostfileinfo->hostfile = strdup(hfile)) == NULL)
00168 goto memory_error;
00169
00170 if (errfile != NULL)
00171 if ((dbproc->hostfileinfo->errorfile = strdup(errfile)) == NULL)
00172 goto memory_error;
00173 } else {
00174 dbproc->hostfileinfo = NULL;
00175 }
00176
00177
00178
00179 dbproc->bcpinfo = malloc(sizeof(DB_BCPINFO));
00180 if (dbproc->bcpinfo == NULL)
00181 goto memory_error;
00182
00183 memset(dbproc->bcpinfo, '\0', sizeof(DB_BCPINFO));
00184
00185 if ((dbproc->bcpinfo->tablename = strdup(tblname)) == NULL)
00186 goto memory_error;
00187
00188 dbproc->bcpinfo->direction = direction;
00189
00190 dbproc->bcpinfo->xfer_init = 0;
00191 dbproc->bcpinfo->var_cols = 0;
00192 dbproc->bcpinfo->bind_count = 0;
00193
00194 if (direction == DB_IN) {
00195 TDSSOCKET *tds = dbproc->tds_socket;
00196
00197 if (tds_submit_queryf(tds, "SET FMTONLY ON select * from %s SET FMTONLY OFF", dbproc->bcpinfo->tablename) == TDS_FAIL) {
00198 return FAIL;
00199 }
00200
00201
00202 while ((rc = tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS))
00203 == TDS_SUCCEED) {
00204 }
00205 if (rc != TDS_NO_MORE_RESULTS) {
00206 return FAIL;
00207 }
00208
00209 if (!tds->res_info) {
00210 return FAIL;
00211 }
00212
00213
00214 resinfo = tds->res_info;
00215 if ((bindinfo = tds_alloc_results(resinfo->num_cols)) == NULL) {
00216 return FAIL;
00217 }
00218
00219 bindinfo->row_size = resinfo->row_size;
00220
00221 dbproc->bcpinfo->bindinfo = bindinfo;
00222 dbproc->bcpinfo->bind_count = 0;
00223
00224
00225 for (i = 0; i < bindinfo->num_cols; i++) {
00226
00227 curcol = bindinfo->columns[i];
00228
00229
00230
00231
00232
00233
00234
00235
00236 curcol->column_type = resinfo->columns[i]->column_type;
00237 curcol->column_usertype = resinfo->columns[i]->column_usertype;
00238 curcol->column_flags = resinfo->columns[i]->column_flags;
00239 curcol->column_size = resinfo->columns[i]->column_size;
00240 curcol->column_varint_size = resinfo->columns[i]->column_varint_size;
00241 curcol->column_prec = resinfo->columns[i]->column_prec;
00242 curcol->column_scale = resinfo->columns[i]->column_scale;
00243 curcol->column_namelen = resinfo->columns[i]->column_namelen;
00244 curcol->on_server.column_type = resinfo->columns[i]->on_server.column_type;
00245 curcol->on_server.column_size = resinfo->columns[i]->on_server.column_size;
00246 curcol->char_conv = resinfo->columns[i]->char_conv;
00247 memcpy(curcol->column_name, resinfo->columns[i]->column_name, resinfo->columns[i]->column_namelen);
00248 curcol->column_nullable = resinfo->columns[i]->column_nullable;
00249 curcol->column_identity = resinfo->columns[i]->column_identity;
00250 curcol->column_timestamp = resinfo->columns[i]->column_timestamp;
00251
00252 memcpy(curcol->column_collation, resinfo->columns[i]->column_collation, 5);
00253
00254 if (is_numeric_type(curcol->column_type)) {
00255 curcol->bcp_column_data = tds_alloc_bcp_column_data(sizeof(TDS_NUMERIC));
00256 ((TDS_NUMERIC *) curcol->bcp_column_data->data)->precision = curcol->column_prec;
00257 ((TDS_NUMERIC *) curcol->bcp_column_data->data)->scale = curcol->column_scale;
00258 } else {
00259 curcol->bcp_column_data = tds_alloc_bcp_column_data(MAX(curcol->column_size,curcol->on_server.column_size));
00260 }
00261 }
00262
00263
00264 bindinfo->current_row = tds_alloc_row(bindinfo);
00265
00266 }
00267
00268 return SUCCEED;
00269
00270 memory_error:
00271 _bcp_free_storage(dbproc);
00272 dbperror(dbproc, SYBEMEM, ENOMEM);
00273 return FAIL;
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 RETCODE
00293 bcp_collen(DBPROCESS * dbproc, DBINT varlen, int table_column)
00294 {
00295 TDSCOLUMN *curcol;
00296
00297 if (dbproc->bcpinfo == NULL) {
00298 dbperror(dbproc, SYBEBCPI, 0);
00299 return FAIL;
00300 }
00301
00302 if (dbproc->bcpinfo->direction != DB_IN) {
00303 dbperror(dbproc, SYBEBCPN, 0);
00304 return FAIL;
00305 }
00306
00307 if (dbproc->hostfileinfo != NULL) {
00308 dbperror(dbproc, SYBEBCPI, 0);
00309 return FAIL;
00310 }
00311
00312
00313 if (table_column <= 0 || table_column > dbproc->bcpinfo->bindinfo->num_cols)
00314 return FAIL;
00315
00316 curcol = dbproc->bcpinfo->bindinfo->columns[table_column - 1];
00317 curcol->column_bindlen = varlen;
00318
00319 return SUCCEED;
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 RETCODE
00334 bcp_columns(DBPROCESS * dbproc, int host_colcount)
00335 {
00336
00337 int i;
00338
00339 if (dbproc->bcpinfo == NULL) {
00340 dbperror(dbproc, SYBEBCPI, 0);
00341 return FAIL;
00342 }
00343
00344 if (dbproc->hostfileinfo == NULL) {
00345 dbperror(dbproc, SYBEBIVI, 0);
00346 return FAIL;
00347 }
00348
00349 if (host_colcount < 1) {
00350 dbperror(dbproc, SYBEBCFO, 0);
00351 return FAIL;
00352 }
00353
00354 _bcp_free_columns(dbproc);
00355
00356
00357
00358 dbproc->hostfileinfo->host_columns = (BCP_HOSTCOLINFO **) malloc(host_colcount * sizeof(BCP_HOSTCOLINFO *));
00359 if (dbproc->hostfileinfo->host_columns == NULL) {
00360 dbperror(dbproc, SYBEMEM, ENOMEM);
00361 return FAIL;
00362 }
00363 dbproc->hostfileinfo->host_colcount = host_colcount;
00364
00365 for (i = 0; i < host_colcount; i++) {
00366 dbproc->hostfileinfo->host_columns[i] = (BCP_HOSTCOLINFO *) malloc(sizeof(BCP_HOSTCOLINFO));
00367 if (dbproc->hostfileinfo->host_columns[i] == NULL) {
00368 dbproc->hostfileinfo->host_colcount = i;
00369 _bcp_free_columns(dbproc);
00370 dbperror(dbproc, SYBEMEM, ENOMEM);
00371 return FAIL;
00372 }
00373 memset(dbproc->hostfileinfo->host_columns[i], '\0', sizeof(BCP_HOSTCOLINFO));
00374 }
00375
00376 return SUCCEED;
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 RETCODE
00418 bcp_colfmt(DBPROCESS * dbproc, int host_colnum, int host_type, int host_prefixlen, DBINT host_collen, const BYTE * host_term,
00419 int host_termlen, int table_colnum)
00420 {
00421 BCP_HOSTCOLINFO *hostcol;
00422
00423
00424 if (dbproc->msdblib && host_termlen == 0)
00425 host_termlen = -1;
00426
00427 if (dbproc->bcpinfo == NULL) {
00428 dbperror(dbproc, SYBEBCPI, 0);
00429 return FAIL;
00430 }
00431
00432 if (dbproc->hostfileinfo == NULL) {
00433 dbperror(dbproc, SYBEBIVI, 0);
00434 return FAIL;
00435 }
00436
00437 if (dbproc->hostfileinfo->host_colcount == 0) {
00438 dbperror(dbproc, SYBEBCBC, 0);
00439 return FAIL;
00440 }
00441
00442 if (host_colnum < 1)
00443 return FAIL;
00444
00445 if (host_prefixlen != 0 && host_prefixlen != 1 && host_prefixlen != 2 && host_prefixlen != 4 && host_prefixlen != -1) {
00446 dbperror(dbproc, SYBEBCPREF, 0);
00447 return FAIL;
00448 }
00449
00450 if (table_colnum <= 0 && host_type == 0) {
00451 dbperror(dbproc, SYBEBCPCTYP, 0);
00452 return FAIL;
00453 }
00454
00455 if (host_prefixlen == 0 && host_collen == -1 && host_termlen == -1 && !is_fixed_type(host_type)) {
00456 dbperror(dbproc, SYBEVDPT, 0);
00457 return FAIL;
00458 }
00459
00460 if (host_collen < -1) {
00461 dbperror(dbproc, SYBEBCHLEN, 0);
00462 return FAIL;
00463 }
00464
00465
00466 if (is_fixed_type(host_type) && (host_collen != -1 && host_collen != 0))
00467 return FAIL;
00468
00469
00470
00471
00472
00473
00474 if (host_termlen > 0 && host_term == NULL)
00475 return FAIL;
00476
00477 hostcol = dbproc->hostfileinfo->host_columns[host_colnum - 1];
00478
00479
00480 hostcol->host_column = host_colnum;
00481 hostcol->datatype = host_type;
00482 hostcol->prefix_len = host_prefixlen;
00483 hostcol->column_len = host_collen;
00484 if (host_term && host_termlen >= 0) {
00485 hostcol->terminator = (BYTE *) malloc(host_termlen);
00486 memcpy(hostcol->terminator, host_term, host_termlen);
00487 }
00488 hostcol->term_len = host_termlen;
00489 hostcol->tab_colnum = table_colnum;
00490
00491 return SUCCEED;
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 RETCODE
00510 bcp_colfmt_ps(DBPROCESS * dbproc, int host_colnum, int host_type,
00511 int host_prefixlen, DBINT host_collen, BYTE * host_term, int host_termlen, int table_colnum, DBTYPEINFO * typeinfo)
00512 {
00513
00514 if (dbproc->bcpinfo == NULL) {
00515 dbperror(dbproc, SYBEBCPI, 0);
00516 return FAIL;
00517 }
00518 return FAIL;
00519 }
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 RETCODE
00544 bcp_control(DBPROCESS * dbproc, int field, DBINT value)
00545 {
00546 if (dbproc->bcpinfo == NULL) {
00547 dbperror(dbproc, SYBEBCPI, 0);
00548 return FAIL;
00549 }
00550
00551 if (dbproc->hostfileinfo == NULL) {
00552 dbperror(dbproc, SYBEBIVI, 0);
00553 return FAIL;
00554 }
00555
00556 switch (field) {
00557
00558 case BCPMAXERRS:
00559 dbproc->hostfileinfo->maxerrs = value;
00560 break;
00561 case BCPFIRST:
00562 dbproc->hostfileinfo->firstrow = value;
00563 break;
00564 case BCPLAST:
00565 dbproc->hostfileinfo->firstrow = value;
00566 break;
00567 case BCPBATCH:
00568 dbproc->hostfileinfo->batch = value;
00569 break;
00570 case BCPKEEPIDENTITY:
00571 dbproc->bcpinfo->identity_insert_on = (value != 0);
00572 break;
00573
00574 default:
00575 dbperror(dbproc, SYBEIFNB, 0);
00576 return FAIL;
00577 }
00578 return SUCCEED;
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602 RETCODE
00603 bcp_options(DBPROCESS * dbproc, int option, BYTE * value, int valuelen)
00604 {
00605 int i;
00606 static const char *const hints[] = {
00607 "ORDER", "ROWS_PER_BATCH", "KILOBYTES_PER_BATCH", "TABLOCK", "CHECK_CONSTRAINTS", NULL
00608 };
00609
00610 if (!dbproc)
00611 return FAIL;
00612
00613 if (dbproc->bcpinfo == NULL) {
00614 dbperror(dbproc, SYBEBCPI, 0);
00615 return FAIL;
00616 }
00617
00618 switch (option) {
00619 case BCPLABELED:
00620 tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED bcp option: BCPLABELED\n");
00621 return FAIL;
00622 case BCPHINTS:
00623 if (!value || valuelen <= 0)
00624 return FAIL;
00625
00626
00627 if (dbproc->bcpinfo->hint != NULL)
00628 return FAIL;
00629
00630 for (i = 0; hints[i]; i++) {
00631
00632 if (strncasecmp((char *) value, hints[i], strlen(hints[i])) == 0)
00633 break;
00634 }
00635 if (!hints[i]) {
00636 return FAIL;
00637 }
00638
00639
00640
00641
00642
00643 dbproc->bcpinfo->hint = (char *) malloc(1 + valuelen);
00644 if (!dbproc->bcpinfo->hint) {
00645 dbperror(dbproc, SYBEMEM, errno);
00646 return FAIL;
00647 }
00648 memcpy(dbproc->bcpinfo->hint, value, valuelen);
00649 dbproc->bcpinfo->hint[valuelen] = '\0';
00650 break;
00651 default:
00652 tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED bcp option: %u\n", option);
00653 return FAIL;
00654 }
00655
00656 return SUCCEED;
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 RETCODE
00672 bcp_colptr(DBPROCESS * dbproc, BYTE * colptr, int table_column)
00673 {
00674 TDSCOLUMN *curcol;
00675
00676
00677
00678 if (dbproc->bcpinfo == NULL || dbproc->bcpinfo->bindinfo == NULL) {
00679 dbperror(dbproc, SYBEBCPI, 0);
00680 return FAIL;
00681 }
00682 if (dbproc->bcpinfo->direction != DB_IN) {
00683 dbperror(dbproc, SYBEBCPN, 0);
00684 return FAIL;
00685 }
00686
00687 if (table_column <= 0 || table_column > dbproc->bcpinfo->bindinfo->num_cols)
00688 return FAIL;
00689
00690 curcol = dbproc->bcpinfo->bindinfo->columns[table_column - 1];
00691 curcol->column_varaddr = (TDS_CHAR *)colptr;
00692
00693 return SUCCEED;
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 DBBOOL
00707 bcp_getl(LOGINREC * login)
00708 {
00709 TDSLOGIN *tdsl = login->tds_login;
00710
00711 return (tdsl->bulk_copy);
00712 }
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725 static RETCODE
00726 _bcp_exec_out(DBPROCESS * dbproc, DBINT * rows_copied)
00727 {
00728
00729 FILE *hostfile;
00730 int i;
00731
00732 TDSSOCKET *tds;
00733 TDSRESULTINFO *resinfo;
00734 TDSCOLUMN *curcol = NULL;
00735 BCP_HOSTCOLINFO *hostcol;
00736 BYTE *src;
00737 int srctype;
00738 int srclen;
00739 int buflen;
00740 int destlen;
00741 int plen;
00742
00743 TDS_INT result_type;
00744
00745 TDS_TINYINT ti;
00746 TDS_SMALLINT si;
00747 TDS_INT li;
00748
00749 TDSDATEREC when;
00750
00751 int row_of_query;
00752 int rows_written;
00753 char *bcpdatefmt = NULL;
00754 int tdsret;
00755
00756 tds = dbproc->tds_socket;
00757 assert(tds);
00758
00759 if (!(hostfile = fopen(dbproc->hostfileinfo->hostfile, "w"))) {
00760 dbperror(dbproc, SYBEBCUO, errno);
00761 return FAIL;
00762 }
00763
00764 bcpdatefmt = getenv("FREEBCP_DATEFMT");
00765
00766 if (dbproc->bcpinfo->direction == DB_QUERYOUT ) {
00767 if (tds_submit_query(tds, dbproc->bcpinfo->tablename) == TDS_FAIL) {
00768 return FAIL;
00769 }
00770 } else {
00771
00772 if (tds_submit_queryf(tds, "select * from %s", dbproc->bcpinfo->tablename)
00773 == TDS_FAIL) {
00774 return FAIL;
00775 }
00776 }
00777
00778 tdsret = tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS);
00779 if (tdsret == TDS_FAIL || tdsret == TDS_CANCELLED) {
00780 fclose(hostfile);
00781 return FAIL;
00782 }
00783 if (!tds->res_info) {
00784
00785 fclose(hostfile);
00786 return FAIL;
00787 }
00788
00789 resinfo = tds->res_info;
00790
00791 row_of_query = 0;
00792 rows_written = 0;
00793
00794
00795
00796
00797
00798
00799
00800
00801 for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
00802
00803 hostcol = dbproc->hostfileinfo->host_columns[i];
00804 if (hostcol->tab_colnum < 1 || hostcol->tab_colnum > resinfo->num_cols)
00805 continue;
00806
00807 curcol = resinfo->columns[hostcol->tab_colnum - 1];
00808
00809 if (hostcol->datatype == 0)
00810 hostcol->datatype = curcol->column_type;
00811
00812
00813
00814
00815 switch (hostcol->datatype) {
00816
00817 case SYBINT1:
00818 buflen = destlen = 1;
00819 break;
00820 case SYBINT2:
00821 buflen = destlen = 2;
00822 break;
00823 case SYBINT4:
00824 buflen = destlen = 4;
00825 break;
00826 case SYBINT8:
00827 buflen = destlen = 8;
00828 break;
00829 case SYBREAL:
00830 buflen = destlen = 4;
00831 break;
00832 case SYBFLT8:
00833 buflen = destlen = 8;
00834 break;
00835 case SYBDATETIME:
00836 buflen = destlen = 8;
00837 break;
00838 case SYBDATETIME4:
00839 buflen = destlen = 4;
00840 break;
00841 case SYBBIT:
00842 buflen = destlen = 1;
00843 break;
00844 case SYBBITN:
00845 buflen = destlen = 1;
00846 break;
00847 case SYBMONEY:
00848 buflen = destlen = 8;
00849 break;
00850 case SYBMONEY4:
00851 buflen = destlen = 4;
00852 break;
00853 case SYBCHAR:
00854 case SYBVARCHAR:
00855 switch (curcol->column_type) {
00856 case SYBVARCHAR:
00857 buflen = curcol->column_size + 1;
00858 destlen = -1;
00859 break;
00860 case SYBCHAR:
00861 buflen = curcol->column_size + 1;
00862 if (curcol->column_nullable)
00863 destlen = -1;
00864 else
00865 destlen = -2;
00866 break;
00867 case SYBTEXT:
00868
00869 buflen = curcol->column_size + 1;
00870 destlen = -2;
00871 break;
00872 case SYBINT1:
00873 buflen = 4 + 1;
00874 destlen = -1;
00875 break;
00876 case SYBINT2:
00877 buflen = 6 + 1;
00878 destlen = -1;
00879 break;
00880 case SYBINT4:
00881 buflen = 11 + 1;
00882 destlen = -1;
00883 break;
00884 case SYBINT8:
00885 buflen = 20 + 1;
00886 destlen = -1;
00887 break;
00888 case SYBNUMERIC:
00889 case SYBDECIMAL:
00890 buflen = 40 + 1;
00891 destlen = -1;
00892 break;
00893 case SYBFLT8:
00894 buflen = 40 + 1;
00895 destlen = -1;
00896 break;
00897 case SYBDATETIME:
00898 case SYBDATETIME4:
00899 buflen = 255 + 1;
00900 destlen = -1;
00901 break;
00902 default:
00903 buflen = 255 + 1;
00904 destlen = -1;
00905 break;
00906 }
00907 break;
00908 default:
00909 buflen = destlen = 255;
00910 }
00911
00912 hostcol->bcp_column_data = tds_alloc_bcp_column_data(buflen);
00913 hostcol->bcp_column_data->datalen = destlen;
00914 }
00915
00916
00917
00918
00919
00920
00921
00922
00923 while (tds_process_tokens(tds, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE) == TDS_SUCCEED) {
00924
00925 if (result_type != TDS_ROW_RESULT && result_type != TDS_COMPUTE_RESULT)
00926 break;
00927
00928 row_of_query++;
00929
00930
00931 if (dbproc->hostfileinfo->firstrow <= row_of_query &&
00932 row_of_query <= MAX(dbproc->hostfileinfo->lastrow, 0x7FFFFFFF)) {
00933
00934
00935 for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
00936
00937 hostcol = dbproc->hostfileinfo->host_columns[i];
00938 if (hostcol->tab_colnum < 1 || hostcol->tab_colnum > resinfo->num_cols) {
00939 continue;
00940 }
00941
00942 curcol = resinfo->columns[hostcol->tab_colnum - 1];
00943
00944 src = &resinfo->current_row[curcol->column_offset];
00945
00946 if (is_blob_type(curcol->column_type)) {
00947 src = (BYTE *) ((TDSBLOB *) src)->textvalue;
00948 }
00949
00950 srctype = tds_get_conversion_type(curcol->column_type, curcol->column_size);
00951
00952 if (curcol->column_cur_size < 0) {
00953 srclen = 0;
00954 hostcol->bcp_column_data->null_column = 1;
00955 } else {
00956 if (is_numeric_type(curcol->column_type))
00957 srclen = sizeof(TDS_NUMERIC);
00958 else
00959 srclen = curcol->column_cur_size;
00960 hostcol->bcp_column_data->null_column = 0;
00961 }
00962
00963 if (hostcol->bcp_column_data->null_column) {
00964 buflen = 0;
00965 } else {
00966
00967
00968
00969
00970
00971 if ((srctype == SYBDATETIME || srctype == SYBDATETIME4)
00972 && (hostcol->datatype == SYBCHAR || hostcol->datatype == SYBVARCHAR)) {
00973 tds_datecrack(srctype, src, &when);
00974 if (bcpdatefmt)
00975 buflen = tds_strftime((TDS_CHAR *)hostcol->bcp_column_data->data, 256, bcpdatefmt, &when);
00976 else
00977 buflen = tds_strftime((TDS_CHAR *)hostcol->bcp_column_data->data, 256, "%Y-%m-%d %H:%M:%S.%z", &when);
00978 } else {
00979
00980
00981
00982
00983
00984 buflen = dbconvert(dbproc, srctype, src, srclen, hostcol->datatype,
00985 hostcol->bcp_column_data->data, hostcol->bcp_column_data->datalen);
00986
00987
00988
00989
00990
00991
00992 if (( curcol->column_type == SYBVARCHAR ||
00993 (curcol->column_type == SYBCHAR && curcol->column_nullable)
00994 ) && srclen > 0 && buflen == 0) {
00995 strcpy ((char *)hostcol->bcp_column_data->data, " ");
00996 buflen = 1;
00997 }
00998 }
00999 }
01000
01001
01002 if ((plen = hostcol->prefix_len) == -1) {
01003 if (is_blob_type(hostcol->datatype))
01004 plen = 4;
01005 else if (!(is_fixed_type(hostcol->datatype)))
01006 plen = 2;
01007 else if (curcol->column_nullable)
01008 plen = 1;
01009 else
01010 plen = 0;
01011
01012 hostcol->prefix_len = plen;
01013 }
01014 switch (plen) {
01015 case 0:
01016 break;
01017 case 1:
01018 ti = buflen;
01019 fwrite(&ti, sizeof(ti), 1, hostfile);
01020 break;
01021 case 2:
01022 si = buflen;
01023 fwrite(&si, sizeof(si), 1, hostfile);
01024 break;
01025 case 4:
01026 li = buflen;
01027 fwrite(&li, sizeof(li), 1, hostfile);
01028 break;
01029 }
01030
01031
01032 if (hostcol->column_len != -1) {
01033 buflen = buflen > hostcol->column_len ? hostcol->column_len : buflen;
01034 }
01035
01036 if (buflen > 0)
01037 fwrite(hostcol->bcp_column_data->data, buflen, 1, hostfile);
01038
01039
01040 if (hostcol->terminator && hostcol->term_len > 0) {
01041 fwrite(hostcol->terminator, hostcol->term_len, 1, hostfile);
01042 }
01043 }
01044 rows_written++;
01045 }
01046 }
01047 if (fclose(hostfile) != 0) {
01048 dbperror(dbproc, SYBEBCUC, errno);
01049 return (FAIL);
01050 }
01051
01052 if (dbproc->hostfileinfo->firstrow > 0 && row_of_query < dbproc->hostfileinfo->firstrow) {
01053
01054
01055
01056
01057
01058
01059 dbperror(dbproc, SYBETTS, 0);
01060 return (FAIL);
01061 }
01062
01063 *rows_copied = rows_written;
01064 return SUCCEED;
01065 }
01066
01067 static RETCODE
01068 _bcp_check_eof(DBPROCESS * dbproc, FILE *file, int icol)
01069 {
01070 int errnum = errno;
01071
01072 if (feof(file)) {
01073 if (icol == 0) {
01074 tdsdump_log(TDS_DBG_FUNC, "Normal end-of-file reached while loading bcp data file.\n");
01075 return (NO_MORE_ROWS);
01076 }
01077 dbperror(dbproc, SYBEBEOF, errnum);
01078 return (FAIL);
01079 }
01080 dbperror(dbproc, SYBEBCRE, errnum);
01081 return (FAIL);
01082 }
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094 static RETCODE
01095 _bcp_read_hostfile(DBPROCESS * dbproc, FILE * hostfile, int *row_error)
01096 {
01097 TDSCOLUMN *bcpcol = NULL;
01098 BCP_HOSTCOLINFO *hostcol;
01099
01100 TDS_TINYINT ti;
01101 TDS_SMALLINT si;
01102 TDS_INT li;
01103 TDS_INT desttype;
01104 BYTE *coldata;
01105
01106 int i, collen, data_is_null;
01107
01108
01109
01110 for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
01111 tdsdump_log(TDS_DBG_FUNC, "parsing host column %d\n", i + 1);
01112 hostcol = dbproc->hostfileinfo->host_columns[i];
01113
01114 data_is_null = 0;
01115 collen = 0;
01116 hostcol->column_error = 0;
01117
01118
01119
01120
01121
01122
01123
01124 if (hostcol->tab_colnum) {
01125 bcpcol = dbproc->bcpinfo->bindinfo->columns[hostcol->tab_colnum - 1];
01126 }
01127
01128
01129 if (bcpcol && hostcol->prefix_len == -1) {
01130 hostcol->prefix_len = bcpcol->column_varint_size;
01131 }
01132
01133
01134 if (hostcol->prefix_len > 0) {
01135
01136 switch (hostcol->prefix_len) {
01137 case 1:
01138 if (fread(&ti, 1, 1, hostfile) != 1)
01139 return _bcp_check_eof(dbproc, hostfile, i);
01140 collen = ti ? ti : -1;
01141 break;
01142 case 2:
01143 if (fread(&si, 2, 1, hostfile) != 1)
01144 return _bcp_check_eof(dbproc, hostfile, i);
01145 collen = si;
01146 break;
01147 case 4:
01148 if (fread(&li, 4, 1, hostfile) != 1)
01149 return _bcp_check_eof(dbproc, hostfile, i);
01150 collen = li;
01151 break;
01152 default:
01153
01154 assert(hostcol->prefix_len <= 4);
01155 break;
01156 }
01157
01158
01159
01160 if (collen <= -1) {
01161 data_is_null = 1;
01162 collen = 0;
01163 }
01164 }
01165
01166
01167
01168 if (!data_is_null && hostcol->column_len >= 0) {
01169 if (hostcol->column_len == 0)
01170 data_is_null = 1;
01171 else {
01172 if (collen)
01173 collen = (hostcol->column_len < collen) ? hostcol->column_len : collen;
01174 else
01175 collen = hostcol->column_len;
01176 }
01177 }
01178
01179 tdsdump_log(TDS_DBG_FUNC, "prefix_len = %d collen = %d \n", hostcol->prefix_len, collen);
01180
01181
01182
01183 if (is_fixed_type(hostcol->datatype)) {
01184 collen = tds_get_size_by_type(hostcol->datatype);
01185 }
01186
01187
01188
01189
01190
01191
01192 if (hostcol->term_len > 0) {
01193 int file_bytes_left, file_len;
01194 size_t col_bytes_left;
01195 offset_type len;
01196 iconv_t cd;
01197
01198 len = _bcp_measure_terminated_field(hostfile, hostcol->terminator, hostcol->term_len);
01199 if (len > 0x7fffffffl || len < 0) {
01200 *row_error = TRUE;
01201 tdsdump_log(TDS_DBG_FUNC, "_bcp_measure_terminated_field returned -1!\n");
01202
01203 return (FAIL);
01204 }
01205 collen = len;
01206 if (collen == 0)
01207 data_is_null = 1;
01208
01209
01210 tdsdump_log(TDS_DBG_FUNC, "_bcp_measure_terminated_field returned %d\n", collen);
01211
01212
01213
01214 file_len = collen;
01215 if (bcpcol->char_conv) {
01216 if (bcpcol->on_server.column_size > bcpcol->column_size)
01217 collen = (collen * bcpcol->on_server.column_size) / bcpcol->column_size;
01218 cd = bcpcol->char_conv->to_wire;
01219 tdsdump_log(TDS_DBG_FUNC, "Adjusted collen is %d.\n", collen);
01220
01221 } else {
01222 cd = (iconv_t) - 1;
01223 }
01224
01225 coldata = (BYTE *) calloc(1, 1 + collen);
01226 if (coldata == NULL) {
01227 *row_error = TRUE;
01228 tdsdump_log(TDS_DBG_FUNC, "calloc returned NULL pointer!\n");
01229 dbperror(dbproc, SYBEMEM, errno);
01230 return (FAIL);
01231 }
01232
01233
01234
01235
01236 col_bytes_left = collen;
01237
01238 file_bytes_left = tds_iconv_fread(cd, hostfile, file_len, hostcol->term_len, (TDS_CHAR *)coldata, &col_bytes_left);
01239 collen -= col_bytes_left;
01240
01241
01242
01243 if (file_bytes_left != 0) {
01244 tdsdump_log(TDS_DBG_FUNC, "col %d: %d of %d bytes unread\nfile_bytes_left != 0!\n",
01245 (i+1), file_bytes_left, collen);
01246 *row_error = TRUE;
01247 free(coldata);
01248 return FAIL;
01249 }
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260 } else {
01261 #if 0
01262 bcpcol = dbproc->bcpinfo->bindinfo->columns[hostcol->tab_colnum - 1];
01263 if (collen == 0 || bcpcol->column_nullable) {
01264 if (collen != 0) {
01265
01266 TDS_TINYINT len;
01267 if (fread(&len, sizeof(len), 1, hostfile) != 1) {
01268 if (i != 0)
01269 dbperror(dbproc, SYBEBCRE, errno);
01270 return (FAIL);
01271 }
01272
01273 collen = len == 255 ? -1 : len;
01274 } else {
01275 TDS_SMALLINT len;
01276
01277 if (fread(&len, sizeof(len), 1, hostfile) != 1) {
01278 if (i != 0)
01279 dbperror(dbproc, SYBEBCRE, errno);
01280 return (FAIL);
01281 }
01282 collen = len;
01283 }
01284
01285 if (collen <= -1) {
01286 collen = 0;
01287 data_is_null = 1;
01288 }
01289
01290 tdsdump_log(TDS_DBG_FUNC, "Length read from hostfile: collen is now %d, data_is_null is %d\n", collen, data_is_null);
01291 }
01292 #endif
01293
01294 coldata = (BYTE *) calloc(1, 1 + collen);
01295 if (coldata == NULL) {
01296 *row_error = TRUE;
01297 dbperror(dbproc, SYBEMEM, errno);
01298 return (FAIL);
01299 }
01300
01301 if (collen) {
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311 tdsdump_log(TDS_DBG_FUNC, "Reading %d bytes from hostfile.\n", collen);
01312 if (fread(coldata, collen, 1, hostfile) != 1) {
01313 free(coldata);
01314 return _bcp_check_eof(dbproc, hostfile, i);
01315 }
01316 }
01317 }
01318
01319
01320
01321
01322
01323
01324 if (i == 0 && collen == 0 && feof(hostfile)) {
01325 free(coldata);
01326 tdsdump_log(TDS_DBG_FUNC, "Normal end-of-file reached while loading bcp data file.\n");
01327 return NO_MORE_ROWS;
01328 }
01329
01330
01331
01332
01333 tdsdump_log(TDS_DBG_FUNC, "Data read from hostfile: collen is now %d, data_is_null is %d\n", collen, data_is_null);
01334 if (hostcol->tab_colnum) {
01335 if (data_is_null) {
01336 bcpcol->bcp_column_data->null_column = 1;
01337 bcpcol->bcp_column_data->datalen = 0;
01338 } else {
01339 bcpcol->bcp_column_data->null_column = 0;
01340 desttype = tds_get_conversion_type(bcpcol->column_type, bcpcol->column_size);
01341
01342
01343
01344 if (bcpcol->column_size == 4096 && collen > bcpcol->column_size) {
01345 BYTE *oldbuffer = bcpcol->bcp_column_data->data;
01346 switch (desttype) {
01347 case SYBTEXT:
01348 case SYBNTEXT:
01349 case SYBIMAGE:
01350 case SYBVARBINARY:
01351 case XSYBVARBINARY:
01352 case SYBLONGBINARY:
01353 bcpcol->column_size = 8 + collen;
01354 bcpcol->bcp_column_data->data = (BYTE *) realloc(bcpcol->bcp_column_data->data, bcpcol->column_size);
01355 if (!bcpcol->bcp_column_data->data) {
01356 dbperror(dbproc, SYBEMEM, errno);
01357 free(oldbuffer);
01358 free(coldata);
01359 return FAIL;
01360 }
01361 break;
01362 default:
01363 break;
01364 }
01365 }
01366
01367
01368
01369
01370
01371
01372 bcpcol->bcp_column_data->datalen =
01373 dbconvert(dbproc, hostcol->datatype, coldata, collen, desttype, bcpcol->bcp_column_data->data, bcpcol->column_size);
01374
01375 if (bcpcol->bcp_column_data->datalen == -1) {
01376 hostcol->column_error = HOST_COL_CONV_ERROR;
01377 *row_error = 1;
01378
01379 tdsdump_log(TDS_DBG_FUNC,
01380 "_bcp_read_hostfile failed to convert %d bytes at offset 0x%lx in the data file.\n",
01381 collen, (unsigned long int) ftello(hostfile) - collen);
01382 }
01383
01384
01385 if (desttype == SYBCHAR || desttype == SYBVARCHAR) {
01386 bcpcol->bcp_column_data->datalen = rtrim((char *) bcpcol->bcp_column_data->data, bcpcol->bcp_column_data->datalen);
01387 }
01388 }
01389
01390
01391 if (0 && !hostcol->column_error) {
01392 if (bcpcol->bcp_column_data->datalen <= 0) {
01393 if (!bcpcol->column_nullable) {
01394
01395 hostcol->column_error = HOST_COL_NULL_ERROR;
01396 *row_error = 1;
01397 dbperror(dbproc, SYBEBCNN, 0);
01398 }
01399 }
01400 }
01401 }
01402 free(coldata);
01403 }
01404 return MORE_ROWS;
01405 }
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425 static offset_type
01426 _bcp_measure_terminated_field(FILE * hostfile, BYTE * terminator, int term_len)
01427 {
01428 char *sample;
01429 int errnum;
01430 int sample_size, bytes_read = 0;
01431 offset_type size;
01432
01433 const offset_type initial_offset = ftello(hostfile);
01434
01435 sample = malloc(term_len);
01436
01437 if (!sample) {
01438 dbperror(NULL, SYBEMEM, errno);
01439 return -1;
01440 }
01441
01442 for (sample_size = 1; (bytes_read = fread(sample, sample_size, 1, hostfile)) != 0;) {
01443
01444 bytes_read *= sample_size;
01445
01446
01447
01448
01449
01450
01451
01452
01453 if (*sample == *terminator) {
01454 int found = 0;
01455
01456 if (sample_size == term_len) {
01457
01458
01459
01460 found = 0 == memcmp(sample, terminator, term_len);
01461
01462 if (found) {
01463 free(sample);
01464 size = ftello(hostfile) - initial_offset;
01465 if (size < 0 || 0 != fseeko(hostfile, initial_offset, SEEK_SET)) {
01466
01467 return -1;
01468 }
01469 return size - term_len;
01470 }
01471
01472
01473
01474
01475 if (sample_size > 1) {
01476 sample_size--;
01477 if (0 != fseeko(hostfile, -sample_size, SEEK_CUR)) {
01478
01479 return -1;
01480 }
01481 }
01482 sample_size = 1;
01483 continue;
01484 } else {
01485
01486
01487
01488
01489 assert(bytes_read == 1);
01490 ungetc(*sample, hostfile);
01491 sample_size = term_len;
01492 continue;
01493 }
01494 assert(0);
01495 }
01496 }
01497
01498 free(sample);
01499
01500
01501
01502
01503
01504
01505
01506 if (feof(hostfile)) {
01507 errnum = errno;
01508 if (initial_offset == ftello(hostfile)) {
01509 return 0;
01510 } else {
01511
01512 dbperror(0, SYBEBEOF, errnum);
01513 }
01514 } else if (ferror(hostfile)) {
01515 dbperror(0, SYBEBCRE, errno);
01516 }
01517
01518 return -1;
01519 }
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535 static int
01536 _bcp_add_fixed_columns(DBPROCESS * dbproc, int behaviour, BYTE * rowbuffer, int start)
01537 {
01538 TDS_NUMERIC *num;
01539 int row_pos = start;
01540 TDSCOLUMN *bcpcol;
01541 int cpbytes;
01542
01543 int i, j;
01544
01545 for (i = 0; i < dbproc->bcpinfo->bindinfo->num_cols; i++) {
01546
01547 bcpcol = dbproc->bcpinfo->bindinfo->columns[i];
01548
01549 if (!is_nullable_type(bcpcol->column_type) && !(bcpcol->column_nullable)) {
01550
01551 tdsdump_log(TDS_DBG_FUNC, "_bcp_add_fixed_columns column %d is a fixed column\n", i + 1);
01552
01553 if (behaviour == BCP_REC_FETCH_DATA) {
01554 if ((_bcp_get_col_data(dbproc, bcpcol)) != SUCCEED) {
01555 tdsdump_log(TDS_DBG_INFO1, "bcp_get_colData (column %d) failed\n", i + 1);
01556 return FAIL;
01557 }
01558 }
01559
01560 if (bcpcol->bcp_column_data->null_column) {
01561 dbperror(dbproc, SYBEBCNN, 0);
01562 return FAIL;
01563 }
01564
01565 if (is_numeric_type(bcpcol->column_type)) {
01566 num = (TDS_NUMERIC *) bcpcol->bcp_column_data->data;
01567 cpbytes = tds_numeric_bytes_per_prec[num->precision];
01568 memcpy(&rowbuffer[row_pos], num->array, cpbytes);
01569 } else {
01570 cpbytes = bcpcol->bcp_column_data->datalen > bcpcol->column_size ? bcpcol->column_size : bcpcol->bcp_column_data->datalen;
01571 memcpy(&rowbuffer[row_pos], bcpcol->bcp_column_data->data, cpbytes);
01572
01573
01574
01575 if (bcpcol->column_type == SYBCHAR && cpbytes < bcpcol->column_size) {
01576 for (j = cpbytes; j < bcpcol->column_size; j++)
01577 rowbuffer[row_pos + j] = ' ';
01578
01579 }
01580 }
01581
01582 row_pos += bcpcol->column_size;
01583 }
01584 }
01585 return row_pos;
01586 }
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603 static int
01604 _bcp_add_variable_columns(DBPROCESS * dbproc, int behaviour, BYTE * rowbuffer, int start, int *var_cols)
01605 {
01606 TDSCOLUMN *bcpcol;
01607 TDS_NUMERIC *num;
01608 int row_pos;
01609 int cpbytes;
01610
01611 BYTE offset_table[256];
01612 BYTE adjust_table[256];
01613
01614 int offset_pos = 0;
01615 int adjust_pos = 0;
01616 int num_cols = 0;
01617 int last_adjustment_increment = 0;
01618 int this_adjustment_increment = 0;
01619
01620 int i, adjust_table_entries_required;
01621
01622
01623
01624
01625 row_pos = start + 2;
01626
01627
01628
01629 for (i = 0; i < dbproc->bcpinfo->bindinfo->num_cols; i++) {
01630
01631 bcpcol = dbproc->bcpinfo->bindinfo->columns[i];
01632
01633
01634
01635
01636 if (is_nullable_type(bcpcol->column_type) || bcpcol->column_nullable) {
01637
01638 tdsdump_log(TDS_DBG_FUNC, "_bcp_add_variable_columns column %d is a variable column\n", i + 1);
01639
01640 if (behaviour == BCP_REC_FETCH_DATA) {
01641 if ((_bcp_get_col_data(dbproc, bcpcol)) != SUCCEED) {
01642 return FAIL;
01643 }
01644 }
01645
01646
01647
01648
01649 if (!(bcpcol->column_nullable) && bcpcol->bcp_column_data->null_column) {
01650 dbperror(dbproc, SYBEBCNN, 0);
01651 return FAIL;
01652 }
01653
01654 if (is_blob_type(bcpcol->column_type)) {
01655 cpbytes = 16;
01656 bcpcol->column_textpos = row_pos;
01657 } else if (is_numeric_type(bcpcol->column_type)) {
01658 num = (TDS_NUMERIC *) bcpcol->bcp_column_data->data;
01659 cpbytes = tds_numeric_bytes_per_prec[num->precision];
01660 memcpy(&rowbuffer[row_pos], num->array, cpbytes);
01661 } else {
01662
01663 if (bcpcol->bcp_column_data->null_column) {
01664 cpbytes = 0;
01665 } else {
01666 cpbytes = bcpcol->bcp_column_data->datalen > bcpcol->column_size ? bcpcol->column_size : bcpcol->bcp_column_data->datalen;
01667 memcpy(&rowbuffer[row_pos], bcpcol->bcp_column_data->data, cpbytes);
01668 }
01669 }
01670
01671
01672
01673 if (cpbytes > 0) {
01674
01675
01676
01677
01678
01679
01680
01681 offset_table[offset_pos++] = row_pos % 256;
01682
01683
01684
01685 num_cols++;
01686
01687
01688
01689
01690
01691
01692 this_adjustment_increment = row_pos / 256;
01693
01694
01695
01696 if (this_adjustment_increment > last_adjustment_increment) {
01697
01698
01699
01700
01701
01702
01703
01704 for ( adjust_table_entries_required = this_adjustment_increment - last_adjustment_increment;
01705 adjust_table_entries_required > 0;
01706 adjust_table_entries_required-- ) {
01707 adjust_table[adjust_pos++] = num_cols;
01708 }
01709 last_adjustment_increment = this_adjustment_increment;
01710 }
01711
01712 row_pos += cpbytes;
01713 }
01714 }
01715 }
01716
01717 if (num_cols) {
01718
01719
01720
01721
01722
01723 offset_table[offset_pos++] = row_pos % 256;
01724
01725
01726
01727
01728
01729
01730 rowbuffer[row_pos++] = num_cols + 1;
01731
01732
01733 for (i = adjust_pos - 1; i >= 0; i--) {
01734 rowbuffer[row_pos++] = adjust_table[i];
01735 }
01736
01737
01738 for (i = offset_pos - 1; i >= 0; i--) {
01739 rowbuffer[row_pos++] = offset_table[i];
01740 }
01741 }
01742
01743 *var_cols = num_cols;
01744
01745 if (num_cols == 0)
01746 return start;
01747 else
01748 return row_pos;
01749 }
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764 RETCODE
01765 bcp_sendrow(DBPROCESS * dbproc)
01766 {
01767
01768 TDSSOCKET *tds = dbproc->tds_socket;
01769
01770 if (dbproc->bcpinfo == NULL) {
01771 dbperror(dbproc, SYBEBCPI, 0);
01772 return FAIL;
01773 }
01774
01775 if (dbproc->bcpinfo->direction != DB_IN) {
01776 dbperror(dbproc, SYBEBCPN, 0);
01777 return FAIL;
01778 }
01779
01780 if (dbproc->hostfileinfo != NULL) {
01781 dbperror(dbproc, SYBEBCPB, 0);
01782 return FAIL;
01783 }
01784
01785
01786
01787
01788
01789 if (dbproc->bcpinfo->xfer_init == 0) {
01790
01791
01792
01793
01794 if (_bcp_start_copy_in(dbproc) == FAIL) {
01795 dbperror(dbproc, SYBEBULKINSERT, 0);
01796 return (FAIL);
01797 }
01798
01799
01800 tds->out_flag = TDS_BULK;
01801 tds_set_state(tds, TDS_QUERYING);
01802
01803 if (IS_TDS7_PLUS(tds)) {
01804 _bcp_send_colmetadata(dbproc);
01805 }
01806
01807 dbproc->bcpinfo->xfer_init = 1;
01808
01809 }
01810
01811 return _bcp_send_bcp_record(dbproc, BCP_REC_FETCH_DATA);
01812 }
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824 static RETCODE
01825 _bcp_exec_in(DBPROCESS * dbproc, DBINT * rows_copied)
01826 {
01827 FILE *hostfile, *errfile = NULL;
01828 TDSSOCKET *tds = dbproc->tds_socket;
01829 BCP_HOSTCOLINFO *hostcol;
01830 RETCODE ret;
01831
01832 int i;
01833 int row_of_hostfile, rows_written_so_far;
01834
01835 int row_error, row_error_count;
01836 offset_type row_start, row_end;
01837 offset_type error_row_size;
01838
01839 const size_t chunk_size = 0x20000u;
01840
01841 *rows_copied = 0;
01842
01843 if (!(hostfile = fopen(dbproc->hostfileinfo->hostfile, "r"))) {
01844 dbperror(dbproc, SYBEBCUO, 0);
01845 return FAIL;
01846 }
01847
01848 if (_bcp_start_copy_in(dbproc) == FAIL)
01849 return FAIL;
01850
01851 tds->out_flag = TDS_BULK;
01852 tds_set_state(tds, TDS_QUERYING);
01853
01854 if (IS_TDS7_PLUS(tds)) {
01855 _bcp_send_colmetadata(dbproc);
01856 }
01857
01858 row_of_hostfile = 0;
01859 rows_written_so_far = 0;
01860
01861 row_start = ftello(hostfile);
01862 row_error_count = 0;
01863 row_error = 0;
01864
01865 while ((ret=_bcp_read_hostfile(dbproc, hostfile, &row_error)) == MORE_ROWS) {
01866
01867 row_of_hostfile++;
01868
01869 if (row_error) {
01870
01871 if (errfile == NULL && dbproc->hostfileinfo->errorfile) {
01872 if (!(errfile = fopen(dbproc->hostfileinfo->errorfile, "w"))) {
01873 dbperror(dbproc, SYBEBUOE, 0);
01874 return FAIL;
01875 }
01876 }
01877
01878 if (errfile != NULL) {
01879 char *row_in_error = NULL;
01880
01881 for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
01882 hostcol = dbproc->hostfileinfo->host_columns[i];
01883 if (hostcol->column_error == HOST_COL_CONV_ERROR) {
01884 fprintf(errfile, "#@ data conversion error on host data file Row %d Column %d\n",
01885 row_of_hostfile, i + 1);
01886 } else if (hostcol->column_error == HOST_COL_NULL_ERROR) {
01887 fprintf(errfile, "#@ Attempt to bulk-copy a NULL value into Server column"
01888 " which does not accept NULL values. Row %d, Column %d\n",
01889 row_of_hostfile, i + 1);
01890 }
01891 }
01892
01893 row_end = ftello(hostfile);
01894
01895
01896 error_row_size = row_end - row_start;
01897 fseeko(hostfile, row_start, SEEK_SET);
01898
01899 while (error_row_size > 0) {
01900 size_t chunk = error_row_size > chunk_size ? chunk_size : error_row_size;
01901
01902 if (!row_in_error)
01903 row_in_error = malloc(chunk);
01904
01905 if (fread(row_in_error, chunk, 1, hostfile) != 1) {
01906 printf("BILL fread failed after fseek\n");
01907 }
01908 fwrite(row_in_error, chunk, 1, errfile);
01909 error_row_size -= chunk;
01910 }
01911 if (row_in_error)
01912 free(row_in_error);
01913
01914 fseeko(hostfile, row_end, SEEK_SET);
01915 fprintf(errfile, "\n");
01916 }
01917 row_error_count++;
01918 if (row_error_count > dbproc->hostfileinfo->maxerrs)
01919 break;
01920 } else {
01921 if (dbproc->hostfileinfo->firstrow <= row_of_hostfile &&
01922 row_of_hostfile <= MAX(dbproc->hostfileinfo->lastrow, 0x7FFFFFFF)) {
01923
01924 if (_bcp_send_bcp_record(dbproc, BCP_REC_NOFETCH_DATA) == SUCCEED) {
01925
01926 rows_written_so_far++;
01927
01928 if (dbproc->hostfileinfo->batch > 0 && rows_written_so_far == dbproc->hostfileinfo->batch) {
01929 rows_written_so_far = 0;
01930
01931 tds_flush_packet(tds);
01932
01933 tds_set_state(tds, TDS_PENDING);
01934
01935 if (tds_process_simple_query(tds) != TDS_SUCCEED) {
01936 if (errfile)
01937 fclose(errfile);
01938 return FAIL;
01939 }
01940
01941 *rows_copied += tds->rows_affected;
01942
01943 dbperror(dbproc, SYBEBBCI, 0);
01944
01945 _bcp_start_new_batch(dbproc);
01946
01947 }
01948 }
01949 }
01950 }
01951
01952 row_start = ftello(hostfile);
01953 row_error = 0;
01954 }
01955
01956 if (errfile) {
01957 fclose(errfile);
01958 errfile = NULL;
01959 }
01960
01961 if (fclose(hostfile) != 0) {
01962 dbperror(dbproc, SYBEBCUC, 0);
01963 return (FAIL);
01964 }
01965
01966 tds_flush_packet(tds);
01967
01968 tds_set_state(tds, TDS_PENDING);
01969
01970 if (tds_process_simple_query(tds) != TDS_SUCCEED)
01971 return FAIL;
01972
01973 *rows_copied += tds->rows_affected;
01974
01975 return ret == NO_MORE_ROWS? SUCCEED : FAIL;
01976 }
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991 RETCODE
01992 bcp_exec(DBPROCESS * dbproc, DBINT *rows_copied)
01993 {
01994 DBINT dummy_copied;
01995 RETCODE ret = 0;
01996
01997 if (rows_copied == NULL)
01998 rows_copied = &dummy_copied;
01999
02000 if (dbproc->bcpinfo == NULL) {
02001 dbperror(dbproc, SYBEBCPI, 0);
02002 return FAIL;
02003 }
02004 if (dbproc->hostfileinfo == NULL) {
02005 dbperror(dbproc, SYBEBCVH, 0);
02006 return FAIL;
02007 }
02008
02009 if (dbproc->bcpinfo->direction == DB_OUT || dbproc->bcpinfo->direction == DB_QUERYOUT) {
02010 ret = _bcp_exec_out(dbproc, rows_copied);
02011 } else if (dbproc->bcpinfo->direction == DB_IN) {
02012 ret = _bcp_exec_in(dbproc, rows_copied);
02013 }
02014 _bcp_free_storage(dbproc);
02015
02016 return ret;
02017 }
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028 static RETCODE
02029 _bcp_start_copy_in(DBPROCESS * dbproc)
02030 {
02031
02032 TDSSOCKET *tds = dbproc->tds_socket;
02033 TDSCOLUMN *bcpcol;
02034
02035 int i;
02036 int firstcol;
02037
02038 int fixed_col_len_tot = 0;
02039 int variable_col_len_tot = 0;
02040 int column_bcp_data_size = 0;
02041 int bcp_record_size = 0;
02042
02043 char *query;
02044
02045 if (IS_TDS7_PLUS(tds)) {
02046 int erc;
02047 char *hint;
02048 TDS_PBCB colclause;
02049 char clause_buffer[4096] = { 0 };
02050
02051 colclause.pb = clause_buffer;
02052 colclause.cb = sizeof(clause_buffer);
02053 colclause.from_malloc = 0;
02054
02055 firstcol = 1;
02056
02057 for (i = 0; i < dbproc->bcpinfo->bindinfo->num_cols; i++) {
02058 bcpcol = dbproc->bcpinfo->bindinfo->columns[i];
02059
02060 if (dbproc->bcpinfo->identity_insert_on) {
02061 if (!bcpcol->column_timestamp) {
02062 _bcp_build_bulk_insert_stmt(tds, &colclause, bcpcol, firstcol);
02063 firstcol = 0;
02064 }
02065 } else {
02066 if (!bcpcol->column_identity && !bcpcol->column_timestamp) {
02067 _bcp_build_bulk_insert_stmt(tds, &colclause, bcpcol, firstcol);
02068 firstcol = 0;
02069 }
02070 }
02071 }
02072
02073 if (dbproc->bcpinfo->hint) {
02074 if (asprintf(&hint, " with (%s)", dbproc->bcpinfo->hint) < 0) {
02075 return FAIL;
02076 }
02077 } else {
02078 hint = strdup("");
02079 }
02080 if (!hint)
02081 return FAIL;
02082
02083 erc = asprintf(&query, "insert bulk %s (%s) %s", dbproc->bcpinfo->tablename, colclause.pb, hint);
02084
02085 free(hint);
02086 if (colclause.from_malloc)
02087 TDS_ZERO_FREE(colclause.pb);
02088
02089 if (erc < 0) {
02090 return FAIL;
02091 }
02092
02093 } else {
02094 if (asprintf(&query, "insert bulk %s", dbproc->bcpinfo->tablename) < 0) {
02095 return FAIL;
02096 }
02097 }
02098
02099 tds_submit_query(tds, query);
02100
02101
02102
02103 dbproc->bcpinfo->insert_stmt = query;
02104
02105
02106
02107
02108
02109 if (tds_process_simple_query(tds) != TDS_SUCCEED)
02110 return FAIL;
02111
02112
02113
02114
02115
02116 dbproc->bcpinfo->var_cols = 0;
02117
02118 if (IS_TDS50(tds)) {
02119 for (i = 0; i < dbproc->bcpinfo->bindinfo->num_cols; i++) {
02120
02121 bcpcol = dbproc->bcpinfo->bindinfo->columns[i];
02122
02123
02124
02125
02126
02127 if (is_blob_type(bcpcol->on_server.column_type))
02128 column_bcp_data_size = 16;
02129 else if (is_numeric_type(bcpcol->on_server.column_type))
02130 column_bcp_data_size = tds_numeric_bytes_per_prec[bcpcol->column_prec];
02131 else
02132 column_bcp_data_size = bcpcol->column_size;
02133
02134
02135
02136
02137 if (is_nullable_type(bcpcol->on_server.column_type) || bcpcol->column_nullable) {
02138 dbproc->bcpinfo->var_cols++;
02139 variable_col_len_tot += column_bcp_data_size;
02140 }
02141 else {
02142 fixed_col_len_tot += column_bcp_data_size;
02143 }
02144 }
02145
02146
02147
02148 bcp_record_size = 4 +
02149 fixed_col_len_tot +
02150 variable_col_len_tot +
02151 ( (int)(variable_col_len_tot / 256 ) + 1 ) +
02152 (dbproc->bcpinfo->var_cols + 1) +
02153 2;
02154
02155 tdsdump_log(TDS_DBG_FUNC, "current_record_size = %d\n", dbproc->bcpinfo->bindinfo->row_size);
02156 tdsdump_log(TDS_DBG_FUNC, "bcp_record_size = %d\n", bcp_record_size);
02157
02158 if (bcp_record_size > dbproc->bcpinfo->bindinfo->row_size) {
02159
02160 dbproc->bcpinfo->bindinfo->current_row = realloc(dbproc->bcpinfo->bindinfo->current_row, bcp_record_size);
02161 if (dbproc->bcpinfo->bindinfo->current_row == NULL) {
02162 tdsdump_log(TDS_DBG_FUNC, "could not realloc current_row\n");
02163 return FAIL;
02164 }
02165 dbproc->bcpinfo->bindinfo->row_size = bcp_record_size;
02166 }
02167 }
02168 if (IS_TDS7_PLUS(tds)) {
02169 for (i = 0; i < dbproc->bcpinfo->bindinfo->num_cols; i++) {
02170
02171 bcpcol = dbproc->bcpinfo->bindinfo->columns[i];
02172
02173
02174
02175
02176
02177
02178 if ((!dbproc->bcpinfo->identity_insert_on && bcpcol->column_identity) ||
02179 bcpcol->column_timestamp) {
02180 continue;
02181 }
02182
02183 switch (bcpcol->column_varint_size) {
02184 case 4:
02185 if (is_blob_type(bcpcol->column_type)) {
02186 bcp_record_size += 25;
02187 }
02188 bcp_record_size += 4;
02189 break;
02190 case 2:
02191 bcp_record_size +=2;
02192 break;
02193 case 1:
02194 bcp_record_size++;
02195 break;
02196 case 0:
02197 break;
02198 }
02199
02200 if (is_numeric_type(bcpcol->column_type)) {
02201 bcp_record_size += tds_numeric_bytes_per_prec[bcpcol->column_prec];
02202 } else {
02203 bcp_record_size += bcpcol->column_size;
02204 }
02205 }
02206 tdsdump_log(TDS_DBG_FUNC, "current_record_size = %d\n", dbproc->bcpinfo->bindinfo->row_size);
02207 tdsdump_log(TDS_DBG_FUNC, "bcp_record_size = %d\n", bcp_record_size);
02208
02209 if (bcp_record_size > dbproc->bcpinfo->bindinfo->row_size) {
02210 dbproc->bcpinfo->bindinfo->current_row = realloc(dbproc->bcpinfo->bindinfo->current_row, bcp_record_size);
02211 if (dbproc->bcpinfo->bindinfo->current_row == NULL) {
02212 tdsdump_log(TDS_DBG_FUNC, "could not realloc current_row\n");
02213 return FAIL;
02214 }
02215 dbproc->bcpinfo->bindinfo->row_size = bcp_record_size;
02216 }
02217 }
02218
02219 return SUCCEED;
02220 }
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233 static RETCODE
02234 _bcp_build_bulk_insert_stmt(TDSSOCKET * tds, TDS_PBCB * clause, TDSCOLUMN * bcpcol, int first)
02235 {
02236 char buffer[32];
02237 char *column_type = buffer;
02238
02239
02240 switch (bcpcol->on_server.column_type) {
02241 case SYBINT1:
02242 column_type = "tinyint";
02243 break;
02244 case SYBBIT:
02245 column_type = "bit";
02246 break;
02247 case SYBINT2:
02248 column_type = "smallint";
02249 break;
02250 case SYBINT4:
02251 column_type = "int";
02252 break;
02253 case SYBINT8:
02254 column_type = "bigint";
02255 break;
02256 case SYBDATETIME:
02257 column_type = "datetime";
02258 break;
02259 case SYBDATETIME4:
02260 column_type = "smalldatetime";
02261 break;
02262 case SYBREAL:
02263 column_type = "real";
02264 break;
02265 case SYBMONEY:
02266 column_type = "money";
02267 break;
02268 case SYBMONEY4:
02269 column_type = "smallmoney";
02270 break;
02271 case SYBFLT8:
02272 column_type = "float";
02273 break;
02274
02275 case SYBINTN:
02276 switch (bcpcol->column_size) {
02277 case 1:
02278 column_type = "tinyint";
02279 break;
02280 case 2:
02281 column_type = "smallint";
02282 break;
02283 case 4:
02284 column_type = "int";
02285 break;
02286 case 8:
02287 column_type = "bigint";
02288 break;
02289 }
02290 break;
02291
02292 case SYBBITN:
02293 column_type = "bit";
02294 break;
02295 case SYBFLTN:
02296 switch (bcpcol->column_size) {
02297 case 4:
02298 column_type = "real";
02299 break;
02300 case 8:
02301 column_type = "float";
02302 break;
02303 }
02304 break;
02305 case SYBMONEYN:
02306 switch (bcpcol->column_size) {
02307 case 4:
02308 column_type = "smallmoney";
02309 break;
02310 case 8:
02311 column_type = "money";
02312 break;
02313 }
02314 break;
02315 case SYBDATETIMN:
02316 switch (bcpcol->column_size) {
02317 case 4:
02318 column_type = "smalldatetime";
02319 break;
02320 case 8:
02321 column_type = "datetime";
02322 break;
02323 }
02324 break;
02325 case SYBDECIMAL:
02326 sprintf(column_type, "decimal(%d,%d)", bcpcol->column_prec, bcpcol->column_scale);
02327 break;
02328 case SYBNUMERIC:
02329 sprintf(column_type, "numeric(%d,%d)", bcpcol->column_prec, bcpcol->column_scale);
02330 break;
02331
02332 case XSYBVARBINARY:
02333 sprintf(column_type, "varbinary(%d)", bcpcol->column_size);
02334 break;
02335 case XSYBVARCHAR:
02336 sprintf(column_type, "varchar(%d)", bcpcol->column_size);
02337 break;
02338 case XSYBBINARY:
02339 sprintf(column_type, "binary(%d)", bcpcol->column_size);
02340 break;
02341 case XSYBCHAR:
02342 sprintf(column_type, "char(%d)", bcpcol->column_size);
02343 break;
02344 case SYBTEXT:
02345 sprintf(column_type, "text");
02346 break;
02347 case SYBIMAGE:
02348 sprintf(column_type, "image");
02349 break;
02350 case XSYBNVARCHAR:
02351 sprintf(column_type, "nvarchar(%d)", bcpcol->column_size);
02352 break;
02353 case XSYBNCHAR:
02354 sprintf(column_type, "nchar(%d)", bcpcol->column_size);
02355 break;
02356 case SYBNTEXT:
02357 sprintf(column_type, "ntext");
02358 break;
02359 case SYBUNIQUE:
02360 sprintf(column_type, "uniqueidentifier ");
02361 break;
02362 default:
02363 tdsdump_log(TDS_DBG_FUNC, "error: cannot build bulk insert statement. unrecognized server datatype %d\n", bcpcol->on_server.column_type);
02364 return FAIL;
02365 }
02366
02367 if (clause->cb < strlen(clause->pb) + tds_quote_id(tds, NULL, bcpcol->column_name, bcpcol->column_namelen) + strlen(column_type) + ((first) ? 2 : 4)) {
02368 char *temp = (char *) malloc(2 * clause->cb);
02369
02370 if (!temp)
02371 return FAIL;
02372 strcpy(temp, clause->pb);
02373 if (clause->from_malloc)
02374 free(clause->pb);
02375 clause->from_malloc = 1;
02376 clause->pb = temp;
02377 clause->cb *= 2;
02378 }
02379
02380 if (!first)
02381 strcat(clause->pb, ", ");
02382
02383 tds_quote_id(tds, strchr(clause->pb, 0), bcpcol->column_name, bcpcol->column_namelen);
02384 strcat(clause->pb, " ");
02385 strcat(clause->pb, column_type);
02386
02387 return SUCCEED;
02388 }
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398 static RETCODE
02399 _bcp_start_new_batch(DBPROCESS * dbproc)
02400 {
02401 TDSSOCKET *tds = dbproc->tds_socket;
02402
02403 tds_submit_query(tds, dbproc->bcpinfo->insert_stmt);
02404
02405 if (tds_process_simple_query(tds) != TDS_SUCCEED)
02406 return FAIL;
02407
02408
02409 tds->out_flag = TDS_BULK;
02410 tds_set_state(tds, TDS_QUERYING);
02411
02412 if (IS_TDS7_PLUS(tds)) {
02413 _bcp_send_colmetadata(dbproc);
02414 }
02415
02416 return SUCCEED;
02417 }
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427 static RETCODE
02428 _bcp_send_colmetadata(DBPROCESS * dbproc)
02429 {
02430
02431 TDSSOCKET *tds = dbproc->tds_socket;
02432 unsigned char colmetadata_token = 0x81;
02433 TDSCOLUMN *bcpcol;
02434 int i;
02435 int num_cols;
02436
02437
02438
02439
02440 tds_put_byte(tds, colmetadata_token);
02441
02442 num_cols = 0;
02443 for (i = 0; i < dbproc->bcpinfo->bindinfo->num_cols; i++) {
02444 bcpcol = dbproc->bcpinfo->bindinfo->columns[i];
02445 if ((!dbproc->bcpinfo->identity_insert_on && bcpcol->column_identity) ||
02446 bcpcol->column_timestamp) {
02447 continue;
02448 }
02449 num_cols++;
02450 }
02451
02452 tds_put_smallint(tds, num_cols);
02453
02454 for (i = 0; i < dbproc->bcpinfo->bindinfo->num_cols; i++) {
02455 bcpcol = dbproc->bcpinfo->bindinfo->columns[i];
02456
02457
02458
02459
02460
02461
02462 if ((!dbproc->bcpinfo->identity_insert_on && bcpcol->column_identity) ||
02463 bcpcol->column_timestamp) {
02464 continue;
02465 }
02466
02467 tds_put_smallint(tds, bcpcol->column_usertype);
02468 tds_put_smallint(tds, bcpcol->column_flags);
02469 tds_put_byte(tds, bcpcol->on_server.column_type);
02470
02471 switch (bcpcol->column_varint_size) {
02472 case 4:
02473 tds_put_int(tds, bcpcol->column_size);
02474 break;
02475 case 2:
02476 tds_put_smallint(tds, bcpcol->column_size);
02477 break;
02478 case 1:
02479 tds_put_byte(tds, bcpcol->column_size);
02480 break;
02481 case 0:
02482 break;
02483 default:
02484 break;
02485 }
02486
02487 if (is_numeric_type(bcpcol->on_server.column_type)) {
02488 tds_put_byte(tds, bcpcol->column_prec);
02489 tds_put_byte(tds, bcpcol->column_scale);
02490 }
02491 if (IS_TDS80(tds)
02492 && is_collate_type(bcpcol->on_server.column_type)) {
02493 tds_put_n(tds, bcpcol->column_collation, 5);
02494 }
02495 if (is_blob_type(bcpcol->on_server.column_type)) {
02496
02497 tds_put_smallint(tds, strlen(dbproc->bcpinfo->tablename));
02498 tds_put_string(tds, dbproc->bcpinfo->tablename, strlen(dbproc->bcpinfo->tablename));
02499 }
02500
02501 tds_put_byte(tds, bcpcol->column_namelen);
02502 tds_put_string(tds, bcpcol->column_name, bcpcol->column_namelen);
02503
02504 }
02505
02506 return SUCCEED;
02507 }
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519 static char *
02520 _bcp_fgets(char *buffer, size_t size, FILE *f)
02521 {
02522 char *p = fgets(buffer, size, f);
02523 if (p == NULL)
02524 return p;
02525
02526
02527 p = strchr(buffer, 0) - 1;
02528 if (p >= buffer && *p == '\n')
02529 *p = 0;
02530 return buffer;
02531 }
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545 RETCODE
02546 bcp_readfmt(DBPROCESS * dbproc, char *filename)
02547 {
02548 FILE *ffile;
02549 char buffer[1024];
02550
02551 float lf_version = 0.0;
02552 int li_numcols = 0;
02553 int colinfo_count = 0;
02554
02555 struct fflist
02556 {
02557 struct fflist *nextptr;
02558 BCP_HOSTCOLINFO colinfo;
02559 };
02560
02561 struct fflist *topptr = NULL;
02562 struct fflist *curptr = NULL;
02563
02564 BCP_HOSTCOLINFO *hostcol;
02565
02566 if (dbproc->bcpinfo == NULL) {
02567 dbperror(dbproc, SYBEBCPI, 0);
02568 return FAIL;
02569 }
02570
02571 if ((ffile = fopen(filename, "r")) == NULL) {
02572 dbperror(dbproc, SYBEBUOF, 0);
02573 return (FAIL);
02574 }
02575
02576 if ((_bcp_fgets(buffer, sizeof(buffer), ffile)) != NULL)
02577 lf_version = atof(buffer);
02578
02579 if ((_bcp_fgets(buffer, sizeof(buffer), ffile)) != NULL)
02580 li_numcols = atoi(buffer);
02581
02582
02583 while ((_bcp_fgets(buffer, sizeof(buffer), ffile)) != NULL) {
02584
02585 if (topptr == NULL) {
02586 if ((curptr = (struct fflist *) malloc(sizeof(struct fflist))) == NULL) {
02587 dbperror(dbproc, SYBEMEM, 0);
02588 return (FAIL);
02589 }
02590 topptr = curptr;
02591 } else {
02592 if ((curptr->nextptr = (struct fflist *) malloc(sizeof(struct fflist))) == NULL) {
02593 dbperror(dbproc, SYBEMEM, 0);
02594 return (FAIL);
02595 }
02596 curptr = curptr->nextptr;
02597 }
02598 curptr->nextptr = NULL;
02599 if (_bcp_readfmt_colinfo(dbproc, buffer, &(curptr->colinfo)))
02600 colinfo_count++;
02601 else
02602 return (FAIL);
02603
02604 }
02605 if (fclose(ffile) != 0) {
02606 dbperror(dbproc, SYBEBUCF, 0);
02607 return (FAIL);
02608 }
02609
02610 if (colinfo_count != li_numcols)
02611 return (FAIL);
02612
02613 if (bcp_columns(dbproc, li_numcols) == FAIL) {
02614 return (FAIL);
02615 }
02616
02617 for (curptr = topptr; curptr->nextptr != NULL; curptr = curptr->nextptr) {
02618 hostcol = &(curptr->colinfo);
02619 if (bcp_colfmt(dbproc, hostcol->host_column, hostcol->datatype,
02620 hostcol->prefix_len, hostcol->column_len,
02621 hostcol->terminator, hostcol->term_len, hostcol->tab_colnum) == FAIL) {
02622 return (FAIL);
02623 }
02624 }
02625 hostcol = &(curptr->colinfo);
02626 if (bcp_colfmt(dbproc, hostcol->host_column, hostcol->datatype,
02627 hostcol->prefix_len, hostcol->column_len,
02628 hostcol->terminator, hostcol->term_len, hostcol->tab_colnum) == FAIL) {
02629 return (FAIL);
02630 }
02631
02632 return (SUCCEED);
02633 }
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645 static int
02646 _bcp_readfmt_colinfo(DBPROCESS * dbproc, char *buf, BCP_HOSTCOLINFO * ci)
02647 {
02648
02649 char *tok;
02650 int whichcol;
02651 char term[30];
02652 int i;
02653
02654 enum nextcol
02655 {
02656 HOST_COLUMN,
02657 DATATYPE,
02658 PREFIX_LEN,
02659 COLUMN_LEN,
02660 TERMINATOR,
02661 TAB_COLNUM,
02662 NO_MORE_COLS
02663 };
02664
02665 tok = strtok(buf, " \t");
02666 whichcol = HOST_COLUMN;
02667
02668
02669 while (tok != NULL && whichcol != NO_MORE_COLS) {
02670 switch (whichcol) {
02671
02672 case HOST_COLUMN:
02673 ci->host_column = atoi(tok);
02674
02675 if (ci->host_column < 1) {
02676 dbperror(dbproc, SYBEBIHC, 0);
02677 return (FALSE);
02678 }
02679
02680 whichcol = DATATYPE;
02681 break;
02682
02683 case DATATYPE:
02684 if (strcmp(tok, "SYBCHAR") == 0)
02685 ci->datatype = SYBCHAR;
02686 else if (strcmp(tok, "SYBTEXT") == 0)
02687 ci->datatype = SYBTEXT;
02688 else if (strcmp(tok, "SYBBINARY") == 0)
02689 ci->datatype = SYBBINARY;
02690 else if (strcmp(tok, "SYBIMAGE") == 0)
02691 ci->datatype = SYBIMAGE;
02692 else if (strcmp(tok, "SYBINT1") == 0)
02693 ci->datatype = SYBINT1;
02694 else if (strcmp(tok, "SYBINT2") == 0)
02695 ci->datatype = SYBINT2;
02696 else if (strcmp(tok, "SYBINT4") == 0)
02697 ci->datatype = SYBINT4;
02698 else if (strcmp(tok, "SYBINT8") == 0)
02699 ci->datatype = SYBINT8;
02700 else if (strcmp(tok, "SYBFLT8") == 0)
02701 ci->datatype = SYBFLT8;
02702 else if (strcmp(tok, "SYBREAL") == 0)
02703 ci->datatype = SYBREAL;
02704 else if (strcmp(tok, "SYBBIT") == 0)
02705 ci->datatype = SYBBIT;
02706 else if (strcmp(tok, "SYBNUMERIC") == 0)
02707 ci->datatype = SYBNUMERIC;
02708 else if (strcmp(tok, "SYBDECIMAL") == 0)
02709 ci->datatype = SYBDECIMAL;
02710 else if (strcmp(tok, "SYBMONEY") == 0)
02711 ci->datatype = SYBMONEY;
02712 else if (strcmp(tok, "SYBDATETIME") == 0)
02713 ci->datatype = SYBDATETIME;
02714 else if (strcmp(tok, "SYBDATETIME4") == 0)
02715 ci->datatype = SYBDATETIME4;
02716 else {
02717 dbperror(dbproc, SYBEBUDF, 0);
02718 return (FALSE);
02719 }
02720
02721 whichcol = PREFIX_LEN;
02722 break;
02723
02724 case PREFIX_LEN:
02725 ci->prefix_len = atoi(tok);
02726 whichcol = COLUMN_LEN;
02727 break;
02728 case COLUMN_LEN:
02729 ci->column_len = atoi(tok);
02730 whichcol = TERMINATOR;
02731 break;
02732 case TERMINATOR:
02733
02734 if (*tok++ != '\"')
02735 return (FALSE);
02736
02737 for (i = 0; *tok != '\"' && i < sizeof(term); i++) {
02738 if (*tok == '\\') {
02739 tok++;
02740 switch (*tok) {
02741 case 't':
02742 term[i] = '\t';
02743 break;
02744 case 'n':
02745 term[i] = '\n';
02746 break;
02747 case 'r':
02748 term[i] = '\r';
02749 break;
02750 case '\\':
02751 term[i] = '\\';
02752 break;
02753 case '0':
02754 term[i] = '\0';
02755 break;
02756 default:
02757 return (FALSE);
02758 }
02759 tok++;
02760 } else
02761 term[i] = *tok++;
02762 }
02763
02764 if (*tok != '\"')
02765 return (FALSE);
02766
02767 ci->terminator = (BYTE *) malloc(i);
02768 memcpy((char *) ci->terminator, term, i);
02769 ci->term_len = i;
02770
02771 whichcol = TAB_COLNUM;
02772 break;
02773
02774 case TAB_COLNUM:
02775 ci->tab_colnum = atoi(tok);
02776 whichcol = NO_MORE_COLS;
02777 break;
02778
02779 }
02780 tok = strtok(NULL, " \t");
02781 }
02782 if (whichcol == NO_MORE_COLS)
02783 return (TRUE);
02784 else
02785 return (FALSE);
02786 }
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805 RETCODE
02806 bcp_writefmt(DBPROCESS * dbproc, char *filename)
02807 {
02808 if (dbproc->bcpinfo == NULL) {
02809 dbperror(dbproc, SYBEBCPI, 0);
02810 return FAIL;
02811 }
02812 return FAIL;
02813 }
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
02830 RETCODE
02831 bcp_moretext(DBPROCESS * dbproc, DBINT size, BYTE * text)
02832 {
02833 if (dbproc->bcpinfo == NULL) {
02834 dbperror(dbproc, SYBEBCPI, 0);
02835 return FAIL;
02836 }
02837 return FAIL;
02838 }
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849 DBINT
02850 bcp_batch(DBPROCESS * dbproc)
02851 {
02852 TDSSOCKET *tds = dbproc->tds_socket;
02853 int rows_copied = 0;
02854
02855 if (dbproc->bcpinfo == NULL) {
02856 dbperror(dbproc, SYBEBCPI, 0);
02857 return -1;
02858 }
02859
02860 tds_flush_packet(tds);
02861
02862 tds_set_state(tds, TDS_PENDING);
02863
02864 if (tds_process_simple_query(tds) != TDS_SUCCEED)
02865 return FAIL;
02866
02867 rows_copied = tds->rows_affected;
02868
02869 _bcp_start_new_batch(dbproc);
02870
02871 return (rows_copied);
02872 }
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884 DBINT
02885 bcp_done(DBPROCESS * dbproc)
02886 {
02887 TDSSOCKET *tds = dbproc->tds_socket;
02888 int rows_copied = -1;
02889
02890 if (dbproc->bcpinfo == NULL) {
02891 dbperror(dbproc, SYBEBCPI, 0);
02892 return -1;
02893 }
02894
02895
02896
02897 tds_flush_packet(tds);
02898
02899 tds_set_state(tds, TDS_PENDING);
02900
02901 if (tds_process_simple_query(tds) != TDS_SUCCEED)
02902 return FAIL;
02903 rows_copied = tds->rows_affected;
02904
02905 _bcp_free_storage(dbproc);
02906
02907 return (rows_copied);
02908
02909 }
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934 RETCODE
02935 bcp_bind(DBPROCESS * dbproc, BYTE * varaddr, int prefixlen, DBINT varlen,
02936 BYTE * terminator, int termlen, int vartype, int table_column)
02937 {
02938
02939 TDSCOLUMN *colinfo;
02940
02941 if (dbproc->bcpinfo == NULL) {
02942 dbperror(dbproc, SYBEBCPI, 0);
02943 return FAIL;
02944 }
02945
02946 if (dbproc->hostfileinfo != NULL) {
02947 dbperror(dbproc, SYBEBCPB, 0);
02948 return FAIL;
02949 }
02950
02951 if (dbproc->bcpinfo->direction != DB_IN) {
02952 dbperror(dbproc, SYBEBCPN, 0);
02953 return FAIL;
02954 }
02955
02956 if (varlen < -1) {
02957 dbperror(dbproc, SYBEBCVLEN, 0);
02958 return FAIL;
02959 }
02960
02961 if (prefixlen != 0 && prefixlen != 1 && prefixlen != 2 && prefixlen != 4) {
02962 dbperror(dbproc, SYBEBCBPREF, 0);
02963 return FAIL;
02964 }
02965
02966 if (prefixlen == 0 && varlen == -1 && termlen == -1 && !is_fixed_type(vartype)) {
02967 return FAIL;
02968 }
02969
02970 if (is_fixed_type(vartype) && (varlen != -1 && varlen != 0)) {
02971 return FAIL;
02972 }
02973
02974 if (table_column <= 0 || table_column > dbproc->bcpinfo->bindinfo->num_cols)
02975 return FAIL;
02976
02977 if (varaddr == NULL && (prefixlen != 0 || termlen != 0)) {
02978 dbperror(dbproc, SYBEBCBNPR, 0);
02979 return FAIL;
02980 }
02981
02982 colinfo = dbproc->bcpinfo->bindinfo->columns[table_column - 1];
02983
02984 colinfo->column_varaddr = (char *)varaddr;
02985 colinfo->column_bindtype = vartype;
02986 colinfo->column_bindlen = varlen;
02987 colinfo->bcp_terminator = malloc(termlen);
02988 memcpy(colinfo->bcp_terminator, terminator, termlen);
02989 colinfo->bcp_term_len = termlen;
02990
02991 return SUCCEED;
02992 }
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003 static RETCODE
03004 _bcp_send_bcp_record(DBPROCESS * dbproc, int behaviour)
03005 {
03006 TDSSOCKET *tds = dbproc->tds_socket;
03007 TDSCOLUMN *bindcol;
03008
03009 static const unsigned char CHARBIN_NULL[] = { 0xff, 0xff };
03010 static const unsigned char GEN_NULL = 0x00;
03011 static const unsigned char textptr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
03012 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
03013 };
03014 static const unsigned char timestamp[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
03015
03016 static const TDS_TINYINT textptr_size = 16;
03017
03018 unsigned char *record;
03019 TDS_INT old_record_size;
03020 TDS_INT new_record_size;
03021
03022 TDS_INT varint_4;
03023 TDS_SMALLINT varint_2;
03024 TDS_TINYINT varint_1;
03025
03026 int row_pos;
03027 int row_sz_pos;
03028 TDS_SMALLINT row_size;
03029
03030 int blob_cols = 0;
03031 int var_cols_written = 0;
03032
03033 int i;
03034
03035 tdsdump_log(TDS_DBG_FUNC, "_bcp_send_bcp_record\n");
03036
03037 record = dbproc->bcpinfo->bindinfo->current_row;
03038 old_record_size = dbproc->bcpinfo->bindinfo->row_size;
03039 new_record_size = 0;
03040
03041 if (IS_TDS7_PLUS(tds)) {
03042
03043 for (i = 0; i < dbproc->bcpinfo->bindinfo->num_cols; i++) {
03044
03045 bindcol = dbproc->bcpinfo->bindinfo->columns[i];
03046
03047
03048
03049
03050
03051
03052 if ((!dbproc->bcpinfo->identity_insert_on && bindcol->column_identity) ||
03053 bindcol->column_timestamp) {
03054 continue;
03055 }
03056
03057 if (behaviour == BCP_REC_FETCH_DATA) {
03058 if ((_bcp_get_col_data(dbproc, bindcol)) != SUCCEED) {
03059 tdsdump_log(TDS_DBG_INFO1, "bcp_get_colData (column %d) failed\n", i + 1);
03060 return FAIL;
03061 }
03062 tdsdump_log(TDS_DBG_INFO1, "gotten column %d length %d null %d\n",
03063 i + 1, bindcol->bcp_column_data->datalen, bindcol->bcp_column_data->null_column);
03064 }
03065 tdsdump_log(TDS_DBG_INFO1, "column %d length %d null %d\n",
03066 i + 1, bindcol->bcp_column_data->datalen, bindcol->bcp_column_data->null_column);
03067
03068 if (bindcol->bcp_column_data->null_column) {
03069 if (bindcol->column_nullable) {
03070 switch (bindcol->on_server.column_type) {
03071 case XSYBCHAR:
03072 case XSYBVARCHAR:
03073 case XSYBBINARY:
03074 case XSYBVARBINARY:
03075 case XSYBNCHAR:
03076 case XSYBNVARCHAR:
03077 memcpy(record, CHARBIN_NULL, 2);
03078 record +=2;
03079 new_record_size +=2;
03080 break;
03081 default:
03082 *record = GEN_NULL;
03083 record++;
03084 new_record_size ++;
03085 break;
03086 }
03087 } else {
03088 dbperror(dbproc, SYBEBCNN, 0);
03089 return FAIL;
03090 }
03091 } else {
03092
03093 switch (bindcol->column_varint_size) {
03094 case 4:
03095 if (is_blob_type(bindcol->column_type)) {
03096 *record = textptr_size; record++;
03097 memcpy(record, textptr, 16); record += 16;
03098 memcpy(record, timestamp, 8); record += 8;
03099 new_record_size += 25;
03100 }
03101 varint_4 = bindcol->bcp_column_data->datalen;
03102 #if WORDS_BIGENDIAN
03103 tds_swap_datatype(SYBINT4, (unsigned char *)&varint_4);
03104 #endif
03105 memcpy(record, &varint_4, 4); record += 4; new_record_size +=4;
03106 break;
03107 case 2:
03108 varint_2 = bindcol->bcp_column_data->datalen;
03109 #if WORDS_BIGENDIAN
03110 tds_swap_datatype(SYBINT2, (unsigned char *)&varint_2);
03111 #endif
03112 memcpy(record, &varint_2, 2); record += 2; new_record_size +=2;
03113 break;
03114 case 1:
03115 varint_1 = bindcol->bcp_column_data->datalen;
03116 if (is_numeric_type(bindcol->column_type)) {
03117 varint_1 = tds_numeric_bytes_per_prec[bindcol->column_prec];
03118 tdsdump_log(TDS_DBG_INFO1, "numeric type prec = %d varint_1 = %d\n", bindcol->column_prec, varint_1);
03119 }
03120 else {
03121 varint_1 = bindcol->bcp_column_data->datalen;
03122 tdsdump_log(TDS_DBG_INFO1, "varint_1 = %d\n", varint_1);
03123 }
03124 *record = varint_1; record++; new_record_size++;
03125 break;
03126 case 0:
03127 break;
03128 }
03129
03130 tdsdump_log(TDS_DBG_INFO1, "new_record_size = %d datalen = %d \n",
03131 new_record_size, bindcol->bcp_column_data->datalen);
03132
03133 #if WORDS_BIGENDIAN
03134 tds_swap_datatype(tds_get_conversion_type(bindcol->column_type, bindcol->bcp_column_data->datalen),
03135 bindcol->bcp_column_data->data);
03136 #endif
03137 tdsdump_log(TDS_DBG_INFO1, "new_record_size = %d datalen = %d \n",
03138 new_record_size, bindcol->bcp_column_data->datalen);
03139
03140
03141 if (is_numeric_type(bindcol->column_type)) {
03142 TDS_NUMERIC *num = (TDS_NUMERIC *) bindcol->bcp_column_data->data;
03143 int size;
03144 tdsdump_log(TDS_DBG_INFO1, "numeric type prec = %d\n", num->precision);
03145 if (IS_TDS7_PLUS(tds))
03146 tds_swap_numeric(num);
03147 size = tds_numeric_bytes_per_prec[num->precision];
03148 memcpy(record, num->array, size);
03149 record += size;
03150 new_record_size += size;
03151 } else {
03152 tdsdump_log(TDS_DBG_INFO1, "new_record_size = %d datalen = %d \n",
03153 new_record_size, bindcol->bcp_column_data->datalen);
03154 memcpy(record, bindcol->bcp_column_data->data, bindcol->bcp_column_data->datalen);
03155 record += bindcol->bcp_column_data->datalen;
03156 new_record_size += bindcol->bcp_column_data->datalen;
03157 }
03158
03159 }
03160 tdsdump_log(TDS_DBG_INFO1, "old_record_size = %d new size = %d \n",
03161 old_record_size, new_record_size);
03162 }
03163
03164 tds_put_byte(tds, TDS_ROW_TOKEN);
03165 tds_put_n(tds, dbproc->bcpinfo->bindinfo->current_row, new_record_size);
03166 }
03167 else {
03168 memset(record, '\0', old_record_size);
03169
03170
03171
03172 row_pos = 2;
03173
03174 if ((row_pos = _bcp_add_fixed_columns(dbproc, behaviour, record, row_pos)) == FAIL)
03175 return FAIL;
03176
03177 row_sz_pos = row_pos;
03178
03179
03180
03181 if (dbproc->bcpinfo->var_cols) {
03182 if ((row_pos = _bcp_add_variable_columns(dbproc, behaviour, record, row_pos, &var_cols_written)) == FAIL)
03183 return FAIL;
03184 }
03185
03186 row_size = row_pos;
03187
03188 if (var_cols_written) {
03189 memcpy(&record[row_sz_pos], &row_size, sizeof(row_size));
03190 record[0] = var_cols_written;
03191 }
03192
03193 tdsdump_log(TDS_DBG_INFO1, "old_record_size = %d new size = %d \n",
03194 old_record_size, row_size);
03195
03196 tds_put_smallint(tds, row_size);
03197 tds_put_n(tds, record, row_size);
03198
03199
03200
03201 blob_cols = 0;
03202
03203 for (i = 0; i < dbproc->bcpinfo->bindinfo->num_cols; i++) {
03204 bindcol = dbproc->bcpinfo->bindinfo->columns[i];
03205 if (is_blob_type(bindcol->column_type)) {
03206 if (behaviour == BCP_REC_FETCH_DATA) {
03207 if ((_bcp_get_col_data(dbproc, bindcol)) != SUCCEED) {
03208 return FAIL;
03209 }
03210 }
03211
03212 tds_put_smallint(tds, 0);
03213 tds_put_byte(tds, bindcol->column_type);
03214 tds_put_byte(tds, 0xff - blob_cols);
03215
03216
03217
03218
03219 tds_put_smallint(tds, bindcol->column_textpos);
03220 tds_put_int(tds, bindcol->bcp_column_data->datalen);
03221 tds_put_n(tds, bindcol->bcp_column_data->data, bindcol->bcp_column_data->datalen);
03222 blob_cols++;
03223
03224 }
03225 }
03226 return SUCCEED;
03227 }
03228
03229 return SUCCEED;
03230 }
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245 static RETCODE
03246 _bcp_get_col_data(DBPROCESS * dbproc, TDSCOLUMN *bindcol)
03247 {
03248 TDS_TINYINT ti;
03249 TDS_SMALLINT si;
03250 TDS_INT li;
03251 TDS_INT desttype;
03252 int collen;
03253 int data_is_null;
03254 int bytes_read;
03255 int converted_data_size;
03256
03257 BYTE *dataptr;
03258
03259
03260 dataptr = (BYTE *) bindcol->column_varaddr;
03261
03262 data_is_null = 0;
03263 collen = 0;
03264
03265
03266
03267 if (bindcol->bcp_prefix_len > 0) {
03268
03269 switch (bindcol->bcp_prefix_len) {
03270 case 1:
03271 memcpy(&ti, dataptr, 1);
03272 dataptr += 1;
03273 collen = ti;
03274 break;
03275 case 2:
03276 memcpy(&si, dataptr, 2);
03277 dataptr += 2;
03278 collen = si;
03279 break;
03280 case 4:
03281 memcpy(&li, dataptr, 4);
03282 dataptr += 4;
03283 collen = li;
03284 break;
03285 }
03286 if (collen == 0)
03287 data_is_null = 1;
03288
03289 }
03290
03291
03292
03293 if (!data_is_null && bindcol->column_bindlen >= 0) {
03294 if (bindcol->column_bindlen == 0)
03295 data_is_null = 1;
03296 else {
03297 if (collen)
03298 collen = (bindcol->column_bindlen < collen) ? bindcol->column_bindlen : collen;
03299 else
03300 collen = bindcol->column_bindlen;
03301 }
03302 }
03303
03304
03305
03306 if (is_fixed_type(bindcol->column_bindtype)) {
03307 collen = tds_get_size_by_type(bindcol->column_bindtype);
03308 }
03309
03310
03311
03312 if (bindcol->bcp_term_len > 0) {
03313 bytes_read = _bcp_get_term_var(dataptr, (BYTE *)bindcol->bcp_terminator, bindcol->bcp_term_len);
03314
03315 if (collen)
03316 collen = (bytes_read < collen) ? bytes_read : collen;
03317 else
03318 collen = bytes_read;
03319
03320 if (collen == 0)
03321 data_is_null = 1;
03322 }
03323
03324 if (data_is_null) {
03325 bindcol->bcp_column_data->datalen = 0;
03326 bindcol->bcp_column_data->null_column = 1;
03327 } else {
03328 desttype = tds_get_conversion_type(bindcol->column_type, bindcol->column_size);
03329
03330 if ((converted_data_size =
03331 dbconvert(dbproc, bindcol->column_bindtype,
03332 (BYTE *) dataptr, collen,
03333 desttype, bindcol->bcp_column_data->data, bindcol->column_size)) == -1) {
03334 return (FAIL);
03335 }
03336
03337 bindcol->bcp_column_data->datalen = converted_data_size;
03338 bindcol->bcp_column_data->null_column = 0;
03339 }
03340
03341 return SUCCEED;
03342 }
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359 static RETCODE
03360 _bcp_get_term_var(BYTE * pdata, BYTE * term, int term_len)
03361 {
03362 int bufpos;
03363
03364 assert(term_len > 0);
03365
03366
03367 for (bufpos = 0; bufpos >= 0 && memcmp(pdata, term, term_len) != 0; pdata++) {
03368 bufpos++;
03369 }
03370
03371 assert(bufpos > 0);
03372 return bufpos;
03373 }
03374
03375
03376
03377
03378
03379
03380
03381
03382
03383
03384 static int
03385 rtrim(char *istr, int ilen)
03386 {
03387 char *t;
03388
03389 for (t = istr + ilen; --t > istr && *t == ' '; )
03390 *t = '\0';
03391 return t - istr + 1;
03392 }
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402 static void
03403 _bcp_free_columns(DBPROCESS * dbproc)
03404 {
03405 int i;
03406
03407 assert(dbproc && dbproc->hostfileinfo);
03408 if (dbproc->hostfileinfo->host_columns) {
03409 for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
03410 if (dbproc->hostfileinfo->host_columns[i]->terminator)
03411 TDS_ZERO_FREE(dbproc->hostfileinfo->host_columns[i]->terminator);
03412 tds_free_bcp_column_data(dbproc->hostfileinfo->host_columns[i]->bcp_column_data);
03413 TDS_ZERO_FREE(dbproc->hostfileinfo->host_columns[i]);
03414 }
03415 TDS_ZERO_FREE(dbproc->hostfileinfo->host_columns);
03416 dbproc->hostfileinfo->host_colcount = 0;
03417 }
03418 }
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428 static RETCODE
03429 _bcp_free_storage(DBPROCESS * dbproc)
03430 {
03431 if (dbproc->hostfileinfo) {
03432 if (dbproc->hostfileinfo->hostfile)
03433 TDS_ZERO_FREE(dbproc->hostfileinfo->hostfile);
03434
03435 if (dbproc->hostfileinfo->errorfile)
03436 TDS_ZERO_FREE(dbproc->hostfileinfo->errorfile);
03437
03438
03439
03440 _bcp_free_columns(dbproc);
03441 TDS_ZERO_FREE(dbproc->hostfileinfo);
03442 }
03443
03444
03445 if (dbproc->bcpinfo) {
03446 if (dbproc->bcpinfo->tablename)
03447 TDS_ZERO_FREE(dbproc->bcpinfo->tablename);
03448
03449 if (dbproc->bcpinfo->insert_stmt)
03450 TDS_ZERO_FREE(dbproc->bcpinfo->insert_stmt);
03451
03452 if (dbproc->bcpinfo->bindinfo) {
03453
03454 if (dbproc->bcpinfo->bindinfo->current_row)
03455 TDS_ZERO_FREE(dbproc->bcpinfo->bindinfo->current_row);
03456 tds_free_results(dbproc->bcpinfo->bindinfo);
03457 dbproc->bcpinfo->bindinfo = NULL;
03458 }
03459
03460 TDS_ZERO_FREE(dbproc->bcpinfo);
03461 }
03462
03463 return (SUCCEED);
03464
03465 }
03466
03467
03468