Line data Source code
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) 2010, 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 <stdarg.h>
24 : #include <stdio.h>
25 : #include <assert.h>
26 :
27 : #if HAVE_STRING_H
28 : #include <string.h>
29 : #endif /* HAVE_STRING_H */
30 :
31 : #if HAVE_STDLIB_H
32 : #include <stdlib.h>
33 : #endif /* HAVE_STDLIB_H */
34 :
35 : #if HAVE_UNISTD_H
36 : #include <unistd.h>
37 : #endif /* HAVE_UNISTD_H */
38 :
39 : #ifdef _WIN32
40 : #include <io.h>
41 : #endif
42 :
43 : #include <freetds/tds.h>
44 : #include <freetds/tds/checks.h>
45 : #include <freetds/tds/iconv.h>
46 : #include <freetds/tds/convert.h>
47 : #include <freetds/bytes.h>
48 : #include <freetds/tds/stream.h>
49 : #include <freetds/utils/string.h>
50 : #include <freetds/encodings.h>
51 : #include <freetds/replacements.h>
52 : #include <sybfront.h>
53 : #include <sybdb.h>
54 : #include <syberror.h>
55 : #include <dblib.h>
56 :
57 : #define BCP_DEFAULT_DATEFMT "%Y-%m-%d %H:%M:%S.%z"
58 :
59 : #define HOST_COL_CONV_ERROR 1
60 : #define HOST_COL_NULL_ERROR 2
61 :
62 : #ifdef HAVE_FSEEKO
63 : typedef off_t offset_type;
64 : #elif defined(_WIN32) || defined(_WIN64)
65 : /* win32 version */
66 : typedef __int64 offset_type;
67 : # if defined(HAVE__FSEEKI64) && defined(HAVE__FTELLI64)
68 : # define fseeko(f,o,w) _fseeki64((f),o,w)
69 : # define ftello(f) _ftelli64((f))
70 : # else
71 : # define fseeko(f,o,w) (_lseeki64(fileno(f),o,w) == -1 ? -1 : 0)
72 : # define ftello(f) _telli64(fileno(f))
73 : # endif
74 : #else
75 : /* use old version */
76 : #define fseeko(f,o,w) fseek(f,o,w)
77 : #define ftello(f) ftell(f)
78 : typedef long offset_type;
79 : #endif
80 :
81 : static void _bcp_free_storage(DBPROCESS * dbproc);
82 : static void _bcp_free_columns(DBPROCESS * dbproc);
83 : static void _bcp_null_error(TDSBCPINFO *bcpinfo, int index, int offset);
84 : static TDSRET _bcp_get_col_data(TDSBCPINFO * bcpinfo, TDSCOLUMN * bindcol, int index, int offset);
85 : static TDSRET _bcp_no_get_col_data(TDSBCPINFO * bcpinfo, TDSCOLUMN * bindcol, int index, int offset);
86 :
87 : static int rtrim(char *, int);
88 : static int rtrim_u16(uint16_t *str, int len, uint16_t space);
89 : static STATUS _bcp_read_hostfile(DBPROCESS * dbproc, FILE * hostfile, bool *row_error, bool skip);
90 : static int _bcp_readfmt_colinfo(DBPROCESS * dbproc, char *buf, BCP_HOSTCOLINFO * ci);
91 : static int _bcp_get_term_var(const BYTE * pdata, const BYTE * term, int term_len);
92 : static int _bcp_strftime(char *buf, size_t maxsize, const char *format, const TDSDATEREC * dr, int prec);
93 :
94 : /*
95 : * "If a host file is being used ... the default data formats are as follows:
96 : *
97 : * > The order, type, length and number of the columns in the host file are
98 : * assumed to be identical to the order, type and number of the columns in the database table.
99 : * > If a given database column's data is fixed-length,
100 : * then the host file's data column will also be fixed-length.
101 : * > If a given database column's data is variable-length or may contain null values,
102 : * the host file's data column will be prefixed by
103 : * a 4-byte length value for SYBTEXT and SYBIMAGE data types, and
104 : * a 1-byte length value for all other types.
105 : * > There are no terminators of any kind between host file columns."
106 : */
107 :
108 : static void
109 328 : init_hostfile_columns(DBPROCESS *dbproc)
110 : {
111 328 : const int ncols = dbproc->bcpinfo->bindinfo->num_cols;
112 : RETCODE erc;
113 : int icol;
114 :
115 328 : if (ncols == 0)
116 : return;
117 :
118 328 : if ((erc = bcp_columns(dbproc, ncols)) != SUCCEED) {
119 0 : assert(erc == SUCCEED);
120 : return;
121 : }
122 :
123 2016 : for (icol = 0; icol < ncols; icol++) {
124 1688 : const TDSCOLUMN *pcol = dbproc->bcpinfo->bindinfo->columns[icol];
125 1688 : int prefixlen = 0, termlen = 0;
126 :
127 1688 : switch (pcol->column_type) {
128 : case SYBTEXT:
129 : case SYBIMAGE:
130 : prefixlen = 4;
131 : break;
132 1548 : default:
133 1548 : prefixlen = dbvarylen(dbproc, icol+1)? 1 : 0;
134 : }
135 :
136 1688 : erc = bcp_colfmt(dbproc, icol+1, pcol->column_type, prefixlen, pcol->column_size, NULL, termlen, icol+1);
137 :
138 1688 : assert(erc == SUCCEED);
139 : if (erc != SUCCEED)
140 : return;
141 : }
142 : }
143 :
144 :
145 : /**
146 : * \ingroup dblib_bcp
147 : * \brief Prepare for bulk copy operation on a table
148 : *
149 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
150 : * \param tblname the name of the table receiving or providing the data.
151 : * \param hfile the data file opposite the table, if any.
152 : * \param errfile the "error file" captures messages and, if errors are encountered,
153 : * copies of any rows that could not be written to the table.
154 : * \param direction one of
155 : * - \b DB_IN writing to the table
156 : * - \b DB_OUT writing to the host file
157 : * .
158 : * \remarks bcp_init() sets the host file data format and acquires the table metadata.
159 : * It is called before the other bulk copy functions.
160 : *
161 : * When writing to a table, bcp can use as its data source a data file (\a hfile),
162 : * or program data in an application's variables. In the latter case, call bcp_bind()
163 : * to associate your data with the appropriate table column.
164 : * \return SUCCEED or FAIL.
165 : * \sa BCP_SETL(), bcp_bind(), bcp_done(), bcp_exec()
166 : */
167 : RETCODE
168 366 : bcp_init(DBPROCESS * dbproc, const char *tblname, const char *hfile, const char *errfile, int direction)
169 : {
170 366 : tdsdump_log(TDS_DBG_FUNC, "bcp_init(%p, %s, %s, %s, %d)\n",
171 : dbproc, tblname? tblname:"NULL", hfile? hfile:"NULL", errfile? errfile:"NULL", direction);
172 366 : CHECK_CONN(FAIL);
173 :
174 : /*
175 : * Validate other parameters
176 : */
177 366 : if (dbproc->tds_socket->conn->tds_version < 0x500) {
178 0 : dbperror(dbproc, SYBETDSVER, 0);
179 0 : return FAIL;
180 : }
181 :
182 366 : if (tblname == NULL) {
183 0 : dbperror(dbproc, SYBEBCITBNM, 0);
184 0 : return FAIL;
185 : }
186 :
187 422 : if (direction != DB_QUERYOUT && !IS_TDS7_PLUS(dbproc->tds_socket->conn) &&
188 56 : strlen(tblname) > 92) { /* 30.30.30 for Sybase */
189 0 : dbperror(dbproc, SYBEBCITBLEN, 0);
190 0 : return FAIL;
191 : }
192 :
193 366 : if (direction != DB_IN && direction != DB_OUT && direction != DB_QUERYOUT) {
194 0 : dbperror(dbproc, SYBEBDIO, 0);
195 0 : return FAIL;
196 : }
197 :
198 : /* Free previously allocated storage in dbproc & initialise flags, etc. */
199 366 : _bcp_free_storage(dbproc);
200 :
201 : /* Allocate storage */
202 366 : dbproc->bcpinfo = tds_alloc_bcpinfo();
203 366 : if (dbproc->bcpinfo == NULL)
204 : goto memory_error;
205 :
206 366 : if (!tds_dstr_copy(&dbproc->bcpinfo->tablename, tblname))
207 : goto memory_error;
208 :
209 366 : dbproc->bcpinfo->direction = direction;
210 :
211 366 : dbproc->bcpinfo->xfer_init = false;
212 366 : dbproc->bcpinfo->bind_count = 0;
213 :
214 366 : if (TDS_FAILED(tds_bcp_init(dbproc->tds_socket, dbproc->bcpinfo))) {
215 : /* TODO return proper error */
216 : /* Attempt to use Bulk Copy with a non-existent Server table (might be why ...) */
217 0 : dbperror(dbproc, SYBEBCNT, 0);
218 0 : return FAIL;
219 : }
220 :
221 : /* Prepare default hostfile columns */
222 :
223 366 : if (hfile == NULL) {
224 38 : dbproc->hostfileinfo = NULL;
225 38 : return SUCCEED;
226 : }
227 :
228 328 : dbproc->hostfileinfo = tds_new0(BCP_HOSTFILEINFO, 1);
229 :
230 328 : if (dbproc->hostfileinfo == NULL)
231 : goto memory_error;
232 328 : dbproc->hostfileinfo->maxerrs = 10;
233 328 : dbproc->hostfileinfo->firstrow = 1;
234 328 : if ((dbproc->hostfileinfo->hostfile = strdup(hfile)) == NULL)
235 : goto memory_error;
236 :
237 328 : if (errfile != NULL)
238 328 : if ((dbproc->hostfileinfo->errorfile = strdup(errfile)) == NULL)
239 : goto memory_error;
240 :
241 328 : init_hostfile_columns(dbproc);
242 :
243 328 : return SUCCEED;
244 :
245 0 : memory_error:
246 0 : _bcp_free_storage(dbproc);
247 0 : dbperror(dbproc, SYBEMEM, ENOMEM);
248 0 : return FAIL;
249 : }
250 :
251 :
252 : /**
253 : * \ingroup dblib_bcp
254 : * \brief Set the length of a host variable to be written to a table.
255 : *
256 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
257 : * \param varlen size of the variable, in bytes, or
258 : * - \b 0 indicating NULL
259 : * - \b -1 indicating size is determined by the prefix or terminator.
260 : * (If both a prefix and a terminator are present, bcp is supposed to use the smaller of the
261 : * two. This feature might or might not actually work.)
262 : * \param table_column the number of the column in the table (starting with 1, not zero).
263 : *
264 : * \return SUCCEED or FAIL.
265 : * \sa bcp_bind(), bcp_colptr(), bcp_sendrow()
266 : */
267 : RETCODE
268 130 : bcp_collen(DBPROCESS * dbproc, DBINT varlen, int table_column)
269 : {
270 : TDSCOLUMN *bcpcol;
271 :
272 130 : tdsdump_log(TDS_DBG_FUNC, "bcp_collen(%p, %d, %d)\n", dbproc, varlen, table_column);
273 :
274 130 : CHECK_CONN(FAIL);
275 130 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL); /* not initialized */
276 130 : DBPERROR_RETURN(dbproc->bcpinfo->direction != DB_IN, SYBEBCPN) /* not inbound */
277 130 : DBPERROR_RETURN(dbproc->hostfileinfo != NULL, SYBEBCPI) /* cannot have data file */
278 130 : CHECK_PARAMETER(0 < table_column &&
279 : table_column <= dbproc->bcpinfo->bindinfo->num_cols, SYBECNOR, FAIL);
280 :
281 130 : bcpcol = dbproc->bcpinfo->bindinfo->columns[table_column - 1];
282 :
283 : /* Sybase library does not check for NULL here, only sending, so don't
284 : * check and send SYBEBCNN */
285 130 : bcpcol->column_bindlen = varlen;
286 :
287 130 : return SUCCEED;
288 : }
289 :
290 : /**
291 : * \ingroup dblib_bcp
292 : * \brief Indicate how many columns are to be found in the datafile.
293 : *
294 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
295 : * \param host_colcount count of columns in the datafile, irrespective of how many you intend to use.
296 : * \remarks This function describes the file as it is, not how it will be used.
297 : *
298 : * \return SUCCEED or FAIL. It's hard to see how it could fail.
299 : * \sa bcp_colfmt()
300 : */
301 : RETCODE
302 656 : bcp_columns(DBPROCESS * dbproc, int host_colcount)
303 : {
304 : int i;
305 :
306 656 : tdsdump_log(TDS_DBG_FUNC, "bcp_columns(%p, %d)\n", dbproc, host_colcount);
307 656 : CHECK_CONN(FAIL);
308 656 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
309 656 : CHECK_PARAMETER(dbproc->hostfileinfo, SYBEBIVI, FAIL);
310 :
311 656 : if (host_colcount < 1) {
312 0 : dbperror(dbproc, SYBEBCFO, 0);
313 0 : return FAIL;
314 : }
315 :
316 656 : _bcp_free_columns(dbproc);
317 :
318 656 : dbproc->hostfileinfo->host_columns = tds_new0(BCP_HOSTCOLINFO *, host_colcount);
319 656 : if (dbproc->hostfileinfo->host_columns == NULL) {
320 0 : dbperror(dbproc, SYBEMEM, ENOMEM);
321 0 : return FAIL;
322 : }
323 :
324 656 : dbproc->hostfileinfo->host_colcount = host_colcount;
325 :
326 4032 : for (i = 0; i < host_colcount; i++) {
327 3376 : dbproc->hostfileinfo->host_columns[i] = tds_new0(BCP_HOSTCOLINFO, 1);
328 3376 : if (dbproc->hostfileinfo->host_columns[i] == NULL) {
329 0 : dbproc->hostfileinfo->host_colcount = i;
330 0 : _bcp_free_columns(dbproc);
331 0 : dbperror(dbproc, SYBEMEM, ENOMEM);
332 0 : return FAIL;
333 : }
334 : }
335 :
336 : return SUCCEED;
337 : }
338 :
339 : /**
340 : * \ingroup dblib_bcp
341 : * \brief Specify the format of a datafile prior to writing to a table.
342 : *
343 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
344 : * \param host_colnum datafile column number (starting with 1, not zero).
345 : * \param host_type dataype token describing the data type in \a host_colnum. E.g. SYBCHAR for character data.
346 : * \param host_prefixlen size of the prefix in the datafile column, if any. For delimited files: zero.
347 : * May be 0, 1, 2, or 4 bytes. The prefix will be read as an integer (not a character string) from the
348 : * data file, and will be interpreted the data size of that column, in bytes.
349 : * \param host_collen maximum size of datafile column, exclusive of any prefix/terminator. Just the data, ma'am.
350 : * Special values:
351 : * - \b 0 indicates NULL.
352 : * - \b -1 for fixed-length non-null datatypes
353 : * - \b -1 for variable-length datatypes (e.g. SYBCHAR) where the length is established
354 : * by a prefix/terminator.
355 : * \param host_term the sequence of characters that will serve as a column terminator (delimiter) in the datafile.
356 : * Often a tab character, but can be any string of any length. Zero indicates no terminator.
357 : * Special characters:
358 : * - \b '\\0' terminator is an ASCII NUL.
359 : * - \b '\\t' terminator is an ASCII TAB.
360 : * - \b '\\n' terminator is an ASCII NL.
361 : * \param host_termlen the length of \a host_term, in bytes.
362 : * \param table_colnum Nth column, starting at 1, in the table that maps to \a host_colnum.
363 : * If there is a column in the datafile that does not map to a table column, set \a table_colnum to zero.
364 : *
365 : *\remarks bcp_colfmt() is called once for each column in the datafile, as specified with bcp_columns().
366 : * In so doing, you describe to FreeTDS how to parse each line of your datafile, and where to send each field.
367 : *
368 : * When a prefix or terminator is used with variable-length data, \a host_collen may have one of three values:
369 : * - \b positive indicating the maximum number of bytes to be used
370 : * - \b 0 indicating NULL
371 : * - \b -1 indicating no maximum; all data, as described by the prefix/terminator will be used.
372 : * .
373 : * \return SUCCEED or FAIL.
374 : * \sa bcp_batch(), bcp_bind(), bcp_colfmt_ps(), bcp_collen(), bcp_colptr(), bcp_columns(),
375 : * bcp_control(), bcp_done(), bcp_exec(), bcp_init(), bcp_sendrow
376 : */
377 : RETCODE
378 3376 : bcp_colfmt(DBPROCESS * dbproc, int host_colnum, int host_type, int host_prefixlen, DBINT host_collen, const BYTE * host_term,
379 : int host_termlen, int table_colnum)
380 : {
381 : BCP_HOSTCOLINFO *hostcol;
382 3376 : BYTE *terminator = NULL;
383 :
384 3376 : tdsdump_log(TDS_DBG_FUNC, "bcp_colfmt(%p, %d, %d, %d, %d, %p, %d, %d)\n",
385 : dbproc, host_colnum, host_type, host_prefixlen, (int) host_collen, host_term, host_termlen, table_colnum);
386 3376 : CHECK_CONN(FAIL);
387 3376 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
388 3376 : CHECK_PARAMETER(dbproc->hostfileinfo, SYBEBIVI, FAIL);
389 :
390 : /* Microsoft specifies a "file_termlen" of zero if there's no terminator */
391 3376 : if (dbproc->msdblib && host_termlen == 0)
392 : host_termlen = -1;
393 :
394 3376 : if (host_termlen < 0)
395 0 : host_termlen = -1;
396 :
397 3376 : if (dbproc->hostfileinfo->host_colcount == 0) {
398 0 : dbperror(dbproc, SYBEBCBC, 0);
399 0 : return FAIL;
400 : }
401 :
402 3376 : if (host_colnum < 1) {
403 0 : dbperror(dbproc, SYBEBCFO, 0);
404 0 : return FAIL;
405 : }
406 :
407 3376 : if (host_colnum > dbproc->hostfileinfo->host_colcount) {
408 0 : dbperror(dbproc, SYBECNOR, 0);
409 0 : return FAIL;
410 : }
411 :
412 3376 : if (host_prefixlen != 0 && host_prefixlen != 1 && host_prefixlen != 2 && host_prefixlen != 4 && host_prefixlen != -1) {
413 0 : dbperror(dbproc, SYBEBCPREF, 0);
414 0 : return FAIL;
415 : }
416 :
417 : /* if column is not copied you cannot specify destination type */
418 3376 : if (table_colnum <= 0 && host_type == 0) {
419 0 : dbperror(dbproc, SYBEBCPCTYP, 0);
420 0 : return FAIL;
421 : }
422 :
423 6752 : if (table_colnum > 0 && !is_tds_type_valid(host_type)) {
424 0 : dbperror(dbproc, SYBEUDTY, 0);
425 0 : return FAIL;
426 : }
427 :
428 3376 : if (host_type && host_prefixlen == 0 && host_collen == -1 && host_termlen == -1 && !is_fixed_type(host_type)) {
429 0 : dbperror(dbproc, SYBEVDPT, 0);
430 0 : return FAIL;
431 : }
432 :
433 3376 : if (host_collen < -1) {
434 0 : dbperror(dbproc, SYBEBCHLEN, 0);
435 0 : return FAIL;
436 : }
437 :
438 : /* No official error message. Fix and warn. */
439 3376 : if (is_fixed_type(host_type) && (host_collen != -1 && host_collen != 0)) {
440 696 : tdsdump_log(TDS_DBG_FUNC,
441 : "bcp_colfmt: changing host_collen to -1 from %d for fixed type %d.\n",
442 : host_collen, host_type);
443 : host_collen = -1;
444 : }
445 :
446 : /*
447 : * If there's a positive terminator length, we need a valid terminator pointer.
448 : * If the terminator length is 0 or -1, then there's no terminator.
449 : */
450 3376 : if (host_term == NULL && host_termlen > 0) {
451 0 : dbperror(dbproc, SYBEVDPT, 0); /* "all variable-length data must have either a length-prefix ..." */
452 0 : return FAIL;
453 : }
454 :
455 3376 : hostcol = dbproc->hostfileinfo->host_columns[host_colnum - 1];
456 :
457 : /* TODO add precision scale and join with bcp_colfmt_ps */
458 3376 : if (host_term && host_termlen > 0) {
459 1648 : if ((terminator = tds_new(BYTE, host_termlen)) == NULL) {
460 0 : dbperror(dbproc, SYBEMEM, errno);
461 0 : return FAIL;
462 : }
463 1648 : memcpy(terminator, host_term, host_termlen);
464 : }
465 3376 : hostcol->host_column = host_colnum;
466 3376 : hostcol->datatype = host_type ? (TDS_SERVER_TYPE) host_type : TDS_INVALID_TYPE;
467 3376 : hostcol->prefix_len = host_prefixlen;
468 3376 : hostcol->column_len = host_collen;
469 3376 : free(hostcol->terminator);
470 3376 : hostcol->terminator = terminator;
471 3376 : hostcol->term_len = host_termlen;
472 3376 : hostcol->tab_colnum = table_colnum;
473 :
474 3376 : return SUCCEED;
475 : }
476 :
477 : /**
478 : * \ingroup dblib_bcp
479 : * \brief Specify the format of a host file for bulk copy purposes,
480 : * with precision and scale support for numeric and decimal columns.
481 : *
482 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
483 : * \param host_colnum datafile column number (starting with 1, not zero).
484 : * \param host_type dataype token describing the data type in \a host_colnum. E.g. SYBCHAR for character data.
485 : * \param host_prefixlen size of the prefix in the datafile column, if any. For delimited files: zero.
486 : * May be 0, 1, 2, or 4 bytes. The prefix will be read as an integer (not a character string) from the
487 : * data file, and will be interpreted the data size of that column, in bytes.
488 : * \param host_collen maximum size of datafile column, exclusive of any prefix/terminator. Just the data, ma'am.
489 : * Special values:
490 : * - \b 0 indicates NULL.
491 : * - \b -1 for fixed-length non-null datatypes
492 : * - \b -1 for variable-length datatypes (e.g. SYBCHAR) where the length is established
493 : * by a prefix/terminator.
494 : * \param host_term the sequence of characters that will serve as a column terminator (delimiter) in the datafile.
495 : * Often a tab character, but can be any string of any length. Zero indicates no terminator.
496 : * Special characters:
497 : * - \b '\\0' terminator is an ASCII NUL.
498 : * - \b '\\t' terminator is an ASCII TAB.
499 : * - \b '\\n' terminator is an ASCII NL.
500 : * \param host_termlen the length of \a host_term, in bytes.
501 : * \param table_colnum Nth column, starting at 1, in the table that maps to \a host_colnum.
502 : * If there is a column in the datafile that does not map to a table column, set \a table_colnum to zero.
503 : * \param typeinfo something
504 : * \todo Not implemented.
505 : * \return SUCCEED or FAIL.
506 : * \sa bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_collen(), bcp_colptr(), bcp_columns(),
507 : * bcp_control(), bcp_done(), bcp_exec(), bcp_init(), bcp_sendrow
508 : */
509 : RETCODE
510 0 : bcp_colfmt_ps(DBPROCESS * dbproc, int host_colnum, int host_type,
511 : int host_prefixlen, DBINT host_collen, BYTE * host_term, int host_termlen, int table_colnum, DBTYPEINFO * typeinfo)
512 : {
513 0 : tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED: bcp_colfmt_ps(%p, %d, %d, %d, %d, %p, %d, %d, %p)\n",
514 : dbproc, host_colnum, host_type, host_prefixlen, (int) host_collen,
515 : host_term, host_termlen, table_colnum, typeinfo);
516 0 : CHECK_CONN(FAIL);
517 0 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
518 :
519 : /* dbperror(dbproc, , 0); Illegal precision specified */
520 :
521 : /* TODO see bcp_colfmt */
522 : return FAIL;
523 : }
524 :
525 :
526 : /**
527 : * \ingroup dblib_bcp
528 : * \brief Set BCP options for uploading a datafile
529 : *
530 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
531 : * \param field symbolic constant indicating the option to be set, one of:
532 : * - \b BCPMAXERRS Maximum errors tolerated before quitting. The default is 10.
533 : * - \b BCPFIRST The first row to read in the datafile. The default is 1.
534 : * - \b BCPLAST The last row to read in the datafile. The default is to copy all rows. A value of
535 : * -1 resets this field to its default?
536 : * - \b BCPBATCH The number of rows per batch. Default is 0, meaning a single batch.
537 : * \param value The value for \a field.
538 : *
539 : * \remarks These options control the behavior of bcp_exec().
540 : * When writing to a table from application host memory variables,
541 : * program logic controls error tolerance and batch size.
542 : *
543 : * \return SUCCEED or FAIL.
544 : * \sa bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_done(), bcp_exec(), bcp_options()
545 : */
546 : RETCODE
547 0 : bcp_control(DBPROCESS * dbproc, int field, DBINT value)
548 : {
549 0 : tdsdump_log(TDS_DBG_FUNC, "bcp_control(%p, %d, %d)\n", dbproc, field, value);
550 0 : CHECK_CONN(FAIL);
551 0 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
552 :
553 0 : if (field == BCPKEEPIDENTITY) {
554 0 : dbproc->bcpinfo->identity_insert_on = (value != 0);
555 0 : return SUCCEED;
556 : }
557 :
558 0 : CHECK_PARAMETER(dbproc->hostfileinfo, SYBEBIVI, FAIL);
559 :
560 0 : switch (field) {
561 :
562 0 : case BCPMAXERRS:
563 0 : if (value < 1)
564 0 : value = 10;
565 0 : dbproc->hostfileinfo->maxerrs = value;
566 0 : break;
567 0 : case BCPFIRST:
568 0 : if (value < 1)
569 0 : value = 1;
570 0 : dbproc->hostfileinfo->firstrow = value;
571 0 : break;
572 0 : case BCPLAST:
573 0 : dbproc->hostfileinfo->lastrow = value;
574 0 : break;
575 0 : case BCPBATCH:
576 0 : dbproc->hostfileinfo->batch = value;
577 0 : break;
578 :
579 0 : default:
580 0 : dbperror(dbproc, SYBEIFNB, 0);
581 0 : return FAIL;
582 : }
583 : return SUCCEED;
584 : }
585 :
586 : /*
587 : * \ingroup dblib_bcp
588 : * \brief Get BCP batch option
589 : *
590 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
591 : * \remarks This function is specific to FreeTDS.
592 : *
593 : * \return the value that was set by bcp_control.
594 : * \sa bcp_batch(), bcp_control()
595 : */
596 : int
597 0 : bcp_getbatchsize(DBPROCESS * dbproc)
598 : {
599 0 : CHECK_CONN(-1);
600 0 : CHECK_PARAMETER(dbproc->hostfileinfo, SYBEBCPI, -1);
601 0 : return dbproc->hostfileinfo->batch;
602 : }
603 :
604 : /*
605 : * \ingroup dblib_bcp
606 : * \brief Get number of columns in the BCP data file
607 : *
608 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
609 : * \remarks This function is specific to FreeTDS.
610 : *
611 : * \return the value that was set by bcp_columns(). This represents the number
612 : * of columns of data in the saved data file. Usually the same as the number
613 : * of columns in the database table, but could be fewer if a Format File is
614 : * in use which only selects a subset of the table columns.
615 : *
616 : * \sa bcp_columns()
617 : */
618 : int
619 0 : bcp_gethostcolcount(DBPROCESS *dbproc)
620 : {
621 0 : CHECK_CONN(-1);
622 0 : CHECK_PARAMETER(dbproc->hostfileinfo, SYBEBCPI, -1);
623 0 : return dbproc->hostfileinfo->host_colcount;
624 : }
625 :
626 : /**
627 : * \ingroup dblib_bcp
628 : * \brief Set bulk copy options.
629 : *
630 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
631 : * \param option symbolic constant indicating the option to be set, one of:
632 : * - \b BCPLABELED Not implemented.
633 : * - \b BCPHINTS The hint to be passed when the bulk-copy begins.
634 : * \param value The string constant for \a option a/k/a the hint. One of:
635 : * - \b ORDER The data are ordered in accordance with the table's clustered index.
636 : * - \b ROWS_PER_BATCH The batch size
637 : * - \b KILOBYTES_PER_BATCH The approximate number of kilobytes to use for a batch size
638 : * - \b TABLOCK Lock the table
639 : * - \b CHECK_CONSTRAINTS Apply constraints
640 : * - \b FIRE_TRIGGERS Fire any INSERT triggers on the target table
641 : * \param valuelen The length of \a value. Ignored for fixed-length option types.
642 : *
643 : * \return SUCCEED or FAIL.
644 : * \sa bcp_control(),
645 : * bcp_exec(),
646 : * \todo Simplify.
647 : */
648 : RETCODE
649 2 : bcp_options(DBPROCESS * dbproc, int option, BYTE * value, int valuelen)
650 : {
651 : int i;
652 : static const char *const hints[] = {
653 : "ORDER", "ROWS_PER_BATCH", "KILOBYTES_PER_BATCH", "TABLOCK", "CHECK_CONSTRAINTS",
654 : "FIRE_TRIGGERS", "KEEP_NULLS", NULL
655 : };
656 :
657 2 : tdsdump_log(TDS_DBG_FUNC, "bcp_options(%p, %d, %p, %d)\n", dbproc, option, value, valuelen);
658 2 : CHECK_CONN(FAIL);
659 2 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
660 2 : CHECK_NULP(value, "bcp_options", 3, FAIL);
661 :
662 2 : switch (option) {
663 0 : case BCPLABELED:
664 0 : tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED bcp option: BCPLABELED\n");
665 : break;
666 2 : case BCPHINTS:
667 2 : if (!value || valuelen <= 0)
668 : break;
669 :
670 10 : for (i = 0; hints[i]; i++) { /* look up hint */
671 12 : if (strncasecmp((char *) value, hints[i], strlen(hints[i])) == 0) {
672 2 : if (!tds_dstr_copy(&dbproc->bcpinfo->hint, hints[i]))
673 : return FAIL;
674 2 : return SUCCEED;
675 : }
676 : }
677 0 : tdsdump_log(TDS_DBG_FUNC, "failed, no such hint\n");
678 : break;
679 0 : default:
680 0 : tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED bcp option: %u\n", option);
681 : break;
682 : }
683 0 : return FAIL;
684 : }
685 :
686 : /**
687 : * \ingroup dblib_bcp
688 : * \brief Override bcp_bind() by pointing to a different host variable.
689 : *
690 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
691 : * \param colptr The pointer, the address of your variable.
692 : * \param table_column The 1-based column ordinal in the table.
693 : * \remarks Use between calls to bcp_sendrow(). After calling bcp_colptr(),
694 : * subsequent calls to bcp_sendrow() will bind to the new address.
695 : * \return SUCCEED or FAIL.
696 : * \sa bcp_bind(), bcp_collen(), bcp_sendrow()
697 : */
698 : RETCODE
699 0 : bcp_colptr(DBPROCESS * dbproc, BYTE * colptr, int table_column)
700 : {
701 : TDSCOLUMN *curcol;
702 :
703 0 : tdsdump_log(TDS_DBG_FUNC, "bcp_colptr(%p, %p, %d)\n", dbproc, colptr, table_column);
704 0 : CHECK_CONN(FAIL);
705 0 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
706 0 : CHECK_PARAMETER(dbproc->bcpinfo->bindinfo, SYBEBCPI, FAIL);
707 : /* colptr can be NULL */
708 :
709 0 : if (dbproc->bcpinfo->direction != DB_IN) {
710 0 : dbperror(dbproc, SYBEBCPN, 0);
711 0 : return FAIL;
712 : }
713 0 : if (table_column <= 0 || table_column > dbproc->bcpinfo->bindinfo->num_cols) {
714 0 : dbperror(dbproc, SYBEBCPN, 0);
715 0 : return FAIL;
716 : }
717 :
718 0 : curcol = dbproc->bcpinfo->bindinfo->columns[table_column - 1];
719 0 : curcol->column_varaddr = (TDS_CHAR *)colptr;
720 :
721 0 : return SUCCEED;
722 : }
723 :
724 :
725 : /**
726 : * \ingroup dblib_bcp
727 : * \brief See if BCP_SETL() was used to set the LOGINREC for BCP work.
728 : *
729 : * \param login Address of the LOGINREC variable to be passed to dbopen().
730 : *
731 : * \return TRUE or FALSE.
732 : * \sa BCP_SETL(), bcp_init(), dblogin(), dbopen()
733 : */
734 : DBBOOL
735 10 : bcp_getl(LOGINREC * login)
736 : {
737 10 : TDSLOGIN *tdsl = login->tds_login;
738 :
739 10 : tdsdump_log(TDS_DBG_FUNC, "bcp_getl(%p)\n", login);
740 :
741 10 : return (tdsl->bulk_copy);
742 : }
743 :
744 : /**
745 : * Convert column for output (usually to a file)
746 : * Conversion is slightly different from input as:
747 : * - date is formatted differently;
748 : * - you have to set properly numeric while on input the column metadata are
749 : * used;
750 : * - we need to make sure buffer is always at least a minimum bytes.
751 : */
752 : static int
753 1648 : _bcp_convert_out(DBPROCESS * dbproc, TDSCOLUMN *curcol, BCP_HOSTCOLINFO *hostcol, TDS_UCHAR **p_data, const char *bcpdatefmt)
754 : {
755 : BYTE *src;
756 : int srclen;
757 : int buflen;
758 1648 : int srctype = tds_get_conversion_type(curcol->column_type, curcol->column_size);
759 :
760 1648 : src = curcol->column_data;
761 1648 : if (is_blob_col(curcol))
762 122 : src = (BYTE *) ((TDSBLOB *) src)->textvalue;
763 :
764 1648 : srclen = curcol->column_cur_size;
765 :
766 : /*
767 : * if we are converting datetime to string, need to override any
768 : * date time formats already established
769 : */
770 1648 : if (is_datetime_type(srctype) && is_ascii_type(hostcol->datatype)) {
771 : TDSDATEREC when;
772 :
773 : /* Some date/time types have variable precision (e.g. MS datetime2),
774 : * and set curcol->column_prec with that precision.
775 : * DATETIME is printed with precision 3 by MS BCP & ASE BCP however
776 : * curcol->column_prec is not set for that type.
777 : * (It might be better to set column_prec at load time for all
778 : * of the datetime types...)
779 : */
780 36 : int prec = curcol->column_prec ? curcol->column_prec : 3;
781 :
782 36 : tds_datecrack(srctype, src, &when);
783 36 : buflen = _bcp_strftime((char *) *p_data, 256, bcpdatefmt, &when, prec);
784 1612 : } else if (srclen == 0 && is_variable_type(curcol->column_type)
785 46 : && is_ascii_type(hostcol->datatype)) {
786 : /*
787 : * An empty string is denoted in the output file by a single ASCII NUL
788 : * byte that we request by specifying a destination length of -1. (Not
789 : * to be confused with a database NULL, which is denoted in the output
790 : * file with an empty string!)
791 : */
792 46 : (*p_data)[0] = 0;
793 46 : buflen = 1;
794 1566 : } else if (is_numeric_type(hostcol->datatype)) {
795 0 : TDS_NUMERIC *num = (TDS_NUMERIC *) (*p_data);
796 0 : if (is_numeric_type(srctype)) {
797 0 : TDS_NUMERIC *nsrc = (TDS_NUMERIC *) src;
798 0 : num->precision = nsrc->precision;
799 0 : num->scale = nsrc->scale;
800 : } else {
801 0 : num->precision = 18;
802 0 : num->scale = 0;
803 : }
804 0 : buflen = tds_convert(dbproc->tds_socket->conn->tds_ctx, srctype, src, srclen, hostcol->datatype, (CONV_RESULT *) num);
805 0 : if (buflen > 0)
806 0 : buflen = tds_numeric_bytes_per_prec[num->precision] + 2;
807 1566 : } else if (!is_variable_type(hostcol->datatype)) {
808 10 : buflen = tds_convert(dbproc->tds_socket->conn->tds_ctx, srctype, src, srclen, hostcol->datatype, (CONV_RESULT *) (*p_data));
809 : } else {
810 : CONV_RESULT cr;
811 :
812 : /*
813 : * For null columns, the above work to determine the output buffer size is moot,
814 : * because bcpcol->data_size is zero, so dbconvert() won't write anything,
815 : * and returns zero.
816 : */
817 1556 : buflen = tds_convert(dbproc->tds_socket->conn->tds_ctx, srctype, src, srclen, hostcol->datatype, (CONV_RESULT *) &cr);
818 1556 : if (buflen < 0)
819 0 : return buflen;
820 :
821 1556 : if (buflen >= 256) {
822 30 : free(*p_data);
823 30 : *p_data = (TDS_UCHAR *) cr.c;
824 : } else {
825 1526 : memcpy(*p_data, cr.c, buflen);
826 1526 : free(cr.c);
827 : }
828 :
829 : /*
830 : * Special case: When outputting database varchar data
831 : * (either varchar or nullable char) conversion may have
832 : * trimmed trailing blanks such that nothing is left.
833 : * In this case we need to put a single blank to the output file.
834 : */
835 1556 : if (is_char_type(curcol->column_type) && srclen > 0 && buflen == 0) {
836 0 : strcpy ((char *) (*p_data), " ");
837 0 : buflen = 1;
838 : }
839 : }
840 : return buflen;
841 : }
842 :
843 : static int
844 : bcp_cache_prefix_len(BCP_HOSTCOLINFO *hostcol, const TDSCOLUMN *curcol)
845 : {
846 : int plen;
847 :
848 0 : if (type_has_textptr(hostcol->datatype))
849 : plen = 4;
850 0 : else if (is_numeric_type(hostcol->datatype))
851 : plen = 1;
852 0 : else if (!is_fixed_type(hostcol->datatype))
853 : plen = 2;
854 0 : else if (curcol->column_nullable)
855 : plen = 1;
856 : else
857 0 : plen = 0;
858 : /* cache */
859 0 : return hostcol->prefix_len = plen;
860 : }
861 :
862 : static RETCODE
863 1862 : bcp_write_prefix(TDSFILEOUTSTREAM *hoststream, BCP_HOSTCOLINFO *hostcol, TDSCOLUMN *curcol, int buflen)
864 : {
865 : union {
866 : TDS_TINYINT ti;
867 : TDS_SMALLINT si;
868 : TDS_INT li;
869 : } u;
870 : int plen;
871 :
872 : /* compute prefix len if needed */
873 1862 : if ((plen = hostcol->prefix_len) == -1)
874 0 : plen = bcp_cache_prefix_len(hostcol, curcol);
875 :
876 : /* output prefix to file */
877 1862 : switch (plen) {
878 : default:
879 : return SUCCEED;
880 10 : case 1:
881 10 : u.ti = buflen;
882 10 : break;
883 0 : case 2:
884 0 : u.si = buflen;
885 0 : break;
886 10 : case 4:
887 10 : u.li = buflen;
888 10 : break;
889 : }
890 20 : return TDS_SUCCEED(tds_fileout_stream_put(hoststream, &u, plen)) ? SUCCEED : FAIL;
891 : }
892 :
893 : /**
894 : * \ingroup dblib_bcp_internal
895 : * \brief
896 : *
897 : *
898 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
899 : * \param rows_copied
900 : *
901 : * \return SUCCEED or FAIL.
902 : * \sa BCP_SETL(), bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_colfmt_ps(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_control(), bcp_done(), bcp_exec(), bcp_getl(), bcp_init(), bcp_moretext(), bcp_options(), bcp_readfmt(), bcp_sendrow()
903 : */
904 : static RETCODE
905 164 : _bcp_exec_out(DBPROCESS * dbproc, DBINT * rows_copied)
906 : {
907 : TDSFILEOUTSTREAM hoststream;
908 164 : FILE *hostfp = NULL;
909 164 : TDS_UCHAR *data = NULL;
910 : int i;
911 :
912 : TDSSOCKET *tds;
913 : TDSRESULTINFO *resinfo;
914 164 : TDSCOLUMN *curcol = NULL;
915 : BCP_HOSTCOLINFO *hostcol;
916 : int buflen;
917 :
918 : TDS_INT result_type;
919 :
920 : TDS_INT row_of_query;
921 : DBINT rows_written;
922 : const char *bcpdatefmt;
923 : TDSRET tdsret;
924 :
925 164 : tdsdump_log(TDS_DBG_FUNC, "_bcp_exec_out(%p, %p)\n", dbproc, rows_copied);
926 164 : assert(dbproc);
927 164 : assert(rows_copied);
928 :
929 164 : tds = dbproc->tds_socket;
930 164 : assert(tds);
931 :
932 : /* See if they want a BCP date format different from the default.
933 : * The ASE bcp client does use the locale for bcp out; but all bcp clients
934 : * appear to successfully read this format for input, regardless of locale.
935 : */
936 164 : bcpdatefmt = getenv("FREEBCP_DATEFMT");
937 164 : if (bcpdatefmt && !strcmp(bcpdatefmt, BCP_DEFAULT_DATEFMT))
938 0 : bcpdatefmt = NULL;
939 :
940 164 : if (dbproc->bcpinfo->direction == DB_QUERYOUT ) {
941 0 : if (TDS_FAILED(tds_submit_query(tds, tds_dstr_cstr(&dbproc->bcpinfo->tablename))))
942 : return FAIL;
943 : } else {
944 : /* TODO quote if needed */
945 328 : if (TDS_FAILED(tds_submit_queryf(tds, "select * from %s", tds_dstr_cstr(&dbproc->bcpinfo->tablename))))
946 : return FAIL;
947 : }
948 :
949 164 : tdsret = tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS);
950 164 : if (TDS_FAILED(tdsret))
951 : return FAIL;
952 :
953 164 : if (!tds->res_info) {
954 : /* TODO flush/cancel to keep consistent state */
955 : return FAIL;
956 : }
957 :
958 164 : resinfo = tds->res_info;
959 :
960 164 : row_of_query = 0;
961 164 : rows_written = 0;
962 :
963 : /* allocate at least 256 bytes */
964 : /* allocate data for buffer conversion */
965 164 : data = tds_new(TDS_UCHAR, 256);
966 164 : if (!data) {
967 0 : dbperror(dbproc, SYBEMEM, errno);
968 : goto Cleanup;
969 : }
970 :
971 : /*
972 : * TODO above we allocate many buffer just to convert and store
973 : * to file.. avoid all that passages...
974 : */
975 164 : if (!(hostfp = fopen(dbproc->hostfileinfo->hostfile, "w"))) {
976 0 : dbperror(dbproc, SYBEBCUO, errno);
977 0 : goto Cleanup;
978 : }
979 164 : tds_fileout_stream_init(&hoststream, hostfp, _IOFBF);
980 :
981 : /* fetch a row of data from the server */
982 :
983 704 : while (tds_process_tokens(tds, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE)
984 : == TDS_SUCCESS) {
985 :
986 540 : if (result_type != TDS_ROW_RESULT && result_type != TDS_COMPUTE_RESULT)
987 : break;
988 :
989 376 : row_of_query++;
990 :
991 : /* skip rows outside of the firstrow/lastrow range, if specified */
992 376 : if (dbproc->hostfileinfo->firstrow > row_of_query)
993 0 : continue;
994 376 : if (dbproc->hostfileinfo->lastrow > 0 && row_of_query > dbproc->hostfileinfo->lastrow) {
995 : /* TODO: If this is freebcp we could now just return success,
996 : * rather than waste time processing the rest of data.
997 : * In other cases we could perhaps send a cancel request.
998 : */
999 0 : continue;
1000 : }
1001 :
1002 : /* Go through the hostfile columns, finding those that relate to database columns. */
1003 1862 : for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
1004 1862 : hostcol = dbproc->hostfileinfo->host_columns[i];
1005 1862 : if (hostcol->tab_colnum < 1 || hostcol->tab_colnum > resinfo->num_cols)
1006 0 : continue;
1007 :
1008 1862 : curcol = resinfo->columns[hostcol->tab_colnum - 1];
1009 :
1010 1862 : if (curcol->column_cur_size < 0) {
1011 : buflen = 0;
1012 : } else {
1013 1648 : buflen = _bcp_convert_out(dbproc, curcol, hostcol, &data, bcpdatefmt);
1014 : }
1015 1648 : if (buflen < 0) {
1016 0 : _dblib_convert_err(dbproc, buflen);
1017 0 : goto Cleanup;
1018 : }
1019 :
1020 : /* The prefix */
1021 1862 : if (bcp_write_prefix(&hoststream, hostcol, curcol, buflen) != SUCCEED)
1022 : goto write_error;
1023 :
1024 : /* The data */
1025 1862 : if (hostcol->column_len != -1) {
1026 0 : buflen = TDS_MIN(buflen, hostcol->column_len);
1027 : }
1028 :
1029 1862 : if (buflen > 0) {
1030 1648 : if (!TDS_SUCCEED(tds_fileout_stream_put(&hoststream, data, buflen)))
1031 : goto write_error;
1032 : }
1033 :
1034 : /* The terminator */
1035 1862 : if (hostcol->terminator && hostcol->term_len > 0) {
1036 1842 : if (!TDS_SUCCEED(tds_fileout_stream_put(&hoststream, hostcol->terminator, hostcol->term_len)))
1037 : goto write_error;
1038 : }
1039 : }
1040 376 : rows_written++;
1041 : }
1042 :
1043 164 : if (TDS_FAILED(tds_fileout_stream_flush(&hoststream)) || fclose(hostfp) != 0) {
1044 0 : dbperror(dbproc, SYBEBCUC, errno);
1045 0 : goto Cleanup;
1046 : }
1047 164 : hostfp = NULL;
1048 :
1049 164 : if (row_of_query + 1 < dbproc->hostfileinfo->firstrow) {
1050 : /*
1051 : * The table which bulk-copy is attempting to
1052 : * copy to a host-file is shorter than the
1053 : * number of rows which bulk-copy was instructed to skip.
1054 : */
1055 : /* TODO reset TDSSOCKET state */
1056 0 : dbperror(dbproc, SYBETTS, 0);
1057 : goto Cleanup;
1058 : }
1059 :
1060 164 : *rows_copied = rows_written;
1061 164 : free(data);
1062 164 : return SUCCEED;
1063 :
1064 0 : write_error:
1065 0 : dbperror(dbproc, SYBEBCWE, errno);
1066 :
1067 0 : Cleanup:
1068 0 : if (hostfp)
1069 0 : fclose(hostfp);
1070 0 : free(data);
1071 0 : return FAIL;
1072 : }
1073 :
1074 : static STATUS
1075 164 : _bcp_check_eof(DBPROCESS * dbproc, FILE *file, int icol)
1076 : {
1077 164 : int errnum = errno;
1078 :
1079 164 : tdsdump_log(TDS_DBG_FUNC, "_bcp_check_eof(%p, %p, %d)\n", dbproc, file, icol);
1080 164 : assert(dbproc);
1081 164 : assert(file);
1082 :
1083 164 : if (feof(file)) {
1084 164 : if (icol == 0) {
1085 164 : tdsdump_log(TDS_DBG_FUNC, "Normal end-of-file reached while loading bcp data file.\n");
1086 : return NO_MORE_ROWS;
1087 : }
1088 0 : dbperror(dbproc, SYBEBEOF, errnum);
1089 0 : return FAIL;
1090 : }
1091 0 : dbperror(dbproc, SYBEBCRE, errnum);
1092 0 : return FAIL;
1093 : }
1094 :
1095 : /**
1096 : * Convert column for input to a table
1097 : */
1098 : static TDSRET
1099 4452 : _bcp_convert_in(DBPROCESS *dbproc, TDS_SERVER_TYPE srctype, const TDS_CHAR *src, TDS_UINT srclen,
1100 : TDS_SERVER_TYPE desttype, TDSCOLUMN *col)
1101 : {
1102 4452 : bool variable = true;
1103 : CONV_RESULT cr, *p_cr;
1104 : TDS_INT len;
1105 4452 : BCPCOLDATA *coldata = col->bcp_column_data;
1106 :
1107 4452 : coldata->is_null = false;
1108 :
1109 4452 : if (!is_variable_type(desttype)) {
1110 3134 : variable = false;
1111 3134 : p_cr = (CONV_RESULT *) coldata->data;
1112 : } else {
1113 : p_cr = &cr;
1114 : }
1115 :
1116 4452 : len = tds_convert(dbproc->tds_socket->conn->tds_ctx, srctype, src, srclen, desttype, p_cr);
1117 4452 : if (len < 0) {
1118 0 : _dblib_convert_err(dbproc, len);
1119 : return TDS_FAIL;
1120 : }
1121 :
1122 4452 : coldata->datalen = len;
1123 4452 : if (variable) {
1124 1318 : if (len > col->on_server.column_size) {
1125 0 : dbperror(dbproc, SYBECOFL, 0);
1126 : return TDS_FAIL;
1127 : }
1128 1318 : free(coldata->data);
1129 1318 : coldata->data = (TDS_UCHAR *) cr.c;
1130 : }
1131 : return TDS_SUCCESS;
1132 : }
1133 :
1134 : static void
1135 4452 : rtrim_bcpcol(TDSCOLUMN *bcpcol)
1136 : {
1137 : /* trim trailing blanks from character data */
1138 4452 : if (is_ascii_type(bcpcol->on_server.column_type)) {
1139 : /* A single NUL byte indicates an empty string. */
1140 1166 : if (bcpcol->bcp_column_data->datalen == 1
1141 206 : && bcpcol->bcp_column_data->data[0] == '\0') {
1142 0 : bcpcol->bcp_column_data->datalen = 0;
1143 0 : return;
1144 : }
1145 2332 : bcpcol->bcp_column_data->datalen = rtrim((char *) bcpcol->bcp_column_data->data,
1146 : bcpcol->bcp_column_data->datalen);
1147 1166 : return;
1148 : }
1149 :
1150 : /* unicode part */
1151 3286 : if (is_unicode_type(bcpcol->on_server.column_type)) {
1152 : uint16_t *data, space;
1153 :
1154 68 : if (!bcpcol->char_conv || bcpcol->char_conv->to.charset.min_bytes_per_char != 2)
1155 6 : return;
1156 :
1157 68 : data = (uint16_t *) bcpcol->bcp_column_data->data;
1158 : /* A single NUL byte indicates an empty string. */
1159 68 : if (bcpcol->bcp_column_data->datalen == 2 && data[0] == 0) {
1160 6 : bcpcol->bcp_column_data->datalen = 0;
1161 6 : return;
1162 : }
1163 62 : switch (bcpcol->char_conv->to.charset.canonic) {
1164 0 : case TDS_CHARSET_UTF_16BE:
1165 : case TDS_CHARSET_UCS_2BE:
1166 0 : TDS_PUT_A2BE(&space, 0x20);
1167 0 : break;
1168 62 : case TDS_CHARSET_UTF_16LE:
1169 : case TDS_CHARSET_UCS_2LE:
1170 62 : TDS_PUT_A2LE(&space, 0x20);
1171 62 : break;
1172 : default:
1173 : return;
1174 : }
1175 124 : bcpcol->bcp_column_data->datalen = rtrim_u16(data, bcpcol->bcp_column_data->datalen, space);
1176 : }
1177 : }
1178 :
1179 : /**
1180 : * \ingroup dblib_bcp_internal
1181 : * \brief
1182 : *
1183 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
1184 : * \param hostfile
1185 : * \param row_error set to true if an error is detected in the row
1186 : * \param skip skip the row
1187 : *
1188 : * \return MORE_ROWS, NO_MORE_ROWS, or FAIL.
1189 : * \sa BCP_SETL(), bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_colfmt_ps(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_control(), bcp_done(), bcp_exec(), bcp_getl(), bcp_init(), bcp_moretext(), bcp_options(), bcp_readfmt(), bcp_sendrow()
1190 : */
1191 : static STATUS
1192 540 : _bcp_read_hostfile(DBPROCESS * dbproc, FILE * hostfile, bool *row_error, bool skip)
1193 : {
1194 : int i;
1195 :
1196 540 : tdsdump_log(TDS_DBG_FUNC, "_bcp_read_hostfile(%p, %p, %p, %d)\n", dbproc, hostfile, row_error, skip);
1197 540 : assert(dbproc);
1198 540 : assert(hostfile);
1199 540 : assert(row_error);
1200 :
1201 : /* for each host file column defined by calls to bcp_colfmt */
1202 :
1203 4264 : for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
1204 2026 : TDSCOLUMN *bcpcol = NULL;
1205 : BCP_HOSTCOLINFO *hostcol;
1206 : TDS_CHAR *coldata;
1207 2026 : int collen = 0;
1208 2026 : bool data_is_null = false;
1209 : offset_type col_start;
1210 :
1211 2026 : tdsdump_log(TDS_DBG_FUNC, "parsing host column %d\n", i + 1);
1212 2026 : hostcol = dbproc->hostfileinfo->host_columns[i];
1213 :
1214 2026 : hostcol->column_error = 0;
1215 :
1216 : /*
1217 : * If this host file column contains table data,
1218 : * find the right element in the table/column list.
1219 : */
1220 2026 : if (hostcol->tab_colnum > 0) {
1221 2026 : if (hostcol->tab_colnum > dbproc->bcpinfo->bindinfo->num_cols) {
1222 0 : tdsdump_log(TDS_DBG_FUNC, "error: file wider than table: %d/%d\n",
1223 : i+1, dbproc->bcpinfo->bindinfo->num_cols);
1224 0 : dbperror(dbproc, SYBEBEOF, 0);
1225 0 : return FAIL;
1226 : }
1227 2026 : tdsdump_log(TDS_DBG_FUNC, "host column %d uses bcpcol %d (%p)\n",
1228 : i+1, hostcol->tab_colnum, bcpcol);
1229 2026 : bcpcol = dbproc->bcpinfo->bindinfo->columns[hostcol->tab_colnum - 1];
1230 2026 : assert(bcpcol != NULL);
1231 : }
1232 :
1233 : /* detect prefix len */
1234 2026 : if (bcpcol && hostcol->prefix_len == -1)
1235 0 : bcp_cache_prefix_len(hostcol, bcpcol);
1236 :
1237 : /* a prefix length, if extant, specifies how many bytes to read */
1238 2026 : if (hostcol->prefix_len > 0) {
1239 : union {
1240 : TDS_TINYINT ti;
1241 : TDS_SMALLINT si;
1242 : TDS_INT li;
1243 : } u;
1244 :
1245 30 : switch (hostcol->prefix_len) {
1246 20 : case 1:
1247 20 : if (fread(&u.ti, 1, 1, hostfile) != 1)
1248 20 : return _bcp_check_eof(dbproc, hostfile, i);
1249 10 : collen = u.ti ? u.ti : -1;
1250 10 : break;
1251 0 : case 2:
1252 0 : if (fread(&u.si, 2, 1, hostfile) != 1)
1253 0 : return _bcp_check_eof(dbproc, hostfile, i);
1254 0 : collen = u.si;
1255 0 : break;
1256 10 : case 4:
1257 10 : if (fread(&u.li, 4, 1, hostfile) != 1)
1258 0 : return _bcp_check_eof(dbproc, hostfile, i);
1259 10 : collen = u.li;
1260 10 : break;
1261 0 : default:
1262 : /* FIXME return error, remember that prefix_len can be 3 */
1263 0 : assert(hostcol->prefix_len <= 4);
1264 : break;
1265 : }
1266 :
1267 : /* TODO test all NULL types */
1268 : /* TODO for < -1 error */
1269 20 : if (collen <= -1) {
1270 : data_is_null = true;
1271 : collen = 0;
1272 : }
1273 : }
1274 :
1275 : /* if (Max) column length specified take that into consideration. (Meaning what, exactly?) */
1276 :
1277 2016 : if (!data_is_null && hostcol->column_len >= 0) {
1278 0 : if (hostcol->column_len == 0)
1279 : data_is_null = true;
1280 0 : else if (collen)
1281 0 : collen = TDS_MIN(hostcol->column_len, collen);
1282 : else
1283 : collen = hostcol->column_len;
1284 : }
1285 :
1286 2016 : tdsdump_log(TDS_DBG_FUNC, "prefix_len = %d collen = %d \n", hostcol->prefix_len, collen);
1287 :
1288 : /* Fixed Length data - this overrides anything else specified */
1289 :
1290 2016 : if (is_fixed_type(hostcol->datatype))
1291 10 : collen = tds_get_size_by_type(hostcol->datatype);
1292 :
1293 2016 : col_start = ftello(hostfile);
1294 :
1295 : /*
1296 : * The data file either contains prefixes stating the length, or is delimited.
1297 : * If delimited, we "measure" the field by looking for the terminator, then read it,
1298 : * and set collen to the field's post-iconv size.
1299 : */
1300 2016 : if (hostcol->term_len > 0) { /* delimited data file */
1301 : size_t col_bytes;
1302 : TDSRET conv_res;
1303 :
1304 : /*
1305 : * Read and convert the data
1306 : */
1307 1996 : coldata = NULL;
1308 3992 : conv_res = tds_bcp_fread(dbproc->tds_socket, bcpcol ? bcpcol->char_conv : NULL, hostfile,
1309 1996 : (const char *) hostcol->terminator, hostcol->term_len, &coldata, &col_bytes);
1310 :
1311 1996 : if (TDS_FAILED(conv_res)) {
1312 0 : tdsdump_log(TDS_DBG_FUNC, "col %d: error converting %ld bytes!\n",
1313 : (i+1), (long) collen);
1314 0 : *row_error = true;
1315 0 : free(coldata);
1316 : /* This case can include columns missing a terminator, and
1317 : * wrong number of columns in the row, as well as the data not
1318 : * being of valid form for the column type. */
1319 0 : dbperror(dbproc, SYBECSYN, 0);
1320 0 : return FAIL;
1321 : }
1322 :
1323 1996 : if (conv_res == TDS_NO_MORE_RESULTS) {
1324 154 : free(coldata);
1325 154 : return _bcp_check_eof(dbproc, hostfile, i);
1326 : }
1327 :
1328 1842 : if (col_bytes > 0x7fffffffl) {
1329 0 : free(coldata);
1330 0 : *row_error = true;
1331 0 : tdsdump_log(TDS_DBG_FUNC, "data from file is too large!\n");
1332 0 : dbperror(dbproc, SYBEBCOR, 0);
1333 0 : return FAIL;
1334 : }
1335 :
1336 1842 : collen = (int)col_bytes;
1337 1842 : if (collen == 0)
1338 220 : data_is_null = true;
1339 :
1340 : /* To support empty strings and keep compatibility with older files empty strings
1341 : * are encoded as a single NUL byte. */
1342 1842 : if (collen == 1 && coldata[0] == '\0')
1343 40 : collen = 0;
1344 :
1345 : /*
1346 : * TODO:
1347 : * Dates are a problem. In theory, we should be able to read non-English dates, which
1348 : * would contain non-ASCII characters. One might suppose we should convert date
1349 : * strings to ISO-8859-1 (or another canonical form) here, because tds_convert() can't be
1350 : * expected to deal with encodings. But instead date strings are read verbatim and
1351 : * passed to tds_convert() without even waving to iconv(). For English dates, this works,
1352 : * because English dates expressed as UTF-8 strings are indistinguishable from the ASCII.
1353 : */
1354 : } else { /* unterminated field */
1355 :
1356 20 : coldata = tds_new(TDS_CHAR, 1 + collen);
1357 20 : if (coldata == NULL) {
1358 0 : *row_error = true;
1359 0 : dbperror(dbproc, SYBEMEM, errno);
1360 0 : return FAIL;
1361 : }
1362 :
1363 20 : coldata[collen] = 0;
1364 20 : if (collen) {
1365 : /*
1366 : * Read and convert the data
1367 : * TODO: Call tds_bcp_fread() instead of fread(3).
1368 : * The columns should each have their iconv cd set, and noncharacter data
1369 : * should have -1 as the iconv cd, causing tds_bcp_fread() to not attempt
1370 : * any conversion. We do not need a datatype switch here to decide what to do.
1371 : * As of 0.62, this *should* actually work. All that remains is to change the
1372 : * call and test it.
1373 : */
1374 20 : tdsdump_log(TDS_DBG_FUNC, "Reading %d bytes from hostfile.\n", collen);
1375 20 : if (fread(coldata, collen, 1, hostfile) != 1) {
1376 0 : free(coldata);
1377 0 : return _bcp_check_eof(dbproc, hostfile, i);
1378 : }
1379 : }
1380 : }
1381 :
1382 : /*
1383 : * At this point, however the field was read, however big it was, its address is coldata and its size is collen.
1384 : */
1385 1862 : tdsdump_log(TDS_DBG_FUNC, "Data read from hostfile: collen is now %d, data_is_null is %d\n", collen, data_is_null);
1386 1862 : if (!skip && bcpcol) {
1387 1862 : if (data_is_null) {
1388 220 : bcpcol->bcp_column_data->is_null = true;
1389 220 : bcpcol->bcp_column_data->datalen = 0;
1390 : } else {
1391 : TDSRET rc;
1392 : TDS_SERVER_TYPE desttype;
1393 :
1394 1642 : desttype = tds_get_conversion_type(bcpcol->column_type, bcpcol->column_size);
1395 :
1396 1642 : rc = _bcp_convert_in(dbproc, hostcol->datatype, (const TDS_CHAR*) coldata, collen,
1397 : desttype, bcpcol);
1398 1642 : if (TDS_FAILED(rc)) {
1399 0 : hostcol->column_error = HOST_COL_CONV_ERROR;
1400 0 : *row_error = true;
1401 0 : tdsdump_log(TDS_DBG_FUNC,
1402 : "_bcp_read_hostfile failed to convert %d bytes at offset 0x%" PRIx64 " in the data file.\n",
1403 : collen, (TDS_INT8) col_start);
1404 : }
1405 :
1406 1642 : rtrim_bcpcol(bcpcol);
1407 : }
1408 : #if USING_SYBEBCNN
1409 : if (!hostcol->column_error) {
1410 : if (bcpcol->bcp_column_data->datalen <= 0) { /* Are we trying to insert a NULL ? */
1411 : if (!bcpcol->column_nullable) {
1412 : /* too bad if the column is not nullable */
1413 : hostcol->column_error = HOST_COL_NULL_ERROR;
1414 : *row_error = true;
1415 : dbperror(dbproc, SYBEBCNN, 0);
1416 : }
1417 : }
1418 : }
1419 : #endif
1420 : }
1421 1862 : free(coldata);
1422 : }
1423 : return MORE_ROWS;
1424 : }
1425 :
1426 : /**
1427 : * \ingroup dblib_bcp
1428 : * \brief Write data in host variables to the table.
1429 : *
1430 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
1431 : *
1432 : * \remarks Call bcp_bind() first to describe the variables to be used.
1433 : * Use bcp_batch() to commit sets of rows.
1434 : * After sending the last row call bcp_done().
1435 : * \return SUCCEED or FAIL.
1436 : * \sa bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_collen(), bcp_colptr(), bcp_columns(),
1437 : * bcp_control(), bcp_done(), bcp_exec(), bcp_init(), bcp_moretext(), bcp_options()
1438 : */
1439 : RETCODE
1440 180 : bcp_sendrow(DBPROCESS * dbproc)
1441 : {
1442 : TDSSOCKET *tds;
1443 :
1444 180 : tdsdump_log(TDS_DBG_FUNC, "bcp_sendrow(%p)\n", dbproc);
1445 180 : CHECK_CONN(FAIL);
1446 180 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
1447 :
1448 180 : tds = dbproc->tds_socket;
1449 :
1450 180 : if (dbproc->bcpinfo->direction != DB_IN) {
1451 0 : dbperror(dbproc, SYBEBCPN, 0);
1452 0 : return FAIL;
1453 : }
1454 :
1455 180 : if (dbproc->hostfileinfo != NULL) {
1456 0 : dbperror(dbproc, SYBEBCPB, 0);
1457 0 : return FAIL;
1458 : }
1459 :
1460 : /*
1461 : * The first time sendrow is called after bcp_init,
1462 : * there is a certain amount of initialisation to be done.
1463 : */
1464 180 : if (!dbproc->bcpinfo->xfer_init) {
1465 :
1466 : /* The start_copy function retrieves details of the table's columns */
1467 28 : if (TDS_FAILED(tds_bcp_start_copy_in(tds, dbproc->bcpinfo))) {
1468 0 : dbperror(dbproc, SYBEBULKINSERT, 0);
1469 0 : return FAIL;
1470 : }
1471 :
1472 28 : dbproc->bcpinfo->xfer_init = true;
1473 :
1474 : }
1475 :
1476 180 : dbproc->bcpinfo->parent = dbproc;
1477 180 : return TDS_FAILED(tds_bcp_send_record(dbproc->tds_socket, dbproc->bcpinfo,
1478 180 : _bcp_get_col_data, _bcp_null_error, 0)) ? FAIL : SUCCEED;
1479 : }
1480 :
1481 :
1482 : /**
1483 : * \ingroup dblib_bcp_internal
1484 : * \brief
1485 : *
1486 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
1487 : * \param rows_copied
1488 : *
1489 : * \return SUCCEED or FAIL.
1490 : * \sa BCP_SETL(), bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_colfmt_ps(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_control(), bcp_done(), bcp_exec(), bcp_getl(), bcp_init(), bcp_moretext(), bcp_options(), bcp_readfmt(), bcp_sendrow()
1491 : */
1492 : static RETCODE
1493 164 : _bcp_exec_in(DBPROCESS * dbproc, DBINT * rows_copied)
1494 : {
1495 164 : FILE *hostfile, *errfile = NULL;
1496 164 : TDSSOCKET *tds = dbproc->tds_socket;
1497 : BCP_HOSTCOLINFO *hostcol;
1498 : STATUS ret;
1499 :
1500 : int i, rows_written_so_far;
1501 : TDS_INT row_of_hostfile;
1502 : int row_error_count;
1503 : bool row_error;
1504 : offset_type row_start, row_end;
1505 : offset_type error_row_size;
1506 164 : const size_t chunk_size = 0x20000u;
1507 :
1508 164 : tdsdump_log(TDS_DBG_FUNC, "_bcp_exec_in(%p, %p)\n", dbproc, rows_copied);
1509 : assert(dbproc);
1510 164 : assert(rows_copied);
1511 :
1512 164 : *rows_copied = 0;
1513 :
1514 164 : if (!(hostfile = fopen(dbproc->hostfileinfo->hostfile, "r"))) {
1515 0 : dbperror(dbproc, SYBEBCUO, 0);
1516 0 : return FAIL;
1517 : }
1518 :
1519 164 : if (TDS_FAILED(tds_bcp_start_copy_in(tds, dbproc->bcpinfo))) {
1520 0 : fclose(hostfile);
1521 0 : return FAIL;
1522 : }
1523 :
1524 164 : row_of_hostfile = 0;
1525 164 : rows_written_so_far = 0;
1526 :
1527 164 : row_error_count = 0;
1528 164 : dbproc->bcpinfo->parent = dbproc;
1529 :
1530 : for (;;) {
1531 : bool skip;
1532 :
1533 540 : row_start = ftello(hostfile);
1534 540 : row_error = false;
1535 :
1536 540 : row_of_hostfile++;
1537 :
1538 540 : if (dbproc->hostfileinfo->lastrow > 0 && row_of_hostfile > dbproc->hostfileinfo->lastrow)
1539 : break;
1540 :
1541 540 : skip = dbproc->hostfileinfo->firstrow > row_of_hostfile;
1542 540 : ret = _bcp_read_hostfile(dbproc, hostfile, &row_error, skip);
1543 540 : if (ret != MORE_ROWS)
1544 : break;
1545 :
1546 376 : if (row_error) {
1547 : int count;
1548 :
1549 0 : if (errfile == NULL && dbproc->hostfileinfo->errorfile) {
1550 0 : if (!(errfile = fopen(dbproc->hostfileinfo->errorfile, "w"))) {
1551 0 : fclose(hostfile);
1552 0 : dbperror(dbproc, SYBEBUOE, 0);
1553 0 : return FAIL;
1554 : }
1555 : }
1556 :
1557 0 : if (errfile != NULL) {
1558 : char *row_in_error = NULL;
1559 :
1560 0 : for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
1561 0 : hostcol = dbproc->hostfileinfo->host_columns[i];
1562 0 : if (hostcol->column_error == HOST_COL_CONV_ERROR) {
1563 0 : count = fprintf(errfile,
1564 : "#@ data conversion error on host data file Row %d Column %d\n",
1565 : (int) row_of_hostfile, i + 1);
1566 0 : if (count < 0) {
1567 0 : dbperror(dbproc, SYBEBWEF, errno);
1568 : }
1569 0 : } else if (hostcol->column_error == HOST_COL_NULL_ERROR) {
1570 0 : count = fprintf(errfile, "#@ Attempt to bulk-copy a NULL value into Server column"
1571 : " which does not accept NULL values. Row %d, Column %d\n",
1572 : row_of_hostfile, i + 1);
1573 0 : if( count < 0 ) {
1574 0 : dbperror(dbproc, SYBEBWEF, errno);
1575 : }
1576 :
1577 : }
1578 : }
1579 :
1580 0 : row_end = ftello(hostfile);
1581 :
1582 : /* error data can be very long so split in chunks */
1583 0 : error_row_size = row_end - row_start;
1584 0 : fseeko(hostfile, row_start, SEEK_SET);
1585 :
1586 0 : while (error_row_size > 0) {
1587 0 : size_t chunk = TDS_MIN((size_t) error_row_size, chunk_size);
1588 : size_t written;
1589 :
1590 0 : if (!row_in_error) {
1591 0 : if ((row_in_error = tds_new(char, chunk)) == NULL) {
1592 0 : dbperror(dbproc, SYBEMEM, errno);
1593 : }
1594 : }
1595 :
1596 0 : if (fread(row_in_error, 1, chunk, hostfile) != chunk)
1597 0 : tdsdump_log(TDS_DBG_ERROR, "BILL fread failed after fseek\n");
1598 :
1599 0 : written = fwrite(row_in_error, 1, chunk, errfile);
1600 0 : if (written < chunk)
1601 0 : dbperror(dbproc, SYBEBWEF, errno);
1602 :
1603 0 : error_row_size -= chunk;
1604 : }
1605 0 : free(row_in_error);
1606 :
1607 0 : fseeko(hostfile, row_end, SEEK_SET);
1608 0 : count = fprintf(errfile, "\n");
1609 0 : if( count < 0 ) {
1610 0 : dbperror(dbproc, SYBEBWEF, errno);
1611 : }
1612 : }
1613 0 : row_error_count++;
1614 0 : if (row_error_count >= dbproc->hostfileinfo->maxerrs)
1615 : break;
1616 0 : continue;
1617 : }
1618 :
1619 376 : if (skip)
1620 0 : continue;
1621 :
1622 376 : if (TDS_SUCCEED(tds_bcp_send_record(dbproc->tds_socket, dbproc->bcpinfo,
1623 : _bcp_no_get_col_data, _bcp_null_error, 0))) {
1624 :
1625 376 : rows_written_so_far++;
1626 :
1627 376 : if (dbproc->hostfileinfo->batch > 0 && rows_written_so_far == dbproc->hostfileinfo->batch) {
1628 0 : if (TDS_FAILED(tds_bcp_done(tds, &rows_written_so_far))) {
1629 0 : if (errfile)
1630 0 : fclose(errfile);
1631 0 : fclose(hostfile);
1632 0 : return FAIL;
1633 : }
1634 :
1635 0 : *rows_copied += rows_written_so_far;
1636 0 : rows_written_so_far = 0;
1637 :
1638 0 : dbperror(dbproc, SYBEBBCI, 0); /* batch copied to server */
1639 :
1640 0 : tds_bcp_start(tds, dbproc->bcpinfo);
1641 : }
1642 : }
1643 : }
1644 :
1645 164 : if (row_error_count == 0 && row_of_hostfile < dbproc->hostfileinfo->firstrow) {
1646 : /* "The BCP hostfile '%1!' contains only %2! rows. */
1647 0 : dbperror(dbproc, SYBEBCSA, 0, dbproc->hostfileinfo->hostfile, row_of_hostfile);
1648 : }
1649 :
1650 164 : if (errfile && 0 != fclose(errfile) ) {
1651 0 : dbperror(dbproc, SYBEBUCE, 0);
1652 : }
1653 :
1654 164 : if (fclose(hostfile) != 0) {
1655 0 : dbperror(dbproc, SYBEBCUC, 0);
1656 0 : ret = FAIL;
1657 : }
1658 :
1659 164 : tds_bcp_done(tds, &rows_written_so_far);
1660 164 : *rows_copied += rows_written_so_far;
1661 :
1662 164 : return ret == NO_MORE_ROWS? SUCCEED : FAIL; /* (ret is returned from _bcp_read_hostfile) */
1663 : }
1664 :
1665 : /**
1666 : * \ingroup dblib_bcp
1667 : * \brief Write a datafile to a table.
1668 : *
1669 : *
1670 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
1671 : * \param rows_copied bcp_exec will write the count of rows successfully written to this address.
1672 : * If \a rows_copied is NULL, it will be ignored by db-lib.
1673 : *
1674 : * \return SUCCEED or FAIL.
1675 : * \sa bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_collen(), bcp_colptr(), bcp_columns(),
1676 : * bcp_control(), bcp_done(), bcp_init(), bcp_sendrow()
1677 : */
1678 : RETCODE
1679 328 : bcp_exec(DBPROCESS * dbproc, DBINT *rows_copied)
1680 : {
1681 : DBINT dummy_copied;
1682 328 : RETCODE ret = FAIL;
1683 :
1684 328 : tdsdump_log(TDS_DBG_FUNC, "bcp_exec(%p, %p)\n", dbproc, rows_copied);
1685 328 : CHECK_CONN(FAIL);
1686 328 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
1687 328 : CHECK_PARAMETER(dbproc->hostfileinfo, SYBEBCVH, FAIL);
1688 :
1689 328 : if (rows_copied == NULL) /* NULL means we should ignore it */
1690 0 : rows_copied = &dummy_copied;
1691 :
1692 328 : if (dbproc->bcpinfo->direction == DB_OUT || dbproc->bcpinfo->direction == DB_QUERYOUT) {
1693 164 : ret = _bcp_exec_out(dbproc, rows_copied);
1694 164 : } else if (dbproc->bcpinfo->direction == DB_IN) {
1695 164 : ret = _bcp_exec_in(dbproc, rows_copied);
1696 : }
1697 328 : _bcp_free_storage(dbproc);
1698 :
1699 328 : return ret;
1700 : }
1701 :
1702 : /**
1703 : * \ingroup dblib_bcp_internal
1704 : * \brief
1705 : *
1706 : * \param buffer
1707 : * \param size
1708 : * \param f
1709 : *
1710 : * \return SUCCEED or FAIL.
1711 : * \sa BCP_SETL(), bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_colfmt_ps(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_control(), bcp_done(), bcp_exec(), bcp_getl(), bcp_init(), bcp_moretext(), bcp_options(), bcp_readfmt(), bcp_sendrow()
1712 : */
1713 : static char *
1714 0 : _bcp_fgets(char *buffer, int size, FILE *f)
1715 : {
1716 0 : char *p = fgets(buffer, size, f);
1717 0 : if (p == NULL)
1718 : return p;
1719 :
1720 : /* discard newline */
1721 0 : p = strchr(buffer, 0) - 1;
1722 0 : if (p >= buffer && *p == '\n')
1723 0 : *p = 0;
1724 : return buffer;
1725 : }
1726 :
1727 : /**
1728 : * \ingroup dblib_bcp
1729 : * \brief Read a format definition file.
1730 : *
1731 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
1732 : * \param filename Name that will be passed to fopen(3).
1733 : *
1734 : * \remarks Reads a format file and calls bcp_columns() and bcp_colfmt() as needed.
1735 : *
1736 : * \return SUCCEED or FAIL.
1737 : * \sa bcp_colfmt(), bcp_colfmt_ps(), bcp_columns(), bcp_writefmt()
1738 : */
1739 : RETCODE
1740 0 : bcp_readfmt(DBPROCESS * dbproc, const char filename[])
1741 : {
1742 : BCP_HOSTCOLINFO hostcol[1];
1743 : FILE *ffile;
1744 : char buffer[1024];
1745 0 : float lf_version = 0.0;
1746 0 : int li_numcols = 0;
1747 0 : int colinfo_count = 0;
1748 :
1749 0 : tdsdump_log(TDS_DBG_FUNC, "bcp_readfmt(%p, %s)\n", dbproc, filename? filename:"NULL");
1750 0 : CHECK_CONN(FAIL);
1751 0 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
1752 0 : CHECK_NULP(filename, "bcp_readfmt", 2, FAIL);
1753 :
1754 0 : memset(hostcol, 0, sizeof(hostcol));
1755 :
1756 0 : if ((ffile = fopen(filename, "r")) == NULL) {
1757 0 : dbperror(dbproc, SYBEBUOF, 0);
1758 0 : goto Cleanup;
1759 : }
1760 :
1761 0 : if ((_bcp_fgets(buffer, sizeof(buffer), ffile)) != NULL) {
1762 0 : lf_version = (float)atof(buffer);
1763 0 : } else if (ferror(ffile)) {
1764 0 : dbperror(dbproc, SYBEBRFF, errno);
1765 0 : goto Cleanup;
1766 : }
1767 :
1768 0 : if ((_bcp_fgets(buffer, sizeof(buffer), ffile)) != NULL) {
1769 0 : li_numcols = atoi(buffer);
1770 0 : } else if (ferror(ffile)) {
1771 0 : dbperror(dbproc, SYBEBRFF, errno);
1772 0 : goto Cleanup;
1773 : }
1774 :
1775 0 : if (li_numcols <= 0)
1776 : goto Cleanup;
1777 :
1778 0 : if (bcp_columns(dbproc, li_numcols) == FAIL)
1779 : goto Cleanup;
1780 :
1781 : do {
1782 0 : memset(hostcol, 0, sizeof(hostcol));
1783 :
1784 0 : if (_bcp_fgets(buffer, sizeof(buffer), ffile) == NULL)
1785 : goto Cleanup;
1786 :
1787 0 : if (!_bcp_readfmt_colinfo(dbproc, buffer, hostcol))
1788 : goto Cleanup;
1789 :
1790 0 : if (bcp_colfmt(dbproc, hostcol->host_column, hostcol->datatype,
1791 : hostcol->prefix_len, hostcol->column_len,
1792 0 : hostcol->terminator, hostcol->term_len, hostcol->tab_colnum) == FAIL) {
1793 : goto Cleanup;
1794 : }
1795 :
1796 0 : TDS_ZERO_FREE(hostcol->terminator);
1797 0 : } while (++colinfo_count < li_numcols);
1798 :
1799 0 : if (ferror(ffile)) {
1800 0 : dbperror(dbproc, SYBEBRFF, errno);
1801 0 : goto Cleanup;
1802 : }
1803 :
1804 0 : if (fclose(ffile) != 0) {
1805 0 : dbperror(dbproc, SYBEBUCF, 0);
1806 : /* even if failure is returned ffile is no more valid */
1807 0 : ffile = NULL;
1808 0 : goto Cleanup;
1809 : }
1810 0 : ffile = NULL;
1811 :
1812 0 : if (colinfo_count != li_numcols)
1813 : goto Cleanup;
1814 :
1815 : return SUCCEED;
1816 :
1817 0 : Cleanup:
1818 0 : TDS_ZERO_FREE(hostcol->terminator);
1819 0 : _bcp_free_columns(dbproc);
1820 0 : if (ffile)
1821 0 : fclose(ffile);
1822 : return FAIL;
1823 : }
1824 :
1825 : /**
1826 : * \ingroup dblib_bcp_internal
1827 : * \brief
1828 : *
1829 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
1830 : * \param buf
1831 : * \param ci
1832 : *
1833 : * \return SUCCEED or FAIL.
1834 : * \sa BCP_SETL(), bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_colfmt_ps(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_control(), bcp_done(), bcp_exec(), bcp_getl(), bcp_init(), bcp_moretext(), bcp_options(), bcp_readfmt(), bcp_sendrow()
1835 : */
1836 : static int
1837 0 : _bcp_readfmt_colinfo(DBPROCESS * dbproc, char *buf, BCP_HOSTCOLINFO * ci)
1838 : {
1839 : char *tok;
1840 : int whichcol;
1841 : char term[30];
1842 : int i;
1843 : char *lasts;
1844 :
1845 : enum nextcol
1846 : {
1847 : HOST_COLUMN,
1848 : DATATYPE,
1849 : PREFIX_LEN,
1850 : COLUMN_LEN,
1851 : TERMINATOR,
1852 : TAB_COLNUM,
1853 : NO_MORE_COLS
1854 : };
1855 :
1856 0 : assert(dbproc);
1857 0 : assert(buf);
1858 0 : assert(ci);
1859 0 : tdsdump_log(TDS_DBG_FUNC, "_bcp_readfmt_colinfo(%p, %s, %p)\n", dbproc, buf, ci);
1860 :
1861 0 : tok = strtok_r(buf, " \t", &lasts);
1862 0 : whichcol = HOST_COLUMN;
1863 :
1864 : /* TODO use a better way to get an int atoi is very error prone */
1865 0 : while (tok != NULL && whichcol != NO_MORE_COLS) {
1866 0 : switch (whichcol) {
1867 :
1868 0 : case HOST_COLUMN:
1869 0 : ci->host_column = atoi(tok);
1870 :
1871 0 : if (ci->host_column < 1) {
1872 0 : dbperror(dbproc, SYBEBIHC, 0);
1873 0 : return (FALSE);
1874 : }
1875 :
1876 : whichcol = DATATYPE;
1877 : break;
1878 :
1879 0 : case DATATYPE:
1880 0 : if (strcmp(tok, "SYBCHAR") == 0)
1881 0 : ci->datatype = SYBCHAR;
1882 0 : else if (strcmp(tok, "SYBTEXT") == 0)
1883 0 : ci->datatype = SYBTEXT;
1884 0 : else if (strcmp(tok, "SYBBINARY") == 0)
1885 0 : ci->datatype = SYBBINARY;
1886 0 : else if (strcmp(tok, "SYBIMAGE") == 0)
1887 0 : ci->datatype = SYBIMAGE;
1888 0 : else if (strcmp(tok, "SYBINT1") == 0)
1889 0 : ci->datatype = SYBINT1;
1890 0 : else if (strcmp(tok, "SYBINT2") == 0)
1891 0 : ci->datatype = SYBINT2;
1892 0 : else if (strcmp(tok, "SYBINT4") == 0)
1893 0 : ci->datatype = SYBINT4;
1894 0 : else if (strcmp(tok, "SYBINT8") == 0)
1895 0 : ci->datatype = SYBINT8;
1896 0 : else if (strcmp(tok, "SYBFLT8") == 0)
1897 0 : ci->datatype = SYBFLT8;
1898 0 : else if (strcmp(tok, "SYBREAL") == 0)
1899 0 : ci->datatype = SYBREAL;
1900 0 : else if (strcmp(tok, "SYBBIT") == 0)
1901 0 : ci->datatype = SYBBIT;
1902 0 : else if (strcmp(tok, "SYBNUMERIC") == 0)
1903 0 : ci->datatype = SYBNUMERIC;
1904 0 : else if (strcmp(tok, "SYBDECIMAL") == 0)
1905 0 : ci->datatype = SYBDECIMAL;
1906 0 : else if (strcmp(tok, "SYBMONEY") == 0)
1907 0 : ci->datatype = SYBMONEY;
1908 0 : else if (strcmp(tok, "SYBMONEY4") == 0)
1909 0 : ci->datatype = SYBMONEY4;
1910 0 : else if (strcmp(tok, "SYBDATETIME") == 0)
1911 0 : ci->datatype = SYBDATETIME;
1912 0 : else if (strcmp(tok, "SYBDATETIME4") == 0)
1913 0 : ci->datatype = SYBDATETIME4;
1914 : /* TODO SQL* for MS
1915 : SQLNCHAR SQLBIGINT SQLTINYINT SQLSMALLINT
1916 : SQLUNIQUEID SQLVARIANT SQLUDT */
1917 : else {
1918 0 : dbperror(dbproc, SYBEBUDF, 0);
1919 0 : return (FALSE);
1920 : }
1921 :
1922 : whichcol = PREFIX_LEN;
1923 : break;
1924 :
1925 0 : case PREFIX_LEN:
1926 0 : ci->prefix_len = atoi(tok);
1927 0 : whichcol = COLUMN_LEN;
1928 0 : break;
1929 0 : case COLUMN_LEN:
1930 0 : ci->column_len = atoi(tok);
1931 0 : whichcol = TERMINATOR;
1932 0 : break;
1933 0 : case TERMINATOR:
1934 :
1935 0 : if (*tok++ != '\"')
1936 : return (FALSE);
1937 :
1938 0 : for (i = 0; *tok != '\"' && i < sizeof(term); i++) {
1939 0 : if (*tok == '\\') {
1940 0 : tok++;
1941 0 : switch (*tok) {
1942 0 : case 't':
1943 0 : term[i] = '\t';
1944 0 : break;
1945 0 : case 'n':
1946 0 : term[i] = '\n';
1947 0 : break;
1948 0 : case 'r':
1949 0 : term[i] = '\r';
1950 0 : break;
1951 0 : case '\\':
1952 0 : term[i] = '\\';
1953 0 : break;
1954 0 : case '0':
1955 0 : term[i] = '\0';
1956 0 : break;
1957 : default:
1958 : return (FALSE);
1959 : }
1960 0 : tok++;
1961 : } else
1962 0 : term[i] = *tok++;
1963 : }
1964 :
1965 0 : if (*tok != '\"')
1966 : return (FALSE);
1967 :
1968 0 : ci->term_len = i;
1969 0 : TDS_ZERO_FREE(ci->terminator);
1970 0 : if (i > 0) {
1971 0 : if ((ci->terminator = tds_new(BYTE, i)) == NULL) {
1972 0 : dbperror(dbproc, SYBEMEM, errno);
1973 0 : return FALSE;
1974 : }
1975 0 : memcpy(ci->terminator, term, i);
1976 : }
1977 :
1978 : whichcol = TAB_COLNUM;
1979 : break;
1980 :
1981 0 : case TAB_COLNUM:
1982 0 : ci->tab_colnum = atoi(tok);
1983 0 : whichcol = NO_MORE_COLS;
1984 0 : break;
1985 :
1986 : }
1987 0 : tok = strtok_r(NULL, " \t", &lasts);
1988 : }
1989 0 : if (whichcol == NO_MORE_COLS)
1990 : return (TRUE);
1991 : else
1992 0 : return (FALSE);
1993 : }
1994 :
1995 : #if defined(DBLIB_UNIMPLEMENTED)
1996 : /**
1997 : * \ingroup dblib_bcp
1998 : * \brief Write a format definition file. Not Implemented.
1999 : *
2000 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
2001 : * \param filename Name that would be passed to fopen(3).
2002 : *
2003 : * \remarks Reads a format file and calls bcp_columns() and bcp_colfmt() as needed.
2004 : * \a FreeTDS includes freebcp, a utility to copy data to or from a host file.
2005 : *
2006 : * \todo For completeness, \a freebcp ought to be able to create format files, but that functionality
2007 : * is currently lacking, as is bcp_writefmt().
2008 : * \todo See the vendors' documentation for the format of these files.
2009 : *
2010 : * \return SUCCEED or FAIL.
2011 : * \sa bcp_colfmt(), bcp_colfmt_ps(), bcp_columns(), bcp_readfmt()
2012 : */
2013 : RETCODE
2014 : bcp_writefmt(DBPROCESS * dbproc, const char filename[])
2015 : {
2016 : tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED: bcp_writefmt(%p, %s)\n", dbproc, filename? filename:"NULL");
2017 : CHECK_CONN(FAIL);
2018 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
2019 : CHECK_NULP(filename, "bcp_writefmt", 2, FAIL);
2020 :
2021 : #if 0
2022 : dbperror(dbproc, SYBEBUFF, errno); /* bcp: Unable to create format file */
2023 : dbperror(dbproc, SYBEBWFF, errno); /* I/O error while writing bcp format file */
2024 : #endif
2025 :
2026 : return FAIL;
2027 : }
2028 :
2029 : /**
2030 : * \ingroup dblib_bcp
2031 : * \brief Write some text or image data to the server. Not implemented, sadly.
2032 : *
2033 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
2034 : * \param size How much to write, in bytes.
2035 : * \param text Address of the data to be written.
2036 : * \remarks For a SYBTEXT or SYBIMAGE column, bcp_bind() can be called with
2037 : * a NULL varaddr parameter. If it is, bcp_sendrow() will return control
2038 : * to the application after the non-text data have been sent. The application then calls
2039 : * bcp_moretext() -- usually in a loop -- to send the text data in manageable chunks.
2040 : * \todo implement bcp_moretext().
2041 : * \return SUCCEED or FAIL.
2042 : * \sa bcp_bind(), bcp_sendrow(), dbmoretext(), dbwritetext()
2043 : */
2044 : RETCODE
2045 : bcp_moretext(DBPROCESS * dbproc, DBINT size, BYTE * text)
2046 : {
2047 : tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED: bcp_moretext(%p, %d, %p)\n", dbproc, size, text);
2048 : CHECK_CONN(FAIL);
2049 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
2050 : CHECK_NULP(text, "bcp_moretext", 3, FAIL);
2051 :
2052 : #if 0
2053 : dbperror(dbproc, SYBEBCMTXT, 0);
2054 : /* bcp_moretext may be used only when there is at least one text or image column in the server table */
2055 : dbperror(dbproc, SYBEBTMT, 0);
2056 : /* Attempt to send too much text data via the bcp_moretext call */
2057 : #endif
2058 : return FAIL;
2059 : }
2060 : #endif
2061 :
2062 : /**
2063 : * \ingroup dblib_bcp
2064 : * \brief Commit a set of rows to the table.
2065 : *
2066 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
2067 : * \remarks If not called, bcp_done() will cause the rows to be saved.
2068 : * \return Count of rows saved, or -1 on error.
2069 : * \sa bcp_bind(), bcp_done(), bcp_sendrow()
2070 : */
2071 : DBINT
2072 10 : bcp_batch(DBPROCESS * dbproc)
2073 : {
2074 10 : int rows_copied = 0;
2075 :
2076 10 : tdsdump_log(TDS_DBG_FUNC, "bcp_batch(%p)\n", dbproc);
2077 10 : CHECK_CONN(-1);
2078 10 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, -1);
2079 :
2080 10 : if (TDS_FAILED(tds_bcp_done(dbproc->tds_socket, &rows_copied)))
2081 : return -1;
2082 :
2083 10 : tds_bcp_start(dbproc->tds_socket, dbproc->bcpinfo);
2084 :
2085 10 : return rows_copied;
2086 : }
2087 :
2088 : /**
2089 : * \ingroup dblib_bcp
2090 : * \brief Conclude the transfer of data from program variables.
2091 : *
2092 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
2093 : * \remarks Do not overlook this function. According to Sybase, failure to call bcp_done()
2094 : * "will result in unpredictable errors".
2095 : * \return As with bcp_batch(), the count of rows saved, or -1 on error.
2096 : * \sa bcp_batch(), bcp_bind(), bcp_moretext(), bcp_sendrow()
2097 : */
2098 : DBINT
2099 38 : bcp_done(DBPROCESS * dbproc)
2100 : {
2101 : int rows_copied;
2102 :
2103 38 : tdsdump_log(TDS_DBG_FUNC, "bcp_done(%p)\n", dbproc);
2104 38 : CHECK_CONN(-1);
2105 :
2106 38 : if (!(dbproc->bcpinfo))
2107 : return -1;
2108 :
2109 38 : if (TDS_FAILED(tds_bcp_done(dbproc->tds_socket, &rows_copied)))
2110 : return -1;
2111 :
2112 20 : _bcp_free_storage(dbproc);
2113 :
2114 20 : return rows_copied;
2115 : }
2116 :
2117 : /**
2118 : * \ingroup dblib_bcp
2119 : * \brief Bind a program host variable to a database column
2120 : *
2121 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
2122 : * \param varaddr address of host variable
2123 : * \param prefixlen length of any prefix found at the beginning of \a varaddr, in bytes.
2124 : Use zero for fixed-length datatypes.
2125 : * \param varlen bytes of data in \a varaddr. Zero for NULL, -1 for fixed-length datatypes.
2126 : * \param terminator byte sequence that marks the end of the data in \a varaddr
2127 : * \param termlen length of \a terminator
2128 : * \param vartype datatype of the host variable
2129 : * \param table_column Nth column, starting at 1, in the table.
2130 : *
2131 : * \remarks The order of operation is:
2132 : * - bcp_init() with \a hfile == NULL and \a direction == DB_IN.
2133 : * - bcp_bind(), once per column you want to write to
2134 : * - bcp_batch(), optionally, to commit a set of rows
2135 : * - bcp_done()
2136 : * \return SUCCEED or FAIL.
2137 : * \sa bcp_batch(), bcp_colfmt(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_control(),
2138 : * bcp_done(), bcp_exec(), bcp_moretext(), bcp_sendrow()
2139 : */
2140 : RETCODE
2141 324 : bcp_bind(DBPROCESS * dbproc, BYTE * varaddr, int prefixlen, DBINT varlen,
2142 : BYTE * terminator, int termlen, int db_vartype, int table_column)
2143 : {
2144 : TDS_SERVER_TYPE vartype;
2145 : TDSCOLUMN *colinfo;
2146 :
2147 324 : tdsdump_log(TDS_DBG_FUNC, "bcp_bind(%p, %p, %d, %d -- %p, %d, %s, %d)\n",
2148 : dbproc, varaddr, prefixlen, varlen,
2149 : terminator, termlen, dbprtype(db_vartype), table_column);
2150 324 : CHECK_CONN(FAIL);
2151 324 : CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
2152 648 : DBPERROR_RETURN(db_vartype != 0 && !is_tds_type_valid(db_vartype), SYBEUDTY);
2153 324 : vartype = (TDS_SERVER_TYPE) db_vartype;
2154 :
2155 324 : if (dbproc->hostfileinfo != NULL) {
2156 0 : dbperror(dbproc, SYBEBCPB, 0);
2157 0 : return FAIL;
2158 : }
2159 :
2160 324 : if (dbproc->bcpinfo->direction != DB_IN) {
2161 0 : dbperror(dbproc, SYBEBCPN, 0);
2162 0 : return FAIL;
2163 : }
2164 :
2165 324 : if (varlen < -1) {
2166 0 : dbperror(dbproc, SYBEBCVLEN, 0);
2167 0 : return FAIL;
2168 : }
2169 :
2170 324 : if (prefixlen != 0 && prefixlen != 1 && prefixlen != 2 && prefixlen != 4) {
2171 0 : dbperror(dbproc, SYBEBCBPREF, 0);
2172 0 : return FAIL;
2173 : }
2174 :
2175 324 : if (prefixlen == 0 && varlen == -1 && termlen == -1 && !is_fixed_type(vartype)) {
2176 0 : tdsdump_log(TDS_DBG_FUNC, "bcp_bind(): non-fixed type %d requires prefix or terminator\n", vartype);
2177 : return FAIL;
2178 : }
2179 :
2180 324 : if (is_fixed_type(vartype) && (varlen != -1 && varlen != 0)) {
2181 0 : dbperror(dbproc, SYBEBCIT, 0);
2182 0 : return FAIL;
2183 : }
2184 :
2185 324 : if (table_column <= 0 || table_column > dbproc->bcpinfo->bindinfo->num_cols) {
2186 0 : dbperror(dbproc, SYBECNOR, 0);
2187 0 : return FAIL;
2188 : }
2189 :
2190 324 : if (varaddr == NULL && (prefixlen != 0 || termlen != 0)) {
2191 0 : dbperror(dbproc, SYBEBCBNPR, 0);
2192 0 : return FAIL;
2193 : }
2194 :
2195 324 : colinfo = dbproc->bcpinfo->bindinfo->columns[table_column - 1];
2196 :
2197 : /* If varaddr is NULL and varlen greater than 0, the table column type must be SYBTEXT or SYBIMAGE
2198 : and the program variable type must be SYBTEXT, SYBCHAR, SYBIMAGE or SYBBINARY */
2199 324 : if (varaddr == NULL && varlen > 0) {
2200 0 : int fOK = (colinfo->column_type == SYBTEXT || colinfo->column_type == SYBIMAGE) &&
2201 0 : (vartype == SYBTEXT || vartype == SYBCHAR || vartype == SYBIMAGE || vartype == SYBBINARY );
2202 : if( !fOK ) {
2203 0 : dbperror(dbproc, SYBEBCBNTYP, 0);
2204 0 : tdsdump_log(TDS_DBG_FUNC, "bcp_bind: SYBEBCBNTYP: column=%d and vartype=%d (should fail?)\n",
2205 : colinfo->column_type, vartype);
2206 : /* return FAIL; */
2207 : }
2208 : }
2209 :
2210 324 : colinfo->column_varaddr = (char *)varaddr;
2211 324 : colinfo->column_bindtype = vartype;
2212 324 : colinfo->column_bindlen = varlen;
2213 324 : colinfo->bcp_prefix_len = prefixlen;
2214 :
2215 324 : TDS_ZERO_FREE(colinfo->bcp_terminator);
2216 324 : colinfo->bcp_term_len = 0;
2217 324 : if (termlen > 0) {
2218 54 : if ((colinfo->bcp_terminator = tds_new(TDS_CHAR, termlen)) == NULL) {
2219 0 : dbperror(dbproc, SYBEMEM, errno);
2220 0 : return FAIL;
2221 : }
2222 54 : memcpy(colinfo->bcp_terminator, terminator, termlen);
2223 54 : colinfo->bcp_term_len = termlen;
2224 : }
2225 :
2226 : return SUCCEED;
2227 : }
2228 :
2229 : static void
2230 0 : _bcp_null_error(TDSBCPINFO *bcpinfo, int index TDS_UNUSED, int offset TDS_UNUSED)
2231 : {
2232 0 : DBPROCESS *dbproc = (DBPROCESS *) bcpinfo->parent;
2233 0 : dbperror(dbproc, SYBEBCNN, 0);
2234 0 : }
2235 :
2236 : /**
2237 : * \ingroup dblib_bcp_internal
2238 : * \brief For a bcp in from program variables, get the data from the host variable
2239 : *
2240 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
2241 : * \param bindcol
2242 : *
2243 : * \return TDS_SUCCESS or TDS_FAIL.
2244 : * \sa _bcp_add_fixed_columns, _bcp_add_variable_columns, _bcp_send_bcp_record
2245 : */
2246 : static TDSRET
2247 4138 : _bcp_get_col_data(TDSBCPINFO *bcpinfo, TDSCOLUMN *bindcol, int index TDS_UNUSED, int offset TDS_UNUSED)
2248 : {
2249 : TDS_SERVER_TYPE coltype, desttype;
2250 : int collen;
2251 : int bytes_read;
2252 : BYTE *dataptr;
2253 4138 : DBPROCESS *dbproc = (DBPROCESS *) bcpinfo->parent;
2254 : TDSRET rc;
2255 :
2256 4138 : tdsdump_log(TDS_DBG_FUNC, "_bcp_get_col_data(%p, %p)\n", bcpinfo, bindcol);
2257 4138 : CHECK_CONN(TDS_FAIL);
2258 4138 : CHECK_NULP(bindcol, "_bcp_get_col_data", 2, TDS_FAIL);
2259 :
2260 4138 : dataptr = (BYTE *) bindcol->column_varaddr;
2261 :
2262 4138 : collen = 0;
2263 :
2264 : /* If a prefix length specified, read the correct amount of data. */
2265 :
2266 4138 : if (bindcol->bcp_prefix_len > 0) {
2267 :
2268 0 : switch (bindcol->bcp_prefix_len) {
2269 0 : case 1:
2270 0 : collen = TDS_GET_UA1(dataptr);
2271 0 : dataptr += 1;
2272 0 : break;
2273 0 : case 2:
2274 0 : collen = (TDS_SMALLINT) TDS_GET_UA2(dataptr);
2275 0 : dataptr += 2;
2276 0 : break;
2277 0 : case 4:
2278 0 : collen = (TDS_INT) TDS_GET_UA4(dataptr);
2279 0 : dataptr += 4;
2280 0 : break;
2281 : }
2282 0 : if (collen <= 0)
2283 : goto null_data;
2284 : }
2285 :
2286 : /* if (Max) column length specified take that into consideration. */
2287 :
2288 4138 : if (bindcol->column_bindlen >= 0) {
2289 2800 : if (bindcol->column_bindlen == 0)
2290 : goto null_data;
2291 1500 : if (collen)
2292 0 : collen = TDS_MIN(bindcol->column_bindlen, collen);
2293 : else
2294 : collen = bindcol->column_bindlen;
2295 : }
2296 :
2297 2838 : desttype = tds_get_conversion_type(bindcol->column_type, bindcol->column_size);
2298 :
2299 2838 : coltype = bindcol->column_bindtype == 0 ? desttype : (TDS_SERVER_TYPE) bindcol->column_bindtype;
2300 :
2301 : /* Fixed Length data - this overrides anything else specified */
2302 2838 : if (is_fixed_type(coltype))
2303 750 : collen = tds_get_size_by_type(coltype);
2304 :
2305 : /* read the data, finally */
2306 :
2307 2838 : if (bindcol->bcp_term_len > 0) { /* terminated field */
2308 88 : bytes_read = _bcp_get_term_var(dataptr, (BYTE *)bindcol->bcp_terminator, bindcol->bcp_term_len);
2309 :
2310 88 : if (collen <= 0 || bytes_read < collen)
2311 88 : collen = bytes_read;
2312 :
2313 88 : if (collen == 0)
2314 : goto null_data;
2315 : }
2316 :
2317 2810 : if (collen < 0)
2318 0 : collen = (int) strlen((char *) dataptr);
2319 :
2320 2810 : rc = _bcp_convert_in(dbproc, coltype, (const TDS_CHAR *) dataptr, collen, desttype, bindcol);
2321 2810 : if (TDS_FAILED(rc))
2322 : return rc;
2323 2810 : rtrim_bcpcol(bindcol);
2324 :
2325 2810 : return TDS_SUCCESS;
2326 :
2327 1328 : null_data:
2328 1328 : bindcol->bcp_column_data->datalen = 0;
2329 1328 : bindcol->bcp_column_data->is_null = true;
2330 1328 : return TDS_SUCCESS;
2331 : }
2332 :
2333 : /**
2334 : * Function to read data from file. In this case is empty as data
2335 : * are already on bcp_column_data
2336 : */
2337 : static TDSRET
2338 1878 : _bcp_no_get_col_data(TDSBCPINFO *bcpinfo TDS_UNUSED, TDSCOLUMN *bindcol TDS_UNUSED, int index TDS_UNUSED, int offset TDS_UNUSED)
2339 : {
2340 1878 : return TDS_SUCCESS;
2341 : }
2342 :
2343 : /**
2344 : * Get the data for bcp-in from program variables, where the program data
2345 : * have been identified as character terminated,
2346 : * This is a low-level, internal function. Call it correctly.
2347 : */
2348 : /**
2349 : * \ingroup dblib_bcp_internal
2350 : * \brief
2351 : *
2352 : * \param pdata
2353 : * \param term
2354 : * \param term_len
2355 : *
2356 : * \return data length.
2357 : */
2358 : static int
2359 88 : _bcp_get_term_var(const BYTE * pdata, const BYTE * term, int term_len)
2360 : {
2361 : int bufpos;
2362 :
2363 88 : assert(term_len > 0);
2364 :
2365 : /* if bufpos becomes negative, we probably failed to find the terminator */
2366 330 : for (bufpos = 0; bufpos >= 0 && memcmp(pdata, term, term_len) != 0; pdata++) {
2367 330 : bufpos++;
2368 : }
2369 :
2370 : assert(bufpos >= 0);
2371 88 : return bufpos;
2372 : }
2373 :
2374 : /**
2375 : * \ingroup dblib_bcp_internal
2376 : * \brief trim a string of trailing blanks
2377 : *
2378 : * Replaces spaces at the end of a string with NULs
2379 : * \param str pointer to a character buffer (not null-terminated)
2380 : * \param len size of the \a str in bytes
2381 : *
2382 : * \return modified length
2383 : */
2384 : static int
2385 : rtrim(char *str, int len)
2386 : {
2387 1166 : char *p = str + len - 1;
2388 :
2389 1660 : while (p > str && *p == ' ') {
2390 494 : *p-- = '\0';
2391 : }
2392 1166 : return (int)(1 + p - str);
2393 : }
2394 :
2395 : static int
2396 : rtrim_u16(uint16_t *str, int len, uint16_t space)
2397 : {
2398 62 : uint16_t *p = str + len / 2 - 1;
2399 :
2400 62 : while (p > str && *p == space) {
2401 0 : *p-- = '\0';
2402 : }
2403 62 : return (int)(1 + p - str) * 2;
2404 : }
2405 :
2406 : /**
2407 : * \ingroup dblib_bcp_internal
2408 : * \brief
2409 : *
2410 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
2411 : */
2412 : static void
2413 984 : _bcp_free_columns(DBPROCESS * dbproc)
2414 : {
2415 : int i;
2416 :
2417 984 : tdsdump_log(TDS_DBG_FUNC, "_bcp_free_columns(%p)\n", dbproc);
2418 984 : assert(dbproc && dbproc->hostfileinfo);
2419 :
2420 984 : if (dbproc->hostfileinfo->host_columns) {
2421 3376 : for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
2422 3376 : TDS_ZERO_FREE(dbproc->hostfileinfo->host_columns[i]->terminator);
2423 3376 : TDS_ZERO_FREE(dbproc->hostfileinfo->host_columns[i]);
2424 : }
2425 656 : TDS_ZERO_FREE(dbproc->hostfileinfo->host_columns);
2426 656 : dbproc->hostfileinfo->host_colcount = 0;
2427 : }
2428 984 : }
2429 :
2430 : /**
2431 : * \ingroup dblib_bcp_internal
2432 : * \brief
2433 : *
2434 : * \param dbproc contains all information needed by db-lib to manage communications with the server.
2435 : *
2436 : * \sa bcp_done(), bcp_exec(), bcp_init()
2437 : */
2438 : static void
2439 714 : _bcp_free_storage(DBPROCESS * dbproc)
2440 : {
2441 714 : tdsdump_log(TDS_DBG_FUNC, "_bcp_free_storage(%p)\n", dbproc);
2442 714 : assert(dbproc);
2443 :
2444 714 : if (dbproc->hostfileinfo) {
2445 328 : TDS_ZERO_FREE(dbproc->hostfileinfo->hostfile);
2446 328 : TDS_ZERO_FREE(dbproc->hostfileinfo->errorfile);
2447 328 : _bcp_free_columns(dbproc);
2448 328 : TDS_ZERO_FREE(dbproc->hostfileinfo);
2449 : }
2450 :
2451 714 : tds_free_bcpinfo(dbproc->bcpinfo);
2452 714 : dbproc->bcpinfo = NULL;
2453 714 : }
2454 :
2455 : /** Fast strftime for default bcp format */
2456 : static int
2457 36 : _bcp_strftime(char *buf, size_t maxsize, const char *format, const TDSDATEREC *dr, int prec)
2458 : {
2459 36 : char *pbuf = buf;
2460 :
2461 36 : if (format)
2462 0 : return (int) tds_strftime(pbuf, maxsize, format, dr, prec);
2463 :
2464 36 : pbuf += tds_u32toa_fast(pbuf, dr->year);
2465 :
2466 : /* The following "& 63" are to avoid overflows if values are corrupted */
2467 :
2468 36 : *pbuf++ = '-';
2469 36 : tds_02d_fast(pbuf, (dr->month + 1) & 63);
2470 36 : pbuf += 2;
2471 :
2472 36 : *pbuf++ = '-';
2473 36 : tds_02d_fast(pbuf, dr->day & 63);
2474 36 : pbuf += 2;
2475 :
2476 36 : *pbuf++ = ' ';
2477 36 : tds_02d_fast(pbuf, dr->hour & 63);
2478 36 : pbuf += 2;
2479 :
2480 36 : *pbuf++ = ':';
2481 36 : tds_02d_fast(pbuf, dr->minute & 63);
2482 36 : pbuf += 2;
2483 :
2484 36 : *pbuf++ = ':';
2485 36 : tds_02d_fast(pbuf, dr->second & 63);
2486 36 : pbuf += 2;
2487 :
2488 36 : if (prec > 0) {
2489 : char ibuf[10];
2490 :
2491 36 : *pbuf++ = '.';
2492 :
2493 36 : memset(ibuf, '0', sizeof(ibuf));
2494 : /* Mask off a negative sign (input should not contain this anyway) */
2495 36 : tds_u32toa_fast_right(ibuf, dr->decimicrosecond & 0x7FFFFFFF);
2496 : /* Skip first 3 digits here, as decimicrosecond should not exceed 9,999,999 */
2497 36 : memcpy(pbuf, ibuf + 3, prec);
2498 36 : pbuf += prec;
2499 : }
2500 36 : *pbuf = '\0';
2501 :
2502 : #if ENABLE_EXTRA_CHECKS
2503 : {
2504 : char tbuf[256];
2505 :
2506 36 : tds_strftime(tbuf, sizeof(tbuf), BCP_DEFAULT_DATEFMT, dr, prec);
2507 36 : if (strcmp(tbuf, (char *) buf)) {
2508 0 : fprintf(stderr, "_bcp_strftime(%s) does not match tds_strftime(%s)\n", tbuf, (char *) buf);
2509 0 : tds_extra_assert(!"_bcp_strftime mismatch");
2510 : }
2511 : }
2512 : #endif
2513 36 : return (int) (pbuf - buf);
2514 : }
|