NCBI C++ ToolKit
bcp.c
Go to the documentation of this file.

Go to the SVN repository for this file.

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