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