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