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