NCBI C++ ToolKit
dblib.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) 2006-2015 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 
25 #include <freetds/time.h>
26 
27 #include <assert.h>
28 #include <stdio.h>
29 
30 #if HAVE_STDLIB_H
31 #include <stdlib.h>
32 #endif /* HAVE_STDLIB_H */
33 
34 #if HAVE_STRING_H
35 #include <string.h>
36 #endif /* HAVE_STRING_H */
37 
38 #if HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif /* HAVE_UNISTD_H */
41 
42 #if HAVE_ERRNO_H
43 # include <errno.h>
44 #endif /* HAVE_ERRNO_H */
45 
46 /**
47  * \ingroup dblib_core
48  * \remarks Either SYBDBLIB or MSDBLIB (not both) must be defined.
49  * This affects how certain application-addressable
50  * strucures are defined.
51  */
52 #include <freetds/tds.h>
53 #include <freetds/thread.h>
54 #include <freetds/convert.h>
55 #include <freetds/string.h>
56 #include <freetds/data.h>
57 #include <replacements.h>
58 #include <sybfront.h>
59 #include <sybdb.h>
60 #include <syberror.h>
61 #include <dblib.h>
62 
64 static BYTE *_dbcoldata(TDSCOLUMN *colinfo);
65 static int _get_printable_size(TDSCOLUMN * colinfo);
66 static char *_dbprdate(char *timestr);
67 static int _dbnullable(DBPROCESS * dbproc, int column);
68 static const char *tds_prdatatype(int datatype_token);
69 
70 static int default_err_handler(DBPROCESS * dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr);
71 
72 void copy_data_to_host_var(DBPROCESS *, TDS_SERVER_TYPE, const BYTE *, int, BYTE *, DBINT, int, DBINT *);
73 RETCODE dbgetnull(DBPROCESS *dbproc, int bindtype, int varlen, BYTE* varaddr);
74 
75 /**
76  * \file dblib.c
77  * Main implementation file for \c db-lib.
78  */
79 /**
80  * \file bcp.c
81  * Implementation of \c db-lib bulk copy functions.
82  */
83 /**
84  * \defgroup dblib_api The db-lib API
85  * Functions callable by \c db-lib client programs
86  *
87  * The \c db_lib interface is implemented by both Sybase and Microsoft. FreeTDS seeks to implement
88  * first the intersection of the functions defined by the vendors.
89  */
90 
91 /**
92  * \ingroup dblib_api
93  * \defgroup dblib_core Primary functions
94  * Core functions needed by most db-lib programs.
95 */
96 /**
97  * \ingroup dblib_api
98  * \defgroup dblib_rpc Remote Procedure functions
99  * Functions used with stored procedures.
100  * Especially useful for OUTPUT parameters, because modern Microsoft servers do not
101  * return output parameter data to the client unless the procedure was invoked
102  * with dbrpcsend().
103  */
104 /**
105  * \ingroup dblib_api
106  * \defgroup dblib_bcp Bulk copy functions
107  * Functions to bulk-copy (a/k/a \em bcp) data to/from the database.
108  */
109 /**
110  * \ingroup dblib_bcp
111  * \defgroup dblib_bcp_internal Internal bcp functions
112  * Static functions internal to the bcp library.
113  */
114 /**
115  * \ingroup dblib_api
116  * \defgroup dblib_money Money functions
117  * Functions to manipulate the MONEY datatype.
118  */
119 /**
120  * \ingroup dblib_api
121  * \defgroup dblib_datetime Datetime functions
122  * Functions to manipulate DBDATETIME structures. Defined by Sybase only.
123  * These are not implemented:
124  * - dbdate4cmp()
125  * - dbdate4zero()
126  * - dbdatechar()
127  * - dbdatename()
128  * - dbdateorder()
129  * - dbdatepart()
130  * - dbdatezero()
131  * - dbdayname()
132  */
133 /**
134  * \ingroup dblib_api
135  * \defgroup dblib_internal Internals
136  * Functions called within \c db-lib for self-help.
137  * These functions are of interest only to people hacking on the FreeTDS db-lib implementation.
138  */
139 /**
140  * \ingroup dblib_api
141  * \defgroup dblib_unimplemented Unimplemented
142  * Functions thus far not implemented in the FreeTDS db-lib implementation.
143  * While some of these are simply awaiting someone with time and skill (and inclination)
144  * it might be noted here that the old browse functions (e.g. dbcolbrowse())
145  * are on the never-to-do list.
146  * They were defined by Sybase and were superseded long ago, although they're still
147  * present in Microsoft's implementation.
148  * They were never popular and today better alternatives are available.
149  * For completeness, they are:
150  * - dbcolbrowse()
151  * - dbcolsource()
152  * - dbfreequal()
153  * - dbqual()
154  * - dbtabbrowse()
155  * - dbtabcount()
156  * - dbtabname()
157  * - dbtabsource()
158  * - dbtsnewlen()
159  * - dbtsnewval()
160  * - dbtsput()
161  */
162 
163 /* info/err message handler functions (or rather pointers to them) */
166 
167 /** \internal
168  * \dblib_internal
169  * \remarks A db-lib connection has an implicit TDS context.
170  */
171 typedef struct dblib_context
172 {
173  /** reference count, time dbinit called */
175 
176  /** libTDS context */
178  /** libTDS context reference counter */
180 
181  /* save all connection in a list */
187  int login_timeout; /**< not used unless positive */
188  int query_timeout; /**< not used unless positive */
189 }
191 
193 #ifdef TDS_HAVE_MUTEX
195 #endif
196 
197 static int g_dblib_version =
198 #ifdef TDS42
199  DBVERSION_42;
200 #elif TDS50
202 #elif TDS46
203  DBVERSION_46;
204 #elif TDS70
205  DBVERSION_70;
206 #elif TDS71
207  DBVERSION_71;
208 #elif TDS72
209  DBVERSION_72;
210 #elif TDS73
211  DBVERSION_73;
212 #elif TDS74
213  DBVERSION_74;
214 #else
216 #endif
217 static int g_dbsetversion_called = 0;
218 
219 
220 static int
222 {
223  int i = 0;
224  const int list_size = ctx->connection_list_size_represented;
225 
226  tdsdump_log(TDS_DBG_FUNC, "dblib_add_connection(%p, %p)\n", ctx, tds);
227 
228  while (i < list_size && ctx->connection_list[i])
229  i++;
230  if (i == list_size) {
231  dbperror((DBPROCESS *) tds_get_parent(tds), 50001, 0);
232  return 1;
233  } else {
234  ctx->connection_list[i] = tds;
235  return 0;
236  }
237 }
238 
239 static void
241 {
242  int i = 0;
243  const int list_size = ctx->connection_list_size;
244 
245  tdsdump_log(TDS_DBG_FUNC, "dblib_del_connection(%p, %p)\n", ctx, tds);
246 
247  while (i < list_size && ctx->connection_list[i] != tds)
248  i++;
249  if (i == list_size) {
250  /* connection wasn't on the free list...now what */
251  } else {
252  /* remove it */
253  ctx->connection_list[i] = NULL;
254  }
255 }
256 
257 static TDSCONTEXT*
259 {
260  tdsdump_log(TDS_DBG_FUNC, "dblib_get_tds_ctx(void)\n");
261 
264  if (g_dblib_ctx.tds_ctx == NULL) {
266 
267  /*
268  * Set the functions in the TDS layer to point to the correct handler functions
269  */
273 
275  /* set default in case there's no locale file */
276  const static char date_format[] =
277 #ifndef _WIN32
278  "%b %e %Y %I:%M:%S:%z%p";
279 #else
280  "%b %d %Y %I:%M:%S:%z%p";
281 #endif
282  g_dblib_ctx.tds_ctx->locale->date_fmt = strdup(date_format);
283  }
284  }
286  return g_dblib_ctx.tds_ctx;
287 }
288 
289 static void
291 {
292  tdsdump_log(TDS_DBG_FUNC, "dblib_release_tds_ctx(%d)\n", count);
293 
296  if (g_dblib_ctx.tds_ctx_ref_count <= 0) {
299  }
301 }
302 
303 #include "buffering.h"
304 
305 static void
306 db_env_chg(TDSSOCKET * tds, int type, char *oldval, char *newval)
307 {
308  DBPROCESS *dbproc;
309 
310  assert(oldval != NULL && newval != NULL);
311  if (strlen(oldval) == 1 && *oldval == 1)
312  oldval = "(0x1)";
313 
314  tdsdump_log(TDS_DBG_FUNC, "db_env_chg(%p, %d, %s, %s)\n", tds, type, oldval, newval);
315 
316  if (!tds || !tds_get_parent(tds))
317  return;
319 
320  dbproc->envchange_rcv |= (1 << (type - 1));
321  switch (type) {
322  case TDS_ENV_DATABASE:
323  strlcpy(dbproc->dbcurdb, newval, sizeof(dbproc->dbcurdb));
324  break;
325  case TDS_ENV_CHARSET:
326  strlcpy(dbproc->servcharset, newval, sizeof(dbproc->servcharset));
327  break;
328  default:
329  break;
330  }
331  return;
332 }
333 
334 /** \internal
335  * \ingroup dblib_internal
336  * \brief Sanity checks for column-oriented functions.
337  *
338  * \param dbproc contains all information needed by db-lib to manage communications with the server.
339  * \param pcolinfo address of pointer to a TDSCOLUMN structure.
340  * \remarks Makes sure dbproc and the requested column are valid.
341  * Calls dbperror() if not.
342  * \returns appropriate error or SUCCEED
343  */
344 static TDSCOLUMN*
346 {
347  if (!dbproc) {
348  dbperror(dbproc, SYBENULL, 0);
349  return NULL;
350  }
351  if (IS_TDSDEAD(dbproc->tds_socket)) {
352  dbperror(dbproc, SYBEDDNE, 0);
353  return NULL;
354  }
355  if (!dbproc->tds_socket->res_info)
356  return NULL;
357  if (column < 1 || column > dbproc->tds_socket->res_info->num_cols) {
358  dbperror(dbproc, SYBECNOR, 0);
359  return NULL;
360  }
361 
362  return dbproc->tds_socket->res_info->columns[column - 1];
363 }
364 
365 static TDSCOLUMN*
366 dbacolptr(DBPROCESS* dbproc, int computeid, int column, int is_bind)
367 {
368  TDS_UINT i;
369  TDSSOCKET *tds;
371 
372  if (!dbproc) {
373  dbperror(dbproc, SYBENULL, 0);
374  return NULL;
375  }
376  tds = dbproc->tds_socket;
377  if (IS_TDSDEAD(tds)) {
378  dbperror(dbproc, SYBEDDNE, 0);
379  return NULL;
380  }
381  for (i = 0;; ++i) {
382  if (i >= tds->num_comp_info) {
383  /* Attempt to bind user variable to a non-existent compute row */
384  if (is_bind)
385  dbperror(dbproc, SYBEBNCR, 0);
386  return NULL;
387  }
388  info = tds->comp_info[i];
389  if (info->computeid == computeid)
390  break;
391  }
392  /* Fail if either the compute id or the column number is invalid. */
393  if (column < 1 || column > info->num_cols) {
394  dbperror(dbproc, is_bind ? SYBEABNC : SYBECNOR, 0);
395  return NULL;
396  }
397 
398  return info->columns[column - 1];
399 }
400 
401 /*
402  * Default null substitution values
403  * Binding Type Null Substitution Value
404  * TINYBIND 0
405  * SMALLBIND 0
406  * INTBIND 0
407  * CHARBIND Empty string (padded with blanks)
408  * STRINGBIND Empty string (padded with blanks, null-terminated)
409  * NTBSTRINGBIND Empty string (null-terminated)
410  * VARYCHARBIND Empty string
411  * BINARYBIND Empty array (padded with zeros)
412  * VARYBINBIND Empty array
413  * DATETIMEBIND 8 bytes of zeros
414  * SMALLDATETIMEBIND 8 bytes of zeros
415  * MONEYBIND $0.00
416  * SMALLMONEYBIND $0.00
417  * FLT8BIND 0.0
418  * REALBIND 0.0
419  * DECIMALBIND 0.0 (with default scale and precision)
420  * NUMERICBIND 0.0 (with default scale and precision)
421  * BOUNDARYBIND Empty string (null-terminated)
422  * SENSITIVITYBIND Empty string (null-terminated)
423  */
424 
425 static const DBBIT null_BIT = 0;
426 static const DBTINYINT null_TINYINT = 0;
427 static const DBSMALLINT null_SMALLINT = 0;
428 static const DBINT null_INT = 0;
429 static const DBBIGINT null_BIGINT = 0;
430 static const DBFLT8 null_FLT8 = 0;
431 static const DBREAL null_REAL = 0;
432 
433 static const DBCHAR null_CHAR = '\0';
434 static const DBVARYCHAR null_VARYCHAR = { 0, {0} };
435 /* static const DBBINARY null_BINARY = 0; */
436 
437 static const DBDATETIME null_DATETIME = { 0, 0 };
438 static const DBDATETIME4 null_SMALLDATETIME = { 0, 0 };
439 static const DBMONEY null_MONEY = { 0, 0 };
440 static const DBMONEY4 null_SMALLMONEY = {0};
441 static const DBNUMERIC null_NUMERIC = { 0, 0, {0} };
442 static const TDS_DATETIMEALL null_DATETIMEALL = { 0, 0, 0, 0 };
443 
445  /* CHARBIND 0 */ { NULL, 0 }
446  /* STRINGBIND 1 */ , { NULL, 0 }
447  /* NTBSTRINGBIND 2 */ , { (BYTE*) &null_CHAR, sizeof(null_CHAR) }
448  /* VARYCHARBIND 3 */ , { (BYTE*) &null_VARYCHAR, sizeof(null_VARYCHAR) }
449  /* VARYBINBIND 4 */ , { (BYTE*) &null_VARYCHAR, sizeof(null_VARYCHAR) }
450  /* no such bind 5 */ , { NULL, 0 }
451  /* TINYBIND 6 */ , { &null_TINYINT, sizeof(null_TINYINT) }
452  /* SMALLBIND 7 */ , { (BYTE*) &null_SMALLINT, sizeof(null_SMALLINT) }
453  /* INTBIND 8 */ , { (BYTE*) &null_INT, sizeof(null_INT) }
454  /* FLT8BIND 9 */ , { (BYTE*) &null_FLT8, sizeof(null_FLT8) }
455  /* REALBIND 10 */ , { (BYTE*) &null_REAL, sizeof(null_REAL) }
456  /* DATETIMEBIND 11 */ , { (BYTE*) &null_DATETIME, sizeof(null_DATETIME) }
457  /* SMALLDATETIMEBIND 12 */ , { (BYTE*) &null_SMALLDATETIME, sizeof(null_SMALLDATETIME) }
458  /* MONEYBIND 13 */ , { (BYTE*) &null_MONEY, sizeof(null_MONEY) }
459  /* SMALLMONEYBIND 14 */ , { (BYTE*) &null_SMALLMONEY, sizeof(null_SMALLMONEY) }
460  /* BINARYBIND 15 */ , { NULL, 0 }
461  /* BITBIND 16 */ , { &null_BIT, sizeof(null_BIT) }
462  /* NUMERICBIND 17 */ , { (BYTE*) &null_NUMERIC, sizeof(null_NUMERIC) }
463  /* DECIMALBIND 18 */ , { (BYTE*) &null_NUMERIC, sizeof(null_NUMERIC) }
464  /* SRCNUMERICBIND 19 */ , { (BYTE*) &null_NUMERIC, sizeof(null_NUMERIC) }
465  /* SRCDECIMALBIND 20 */ , { (BYTE*) &null_NUMERIC, sizeof(null_NUMERIC) }
466  /* DATEBIND 21 */ , { (BYTE*) &null_INT, sizeof(null_INT) }
467  /* TIMEBIND 22 */ , { (BYTE*) &null_INT, sizeof(null_INT) }
468  /* BIGDATETIMEBIND 23 */ , { (BYTE*) &null_BIGINT, sizeof(null_BIGINT) }
469  /* BIGTIMEBIND 24 */ , { (BYTE*) &null_BIGINT, sizeof(null_BIGINT) }
470  /* 25 */ , { NULL, 0 }
471  /* 26 */ , { NULL, 0 }
472  /* 27 */ , { NULL, 0 }
473  /* 28 */ , { NULL, 0 }
474  /* 29 */ , { NULL, 0 }
475  /* BIGINTBIND 30 */ , { (BYTE*) &null_BIGINT, sizeof(null_BIGINT) }
476  /* DATETIME2BIND 31 */ , { (BYTE*) &null_DATETIMEALL, sizeof(null_DATETIMEALL) }
477  /* MAXBINDTYPES 32 */
478 };
479 
480 static int
481 dbbindtype(int datatype)
482 {
483  switch (datatype) {
484  case SYBIMAGE:
485  case SYBVARBINARY:
486  case SYBBINARY: return BINARYBIND;
487 
488  case SYBBIT: return BITBIND;
489 
490  case SYBTEXT:
491  case SYBVARCHAR:
492  case SYBCHAR: return NTBSTRINGBIND;
493 
494  case SYBDATETIME: return DATETIMEBIND;
495  case SYBDATETIME4: return SMALLDATETIMEBIND;
496 
497  case SYBDATE: return DATEBIND;
498  case SYBTIME: return TIMEBIND;
499 
500  case SYB5BIGDATETIME: return BIGDATETIMEBIND;
501  case SYB5BIGTIME: return BIGTIMEBIND;
502 
503  case SYBDECIMAL: return DECIMALBIND;
504  case SYBNUMERIC: return NUMERICBIND;
505 
506  case SYBFLT8: return FLT8BIND;
507  case SYBREAL: return REALBIND;
508 
509  case SYBINT1: return TINYBIND;
510  case SYBINT2: return SMALLBIND;
511  case SYBINT4: return INTBIND;
512  case SYBINT8: return BIGINTBIND;
513 
514  case SYBMONEY: return MONEYBIND;
515  case SYBMONEY4: return SMALLMONEYBIND;
516 
517  case SYBMSDATE:
518  case SYBMSTIME:
519  case SYBMSDATETIME2:
520  case SYBMSDATETIMEOFFSET:
521  return DATETIME2BIND;
522 
523  default:
524  assert(0 == "no such datatype");
525  }
526 
527  return 0;
528 }
529 
530 /** \internal
531  * dbbind() says: "Note that if varlen is 0, no padding takes place"
532  * dbgetnull() will not pad varaddr unless varlen is positive.
533  * Vartype Program Type Padding Terminator
534  * ------------------- -------------- -------------- ----------
535  * CHARBIND DBCHAR blanks none
536  * STRINGBIND DBCHAR blanks \0
537  * NTBSTRINGBIND DBCHAR none \0
538  * VARYCHARBIND DBVARYCHAR none none
539  * BOUNDARYBIND DBCHAR none \0
540  * SENSITIVITYBIND DBCHAR none \0
541  */
542 RETCODE
543 dbgetnull(DBPROCESS *dbproc, int bindtype, int varlen, BYTE* varaddr)
544 {
545  NULLREP *pnullrep = default_null_representations + bindtype;
546 
547  tdsdump_log(TDS_DBG_FUNC, "dbgetnull(%p, %d, %d, %p)\n", dbproc, bindtype, varlen, varaddr);
548 
549  CHECK_PARAMETER(varaddr, SYBENULL, FAIL);
550  CHECK_PARAMETER(0 <= bindtype && bindtype < MAXBINDTYPES, SYBEBTYP, FAIL);
551 
552  /* dbproc can be NULL */
553  if (NULL != dbproc) {
555  pnullrep = dbproc->nullreps + bindtype;
556  }
557 
558  /*
559  * Fixed types: ignore varlen
560  * Other types: ignore varlen if <= 0, else varlen must be >= pnullrep->len.
561  */
562  switch (bindtype) {
563  case DATETIMEBIND:
564  case DATETIME2BIND:
565  case DECIMALBIND:
566  case SRCDECIMALBIND:
567  case FLT8BIND:
568  case INTBIND:
569  case MONEYBIND:
570  case NUMERICBIND:
571  case SRCNUMERICBIND:
572  case REALBIND:
573  case SMALLBIND:
574  case SMALLDATETIMEBIND:
575  case SMALLMONEYBIND:
576  case TINYBIND:
577  case BIGINTBIND:
578  case BITBIND:
579  case TIMEBIND:
580  case DATEBIND:
581  case BIGDATETIMEBIND:
582  case BIGTIMEBIND:
583  memcpy(varaddr, pnullrep->bindval, pnullrep->len);
584  return SUCCEED;
585  case CHARBIND:
586  case STRINGBIND:
587  case NTBSTRINGBIND:
588  case BINARYBIND:
589  case VARYCHARBIND:
590  case VARYBINBIND:
591  if (pnullrep->bindval && (varlen <= 0 || (size_t)varlen >= pnullrep->len)) {
592  memcpy(varaddr, pnullrep->bindval, pnullrep->len);
593  }
594  break;
595  default:
596  dbperror(dbproc, SYBEBTYP, 0);
597  return FAIL;
598  }
599 
600  /*
601  * For variable-length types, nonpositive varlen indicates
602  * buffer is "big enough" but also not to pad.
603  * Apply terminator (if applicable) and go home.
604  */
605  if (varlen <= 0) {
606  varlen = pnullrep->len;
607  switch (bindtype) {
608  case STRINGBIND:
609  case NTBSTRINGBIND:
610  ++varlen;
611  break;
612 #if 0
613  case BOUNDARYBIND:
614  case SENSITIVITYBIND:
615 #endif
616  }
617  }
618 
619  if (varlen < (long)pnullrep->len) {
620  tdsdump_log(TDS_DBG_FUNC, "dbgetnull: error: not setting varaddr(%p) because %d < %lu\n",
621  varaddr, varlen, (unsigned long int) pnullrep->len);
622  return FAIL;
623  }
624 
625  tdsdump_log(TDS_DBG_FUNC, "varaddr(%p) varlen %d < %lu?\n",
626  varaddr, varlen, (unsigned long int) pnullrep->len);
627 
628  assert(varlen >= 0);
629 
630  /*
631  * CHARBIND Empty string (padded with blanks)
632  * STRINGBIND Empty string (padded with blanks, null-terminated)
633  * NTBSTRINGBIND Empty string (unpadded, null-terminated)
634  * BINARYBIND Empty array (padded with zeros)
635  */
636  varaddr += pnullrep->len;
637  varlen -= (int)pnullrep->len;
638  if (varlen > 0) {
639  switch (bindtype) {
640  case CHARBIND:
641  memset(varaddr, ' ', varlen);
642  break;
643  case STRINGBIND:
644  memset(varaddr, ' ', varlen);
645  varaddr[varlen-1] = '\0';
646  break;
647  case NTBSTRINGBIND:
648  varaddr[0] = '\0';
649  break;
650  case BINARYBIND:
651  memset(varaddr, 0, varlen);
652  break;
653  case VARYCHARBIND:
654  case VARYBINBIND:
655  break;
656  default:
657  assert(!"unknown bindtype");
658  }
659  }
660  return SUCCEED;
661 }
662 
663 /**
664  * \ingroup dblib_core
665  * \brief Initialize db-lib.
666  *
667  * \remarks Call this function before trying to use db-lib in any way.
668  * Allocates various internal structures and reads \c locales.conf (if any) to determine the default
669  * date format.
670  * \retval SUCCEED normal.
671  * \retval FAIL cannot allocate an array of \c TDS_MAX_CONN \c TDSSOCKET pointers.
672  */
673 RETCODE
674 dbinit(void)
675 {
677 
679 
680  tdsdump_log(TDS_DBG_FUNC, "dbinit(void)\n");
681 
682  if (++g_dblib_ctx.ref_count != 1) {
684  return SUCCEED;
685  }
686  /*
687  * DBLIBCONTEXT stores a list of current connections so they may be closed with dbexit()
688  */
689 
692  tdsdump_log(TDS_DBG_FUNC, "dbinit: out of memory\n");
694  return FAIL;
695  }
698 
701 
703 
705 
706  return SUCCEED;
707 }
708 
709 /**
710  * \ingroup dblib_core
711  * \brief Allocate a \c LOGINREC structure.
712  *
713  * \remarks A \c LOGINREC structure is passed to \c dbopen() to create a connection to the database.
714  * Does not communicate to the server; interacts strictly with library.
715  * \retval NULL the \c LOGINREC cannot be allocated.
716  * \retval LOGINREC* to valid memory, otherwise.
717  */
718 LOGINREC *
719 dblogin(void)
720 {
721  LOGINREC *loginrec;
722 
723  tdsdump_log(TDS_DBG_FUNC, "dblogin(void)\n");
724 
725  if ((loginrec = tds_new(LOGINREC, 1)) == NULL) {
726  dbperror(NULL, SYBEMEM, errno);
727  return NULL;
728  }
729  if ((loginrec->tds_login = tds_alloc_login(1)) == NULL) {
730  dbperror(NULL, SYBEMEM, errno);
731  free(loginrec);
732  return NULL;
733  }
734 
735  /* set default values for loginrec */
736  if (!tds_set_library(loginrec->tds_login, "DB-Library")) {
737  dbperror(NULL, SYBEMEM, errno);
738  free(loginrec);
739  return NULL;
740  }
741 
742  return loginrec;
743 }
744 
745 /**
746  * \ingroup dblib_core
747  * \brief free the \c LOGINREC
748  *
749  */
750 void
752 {
753  tdsdump_log(TDS_DBG_FUNC, "dbloginfree(%p)\n", login);
754 
755  if (login) {
756  tds_free_login(login->tds_login);
758  }
759 }
760 
761 /** \internal
762  * \ingroup dblib_internal
763  * \brief Set the value of a string in a \c LOGINREC structure.
764  *
765  * Called by various macros to populate \a login.
766  * \param login the \c LOGINREC* to modify.
767  * \param value the value to set it to.
768  * \param which the field to set.
769  * \retval SUCCEED the value was set.
770  * \retval FAIL \c DBSETHID or other invalid \a which was tried.
771  */
772 RETCODE
773 dbsetlname(LOGINREC * login, const char *value, int which)
774 {
775  bool copy_ret;
776  const char *value_nonull = value ? value : "";
777 
778  tdsdump_log(TDS_DBG_FUNC, "dbsetlname(%p, %s, %d)\n", login, value, which);
779 
780  if (login == NULL) {
781  dbperror(NULL, SYBEASNL, 0);
782  return FAIL;
783  }
784 
785  if (TDS_MAX_LOGIN_STR_SZ < strlen(value_nonull)) {
786  dbperror(NULL, SYBENTLL, 0);
787  return FAIL;
788  }
789 
790  switch (which) {
791  case DBSETHOST:
792  copy_ret = tds_set_host(login->tds_login, value_nonull);
793  break;
794  case DBSETUSER:
795  copy_ret = tds_set_user(login->tds_login, value_nonull);
796  break;
797  case DBSETPWD:
798  copy_ret = tds_set_passwd(login->tds_login, value_nonull);
799  break;
800  case DBSETAPP:
801  copy_ret = tds_set_app(login->tds_login, value_nonull);
802  break;
803  case DBSETCHARSET:
804  /* TODO NULL == no conversion desired */
805  copy_ret = tds_set_client_charset(login->tds_login, value_nonull);
806  break;
807  case DBSETNATLANG:
808  copy_ret = tds_set_language(login->tds_login, value_nonull);
809  break;
810  case DBSETDBNAME:
811  copy_ret = !!tds_dstr_copy(&login->tds_login->database, value_nonull);
812  break;
813  default:
814  dbperror(NULL, SYBEASUL, 0); /* Attempt to set unknown LOGINREC field */
815  return FAIL;
816  break;
817  }
818 
819  if (!copy_ret)
820  return FAIL;
821  return SUCCEED;
822 }
823 
824 /** \internal
825  * \ingroup dblib_internal
826  * \brief Set an integer value in a \c LOGINREC structure.
827  *
828  * Called by various macros to populate \a login.
829  * \param login the \c LOGINREC* to modify.
830  * \param value the value to set it to.
831  * \param which the field to set.
832  * \retval SUCCEED the value was set.
833  * \retval FAIL anything other than \c DBSETPACKET was passed for \a which.
834  */
835 RETCODE
836 dbsetllong(LOGINREC * login, long value, int which)
837 {
838  tdsdump_log(TDS_DBG_FUNC, "dbsetllong(%p, %ld, %d)\n", login, value, which);
839 
840  if( login == NULL ) {
841  dbperror(NULL, SYBEASNL, 0);
842  return FAIL;
843  }
844 
845  switch (which) {
846  case DBSETPACKET:
847  if (0 <= value && value <= 999999) {
848  tds_set_packet(login->tds_login, (int) value);
849  return SUCCEED;
850  }
851  dbperror(0, SYBEBADPK, 0, (int) value, (int) login->tds_login->block_size);
852  return FAIL;
853  break;
854  default:
855  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbsetllong() which = %d\n", which);
856  return FAIL;
857  break;
858  }
859 }
860 
861 #if defined(DBLIB_UNIMPLEMENTED)
862 /** \internal
863  * \ingroup dblib_internal
864  * \brief Set an integer value in a \c LOGINREC structure.
865  *
866  * Called by various macros to populate \a login.
867  * \param login the \c LOGINREC* to modify.
868  * \param value the value to set it to.
869  * \param which the field to set.
870  * \retval SUCCEED the value was set.
871  * \retval FAIL anything other than \c DBSETHIER was passed for \a which.
872  */
873 RETCODE
874 dbsetlshort(LOGINREC * login, int value, int which)
875 {
876  tdsdump_log(TDS_DBG_FUNC, "dbsetlshort(%p, %d, %d)\n", login, value, which);
877 
878  if( login == NULL ) {
879  dbperror(NULL, SYBEASNL, 0);
880  return FAIL;
881  }
882 
883  switch (which) {
884  case DBSETHIER:
885  default:
886  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbsetlshort() which = %d\n", which);
887  return FAIL;
888  break;
889  }
890 }
891 #endif
892 
893 /** \internal
894  * \ingroup dblib_internal
895  * \brief Set a boolean value in a \c LOGINREC structure.
896  *
897  * Called by various macros to populate \a login.
898  * \param login the \c LOGINREC* to modify.
899  * \param value the value to set it to.
900  * \param which the field to set.
901  * \remark Only DBSETBCP is implemented.
902  * \retval SUCCEED the value was set.
903  * \retval FAIL invalid value passed for \a which.
904  * \todo DBSETNOSHORT, DBSETENCRYPT, DBSETLABELED
905  */
906 RETCODE
907 dbsetlbool(LOGINREC * login, int value, int which)
908 {
909  tdsdump_log(TDS_DBG_FUNC, "dbsetlbool(%p, %d, %d)\n", login, value, which);
910 
911  if( login == NULL ) {
912  dbperror(NULL, SYBEASNL, 0);
913  return FAIL;
914  }
915 
916  switch (which) {
917  case DBSETBCP:
918  tds_set_bulk(login->tds_login, (TDS_TINYINT) value);
919  return SUCCEED;
920  break;
921  case DBSETUTF16:
922  login->tds_login->use_utf16 = (value != 0);
923  return SUCCEED;
924  case DBSETNTLMV2:
925  login->tds_login->use_ntlmv2 = (value != 0);
926  return SUCCEED;
927  case DBSETREADONLY:
928  login->tds_login->readonly_intent = (value != 0);
929  return SUCCEED;
930  case DBSETENCRYPT:
931  case DBSETLABELED:
932  default:
933  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbsetlbool() which = %d\n", which);
934  return FAIL;
935  break;
936  }
937 }
938 
939 /**
940  * \ingroup dblib_core
941  * \brief Set TDS version for future connections
942  *
943  */
944 RETCODE
946 {
947  tdsdump_log(TDS_DBG_FUNC, "dbsetlversion(%p, %x)\n", login, version);
948 
949  if( login == NULL ) {
950  dbperror(NULL, SYBEASNL, 0);
951  return FAIL;
952  }
953 
954  assert(login->tds_login != NULL);
955 
956  switch (version) {
957  case DBVER42:
958  login->tds_login->tds_version = 0x402;
959  return SUCCEED;
960  case DBVER60:
961  login->tds_login->tds_version = 0x700;
962  return SUCCEED;
963  case DBVERSION_100:
964  tds_set_version(login->tds_login, 5, 0);
965  return SUCCEED;
966  case DBVERSION_71:
967  tds_set_version(login->tds_login, 7, 1);
968  return SUCCEED;
969  case DBVERSION_72:
970  tds_set_version(login->tds_login, 7, 2);
971  return SUCCEED;
972  case DBVERSION_73:
973  tds_set_version(login->tds_login, 7, 3);
974  return SUCCEED;
975  case DBVERSION_74:
976  tds_set_version(login->tds_login, 7, 4);
977  return SUCCEED;
978  }
979 
980  return FAIL;
981 }
982 
983 static void
985 {
986  DBSTRING *curr, *next;
987  /* tdsdump_log(TDS_DBG_FUNC, "dbstring_free(%p)\n", dbstrp); */
988 
989  if (!dbstrp)
990  return;
991 
992  curr = *dbstrp;
993  *dbstrp = NULL;
994  for (; curr; ) {
995  next = curr->strnext;
996  free(curr->strtext);
997  free(curr);
998  curr = next;
999  }
1000 }
1001 
1002 static RETCODE
1003 dbstring_concat(DBSTRING ** dbstrp, const char *p)
1004 {
1005  DBSTRING **strp = dbstrp;
1006 
1007  /* tdsdump_log(TDS_DBG_FUNC, "dbstring_concat(%p, %s)\n", *dbstrp, p); */
1008 
1009  while (*strp != NULL) {
1010  strp = &((*strp)->strnext);
1011  }
1012  if ((*strp = tds_new(DBSTRING, 1)) == NULL) {
1013  dbperror(NULL, SYBEMEM, errno);
1014  return FAIL;
1015  }
1016  (*strp)->strtotlen = (DBINT)strlen(p);
1017  if (((*strp)->strtext = tds_new(BYTE, (*strp)->strtotlen)) == NULL) {
1018  TDS_ZERO_FREE(*strp);
1019  dbperror(NULL, SYBEMEM, errno);
1020  return FAIL;
1021  }
1022  memcpy((*strp)->strtext, p, (*strp)->strtotlen);
1023  (*strp)->strnext = NULL;
1024  return SUCCEED;
1025 }
1026 
1027 static RETCODE
1028 dbstring_assign(DBSTRING ** dbstrp, const char *p)
1029 {
1030  /* tdsdump_log(TDS_DBG_FUNC, "dbstring_assign(%p, %s)\n", *dbstrp, p); */
1031 
1032  dbstring_free(dbstrp);
1033  return dbstring_concat(dbstrp, p);
1034 }
1035 
1036 static DBINT
1038 {
1039  DBINT len = 0;
1040  DBSTRING *next;
1041 
1042  /* tdsdump_log(TDS_DBG_FUNC, "dbstring_length(%p)\n", dbstr); */
1043 
1044  for (next = dbstr; next != NULL; next = next->strnext) {
1045  len += next->strtotlen;
1046  }
1047  return len;
1048 }
1049 
1050 static int
1052 {
1053 
1054  /* tdsdump_log(TDS_DBG_FUNC, "dbstring_getchar(%p, %d)\n", dbstr, i); */
1055 
1056  if (dbstr == NULL) {
1057  return -1;
1058  }
1059  if (i < 0) {
1060  return -1;
1061  }
1062  if (i < dbstr->strtotlen) {
1063  return dbstr->strtext[i];
1064  }
1065  return dbstring_getchar(dbstr->strnext, i - dbstr->strtotlen);
1066 }
1067 
1068 static char *
1070 {
1071  DBSTRING *next;
1072  int len;
1073  char *ret;
1074  char *cp;
1075 
1076  /* tdsdump_log(TDS_DBG_FUNC, "dbstring_get(%p)\n", dbstr); */
1077 
1078  if (dbstr == NULL) {
1079  return NULL;
1080  }
1081  len = dbstring_length(dbstr);
1082  if ((ret = tds_new(char, len + 1)) == NULL) {
1083  dbperror(NULL, SYBEMEM, errno);
1084  return NULL;
1085  }
1086  cp = ret;
1087  for (next = dbstr; next != NULL; next = next->strnext) {
1088  memcpy(cp, next->strtext, next->strtotlen);
1089  cp += next->strtotlen;
1090  }
1091  *cp = '\0';
1092  return ret;
1093 }
1094 
1095 static const char *const opttext[DBNUMOPTIONS] = {
1096  "parseonly",
1097  "estimate",
1098  "showplan",
1099  "noexec",
1100  "arithignore",
1101  "nocount",
1102  "arithabort",
1103  "textlimit",
1104  "browse",
1105  "offsets",
1106  "statistics",
1107  "errlvl",
1108  "confirm",
1109  "spid",
1110  "buffer",
1111  "noautofree",
1112  "rowcount",
1113  "textsize",
1114  "language",
1115  "dateformat",
1116  "prpad",
1117  "prcolsep",
1118  "prlinelen",
1119  "prlinesep",
1120  "lfconvert",
1121  "datefirst",
1122  "chained",
1123  "fipsflagger",
1124  "transaction isolation level",
1125  "auth",
1126  "identity_insert",
1127  "no_identity_column",
1128  "cnv_date2char_short",
1129  "client cursors",
1130  "set time",
1131  "quoted_identifier"
1132 };
1133 
1134 static DBOPTION *
1136 {
1137  DBOPTION *dbopts;
1138  int i;
1139 
1140  if ((dbopts = tds_new0(DBOPTION, DBNUMOPTIONS)) == NULL) {
1141  dbperror(NULL, SYBEMEM, errno);
1142  return NULL;
1143  }
1144  for (i = 0; i < DBNUMOPTIONS; i++) {
1145  dbopts[i].text = opttext[i];
1146  dbopts[i].param = NULL;
1147  dbopts[i].factive = FALSE;
1148  }
1149  dbstring_assign(&(dbopts[DBPRPAD].param), " ");
1150  dbstring_assign(&(dbopts[DBPRCOLSEP].param), " ");
1151  dbstring_assign(&(dbopts[DBPRLINELEN].param), "80");
1152  dbstring_assign(&(dbopts[DBPRLINESEP].param), "\n");
1153  dbstring_assign(&(dbopts[DBCLIENTCURSORS].param), " ");
1154  dbstring_assign(&(dbopts[DBSETTIME].param), " ");
1155  return dbopts;
1156 }
1157 
1158 /** \internal
1159  * \ingroup dblib_internal
1160  * \brief Form a connection with the server.
1161  *
1162  * Called by the \c dbopen() macro, normally. If FreeTDS was configured with \c --enable-msdblib, this
1163  * function is called by (exported) \c dbopen() function. \c tdsdbopen is so-named to avoid
1164  * namespace conflicts with other database libraries that use the same function name.
1165  * \param login \c LOGINREC* carrying the account information.
1166  * \param server name of the dataserver to connect to.
1167  * \return valid pointer on successful login.
1168  * \retval NULL insufficient memory, unable to connect for any reason.
1169  * \sa dbopen()
1170  * \todo use \c asprintf() to avoid buffer overflow.
1171  * \todo separate error messages for \em no-such-server and \em no-such-user.
1172  */
1173 DBPROCESS *
1174 tdsdbopen(LOGINREC * login, const char *server, int msdblib)
1175 {
1176  DBPROCESS *dbproc = NULL;
1177  TDSLOGIN *connection;
1178 
1179  char *tdsdump = getenv("TDSDUMP");
1180  if (tdsdump && *tdsdump) {
1181  tdsdump_open(tdsdump);
1182  tdsdump_log(TDS_DBG_FUNC, "tdsdbopen(%p, %s, [%s])\n", login, server? server : "0x0", msdblib? "microsoft" : "sybase");
1183  }
1184 
1185  /*
1186  * Sybase supports the DSQUERY environment variable and falls back to "SYBASE" if server is NULL.
1187  * Microsoft uses a NULL or "" server to indicate a local server.
1188  * FIXME: support local server for win32.
1189  */
1190  if (!server && !msdblib) {
1191  if ((server = getenv("TDSQUERY")) == NULL)
1192  if ((server = getenv("DSQUERY")) == NULL)
1193  server = "SYBASE";
1194  tdsdump_log(TDS_DBG_FUNC, "tdsdbopen: servername set to %s\n", server);
1195  }
1196 
1197  if ((dbproc = tds_new0(DBPROCESS, 1)) == NULL) {
1198  dbperror(NULL, SYBEMEM, errno);
1199  return NULL;
1200  }
1201  dbproc->msdblib = msdblib;
1202 
1204  if (dbproc->dbopts == NULL) {
1205  free(dbproc);
1206  return NULL;
1207  }
1208  tdsdump_log(TDS_DBG_FUNC, "tdsdbopen: dbproc->dbopts = %p\n", dbproc->dbopts);
1209 
1210  dbproc->dboptcmd = NULL;
1211  dbproc->avail_flag = TRUE;
1213 
1214  if (!tds_set_server(login->tds_login, server)) {
1215  dbperror(NULL, SYBEMEM, 0);
1216  free(dbproc);
1217  return NULL;
1218  }
1219  tdsdump_log(TDS_DBG_FUNC, "tdsdbopen: tds_set_server(%p, \"%s\")\n", login->tds_login, server);
1220 
1222  dbperror(NULL, SYBEMEM, 0);
1223  free(dbproc);
1224  return NULL;
1225  }
1226 
1227 
1229 
1231  dbproc->envchange_rcv = 0;
1232 
1233  dbproc->dbcurdb[0] = '\0';
1234  dbproc->servcharset[0] = '\0';
1235 
1236  tdsdump_log(TDS_DBG_FUNC, "tdsdbopen: About to call tds_read_config_info...\n");
1237 
1238  connection = tds_read_config_info(dbproc->tds_socket, login->tds_login, g_dblib_ctx.tds_ctx->locale);
1239  if (!connection) {
1240  dbclose(dbproc);
1241  return NULL;
1242  }
1243  connection->option_flag2 &= ~TDS_ODBC_ON; /* we're not an ODBC driver */
1244  tds_fix_login(connection); /* initialize from Environment variables */
1245 
1246  dbproc->chkintr = NULL;
1247  dbproc->hndlintr = NULL;
1248 
1250 
1251  /* override connection timeout if dbsetlogintime() was called */
1252  if (g_dblib_ctx.login_timeout > 0) {
1254  }
1255 
1256  /* override query timeout if dbsettime() was called */
1257  if (g_dblib_ctx.query_timeout > 0) {
1258  connection->query_timeout = g_dblib_ctx.query_timeout;
1259  }
1260 
1261  /* override TDS version if dbsetversion() was called */
1262  if (g_dbsetversion_called) {
1263  switch (g_dblib_version) {
1264  case DBVERSION_42: connection->tds_version=0x402; break;
1265  case DBVERSION_46: connection->tds_version=0x406; break;
1266  case DBVERSION_100: connection->tds_version=0x500; break;
1267  case DBVERSION_70: connection->tds_version=0x700; break;
1268  case DBVERSION_71: connection->tds_version=0x701; break;
1269  case DBVERSION_72: connection->tds_version=0x702; break;
1270  case DBVERSION_73: connection->tds_version=0x703; break;
1271  case DBVERSION_74: connection->tds_version=0x704; break;
1272  default: connection->tds_version=0; break;
1273  };
1274  }
1275 
1277 
1278  tdsdump_log(TDS_DBG_FUNC, "tdsdbopen: Calling tds_connect_and_login(%p, %p)\n",
1279  dbproc->tds_socket, connection);
1280 
1281  if (TDS_FAILED(tds_connect_and_login(dbproc->tds_socket, connection))) {
1282  tdsdump_log(TDS_DBG_ERROR, "tdsdbopen: tds_connect_and_login failed for \"%s\"!\n",
1283  tds_dstr_cstr(&connection->server_name));
1284  tds_free_login(connection);
1285  dbclose(dbproc);
1286  return NULL;
1287  }
1288  tds_free_login(connection);
1289 
1290  dbproc->dbbuf = NULL;
1291  dbproc->dbbufsz = 0;
1292 
1296 
1297  /* set the DBBUFFER capacity to nil */
1299 
1301 
1303  char *temp_filename = NULL;
1304  const int len = asprintf(&temp_filename, "%s.%d",
1306  if (len >= 0) {
1307  dbproc->ftos = fopen(temp_filename, "w");
1308  if (dbproc->ftos != NULL) {
1309  fprintf(dbproc->ftos, "/* dbopen() at %s */\n", _dbprdate(temp_filename));
1310  fflush(dbproc->ftos);
1312  }
1313  free(temp_filename);
1314  }
1315  }
1316 
1318 
1320 
1321  tdsdump_log(TDS_DBG_FUNC, "tdsdbopen: Returning dbproc = %p\n", dbproc);
1322 
1323  return dbproc;
1324 }
1325 
1326 /**
1327  * \ingroup dblib_core
1328  * \brief \c printf-like way to form SQL to send to the server.
1329  *
1330  * Forms a command string and writes to the command buffer with dbcmd().
1331  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1332  * \param fmt <tt> man vasprintf</tt> for details.
1333  * \retval SUCCEED success.
1334  * \retval FAIL insufficient memory, or dbcmd() failed.
1335  * \sa dbcmd(), dbfreebuf(), dbgetchar(), dbopen(), dbstrcpy(), dbstrlen().
1336  */
1337 RETCODE
1338 dbfcmd(DBPROCESS * dbproc, const char *fmt, ...)
1339 {
1340  va_list ap;
1341  char *s;
1342  int len;
1343  RETCODE ret;
1344 
1345  tdsdump_log(TDS_DBG_FUNC, "dbfcmd(%p, %s, ...)\n", dbproc, fmt);
1346  CHECK_CONN(FAIL);
1347  CHECK_NULP(fmt, "dbfcmd", 2, FAIL);
1348 
1349  va_start(ap, fmt);
1350  len = vasprintf(&s, fmt, ap);
1351  va_end(ap);
1352 
1353  if (len < 0) {
1354  dbperror(dbproc, SYBEMEM, errno);
1355  return FAIL;
1356  }
1357 
1358  ret = dbcmd(dbproc, s);
1359  free(s);
1360 
1361  return ret;
1362 }
1363 
1364 /**
1365  * \ingroup dblib_core
1366  * \brief \c Append SQL to the command buffer.
1367  *
1368  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1369  * \param cmdstring SQL to append to the command buffer.
1370  * \retval SUCCEED success.
1371  * \retval FAIL insufficient memory.
1372  * \remarks set command state to \c DBCMDPEND unless the command state is DBCMDSENT, in which case
1373  * it frees the command buffer. This latter may or may not be the Right Thing to do.
1374  * \sa dbfcmd(), dbfreebuf(), dbgetchar(), dbopen(), dbstrcpy(), dbstrlen().
1375  */
1376 RETCODE
1377 dbcmd(DBPROCESS * dbproc, const char cmdstring[])
1378 {
1379  size_t cmd_len, buf_len, newsz;
1380 
1381  tdsdump_log(TDS_DBG_FUNC, "dbcmd(%p, %s)\n", dbproc, cmdstring);
1382  CHECK_CONN(FAIL);
1383  CHECK_NULP(cmdstring, "dbcmd", 2, FAIL);
1384 
1385  dbproc->avail_flag = FALSE;
1386 
1387  tdsdump_log(TDS_DBG_FUNC, "dbcmd() bufsz = %d\n", dbproc->dbbufsz);
1388 
1389  if (dbproc->command_state == DBCMDSENT) {
1390  if (!dbproc->noautofree) {
1391  dbfreebuf(dbproc);
1392  }
1393  }
1394 
1395  buf_len = (dbproc->dbbufsz == 0) ? 0 : dbproc->dbbufsz - 1;
1396  cmd_len = strlen(cmdstring);
1397  newsz = buf_len + cmd_len + 1;
1398  if (newsz > 0x7fffffffu || !TDS_RESIZE(dbproc->dbbuf, newsz)) {
1399  dbperror(dbproc, SYBEMEM, errno);
1400  return FAIL;
1401  }
1402  memcpy(dbproc->dbbuf + buf_len, cmdstring, cmd_len);
1403  dbproc->dbbuf[newsz - 1] = 0;
1404  dbproc->dbbufsz = (int) newsz;
1405 
1407 
1408  return SUCCEED;
1409 }
1410 
1411 /**
1412  * \ingroup dblib_core
1413  * \brief send the SQL command to the server and wait for an answer.
1414  *
1415  * Please be patient. This function waits for the server to respond. \c dbsqlexec is equivalent
1416  * to dbsqlsend() followed by dbsqlok().
1417  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1418  * \retval SUCCEED query was processed without errors.
1419  * \retval FAIL was returned by dbsqlsend() or dbsqlok().
1420  * \sa dbcmd(), dbfcmd(), dbnextrow(), dbresults(), dbretstatus(), dbsettime(), dbsqlok(), dbsqlsend()
1421  */
1422 RETCODE
1424 {
1425  RETCODE rc = FAIL;
1426 
1427  tdsdump_log(TDS_DBG_FUNC, "dbsqlexec(%p)\n", dbproc);
1428  CHECK_CONN(FAIL);
1429 
1430  if (SUCCEED == (rc = dbsqlsend(dbproc))) {
1431  rc = dbsqlok(dbproc);
1432  }
1433  return rc;
1434 }
1435 
1436 /**
1437  * \ingroup dblib_core
1438  * \brief Change current database.
1439  *
1440  * Analagous to the unix command \c cd, dbuse() makes \a name the default database. Waits for an answer
1441  * from the server.
1442  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1443  * \param name database to use.
1444  * \retval SUCCEED query was processed without errors.
1445  * \retval FAIL query was not processed
1446  * \sa dbchange(), dbname().
1447  */
1448 RETCODE
1449 dbuse(DBPROCESS * dbproc, const char *name)
1450 {
1451  RETCODE rc;
1452  char *query;
1453 
1454  tdsdump_log(TDS_DBG_FUNC, "dbuse(%p, %s)\n", dbproc, name);
1455  CHECK_CONN(FAIL);
1456  CHECK_NULP(name, "dbuse", 2, FAIL);
1457 
1458  if (!dbproc->tds_socket)
1459  return FAIL;
1460 
1461  /* quote name */
1462  query = tds_new(char, tds_quote_id(dbproc->tds_socket, NULL, name, -1) + 6);
1463  if (!query) {
1464  dbperror(dbproc, SYBEMEM, errno);
1465  return FAIL;
1466  }
1467  strcpy(query, "use ");
1468  /* TODO PHP suggest to quote by yourself with []... what should I do ?? quote or not ?? */
1469  if (name[0] == '[' && name[strlen(name)-1] == ']')
1470  strcat(query, name);
1471  else
1472  tds_quote_id(dbproc->tds_socket, query + 4, name, -1);
1473 
1474  rc = SUCCEED;
1475  if ((dbcmd(dbproc, query) == FAIL)
1476  || (dbsqlexec(dbproc) == FAIL)
1477  || (dbresults(dbproc) == FAIL)
1478  || (dbcanquery(dbproc) == FAIL))
1479  rc = FAIL;
1480  free(query);
1481  return rc;
1482 }
1483 
1484 /**
1485  * \ingroup dblib_core
1486  * \brief Close a connection to the server and free associated resources.
1487  *
1488  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1489  * \sa dbexit(), dbopen().
1490  */
1491 void
1493 {
1494  TDSSOCKET *tds;
1495  int i;
1496  char timestr[256];
1497 
1498  tdsdump_log(TDS_DBG_FUNC, "dbclose(%p)\n", dbproc);
1500 
1501  tds = dbproc->tds_socket;
1502  if (tds) {
1503  /*
1504  * this MUST be done before socket destruction
1505  * it is possible that a TDSSOCKET is allocated on same position
1506  */
1510 
1514  }
1515  buffer_free(&(dbproc->row_buf));
1516 
1517  if (dbproc->ftos != NULL) {
1518  fprintf(dbproc->ftos, "/* dbclose() at %s */\n", _dbprdate(timestr));
1519  fclose(dbproc->ftos);
1520  }
1521 
1523  if (dbproc->hostfileinfo) {
1527  for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
1530  }
1532  }
1533  }
1534 
1535  for (i = 0; i < DBNUMOPTIONS; i++) {
1537  }
1538  free(dbproc->dbopts);
1539 
1541 
1542  for (i=0; i < MAXBINDTYPES; i++) {
1545  }
1546 
1547  dbfreebuf(dbproc);
1548  free(dbproc);
1549 }
1550 
1551 /**
1552  * \ingroup dblib_core
1553  * \brief Close server connections and free all related structures.
1554  *
1555  * \sa dbclose(), dbinit(), dbopen().
1556  * \todo breaks if ctlib/dblib used in same process.
1557  */
1558 void
1560 {
1561  TDSSOCKET *tds;
1562  DBPROCESS *dbproc;
1563  int i, list_size, count = 1;
1564 
1565  tdsdump_log(TDS_DBG_FUNC, "dbexit(void)\n");
1566 
1568 
1569  if (--g_dblib_ctx.ref_count != 0) {
1571  return;
1572  }
1573 
1574  list_size = g_dblib_ctx.connection_list_size;
1575 
1576  for (i = 0; i < list_size; i++) {
1579  if (tds) {
1580  ++count;
1584  if (dbproc) {
1585  /* avoid locking in dbclose */
1586  dbproc->tds_socket = NULL;
1587  dbclose(dbproc);
1588  }
1589  }
1590  }
1594  }
1595 
1597 
1598  dblib_release_tds_ctx(count);
1599 }
1600 
1601 typedef char prbuf_t[24];
1602 
1603 static const char *
1605 {
1606  switch(retcode) {
1607  case _DB_RES_INIT: return "_DB_RES_INIT";
1608  case _DB_RES_RESULTSET_EMPTY: return "_DB_RES_RESULTSET_EMPTY";
1609  case _DB_RES_RESULTSET_ROWS: return "_DB_RES_RESULTSET_ROWS";
1610  case _DB_RES_NEXT_RESULT: return "_DB_RES_NEXT_RESULT";
1611  case _DB_RES_NO_MORE_RESULTS: return "_DB_RES_NO_MORE_RESULTS";
1612  case _DB_RES_SUCCEED: return "_DB_RES_SUCCEED";
1613  default:
1614  sprintf(buf, "oops: %u ??", retcode);
1615  }
1616  return buf;
1617 }
1618 
1619 static const char *
1621 {
1622  switch(retcode) {
1623  case REG_ROW: return "REG_ROW/MORE_ROWS";
1624  case NO_MORE_ROWS: return "NO_MORE_ROWS";
1625  case BUF_FULL: return "BUF_FULL";
1626  case NO_MORE_RESULTS: return "NO_MORE_RESULTS";
1627  case SUCCEED: return "SUCCEED";
1628  case FAIL: return "FAIL";
1629  default:
1630  sprintf(buf, "oops: %u ??", retcode);
1631  }
1632  return buf;
1633 }
1634 
1635 static const char *
1636 prretcode(int retcode, prbuf_t buf)
1637 {
1638  switch(retcode) {
1639  case TDS_SUCCESS: return "TDS_SUCCESS";
1640  case TDS_FAIL: return "TDS_FAIL";
1641  case TDS_NO_MORE_RESULTS: return "TDS_NO_MORE_RESULTS";
1642  case TDS_CANCELLED: return "TDS_CANCELLED";
1643  default:
1644  sprintf(buf, "oops: %u ??", retcode);
1645  }
1646  return buf;
1647 }
1648 
1649 static const char *
1650 prresult_type(int result_type, prbuf_t buf)
1651 {
1652  switch(result_type) {
1653  case TDS_ROW_RESULT: return "TDS_ROW_RESULT";
1654  case TDS_PARAM_RESULT: return "TDS_PARAM_RESULT";
1655  case TDS_STATUS_RESULT: return "TDS_STATUS_RESULT";
1656  case TDS_MSG_RESULT: return "TDS_MSG_RESULT";
1657  case TDS_COMPUTE_RESULT: return "TDS_COMPUTE_RESULT";
1658  case TDS_CMD_DONE: return "TDS_CMD_DONE";
1659  case TDS_CMD_SUCCEED: return "TDS_CMD_SUCCEED";
1660  case TDS_CMD_FAIL: return "TDS_CMD_FAIL";
1661  case TDS_ROWFMT_RESULT: return "TDS_ROWFMT_RESULT";
1662  case TDS_COMPUTEFMT_RESULT: return "TDS_COMPUTEFMT_RESULT";
1663  case TDS_DESCRIBE_RESULT: return "TDS_DESCRIBE_RESULT";
1664  case TDS_DONE_RESULT: return "TDS_DONE_RESULT";
1665  case TDS_DONEPROC_RESULT: return "TDS_DONEPROC_RESULT";
1666  case TDS_DONEINPROC_RESULT: return "TDS_DONEINPROC_RESULT";
1667  case TDS_OTHERS_RESULT: return "TDS_OTHERS_RESULT";
1668  default:
1669  sprintf(buf, "oops: %u ??", result_type);
1670  }
1671  return buf;
1672 }
1673 
1674 /**
1675  * \ingroup dblib_core
1676  * \brief Set up query results.
1677  *
1678  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1679  * \retval SUCCEED Some results are available.
1680  * \retval FAIL query was not processed successfully by the server
1681  * \retval NO_MORE_RESULTS query produced no results.
1682  *
1683  * \remarks Call dbresults() after calling dbsqlexec() or dbsqlok(), or dbrpcsend() returns SUCCEED. Unless
1684  * one of them fails, dbresults will return either SUCCEED or NO_MORE_RESULTS.
1685  *
1686  * The meaning of \em results is very specific and not very intuitive. Results are created by either
1687  * - a SELECT statement
1688  * - a stored procedure
1689  *
1690  * When dbresults returns SUCCEED, therefore, it indicates the server processed the query successfully and
1691  * that one or more of these is present:
1692  * - metadata -- dbnumcols() returns 1 or more
1693  * - data -- dbnextrow() returns SUCCEED
1694  * - return status -- dbhasretstat() returns TRUE
1695  * - output parameters -- dbnumrets() returns 1 or more
1696  *
1697  * If none of the above are present, dbresults() returns NO_MORE_RESULTS.
1698  *
1699  * SUCCEED does not imply that DBROWS() will return TRUE or even that dbnumcols() will return nonzero.
1700  * A general algorithm for reading results will call dbresults() until it return NO_MORE_RESULTS (or FAIL).
1701  * An application should check for all the above kinds of results within the dbresults() loop.
1702  *
1703  * \sa dbsqlexec(), dbsqlok(), dbrpcsend(), dbcancel(), DBROWS(), dbnextrow(), dbnumcols(), dbhasretstat(), dbretstatus(), dbnumrets()
1704  */
1705 RETCODE
1707 {
1708  RETCODE erc = _dbresults(dbproc);
1709  prbuf_t buf;
1710 
1711  tdsdump_log(TDS_DBG_FUNC, "dbresults returning %d (%s)\n", erc, prdbretcode(erc, buf));
1712  return erc;
1713 }
1714 
1715 static RETCODE
1717 {
1718  TDSSOCKET *tds;
1719  int result_type = 0, done_flags;
1720  prbuf_t prbuf1, prbuf2;
1721 
1722  tdsdump_log(TDS_DBG_FUNC, "dbresults(%p)\n", dbproc);
1723  CHECK_CONN(FAIL);
1724 
1725  tds = dbproc->tds_socket;
1726 
1727  tdsdump_log(TDS_DBG_FUNC, "dbresults: dbresults_state is %d (%s)\n",
1729  switch ( dbproc->dbresults_state ) {
1730  case _DB_RES_SUCCEED:
1732  return SUCCEED;
1733  break;
1735  dbperror(dbproc, SYBERPND, 0); /* dbresults called while rows outstanding.... */
1736  return FAIL;
1737  break;
1739  return NO_MORE_RESULTS;
1740  break;
1741  default:
1742  break;
1743  }
1744 
1745  for (;;) {
1746  TDSRET retcode = tds_process_tokens(tds, &result_type, &done_flags, TDS_TOKEN_RESULTS);
1747 
1748  tdsdump_log(TDS_DBG_FUNC, "dbresults() tds_process_tokens returned %d (%s),\n\t\t\tresult_type %s\n",
1749  retcode, prretcode(retcode, prbuf1), prresult_type(result_type, prbuf2));
1750 
1751  switch (retcode) {
1752 
1753  case TDS_SUCCESS:
1754 
1755  switch (result_type) {
1756 
1757  case TDS_ROWFMT_RESULT:
1761  break;
1762 
1763  case TDS_COMPUTEFMT_RESULT:
1764  break;
1765 
1766  case TDS_ROW_RESULT:
1767  case TDS_COMPUTE_RESULT:
1768 
1770  return SUCCEED;
1771  break;
1772 
1773  case TDS_DONE_RESULT:
1774  case TDS_DONEPROC_RESULT:
1775  tdsdump_log(TDS_DBG_FUNC, "dbresults(): dbresults_state is %d (%s)\n",
1777 
1778  /* A done token signifies the end of a logical command.
1779  * There are three possibilities:
1780  * 1. Simple command with no result set, i.e. update, delete, insert
1781  * 2. Command with result set but no rows
1782  * 3. Command with result set and rows
1783  */
1784  switch (dbproc->dbresults_state) {
1785 
1786  case _DB_RES_INIT:
1787  case _DB_RES_NEXT_RESULT:
1789  if (done_flags & TDS_DONE_ERROR)
1790  return FAIL;
1791  if (result_type == TDS_DONE_RESULT)
1792  return SUCCEED;
1793  break;
1794 
1798  return SUCCEED;
1799  break;
1800  default:
1801  assert(0);
1802  break;
1803  }
1804  break;
1805 
1806  case TDS_DONEINPROC_RESULT:
1807  /*
1808  * Return SUCCEED on a command within a stored procedure
1809  * only if the command returned a result set.
1810  */
1811  switch (dbproc->dbresults_state) {
1812  case _DB_RES_INIT:
1813  case _DB_RES_NEXT_RESULT:
1815  break;
1817  case _DB_RES_RESULTSET_ROWS :
1819  return SUCCEED;
1820  break;
1822  case _DB_RES_SUCCEED:
1823  break;
1824  }
1825  break;
1826 
1827  case TDS_STATUS_RESULT:
1828  case TDS_MSG_RESULT:
1829  case TDS_DESCRIBE_RESULT:
1830  case TDS_PARAM_RESULT:
1831  default:
1832  break;
1833  }
1834 
1835  break;
1836 
1837  case TDS_NO_MORE_RESULTS:
1839  return NO_MORE_RESULTS;
1840  break;
1841 
1842  default:
1843  assert(TDS_FAILED(retcode));
1845  return FAIL;
1846  break;
1847  }
1848  }
1849 }
1850 
1851 
1852 /**
1853  * \ingroup dblib_core
1854  * \brief Return number of regular columns in a result set.
1855  *
1856  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1857  * \sa dbcollen(), dbcolname(), dbnumalts().
1858  */
1859 int
1861 {
1862  tdsdump_log(TDS_DBG_FUNC, "dbnumcols(%p)\n", dbproc);
1864 
1866  return dbproc->tds_socket->res_info->num_cols;
1867  return 0;
1868 }
1869 
1870 /**
1871  * \ingroup dblib_core
1872  * \brief Return name of a regular result column.
1873  *
1874  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1875  * \param column Nth in the result set, starting with 1.
1876  * \return pointer to ASCII null-terminated string, the name of the column.
1877  * \retval NULL \a column is not in range.
1878  * \sa dbcollen(), dbcoltype(), dbdata(), dbdatlen(), dbnumcols().
1879  * \bug Relies on ASCII column names, post iconv conversion.
1880  * Will not work as described for UTF-8 or UCS-2 clients.
1881  * But maybe it shouldn't.
1882  */
1883 char *
1885 {
1886  TDSCOLUMN *colinfo;
1887 
1888  tdsdump_log(TDS_DBG_FUNC, "dbcolname(%p, %d)\n", dbproc, column);
1889 
1890  colinfo = dbcolptr(dbproc, column);
1891  if (!colinfo)
1892  return NULL;
1893 
1894  return tds_dstr_buf(&colinfo->column_name);
1895 }
1896 
1897 static
1898 const char *
1900 {
1901  TDSCOLUMN *colinfo;
1902 
1903  tdsdump_log(TDS_DBG_FUNC, "dbcoltablename(%p, %d)\n", dbproc, column);
1905 
1906  colinfo = dbcolptr(dbproc, column);
1907  if (!colinfo)
1908  return NULL;
1909 
1910  return tds_dstr_cstr(&colinfo->table_name);
1911 }
1912 
1913 /**
1914  * \ingroup dblib_core
1915  * \brief Read a row from the row buffer.
1916  *
1917  * When row buffering is enabled (DBBUFFER option is on), the client can use dbgetrow() to re-read a row previously fetched
1918  * with dbnextrow(). The effect is to move the row pointer -- analogous to fseek() -- back to \a row.
1919  * Calls to dbnextrow() read from \a row + 1 until the buffer is exhausted, at which point it resumes
1920  * its normal behavior, except that as each row is fetched from the server, it is added to the row
1921  * buffer (in addition to being returned to the client). When the buffer is filled, dbnextrow() returns
1922  * \c FAIL until the buffer is at least partially emptied with dbclrbuf().
1923  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1924  * \param row Nth row to read, starting with 1.
1925  * \retval REG_ROW returned row is a regular row.
1926  * \returns computeid when returned row is a compute row.
1927  * \retval NO_MORE_ROWS no such row in the row buffer. Current row is unchanged.
1928  * \retval FAIL unsuccessful; row buffer may be full.
1929  * \sa dbaltbind(), dbbind(), dbclrbuf(), DBCURROW(), DBFIRSTROW(), DBLASTROW(), dbnextrow(), dbsetrow().
1930  */
1931 RETCODE
1933 {
1934  RETCODE result = FAIL;
1935  const int idx = buffer_row2idx(&dbproc->row_buf, row);
1936 
1937  tdsdump_log(TDS_DBG_FUNC, "dbgetrow(%p, %d)\n", dbproc, row);
1938  CHECK_CONN(FAIL);
1939 
1940  if (-1 == idx)
1941  return NO_MORE_ROWS;
1942 
1943  dbproc->row_buf.current = idx;
1945  result = REG_ROW;
1946 
1947  return result;
1948 }
1949 
1950 /**
1951  * \ingroup dblib_core
1952  * \brief Define substitution values to be used when binding null values.
1953  *
1954  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1955  * \param bindtype type of binding to which the substitute value will apply.
1956  * \param bindlen size of the substitute value you are supplying, in bytes.
1957  * Ignored except for CHARBIND and BINARYBIND.
1958  * \param bindval pointer to a buffer containing the substitute value.
1959  * \retval SUCCEED query was processed without errors.
1960  * \retval FAIL query was not processed
1961  * \sa dbaltbind(), dbbind(), dbconvert(), dbnullbind().
1962  */
1963 RETCODE
1964 dbsetnull(DBPROCESS * dbproc, int bindtype, int bindlen, BYTE *bindval)
1965 {
1966  BYTE *pval;
1967 
1968  tdsdump_log(TDS_DBG_FUNC, "dbsetnull(%p, %d, %d, %p)\n", dbproc, bindtype, bindlen, bindval);
1969 
1970  CHECK_CONN(FAIL);
1971  CHECK_PARAMETER(bindval, SYBENBVP, FAIL);
1972 
1973  switch (bindtype) {
1974  case DATETIMEBIND:
1975  case DECIMALBIND:
1976  case SRCDECIMALBIND:
1977  case FLT8BIND:
1978  case INTBIND:
1979  case MONEYBIND:
1980  case NUMERICBIND:
1981  case SRCNUMERICBIND:
1982  case REALBIND:
1983  case SMALLBIND:
1984  case SMALLDATETIMEBIND:
1985  case SMALLMONEYBIND:
1986  case TINYBIND:
1987  case BIGINTBIND:
1988  case DATEBIND:
1989  case TIMEBIND:
1990  case BIGDATETIMEBIND:
1991  case BIGTIMEBIND:
1992  bindlen = (int)default_null_representations[bindtype].len;
1993  break;
1994 
1995  case CHARBIND:
1996  case BINARYBIND:
1997  CHECK_PARAMETER(bindlen >= 0, SYBEBBL, FAIL);
1998  break;
1999 
2000  case NTBSTRINGBIND: bindlen = (int)strlen((char *) bindval);
2001  break;
2002  case STRINGBIND: bindlen = (int)strlen((char *) bindval);
2003  break;
2004  case VARYBINBIND: bindlen = ((DBVARYBIN*) bindval)->len;
2005  break;
2006  case VARYCHARBIND: bindlen = ((DBVARYCHAR*) bindval)->len;
2007  break;
2008 
2009 #if 0
2010  case SENSITIVITYBIND:
2011  case BOUNDARYBIND:
2012 #endif
2013  default:
2014  dbperror(dbproc, SYBEBTYP, 0);
2015  return FAIL;
2016  }
2017 
2018  if ((pval = tds_new(BYTE, bindlen)) == NULL) {
2019  dbperror(dbproc, SYBEMEM, errno);
2020  return FAIL;
2021  }
2022 
2023  /* free any prior allocation */
2024  if (dbproc->nullreps[bindtype].bindval != default_null_representations[bindtype].bindval)
2025  free((BYTE*)dbproc->nullreps[bindtype].bindval);
2026 
2027  memcpy(pval, bindval, bindlen);
2028 
2029  dbproc->nullreps[bindtype].bindval = pval;
2030  dbproc->nullreps[bindtype].len = bindlen;
2031 
2032  tdsdump_dump_buf(TDS_DBG_NETWORK, "null representation set ", pval, bindlen);
2033  return SUCCEED;
2034 }
2035 
2036 /**
2037  * \ingroup dblib_core
2038  * \brief Make a buffered row "current" without fetching it into bound variables.
2039  *
2040  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2041  * \retval MORE_ROWS row found
2042  * \retval NO_MORE_ROWS row not found
2043  * \retval FAIL \a dbproc is dead or not enabled
2044  * \sa dbaltbind(), dbbind(), dbcanquery(), dbclrbuf(), dbgetrow(), dbnextrow(), dbprrow().
2045  */
2046 STATUS
2048 {
2049  const int idx = buffer_row2idx(&dbproc->row_buf, row);
2050 
2051  tdsdump_log(TDS_DBG_FUNC, "dbsetrow(%p, %d)\n", dbproc, row);
2052  CHECK_CONN(FAIL);
2053 
2054  if (-1 == idx)
2055  return NO_MORE_ROWS;
2056 
2057  dbproc->row_buf.current = idx;
2058 
2059  /* FIXME: should determine REG_ROW or compute_id; */
2060  return REG_ROW;
2061 }
2062 
2063 /**
2064  * \ingroup dblib_core
2065  * \brief Read result row into the row buffer and into any bound host variables.
2066  *
2067  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2068  * \retval REG_ROW regular row has been read.
2069  * \returns computeid when a compute row is read.
2070  * \retval BUF_FULL reading next row would cause the buffer to be exceeded (and buffering is turned on).
2071  * No row was read from the server
2072  * \sa dbaltbind(), dbbind(), dbcanquery(), dbclrbuf(), dbgetrow(), dbprrow(), dbsetrow().
2073  */
2074 struct pivot_t;
2075 STATUS
2077 {
2078  TDSRESULTINFO *resinfo;
2079  TDSSOCKET *tds;
2080  STATUS result = FAIL;
2081  TDS_INT res_type;
2082  TDS_INT computeid;
2083  int idx; /* row buffer index. Unless DBUFFER is on, idx will always be 0. */
2084  struct pivot_t *pivot;
2085  prbuf_t prbuf;
2086 
2087  tdsdump_log(TDS_DBG_FUNC, "dbnextrow(%p)\n", dbproc);
2088  CHECK_CONN(FAIL);
2089 
2090  tds = dbproc->tds_socket;
2091  resinfo = tds->res_info;
2092 
2093  tdsdump_log(TDS_DBG_FUNC, "dbnextrow() dbresults_state = %d (%s)\n",
2095 
2096  if (!resinfo || dbproc->dbresults_state != _DB_RES_RESULTSET_ROWS) {
2097  /* no result set or result set empty (no rows) */
2098  tdsdump_log(TDS_DBG_FUNC, "leaving dbnextrow() returning %d (NO_MORE_ROWS)\n", NO_MORE_ROWS);
2099  return dbproc->row_type = NO_MORE_ROWS;
2100  }
2101 
2102  /*
2103  * Try to get the dbproc->row_buf.current item from the buffered rows, if any.
2104  * Else read from the stream, unless the buffer is exhausted.
2105  * If no rows are read, DBROWTYPE() will report NO_MORE_ROWS.
2106  */
2108  computeid = REG_ROW;
2109  if (-1 != (idx = buffer_current_index(dbproc))) {
2110  /*
2111  * Cool, the item we want is already there
2112  */
2114  res_type = TDS_ROW_RESULT;
2115 
2116  } else if (buffer_is_full(&dbproc->row_buf)) {
2117 
2118  result = BUF_FULL;
2119  res_type = TDS_ROWFMT_RESULT;
2120 
2121  } else if ((pivot = dbrows_pivoted(dbproc)) != NULL) {
2122 
2123  tdsdump_log(TDS_DBG_FUNC, "returning pivoted row\n");
2124  return dbnextrow_pivoted(dbproc, pivot);
2125 
2126  } else {
2128  TDS_INT8 row_count = TDS_NO_COUNT;
2129  bool rows_set = false;
2131 
2132  /* Get the row from the TDS stream. */
2133 again:
2134  switch (tds_process_tokens(tds, &res_type, NULL, mask)) {
2135  case TDS_SUCCESS:
2136  if (res_type == TDS_ROW_RESULT || res_type == TDS_COMPUTE_RESULT) {
2137  if (res_type == TDS_COMPUTE_RESULT)
2138  computeid = tds->current_results->computeid;
2139  /* Add the row to the row buffer, whose capacity is always at least 1 */
2140  resinfo = tds->current_results;
2141  idx = buffer_add_row(dbproc, resinfo);
2142  assert(idx != -1);
2143  result = dbproc->row_type = (res_type == TDS_ROW_RESULT)? REG_ROW : computeid;
2144 #if 0 /* TODO */
2146 #endif
2147  break;
2148  }
2149  /* allows to process trailing tokens */
2150  if (res_type == TDS_DONEINPROC_RESULT) {
2151  if (!rows_set)
2152  row_count = tds->rows_affected;
2153  rows_set = true;
2154  goto again;
2155  }
2156  /* fall through */
2157  case TDS_NO_MORE_RESULTS:
2159  result = NO_MORE_ROWS;
2160  break;
2161  default:
2162  tdsdump_log(TDS_DBG_FUNC, "unexpected: leaving dbnextrow() returning FAIL\n");
2163  return FAIL;
2164  break;
2165  }
2166  if (rows_set)
2167  tds->rows_affected = row_count;
2168  }
2169 
2170  if (res_type == TDS_ROW_RESULT || res_type == TDS_COMPUTE_RESULT) {
2171  /*
2172  * Transfer the data from the row buffer to the bound variables.
2173  */
2174  buffer_transfer_bound_data(&dbproc->row_buf, res_type, computeid, dbproc, idx);
2175  }
2176 
2177  if (res_type == TDS_COMPUTE_RESULT) {
2178  tdsdump_log(TDS_DBG_FUNC, "leaving dbnextrow() returning compute_id %d\n", result);
2179  } else {
2180  tdsdump_log(TDS_DBG_FUNC, "leaving dbnextrow() returning %s\n", prdbretcode(result, prbuf));
2181  }
2182  return result;
2183 } /* dbnextrow() */
2184 
2185 static TDS_SERVER_TYPE
2186 dblib_bound_type(int bindtype)
2187 {
2188  switch (bindtype) {
2189  case CHARBIND:
2190  case STRINGBIND:
2191  case NTBSTRINGBIND:
2192  return SYBCHAR;
2193  break;
2194  case FLT8BIND:
2195  return SYBFLT8;
2196  break;
2197  case REALBIND:
2198  return SYBREAL;
2199  break;
2200  case INTBIND:
2201  return SYBINT4;
2202  break;
2203  case SMALLBIND:
2204  return SYBINT2;
2205  break;
2206  case TINYBIND:
2207  return SYBINT1;
2208  break;
2209  case BIGINTBIND:
2210  return SYBINT8;
2211  break;
2212  case DATETIMEBIND:
2213  return SYBDATETIME;
2214  break;
2215  case SMALLDATETIMEBIND:
2216  return SYBDATETIME4;
2217  break;
2218  case DATEBIND:
2219  return SYBDATE;
2220  break;
2221  case TIMEBIND:
2222  return SYBTIME;
2223  break;
2224  case BIGDATETIMEBIND:
2225  return SYB5BIGDATETIME;
2226  break;
2227  case BIGTIMEBIND:
2228  return SYB5BIGTIME;
2229  break;
2230  case MONEYBIND:
2231  return SYBMONEY;
2232  break;
2233  case SMALLMONEYBIND:
2234  return SYBMONEY4;
2235  break;
2236  case BINARYBIND:
2237  return SYBBINARY;
2238  break;
2239  case VARYBINBIND:
2240  return SYBVARBINARY;
2241  break;
2242  case VARYCHARBIND:
2243  return SYBVARCHAR;
2244  break;
2245  case BITBIND:
2246  return SYBBIT;
2247  break;
2248  case NUMERICBIND:
2249  case SRCNUMERICBIND:
2250  case DECIMALBIND:
2251  case SRCDECIMALBIND:
2252  return SYBNUMERIC;
2253  break;
2254  case DATETIME2BIND:
2255  return SYBMSDATETIMEOFFSET;
2256  break;
2257  default:
2258  return TDS_INVALID_TYPE;
2259  }
2260 }
2261 
2262 /**
2263  * \ingroup dblib_core
2264  * \brief Convert one datatype to another.
2265  *
2266  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2267  * \param srctype datatype of the data to convert.
2268  * \param src buffer to convert
2269  * \param srclen length of \a src
2270  * \param desttype target datatype
2271  * \param dest output buffer
2272  * \param destlen size of \a dest
2273  * \returns On success, the count of output bytes in \a dest, else -1. On failure, it will call any user-supplied error handler.
2274  * \remarks Causes of failure:
2275  * - No such conversion unavailable.
2276  * - Character data output was truncated, or numerical data overflowed or lost precision.
2277  * - In converting character data to one of the numeric types, the string could not be interpreted as a number.
2278  *
2279  * Conversion functions are handled in the TDS layer.
2280  *
2281  * The main reason for this is that \c ct-lib and \c ODBC (and presumably \c DBI) need
2282  * to be able to do conversions between datatypes. This is possible because
2283  * the format of complex data (dates, money, numeric, decimal) is defined by
2284  * its representation on the wire; thus what we call \c DBMONEY is exactly its
2285  * format on the wire. CLIs that need a different representation (ODBC?)
2286  * need to convert from this format anyway, so the code would already be in
2287  * place.
2288  *
2289  * Each datatype is also defined by its Server-type so all CLIs should be
2290  * able to map native types to server types as well.
2291  *
2292  * tds_convert() copies from src to dest and returns the output data length,
2293  * period. All padding and termination is the responsibility of the API library
2294  * and is done post-conversion. The peculiar rule in dbconvert() is that
2295  * a \a destlen of -1 and a \a desttype of \c SYBCHAR means the output buffer
2296  * should be null-terminated.
2297  *
2298  * \sa dbaltbind(), dbaltbind_ps(), dbbind(), dbbind_ps(), dbconvert_ps(), dberrhandle(), dbsetnull(), dbsetversion(), dbwillconvert().
2299  * \todo What happens if client does not reset values?
2300  * \todo Microsoft and Sybase define this function differently.
2301  */
2302 DBINT
2303 dbconvert_ps(DBPROCESS * dbproc, int db_srctype, const BYTE * src, DBINT srclen,
2304  int db_desttype, BYTE * dest, DBINT destlen, DBTYPEINFO * typeinfo)
2305 {
2306  CONV_RESULT dres;
2307  DBINT ret;
2308  int i;
2309  int len;
2310  TDS_SERVER_TYPE srctype, desttype;
2311 
2312  tdsdump_log(TDS_DBG_FUNC, "dbconvert_ps(%p, %s, %p, %d, %s, %p, %d, %p)\n",
2313  dbproc, tds_prdatatype(db_srctype), src, srclen,
2314  tds_prdatatype(db_desttype), dest, destlen, typeinfo);
2315  /* dbproc and src can be NULLs */
2316  CHECK_PARAMETER(dest, SYBEACNV, -1);
2317 
2319  srctype = (TDS_SERVER_TYPE) db_srctype;
2320  DBPERROR_RETURN(!is_tds_type_valid(db_desttype), SYBEUDTY);
2321  desttype = (TDS_SERVER_TYPE) db_desttype;
2322 
2323  if (is_numeric_type(desttype)) {
2324  TDS_NUMERIC *d = &dres.n;
2325 
2326  if (typeinfo == NULL) {
2327  if (is_numeric_type(srctype)) {
2328  DBNUMERIC *s = (DBNUMERIC *) src;
2329  d->precision = s->precision;
2330  d->scale = s->scale;
2331  } else {
2332  d->precision = 18;
2333  d->scale = 0;
2334  }
2335  } else {
2336  d->precision = typeinfo->precision;
2337  d->scale = typeinfo->scale;
2338  }
2339  }
2340 
2341  if (0 == destlen)
2342  return 0;
2343 
2344  if (src == NULL || srclen == 0) {
2345  int bind = dbbindtype(desttype);
2346  int size = tds_get_size_by_type(desttype);
2347 
2348  if (bind == NTBSTRINGBIND) {
2349  if (destlen > 0) {
2350  size = destlen;
2351  bind = CHARBIND;
2352  } else {
2353  size = 1;
2354  bind = NTBSTRINGBIND;
2355  }
2356  } else if (bind == BINARYBIND) {
2357  if (destlen > 0)
2358  size = destlen;
2359  else
2360  size = 0;
2361  }
2362 
2363  dbgetnull(dbproc, bind, size, dest);
2364  return size;
2365  }
2366 
2367  /* srclen of -1 means the source data is definitely NULL terminated */
2368  if (srclen == -1)
2369  srclen = (int)strlen((const char *) src);
2370 
2371  /* often times we are asked to convert a data type to itself */
2372  if (srctype == desttype && !is_numeric_type(desttype)) {
2373  ret = -2; /* to make sure we always set it */
2374  tdsdump_log(TDS_DBG_INFO1, "dbconvert_ps() srctype == desttype\n");
2375  switch (desttype) {
2376 
2377  case SYBBINARY:
2378  case SYBVARBINARY:
2379  case SYBIMAGE:
2380  if (srclen > destlen && destlen >= 0) {
2381  dbperror(dbproc, SYBECOFL, 0);
2382  ret = -1;
2383  } else {
2384  memcpy(dest, src, srclen);
2385  if (srclen < destlen)
2386  memset(dest + srclen, 0, destlen - srclen);
2387  ret = srclen;
2388  }
2389  break;
2390 
2391  case SYBCHAR:
2392  case SYBVARCHAR:
2393  case SYBTEXT:
2394  /* srclen of -1 means the source data is definitely NULL terminated */
2395  if (srclen == -1)
2396  srclen = (int)strlen((const char *) src);
2397 
2398  switch (destlen) {
2399  case 0: /* nothing to copy */
2400  ret = 0;
2401  break;
2402  case -1: /* rtrim and null terminate */
2403  while (srclen && src[srclen - 1] == ' ') {
2404  --srclen;
2405  }
2406  /* fall thru */
2407  case -2: /* just null terminate */
2408  memcpy(dest, src, srclen);
2409  dest[srclen] = '\0';
2410  ret = srclen;
2411  break;
2412  default:
2413  assert(destlen > 0);
2414  if (destlen < 0) {
2415  dbperror(dbproc, SYBECOFL, 0);
2416  ret = -1;
2417  } else {
2418  if (srclen > destlen) {
2419  dbperror(dbproc, 50000, 0);
2420  srclen = destlen;
2421  }
2422  memcpy(dest, src, srclen);
2423  for (i = srclen; i < destlen; i++)
2424  dest[i] = ' ';
2425  ret = srclen;
2426  }
2427  break;
2428  }
2429  break;
2430  case SYBINT1:
2431  case SYBINT2:
2432  case SYBINT4:
2433  case SYBINT8:
2434  case SYBFLT8:
2435  case SYBREAL:
2436  case SYBBIT:
2437  case SYBBITN:
2438  case SYBMONEY:
2439  case SYBMONEY4:
2440  case SYBDATETIME:
2441  case SYBDATETIME4:
2442  case SYBDATE:
2443  case SYBTIME:
2444  case SYB5BIGDATETIME:
2445  case SYB5BIGTIME:
2446  case SYBUNIQUE:
2447  ret = tds_get_size_by_type(desttype);
2448  memcpy(dest, src, ret);
2449  break;
2450 
2451  case SYBMSDATE:
2452  case SYBMSTIME:
2453  case SYBMSDATETIME2:
2454  case SYBMSDATETIMEOFFSET:
2455  ret = sizeof(TDS_DATETIMEALL);
2456  memcpy(dest, src, ret);
2457  break;
2458 
2459  default:
2460  ret = -1;
2461  break;
2462  }
2463  assert(ret > -2);
2464  return ret;
2465  }
2466  /* end srctype == desttype */
2467 
2468  /*
2469  * Character types need no conversion. Just move the data.
2470  */
2471  if (is_similar_type(srctype, desttype)) {
2472  if (src && dest && srclen > 0 && destlen >= srclen) {
2473  memcpy(dest, src, srclen);
2474  return srclen;
2475  }
2476  }
2477 
2478  tdsdump_log(TDS_DBG_INFO1, "dbconvert_ps() calling tds_convert\n");
2479 
2480  len = tds_convert(g_dblib_ctx.tds_ctx, srctype, (const TDS_CHAR *) src, srclen, desttype, &dres);
2481  tdsdump_log(TDS_DBG_INFO1, "dbconvert_ps() called tds_convert returned %d\n", len);
2482 
2483  if (len < 0) {
2485  return -1;
2486  }
2487 
2488  switch (desttype) {
2489  case SYBBINARY:
2490  case SYBVARBINARY:
2491  case SYBIMAGE:
2492  if (len > destlen && destlen >= 0) {
2493  dbperror(dbproc, SYBECOFL, 0);
2494  ret = -1;
2495  } else {
2496  memcpy(dest, dres.ib, len);
2497  if (len < destlen)
2498  memset(dest + len, 0, destlen - len);
2499  ret = len;
2500  }
2501  free(dres.ib);
2502  break;
2503  case SYBINT1:
2504  case SYBINT2:
2505  case SYBINT4:
2506  case SYBINT8:
2507  case SYBFLT8:
2508  case SYBREAL:
2509  case SYBBIT:
2510  case SYBBITN:
2511  case SYBMONEY:
2512  case SYBMONEY4:
2513  case SYBDATETIME:
2514  case SYBDATETIME4:
2515  case SYBTIME:
2516  case SYBDATE:
2517  case SYB5BIGDATETIME:
2518  case SYB5BIGTIME:
2519  case SYBUNIQUE:
2520  case SYBMSDATE:
2521  case SYBMSTIME:
2522  case SYBMSDATETIME2:
2523  case SYBMSDATETIMEOFFSET:
2524  case SYBNUMERIC:
2525  case SYBDECIMAL:
2526  memcpy(dest, &(dres.ti), len);
2527  ret = len;
2528  break;
2529  case SYBCHAR:
2530  case SYBVARCHAR:
2531  case SYBTEXT:
2532  tdsdump_log(TDS_DBG_INFO1, "dbconvert_ps() outputting %d bytes character data destlen = %d \n", len, destlen);
2533 
2534  if (destlen < -2)
2535  destlen = 0; /* failure condition */
2536 
2537  switch (destlen) {
2538  case 0:
2539  ret = -1;
2540  break;
2541  case -1: /* rtrim and null terminate */
2542  for (i = len - 1; i >= 0 && dres.c[i] == ' '; --i) {
2543  len = i;
2544  }
2545  memcpy(dest, dres.c, len);
2546  dest[len] = '\0';
2547  ret = len;
2548  break;
2549  case -2: /* just null terminate */
2550  memcpy(dest, dres.c, len);
2551  dest[len] = 0;
2552  ret = len;
2553  break;
2554  default:
2555  assert(destlen > 0);
2556  if (destlen < 0) {
2557  dbperror(dbproc, SYBECOFL, 0);
2558  ret = -1;
2559  tdsdump_log(TDS_DBG_INFO1, "%d bytes type %d -> %d, destlen %d < %d required\n",
2560  srclen, srctype, desttype, destlen, len);
2561  break;
2562  }
2563  if (len > destlen) {
2564  dbperror(dbproc, 50000, 0);
2565  len = destlen;
2566  }
2567  /* else pad with blanks */
2568  memcpy(dest, dres.c, len);
2569  for (i = len; i < destlen; i++)
2570  dest[i] = ' ';
2571  ret = len;
2572 
2573  break;
2574  }
2575 
2576  free(dres.c);
2577 
2578  break;
2579  default:
2580  tdsdump_log(TDS_DBG_INFO1, "error: dbconvert_ps(): unrecognized desttype %d \n", desttype);
2581  ret = -1;
2582  break;
2583 
2584  }
2585  return (ret);
2586 }
2587 
2588 /**
2589  * \ingroup dblib_core
2590  * \brief cf. dbconvert_ps(), above
2591  *
2592  * \em Sybase: Convert numeric types.
2593  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2594  * \param srctype datatype of the data to convert.
2595  * \param src buffer to convert
2596  * \param srclen length of \a src
2597  * \param desttype target datatype
2598  * \param dest output buffer
2599  * \param destlen size of \a dest
2600  * \param typeinfo address of a \c DBTYPEINFO structure that governs the precision & scale of the output, may be \c NULL.
2601  * \sa dbaltbind(), dbaltbind_ps(), dbbind(), dbbind_ps(), dbconvert_ps(), dberrhandle(), dbsetnull(), dbsetversion(), dbwillconvert().
2602  */
2603 DBINT
2605  int srctype, const BYTE * src, DBINT srclen, int desttype, BYTE * dest, DBINT destlen)
2606 {
2607  DBTYPEINFO ti, *pti = NULL;
2608 
2609  tdsdump_log(TDS_DBG_FUNC, "dbconvert(%p)\n", dbproc);
2610  /* dbproc can be NULL*/
2611 
2613 
2614  if (is_numeric_type(desttype)) {
2615  DBNUMERIC *num;
2616 
2617  /* FIXME what happen if client do not reset values ??? */
2618  if (dbproc->msdblib) {
2619  num = (DBNUMERIC *) dest;
2620  ti.precision = num->precision;
2621  ti.scale = num->scale;
2622  pti = &ti;
2623  } else {
2624  /* for Sybase passing NULL as DBTYPEINFO is fine */
2625  }
2626  }
2627 
2628  return dbconvert_ps(dbproc, srctype, src, srclen, desttype, dest, destlen, pti);
2629 }
2630 
2631 /**
2632  * \ingroup dblib_core
2633  * \brief Tie a host variable to a resultset column.
2634  *
2635  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2636  * \param column Nth column, starting at 1.
2637  * \param vartype datatype of the host variable that will receive the data
2638  * \param varlen size of host variable pointed to \a varaddr
2639  * \param varaddr address of host variable
2640  * \retval SUCCEED everything worked.
2641  * \retval FAIL no such \a column or no such conversion possible, or target buffer too small.
2642  * \sa
2643  */
2644 RETCODE
2645 dbbind(DBPROCESS * dbproc, int column, int vartype, DBINT varlen, BYTE * varaddr)
2646 {
2647  TDSCOLUMN *colinfo = NULL;
2648  TDSRESULTINFO* results;
2649  TDS_SERVER_TYPE srctype, desttype;
2650 
2651  tdsdump_log(TDS_DBG_FUNC, "dbbind(%p, %d, %d, %d, %p)\n", dbproc, column, vartype, varlen, varaddr);
2652  CHECK_CONN(FAIL);
2653  CHECK_PARAMETER(varaddr, SYBEABNV, FAIL);
2654 
2655  results = dbproc->tds_socket->res_info;
2656 
2657  if (results == NULL || results->num_cols < column || column < 1) {
2658  dbperror(dbproc, SYBEABNC, 0);
2659  return FAIL;
2660  }
2661 
2662  if (varlen < 0) {
2663  switch (vartype) {
2664  case CHARBIND:
2665  case STRINGBIND:
2666  case NTBSTRINGBIND:
2667  case VARYCHARBIND:
2668  case VARYBINBIND:
2669  /*
2670  * No message for this error. Documentation doesn't define varlen < 0, but
2671  * experimentation with Sybase db-lib shows it's accepted as if zero.
2672  */
2673  tdsdump_log(TDS_DBG_FUNC, "dbbind: setting varlen (%d) to 0\n", varlen);
2674  varlen = 0;
2675  break;
2676  }
2677  }
2678 
2679  if (0 == varlen) { /* "Note that if varlen is 0, no padding takes place." */
2680  switch (vartype) {
2681  case CHARBIND:
2682  case STRINGBIND:
2683  case NTBSTRINGBIND:
2684  varlen = -1;
2685  break;
2686  default:
2687  break; /* dbconvert: "The destlen is ignored for all fixed-length, non-NULL data types." */
2688  }
2689  }
2690 
2691  dbproc->avail_flag = FALSE;
2692 
2693  colinfo = dbproc->tds_socket->res_info->columns[column - 1];
2694  srctype = tds_get_conversion_type(colinfo->column_type, colinfo->column_size);
2695  desttype = dblib_bound_type(vartype);
2696  if (desttype == TDS_INVALID_TYPE) {
2697  dbperror(dbproc, SYBEBTYP, 0);
2698  return FAIL;
2699  }
2700 
2701  if (!dbwillconvert(srctype, desttype)) {
2702  dbperror(dbproc, SYBEABMT, 0);
2703  return FAIL;
2704  }
2705 
2706  colinfo->column_varaddr = (char *) varaddr;
2707  colinfo->column_bindtype = vartype;
2708  colinfo->column_bindlen = varlen;
2709 
2710  return SUCCEED;
2711 } /* dbbind() */
2712 
2713 /**
2714  * \ingroup dblib_core
2715  * \brief set name and location of the \c interfaces file FreeTDS should use to look up a servername.
2716  *
2717  * Does not affect lookups or location of \c freetds.conf.
2718  * \param filename name of \c interfaces
2719  * \sa dbopen()
2720  */
2721 void
2722 dbsetifile(char *filename)
2723 {
2724  tdsdump_log(TDS_DBG_FUNC, "dbsetifile(%s)\n", filename? filename : "0x00");
2725  if (filename == NULL) {
2726  dbperror(NULL, SYBENULP, 0);
2727  return;
2728  }
2729  tds_set_interfaces_file_loc(filename);
2730 }
2731 
2732 /**
2733  * \ingroup dblib_core
2734  * \brief Tie a null-indicator to a regular result column.
2735  *
2736  *
2737  * When a row is fetched, the indicator variable tells the state of the column's data.
2738  *
2739  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2740  * \param column Nth column in the result set, starting with 1.
2741  * \param indicator address of host variable.
2742  * \retval SUCCEED variable accepted.
2743  * \retval FAIL \a indicator is NULL or \a column is out of range.
2744  * \remarks Contents of \a indicator are set with \c dbnextrow(). Possible values are:
2745  * - 0 \a column bound successfully
2746  * - -1 \a column is NULL.
2747  * - >0 true length of data, had \a column not been truncated due to insufficient space in the columns bound host variable .
2748  * \sa dbanullbind(), dbbind(), dbdata(), dbdatlen(), dbnextrow().
2749  */
2750 RETCODE
2752 {
2753  TDSCOLUMN *colinfo;
2754 
2755  tdsdump_log(TDS_DBG_FUNC, "dbnullbind(%p, %d, %p)\n", dbproc, column, indicator);
2756 
2757  colinfo = dbcolptr(dbproc, column);
2758  if (!colinfo)
2759  return FAIL; /* dbcolptr sent SYBECNOR, Column number out of range */
2760 
2761  colinfo->column_nullbind = (TDS_SMALLINT *)indicator;
2762  return SUCCEED;
2763 }
2764 
2765 /**
2766  * \ingroup dblib_core
2767  * \brief Tie a null-indicator to a compute result column.
2768  *
2769  *
2770  * When a row is fetched, the indicator variable tells the state of the column's data.
2771  *
2772  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2773  * \param computeid identifies which one of potientially many compute rows is meant. The first compute
2774  * clause has \a computeid == 1.
2775  * \param column Nth column in the result set, starting with 1.
2776  * \param indicator address of host variable.
2777  * \retval SUCCEED variable accepted.
2778  * \retval FAIL \a indicator is NULL or \a column is out of range.
2779  * \remarks Contents of \a indicator are set with \c dbnextrow(). Possible values are:
2780  * - 0 \a column bound successfully
2781  * - -1 \a column is NULL.
2782  * - >0 true length of data, had \a column not been truncated due to insufficient space in the columns bound host variable .
2783  * \sa dbadata(), dbadlen(), dbaltbind(), dbnextrow(), dbnullbind().
2784  * \todo Never fails, but only because failure conditions aren't checked.
2785  */
2786 RETCODE
2787 dbanullbind(DBPROCESS * dbproc, int computeid, int column, DBINT * indicator)
2788 {
2789  TDSCOLUMN *curcol;
2790 
2791  tdsdump_log(TDS_DBG_FUNC, "dbanullbind(%p, %d, %d, %p)\n", dbproc, computeid, column, indicator);
2792 
2793  curcol = dbacolptr(dbproc, computeid, column, 1);
2794  if (!curcol)
2795  return FAIL;
2796 
2797  /*
2798  * XXX Need to check for possibly problems before assuming
2799  * everything is okay
2800  */
2801  curcol->column_nullbind = (TDS_SMALLINT *)indicator;
2802 
2803  return SUCCEED;
2804 }
2805 
2806 /**
2807  * \ingroup dblib_core
2808  * \brief Indicates whether or not the count returned by dbcount is real (Microsoft-compatibility feature).
2809  *
2810  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2811  * \returns TRUE if the count returned by dbcount is real or FALSE if the count returned by dbcount is not real.
2812  * \sa DBCOUNT(), dbcount().
2813  */
2814 BOOL
2816 {
2817  tdsdump_log(TDS_DBG_FUNC, "dbiscount(%p)\n", dbproc);
2819 
2821 }
2822 
2823 /**
2824  * \ingroup dblib_core
2825  * \brief Get count of rows processed
2826  *
2827  *
2828  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2829  * \returns
2830  * - for insert/update/delete, count of rows affected.
2831  * - for select, count of rows returned, after all rows have been fetched.
2832  * \sa DBCOUNT(), dbnextrow(), dbresults().
2833  */
2834 DBINT
2836 {
2837  tdsdump_log(TDS_DBG_FUNC, "dbcount(%p)\n", dbproc);
2839 
2841  return -1;
2843 }
2844 
2845 /**
2846  * \ingroup dblib_core
2847  * \brief Clear \a n rows from the row buffer.
2848  *
2849  *
2850  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2851  * \param n number of rows to remove, >= 0.
2852  * \sa dbgetrow(), dbnextrow(), dbsetopt().
2853  */
2854 void
2856 {
2857  tdsdump_log(TDS_DBG_FUNC, "dbclrbuf(%p, %d)\n", dbproc, n);
2859 
2860  if (n <= 0)
2861  return;
2862 
2863  if (dbproc->dbopts[DBBUFFER].factive) {
2864  DBPROC_ROWBUF * buf = &(dbproc->row_buf);
2865  int count = buffer_count(buf);
2866  if (n >= count)
2867  n = count - 1;
2869  }
2870 }
2871 
2872 /**
2873  * \ingroup dblib_core
2874  * \brief Test whether or not a datatype can be converted to another datatype
2875  *
2876  * \param srctype type converting from
2877  * \param desttype type converting to
2878  * \remarks dbwillconvert() lies sometimes. Some datatypes \em should be convertible but aren't yet in our implementation.
2879  * Legal unimplemented conversions return \em TRUE.
2880  * \retval TRUE convertible, or should be.
2881  * \retval FAIL not convertible.
2882  * \sa dbaltbind(), dbbind(), dbconvert(), dbconvert_ps(), \c src/dblib/unittests/convert().c().
2883  */
2884 DBBOOL
2885 dbwillconvert(int srctype, int desttype)
2886 {
2887  tdsdump_log(TDS_DBG_FUNC, "dbwillconvert(%s, %s)\n", tds_prdatatype(srctype), tds_prdatatype(desttype));
2888  return tds_willconvert(srctype, desttype) ? TRUE : FALSE;
2889 }
2890 
2891 /**
2892  * \ingroup dblib_core
2893  * \brief Get the datatype of a regular result set column.
2894  *
2895  *
2896  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2897  * \param column Nth in the result set, starting from 1.
2898  * \returns \c SYB* datetype token value, or zero if \a column out of range
2899  * \sa dbcollen(), dbcolname(), dbdata(), dbdatlen(), dbnumcols(), dbprtype(), dbvarylen().
2900  */
2901 int
2903 {
2904  TDSCOLUMN *colinfo;
2905 
2906  tdsdump_log(TDS_DBG_FUNC, "dbcoltype(%p, %d)\n", dbproc, column);
2907 
2908  colinfo = dbcolptr(dbproc, column);
2909  if (!colinfo)
2910  return -1;
2911 
2912  switch (colinfo->column_type) {
2913  case SYBVARCHAR:
2914  return SYBCHAR;
2915  case SYBVARBINARY:
2916  return SYBBINARY;
2917  default:
2918  return tds_get_conversion_type(colinfo->column_type,
2919  colinfo->column_size);
2920  }
2921 }
2922 
2923 /**
2924  * \ingroup dblib_core
2925  * \brief Get user-defined datatype of a regular result column.
2926  *
2927  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2928  * \param column Nth in the result set, starting from 1.
2929  * \returns \c SYB* datetype token value, or -1 if \a column out of range
2930  * \sa dbaltutype(), dbcoltype().
2931  */
2932 int
2934 {
2935  TDSCOLUMN *colinfo;
2936 
2937  tdsdump_log(TDS_DBG_FUNC, "dbcolutype(%p, %d)\n", dbproc, column);
2938 
2939  colinfo = dbcolptr(dbproc, column);
2940  if (!colinfo)
2941  return -1;
2942 
2943  return colinfo->column_usertype;
2944 }
2945 
2946 /**
2947  * \ingroup dblib_core
2948  * \brief Get precision and scale information for a regular result column.
2949  *
2950  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2951  * \param column Nth in the result set, starting from 1.
2952  * \return Pointer to a DBTYPEINFO structure . NULL \a column is out of range.
2953  * \sa dbcollen(), dbcolname(), dbcoltype(), dbdata(), dbdatlen(), dbnumcols(), dbprtype(), dbvarylen().
2954  */
2955 DBTYPEINFO *
2957 {
2958  /* moved typeinfo from static into dbproc structure to make thread safe. (mlilback 11/7/01) */
2959  TDSCOLUMN *colinfo;
2960 
2961  tdsdump_log(TDS_DBG_FUNC, "dbcoltypeinfo(%p, %d)\n", dbproc, column);
2962 
2963  colinfo = dbcolptr(dbproc, column);
2964  if (!colinfo)
2965  return NULL;
2966 
2967  dbproc->typeinfo.precision = colinfo->column_prec;
2968  dbproc->typeinfo.scale = colinfo->column_scale;
2969  return &dbproc->typeinfo;
2970 }
2971 
2972 /**
2973  * \brief Get a bunch of column attributes with a single call (Microsoft-compatibility feature).
2974  *
2975  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2976  * \param type must be CI_REGULAR or CI_ALTERNATE (CI_CURSOR is defined by the vendor, but is not yet implemented).
2977  * \param column Nth in the result set, starting from 1.
2978  * \param computeid (ignored)
2979  * \param pdbcol address of structure to be populated by this function.
2980  * \return SUCCEED or FAIL.
2981  * \sa dbcolbrowse(), dbqual(), dbtabbrowse(), dbtabcount(), dbtabname(), dbtabsource(), dbtsnewlen(), dbtsnewval(), dbtsput().
2982  * \todo Support cursor rows.
2983  */
2984 RETCODE
2986 {
2987  DBTYPEINFO *ps;
2989  TDSCOLUMN *colinfo;
2990  TDS_UINT i;
2991 
2992  tdsdump_log(TDS_DBG_FUNC, "dbcolinfo(%p, %d, %d, %d, %p)\n", dbproc, type, column, computeid, pdbcol);
2993 
2994  colinfo = dbcolptr(dbproc, column);
2995  if (!colinfo)
2996  return FAIL;
2997 
2998  CHECK_NULP(pdbcol, "dbcolinfo", 5, FAIL);
2999 
3000  if (type == CI_REGULAR) {
3001 
3002  strlcpy(pdbcol->Name, dbcolname(dbproc, column), sizeof(pdbcol->Name));
3003  strlcpy(pdbcol->ActualName, dbcolname(dbproc, column), sizeof(pdbcol->ActualName));
3005  sizeof(pdbcol->TableName));
3006 
3007  pdbcol->Type = dbcoltype(dbproc, column);
3008  pdbcol->UserType = dbcolutype(dbproc, column);
3009  pdbcol->MaxLength = dbcollen(dbproc, column);
3010  pdbcol->Null = _dbnullable(dbproc, column);
3011  pdbcol->VarLength = dbvarylen(dbproc, column);
3012 
3013  ps = dbcoltypeinfo(dbproc, column);
3014 
3015  if( ps ) {
3016  pdbcol->Precision = ps->precision;
3017  pdbcol->Scale = ps->scale;
3018  }
3019 
3020  pdbcol->Updatable = colinfo->column_writeable ? TRUE : FALSE;
3021  pdbcol->Identity = colinfo->column_identity ? TRUE : FALSE;
3022 
3023  return SUCCEED;
3024  }
3025 
3026  if (type == CI_ALTERNATE) {
3027 
3028  if (computeid == 0)
3029  return FAIL;
3030 
3031  for (i = 0;; ++i) {
3032  if (i >= dbproc->tds_socket->num_comp_info)
3033  return FAIL;
3035  if (info->computeid == computeid)
3036  break;
3037  }
3038 
3039  /* if either the compute id or the column number are invalid, return -1 */
3040  if (column < 1 || column > info->num_cols)
3041  return FAIL;
3042 
3043  colinfo = info->columns[column - 1];
3044 
3045  strlcpy(pdbcol->Name, tds_dstr_cstr(&colinfo->column_name), sizeof(pdbcol->Name));
3046  strlcpy(pdbcol->ActualName, tds_dstr_cstr(&colinfo->column_name), sizeof(pdbcol->ActualName));
3047 
3048  pdbcol->Type = dbalttype(dbproc, computeid, column);
3049  pdbcol->UserType = dbaltutype(dbproc, computeid, column);
3050  pdbcol->MaxLength = dbaltlen(dbproc, computeid, column);
3051  if (colinfo->column_nullable)
3052  pdbcol->Null = TRUE;
3053  else
3054  pdbcol->Null = FALSE;
3055 
3056  pdbcol->VarLength = FALSE;
3057 
3058  if (colinfo->column_nullable
3059  || is_nullable_type(colinfo->column_type))
3060  pdbcol->VarLength = TRUE;
3061 
3062  pdbcol->Precision = colinfo->column_prec;
3063  pdbcol->Scale = colinfo->column_scale;
3064 
3065  pdbcol->Updatable = colinfo->column_writeable ? TRUE : FALSE ;
3066  pdbcol->Identity = colinfo->column_identity ? TRUE : FALSE ;
3067 
3068  return SUCCEED;
3069  }
3070 
3071  return FAIL;
3072 }
3073 
3074 /**
3075  * \ingroup dblib_core
3076  * \brief Get base database column name for a result set column.
3077  *
3078  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3079  * \param column Nth in the result set, starting from 1.
3080  * \return pointer to ASCII null-terminated string, the name of the column. On error, NULL.
3081  * \sa dbcolbrowse(), dbqual(), dbtabbrowse(), dbtabcount(), dbtabname(), dbtabsource(), dbtsnewlen(), dbtsnewval(), dbtsput().
3082  */
3083 char *
3085 {
3086  TDSCOLUMN *colinfo;
3087 
3088  tdsdump_log(TDS_DBG_FUNC, "dbcolsource(%p, %d)\n", dbproc, column);
3089 
3090  colinfo = dbcolptr(dbproc, column);
3091  if (!colinfo)
3092  return NULL;
3093 
3094  return tds_dstr_buf(tds_dstr_isempty(&colinfo->table_column_name) ?
3095  &colinfo->column_name :
3096  &colinfo->table_column_name);
3097 }
3098 
3099 /**
3100  * \ingroup dblib_core
3101  * \brief Get size of a regular result column.
3102  *
3103  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3104  * \param column Nth in the result set, starting from 1.
3105  * \return size of the column (not of data in any particular row). On error, -1.
3106  * \sa dbcolname(), dbcoltype(), dbdata(), dbdatlen(), dbnumcols().
3107  */
3108 DBINT
3110 {
3111  TDSCOLUMN *colinfo;
3112 
3113  tdsdump_log(TDS_DBG_FUNC, "dbcollen(%p, %d)\n", dbproc, column);
3114 
3115  colinfo = dbcolptr(dbproc, column);
3116  if (!colinfo)
3117  return -1;
3118 
3119  return colinfo->column_size;
3120 }
3121 
3122 /**
3123  * \ingroup dblib_core
3124  * \brief Get size of a result column needed to print column.
3125  *
3126  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3127  * \param column Nth in the result set, starting from 1.
3128  * \return size of the column in characters (not of data in any particular row). On error, -1.
3129  * \sa dbcolname(), dbcoltype(), dbdata(), dbdatlen(), dbnumcols().
3130  */
3131 DBINT
3133 {
3134  TDSCOLUMN *colinfo;
3135 
3136  tdsdump_log(TDS_DBG_FUNC, "dbprcollen(%p, %d)\n", dbproc, column);
3137 
3138  colinfo = dbcolptr(dbproc, column);
3139  if (!colinfo)
3140  return 0;
3141 
3142  return _get_printable_size(colinfo);
3143 }
3144 
3145 
3146 /* dbvarylen(), pkleef@openlinksw.com 01/21/02 */
3147 /**
3148  * \ingroup dblib_core
3149  * \brief Determine whether a column can vary in size.
3150  *
3151  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3152  * \param column Nth in the result set, starting from 1.
3153  * \retval TRUE datatype of column can vary in size, or is nullable.
3154  * \retval FALSE datatype of column is fixed and is not nullable.
3155  * \sa dbcollen(), dbcolname(), dbcoltype(), dbdata(), dbdatlen(), dbnumcols(), dbprtype().
3156  */
3157 DBINT
3159 {
3160  TDSCOLUMN *colinfo;
3161 
3162  tdsdump_log(TDS_DBG_FUNC, "dbvarylen(%p, %d)\n", dbproc, column);
3163 
3164  colinfo = dbcolptr(dbproc, column);
3165  if (!colinfo)
3166  return FALSE;
3167 
3168  if (colinfo->column_nullable)
3169  return TRUE;
3170 
3171  switch (colinfo->column_type) {
3172  /* variable length fields */
3173  case SYBNVARCHAR:
3174  case SYBVARBINARY:
3175  case SYBVARCHAR:
3176  return TRUE;
3177 
3178  /* types that can be null */
3179  case SYBBITN:
3180  case SYBDATETIMN:
3181  case SYBDECIMAL:
3182  case SYBFLTN:
3183  case SYBINTN:
3184  case SYBMONEYN:
3185  case SYBNUMERIC:
3186  return TRUE;
3187 
3188  /* blob types */
3189  case SYBIMAGE:
3190  case SYBNTEXT:
3191  case SYBTEXT:
3192  return TRUE;
3193 
3194  default:
3195  return FALSE;
3196  }
3197 }
3198 
3199 /**
3200  * \ingroup dblib_core
3201  * \brief Get size of current row's data in a regular result column.
3202  *
3203  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3204  * \param column Nth in the result set, starting from 1.
3205  * \return size of the data, in bytes.
3206  * \sa dbcollen(), dbcolname(), dbcoltype(), dbdata(), dbnumcols().
3207  */
3208 DBINT
3210 {
3211  DBINT len;
3212  TDSCOLUMN *colinfo;
3213 
3214  tdsdump_log(TDS_DBG_FUNC, "dbdatlen(%p, %d)\n", dbproc, column);
3215 
3216  colinfo = dbcolptr(dbproc, column);
3217  if (!colinfo)
3218  return -1;
3219 
3220  len = (colinfo->column_cur_size < 0)? 0 : colinfo->column_cur_size;
3221 
3222  tdsdump_log(TDS_DBG_FUNC, "dbdatlen() type = %d, len= %d\n", colinfo->column_type, len);
3223 
3224  return len;
3225 }
3226 
3227 /**
3228  * \ingroup dblib_core
3229  * \brief Get address of data in a regular result column.
3230  *
3231  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3232  * \param column Nth in the result set, starting from 1.
3233  * \return pointer the data, or NULL if data are NULL, or if \a column is out of range.
3234  * \sa dbbind(), dbcollen(), dbcolname(), dbcoltype(), dbdatlen(), dbnumcols().
3235  */
3236 BYTE *
3238 {
3239  tdsdump_log(TDS_DBG_FUNC, "dbdata(%p, %d)\n", dbproc, column);
3240 
3241  return _dbcoldata(dbcolptr(dbproc, column));
3242 }
3243 
3244 /** \internal
3245  * \ingroup dblib_internal
3246  * \brief Return data from a column
3247  *
3248  * \param colinfo contains information on a result column.
3249  * \return pointer to the data, or NULL if data are NULL
3250  * \sa dbdata(), dbretdata()
3251  */
3252 static BYTE *
3254 {
3255  BYTE *res;
3256  const static BYTE empty[1] = { 0 };
3257 
3258  if (!colinfo || colinfo->column_cur_size < 0)
3259  return NULL;
3260 
3261  res = colinfo->column_data;
3262  if (is_blob_col(colinfo))
3263  res = (BYTE *) ((TDSBLOB *) res)->textvalue;
3264  if (!res)
3265  return (BYTE *) empty;
3266  return res;
3267 }
3268 
3269 /**
3270  * \ingroup dblib_core
3271  * \brief Cancel the current command batch.
3272  *
3273  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3274  * \retval SUCCEED always.
3275  * \sa dbcanquery(), dbnextrow(), dbresults(), dbsetinterrupt(), dbsqlexec(), dbsqlok(), dbsqlsend().
3276  * \todo Check for failure and return accordingly.
3277  */
3278 RETCODE
3280 {
3281  TDSSOCKET *tds;
3282 
3283  tdsdump_log(TDS_DBG_FUNC, "dbcancel(%p)\n", dbproc);
3284  CHECK_CONN(FAIL);
3285 
3286  tds = dbproc->tds_socket;
3287 
3290 
3291  return SUCCEED;
3292 }
3293 
3294 /**
3295  * \ingroup dblib_core
3296  * \brief Determine size buffer required to hold the results returned by dbsprhead(), dbsprline(), and dbspr1row().
3297  *
3298  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3299  * \return size of buffer requirement, in bytes.
3300  * \remarks An esoteric function.
3301  * \sa dbprhead(), dbprrow(), dbspr1row(), dbsprhead(), dbsprline().
3302  */
3303 DBINT
3305 {
3306  TDSSOCKET *tds;
3307  int col, len = 0;
3308 
3309  tdsdump_log(TDS_DBG_FUNC, "dbspr1rowlen(%p)\n", dbproc);
3312 
3313  tds = dbproc->tds_socket;
3314 
3315  for (col = 0; col < tds->res_info->num_cols; col++) {
3316  TDSCOLUMN *colinfo = tds->res_info->columns[col];
3317  int collen = _get_printable_size(colinfo);
3318  int namlen = (int) tds_dstr_len(&colinfo->column_name);
3319 
3320  len += collen > namlen ? collen : namlen;
3321 
3322  if (col > 0) /* allow for the space between columns */
3324  }
3325 
3326  return ++len; /* allow for the nul */
3327 }
3328 
3329 /**
3330  * \ingroup dblib_core
3331  * \brief Print a regular result row to a buffer.
3332  *
3333  * Fills a buffer with one data row, represented as a null-terminated ASCII string. Helpful for debugging.
3334  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3335  * \param buffer \em output: Address of a buffer to hold ASCII null-terminated string.
3336  * \param buf_len size of \a buffer, in bytes.
3337  * \retval SUCCEED on success.
3338  * \retval FAIL trouble encountered.
3339  * \sa dbclropt(), dbisopt(), dbprhead(), dbprrow(), dbspr1rowlen(), dbsprhead(), dbsprline().
3340  */
3341 RETCODE
3343 {
3344  TDSSOCKET *tds;
3345  TDSDATEREC when;
3346  int i, c, col;
3347  DBINT len;
3348 
3349  tdsdump_log(TDS_DBG_FUNC, "dbspr1row(%p, %s, %d)\n", dbproc, buffer, buf_len);
3350  CHECK_CONN(FAIL);
3351  CHECK_NULP(buffer, "dbspr1row", 2, FAIL);
3352 
3353  if (!dbproc->tds_socket)
3354  return FAIL;
3355 
3356  tds = dbproc->tds_socket;
3357 
3358  for (col = 0; col < tds->res_info->num_cols; col++) {
3359  size_t padlen, collen, namlen;
3360  TDSCOLUMN *colinfo = tds->res_info->columns[col];
3361  if (colinfo->column_cur_size < 0) {
3362  len = 4;
3363  if (buf_len <= len) {
3364  return FAIL;
3365  }
3366  strcpy(buffer, "NULL");
3367  } else {
3368  TDS_SERVER_TYPE desttype, srctype;
3369 
3370  desttype = dblib_bound_type(STRINGBIND);
3371  srctype = tds_get_conversion_type(colinfo->column_type, colinfo->column_size);
3372  if (is_datetime_type(srctype)) {
3373  tds_datecrack(srctype, dbdata(dbproc, col + 1), &when);
3374  len = (int)tds_strftime(buffer, buf_len, STD_DATETIME_FMT, &when, 3);
3375  } else {
3376  len = dbconvert(dbproc, srctype, dbdata(dbproc, col + 1), dbdatlen(dbproc, col + 1),
3377  desttype, (BYTE *) buffer, buf_len);
3378  }
3379  if (len == -1) {
3380  return FAIL;
3381  }
3382  }
3383  buffer += len;
3384  buf_len -= len;
3385  collen = _get_printable_size(colinfo);
3386  namlen = tds_dstr_len(&colinfo->column_name);
3387  padlen = (collen > namlen ? collen : namlen) - len;
3388  if ((c = dbstring_getchar(dbproc->dbopts[DBPRPAD].param, 0)) == -1) {
3389  c = ' ';
3390  }
3391  for (; padlen > 0; padlen--) {
3392  if (buf_len < 1) {
3393  return FAIL;
3394  }
3395  *buffer++ = c;
3396  buf_len--;
3397  }
3398  if ((col + 1) < tds->res_info->num_cols) {
3399  i = 0;
3400  while ((c = dbstring_getchar(dbproc->dbopts[DBPRCOLSEP].param, i)) != -1) {
3401  if (buf_len < 1) {
3402  return FAIL;
3403  }
3404  *buffer++ = c;
3405  buf_len--;
3406  i++;
3407  }
3408  }
3409  }
3410  if (buf_len < 1) {
3411  return FAIL;
3412  }
3413  *buffer = '\0';
3414  return SUCCEED;
3415 }
3416 
3417 /**
3418  * \ingroup dblib_core
3419  * \brief Print a result set to stdout.
3420  *
3421  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3422  * \sa dbbind(), dbnextrow(), dbprhead(), dbresults(), dbspr1row(), dbsprhead(), dbsprline().
3423  */
3424 RETCODE
3426 {
3427  TDSCOLUMN *colinfo;
3428  TDSRESULTINFO *resinfo;
3429  TDSSOCKET *tds;
3430  int i, col;
3431  size_t collen, namlen, len;
3432  char dest[8192];
3433  int desttype, srctype;
3434  TDSDATEREC when;
3435  STATUS status;
3436  ssize_t padlen;
3437  int c;
3438  int selcol;
3439  int linechar;
3440  int op;
3441  const char *opname, *p;
3442 
3443  /* these are for compute rows */
3444  DBINT computeid, num_cols, colid;
3445  TDS_SMALLINT *col_printlens = NULL;
3446 
3447  tdsdump_log(TDS_DBG_FUNC, "dbprrow(%p)\n", dbproc);
3448  CHECK_CONN(FAIL);
3449 
3450  tds = dbproc->tds_socket;
3451 
3452  while ((status = dbnextrow(dbproc)) != NO_MORE_ROWS) {
3453 
3454  if (status == FAIL) {
3455  free(col_printlens);
3456  return FAIL;
3457  }
3458 
3459  if (status == REG_ROW) {
3460 
3461  resinfo = tds->res_info;
3462 
3463  if (col_printlens == NULL) {
3464  if ((col_printlens = tds_new0(TDS_SMALLINT, resinfo->num_cols)) == NULL) {
3465  dbperror(dbproc, SYBEMEM, errno);
3466  return FAIL;
3467  }
3468  }
3469 
3470  for (col = 0; col < resinfo->num_cols; col++) {
3471  colinfo = resinfo->columns[col];
3472  if (colinfo->column_cur_size < 0) {
3473  len = 4;
3474  strcpy(dest, "NULL");
3475  } else {
3476  desttype = dblib_bound_type(STRINGBIND);
3477  srctype = tds_get_conversion_type(colinfo->column_type, colinfo->column_size);
3478  if (is_datetime_type(srctype)) {
3479  tds_datecrack(srctype, dbdata(dbproc, col + 1), &when);
3480  len = (int)tds_strftime(dest, sizeof(dest), STD_DATETIME_FMT, &when, 3);
3481  } else {
3482  len = dbconvert(dbproc, srctype, dbdata(dbproc, col + 1), dbdatlen(dbproc, col + 1),
3483  desttype, (BYTE *) dest, sizeof(dest));
3484  }
3485  }
3486 
3487  p = memchr(dest, '\0', len);
3488  fwrite(dest, 1, p == NULL ? len : (p - dest),
3489  stdout);
3490  collen = _get_printable_size(colinfo);
3491  namlen = tds_dstr_len(&colinfo->column_name);
3492  padlen = (collen > namlen ? collen : namlen) - len;
3493 
3495  for (; c > -1 && padlen > 0; padlen--) {
3496  putchar(c);
3497  }
3498 
3499  if ((col + 1) < resinfo->num_cols) {
3500  i = 0;
3501  while ((c = dbstring_getchar(dbproc->dbopts[DBPRCOLSEP].param, i++)) != -1) {
3502  putchar(c);
3503  }
3504  }
3505  col_printlens[col] = collen;
3506  }
3507  i = 0;
3508  while ((c = dbstring_getchar(dbproc->dbopts[DBPRLINESEP].param, i++)) != -1) {
3509  putchar(c);
3510  }
3511 
3512  } else if (col_printlens == NULL) {
3513  return FAIL;
3514  } else {
3515 
3516  computeid = status;
3517 
3518  for (i = 0;; ++i) {
3519  if ((TDS_UINT) i >= tds->num_comp_info) {
3520  free(col_printlens);
3521  return FAIL;
3522  }
3523  resinfo = tds->comp_info[i];
3524  if (resinfo->computeid == computeid)
3525  break;
3526  }
3527 
3528  num_cols = dbnumalts(dbproc, computeid);
3529  tdsdump_log(TDS_DBG_FUNC, "dbprrow num compute cols = %d\n", num_cols);
3530 
3531  i = 0;
3532  while ((c = dbstring_getchar(dbproc->dbopts[DBPRLINESEP].param, i++)) != -1) {
3533  putchar(c);
3534  }
3535  for (selcol = col = 1; col <= num_cols; col++) {
3536  tdsdump_log(TDS_DBG_FUNC, "dbprrow calling dbaltcolid(%d,%d)\n", computeid, col);
3537  colid = dbaltcolid(dbproc, computeid, col);
3538  /*
3539  * The pad character is pointed to by dbopts[DBPRPAD].param. If that pointer
3540  * is NULL -- meaning padding is turned off -- dbstring_getchar returns -1.
3541  */
3542  while (selcol < colid) {
3543  for (i = 0; i < col_printlens[selcol - 1]; i++) {
3544  if ((c = dbstring_getchar(dbproc->dbopts[DBPRPAD].param, 0)) >= 0)
3545  putchar(c);
3546  }
3547  selcol++;
3548  i = 0;
3549  while ((c = dbstring_getchar(dbproc->dbopts[DBPRCOLSEP].param, i++)) != -1) {
3550  putchar(c);
3551  }
3552  }
3553  op = dbaltop(dbproc, computeid, col);
3554  opname = dbprtype(op);
3555  printf("%s", opname);
3556  for (i = 0;
3557  i < (col_printlens[selcol - 1]
3558  - (int) strlen(opname));
3559  i++) {
3560  if ((c = dbstring_getchar(dbproc->dbopts[DBPRPAD].param, 0)) >= 0)
3561  putchar(c);
3562  }
3563  selcol++;
3564  if ((colid + 1) < num_cols) {
3565  i = 0;
3566  while ((c = dbstring_getchar(dbproc->dbopts[DBPRCOLSEP].param, i++)) != -1) {
3567  putchar(c);
3568  }
3569  }
3570  }
3571  i = 0;
3572  while ((c = dbstring_getchar(dbproc->dbopts[DBPRLINESEP].param, i++)) != -1) {
3573  putchar(c);
3574  }
3575 
3576  for (selcol = col = 1; col <= num_cols; col++) {
3577  tdsdump_log(TDS_DBG_FUNC, "dbprrow calling dbaltcolid(%d,%d)\n", computeid, col);
3578  colid = dbaltcolid(dbproc, computeid, col);
3579  while (selcol < colid) {
3580  for (i = 0; i < col_printlens[selcol - 1]; i++) {
3581  putchar(' ');
3582  }
3583  selcol++;
3584  i = 0;
3585  while ((c = dbstring_getchar(dbproc->dbopts[DBPRCOLSEP].param, i++)) != -1) {
3586  putchar(c);
3587  }
3588  }
3589  if (resinfo->by_cols > 0) {
3590  linechar = '-';
3591  } else {
3592  linechar = '=';
3593  }
3594  for (i = 0; i < col_printlens[colid - 1]; i++)
3595  putchar(linechar);
3596  selcol++;
3597  if ((colid + 1) < num_cols) {
3598  i = 0;
3599  while ((c = dbstring_getchar(dbproc->dbopts[DBPRCOLSEP].param, i++)) != -1) {
3600  putchar(c);
3601  }
3602  }
3603  }
3604  i = 0;
3605  while ((c = dbstring_getchar(dbproc->dbopts[DBPRLINESEP].param, i++)) != -1) {
3606  putchar(c);
3607  }
3608 
3609  for (selcol = col = 1; col <= num_cols; col++) {
3610  colinfo = resinfo->columns[col - 1];
3611 
3612  desttype = dblib_bound_type(STRINGBIND);
3613  srctype = dbalttype(dbproc, computeid, col);
3614 
3615  if (is_datetime_type(srctype)) {
3616  tds_datecrack(srctype, dbadata(dbproc, computeid, col), &when);
3617  len = (int)tds_strftime(dest, sizeof(dest), STD_DATETIME_FMT, &when, 3);
3618  } else {
3619  len = dbconvert(dbproc, srctype, dbadata(dbproc, computeid, col), -1, desttype,
3620  (BYTE *) dest, sizeof(dest));
3621  }
3622 
3623  tdsdump_log(TDS_DBG_FUNC, "dbprrow calling dbaltcolid(%d,%d)\n", computeid, col);
3624  colid = dbaltcolid(dbproc, computeid, col);
3625  tdsdump_log(TDS_DBG_FUNC, "dbprrow select column = %d\n", colid);
3626 
3627  while (selcol < colid) {
3628  for (i = 0; i < col_printlens[selcol - 1]; i++) {
3629  putchar(' ');
3630  }
3631  selcol++;
3632  i = 0;
3633  while ((c = dbstring_getchar(dbproc->dbopts[DBPRCOLSEP].param, i++)) != -1) {
3634  putchar(c);
3635  }
3636  }
3637  p = memchr(dest, '\0', len);
3638  fwrite(dest, 1, p == NULL ? len : (p - dest),
3639  stdout);
3640  collen = _get_printable_size(colinfo);
3641  namlen = tds_dstr_len(&colinfo->column_name);
3642  padlen = (collen > namlen ? collen : namlen) - len;
3643  if ((c = dbstring_getchar(dbproc->dbopts[DBPRPAD].param, 0)) == -1) {
3644  c = ' ';
3645  }
3646  for (; padlen > 0; padlen--) {
3647  putchar(c);
3648  }
3649  selcol++;
3650  if ((colid + 1) < num_cols) {
3651  i = 0;
3652  while ((c = dbstring_getchar(dbproc->dbopts[DBPRCOLSEP].param, i++)) != -1) {
3653  putchar(c);
3654  }
3655  }
3656  }
3657  i = 0;
3658  while ((c = dbstring_getchar(dbproc->dbopts[DBPRLINESEP].param, i++)) != -1) {
3659  putchar(c);
3660  }
3661  }
3662  }
3663 
3664  free(col_printlens);
3665 
3666  return SUCCEED;
3667 }
3668 
3669 static int
3671 {
3672  switch (tds_get_conversion_type(colinfo->column_type, colinfo->column_size)) {
3673  case SYBINT1:
3674  return 3;
3675  case SYBINT2:
3676  return 6;
3677  case SYBINT4:
3678  return 11;
3679  case SYBINT8:
3680  return 21;
3681  case SYBVARCHAR:
3682  case SYBCHAR:
3683  case SYBTEXT:
3684  case SYBNTEXT:
3685  case SYBNVARCHAR:
3686  case SYBLONGCHAR:
3687  return colinfo->column_size;
3688  case SYBBINARY:
3689  case SYBIMAGE:
3690  case SYBLONGBINARY:
3691  case SYBVARBINARY:
3692  return colinfo->column_size * 2u;
3693  case SYBFLT8:
3694  case SYBREAL:
3695  return 11; /* FIX ME -- we do not track precision */
3696  case SYBMONEY:
3697  case SYBMONEY4:
3698  return 12;
3699  case SYB5BIGDATETIME:
3700  case SYBDATETIME:
3701  case SYBDATETIME4:
3702  return 26;
3703  case SYBTIME:
3704  case SYB5BIGTIME:
3705  return 15;
3706  case SYBDATE:
3707  return 10;
3708  case SYBUNIQUE:
3709  return 36;
3710  case SYBBIT:
3711  return 1;
3712  /* FIX ME -- not all types present */
3713  default:
3714  return 0;
3715  }
3716 }
3717 
3718 /**
3719  * \ingroup dblib_core
3720  * \brief Get formatted string for underlining dbsprhead() column names.
3721  *
3722  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3723  * \param buffer output buffer
3724  * \param buf_len size of \a buffer
3725  * \param line_char character to use to represent underlining.
3726  * \retval SUCCEED \a buffer filled.
3727  * \retval FAIL insufficient space in \a buffer, usually.
3728  * \sa dbprhead(), dbprrow(), dbspr1row(), dbspr1rowlen(), dbsprhead().
3729  */
3730 RETCODE
3731 dbsprline(DBPROCESS * dbproc, char *buffer, DBINT buf_len, DBCHAR line_char)
3732 {
3733  TDSCOLUMN *colinfo;
3734  TDSRESULTINFO *resinfo;
3735  TDSSOCKET *tds;
3736  size_t i, col, len, collen, namlen;
3737  int c;
3738 
3739  tdsdump_log(TDS_DBG_FUNC, "dbsprline(%p, %s, %d, '%c')\n", dbproc, buffer, buf_len, line_char);
3740  CHECK_CONN(FAIL);
3741  CHECK_NULP(buffer, "dbsprline", 2, FAIL);
3742 
3743  tds = dbproc->tds_socket;
3744  resinfo = tds->res_info;
3745 
3746  for (col = 0; col < resinfo->num_cols; col++) {
3747  colinfo = resinfo->columns[col];
3748  collen = _get_printable_size(colinfo);
3749  namlen = tds_dstr_len(&colinfo->column_name);
3750  len = collen > namlen ? collen : namlen;
3751  for (i = 0; i < len; i++) {
3752  if (buf_len < 1) {
3753  return FAIL;
3754  }
3755  *buffer++ = line_char;
3756  buf_len--;
3757  }
3758  if ((col + 1) < resinfo->num_cols) {
3759  i = 0;
3760  while ((c = dbstring_getchar(dbproc->dbopts[DBPRCOLSEP].param, i)) != -1) {
3761  if (buf_len < 1) {
3762  return FAIL;
3763  }
3764  *buffer++ = c;
3765  buf_len--;
3766  i++;
3767  }
3768  }
3769  }
3770  if (buf_len < 1) {
3771  return FAIL;
3772  }
3773  *buffer = '\0';
3774  return SUCCEED;
3775 }
3776 
3777 /**
3778  * \ingroup dblib_core
3779  * \brief Print result set headings to a buffer.
3780  *
3781  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3782  * \param buffer output buffer
3783  * \param buf_len size of \a buffer
3784  * \retval SUCCEED \a buffer filled.
3785  * \retval FAIL insufficient spaace in \a buffer, usually.
3786  * \sa dbprhead(), dbprrow(), dbsetopt(), dbspr1row(), dbspr1rowlen(), dbsprline().
3787  */
3788 RETCODE
3790 {
3791  TDSCOLUMN *colinfo;
3792  TDSRESULTINFO *resinfo;
3793  TDSSOCKET *tds;
3794  int i, collen, namlen;
3795  TDS_USMALLINT col;
3796  int padlen;
3797  int c;
3798 
3799  tdsdump_log(TDS_DBG_FUNC, "dbsprhead(%p, %p, %d)\n", dbproc, buffer, buf_len);
3800  CHECK_CONN(FAIL);
3801  CHECK_NULP(buffer, "dbsprhead", 2, FAIL);
3802 
3803  tds = dbproc->tds_socket;
3804  resinfo = tds->res_info;
3805 
3806  for (col = 0; col < resinfo->num_cols; col++) {
3807  colinfo = resinfo->columns[col];
3808  collen = _get_printable_size(colinfo);
3809  namlen = (int) tds_dstr_len(&colinfo->column_name);
3810  padlen = (collen > namlen ? collen : namlen) - namlen;
3811  if (buf_len < namlen) {
3812  return FAIL;
3813  }
3814  memcpy(buffer, tds_dstr_cstr(&colinfo->column_name), namlen);
3815  buffer += namlen;
3816  buf_len -= namlen;
3817  if ((c = dbstring_getchar(dbproc->dbopts[DBPRPAD].param, 0)) == -1) {
3818  c = ' ';
3819  }
3820  for (; padlen > 0; padlen--) {
3821  if (buf_len < 1) {
3822  return FAIL;
3823  }
3824  *buffer++ = c;
3825  buf_len--;
3826  }
3827  if ((col + 1) < resinfo->num_cols) {
3828  i = 0;
3829  while ((c = dbstring_getchar(dbproc->dbopts[DBPRCOLSEP].param, i)) != -1) {
3830  if (buf_len < 1) {
3831  return FAIL;
3832  }
3833  *buffer++ = c;
3834  buf_len--;
3835  i++;
3836  }
3837  }
3838  }
3839  if (buf_len < 1) {
3840  return FAIL;
3841  }
3842  *buffer = '\0';
3843  return SUCCEED;
3844 }
3845 
3846 /**
3847  * \ingroup dblib_core
3848  * \brief Print result set headings to stdout.
3849  *
3850  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3851  * \sa
3852  */
3853 void
3855 {
3856  TDSCOLUMN *colinfo;
3857  TDSRESULTINFO *resinfo;
3858  TDSSOCKET *tds;
3859  size_t i, col, len, collen, namlen;
3860  size_t padlen;
3861  int c;
3862 
3863  tdsdump_log(TDS_DBG_FUNC, "dbprhead(%p)\n", dbproc);
3865 
3866  tds = dbproc->tds_socket;
3867  resinfo = tds->res_info;
3868  if (resinfo == NULL) {
3869  return;
3870  }
3871  for (col = 0; col < resinfo->num_cols; col++) {
3872  colinfo = resinfo->columns[col];
3873  collen = _get_printable_size(colinfo);
3874  namlen = tds_dstr_len(&colinfo->column_name);
3875  padlen = (collen > namlen ? collen : namlen) - namlen;
3876  printf("%s", tds_dstr_cstr(&colinfo->column_name));
3877 
3879  if (c == -1) {
3880  c = ' ';
3881  }
3882  for (; padlen > 0; padlen--) {
3883  putchar(c);
3884  }
3885 
3886  if ((col + 1) < resinfo->num_cols) {
3887  i = 0;
3888  while ((c = dbstring_getchar(dbproc->dbopts[DBPRCOLSEP].param, i)) != -1) {
3889  putchar(c);
3890  i++;
3891  }
3892  }
3893  }
3894  i = 0;
3895  while ((c = dbstring_getchar(dbproc->dbopts[DBPRLINESEP].param, i)) != -1) {
3896  putchar(c);
3897  i++;
3898  }
3899  for (col = 0; col < resinfo->num_cols; col++) {
3900  colinfo = resinfo->columns[col];
3901  collen = _get_printable_size(colinfo);
3902  namlen = tds_dstr_len(&colinfo->column_name);
3903  len = collen > namlen ? collen : namlen;
3904  for (i = 0; i < len; i++)
3905  putchar('-');
3906  if ((col + 1) < resinfo->num_cols) {
3907  i = 0;
3908  while ((c = dbstring_getchar(dbproc->dbopts[DBPRCOLSEP].param, i)) != -1) {
3909  putchar(c);
3910  i++;
3911  }
3912  }
3913  }
3914  i = 0;
3915  while ((c = dbstring_getchar(dbproc->dbopts[DBPRLINESEP].param, i)) != -1) {
3916  putchar(c);
3917  i++;
3918  }
3919 }
3920 
3921 /** \internal
3922  * \ingroup dblib_internal
3923  * \brief Indicate whether a query returned rows.
3924  *
3925  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3926  * \sa DBROWS(), DBCMDROW(), dbnextrow(), dbresults(), DBROWTYPE().
3927  */
3928 RETCODE
3930 {
3931  TDSSOCKET *tds;
3932 
3933  tdsdump_log(TDS_DBG_FUNC, "dbrows(%p)\n", dbproc);
3934  CHECK_CONN(FAIL);
3935 
3936  if (!(tds=dbproc->tds_socket))
3937  return FAIL;
3938 
3939  return (tds->res_info && tds->res_info->rows_exist)? SUCCEED : FAIL;
3940 }
3941 
3942 #if defined(DBLIB_UNIMPLEMENTED)
3943 /**
3944  * \ingroup dblib_core
3945  * \brief Set the default character set for an application.
3946  *
3947  * \param language ASCII null-terminated string.
3948  * \sa dbsetdeflang(), dbsetdefcharset(), dblogin(), dbopen().
3949  * \retval SUCCEED Always.
3950  * \todo Unimplemented.
3951  */
3952 RETCODE
3953 dbsetdeflang(char *language)
3954 {
3955  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbsetdeflang(%s)\n", language);
3956  CHECK_PARAMETER_NOPROC(language, SYBENULP);
3957  return SUCCEED;
3958 }
3959 #endif
3960 
3961 /**
3962  * \ingroup dblib_core
3963  * \brief Get TDS packet size for the connection.
3964  *
3965  * \param dbproc contains all information needed by db-lib to manage communications with the server.
3966  * \return TDS packet size, in bytes.
3967  * \sa DBSETLPACKET()
3968  */
3969 int
3971 {
3972  TDSSOCKET *tds;
3973 
3974  tdsdump_log(TDS_DBG_FUNC, "dbgetpacket(%p)\n", dbproc);
3976 
3977  tds = dbproc->tds_socket;
3978  if (!tds) {
3979  return TDS_DEF_BLKSZ;
3980  } else {
3981  return tds->conn->env.block_size;
3982  }
3983 }
3984 
3985 /**
3986  * \ingroup dblib_core
3987  * \brief Set maximum simultaneous connections db-lib will open to the server.
3988  *
3989  * \param maxprocs Limit for process.
3990  * \retval SUCCEED Always.
3991  * \sa dbgetmaxprocs(), dbopen()
3992  */
3993 RETCODE
3994 dbsetmaxprocs(int maxprocs)
3995 {
3996  int i, j;
3997  TDSSOCKET **old_list;
3998 
3999  tdsdump_log(TDS_DBG_FUNC, "UNTESTED dbsetmaxprocs(%d)\n", maxprocs);
4000 
4001  /* not too few elements */
4002  if (maxprocs <= 0)
4003  return FAIL;
4004 
4006 
4007  old_list = g_dblib_ctx.connection_list;
4008 
4009  /* "compress" array */
4010  for (i = 0; i < g_dblib_ctx.connection_list_size; ++i) {
4011  /* if empty replace with first no-empty */
4012  if (old_list[i])
4013  continue;
4014  for (j = i + 1; j < g_dblib_ctx.connection_list_size; ++j)
4015  if (old_list[j]) {
4016  old_list[i] = old_list[j];
4017  old_list[j] = NULL;
4018  break;
4019  }
4021  break;
4022  }
4023  /* do not restrict too much, i here contains minimun size */
4024  if (maxprocs < i)
4025  maxprocs = i;
4026  assert(maxprocs > 0);
4027 
4028  /*
4029  * Don't reallocate less memory.
4030  * If maxprocs is less than was initially allocated, just reduce the represented list size.
4031  * If larger, reallocate and copy.
4032  * We probably should check for valid connections beyond the new max.
4033  */
4034  if (maxprocs <= g_dblib_ctx.connection_list_size) {
4037  return SUCCEED;
4038  }
4039 
4041 
4042  if (g_dblib_ctx.connection_list == NULL) {
4043  g_dblib_ctx.connection_list = old_list;
4045  dbperror(NULL, SYBEMEM, errno);
4046  return FAIL;
4047  }
4048 
4049  for (i = 0; i < g_dblib_ctx.connection_list_size; i++) {
4050  g_dblib_ctx.connection_list[i] = old_list[i];
4051  }
4052 
4053  g_dblib_ctx.connection_list_size = maxprocs;
4055 
4057 
4058  return SUCCEED;
4059 }
4060 
4061 /**
4062  * \ingroup dblib_core
4063  * \brief get maximum simultaneous connections db-lib will open to the server.
4064  *
4065  * \return Current maximum.
4066  * \sa dbsetmaxprocs(), dbopen()
4067  */
4068 int
4070 {
4071  int r;
4072 
4073  tdsdump_log(TDS_DBG_FUNC, "dbgetmaxprocs(void)\n");
4074 
4078  return r;
4079 }
4080 
4081 /**
4082  * \ingroup dblib_core
4083  * \brief Set maximum seconds db-lib waits for a server response to query.
4084  *
4085  * \param seconds New limit for application.
4086  * \retval SUCCEED Always.
4087  * \sa dberrhandle(), DBGETTIME(), dbsetlogintime(), dbsqlexec(), dbsqlok(), dbsqlsend().
4088  */
4089 RETCODE
4090 dbsettime(int seconds)
4091 {
4092  TDSSOCKET **tds;
4093  int i;
4094  DBPROCESS *dbproc;
4095  tdsdump_log(TDS_DBG_FUNC, "dbsettime(%d)\n", seconds);
4096 
4098  g_dblib_ctx.query_timeout = seconds;
4099 
4101  for (i = 0; i < TDS_MAX_CONN; i++) {
4102  if (tds[i]) {
4104  if (!dbisopt(dbproc, DBSETTIME, 0))
4105  tds[i]->query_timeout = seconds;
4106  }
4107  }
4108 
4110  return SUCCEED;
4111 }
4112 
4113 /**
4114  * \ingroup dblib_core
4115  * \brief Get maximum seconds db-lib waits for a server response to query.
4116  *
4117  * \retval query timeout limit, in seconds
4118  * \sa dberrhandle(), DBSETTIME(), dbsetlogintime(), dbsqlexec(), dbsqlok(), dbsqlsend().
4119  */
4120 int
4122 {
4123  tdsdump_log(TDS_DBG_FUNC, "dbgettime()\n");
4124 
4125  return g_dblib_ctx.query_timeout;
4126 }
4127 
4128 /**
4129  * \ingroup dblib_core
4130  * \brief Set maximum seconds db-lib waits for a server response to a login attempt.
4131  *
4132  * \param seconds New limit for application.
4133  * \retval SUCCEED Always.
4134  * \sa dberrhandle(), dbsettime()
4135  */
4136 RETCODE
4137 dbsetlogintime(int seconds)
4138 {
4139  tdsdump_log(TDS_DBG_FUNC, "dbsetlogintime(%d)\n", seconds);
4140 
4142  g_dblib_ctx.login_timeout = seconds;
4144  return SUCCEED;
4145 }
4146 
4147 /** \internal
4148  * \ingroup dblib_internal
4149  * \brief See if the current command can return rows.
4150  *
4151  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4152  * \retval SUCCEED Yes, it can.
4153  * \retval FAIL No, it can't.
4154  * \remarks Use DBCMDROW() macro instead.
4155  * \sa DBCMDROW(), dbnextrow(), dbresults(), DBROWS(), DBROWTYPE().
4156  */
4157 RETCODE
4159 {
4160  TDSSOCKET *tds;
4161 
4162  tdsdump_log(TDS_DBG_FUNC, "dbcmdrow(%p)\n", dbproc);
4163  CHECK_CONN(FAIL);
4164 
4165  tds = dbproc->tds_socket;
4166  if (tds->res_info)
4167  return SUCCEED;
4168  return FAIL;
4169 }
4170 
4171 /**
4172  * \ingroup dblib_core
4173  * \brief Get column ID of a compute column.
4174  *
4175  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4176  * \param computeid of \c COMPUTE clause to which we're referring.
4177  * \param column Nth column in \a computeid, starting from 1.
4178  * \return Nth column in the base result set, on which \a column was computed.
4179  * \sa dbadata(), dbadlen(), dbaltlen(), dbgetrow(), dbnextrow(), dbnumalts(), dbprtype().
4180  */
4181 int
4182 dbaltcolid(DBPROCESS * dbproc, int computeid, int column)
4183 {
4184  TDSCOLUMN *curcol;
4185 
4186  tdsdump_log(TDS_DBG_FUNC, "dbaltcolid(%p, %d, %d)\n", dbproc, computeid, column);
4188 
4189  curcol = dbacolptr(dbproc, computeid, column, 0);
4190  if (!curcol)
4191  return -1;
4192 
4193  return curcol->column_operand;
4194 }
4195 
4196 /**
4197  * \ingroup dblib_core
4198  * \brief Get size of data in a compute column.
4199  *
4200  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4201  * \param computeid of \c COMPUTE clause to which we're referring.
4202  * \param column Nth column in \a computeid, starting from 1.
4203  * \return size of the data, in bytes.
4204  * \retval -1 no such \a column or \a computeid.
4205  * \retval 0 data are NULL.
4206  * \sa dbadata(), dbaltlen(), dbalttype(), dbgetrow(), dbnextrow(), dbnumalts().
4207  */
4208 DBINT
4209 dbadlen(DBPROCESS * dbproc, int computeid, int column)
4210 {
4211  TDSCOLUMN *colinfo;
4212  DBINT len;
4213 
4214  tdsdump_log(TDS_DBG_FUNC, "dbadlen(%p, %d, %d)\n", dbproc, computeid, column);
4216 
4217  colinfo = dbacolptr(dbproc, computeid, column, 0);
4218  if (!colinfo)
4219  return -1;
4220 
4221  len = colinfo->column_cur_size < 0? 0 : colinfo->column_cur_size;
4222 
4223  tdsdump_log(TDS_DBG_FUNC, "leaving dbadlen() type = %d, returning %d\n", colinfo->column_type, len);
4224 
4225  return len;
4226 }
4227 
4228 /**
4229  * \ingroup dblib_core
4230  * \brief Get datatype for a compute column.
4231  *
4232  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4233  * \param computeid of \c COMPUTE clause to which we're referring.
4234  * \param column Nth column in \a computeid, starting from 1.
4235  * \return \c SYB* dataype token.
4236  * \retval -1 no such \a column or \a computeid.
4237  * \sa dbadata(), dbadlen(), dbaltlen(), dbnextrow(), dbnumalts(), dbprtype().
4238  */
4239 int
4240 dbalttype(DBPROCESS * dbproc, int computeid, int column)
4241 {
4242  TDSCOLUMN *colinfo;
4243 
4244  tdsdump_log(TDS_DBG_FUNC, "dbalttype(%p, %d, %d)\n", dbproc, computeid, column);
4246 
4247  colinfo = dbacolptr(dbproc, computeid, column, 0);
4248  if (!colinfo)
4249  return -1;
4250 
4251  switch (colinfo->column_type) {
4252  case SYBVARCHAR:
4253  return SYBCHAR;
4254  case SYBVARBINARY:
4255  return SYBBINARY;
4256  default:
4257  return tds_get_conversion_type(colinfo->column_type,
4258  colinfo->column_size);
4259  }
4260 }
4261 
4262 /**
4263  * \ingroup dblib_core
4264  * \brief Bind a compute column to a program variable.
4265  *
4266  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4267  * \param computeid of \c COMPUTE clause to which we're referring.
4268  * \param column Nth column in \a computeid, starting from 1.
4269  * \param vartype datatype of the host variable that will receive the data
4270  * \param varlen size of host variable pointed to \a varaddr
4271  * \param varaddr address of host variable
4272  * \retval SUCCEED everything worked.
4273  * \retval FAIL no such \a computeid or \a column, or no such conversion possible, or target buffer too small.
4274  * \sa dbadata(), dbaltbind_ps(), dbanullbind(), dbbind(), dbbind_ps(), dbconvert(),
4275  * dbconvert_ps(), dbnullbind(), dbsetnull(), dbsetversion(), dbwillconvert().
4276  */
4277 RETCODE
4278 dbaltbind(DBPROCESS * dbproc, int computeid, int column, int vartype, DBINT varlen, BYTE * varaddr)
4279 {
4280  TDS_SERVER_TYPE srctype, desttype;
4281  TDSCOLUMN *colinfo = NULL;
4282 
4283  tdsdump_log(TDS_DBG_FUNC, "dbaltbind(%p, %d, %d, %d, %d, %p)\n", dbproc, computeid, column, vartype, varlen, varaddr);
4285 
4286  colinfo = dbacolptr(dbproc, computeid, column, 1);
4287  if (!colinfo)
4288  return FAIL;
4289  CHECK_PARAMETER(varaddr, SYBEABNV, FAIL);
4290 
4291  dbproc->avail_flag = FALSE;
4292 
4293  srctype = tds_get_conversion_type(colinfo->column_type, colinfo->column_size);
4294  desttype = dblib_bound_type(vartype);
4295  if (desttype == TDS_INVALID_TYPE) {
4296  dbperror(dbproc, SYBEBTYP, 0);
4297  return FAIL;
4298  }
4299 
4300  if (!dbwillconvert(srctype, desttype)) {
4301  dbperror(dbproc, SYBEAAMT, 0);
4302  return FAIL;
4303  }
4304 
4305  colinfo->column_varaddr = (char *) varaddr;
4306  colinfo->column_bindtype = vartype;
4307  colinfo->column_bindlen = varlen;
4308 
4309  return SUCCEED;
4310 }
4311 
4312 
4313 /**
4314  * \ingroup dblib_core
4315  * \brief Get address of compute column data.
4316  *
4317  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4318  * \param computeid of \c COMPUTE clause to which we're referring.
4319  * \param column Nth column in \a computeid, starting from 1.
4320  * \return pointer to columns's data buffer.
4321  * \retval NULL no such \a computeid or \a column.
4322  * \sa dbadlen(), dbaltbind(), dbaltlen(), dbalttype(), dbgetrow(), dbnextrow(), dbnumalts().
4323  */
4324 BYTE *
4325 dbadata(DBPROCESS * dbproc, int computeid, int column)
4326 {
4327  TDSCOLUMN *colinfo;
4328 
4329  tdsdump_log(TDS_DBG_FUNC, "dbadata(%p, %d, %d)\n", dbproc, computeid, column);
4331 
4332  colinfo = dbacolptr(dbproc, computeid, column, 0);
4333  if (!colinfo)
4334  return NULL;
4335 
4336  if (is_blob_col(colinfo)) {
4337  return (BYTE *) ((TDSBLOB *) colinfo->column_data)->textvalue;
4338  }
4339 
4340  return (BYTE *) colinfo->column_data;
4341 }
4342 
4343 /**
4344  * \ingroup dblib_core
4345  * \brief Get aggregation operator for a compute column.
4346  *
4347  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4348  * \param computeid of \c COMPUTE clause to which we're referring.
4349  * \param column Nth column in \a computeid, starting from 1.
4350  * \return token value for the type of the compute column's aggregation operator.
4351  * \retval -1 no such \a computeid or \a column.
4352  * \sa dbadata(), dbadlen(), dbaltlen(), dbnextrow(), dbnumalts(), dbprtype().
4353  */
4354 int
4355 dbaltop(DBPROCESS * dbproc, int computeid, int column)
4356 {
4357  TDSCOLUMN *curcol;
4358 
4359  tdsdump_log(TDS_DBG_FUNC, "dbaltop(%p, %d, %d)\n", dbproc, computeid, column);
4361 
4362  if ((curcol=dbacolptr(dbproc, computeid, column, 0)) == NULL)
4363  return -1;
4364 
4365  return curcol->column_operator;
4366 }
4367 
4368 /**
4369  * \ingroup dblib_core
4370  * \brief Set db-lib or server option.
4371  *
4372  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4373  * \param option option to set.
4374  * \param char_param value to set \a option to, if it wants a null-teminated ASCII string.
4375  * \param int_param value to set \a option to, if it wants an integer value.
4376  * \retval SUCCEED everything worked.
4377  * \retval FAIL no such \a option, or insufficient memory, or unimplemented.
4378  * \remarks Many are unimplemented.
4379  * \sa dbclropt(), dbisopt().
4380  * \todo Implement more options.
4381  */
4382 RETCODE
4383 dbsetopt(DBPROCESS * dbproc, int option, const char *char_param, int int_param)
4384 {
4385  char *cmd;
4386  RETCODE rc;
4387  int i;
4388 
4389  tdsdump_log(TDS_DBG_FUNC, "dbsetopt(%p, %d, %s, %d)\n", dbproc, option, char_param, int_param);
4390  CHECK_CONN(FAIL);
4391  CHECK_NULP(char_param, "dbsetopt", 3, FAIL);
4392 
4393  if ((option < 0) || (option >= DBNUMOPTIONS)) {
4394  dbperror(dbproc, SYBEUNOP, 0);
4395  return FAIL;
4396  }
4397  dbproc->dbopts[option].factive = 1;
4398  switch (option) {
4399  case DBARITHABORT:
4400  case DBARITHIGNORE:
4401  case DBCHAINXACTS:
4402  case DBFIPSFLAG:
4403  case DBISOLATION:
4404  case DBNOCOUNT:
4405  case DBNOEXEC:
4406  case DBPARSEONLY:
4407  case DBSHOWPLAN:
4408  case DBSTORPROCID:
4409  case DBQUOTEDIDENT:
4410  /* server options (on/off) */
4411  if (asprintf(&cmd, "set %s on\n", dbproc->dbopts[option].text) < 0) {
4412  return FAIL;
4413  }
4414  rc = dbstring_concat(&(dbproc->dboptcmd), cmd);
4415  free(cmd);
4416  return rc;
4417  break;
4418  case DBNATLANG:
4419  case DBDATEFIRST:
4420  case DBDATEFORMAT:
4421  /* server options (char_param) */
4422  if (asprintf(&cmd, "set %s %s\n", dbproc->dbopts[option].text, char_param) < 0) {
4423  return FAIL;
4424  }
4425  rc = dbstring_concat(&(dbproc->dboptcmd), cmd);
4426  free(cmd);
4427  return rc;
4428  break;
4429  case DBOFFSET:
4430  /* server option */
4431  /* requires param
4432  * "select", "from", "table", "order", "compute",
4433  * "statement", "procedure", "execute", or "param"
4434  */
4435  break;
4436  case DBROWCOUNT:
4437  /* server option */
4438  /* requires param "0" to "2147483647" */
4439  break;
4440  case DBSTAT:
4441  /* server option */
4442  /* requires param "io" or "time" */
4443  break;
4444  case DBTEXTLIMIT:
4445  /* dblib option */
4446  /* requires param "0" to "2147483647" */
4447  /* dblib do not return more than this length from text/image */
4448  /* TODO required for PHP */
4449  break;
4450  case DBTEXTSIZE:
4451  /* server option */
4452  /* requires param "0" to "2147483647" */
4453  /* limit text/image from network */
4454  if (!char_param)
4455  char_param = "0";
4456  i = atoi(char_param);
4457  if (i < 0 || i > 2147483647)
4458  return FAIL;
4459  if (asprintf(&cmd, "set textsize %d\n", i) < 0)
4460  return FAIL;
4461  rc = dbstring_concat(&(dbproc->dboptcmd), cmd);
4462  free(cmd);
4463  return rc;
4464 
4465  case DBAUTH:
4466  /* ??? */
4467  break;
4468  case DBNOAUTOFREE:
4469  /* dblib option */
4470  break;
4471  case DBBUFFER:
4472  /*
4473  * Requires param "2" to "2147483647"
4474  * (0 or 1 is an error, < 0 yields the default 100)
4475  */
4476  {
4477  int nrows;
4478 
4479  /* 100 is the default, according to Microsoft */
4480  if( !char_param )
4481  char_param = "100";
4482 
4483  nrows = atoi(char_param);
4484 
4485  nrows = (nrows < 0 )? 100 : nrows;
4486 
4487  if( 1 < nrows && nrows <= 2147483647 ) {
4488  buffer_set_capacity(dbproc, nrows);
4489  return SUCCEED;
4490  }
4491  }
4492  break;
4493  case DBPRCOLSEP:
4494  case DBPRLINELEN:
4495  case DBPRLINESEP:
4496  rc = dbstring_assign(&(dbproc->dbopts[option].param), char_param);
4497  return rc;
4498  case DBPRPAD:
4499  /*
4500  * "If the character is not specified, the ASCII space character is used."
4501  * A NULL pointer to the pad character signifies that padding is turned off.
4502  */
4503  if (int_param) {
4504  rc = dbstring_assign(&(dbproc->dbopts[option].param), char_param? char_param : " ");
4505  } else {
4507  }
4508  return rc;
4509  break;
4510  case DBSETTIME:
4511  if (char_param) {
4512  i = atoi(char_param);
4513  if (0 < i) {
4514  rc = dbstring_assign(&(dbproc->dbopts[option].param), char_param);
4515  if (rc == SUCCEED) {
4517  }
4518  return rc;
4519  }
4520  }
4521  break;
4522  default:
4523  break;
4524  }
4525  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbsetopt(option = %d)\n", option);
4526  return FAIL;
4527 }
4528 
4529 /**
4530  * \ingroup dblib_core
4531  * \brief Set interrupt handler for db-lib to use while blocked against a read from the server.
4532  *
4533  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4534  * \param chkintr
4535  * \param hndlintr
4536  * \sa dbcancel(), dbgetuserdata(), dbsetuserdata(), dbsetbusy(), dbsetidle().
4537  */
4538 void
4540 {
4541  tdsdump_log(TDS_DBG_FUNC, "dbsetinterrupt(%p, %p, %p)\n", dbproc, chkintr, hndlintr);
4543 
4544  dbproc->chkintr = chkintr;
4546 }
4547 
4548 /**
4549  * \ingroup dblib_rpc
4550  * \brief Determine if query generated a return status number.
4551  *
4552  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4553  * \retval TRUE fetch return status with dbretstatus().
4554  * \retval FALSE no return status.
4555  * \sa dbnextrow(), dbresults(), dbretdata(), dbretstatus(), dbrpcinit(), dbrpcparam(), dbrpcsend().
4556  */
4557 DBBOOL
4559 {
4560  TDSSOCKET *tds;
4561 
4562  tdsdump_log(TDS_DBG_FUNC, "dbhasretstat(%p)\n", dbproc);
4564 
4565  tds = dbproc->tds_socket;
4566  if (tds->has_status) {
4567  return TRUE;
4568  } else {
4569  return FALSE;
4570  }
4571 }
4572 
4573 /**
4574  * \ingroup dblib_rpc
4575  * \brief Fetch status value returned by query or remote procedure call.
4576  *
4577  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4578  * \return return value
4579  * \sa dbhasretstat(), dbnextrow(), dbresults(), dbretdata(), dbrpcinit(), dbrpcparam(), dbrpcsend().
4580  */
4581 DBINT
4583 {
4584  tdsdump_log(TDS_DBG_FUNC, "dbretstatus(%p)\n", dbproc);
4586 
4587  return dbproc->tds_socket->ret_status;
4588 }
4589 
4590 /**
4591  * \ingroup dblib_rpc
4592  * \brief Get count of output parameters filled by a stored procedure.
4593  *
4594  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4595  * \return How many, possibly zero.
4596  * \remarks This name sounds funny.
4597  * \sa
4598  */
4599 int
4601 {
4602  TDSSOCKET *tds;
4603  TDS_INT result_type;
4604 
4605  tdsdump_log(TDS_DBG_FUNC, "dbnumrets(%p)\n", dbproc);
4607 
4608  tds = dbproc->tds_socket;
4609 
4610  tdsdump_log(TDS_DBG_FUNC, "dbnumrets() finds %d columns\n", (tds->param_info? tds->param_info->num_cols : 0));
4611 
4612  /* try to fetch output parameters and return status, if we have not already done so */
4613  if (!tds->param_info)
4614  tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_TRAILING);
4615 
4616  if (!tds->param_info)
4617  return 0;
4618 
4619  return tds->param_info->num_cols;
4620 }
4621 
4622 /**
4623  * \ingroup dblib_rpc
4624  * \brief Get name of an output parameter filled by a stored procedure.
4625  *
4626  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4627  * \param retnum Nth parameter between \c 1 and the return value from \c dbnumrets().
4628  * \returns ASCII null-terminated string, \c NULL if no such \a retnum.
4629  * \sa dbnextrow(), dbnumrets(), dbresults(), dbretdata(), dbretlen(), dbrettype(), dbrpcinit(), dbrpcparam().
4630  */
4631 char *
4633 {
4634  TDSPARAMINFO *param_info;
4635 
4636  tdsdump_log(TDS_DBG_FUNC, "dbretname(%p, %d)\n", dbproc, retnum);
4638 
4639  if (!dbproc->tds_socket)
4640  return NULL;
4641 
4642  dbnumrets(dbproc);
4643 
4644  param_info = dbproc->tds_socket->param_info;
4645  if (!param_info || !param_info->columns || retnum < 1 || retnum > param_info->num_cols)
4646  return NULL;
4647  return tds_dstr_buf(&param_info->columns[retnum - 1]->column_name);
4648 }
4649 
4650 /**
4651  * \ingroup dblib_rpc
4652  * \brief Get value of an output parameter filled by a stored procedure.
4653  *
4654  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4655  * \param retnum Nth parameter between \c 1 and the return value from \c dbnumrets().
4656  * \returns Address of a return parameter value, or \c NULL if no such \a retnum.
4657  * \sa dbnextrow(), dbnumrets(), dbresults(), dbretlen(), dbretname(), dbrettype(), dbrpcinit(), dbrpcparam().
4658  * \todo Handle blobs.
4659  */
4660 BYTE *
4662 {
4663  TDSPARAMINFO *param_info;
4664 
4665  tdsdump_log(TDS_DBG_FUNC, "dbretdata(%p, %d)\n", dbproc, retnum);
4667 
4668  dbnumrets(dbproc);
4669 
4670  param_info = dbproc->tds_socket->param_info;
4671  if (!param_info || !param_info->columns || retnum < 1 || retnum > param_info->num_cols)
4672  return NULL;
4673 
4674  return _dbcoldata(param_info->columns[retnum - 1]);
4675 }
4676 
4677 /**
4678  * \ingroup dblib_rpc
4679  * \brief Get size of an output parameter filled by a stored procedure.
4680  *
4681  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4682  * \param retnum Nth parameter between \c 1 and the return value from \c dbnumrets().
4683  * \returns Size of a return parameter value, or \c NULL if no such \a retnum.
4684  * \sa dbnextrow(), dbnumrets(), dbresults(), dbretdata(), dbretname(), dbrettype(), dbrpcinit(), dbrpcparam().
4685  */
4686 int
4687 dbretlen(DBPROCESS * dbproc, int retnum)
4688 {
4689  TDSCOLUMN *column;
4690  TDSPARAMINFO *param_info;
4691  TDSSOCKET *tds;
4692 
4693  tdsdump_log(TDS_DBG_FUNC, "dbretlen(%p, %d)\n", dbproc, retnum);
4695 
4696  dbnumrets(dbproc);
4697 
4698  tds = dbproc->tds_socket;
4699  param_info = tds->param_info;
4700  if (!param_info || !param_info->columns || retnum < 1 || retnum > param_info->num_cols)
4701  return -1;
4702 
4703  column = param_info->columns[retnum - 1];
4704  if (column->column_cur_size < 0)
4705  return 0;
4706 
4707  return column->column_cur_size;
4708 }
4709 
4710 /**
4711  * \ingroup dblib_core
4712  * \brief Wait for results of a query from the server.
4713  *
4714  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4715  * \retval SUCCEED everything worked, fetch results with \c dbnextresults().
4716  * \retval FAIL SQL syntax error, typically.
4717  * \sa dbcmd(), dbfcmd(), DBIORDESC(), DBIOWDESC(), dbmoretext(), dbnextrow(),
4718  dbpoll(), DBRBUF(), dbresults(), dbretstatus(), dbrpcsend(), dbsettime(), dbsqlexec(),
4719  dbsqlsend(), dbwritetext().
4720  */
4721 RETCODE
4723 {
4724  TDSSOCKET *tds;
4725  TDS_INT result_type;
4726  RETCODE return_code = SUCCEED;
4727  prbuf_t prretbuf;
4728 
4729  tdsdump_log(TDS_DBG_FUNC, "dbsqlok(%p)\n", dbproc);
4730  CHECK_CONN(FAIL);
4731 
4732  tds = dbproc->tds_socket;
4733 
4734  /*
4735  * dbsqlok has been called after dbmoretext()
4736  * This is the trigger to send the text data.
4737  */
4738 
4739  if (dbproc->text_sent) {
4741  dbproc->text_sent = 0;
4742  }
4743 
4744  /*
4745  * See what the next packet from the server is.
4746  * We want to skip any messages which are not processable.
4747  * We're looking for a result token or a done token.
4748  */
4749  for (;;) {
4750  TDSRET tds_code;
4751  int done_flags = 0;
4752 
4753  /*
4754  * If we hit an end token -- e.g. if the command
4755  * submitted returned no data (like an insert) -- then
4756  * we process the end token to extract the status code.
4757  */
4758  tdsdump_log(TDS_DBG_FUNC, "dbsqlok() not done, calling tds_process_tokens()\n");
4759 
4760  tds_code = tds_process_tokens(tds, &result_type, &done_flags, TDS_TOKEN_RESULTS);
4761 
4762  /*
4763  * The error flag may be set for any intervening DONEINPROC packet, in particular
4764  * by a RAISERROR statement. Microsoft db-lib returns FAIL in that case.
4765  */
4766  if (done_flags & TDS_DONE_ERROR) {
4767  return_code = FAIL;
4768  }
4769 
4770  switch (tds_code) {
4771  case TDS_NO_MORE_RESULTS:
4772  return SUCCEED;
4773  break;
4774 
4775  case TDS_SUCCESS:
4776  switch (result_type) {
4777  case TDS_ROWFMT_RESULT:
4780  case TDS_COMPUTEFMT_RESULT:
4782  case TDS_COMPUTE_RESULT:
4783  case TDS_ROW_RESULT:
4784  tdsdump_log(TDS_DBG_FUNC, "dbsqlok() found result token\n");
4785  return SUCCEED;
4786  break;
4787  case TDS_DONEINPROC_RESULT:
4788  break;
4789  case TDS_DONE_RESULT:
4790  case TDS_DONEPROC_RESULT:
4791  tdsdump_log(TDS_DBG_FUNC, "dbsqlok() end status is %s\n", prdbretcode(return_code, prretbuf));
4792 #if 1
4793  if (done_flags & TDS_DONE_ERROR) {
4794 
4795  if (done_flags & TDS_DONE_MORE_RESULTS) {
4797  } else {
4799  }
4800 
4801  } else {
4802  tdsdump_log(TDS_DBG_FUNC, "dbsqlok() end status was success\n");
4803 
4805  }
4806 
4807  return return_code;
4808  break;
4809 #else
4810  int retcode = (done_flags & TDS_DONE_ERROR)? FAIL : SUCCEED;
4811  dbproc->dbresults_state = (done_flags & TDS_DONE_MORE_RESULTS)?
4813 
4814  tdsdump_log(TDS_DBG_FUNC, "dbsqlok: returning %s with %s (%#x)\n",
4815  prdbretcode(retcode), prdbresults_state(dbproc->dbresults_state), done_flags);
4816 
4817  if (retcode == SUCCEED && (done_flags & TDS_DONE_MORE_RESULTS))
4818  continue;
4819 
4820  return retcode;
4821 #endif
4822  default:
4823  tdsdump_log(TDS_DBG_FUNC, "%s %d: logic error: tds_process_tokens result_type %d\n",
4824  __FILE__, __LINE__, result_type);
4825  break;
4826  }
4827  break;
4828 
4829  default:
4830  assert(TDS_FAILED(tds_code));
4831  return FAIL;
4832  break;
4833  }
4834  }
4835 
4836  return SUCCEED;
4837 }
4838 
4839 /**
4840  * \ingroup dblib_core
4841  * \brief Get count of columns in a compute row.
4842  *
4843  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4844  * \param computeid of \c COMPUTE clause to which we're referring.
4845  * \return number of columns, else -1 if no such \a computeid.
4846  * \sa dbadata(), dbadlen(), dbaltlen(), dbalttype(), dbgetrow(), dbnextrow(), dbnumcols().
4847  */
4848 int
4849 dbnumalts(DBPROCESS * dbproc, int computeid)
4850 {
4851  TDSSOCKET *tds;
4853  TDS_SMALLINT compute_id;
4854  TDS_UINT i;
4855 
4856  tdsdump_log(TDS_DBG_FUNC, "dbnumalts(%p, %d)\n", dbproc, computeid);
4858 
4859  tds = dbproc->tds_socket;
4860  compute_id = computeid;
4861 
4862  for (i = 0;; ++i) {
4863  if (i >= tds->num_comp_info)
4864  return -1;
4865  info = tds->comp_info[i];
4866  if (info->computeid == compute_id)
4867  break;
4868  }
4869 
4870  return info->num_cols;
4871 }
4872 
4873 /**
4874  * \ingroup dblib_core
4875  * \brief Get count of \c COMPUTE clauses for a result set.
4876  *
4877  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4878  * \return number of compute clauses for the current query, possibly zero.
4879  * \sa dbnumalts(), dbresults().
4880  */
4881 int
4883 {
4884  TDSSOCKET *tds;
4885 
4886  tdsdump_log(TDS_DBG_FUNC, "dbnumcompute(%p)\n", dbproc);
4888 
4889  tds = dbproc->tds_socket;
4890 
4891  return tds->num_comp_info;
4892 }
4893 
4894 
4895 /**
4896  * \ingroup dblib_core
4897  * \brief Get \c bylist for a compute row.
4898  *
4899  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4900  * \param computeid of \c COMPUTE clause to which we're referring.
4901  * \param size \em output: size of \c bylist buffer whose address is returned, possibly zero.
4902  * \return address of \c bylist for \a computeid.
4903  * \retval NULL no such \a computeid.
4904  * \remarks Do not free returned pointer.
4905  * \sa dbadata(), dbadlen(), dbaltlen(), dbalttype(), dbcolname(), dbgetrow(), dbnextrow().
4906  */
4907 BYTE *
4908 dbbylist(DBPROCESS * dbproc, int computeid, int *size)
4909 {
4910  TDSSOCKET *tds;
4912  TDS_UINT i;
4913  const TDS_SMALLINT byte_flag = -0x8000;
4914 
4915  tdsdump_log(TDS_DBG_FUNC, "dbbylist(%p, %d, %p)\n", dbproc, computeid, size);
4917 
4918  tds = dbproc->tds_socket;
4919 
4920  for (i = 0;; ++i) {
4921  if (i >= tds->num_comp_info) {
4922  if (size)
4923  *size = 0;
4924  return NULL;
4925  }
4926  info = tds->comp_info[i];
4927  if (info->computeid == computeid)
4928  break;
4929  }
4930 
4931  if (size)
4932  *size = info->by_cols;
4933 
4934  /*
4935  * libtds stores this information using TDS_SMALLINT so we
4936  * have to convert it. We can do this because libtds just
4937  * stores these data.
4938  */
4939  if (info->by_cols > 0 && info->bycolumns[0] != byte_flag) {
4940  int n;
4941  TDS_TINYINT *p = (TDS_TINYINT*) malloc(sizeof(info->bycolumns[0]) + info->by_cols);
4942  if (!p) {
4943  dbperror(dbproc, SYBEMEM, errno);
4944  return NULL;
4945  }
4946  for (n = 0; n < info->by_cols; ++n)
4947  p[sizeof(info->bycolumns[0]) + n] = info->bycolumns[n] > 255 ? 255 : info->bycolumns[n];
4948  *((TDS_SMALLINT *)p) = byte_flag;
4949  free(info->bycolumns);
4950  info->bycolumns = (TDS_SMALLINT *) p;
4951  }
4952  return (BYTE *) (&info->bycolumns[1]);
4953 }
4954 
4955 /** \internal
4956  * \ingroup dblib_internal
4957  * \brief Check if \a dbproc is an ex-parrot.
4958  *
4959  * \param dbproc contains all information needed by db-lib to manage communications with the server.
4960  * \retval TRUE process has been marked \em dead.
4961  * \retval FALSE process is OK.
4962  * \remarks dbdead() does not communicate with the server.
4963  * Unless a previously db-lib marked \a dbproc \em dead, dbdead() returns \c FALSE.
4964  * \sa dberrhandle().
4965  */
4966 DBBOOL
4968 {
4969  tdsdump_log(TDS_DBG_FUNC, "dbdead(%p) [%s]\n", dbproc, dbproc? IS_TDSDEAD(dbproc->tds_socket)? "dead":"alive" : "quite dead");
4970 
4971  if( NULL == dbproc )
4972  return TRUE;
4973 
4975  return TRUE;
4976  else
4977  return FALSE;
4978 }
4979 
4980 /** \internal
4981  * \ingroup dblib_internal
4982  * \brief default error handler for db-lib (handles library-generated errors)
4983  *
4984  * The default error handler doesn't print anything. If you want to see your messages printed,
4985  * install an error handler. If you think that should be an optional compile- or run-time default,
4986  * submit a patch. It could be done.
4987  *
4988  * \sa DBDEAD(), dberrhandle().
4989  */
4990 /* Thus saith Sybase:
4991  * "If the user does not supply an error handler (or passes a NULL pointer to
4992  * dberrhandle), DB-Library will exhibit its default error-handling
4993  * behavior: It will abort the program if the error has made the affected
4994  * DBPROCESS unusable (the user can call DBDEAD to determine whether
4995  * or not a DBPROCESS has become unusable). If the error has not made the
4996  * DBPROCESS unusable, DB-Library will simply return an error code to its caller."
4997  *
4998  * It is not the error handler, however, that aborts anything. It is db-lib, cf. dbperror().
4999  */
5000 static int
5001 default_err_handler(DBPROCESS * dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
5002 {
5003  tdsdump_log(TDS_DBG_FUNC, "default_err_handler %p, %d, %d, %d, %p, %p", dbproc, severity, dberr, oserr, dberrstr, oserrstr);
5004 
5005  if (DBDEAD(dbproc) && (!dbproc || !dbproc->msdblib)) {
5006  return INT_EXIT;
5007  }
5008 
5009  if (!dbproc || !dbproc->msdblib) { /* i.e. Sybase behavior */
5010  switch(dberr) {
5011  case SYBETIME:
5012  return INT_EXIT;
5013  default:
5014  break;
5015  }
5016  }
5017  return INT_CANCEL;
5018 }
5019 
5020 /**
5021  * \ingroup dblib_core
5022  * \brief Set an error handler, for messages from db-lib.
5023  *
5024  * \param handler pointer to callback function that will handle errors.
5025  * Pass NULL to restore the default handler.
5026  * \return address of prior handler, or NULL if none was previously installed.
5027  * \sa DBDEAD(), dbmsghandle().
5028  */
5031 {
5032  EHANDLEFUNC old_handler = _dblib_err_handler;
5033 
5034  tdsdump_log(TDS_DBG_FUNC, "dberrhandle(%p)\n", handler);
5035 
5037 
5038  return (old_handler == default_err_handler)? NULL : old_handler;
5039 }
5040 
5041 /**
5042  * \ingroup dblib_core
5043  * \brief Set a message handler, for messages from the server.
5044  *
5045  * \param handler address of the function that will process the messages.
5046  * \sa DBDEAD(), dberrhandle().
5047  */
5050 {
5052 
5053  tdsdump_log(TDS_DBG_FUNC, "dbmsghandle(%p)\n", handler);
5054 
5056  return retFun;
5057 }
5058 
5059 #if defined(DBLIB_UNIMPLEMENTED)
5060 /**
5061  * \ingroup dblib_money
5062  * \brief Add two DBMONEY values.
5063  *
5064  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5065  * \param m1 first operand.
5066  * \param m2 other operand.
5067  * \param sum \em output: result of computation.
5068  * \retval SUCCEED Always.
5069  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5070  * \todo Unimplemented.
5071  */
5072 RETCODE
5073 dbmnyadd(DBPROCESS * dbproc, DBMONEY * m1, DBMONEY * m2, DBMONEY * sum)
5074 {
5075  tdsdump_log(TDS_DBG_FUNC, "dbmnyadd(%p, %p, %p, %p)\n", dbproc, m1, m2, sum);
5076  CHECK_CONN(FAIL);
5077  CHECK_NULP(m1, "dbmnyadd", 2, FAIL);
5078  CHECK_NULP(m2, "dbmnyadd", 3, FAIL);
5079  CHECK_NULP(sum, "dbmnyadd", 4, FAIL);
5080 
5081  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbmnyadd()\n");
5082  return SUCCEED;
5083 }
5084 
5085 
5086 /**
5087  * \ingroup dblib_money
5088  * \brief Subtract two DBMONEY values.
5089  *
5090  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5091  * \param m1 first operand.
5092  * \param m2 other operand, subtracted from \a m1.
5093  * \param difference \em output: result of computation.
5094  * \retval SUCCEED Always.
5095  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5096  * \todo Unimplemented.
5097  */
5098 RETCODE
5099 dbmnysub(DBPROCESS * dbproc, DBMONEY * m1, DBMONEY * m2, DBMONEY * difference)
5100 {
5101  tdsdump_log(TDS_DBG_FUNC, "dbmnysub(%p, %p, %p, %p)\n", dbproc, m1, m2, difference);
5102  CHECK_CONN(FAIL);
5103  CHECK_NULP(m1, "dbmnysub", 2, FAIL);
5104  CHECK_NULP(m2, "dbmnysub", 3, FAIL);
5105  CHECK_NULP(difference, "dbmnysub", 4, FAIL);
5106 
5107  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbmnysyb()\n");
5108  return SUCCEED;
5109 }
5110 
5111 /**
5112  * \ingroup dblib_money
5113  * \brief Multiply two DBMONEY values.
5114  *
5115  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5116  * \param m1 first operand.
5117  * \param m2 other operand.
5118  * \param prod \em output: result of computation.
5119  * \retval SUCCEED Always.
5120  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5121  * \todo Unimplemented.
5122  */
5123 RETCODE
5124 dbmnymul(DBPROCESS * dbproc, DBMONEY * m1, DBMONEY * m2, DBMONEY * prod)
5125 {
5126  tdsdump_log(TDS_DBG_FUNC, "dbmnymul(%p, %p, %p, %p)\n", dbproc, m1, m2, prod);
5127  CHECK_CONN(FAIL);
5128  CHECK_NULP(m1, "dbmnymul", 2, FAIL);
5129  CHECK_NULP(m2, "dbmnymul", 3, FAIL);
5130  CHECK_NULP(prod, "dbmnymul", 4, FAIL);
5131 
5132  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbmnymul()\n");
5133  return SUCCEED;
5134 }
5135 
5136 /**
5137  * \ingroup dblib_money
5138  * \brief Divide two DBMONEY values.
5139  *
5140  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5141  * \param m1 dividend.
5142  * \param m2 divisor.
5143  * \param quotient \em output: result of computation.
5144  * \retval SUCCEED Always.
5145  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5146  * \todo Unimplemented.
5147  */
5148 RETCODE
5149 dbmnydivide(DBPROCESS * dbproc, DBMONEY * m1, DBMONEY * m2, DBMONEY * quotient)
5150 {
5151  tdsdump_log(TDS_DBG_FUNC, "dbmnydivide(%p, %p, %p, %p)\n", dbproc, m1, m2, quotient);
5152  CHECK_CONN(FAIL);
5153  CHECK_NULP(m1, "dbmnydivide", 2, FAIL);
5154  CHECK_NULP(m2, "dbmnydivide", 3, FAIL);
5155  CHECK_NULP(quotient, "dbmnydivide", 4, FAIL);
5156 
5157  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbmnydivide()\n");
5158  return SUCCEED;
5159 }
5160 #endif
5161 
5162 /**
5163  * \ingroup dblib_money
5164  * \brief Compare two DBMONEY values.
5165  *
5166  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5167  * \param m1 some money.
5168  * \param m2 some other money.
5169  * \retval 0 m1 == m2.
5170  * \retval -1 m1 < m2.
5171  * \retval 1 m1 > m2.
5172  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5173  */
5174 int
5176 {
5177  tdsdump_log(TDS_DBG_FUNC, "dbmnycmp(%p, %p, %p)\n", dbproc, m1, m2);
5179  CHECK_NULP(m1, "dbmnycmp", 2, 0);
5180  CHECK_NULP(m2, "dbmnycmp", 3, 0);
5181 
5182  if (m1->mnyhigh < m2->mnyhigh) {
5183  return -1;
5184  }
5185  if (m1->mnyhigh > m2->mnyhigh) {
5186  return 1;
5187  }
5188  if (m1->mnylow < m2->mnylow) {
5189  return -1;
5190  }
5191  if (m1->mnylow > m2->mnylow) {
5192  return 1;
5193  }
5194  return 0;
5195 }
5196 
5197 #if defined(DBLIB_UNIMPLEMENTED)
5198 /**
5199  * \ingroup dblib_money
5200  * \brief Multiply a DBMONEY value by a positive integer, and add an amount.
5201  *
5202  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5203  * \param amount starting amount of money, also holds output.
5204  * \param multiplier amount to multiply \a amount by.
5205  * \param addend amount to add to \a amount, after multiplying by \a multiplier.
5206  * \retval SUCCEED Always.
5207  * \remarks This function is goofy.
5208  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5209  * \todo Unimplemented.
5210  */
5211 RETCODE
5212 dbmnyscale(DBPROCESS * dbproc, DBMONEY * amount, int multiplier, int addend)
5213 {
5214  tdsdump_log(TDS_DBG_FUNC, "dbmnyscale(%p, %p, %d, %d)\n", dbproc, amount, multiplier, addend);
5215  CHECK_CONN(FAIL);
5216  CHECK_NULP(amount, "dbmnyscale", 2, FAIL);
5217 
5218  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbmnyscale()\n");
5219  return SUCCEED;
5220 }
5221 #endif
5222 
5223 /**
5224  * \ingroup dblib_money
5225  * \brief Set a DBMONEY value to zero.
5226  *
5227  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5228  * \param dest address of a DBMONEY structure.
5229  * \retval SUCCEED unless \a amount is NULL.
5230  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5231  */
5232 RETCODE
5234 {
5235  tdsdump_log(TDS_DBG_FUNC, "dbmnyzero(%p, %p)\n", dbproc, dest);
5236  CHECK_CONN(FAIL);
5237  CHECK_NULP(dest, "dbmnyzero", 2, FAIL);
5238 
5239  dest->mnylow = 0;
5240  dest->mnyhigh = 0;
5241  return SUCCEED;
5242 }
5243 
5244 /**
5245  * \ingroup dblib_money
5246  * \brief Get maximum positive DBMONEY value supported.
5247  *
5248  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5249  * \param amount address of a DBMONEY structure.
5250  * \retval SUCCEED Always.
5251  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5252  */
5253 RETCODE
5255 {
5256  tdsdump_log(TDS_DBG_FUNC, "dbmnymaxpos(%p, %p)\n", dbproc, amount);
5257  CHECK_CONN(FAIL);
5258  CHECK_NULP(amount, "dbmnymaxpos", 2, FAIL);
5259 
5260  amount->mnylow = 0xFFFFFFFFlu;
5261  amount->mnyhigh = 0x7FFFFFFFl;
5262  return SUCCEED;
5263 }
5264 
5265 /**
5266  * \ingroup dblib_money
5267  * \brief Get maximum negative DBMONEY value supported.
5268  *
5269  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5270  * \param amount address of a DBMONEY structure.
5271  * \retval SUCCEED Always.
5272  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5273  */
5274 RETCODE
5276 {
5277  tdsdump_log(TDS_DBG_FUNC, "dbmnymaxneg(%p, %p)\n", dbproc, amount);
5278  CHECK_CONN(FAIL);
5279  CHECK_NULP(amount, "dbmnymaxneg", 2, FAIL);
5280 
5281  amount->mnylow = 0;
5282  amount->mnyhigh = -0x7FFFFFFFL - 1;
5283  return SUCCEED;
5284 }
5285 
5286 #if defined(DBLIB_UNIMPLEMENTED)
5287 /**
5288  * \ingroup dblib_money
5289  * \brief Get the least significant digit of a DBMONEY value, represented as a character.
5290  *
5291  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5292  * \param mnyptr \em input the money amount, \em and \em output: \a mnyptr divided by 10.
5293  * \param digit the character value (between '0' and '9') of the rightmost digit in \a mnyptr.
5294  * \param zero \em output: \c TRUE if \a mnyptr is zero on output, else \c FALSE.
5295  * \retval SUCCEED Always.
5296  * \sa dbconvert(), dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5297  * \remarks Unimplemented and likely to remain so. We'd be amused to learn anyone wants this function.
5298  * \todo Unimplemented.
5299  */
5300 RETCODE
5301 dbmnyndigit(DBPROCESS * dbproc, DBMONEY * mnyptr, DBCHAR * digit, DBBOOL * zero)
5302 {
5303  tdsdump_log(TDS_DBG_FUNC, "dbmnyndigit(%p, %p, %s, %p)\n", dbproc, mnyptr, digit, zero);
5304  CHECK_CONN(FAIL);
5305  CHECK_NULP(mnyptr, "dbmnyndigit", 2, FAIL);
5306  CHECK_NULP(digit, "dbmnyndigit", 3, FAIL);
5307  CHECK_NULP(zero, "dbmnyndigit", 4, FAIL);
5308 
5309  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbmnyndigit()\n");
5310  return SUCCEED;
5311 }
5312 
5313 /**
5314  * \ingroup dblib_money
5315  * \brief Prepare a DBMONEY value for use with dbmnyndigit().
5316  *
5317  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5318  * \param amount address of a DBMONEY structure.
5319  * \param trim number of digits to trim from \a amount.
5320  * \param negative \em output: \c TRUE if \a amount < 0.
5321  * \retval SUCCEED Always.
5322  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5323  * \todo Unimplemented.
5324  */
5325 RETCODE
5326 dbmnyinit(DBPROCESS * dbproc, DBMONEY * amount, int trim, DBBOOL * negative)
5327 {
5328  tdsdump_log(TDS_DBG_FUNC, "dbmnyinit(%p, %p, %d, %p)\n", dbproc, amount, trim, negative);
5329  CHECK_CONN(FAIL);
5330  CHECK_NULP(amount, "dbmnyinit", 2, FAIL);
5331  CHECK_NULP(negative, "dbmnyinit", 4, FAIL);
5332 
5333  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbmnyinit()\n");
5334  return SUCCEED;
5335 }
5336 
5337 
5338 /**
5339  * \ingroup dblib_money
5340  * \brief Divide a DBMONEY value by a positive integer.
5341  *
5342  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5343  * \param amount address of a DBMONEY structure.
5344  * \param divisor of \a amount.
5345  * \param remainder \em output: modulo of integer division.
5346  * \retval SUCCEED Always.
5347  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5348  * \todo Unimplemented.
5349  */
5350 RETCODE
5351 dbmnydown(DBPROCESS * dbproc, DBMONEY * amount, int divisor, int *remainder)
5352 {
5353  tdsdump_log(TDS_DBG_FUNC, "dbmnydown(%p, %p, %d, %p)\n", dbproc, amount, divisor, remainder);
5354  CHECK_CONN(FAIL);
5355  CHECK_NULP(amount, "dbmnydown", 2, FAIL);
5356  CHECK_NULP(remainder, "dbmnydown", 4, FAIL);
5357  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbmnydown()\n");
5358  return SUCCEED;
5359 }
5360 #endif
5361 
5362 /**
5363  * \ingroup dblib_money
5364  * \brief Add $0.0001 to a DBMONEY value.
5365  *
5366  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5367  * \param amount address of a DBMONEY structure.
5368  * \retval SUCCEED or FAIL if overflow or amount NULL.
5369  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5370  */
5371 RETCODE
5373 {
5374  tdsdump_log(TDS_DBG_FUNC, "dbmnyinc(%p, %p)\n", dbproc, amount);
5375  CHECK_CONN(FAIL);
5376  CHECK_NULP(amount, "dbmnyinc", 2, FAIL);
5377 
5378  if (amount->mnylow != 0xFFFFFFFFlu) {
5379  ++amount->mnylow;
5380  return SUCCEED;
5381  }
5382  if (amount->mnyhigh == 0x7FFFFFFFl)
5383  return FAIL;
5384  amount->mnylow = 0;
5385  ++amount->mnyhigh;
5386  return SUCCEED;
5387 }
5388 
5389 
5390 /**
5391  * \ingroup dblib_money
5392  * \brief Subtract $0.0001 from a DBMONEY value.
5393  *
5394  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5395  * \param amount address of a DBMONEY structure.
5396  * \retval SUCCEED or FAIL if overflow or amount NULL.
5397  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5398  */
5399 RETCODE
5401 {
5402  tdsdump_log(TDS_DBG_FUNC, "dbmnydec(%p, %p)\n", dbproc, amount);
5403  CHECK_CONN(FAIL);
5404  CHECK_NULP(amount, "dbmnydec", 2, FAIL);
5405 
5406  if (amount->mnylow != 0) {
5407  --amount->mnylow;
5408  return SUCCEED;
5409  }
5410  if (amount->mnyhigh == -0x7FFFFFFFL - 1)
5411  return FAIL;
5412  amount->mnylow = 0xFFFFFFFFlu;
5413  --amount->mnyhigh;
5414  return SUCCEED;
5415 }
5416 
5417 /**
5418  * \ingroup dblib_money
5419  * \brief Negate a DBMONEY value.
5420  *
5421  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5422  * \param src address of a DBMONEY structure.
5423  * \param dest \em output: result of negation.
5424  * \retval SUCCEED or FAIL if overflow or src/dest NULL.
5425  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5426  */
5427 RETCODE
5429 {
5430  tdsdump_log(TDS_DBG_FUNC, "dbmnyminus(%p, %p, %p)\n", dbproc, src, dest);
5431  CHECK_CONN(FAIL);
5432  CHECK_NULP(src, "dbmnyminus", 2, FAIL);
5433  CHECK_NULP(dest, "dbmnyminus", 3, FAIL);
5434 
5435  if (src->mnyhigh == -0x7FFFFFFFL - 1 && src->mnylow == 0)
5436  return FAIL;
5437  dest->mnyhigh = -src->mnyhigh;
5438  dest->mnylow = (~src->mnylow) + 1u;
5439  return SUCCEED;
5440 }
5441 
5442 
5443 /**
5444  * \ingroup dblib_money
5445  * \brief Negate a DBMONEY4 value.
5446  *
5447  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5448  * \param src address of a DBMONEY4 structure.
5449  * \param dest \em output: result of negation.
5450  * \retval SUCCEED usually.
5451  * \retval FAIL on overflow.
5452  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5453  */
5454 RETCODE
5456 {
5457  DBMONEY4 zero;
5458 
5459  tdsdump_log(TDS_DBG_FUNC, "dbmny4minus(%p, %p, %p)\n", dbproc, src, dest);
5460  CHECK_CONN(FAIL);
5461  CHECK_NULP(src, "dbmny4minus", 2, FAIL);
5462  CHECK_NULP(dest, "dbmny4minus", 3, FAIL);
5463 
5464  dbmny4zero(dbproc, &zero);
5465  return (dbmny4sub(dbproc, &zero, src, dest));
5466 }
5467 
5468 /**
5469  * \ingroup dblib_money
5470  * \brief Zero a DBMONEY4 value.
5471  *
5472  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5473  * \param dest address of a DBMONEY structure.
5474  * \retval SUCCEED usually.
5475  * \retval FAIL \a dest is NULL.
5476  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5477  */
5478 RETCODE
5480 {
5481  tdsdump_log(TDS_DBG_FUNC, "dbmny4zero(%p, %p)\n", dbproc, dest);
5482  CHECK_CONN(FAIL);
5483  CHECK_NULP(dest, "dbmny4zero", 2, FAIL);
5484 
5485  dest->mny4 = 0;
5486  return SUCCEED;
5487 }
5488 
5489 /**
5490  * \ingroup dblib_money
5491  * \brief Add two DBMONEY4 values.
5492  *
5493  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5494  * \param m1 first operand.
5495  * \param m2 other operand.
5496  * \param sum \em output: result of computation.
5497  * \retval SUCCEED usually.
5498  * \retval FAIL on overflow.
5499  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5500  */
5501 RETCODE
5503 {
5504  tdsdump_log(TDS_DBG_FUNC, "dbmny4add(%p, %p, %p, %p)\n", dbproc, m1, m2, sum);
5505  CHECK_CONN(FAIL);
5506  CHECK_NULP(m1, "dbmny4add", 2, FAIL);
5507  CHECK_NULP(m2, "dbmny4add", 3, FAIL);
5508  CHECK_NULP(sum, "dbmny4add", 4, FAIL);
5509 
5510  sum->mny4 = m1->mny4 + m2->mny4;
5511  if (((m1->mny4 < 0) && (m2->mny4 < 0) && (sum->mny4 >= 0))
5512  || ((m1->mny4 > 0) && (m2->mny4 > 0) && (sum->mny4 <= 0))) {
5513  /* overflow */
5514  sum->mny4 = 0;
5515  return FAIL;
5516  }
5517  return SUCCEED;
5518 }
5519 
5520 /**
5521  * \ingroup dblib_money
5522  * \brief Subtract two DBMONEY4 values.
5523  *
5524  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5525  * \param m1 first operand.
5526  * \param m2 other operand, subtracted from \a m1.
5527  * \param diff \em output: result of computation.
5528  * \retval SUCCEED usually.
5529  * \retval FAIL on overflow.
5530  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5531  */
5532 RETCODE
5534 {
5535 
5536  tdsdump_log(TDS_DBG_FUNC, "dbmny4sub(%p, %p, %p, %p)\n", dbproc, m1, m2, diff);
5537  CHECK_CONN(FAIL);
5538  CHECK_NULP(m1, "dbmny4sub", 2, FAIL);
5539  CHECK_NULP(m2, "dbmny4sub", 3, FAIL);
5540  CHECK_NULP(diff, "dbmny4sub", 4, FAIL);
5541 
5542  diff->mny4 = m1->mny4 - m2->mny4;
5543  if (((m1->mny4 <= 0) && (m2->mny4 > 0) && (diff->mny4 > 0))
5544  || ((m1->mny4 >= 0) && (m2->mny4 < 0) && (diff->mny4 < 0))) {
5545  /* overflow */
5546  diff->mny4 = 0;
5547  return FAIL;
5548  }
5549  return SUCCEED;
5550 }
5551 
5552 #if defined(DBLIB_UNIMPLEMENTED)
5553 /**
5554  * \ingroup dblib_money
5555  * \brief Multiply two DBMONEY4 values.
5556  *
5557  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5558  * \param m1 first operand.
5559  * \param m2 other operand.
5560  * \param prod \em output: result of computation.
5561  * \retval SUCCEED usually.
5562  * \retval FAIL a parameter is NULL.
5563  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5564  * \todo Unimplemented.
5565  */
5566 RETCODE
5567 dbmny4mul(DBPROCESS * dbproc, DBMONEY4 * m1, DBMONEY4 * m2, DBMONEY4 * prod)
5568 {
5569 
5570  tdsdump_log(TDS_DBG_FUNC, "dbmny4mul(%p, %p, %p, %p)\n", dbproc, m1, m2, prod);
5571  CHECK_CONN(FAIL);
5572  CHECK_NULP(m1, "dbmny4mul", 2, FAIL);
5573  CHECK_NULP(m2, "dbmny4mul", 3, FAIL);
5574  CHECK_NULP(prod, "dbmny4mul", 4, FAIL);
5575 
5576  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbmny4mul()\n");
5577  return FAIL;
5578 }
5579 
5580 /**
5581  * \ingroup dblib_money
5582  * \brief Divide two DBMONEY4 values.
5583  *
5584  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5585  * \param m1 dividend.
5586  * \param m2 divisor.
5587  * \param quotient \em output: result of computation.
5588  * \retval SUCCEED usually.
5589  * \retval FAIL a parameter is NULL.
5590  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5591  * \todo Unimplemented.
5592  */
5593 RETCODE
5594 dbmny4divide(DBPROCESS * dbproc, DBMONEY4 * m1, DBMONEY4 * m2, DBMONEY4 * quotient)
5595 {
5596 
5597  tdsdump_log(TDS_DBG_FUNC, "dbmny4divide(%p, %p, %p, %p)\n", dbproc, m1, m2, quotient);
5598  CHECK_CONN(FAIL);
5599  CHECK_NULP(m1, "dbmny4divide", 2, FAIL);
5600  CHECK_NULP(m2, "dbmny4divide", 3, FAIL);
5601  CHECK_NULP(quotient, "dbmny4divide", 4, FAIL);
5602 
5603  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbmny4divide()\n");
5604  return FAIL;
5605 }
5606 #endif
5607 
5608 /**
5609  * \ingroup dblib_money
5610  * \brief Compare two DBMONEY4 values.
5611  *
5612  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5613  * \param m1 some money.
5614  * \param m2 some other money.
5615  * \retval 0 m1 == m2.
5616  * \retval -1 m1 < m2.
5617  * \retval 1 m1 > m2.
5618  * \sa dbmnyadd(), dbmnysub(), dbmnymul(), dbmnydivide(), dbmnyminus(), dbmny4add(), dbmny4sub(), dbmny4mul(), dbmny4divide(), dbmny4minus().
5619  */
5620 int
5622 {
5623 
5624  tdsdump_log(TDS_DBG_FUNC, "dbmny4cmp(%p, %p, %p)\n", dbproc, m1, m2);
5626  CHECK_NULP(m1, "dbmny4cmp", 2, 0);
5627  CHECK_NULP(m2, "dbmny4cmp", 3, 0);
5628 
5629  if (m1->mny4 < m2->mny4) {
5630  return -1;
5631  }
5632  if (m1->mny4 > m2->mny4) {
5633  return 1;
5634  }
5635  return 0;
5636 }
5637 
5638 /**
5639  * \ingroup dblib_money
5640  * \brief Copy a DBMONEY4 value.
5641  *
5642  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5643  * \param src address of a DBMONEY4 structure.
5644  * \param dest \em output: new money.
5645  * \retval SUCCEED or FAIL if src/dest NULL.
5646  * \sa dbmnycopy(), dbmnyminus(), dbmny4minus().
5647  */
5648 RETCODE
5650 {
5651 
5652  tdsdump_log(TDS_DBG_FUNC, "dbmny4copy(%p, %p, %p)\n", dbproc, src, dest);
5653  CHECK_CONN(FAIL);
5654  CHECK_NULP(src, "dbmny4copy", 2, FAIL);
5655  CHECK_NULP(dest, "dbmny4copy", 3, FAIL);
5656 
5657  dest->mny4 = src->mny4;
5658  return SUCCEED;
5659 }
5660 
5661 /**
5662  * \ingroup dblib_datetime
5663  * \brief Compare DBDATETIME values, similar to strcmp(3).
5664  *
5665  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5666  * \param d1 a \c DBDATETIME structure address
5667  * \param d2 another \c DBDATETIME structure address
5668  * \retval 0 d1 = d2.
5669  * \retval -1 d1 < d2.
5670  * \retval 1 d1 > d2.
5671  * \sa dbdate4cmp(), dbmnycmp(), dbmny4cmp().
5672  */
5673 int
5675 {
5676  tdsdump_log(TDS_DBG_FUNC, "dbdatecmp(%p, %p, %p)\n", dbproc, d1, d2);
5677  CHECK_CONN(FAIL);
5678  CHECK_NULP(d1, "dbdatecmp", 2, 0);
5679  CHECK_NULP(d2, "dbdatecmp", 3, 0);
5680 
5681  if (d1->dtdays == d2->dtdays) {
5682  if (d1->dttime == d2->dttime)
5683  return 0;
5684  return d1->dttime > d2->dttime ? 1 : -1;
5685  }
5686 
5687  /* date 1 is before 1900 */
5688  if (d1->dtdays > 2958463) {
5689 
5690  if (d2->dtdays > 2958463) /* date 2 is before 1900 */
5691  return d1->dtdays > d2->dtdays ? 1 : -1;
5692  return -1;
5693  }
5694 
5695  /* date 1 is after 1900 */
5696  if (d2->dtdays < 2958463) /* date 2 is after 1900 */
5697  return d1->dtdays > d2->dtdays ? 1 : -1;
5698  return 1;
5699 }
5700 
5701 static RETCODE
5702 dblib_datecrack(DBPROCESS * dbproc, BOOL nano_precision, DBDATEREC * output, int type, const void * data)
5703 {
5704  TDSDATEREC dr;
5705  struct tds_sybase_dbdaterec *di = (struct tds_sybase_dbdaterec*) output;
5706 
5707  tdsdump_log(TDS_DBG_FUNC, "dblib_datecrack(%p, %d, %p, %d, %p)\n", dbproc, nano_precision, output, type, data);
5708  CHECK_NULP(output, "dbdatecrack", 2, FAIL);
5710 
5711  if (TDS_FAILED(tds_datecrack(type, data, &dr)))
5712  return FAIL;
5713 
5714  di->dateyear = dr.year;
5715  di->quarter = dr.quarter;
5716  di->datemonth = dr.month;
5717  di->datedmonth = dr.day;
5718  di->datedyear = dr.dayofyear;
5719  di->datedweek = dr.weekday;
5720  di->datehour = dr.hour;
5721  di->dateminute = dr.minute;
5722  di->datesecond = dr.second;
5723  di->datetzone = dr.timezone;
5724  if (nano_precision)
5725  /* here we are writing to nanosecond field */
5726  di->datemsecond = dr.decimicrosecond * 100u;
5727  else
5728  di->datemsecond = dr.decimicrosecond / 10000u;
5729  /* Revert to compiled-in default if dbproc can't be used to find the runtime override. */
5730  if (dbproc ? dbproc->msdblib : dblib_msdblib) {
5731  ++di->quarter;
5732  ++di->datemonth;
5733  ++di->datedweek;
5734  }
5735  return SUCCEED;
5736 }
5737 
5738 /**
5739  * \ingroup dblib_core
5740  * \brief Break a DBDATETIME value into useful pieces.
5741  *
5742  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5743  * \param di \em output: structure to contain the exploded parts of \a datetime.
5744  * \param datetime \em input: \c DBDATETIME to be converted.
5745  * \retval SUCCEED always.
5746  * \remarks The members of \a di have different names, depending on whether \c --with-msdblib was configured.
5747  *
5748  * If DBPROCESS is NULL, dbdatecrack() uses the compiled in default
5749  * value of MSDBLIB as of when libsybdb was compiled, irrespective of its value when the
5750  * application is compiled. This can lead to incorrect results because Sybase and Microsoft use different
5751  * ranges -- [0,11] vs. [1,12] -- for the month.
5752  *
5753  * \sa dbconvert(), dbdata(), dbdatechar(), dbdatename(), dbdatepart(), tdsdbopen().
5754  */
5755 RETCODE
5757 {
5758  return dblib_datecrack(dbproc, FALSE, di, SYBDATETIME, datetime);
5759 }
5760 
5761 /**
5762  * \ingroup dblib_core
5763  * \brief Break any kind of date or time value into useful pieces.
5764  *
5765  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5766  * \param di \em output: structure to contain the exploded parts of \a datetime.
5767  * \param type \em input: \c type of date/time value returned by dbcoltype().
5768  * \param data \em input: \c date/time value to be converted.
5769  * \retval SUCCEED always.
5770  * \remarks The members of \a di have different names, depending on whether \c --with-msdblib was configured.
5771  *
5772  * This is an extension to dbdatecrack(), see it for more information.
5773  *
5774  * \sa dbdatecrack(), dbconvert(), dbdata(), dbdatechar(), dbdatename(), dbdatepart(), tdsdbopen().
5775  */
5776 RETCODE
5778 {
5779  return dblib_datecrack(dbproc, TRUE, (DBDATEREC *) di, type, data);
5780 }
5781 
5782 #if defined(DBLIB_UNIMPLEMENTED)
5783 /**
5784  * \ingroup dblib_core
5785  * \brief Clear remote passwords from the LOGINREC structure.
5786  *
5787  * \param login structure to pass to dbopen().
5788  * \sa dblogin(), dbopen(), dbrpwset(), DBSETLAPP(), DBSETLHOST(), DBSETLPWD(), DBSETLUSER().
5789  * \remarks Useful for remote stored procedure calls, but not in high demand from FreeTDS.
5790  * \todo Unimplemented.
5791  */
5792 void
5793 dbrpwclr(LOGINREC * login)
5794 {
5795  tdsdump_log(TDS_DBG_FUNC, "dbrpwclr(%p)\n", login);
5796  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbrpwclr()\n");
5797 }
5798 
5799 /**
5800  * \ingroup dblib_core
5801  * \brief Add a remote password to the LOGINREC structure.
5802  *
5803  * \param login structure to pass to dbopen().
5804  * \param srvname server for which \a password should be used.
5805  * \param password you guessed it, let's hope no else does.
5806  * \param pwlen count of \a password, in bytes.
5807  * \remarks Useful for remote stored procedure calls, but not in high demand from FreeTDS.
5808  * \sa dblogin(), dbopen(), dbrpwclr(), DBSETLAPP(), DBSETLHOST(), DBSETLPWD(), DBSETLUSER().
5809  * \todo Unimplemented.
5810  */
5811 RETCODE
5812 dbrpwset(LOGINREC * login, char *srvname, char *password, int pwlen)
5813 {
5814  tdsdump_log(TDS_DBG_FUNC, "dbrpwset(%p, %s, %s, %d)\n", login, srvname, password, pwlen);
5815  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbrpwset()\n");
5816  return SUCCEED;
5817 }
5818 #endif
5819 
5820 /**
5821  * \ingroup dblib_core
5822  * \brief Get server process ID for a \c DBPROCESS.
5823  *
5824  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5825  * \return \em "spid", the server's process ID.
5826  * \sa dbopen().
5827  */
5828 int
5830 {
5831  tdsdump_log(TDS_DBG_FUNC, "dbspid(%p)\n", dbproc);
5832  CHECK_CONN(-1);
5833 
5834  return dbproc->tds_socket->conn->spid;
5835 }
5836 
5837 /**
5838  * \ingroup dblib_core
5839  * \brief Associate client-allocated (and defined) data with a \c DBPROCESS.
5840  *
5841  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5842  * \param ptr address of client-defined data.
5843  * \remarks \a ptr is the location of user data that \c db-lib will associate with \a dbproc.
5844  * The client allocates the buffer addressed by \a ptr. \c db-lib never examines or uses the information;
5845  * it just stashes the pointer for later retrieval by the application with \c dbgetuserdata().
5846  * \sa dbgetuserdata().
5847  */
5848 void
5850 {
5851  tdsdump_log(TDS_DBG_FUNC, "dbsetuserdata(%p, %p)\n", dbproc, ptr);
5853 
5854  dbproc->user_data = ptr;
5855 }
5856 
5857 /**
5858  * \ingroup dblib_core
5859  * \brief Get address of user-allocated data from a \c DBPROCESS.
5860  *
5861  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5862  * \return address of user-defined data that \c db-lib associated with \a dbproc when the client called dbsetuserdata().
5863  * \retval undefined (probably \c NULL) dbsetuserdata() was not previously called.
5864  * \sa dbsetuserdata().
5865  */
5866 BYTE *
5868 {
5869  tdsdump_log(TDS_DBG_FUNC, "dbgetuserdata(%p)\n", dbproc);
5871 
5872  return dbproc->user_data;
5873 }
5874 
5875 /**
5876  * \ingroup dblib_core
5877  * \brief Specify a db-lib version level.
5878  *
5879  * \param version Any DBVERSION_* constant.
5880  * \retval SUCCEED if version was valid, FAIL otherwise.
5881  * \remarks Use the corresponding protocol version for subsequent connections.
5882  * \sa
5883  */
5884 RETCODE
5886 {
5887  tdsdump_log(TDS_DBG_FUNC, "dbsetversion(%d)\n", version);
5888 
5889  switch (version ) {
5890  case DBVERSION_42:
5891  case DBVERSION_46:
5892  case DBVERSION_100:
5893  case DBVERSION_70:
5894  case DBVERSION_71:
5895  case DBVERSION_72:
5896  case DBVERSION_73:
5897  case DBVERSION_74:
5900  return SUCCEED;
5901  default:
5902  break;
5903  }
5904 
5905  dbperror(NULL, SYBEIVERS, 0);
5906  return FAIL;
5907 }
5908 
5909 /**
5910  * \ingroup dblib_money
5911  * \brief Copy a DBMONEY value.
5912  *
5913  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5914  * \param src address of a DBMONEY structure.
5915  * \param dest \em output: new money.
5916  * \retval SUCCEED always, unless \a src or \a dest is \c NULL.
5917  * \sa
5918  */
5919 RETCODE
5921 {
5922  tdsdump_log(TDS_DBG_FUNC, "dbmnycopy(%p, %p, %p)\n", dbproc, src, dest);
5923  CHECK_CONN(FAIL);
5924  CHECK_NULP(src, "dbmnycopy", 2, FAIL);
5925  CHECK_NULP(dest, "dbmnycopy", 3, FAIL);
5926 
5927  dest->mnylow = src->mnylow;
5928  dest->mnyhigh = src->mnyhigh;
5929  return SUCCEED;
5930 }
5931 
5932 
5933 /**
5934  * \ingroup dblib_core
5935  * \brief Cancel the query currently being retrieved, discarding all pending rows.
5936  *
5937  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5938  * \sa
5939  */
5940 RETCODE
5942 {
5943  TDSRET rc;
5944  TDS_INT result_type;
5945 
5946  tdsdump_log(TDS_DBG_FUNC, "dbcanquery(%p)\n", dbproc);
5947  CHECK_CONN(FAIL);
5948 
5950  return FAIL;
5951 
5952  /* Just throw away all pending rows from the last query */
5953 
5955 
5956  if (TDS_FAILED(rc))
5957  return FAIL;
5958 
5960 
5961  return SUCCEED;
5962 }
5963 
5964 /**
5965  * \ingroup dblib_core
5966  * \brief Erase the command buffer, in case \c DBNOAUTOFREE was set with dbsetopt().
5967  *
5968  *
5969  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5970  * \sa dbcmd(), dbfcmd(), dbgetchar(), dbsqlexec(), dbsqlsend(), dbsetopt(), dbstrcpy(), dbstrlen().
5971  */
5972 void
5974 {
5975  tdsdump_log(TDS_DBG_FUNC, "dbfreebuf(%p)\n", dbproc);
5977 
5978  if (dbproc->dbbuf)
5980  dbproc->dbbufsz = 0;
5981 }
5982 
5983 /**
5984  * \ingroup dblib_core
5985  * \brief Reset an option.
5986  *
5987  * \param dbproc contains all information needed by db-lib to manage communications with the server.
5988  * \param option to be turned off.
5989  * \param param clearing some options requires a parameter, believe it or not.
5990  * \retval SUCCEED \a option and \a parameter seem sane.
5991  * \retval FAIL no such \a option.
5992  * \remarks Only the following options are recognized:
5993  - DBARITHABORT
5994  - DBARITHIGNORE
5995  - DBCHAINXACTS
5996  - DBFIPSFLAG
5997  - DBISOLATION
5998  - DBNOCOUNT
5999  - DBNOEXEC
6000  - DBPARSEONLY
6001  - DBSHOWPLAN
6002  - DBSTORPROCID
6003  - DBQUOTEDIDENT
6004  - DBSETTIME
6005  * \sa dbisopt(), dbsetopt().
6006  */
6007 RETCODE
6008 dbclropt(DBPROCESS * dbproc, int option, const char param[])
6009 {
6010  char *cmd;
6011 
6012  tdsdump_log(TDS_DBG_FUNC, "dbclropt(%p, %d, %s)\n", dbproc, option, param);
6013  CHECK_CONN(FAIL);
6014  if (option != DBSETTIME) {
6015  CHECK_NULP(param, "dbclropt", 3, FAIL);
6016  }
6017 
6018  if ((option < 0) || (option >= DBNUMOPTIONS)) {
6019  return FAIL;
6020  }
6021  dbproc->dbopts[option].factive = 0;
6022  switch (option) {
6023  case DBARITHABORT:
6024  case DBARITHIGNORE:
6025  case DBCHAINXACTS:
6026  case DBFIPSFLAG:
6027  case DBISOLATION:
6028  case DBNOCOUNT:
6029  case DBNOEXEC:
6030  case DBPARSEONLY:
6031  case DBSHOWPLAN:
6032  case DBSTORPROCID:
6033  case DBQUOTEDIDENT:
6034  /* server options (on/off) */
6035  if (asprintf(&cmd, "set %s off\n", dbproc->dbopts[option].text) < 0) {
6036  return FAIL;
6037  }
6039  free(cmd);
6040  break;
6041  case DBBUFFER:
6042  buffer_set_capacity(dbproc, 1); /* frees row_buf->rows */
6043  return SUCCEED;
6044  break;
6045  case DBSETTIME:
6047  /*
6048  * Use global value of query timeout set by dbsettime() if any,
6049  * otherwise set it to zero just like tds_init_socket() does.
6050  */
6051  if (g_dblib_ctx.query_timeout > 0) {
6053  } else {
6055  }
6057  return SUCCEED;
6058  break;
6059  default:
6060  break;
6061  }
6062  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbclropt(option = %d)\n", option);
6063  return FAIL;
6064 }
6065 
6066 /**
6067  * \ingroup dblib_core
6068  * \brief Get value of an option
6069  *
6070  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6071  * \param option the option
6072  * \param param a parameter to \a option.
6073  * \sa dbclropt(), dbsetopt().
6074  */
6075 DBBOOL
6076 dbisopt(DBPROCESS * dbproc, int option, const char param[])
6077 {
6078  tdsdump_log(TDS_DBG_FUNC, "dbisopt(%p, %d, %s)\n", dbproc, option, param);
6080  /* sometimes param can be NULL */
6081 
6082  if ((option < 0) || (option >= DBNUMOPTIONS)) {
6083  return FALSE;
6084  }
6085  return dbproc->dbopts[option].factive;
6086 }
6087 
6088 /** \internal
6089  * \ingroup dblib_internal
6090  * \brief Get number of the row currently being read.
6091  *
6092  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6093  * \return ostensibly the row number, or 0 if no rows have been read yet.
6094  * \retval 0 Always.
6095  * \sa DBCURROW(), dbclrbuf(), DBFIRSTROW(), dbgetrow(), DBLASTROW(), dbnextrow(), dbsetopt(),.
6096  * \todo Unimplemented.
6097  */
6098 DBINT
6100 {
6101  tdsdump_log(TDS_DBG_FUNC, "dbcurrow(%p)\n", dbproc);
6103  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbcurrow()\n");
6104  return 0;
6105 }
6106 
6107 
6108 /** \internal
6109  * \ingroup dblib_internal
6110  * \brief Get returned row's type.
6111  *
6112  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6113  * \sa DBROWTYPE().
6114  */
6115 STATUS
6117 {
6118  tdsdump_log(TDS_DBG_FUNC, "dbrowtype(%p)\n", dbproc);
6120  return dbproc->row_type;
6121 }
6122 
6123 
6124 /** \internal
6125  * \ingroup dblib_internal
6126  * \brief Get number of the row just returned.
6127  *
6128  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6129  * \sa DBCURROW().
6130  * \todo Unimplemented.
6131  */
6132 int
6134 {
6135  tdsdump_log(TDS_DBG_FUNC, "dbcurcmd(%p)\n", dbproc);
6137  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbcurcmd()\n");
6138  return 0;
6139 }
6140 
6141 
6142 /**
6143  * \ingroup dblib_core
6144  * \brief See if more commands are to be processed.
6145  *
6146  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6147  * \sa DBMORECMDS(). DBCMDROW(), dbresults(), DBROWS(), DBROWTYPE().
6148  */
6149 RETCODE
6151 {
6152  tdsdump_log(TDS_DBG_FUNC, "dbmorecmds(%p)\n", dbproc);
6153  CHECK_CONN(FAIL);
6154 
6155  if (dbproc->tds_socket->res_info == NULL) {
6156  return FAIL;
6157  }
6158 
6159  if (dbproc->tds_socket->res_info->more_results == 0) {
6160  tdsdump_log(TDS_DBG_FUNC, "more_results == 0; returns FAIL\n");
6161  return FAIL;
6162  }
6163 
6165 
6166  tdsdump_log(TDS_DBG_FUNC, "more_results == 1; returns SUCCEED\n");
6167 
6168  return SUCCEED;
6169 }
6170 
6171 /**
6172  * \ingroup dblib_rpc
6173  * \brief Get datatype of a stored procedure's return parameter.
6174  *
6175  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6176  * \param retnum Nth return parameter, between 1 and \c dbnumrets().
6177  * \return SYB* datatype token, or -1 if \a retnum is out of range.
6178  * \sa dbnextrow(), dbnumrets(), dbprtype(), dbresults(), dbretdata(), dbretlen(), dbretname(), dbrpcinit(), dbrpcparam().
6179  */
6180 int
6182 {
6183  TDSCOLUMN *colinfo;
6184 
6185  tdsdump_log(TDS_DBG_FUNC, "dbrettype(%p, %d)\n", dbproc, retnum);
6189 
6190  if (retnum < 1 || retnum > dbproc->tds_socket->param_info->num_cols)
6191  return -1;
6192 
6193  colinfo = dbproc->tds_socket->param_info->columns[retnum - 1];
6194 
6195  return tds_get_conversion_type(colinfo->column_type, colinfo->column_size);
6196 }
6197 
6198 /**
6199  * \ingroup dblib_core
6200  * \brief Get size of the command buffer, in bytes.
6201  *
6202  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6203  * \sa dbcmd(), dbfcmd(), dbfreebuf(), dbgetchar(), dbstrcpy().
6204  */
6205 int
6207 {
6208  tdsdump_log(TDS_DBG_FUNC, "dbstrlen(%p)\n", dbproc);
6210 
6211  return dbproc->dbbufsz;
6212 }
6213 
6214 
6215 /**
6216  * \ingroup dblib_core
6217  * \brief Get address of a position in the command buffer.
6218  *
6219  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6220  * \param pos offset within the command buffer, starting at \em 0.
6221  * \remarks A bit overspecialized, this one.
6222  * \sa dbcmd(), dbfcmd(), dbfreebuf(), dbstrcpy(), dbstrlen(),
6223  */
6224 char *
6226 {
6227  tdsdump_log(TDS_DBG_FUNC, "dbgetchar(%p, %d)\n", dbproc, pos);
6229  tdsdump_log(TDS_DBG_FUNC, "dbgetchar() bufsz = %d, pos = %d\n", dbproc->dbbufsz, pos);
6230 
6231  if (dbproc->dbbufsz > 0) {
6232  if (pos >= 0 && pos < (dbproc->dbbufsz - 1))
6233  return (char *) &dbproc->dbbuf[pos];
6234  else
6235  return NULL;
6236  } else
6237  return NULL;
6238 }
6239 
6240 /**
6241  * \ingroup dblib_core
6242  * \brief Get a copy of a chunk of the command buffer.
6243  *
6244  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6245  * \param start position in the command buffer to start copying from, starting from \em 0.
6246  * If start is past the end of the command buffer, dbstrcpy() inserts a null terminator at dest[0].
6247  * \param numbytes number of bytes to copy.
6248  - If -1, dbstrcpy() copies the whole command buffer.
6249  - If 0 dbstrcpy() writes a \c NULL to dest[0].
6250  - If the command buffer contains fewer than \a numbytes (taking \a start into account) dbstrcpy()
6251  copies the rest of it.
6252  * \param dest \em output: the buffer to write to. Make sure it's big enough.
6253  * \retval SUCCEED the inputs were valid and \a dest was affected.
6254  * \retval FAIL \a start < 0 or \a numbytes < -1.
6255  * \sa dbcmd(), dbfcmd(), dbfreebuf(), dbgetchar(), dbstrlen().
6256  */
6257 RETCODE
6258 dbstrcpy(DBPROCESS * dbproc, int start, int numbytes, char *dest)
6259 {
6260  tdsdump_log(TDS_DBG_FUNC, "dbstrcpy(%p, %d, %d, %s)\n", dbproc, start, numbytes, dest);
6261  CHECK_CONN(FAIL);
6262  CHECK_NULP(dest, "dbstrcpy", 4, FAIL);
6263 
6264  if (start < 0) {
6265  dbperror(dbproc, SYBENSIP, 0);
6266  return FAIL;
6267  }
6268  if (numbytes < -1) {
6269  dbperror(dbproc, SYBEBNUM, 0);
6270  return FAIL;
6271  }
6272  dest[0] = 0; /* start with empty string being returned */
6273  if (dbproc->dbbufsz > 0 && start < dbproc->dbbufsz) {
6274  if (numbytes == -1)
6275  numbytes = dbproc->dbbufsz - start;
6276  if (start + numbytes > dbproc->dbbufsz)
6277  numbytes = dbproc->dbbufsz - start;
6278  memcpy(dest, (char *) &dbproc->dbbuf[start], numbytes);
6279  dest[numbytes] = '\0';
6280  }
6281  return SUCCEED;
6282 }
6283 
6284 /**
6285  * \ingroup dblib_core
6286  * \brief safely quotes character values in SQL text.
6287  *
6288  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6289  * \param src input string.
6290  * \param srclen length of \a src in bytes, or -1 to indicate it's null-terminated.
6291  * \param dest \em output: client-provided output buffer.
6292  * \param destlen size of \a dest in bytes, or -1 to indicate it's "big enough" and the data should be null-terminated.
6293  * \param quotetype
6294  - \c DBSINGLE Doubles all single quotes (').
6295  - \c DBDOUBLE Doubles all double quotes (").
6296  - \c DBBOTH Doubles all single and double quotes.
6297  * \retval SUCCEED everything worked.
6298  * \retval FAIL no such \a quotetype, or insufficient room in \a dest.
6299  * \sa dbcmd(), dbfcmd().
6300  */
6301 RETCODE
6302 dbsafestr(DBPROCESS * dbproc, const char *src, DBINT srclen, char *dest, DBINT destlen, int quotetype)
6303 {
6304  int i, j = 0;
6305  int squote = FALSE, dquote = FALSE;
6306 
6307  tdsdump_log(TDS_DBG_FUNC, "dbsafestr(%p, %s, %d, %s, %d, %d)\n", dbproc, src, srclen, dest, destlen, quotetype);
6308  CHECK_NULP(src, "dbsafestr", 2, FAIL);
6309  CHECK_NULP(dest, "dbsafestr", 4, FAIL);
6310 
6311  /* check parameters */
6312  if (srclen < -1 || destlen < -1)
6313  return FAIL;
6314 
6315  if (srclen == -1)
6316  srclen = (int)strlen(src);
6317 
6318  if (quotetype == DBSINGLE || quotetype == DBBOTH)
6319  squote = TRUE;
6320  if (quotetype == DBDOUBLE || quotetype == DBBOTH)
6321  dquote = TRUE;
6322 
6323  /* return FAIL if invalid quotetype */
6324  if (!dquote && !squote)
6325  return FAIL;
6326 
6327 
6328  for (i = 0; i < srclen; i++) {
6329 
6330  /* dbsafestr returns fail if the deststr is not big enough */
6331  /* need one char + one for terminator */
6332  if (destlen >= 0 && j >= destlen)
6333  return FAIL;
6334 
6335  if (squote && src[i] == '\'')
6336  dest[j++] = '\'';
6337  else if (dquote && src[i] == '\"')
6338  dest[j++] = '\"';
6339 
6340  if (destlen >= 0 && j >= destlen)
6341  return FAIL;
6342 
6343  dest[j++] = src[i];
6344  }
6345 
6346  if (destlen >= 0 && j >= destlen)
6347  return FAIL;
6348 
6349  dest[j] = '\0';
6350  return SUCCEED;
6351 }
6352 
6353 /**
6354  * \ingroup dblib_core
6355  * \brief Print a token value's name to a buffer
6356  *
6357  * \param token server SYB* value, e.g. SYBINT.
6358 
6359  * \return ASCII null-terminated string.
6360  * \sa dbaltop(), dbalttype(), dbcoltype(), dbrettype().
6361  */
6362 const char *
6363 dbprtype(int token)
6364 {
6365  tdsdump_log(TDS_DBG_FUNC, "dbprtype(%d)\n", token);
6366  return tds_prtype(token);
6367 }
6368 
6369 /**
6370  * \ingroup dblib_core
6371  * \brief describe table column attributes with a single call (Freetds-only API function modelled on dbcolinfo)
6372  *
6373  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6374  * \param column Nth in the result set, starting from 1.
6375  * \param pdbcol address of structure to be populated by this function.
6376  * \return SUCCEED or FAIL.
6377  * \sa dbcolinfo().
6378  */
6379 RETCODE
6381 {
6382  TDSCOLUMN *colinfo;
6383 
6384  tdsdump_log(TDS_DBG_FUNC, "dbtablecolinfo(%p, %d, %p)\n", dbproc, column, pdbcol);
6385  CHECK_CONN(FAIL);
6386  CHECK_NULP(pdbcol, "dbtablecolinfo", 3, FAIL);
6387  DBPERROR_RETURN(pdbcol->SizeOfStruct != sizeof(DBCOL)
6388  && pdbcol->SizeOfStruct != sizeof(DBCOL2), SYBECOLSIZE);
6389 
6390  colinfo = dbcolptr(dbproc, column);
6391  if (!colinfo)
6392  return FAIL;
6393 
6394  strlcpy(pdbcol->Name, tds_dstr_cstr(&colinfo->column_name), sizeof(pdbcol->Name));
6395  strlcpy(pdbcol->ActualName, tds_dstr_cstr(&colinfo->column_name), sizeof(pdbcol->ActualName));
6396 
6397  pdbcol->Type = tds_get_conversion_type(colinfo->column_type, colinfo->column_size);
6398  pdbcol->UserType = colinfo->column_usertype;
6399  pdbcol->MaxLength = colinfo->column_size;
6400  if (colinfo->column_nullable)
6401  pdbcol->Null = TRUE;
6402  else
6403  pdbcol->Null = FALSE;
6404 
6405  pdbcol->VarLength = FALSE;
6406 
6407  if (colinfo->column_nullable
6408  || is_nullable_type(colinfo->column_type))
6409  pdbcol->VarLength = TRUE;
6410 
6411  pdbcol->Precision = colinfo->column_prec;
6412  pdbcol->Scale = colinfo->column_scale;
6413 
6414  pdbcol->Updatable = colinfo->column_writeable ? TRUE : FALSE;
6415  pdbcol->Identity = colinfo->column_identity ? TRUE : FALSE;
6416 
6417  if (pdbcol->SizeOfStruct >= sizeof(DBCOL2)) {
6418  DBCOL2 *col = (DBCOL2 *) pdbcol;
6419  TDSRET rc;
6420 
6421  col->ServerType = colinfo->on_server.column_type;
6422  col->ServerMaxLength = colinfo->on_server.column_size;
6423 
6425  if (TDS_FAILED(rc))
6426  return FAIL;
6427  }
6428 
6429  return SUCCEED;
6430 }
6431 
6432 /**
6433  * \ingroup dblib_core
6434  * \brief Get text timestamp for a column in the current row.
6435  *
6436  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6437  * \param column number of the column in the \c SELECT statement, starting at 1.
6438  * \return timestamp for \a column, may be NULL.
6439  * \sa dbtxptr(), dbwritetext().
6440  */
6441 DBBINARY *
6443 {
6444  TDSCOLUMN *colinfo;
6445  TDSBLOB *blob;
6446 
6447  tdsdump_log(TDS_DBG_FUNC, "dbtxtimestamp(%p, %d)\n", dbproc, column);
6448 
6449  colinfo = dbcolptr(dbproc, column);
6450  if (!colinfo || !is_blob_col(colinfo))
6451  return NULL;
6452 
6453  blob = (TDSBLOB *) colinfo->column_data;
6454 
6455  /* test if valid */
6456  if (!blob->valid_ptr)
6457  return NULL;
6458 
6459  return (DBBINARY *) blob->timestamp;
6460 }
6461 
6462 /**
6463  * \ingroup dblib_core
6464  * \brief Get text pointer for a column in the current row.
6465  *
6466  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6467  * \param column number of the column in the \c SELECT statement, starting at 1.
6468  * \return text pointer for \a column, may be NULL.
6469  * \sa dbtxtimestamp(), dbwritetext().
6470  */
6471 DBBINARY *
6473 {
6474  TDSCOLUMN *colinfo;
6475  TDSBLOB *blob;
6476 
6477  tdsdump_log(TDS_DBG_FUNC, "dbtxptr(%p, %d)\n", dbproc, column);
6478 
6479  colinfo = dbcolptr(dbproc, column);
6480  if (!colinfo || !is_blob_col(colinfo))
6481  return NULL;
6482 
6483  blob = (TDSBLOB *) colinfo->column_data;
6484 
6485  /* test if valid */
6486  if (!blob->valid_ptr)
6487  return NULL;
6488 
6489  return (DBBINARY *) blob->textptr;
6490 }
6491 
6492 /**
6493  * \ingroup dblib_core
6494  * \brief Send text or image data to the server.
6495  *
6496  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6497  * \param objname table name
6498  * \param textptr text pointer to be modified, obtained from dbtxptr().
6499  * \param textptrlen \em Ignored. Supposed to be \c DBTXPLEN.
6500  * \param timestamp text timestamp to be modified, obtained from dbtxtimestamp() or dbtxtsnewval(), may be \c NULL.
6501  * \param log \c TRUE if the operation is to be recorded in the transaction log.
6502  * \param size overall size of the data (in total, not just for this call), in bytes. A guideline, must not overstate the case.
6503  * \param text the chunk of data to write.
6504  * \retval SUCCEED everything worked.
6505  * \retval FAIL not sent, possibly because \a timestamp is invalid or was changed in the database since it was fetched.
6506  * \sa dbmoretext(), dbtxptr(), dbtxtimestamp(), dbwritetext(), dbtxtsput().
6507  */
6508 RETCODE
6509 dbwritetext(DBPROCESS * dbproc, char *objname, DBBINARY * textptr, DBTINYINT textptrlen, DBBINARY * timestamp, DBBOOL log,
6510  DBINT size, BYTE * text)
6511 {
6512  DBINT rc = 0;
6513  char textptr_string[35]; /* 16 * 2 + 2 (0x) + 1 */
6514  char timestamp_string[19]; /* 8 * 2 + 2 (0x) + 1 */
6515  TDS_INT result_type;
6516 
6517  tdsdump_log(TDS_DBG_FUNC, "dbwritetext(%p, %s, %p, %d, %p, %d)\n",
6518  dbproc, objname, textptr, textptrlen, timestamp, log);
6519  CHECK_CONN(FAIL);
6520  CHECK_NULP(objname, "dbwritetext", 2, FAIL);
6521  CHECK_NULP(textptr, "dbwritetext", 3, FAIL);
6522  CHECK_NULP(timestamp, "dbwritetext", 5, FAIL);
6524 
6526  return FAIL;
6527 
6528  if (textptrlen > DBTXPLEN)
6529  return FAIL;
6530 
6531  rc = dbconvert(dbproc, SYBBINARY, (BYTE *) textptr, textptrlen,
6532  SYBCHAR, (BYTE *) textptr_string, -1);
6533  if (rc < 0)
6534  return FAIL;
6535  rc = dbconvert(dbproc, SYBBINARY, (BYTE *) timestamp, 8, SYBCHAR,
6536  (BYTE *) timestamp_string, -1);
6537  if (rc < 0)
6538  return FAIL;
6539 
6541 
6542  if (dbproc->tds_socket->state == TDS_PENDING) {
6543  const TDSRET ret = tds_process_tokens(dbproc->tds_socket, &result_type, NULL, TDS_TOKEN_TRAILING);
6544  if (ret != TDS_NO_MORE_RESULTS) {
6545  dbperror(dbproc, SYBERPND, 0);
6547  return FAIL;
6548  }
6549  }
6550 
6552  textptr_string, timestamp_string, (log == TRUE), size)))
6553  return FAIL;
6554 
6555  if (!text) {
6556  dbproc->text_size = size;
6557  dbproc->text_sent = 0;
6558  return SUCCEED;
6559  }
6560 
6563  dbproc->text_sent = 0;
6564 
6565  if (dbsqlok(dbproc) == SUCCEED && dbresults(dbproc) == SUCCEED)
6566  return SUCCEED;
6567  return FAIL;
6568 }
6569 
6570 /**
6571  * \ingroup dblib_core
6572  * \brief Fetch part of a text or image value from the server.
6573  *
6574  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6575  * \param buf \em output: buffer into which text will be placed.
6576  * \param bufsize size of \a buf, in bytes.
6577  * \return
6578  - \c >0 count of bytes placed in \a buf.
6579  - \c 0 end of row.
6580  - \c -1 \em error, no result set ready for \a dbproc.
6581  - \c NO_MORE_ROWS all rows read, no further data.
6582  * \sa dbmoretext(), dbnextrow(), dbwritetext().
6583  */
6584 STATUS
6586 {
6587  TDSSOCKET *tds;
6588  TDSCOLUMN *curcol;
6589  int cpbytes, bytes_avail;
6590  TDS_INT result_type;
6591  TDSRESULTINFO *resinfo;
6592 
6593  tdsdump_log(TDS_DBG_FUNC, "dbreadtext(%p, %p, %d)\n", dbproc, buf, bufsize);
6595  CHECK_NULP(buf, "dbreadtext", 2, -1);
6596 
6597  tds = dbproc->tds_socket;
6598 
6599  if (!tds || !tds->res_info || !tds->res_info->columns[0])
6600  return -1;
6601 
6602  resinfo = tds->res_info;
6603  curcol = resinfo->columns[0];
6604 
6605  /*
6606  * if the current position is beyond the end of the text
6607  * set pos to 0 and return 0 to denote the end of the
6608  * text
6609  */
6610  if (curcol->column_textpos && curcol->column_textpos >= curcol->column_cur_size) {
6611  curcol->column_textpos = 0;
6612  return 0;
6613  }
6614 
6615  /*
6616  * if pos is 0 (first time through or last call exhausted the text)
6617  * then read another row
6618  */
6619 
6620  if (curcol->column_textpos == 0) {
6623  switch (tds_process_tokens(dbproc->tds_socket, &result_type, NULL, mask)) {
6624  case TDS_SUCCESS:
6625  if (result_type == TDS_ROW_RESULT || result_type == TDS_COMPUTE_RESULT)
6626  break;
6627  case TDS_NO_MORE_RESULTS:
6628  return NO_MORE_ROWS;
6629  default:
6630  return -1;
6631  }
6632  }
6633 
6634  /* find the number of bytes to return */
6635  bytes_avail = curcol->column_cur_size - curcol->column_textpos;
6636  cpbytes = bytes_avail > bufsize ? bufsize : bytes_avail;
6637  memcpy(buf, &((TDSBLOB *) curcol->column_data)->textvalue[curcol->column_textpos], cpbytes);
6638  curcol->column_textpos += cpbytes;
6639  return cpbytes;
6640 }
6641 
6642 /**
6643  * \ingroup dblib_core
6644  * \brief Send chunk of a text/image value to the server.
6645  *
6646  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6647  * \param size count of bytes to send.
6648  * \param text textpointer, obtained from dbtxptr.
6649  * \retval SUCCEED always.
6650  * \sa dbtxptr(), dbtxtimestamp(), dbwritetext().
6651  * \todo Check return value of called functions and return \c FAIL if appropriate.
6652  */
6653 RETCODE
6655 {
6656  tdsdump_log(TDS_DBG_FUNC, "dbmoretext(%p, %d, %p)\n", dbproc, size, text);
6657  CHECK_CONN(FAIL);
6658  CHECK_NULP(text, "dbmoretext", 3, FAIL);
6659 
6661 
6662  /* TODO this test should be inside tds_writetext_continue, currently not */
6663  if (size < 0 || size > dbproc->text_size - dbproc->text_sent)
6664  return FAIL;
6665 
6666  if (size) {
6668  return FAIL;
6669  dbproc->text_sent += size;
6670 
6671  if (dbproc->text_sent == dbproc->text_size) {
6673  dbproc->text_sent = 0;
6674  }
6675  }
6676 
6677  return SUCCEED;
6678 }
6679 
6680 /**
6681  * \ingroup dblib_core
6682  * \brief Record to a file all SQL commands sent to the server
6683  *
6684  * \param filename name of file to write to.
6685  * \remarks Files are named \em filename.n, where n is an integer, starting with 0, and incremented with each callto dbopen().
6686  * \sa dbopen(), TDSDUMP environment variable().
6687  */
6688 void
6689 dbrecftos(const char filename[])
6690 {
6691  char *f;
6692 
6693  tdsdump_log(TDS_DBG_FUNC, "dbrecftos(%s)\n", filename);
6694  if (filename == NULL) {
6695  dbperror(NULL, SYBENULP, 0);
6696  return;
6697  }
6698 
6699  f = strdup(filename);
6700  if (!f) {
6701  dbperror(NULL, SYBEMEM, 0);
6702  return;
6703  }
6704 
6710 }
6711 
6712 /** \internal
6713  * \ingroup dblib_internal
6714  * \brief Get the TDS version in use for \a dbproc.
6715  *
6716  *
6717  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6718  * \return a \c DBTDS* token.
6719  * \remarks The integer values of the constants are counterintuitive.
6720  * \sa DBTDS().
6721  */
6722 int
6724 {
6725  tdsdump_log(TDS_DBG_FUNC, "dbtds(%p)\n", dbproc);
6727 
6728  if (dbproc->tds_socket) {
6729  switch (dbproc->tds_socket->conn->tds_version) {
6730  case 0x402:
6731  return DBTDS_4_2;
6732  case 0x406:
6733  return DBTDS_4_6;
6734  case 0x500:
6735  return DBTDS_5_0;
6736  case 0x700:
6737  return DBTDS_7_0;
6738  case 0x701:
6739  return DBTDS_7_1;
6740  case 0x702:
6741  return DBTDS_7_2;
6742  case 0x703:
6743  return DBTDS_7_3;
6744  case 0x704:
6745  return DBTDS_7_4;
6746  default:
6747  return DBTDS_UNKNOWN;
6748  }
6749  }
6750  return -1;
6751 }
6752 
6753 /**
6754  * \ingroup dblib_core
6755  * \brief See which version of db-lib is in use.
6756  *
6757  * \return null-terminated ASCII string representing the version of db-lib.
6758  * \remarks FreeTDS returns the CVS version string of dblib.c.
6759  * \sa
6760  */
6761 const char *
6763 {
6764  tdsdump_log(TDS_DBG_FUNC, "dbversion(void)\n");
6765  return TDS_VERSION_NO;
6766 }
6767 
6768 #if defined(DBLIB_UNIMPLEMENTED)
6769 /**
6770  * \ingroup dblib_core
6771  * \brief Set the default character set.
6772  *
6773  * \param charset null-terminated ASCII string, matching a row in master..syscharsets.
6774  * \sa dbsetdeflang(), dbsetdefcharset(), dblogin(), dbopen().
6775  * \todo Unimplemented.
6776  */
6777 RETCODE
6778 dbsetdefcharset(char *charset)
6779 {
6780  tdsdump_log(TDS_DBG_FUNC, "dbsetdefcharset(%s)\n", charset);
6781  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbsetdefcharset()\n");
6782  return SUCCEED;
6783 }
6784 
6785 /**
6786  * \ingroup dblib_core
6787  * \brief Ready execution of a registered procedure.
6788  *
6789  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6790  * \param procedure_name to call.
6791  * \param namelen size of \a procedure_name, in bytes.
6792  * \sa dbregparam(), dbregexec(), dbregwatch(), dbreglist(), dbregwatchlist
6793  * \todo Unimplemented.
6794  */
6795 RETCODE
6796 dbreginit(DBPROCESS * dbproc, DBCHAR * procedure_name, DBSMALLINT namelen)
6797 {
6798  tdsdump_log(TDS_DBG_FUNC, "dbreginit(%p, %s, %d)\n", dbproc, procedure_name, namelen);
6799  CHECK_CONN(FAIL);
6800  CHECK_NULP(procedure_name, "dbreginit", 2, FAIL);
6801  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbreginit()\n");
6802  return SUCCEED;
6803 }
6804 
6805 
6806 /**
6807  * \ingroup dblib_core
6808  * \brief Get names of Open Server registered procedures.
6809  *
6810  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6811  * \sa dbregparam(), dbregexec(), dbregwatch(), dbreglist(), dbregwatchlist().
6812  * \todo Unimplemented.
6813  */
6814 RETCODE
6815 dbreglist(DBPROCESS * dbproc)
6816 {
6817  tdsdump_log(TDS_DBG_FUNC, "dbreglist(%p)\n", dbproc);
6818  CHECK_CONN(FAIL);
6819  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbreglist()\n");
6820  return SUCCEED;
6821 }
6822 
6823 
6824 /**
6825  * \ingroup dblib_core
6826  * \brief Describe parameter of registered procedure .
6827  *
6828  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6829  * \param param_name
6830  * \param type \c SYB* datatype.
6831  * \param datalen size of \a data.
6832  * \param data address of buffer holding value for the parameter.
6833  * \sa dbreginit(), dbregexec(), dbnpdefine(), dbnpcreate(), dbregwatch().
6834  * \todo Unimplemented.
6835  */
6836 RETCODE
6837 dbregparam(DBPROCESS * dbproc, char *param_name, int type, DBINT datalen, BYTE * data)
6838 {
6839  tdsdump_log(TDS_DBG_FUNC, "dbregparam(%p, %s, %d, %d, %p)\n", dbproc, param_name, type, datalen, data);
6840  CHECK_CONN(FAIL);
6841  CHECK_NULP(param_name, "dbregparam", 2, FAIL);
6842  CHECK_NULP(data, "dbregparam", 5, FAIL);
6843  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbregparam()\n");
6844  return SUCCEED;
6845 }
6846 
6847 
6848 /**
6849  * \ingroup dblib_core
6850  * \brief Execute a registered procedure.
6851  *
6852  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6853  * \param options
6854  * \sa dbreginit(), dbregparam(), dbregwatch(), dbregnowatch
6855  * \todo Unimplemented.
6856  */
6857 RETCODE
6858 dbregexec(DBPROCESS * dbproc, DBUSMALLINT options)
6859 {
6860  tdsdump_log(TDS_DBG_FUNC, "dbregexec(%p, %d)\n", dbproc, options);
6861  CHECK_CONN(FAIL);
6862  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbregexec()\n");
6863  return SUCCEED;
6864 }
6865 #endif
6866 
6867 
6868 /**
6869  * \ingroup dblib_datetime
6870  * \brief Get name of a month, in some human language.
6871  *
6872  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6873  * \param language \em ignored.
6874  * \param monthnum number of the month, starting with 1.
6875  * \param shortform set to \c TRUE for a three letter output ("Jan" - "Dec"), else zero.
6876  * \return address of null-terminated ASCII string, or \c NULL on error.
6877  * \sa db12hour(), dbdateorder(), dbdayname(), DBSETLNATLANG(), dbsetopt().
6878  */
6879 const char *
6880 dbmonthname(DBPROCESS * dbproc, char *language, int monthnum, DBBOOL shortform)
6881 {
6882  static const char shortmon[][4] = {
6883  "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
6884  };
6885  static const char longmon[][12] = {
6886  "January", "February", "March", "April", "May", "June",
6887  "July", "August", "September", "October", "November", "December"
6888  };
6889 
6890  tdsdump_log(TDS_DBG_FUNC, "dbmonthname(%p, %s, %d, %d)\n", dbproc, language, monthnum, shortform);
6892  CHECK_NULP(language, "dbmonthname", 2, NULL);
6893 
6894  if (monthnum < 1 || monthnum > 12)
6895  return NULL;
6896  return (shortform) ? shortmon[monthnum - 1] : longmon[monthnum - 1];
6897 }
6898 
6899 /**
6900  * \ingroup dblib_core
6901  * \brief See if a command caused the current database to change.
6902  *
6903  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6904  * \return name of new database, if changed, as a null-terminated ASCII string, else \c NULL.
6905 
6906  * \sa dbname(), dbresults(), dbsqlexec(), dbsqlsend(), dbuse().
6907  */
6908 char *
6910 {
6911  tdsdump_log(TDS_DBG_FUNC, "dbchange(%p)\n", dbproc);
6913 
6914  if (dbproc->envchange_rcv & (1 << (TDS_ENV_DATABASE - 1))) {
6915  return dbproc->dbcurdb;
6916  }
6917  return NULL;
6918 }
6919 
6920 /**
6921  * \ingroup dblib_core
6922  * \brief Get name of current database.
6923  *
6924  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6925  * \return current database name, as null-terminated ASCII string.
6926  * \sa dbchange(), dbuse().
6927  */
6928 char *
6930 {
6931  tdsdump_log(TDS_DBG_FUNC, "dbname(%p)\n", dbproc);
6933  return dbproc->dbcurdb;
6934 }
6935 
6936 /**
6937  * \ingroup dblib_core
6938  * \brief Get \c syscharset name of the server character set.
6939  *
6940  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6941  * \return name of server's charset, as null-terminated ASCII string.
6942  * \sa dbcharsetconv(), dbgetcharset(), DBSETLCHARSET().
6943  */
6944 char *
6946 {
6947 
6948  tdsdump_log(TDS_DBG_FUNC, "dbservcharset(%p)\n", dbproc);
6950 
6951  return dbproc->servcharset;
6952 }
6953 
6954 /**
6955  * \ingroup dblib_core
6956  * \brief Transmit the command buffer to the server. \em Non-blocking, does not wait for a response.
6957  *
6958  * \param dbproc contains all information needed by db-lib to manage communications with the server.
6959  * \retval SUCCEED SQL sent.
6960  * \retval FAIL protocol problem, unless dbsqlsend() when it's not supposed to be (in which case a db-lib error
6961  message will be emitted).
6962  * \sa dbcmd(), dbfcmd(), DBIORDESC(), DBIOWDESC(), dbnextrow(), dbpoll(), dbresults(), dbsettime(), dbsqlexec(), dbsqlok().
6963  */
6964 RETCODE
6966 {
6967  TDSSOCKET *tds;
6968  char *cmdstr;
6969  TDSRET rc;
6970  TDS_INT result_type;
6971  char timestr[256];
6972 
6973  tdsdump_log(TDS_DBG_FUNC, "dbsqlsend(%p)\n", dbproc);
6974  CHECK_CONN(FAIL);
6975 
6976  tds = dbproc->tds_socket;
6977 
6978  if (tds->state == TDS_PENDING) {
6979 
6981  dbperror(dbproc, SYBERPND, 0);
6983  return FAIL;
6984  }
6985  }
6986 
6987  if (dbproc->dboptcmd) {
6988  if ((cmdstr = dbstring_get(dbproc->dboptcmd)) == NULL) {
6989  dbperror(dbproc, SYBEASEC, 0); /* Attempt to send an empty command buffer to the server */
6990  return FAIL;
6991  }
6992  rc = tds_submit_query(dbproc->tds_socket, cmdstr);
6993  free(cmdstr);
6995  if (TDS_FAILED(rc)) {
6996  return FAIL;
6997  }
6998  dbproc->avail_flag = FALSE;
6999  dbproc->envchange_rcv = 0;
7001  while ((rc = tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS))
7002  == TDS_SUCCESS);
7003  if (rc != TDS_NO_MORE_RESULTS) {
7004  return FAIL;
7005  }
7006  }
7008 
7009  if (dbproc->ftos != NULL) {
7010  fprintf(dbproc->ftos, "%s\n", dbproc->dbbuf);
7011  fprintf(dbproc->ftos, "go /* %s */\n", _dbprdate(timestr));
7012  fflush(dbproc->ftos);
7013  }
7014 
7016  return FAIL;
7017  }
7018  dbproc->avail_flag = FALSE;
7019  dbproc->envchange_rcv = 0;
7022  return SUCCEED;
7023 }
7024 
7025 /**
7026  * \ingroup dblib_core
7027  * \brief Get user-defined datatype of a compute column.
7028  *
7029  * \param dbproc contains all information needed by db-lib to manage communications with the server.
7030  * \param computeid of \c COMPUTE clause to which we're referring.
7031  * \param column Nth column in \a computeid, starting from 1.
7032  * \returns user-defined datatype of compute column, else -1.
7033  * \sa dbalttype(), dbcolutype().
7034  */
7035 DBINT
7036 dbaltutype(DBPROCESS * dbproc, int computeid, int column)
7037 {
7038  TDSCOLUMN *colinfo;
7039 
7040  tdsdump_log(TDS_DBG_FUNC, "dbaltutype(%p, %d, %d)\n", dbproc, computeid, column);
7042 
7043  colinfo = dbacolptr(dbproc, computeid, column, 0);
7044  if (!colinfo)
7045  return -1;
7046 
7047  return colinfo->column_usertype;
7048 }
7049 
7050 /**
7051  * \ingroup dblib_core
7052  * \brief Get size of data in compute column.
7053  *
7054  * \param dbproc contains all information needed by db-lib to manage communications with the server.
7055  * \param computeid of \c COMPUTE clause to which we're referring.
7056  * \param column Nth column in \a computeid, starting from 1.
7057  * \sa dbadata(), dbadlen(), dbalttype(), dbgetrow(), dbnextrow(), dbnumalts().
7058  */
7059 DBINT
7060 dbaltlen(DBPROCESS * dbproc, int computeid, int column)
7061 {
7062  TDSCOLUMN *colinfo;
7063 
7064  tdsdump_log(TDS_DBG_FUNC, "dbaltlen(%p, %d, %d)\n", dbproc, computeid, column);
7065 
7066  colinfo = dbacolptr(dbproc, computeid, column, 0);
7067  if (!colinfo)
7068  return -1;
7069 
7070  return colinfo->column_size;
7071 
7072 }
7073 
7074 /**
7075  * \ingroup dblib_core
7076  * \brief See if a server response has arrived.
7077  *
7078  * \param dbproc contains all information needed by db-lib to manage communications with the server.
7079  * \param milliseconds how long to wait for the server before returning:
7080  - \c 0 return immediately.
7081  - \c -1 do not return until the server responds or a system interrupt occurs.
7082  * \param ready_dbproc \em output: DBPROCESS for which a response arrived, of \c NULL.
7083  * \param return_reason \em output:
7084  - \c DBRESULT server responded.
7085  - \c DBNOTIFICATION registered procedure notification has arrived. dbpoll() the registered handler, if
7086  any, before it returns.
7087  - \c DBTIMEOUT \a milliseconds elapsed before the server responded.
7088  - \c DBINTERRUPT operating-system interrupt occurred before the server responded.
7089  * \retval SUCCEED everything worked.
7090  * \retval FAIL a server connection died.
7091  * \sa DBIORDESC(), DBRBUF(), dbresults(), dbreghandle(), dbsqlok().
7092  * \todo Unimplemented.
7093  */
7094 #if defined(DBLIB_UNIMPLEMENTED)
7095 RETCODE
7096 dbpoll(DBPROCESS * dbproc, long milliseconds, DBPROCESS ** ready_dbproc, int *return_reason)
7097 {
7098  tdsdump_log(TDS_DBG_FUNC, "dbpoll(%p, %ld, %p, %p)\n", dbproc, milliseconds, ready_dbproc, return_reason);
7099  CHECK_CONN(FAIL);
7100  CHECK_NULP(ready_dbproc, "dbpoll", 3, FAIL);
7101  CHECK_NULP(return_reason, "dbpoll", 4, FAIL);
7102  tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED dbpoll()\n");
7103  return SUCCEED;
7104 }
7105 #endif
7106 
7107 /** \internal
7108  * \ingroup dblib_internal
7109  * \brief Get number of the first row in the row buffer.
7110  *
7111  * \param dbproc contains all information needed by db-lib to manage communications with the server.
7112  * \sa DBFIRSTROW(), dbclrbuf(), DBCURROW(), dbgetrow(), DBLASTROW(), dbnextrow(), dbsetopt().
7113  */
7114 DBINT
7116 {
7117  tdsdump_log(TDS_DBG_FUNC, "dbfirstrow(%p)\n", dbproc);
7118  CHECK_CONN(0);
7120 }
7121 
7122 /** \internal
7123  * \ingroup dblib_internal
7124  * \brief Get number of the last row in the row buffer.
7125  *
7126  * \param dbproc contains all information needed by db-lib to manage communications with the server.
7127  * \sa DBLASTROW(), dbclrbuf(), DBCURROW(), DBFIRSTROW(), dbgetrow(), dbnextrow(), dbsetopt().
7128  */
7129 DBINT
7131 {
7132  int idx;
7133 
7134  tdsdump_log(TDS_DBG_FUNC, "dblastrow(%p)\n", dbproc);
7136  idx = dbproc->row_buf.head;
7137  if (dbproc->row_buf.head != dbproc->row_buf.tail) {
7138  if (--idx < 0)
7139  idx = dbproc->row_buf.capacity - 1;
7140  }
7141  assert(idx >= 0);
7142  return buffer_idx2row(&dbproc->row_buf, idx);
7143 }
7144 
7145 
7146 /** \internal
7147  * \ingroup dblib_internal
7148  * \brief Get file descriptor of the socket used by a \c DBPROCESS to read data coming from the server. (!)
7149  *
7150  * \param dbproc contains all information needed by db-lib to manage communications with the server.
7151  * \sa dbcmd(), DBIORDESC(), DBIOWDESC(), dbnextrow(), dbpoll(), DBRBUF(), dbresults(), dbsqlok(), dbsqlsend().
7152  */
7153 int
7155 {
7156  tdsdump_log(TDS_DBG_FUNC, "dbiordesc(%p)\n", dbproc);
7158  return (int) tds_get_s(dbproc->tds_socket);
7159 }
7160 
7161 
7162 /** \internal
7163  * \ingroup dblib_internal
7164  * \brief Get file descriptor of the socket used by a \c DBPROCESS to write data coming to the server. (!)
7165  *
7166  * \param dbproc contains all information needed by db-lib to manage communications with the server.
7167  * \sa dbcmd(), DBIORDESC(), DBIOWDESC(), dbnextrow(), dbpoll(), DBRBUF(), dbresults(), dbsqlok(), dbsqlsend().
7168  */
7169 int
7171 {
7172  tdsdump_log(TDS_DBG_FUNC, "dbiowdesc(%p)\n", dbproc);
7174 
7175  return (int) tds_get_s(dbproc->tds_socket);
7176 }
7177 
7178 DBBOOL
7180 {
7181  tdsdump_log(TDS_DBG_FUNC, "dbisavail(%p)\n", dbproc);
7183  return dbproc->avail_flag;
7184 }
7185 
7186 
7187 /** \internal
7188  * \ingroup dblib_internal
7189  * \brief Mark a \c DBPROCESS as "available".
7190  *
7191  * \param dbproc contains all information needed by db-lib to manage communications with the server.
7192  * \remarks Basically bogus. \c FreeTDS behaves the way Sybase's implementation does, but so what?
7193  Many \c db-lib functions set the \c DBPROCESS to "not available", but only
7194  dbsetavail() resets it to "available".
7195  * \sa DBISAVAIL(). DBSETAVAIL().
7196  */
7197 void
7199 {
7200  tdsdump_log(TDS_DBG_FUNC, "dbsetavail(%p)\n", dbproc);
7202  dbproc->avail_flag = TRUE;
7203 }
7204 
7205 
7206 /**
7207  * \ingroup dblib_core
7208  * \brief Build a printable string from text containing placeholders for variables.
7209  *
7210  * \param dbproc contains all information needed by db-lib to manage communications with the server.
7211  * \param charbuf \em output: buffer that will contain the ASCII null-terminated string built by \c dbstrbuild().
7212  * \param bufsize size of \a charbuf, in bytes.
7213  * \param text null-terminated ASCII string, with \em placeholders for variables. \em A Placeholder is a
7214  * three-byte string, made up of:
7215  - '%' a percent sign
7216  - 0-9 an integer (designates the argument number to use, starting with 1.)
7217  - '!' an exclamation point
7218  * \param formats null-terminated ASCII sprintf-style string. Has one format specifier for each placeholder in \a text.
7219  * \remarks Following \a formats are the arguments, the values to substitute for the placeholders.
7220  * \sa dbconvert(), dbdatename(), dbdatepart().
7221  */
7222 RETCODE
7223 dbstrbuild(DBPROCESS * dbproc, char *charbuf, int bufsize, char *text, char *formats, ...)
7224 {
7225  va_list ap;
7226  TDSRET rc;
7227  int resultlen;
7228 
7229  tdsdump_log(TDS_DBG_FUNC, "dbstrbuild(%p, %s, %d, %s, %s, ...)\n", dbproc, charbuf, bufsize, text, formats);
7230  CHECK_NULP(charbuf, "dbstrbuild", 2, FAIL);
7231  CHECK_NULP(text, "dbstrbuild", 4, FAIL);
7232  CHECK_NULP(formats, "dbstrbuild", 5, FAIL);
7233 
7234  va_start(ap, formats);
7235  rc = tds_vstrbuild(charbuf, bufsize, &resultlen, text, TDS_NULLTERM, formats, TDS_NULLTERM, ap);
7236  charbuf[resultlen] = '\0';
7237  va_end(ap);
7238  return TDS_SUCCEED(rc) ? SUCCEED : FAIL;
7239 }
7240 
7241 static char *
7242 _dbprdate(char *timestr)
7243 {
7244  time_t currtime = time(NULL);
7245 
7246  assert(timestr);
7247 
7248  strcpy(timestr, asctime(gmtime(&currtime)));
7249  timestr[strlen(timestr) - 1] = '\0'; /* remove newline */
7250  return timestr;
7251 
7252 }
7253 
7254 static DBINT
7256 {
7257  TDSCOLUMN *colinfo;
7258  TDSRESULTINFO *resinfo;
7259 
7261  resinfo = dbproc->tds_socket->res_info;
7262  if (!resinfo || column < 1 || column > resinfo->num_cols)
7263  return FALSE;
7264  colinfo = resinfo->columns[column - 1];
7265 
7266  if (colinfo->column_nullable)
7267  return TRUE;
7268  return FALSE;
7269 }
7270 
7271 /** Returns type in string. Used for debugging purpose */
7272 static const char *
7273 tds_prdatatype(int datatype_token)
7274 {
7275  switch ((TDS_SERVER_TYPE) datatype_token) {
7276  case SYBCHAR: return "SYBCHAR";
7277  case SYBVARCHAR: return "SYBVARCHAR";
7278  case SYBINTN: return "SYBINTN";
7279  case SYBINT1: return "SYBINT1";
7280  case SYBINT2: return "SYBINT2";
7281  case SYBINT4: return "SYBINT4";
7282  case SYBINT8: return "SYBINT8";
7283  case SYBFLT8: return "SYBFLT8";
7284  case SYBDATETIME: return "SYBDATETIME";
7285  case SYBBIT: return "SYBBIT";
7286  case SYBTEXT: return "SYBTEXT";
7287  case SYBNTEXT: return "SYBNTEXT";
7288  case SYBIMAGE: return "SYBIMAGE";
7289  case SYBMONEY4: return "SYBMONEY4";
7290  case SYBMONEY: return "SYBMONEY";
7291  case SYBDATETIME4: return "SYBDATETIME4";
7292  case SYBREAL: return "SYBREAL";
7293  case SYBBINARY: return "SYBBINARY";
7294  case SYBVOID: return "SYBVOID";
7295  case SYBVARBINARY: return "SYBVARBINARY";
7296  case SYBNVARCHAR: return "SYBNVARCHAR";
7297  case SYBBITN: return "SYBBITN";
7298  case SYBNUMERIC: return "SYBNUMERIC";
7299  case SYBDECIMAL: return "SYBDECIMAL";
7300  case SYBFLTN: return "SYBFLTN";
7301  case SYBMONEYN: return "SYBMONEYN";
7302  case SYBDATETIMN: return "SYBDATETIMN";
7303  case XSYBCHAR: return "XSYBCHAR";
7304  case XSYBVARCHAR: return "XSYBVARCHAR";
7305  case XSYBNVARCHAR: return "XSYBNVARCHAR";
7306  case XSYBNCHAR: return "XSYBNCHAR";
7307  case XSYBVARBINARY: return "XSYBVARBINARY";
7308  case XSYBBINARY: return "XSYBBINARY";
7309  case SYBLONGBINARY: return "SYBLONGBINARY";
7310  case SYBSINT1: return "SYBSINT1";
7311  case SYBUINT2: return "SYBUINT2";
7312  case SYBUINT4: return "SYBUINT4";
7313  case SYBUINT8: return "SYBUINT8";
7314  case SYBUNIQUE: return "SYBUNIQUE";
7315  case SYBVARIANT: return "SYBVARIANT";
7316  case SYBMSXML: return "SYBMSXML";
7317  case SYBMSDATE: return "SYBMSDATE";
7318  case SYBMSTIME: return "SYBMSTIME";
7319  case SYBMSDATETIME2: return "SYBMSDATETIME2";
7320  case SYBMSDATETIMEOFFSET: return "SYBMSDATETIMEOFFSET";
7321  case SYBDATE: return "SYBDATE";
7322  case SYBTIME: return "SYBTIME";
7323  case SYB5BIGDATETIME: return "SYBBIGDATETIME";
7324  case SYB5BIGTIME: return "SYBBIGTIME";
7325  case SYBMSUDT: return "SYBMSUDT";
7326  case SYBUINT1: return "SYBUINT1";
7327  case SYBDATEN: return "SYBDATEN";
7328  case SYB5INT8: return "SYB5INT8";
7329  case SYBINTERVAL: return "SYBINTERVAL";
7330  case SYBTIMEN: return "SYBTIMEN";
7331  case SYBUINTN: return "SYBUINTN";
7332  case SYBUNITEXT: return "SYBUNITEXT";
7333  case SYBXML: return "SYBXML";
7334  }
7335  return "(unknown)";
7336 }
7337 #if 1
7338 void
7340  BYTE * dest, DBINT destlen,
7341  int bindtype, DBINT *indicator)
7342 {
7343  CONV_RESULT dres;
7344  DBINT ret;
7345  int i, len;
7346  DBINT indicator_value = 0;
7347 
7348  int limited_dest_space = 0;
7349  TDS_SERVER_TYPE desttype = dblib_bound_type(bindtype);
7350 
7351  tdsdump_log(TDS_DBG_FUNC, "copy_data_to_host_var(%d [%s] len %d => %d [%s] len %d)\n",
7352  srctype, tds_prdatatype(srctype), srclen, desttype, tds_prdatatype(desttype), destlen);
7353  CHECK_NULP(src, "copy_data_to_host_var", 3, );
7354  CHECK_NULP(dest, "copy_data_to_host_var", 6, );
7355  if (desttype == TDS_INVALID_TYPE)
7356  return;
7357  /* indicator can be NULL */
7358 
7359  assert(srclen >= 0);
7360 
7361  if (destlen > 0) {
7362  limited_dest_space = 1;
7363  }
7364 
7365  /* oft times we are asked to convert a data type to itself */
7366 
7367  if (desttype == SYBNUMERIC) {
7368  DBNUMERIC *num = NULL; /* num->scale is unsigned */
7369 
7370  /* only MS, use always source */
7371  if (bindtype == SRCNUMERICBIND || bindtype == SRCDECIMALBIND) {
7372  if (is_numeric_type(srctype))
7373  num = (DBNUMERIC*) src;
7374  else
7375  num = (DBNUMERIC*) dest;
7376  } else if (dbproc->msdblib) {
7377  /* MS by default use only destination informations */
7378  num = (DBNUMERIC*) dest;
7379  } else {
7380  /* Sybase, dbbind means source or default */
7381  /* TODO if dbbind_ps is used is more complicated */
7382  if (is_numeric_type(srctype))
7383  num = (DBNUMERIC*) src;
7384  }
7385  if (!num) {
7386  dres.n.precision = 18;
7387  dres.n.scale = 0;
7388  } else {
7389  dres.n.precision = num->precision;
7390  dres.n.scale = num->scale;
7391  }
7392  } else if ((srctype == desttype) ||
7393  (is_similar_type(srctype, desttype))) {
7394 
7395  tdsdump_log(TDS_DBG_INFO1, "copy_data_to_host_var() srctype == desttype\n");
7396  switch (desttype) {
7397 
7398  case SYBBINARY:
7399  case SYBIMAGE:
7400  if (srclen > destlen && destlen >= 0) {
7401  dbperror(dbproc, SYBECOFL, 0);
7402  } else {
7403  memcpy(dest, src, srclen);
7404  if (srclen < destlen)
7405  memset(dest + srclen, 0, destlen - srclen);
7406  }
7407  break;
7408 
7409  case SYBCHAR:
7410  case SYBVARCHAR:
7411  case SYBTEXT:
7412 
7413  switch (bindtype) {
7414  case NTBSTRINGBIND: /* strip trailing blanks, null term */
7415  while (srclen && src[srclen - 1] == ' ') {
7416  --srclen;
7417  }
7418  if (limited_dest_space) {
7419  if (srclen + 1 > destlen) {
7420  dbperror(dbproc, SYBECOFL, 0);
7421  indicator_value = srclen + 1;
7422  srclen = destlen - 1;
7423  }
7424  }
7425  memcpy(dest, src, srclen);
7426  dest[srclen] = '\0';
7427  break;
7428  case STRINGBIND: /* pad with blanks, NUL term */
7429  if (limited_dest_space) {
7430  if (srclen + 1 > destlen) {
7431  dbperror(dbproc, SYBECOFL, 0);
7432  indicator_value = srclen + 1;
7433  srclen = destlen - 1;
7434  }
7435  } else {
7436  destlen = srclen;
7437  }
7438  memcpy(dest, src, srclen);
7439  for (i = srclen; i < destlen - 1; i++)
7440  dest[i] = ' ';
7441  dest[i] = '\0';
7442  break;
7443  case CHARBIND: /* pad with blanks, NO NUL term */
7444  if (limited_dest_space) {
7445  if (srclen > destlen) {
7446  dbperror(dbproc, SYBECOFL, 0);
7447  indicator_value = srclen;
7448  srclen = destlen;
7449  }
7450  } else {
7451  destlen = srclen;
7452  }
7453  memcpy(dest, src, srclen);
7454  for (i = srclen; i < destlen; i++)
7455  dest[i] = ' ';
7456  break;
7457  case VARYCHARBIND: /* strip trailing blanks, NO NUL term */
7458  if (limited_dest_space) {
7459  if (srclen > destlen) {
7460  dbperror(dbproc, SYBECOFL, 0);
7461  indicator_value = srclen;
7462  srclen = destlen;
7463  }
7464  }
7465  memcpy(((DBVARYCHAR *)dest)->str, src, srclen);
7466  ((DBVARYCHAR *)dest)->len = srclen;
7467  break;
7468  }
7469  break;
7470  case SYBINT1:
7471  case SYBINT2:
7472  case SYBINT4:
7473  case SYBINT8:
7474  case SYBFLT8:
7475  case SYBREAL:
7476  case SYBBIT:
7477  case SYBBITN:
7478  case SYBMONEY:
7479  case SYBMONEY4:
7480  case SYBDATETIME:
7481  case SYBDATETIME4:
7482  case SYBDATE:
7483  case SYBTIME:
7484  case SYB5BIGDATETIME:
7485  case SYB5BIGTIME:
7486  case SYBUNIQUE:
7487  ret = tds_get_size_by_type(desttype);
7488  memcpy(dest, src, ret);
7489  break;
7490 
7491  case SYBMSDATE:
7492  case SYBMSTIME:
7493  case SYBMSDATETIME2:
7494  case SYBMSDATETIMEOFFSET:
7495  ret = sizeof(TDS_DATETIMEALL);
7496  memcpy(dest, src, ret);
7497  break;
7498 
7499  default:
7500  break;
7501  }
7502  if (indicator)
7503  *indicator = indicator_value;
7504 
7505  return;
7506 
7507  } /* end srctype == desttype */
7508 
7509  len = tds_convert(g_dblib_ctx.tds_ctx, srctype, (const TDS_CHAR *) src, srclen, desttype, &dres);
7510 
7511  tdsdump_log(TDS_DBG_INFO1, "copy_data_to_host_var(): tds_convert returned %d\n", len);
7512 
7513  if (len < 0) {
7515  return;
7516  }
7517 
7518  switch (desttype) {
7519  case SYBVARBINARY:
7520  case SYBBINARY:
7521  case SYBIMAGE:
7522  if (bindtype == VARYBINBIND) {
7523  if (limited_dest_space) {
7524  if (len > sizeof(((DBVARYBIN *)dest)->array)) {
7525  dbperror(dbproc, SYBECOFL, 0);
7526  indicator_value = len;
7527  len = sizeof(((DBVARYBIN *)dest)->array);
7528  }
7529  }
7530  memcpy(((DBVARYBIN *)dest)->array, dres.c, len);
7531  ((DBVARYBIN *)dest)->len = len;
7532  } else {
7533  if (len > destlen && destlen >= 0) {
7534  dbperror(dbproc, SYBECOFL, 0);
7535  } else {
7536  memcpy(dest, dres.ib, len);
7537  if (len < destlen)
7538  memset(dest + len, 0, destlen - len);
7539  }
7540  }
7541  TDS_ZERO_FREE(dres.ib);
7542  break;
7543  case SYBINT1:
7544  case SYBINT2:
7545  case SYBINT4:
7546  case SYBINT8:
7547  case SYBFLT8:
7548  case SYBREAL:
7549  case SYBBIT:
7550  case SYBBITN:
7551  case SYBMONEY:
7552  case SYBMONEY4:
7553  case SYBDATETIME:
7554  case SYBDATETIME4:
7555  case SYBDATE:
7556  case SYBTIME:
7557  case SYBNUMERIC:
7558  case SYBDECIMAL:
7559  case SYBUNIQUE:
7560  case SYBMSDATE:
7561  case SYBMSTIME:
7562  case SYB5BIGDATETIME:
7563  case SYB5BIGTIME:
7564  case SYBMSDATETIME2:
7565  case SYBMSDATETIMEOFFSET:
7566  memcpy(dest, &(dres.ti), len);
7567  break;
7568  case SYBCHAR:
7569  case SYBVARCHAR:
7570  case SYBTEXT:
7571  tdsdump_log(TDS_DBG_INFO1, "copy_data_to_host_var() outputs %d bytes char data destlen = %d \n", len, destlen);
7572  switch (bindtype) {
7573  case NTBSTRINGBIND: /* strip trailing blanks, null term */
7574  while (len && dres.c[len - 1] == ' ') {
7575  --len;
7576  }
7577  if (limited_dest_space) {
7578  if (len + 1 > destlen) {
7579  dbperror(dbproc, SYBECOFL, 0);
7580  len = destlen - 1;
7581  }
7582  }
7583  memcpy(dest, dres.c, len);
7584  dest[len] = '\0';
7585  break;
7586  case STRINGBIND: /* pad with blanks, null term */
7587  if (limited_dest_space) {
7588  if (len + 1 > destlen) {
7589  dbperror(dbproc, SYBECOFL, 0);
7590  len = destlen - 1;
7591  }
7592  } else {
7593  destlen = len;
7594  }
7595  memcpy(dest, dres.c, len);
7596  for (i = len; i < destlen - 1; i++)
7597  dest[i] = ' ';
7598  dest[i] = '\0';
7599  break;
7600  case CHARBIND: /* pad with blanks, NO null term */
7601  if (limited_dest_space) {
7602  if (len > destlen) {
7603  dbperror(dbproc, SYBECOFL, 0);
7604  indicator_value = len;
7605  len = destlen;
7606  }
7607  } else {
7608  destlen = len;
7609  }
7610  memcpy(dest, dres.c, len);
7611  for (i = len; i < destlen; i++)
7612  dest[i] = ' ';
7613  break;
7614  case VARYCHARBIND: /* strip trailing blanks, NO null term */
7615  if (limited_dest_space) {
7616  if (len > sizeof(((DBVARYCHAR *)dest)->str)) {
7617  dbperror(dbproc, SYBECOFL, 0);
7618  indicator_value = len;
7619  len = sizeof(((DBVARYCHAR *)dest)->str);
7620  }
7621  }
7622  memcpy(((DBVARYCHAR *)dest)->str, dres.c, len);
7623  ((DBVARYCHAR *)dest)->len = len;
7624  break;
7625  }
7626 
7627  free(dres.c);
7628  break;
7629  default:
7630  tdsdump_log(TDS_DBG_INFO1, "error: copy_data_to_host_var(): unrecognized desttype %d \n", desttype);
7631  break;
7632 
7633  }
7634  if (indicator)
7635  *indicator = indicator_value;
7636 
7637  return;
7638 }
7639 #endif
7640 
7641 /** \internal
7642  * \ingroup dblib_internal
7643  * \remarks member msgno Vendor-defined message number
7644  * \remarks member severity Is passed to the error handler
7645  * \remarks member msgtext Text of message
7646  */
7647 typedef struct _dblib_error_message
7648 {
7651  const char *msgtext;
7653 
7654 /*
7655  * The msgtext member holds up to two strings. The first one is the message text, which may contain placeholders.
7656  * The second one, if it exists, is the format string for dbstrbuild(). Messages containing no placeholders still need
7657  * an extra NULL to indicate a zero-length format string.
7658  */
7660  { { SYBEVERDOWN, EXINFO, "TDS version downgraded to 7.1!\0" }
7661  , { SYBEICONVIU, EXCONVERSION, "Some character(s) could not be converted into client's character set\0" }
7662  , { SYBEICONVAVAIL, EXCONVERSION, "Character set conversion is not available between client character set '%1!' and "
7663  "server character set '%2!'\0%s %s" }
7664  , { SYBEICONVO, EXCONVERSION, "Error converting characters into server's character set. Some character(s) could "
7665  "not be converted\0" }
7666  , { SYBEICONVI, EXCONVERSION, "Some character(s) could not be converted into client's character set. Unconverted "
7667  "bytes were changed to question marks ('?')\0" }
7668  , { SYBEICONV2BIG, EXCONVERSION, "Buffer overflow converting characters from client into server's character set\0" }
7669 
7670 
7671  , { SYBEPORT, EXUSER, "Both port and instance specified\0" }
7672  , { SYBETDSVER, EXUSER, "Cannot bcp with TDSVER < 5.0\0" }
7673  , { SYBEAAMT, EXPROGRAM, "User attempted a dbaltbind with mismatched column and variable types\0" }
7674  , { SYBEABMT, EXPROGRAM, "User attempted a dbbind with mismatched column and variable types\0" }
7675  , { SYBEABNC, EXPROGRAM, "Attempt to bind to a non-existent column\0" }
7676  , { SYBEABNP, EXPROGRAM, "Attempt to bind using NULL pointers\0" }
7677  , { SYBEABNV, EXPROGRAM, "Attempt to bind to a NULL program variable\0" }
7678  , { SYBEACNV, EXCONVERSION, "Attempt to do data-conversion with NULL destination variable.\0" }
7679  , { SYBEADST, EXCONSISTENCY, "International Release: Error in attempting to determine the size of a pair of "
7680  "translation tables\0" }
7681  , { SYBEAICF, EXCONSISTENCY, "International Release: Error in attempting to install custom format\0" }
7682  , { SYBEALTT, EXCONSISTENCY, "International Release: Error in attempting to load a pair of translation tables\0" }
7683  , { SYBEAOLF, EXRESOURCE, "International Release: Error in attempting to open a localization file\0" }
7684  , { SYBEAPCT, EXCONSISTENCY, "International Release: Error in attempting to perform a character set translation\0" }
7685  , { SYBEAPUT, EXPROGRAM, "Attempt to print unknown token\0" }
7686  , { SYBEARDI, EXRESOURCE, "International Release: Error in attempting to read datetime information from a "
7687  "localization file\0" }
7688  , { SYBEARDL, EXRESOURCE, "International Release: Error in attempting to read the dblib.loc localization file\0" }
7689  , { SYBEASEC, EXPROGRAM, "Attempt to send an empty command buffer to the server\0" }
7690  , { SYBEASNL, EXPROGRAM, "Attempt to set fields in a null LOGINREC\0" }
7691  , { SYBEASTL, EXPROGRAM, "Synchronous I/O attempted at AST level\0" }
7692  , { SYBEASUL, EXPROGRAM, "Attempt to set unknown LOGINREC field\0" }
7693  , { SYBEAUTN, EXPROGRAM, "Attempt to update the timestamp of a table that has no timestamp column\0" }
7694  , { SYBEBADPK, EXINFO, "Packet size of %1! not supported -- size of %2! used instead!\0%d %d" }
7695  , { SYBEBBCI, EXINFO, "Batch successfully bulk copied to the server\0" }
7696  , { SYBEBBL, EXPROGRAM, "Bad bindlen parameter passed to dbsetnull\0" }
7697  , { SYBEBCBC, EXPROGRAM, "bcp_columns must be called before bcp_colfmt and bcp_colfmt_ps\0" }
7698  , { SYBEBCBNPR, EXPROGRAM, "bcp_bind: if varaddr is NULL, prefixlen must be 0 "
7699  "and no terminator should be specified\0" }
7700  , { SYBEBCBNTYP, EXPROGRAM, "bcp_bind: if varaddr is NULL and varlen greater than 0, the table column type "
7701  "must be SYBTEXT or SYBIMAGE and the program variable type must be SYBTEXT, SYBCHAR, "
7702  "SYBIMAGE or SYBBINARY\0" }
7703  , { SYBEBCBPREF, EXPROGRAM, "Illegal prefix length. Legal values are 0, 1, 2 or 4\0" }
7704  , { SYBEBCFO, EXUSER, "bcp host files must contain at least one column\0" }
7705  , { SYBEBCHLEN, EXPROGRAM, "host_collen should be greater than or equal to -1\0" }
7706  , { SYBEBCIS, EXCONSISTENCY, "Attempt to bulk copy an illegally-sized column value to the server\0" }
7707  , { SYBEBCIT, EXPROGRAM, "It is illegal to use BCP terminators with program variables other than SYBCHAR, "
7708  "SYBBINARY, SYBTEXT, or SYBIMAGE\0" }
7709  , { SYBEBCITBLEN, EXPROGRAM, "bcp_init: tblname parameter is too long\0" }
7710  , { SYBEBCITBNM, EXPROGRAM, "bcp_init: tblname parameter cannot be NULL\0" }
7711  , { SYBEBCMTXT, EXPROGRAM, "bcp_moretext may be used only when there is at least one text or image column in "
7712  "the server table\0" }
7713  , { SYBEBCNL, EXNONFATAL, "Negative length-prefix found in BCP data-file\0" }
7714  , { SYBEBCNN, EXUSER, "Attempt to bulk copy a NULL value into a Server column "
7715  "which does not accept null values\0" }
7716  , { SYBEBCNT, EXUSER, "Attempt to use Bulk Copy with a non-existent Server table\0" }
7717  , { SYBEBCOR, EXCONSISTENCY, "Attempt to bulk copy an oversized row to the server\0" }
7718  , { SYBEBCPB, EXPROGRAM, "bcp_bind, bcp_moretext and bcp_sendrow may not be used after bcp_init has been "
7719  "passed a non-NULL input file name\0" }
7720  , { SYBEBCPCTYP, EXPROGRAM, "bcp_colfmt: If table_colnum is 0, host_type cannot be 0\0" }
7721  , { SYBEBCPI, EXPROGRAM, "bcp_init must be called before any other bcp routines\0" }
7722  , { SYBEBCPN, EXPROGRAM, "bcp_bind, bcp_collen, bcp_colptr, bcp_moretext and bcp_sendrow may be used only "
7723  "after bcp_init has been called with the copy direction set to DB_IN\0" }
7724  , { SYBEBCPREC, EXNONFATAL, "Column %1!: Illegal precision value encountered\0%d" }
7725  , { SYBEBCPREF, EXPROGRAM, "Illegal prefix length. Legal values are -1, 0, 1, 2 or 4\0" }
7726  , { SYBEBCRE, EXNONFATAL, "I/O error while reading bcp datafile\0" }
7727  , { SYBEBCRO, EXINFO, "The BCP hostfile '%1!' contains only %2! rows. It was impossible to read the "
7728  "requested %3! rows\0%s %d %d" }
7729  , { SYBEBCSA, EXUSER, "The BCP hostfile '%1!' contains only %2! rows. "
7730  "Skipping all of these rows is not allowed\0%s %d" }
7731  , { SYBEBCSET, EXCONSISTENCY, "Unknown character-set encountered\0" }
7732  , { SYBEBCSI, EXPROGRAM, "Host-file columns may be skipped only when copying into the Server\0" }
7733  , { SYBEBCSNDROW, EXPROGRAM, "bcp_sendrow may not be called unless all text data for the previous row has been "
7734  "sent using bcp_moretext\0" }
7735  , { SYBEBCSNTYP, EXPROGRAM, "column number %1!: if varaddr is NULL and varlen greater than 0, the table column "
7736  "type must be SYBTEXT or SYBIMAGE and the program variable type must be SYBTEXT, "
7737  "SYBCHAR, SYBIMAGE or SYBBINARY\0%d" }
7738  , { SYBEBCUC, EXRESOURCE, "bcp: Unable to close host datafile\0" }
7739  , { SYBEBCUO, EXRESOURCE, "bcp: Unable to open host datafile\0" }
7740  , { SYBEBCVH, EXPROGRAM, "bcp_exec may be called only after bcp_init has been passed a valid host file\0" }
7741  , { SYBEBCVLEN, EXPROGRAM, "varlen should be greater than or equal to -1\0" }
7742  , { SYBEBCWE, EXNONFATAL, "I/O error while writing bcp datafile\0" }
7743  , { SYBEBDIO, EXPROGRAM, "Bad bulk copy direction. Must be either IN or OUT\0" }
7744  , { SYBEBEOF, EXNONFATAL, "Unexpected EOF encountered in bcp datafile\0" }
7745  , { SYBEBIHC, EXPROGRAM, "Incorrect host-column number found in bcp format file\0" }
7746  , { SYBEBIVI, EXPROGRAM, "bcp_columns, bcp_colfmt and bcp_colfmt_ps may be used only after bcp_init has been "
7747  "passed a valid input file\0" }
7748  , { SYBEBNCR, EXPROGRAM, "Attempt to bind user variable to a non-existent compute row\0" }
7749  , { SYBEBNUM, EXPROGRAM, "Bad numbytes parameter passed to dbstrcpy\0" }
7750  , { SYBEBPKS, EXPROGRAM, "In DBSETLPACKET, the packet size parameter must be between 0 and 999999\0" }
7751  , { SYBEBPREC, EXPROGRAM, "Illegal precision specified\0" }
7752  , { SYBEBPROBADDEF, EXCONSISTENCY, "bcp protocol error: illegal default column id received\0" }
7753  , { SYBEBPROCOL, EXCONSISTENCY, "bcp protocol error: returned column count differs from the actual number of "
7754  "columns received\0" }
7755  , { SYBEBPRODEF, EXCONSISTENCY, "bcp protocol error: expected default information and got none\0" }
7756  , { SYBEBPRODEFID, EXCONSISTENCY, "bcp protocol error: default column id and actual column id are not same\0" }
7757  , { SYBEBPRODEFTYP, EXCONSISTENCY, "bcp protocol error: default value datatype differs from column datatype\0" }
7758  , { SYBEBPROEXTDEF, EXCONSISTENCY, "bcp protocol error: more than one row of default information received\0" }
7759  , { SYBEBPROEXTRES, EXCONSISTENCY, "bcp protocol error: unexpected set of results received\0" }
7760  , { SYBEBPRONODEF, EXCONSISTENCY, "bcp protocol error: default value received for column that does not have default\0" }
7761  , { SYBEBPRONUMDEF, EXCONSISTENCY, "bcp protocol error: expected number of defaults differs from the actual number of "
7762  "defaults received\0" }
7763  , { SYBEBRFF, EXRESOURCE, "I/O error while reading bcp format file\0" }
7764  , { SYBEBSCALE, EXPROGRAM, "Illegal scale specified\0" }
7765  , { SYBEBTMT, EXPROGRAM, "Attempt to send too much text data via the bcp_moretext call\0" }
7766  , { SYBEBTOK, EXCOMM, "Bad token from the server: Datastream processing out of sync\0" }
7767  , { SYBEBTYP, EXPROGRAM, "Unknown bind type passed to DB-Library function\0" }
7768  , { SYBEBTYPSRV, EXPROGRAM, "Datatype is not supported by the server\0" }
7769  , { SYBEBUCE, EXRESOURCE, "bcp: Unable to close error file\0" }
7770  , { SYBEBUCF, EXPROGRAM, "bcp: Unable to close format file\0" }
7771  , { SYBEBUDF, EXPROGRAM, "bcp: Unrecognized datatype found in format file\0" }
7772  , { SYBEBUFF, EXPROGRAM, "bcp: Unable to create format file\0" }
7773  , { SYBEBUFL, EXCONSISTENCY, "DB-Library internal error-send buffer length corrupted\0" }
7774  , { SYBEBUOE, EXRESOURCE, "bcp: Unable to open error file\0" }
7775  , { SYBEBUOF, EXPROGRAM, "bcp: Unable to open format file\0" }
7776  , { SYBEBWEF, EXNONFATAL, "I/O error while writing bcp error file\0" }
7777  , { SYBEBWFF, EXRESOURCE, "I/O error while writing bcp format file\0" }
7778  , { SYBECAP, EXCOMM, "DB-Library capabilities not accepted by the Server\0" }
7779  , { SYBECAPTYP, EXCOMM, "Unexpected capability type in CAPABILITY datastream\0" }
7780  , { SYBECDNS, EXCONSISTENCY, "Datastream indicates that a compute column is derived from a non-existent select "
7781  "list member\0" }
7782  , { SYBECDOMAIN, EXCONVERSION, "Source field value is not within the domain of legal values\0" }
7783  , { SYBECINTERNAL, EXCONVERSION, "Internal Conversion error\0" }
7784  , { SYBECLOS, EXCOMM, "Error in closing network connection\0" }
7785  , { SYBECLPR, EXCONVERSION, "Data conversion resulted in loss of precision\0" }
7786  , { SYBECNOR, EXPROGRAM, "Column number out of range\0" }
7787  , { SYBECNOV, EXCONVERSION, "Attempt to set variable to NULL resulted in overflow\0" }
7788  , { SYBECOFL, EXCONVERSION, "Data conversion resulted in overflow\0" }
7789  , { SYBECONN, EXCOMM, "Unable to connect: Adaptive Server is unavailable or does not exist\0" }
7790  , { SYBECRNC, EXPROGRAM, "The current row is not a result of compute clause %1!, so it is illegal to attempt "
7791  "to extract that data from this row\0%d" }
7792  , { SYBECRSAGR, EXPROGRAM, "Aggregate functions are not allowed in a cursor statement\0" }
7793  , { SYBECRSBROL, EXPROGRAM, "Backward scrolling cannot be used in a forward scrolling cursor\0" }
7794  , { SYBECRSBSKEY, EXPROGRAM, "Keyset cannot be scrolled backward in mixed cursors with a previous fetch type\0" }
7795  , { SYBECRSBUFR, EXPROGRAM, "Row buffering should not be turned on when using cursor APIs\0" }
7796  , { SYBECRSDIS, EXPROGRAM, "Cursor statement contains one of the disallowed phrases compute, union, for "
7797  "browse, or select into\0" }
7798  , { SYBECRSFLAST, EXPROGRAM, "Fetch type LAST requires fully keyset driven cursors\0" }
7799  , { SYBECRSFRAND, EXPROGRAM, "Fetch types RANDOM and RELATIVE can only be used within the keyset of keyset "
7800  "driven cursors\0" }
7801  , { SYBECRSFROWN, EXPROGRAM, "Row number to be fetched is outside valid range\0" }
7802  , { SYBECRSFTYPE, EXRESOURCE, "Unknown fetch type\0" }
7803  , { SYBECRSINV, EXPROGRAM, "Invalid cursor statement\0" }
7804  , { SYBECRSINVALID, EXRESOURCE, "The cursor handle is invalid\0" }
7805  , { SYBECRSMROWS, EXRESOURCE, "Multiple rows are returned, only one is expected while retrieving dbname\0" }
7806  , { SYBECRSNOBIND, EXPROGRAM, "Cursor bind must be called prior to dbcursor invocation\0" }
7807  , { SYBECRSNOCOUNT, EXPROGRAM, "The DBNOCOUNT option should not be turned on "
7808  "when doing updates or deletes with dbcursor\0" }
7809  , { SYBECRSNOFREE, EXPROGRAM, "The DBNOAUTOFREE option should not be turned on when using cursor APIs\0" }
7810  , { SYBECRSNOIND, EXPROGRAM, "One of the tables involved in the cursor statement does not have a unique index\0" }
7811  , { SYBECRSNOKEYS, EXRESOURCE, "The entire keyset must be defined for KEYSET type cursors\0" }
7812  , { SYBECRSNOLEN, EXRESOURCE, "No unique index found\0" }
7813  , { SYBECRSNOPTCC, EXRESOURCE, "No OPTCC was found\0" }
7814  , { SYBECRSNORDER, EXRESOURCE, "The order of clauses must be from, where, and order by\0" }
7815  , { SYBECRSNORES, EXPROGRAM, "Cursor statement generated no results\0" }
7816  , { SYBECRSNROWS, EXRESOURCE, "No rows returned, at least one is expected\0" }
7817  , { SYBECRSNOTABLE, EXRESOURCE, "Table name is NULL\0" }
7818  , { SYBECRSNOUPD, EXPROGRAM, "Update or delete operation did not affect any rows\0" }
7819  , { SYBECRSNOWHERE, EXPROGRAM, "A WHERE clause is not allowed in a cursor update or insert\0" }
7820  , { SYBECRSNUNIQUE, EXRESOURCE, "No unique keys associated with this view\0" }
7821  , { SYBECRSORD, EXPROGRAM, "Only fully keyset driven cursors can have order by, group by, or having phrases\0" }
7822  , { SYBECRSRO, EXPROGRAM, "Data locking or modifications cannot be made in a READONLY cursor\0" }
7823  , { SYBECRSSET, EXPROGRAM, "A SET clause is required for a cursor update or insert\0" }
7824  , { SYBECRSTAB, EXPROGRAM, "Table name must be determined in operations involving data locking or modifications\0" }
7825  , { SYBECRSVAR, EXRESOURCE, "There is no valid address associated with this bind\0" }
7826  , { SYBECRSVIEW, EXPROGRAM, "A view cannot be joined with another table or a view in a cursor statement\0" }
7827  , { SYBECRSVIIND, EXPROGRAM, "The view used in the cursor statement does not include all the unique index "
7828  "columns of the underlying tables\0" }
7829  , { SYBECRSUPDNB, EXPROGRAM, "Update or insert operations cannot use bind variables when binding type is NOBIND\0" }
7830  , { SYBECRSUPDTAB, EXPROGRAM, "Update or insert operations using bind variables require single table cursors\0" }
7831  , { SYBECSYN, EXCONVERSION, "Attempt to convert data stopped by syntax error in source field\0" }
7832  , { SYBECUFL, EXCONVERSION, "Data conversion resulted in underflow\0" }
7833  , { SYBECWLL, EXPROGRAM, "Attempt to set column width less than 1\0" }
7834  , { SYBEDBPS, EXRESOURCE, "Maximum number of DBPROCESSes already allocated\0" }
7835  , { SYBEDDNE, EXINFO, "DBPROCESS is dead or not enabled\0" }
7836  , { SYBEDIVZ, EXUSER, "Attempt to divide by $0.00 in function %1!\0%s" }
7837  , { SYBEDNTI, EXPROGRAM, "Attempt to use dbtxtsput to put a new text timestamp into a column whose datatype "
7838  "is neither SYBTEXT nor SYBIMAGE\0" }
7839  , { SYBEDPOR, EXPROGRAM, "Out-of-range datepart constant\0" }
7840  , { SYBEDVOR, EXPROGRAM, "Day values must be between 1 and 7\0" }
7841  , { SYBEECAN, EXINFO, "Attempted to cancel unrequested event notification\0" }
7842  , { SYBEEINI, EXINFO, "Must call dbreginit before dbregexec\0" }
7843  , { SYBEETD, EXPROGRAM, "Failure to send the expected amount of TEXT or IMAGE data via dbmoretext\0" }
7844  , { SYBEEUNR, EXCOMM, "Unsolicited event notification received\0" }
7845  , { SYBEEVOP, EXINFO, "Called dbregwatch with a bad options parameter\0" }
7846  , { SYBEEVST, EXINFO, "Must initiate a transaction before calling dbregparam\0" }
7847  , { SYBEFCON, EXCOMM, "Adaptive Server connection failed\0" }
7848  , { SYBEFRES, EXFATAL, "Challenge-Response function failed\0" }
7849  , { SYBEFSHD, EXRESOURCE, "Error in attempting to find the Sybase home directory\0" }
7850  , { SYBEFUNC, EXPROGRAM, "Functionality not supported at the specified version level\0" }
7851  , { SYBEICN, EXPROGRAM, "Invalid computeid or compute column number\0" }
7852  , { SYBEIDCL, EXCONSISTENCY, "Illegal datetime column length returned by Adaptive Server. Legal datetime lengths "
7853  "are 4 and 8 bytes\0" }
7854  , { SYBEIDECCL, EXCONSISTENCY, "Invalid decimal column length returned by the server\0" }
7855  , { SYBEIFCL, EXCONSISTENCY, "Illegal floating-point column length returned by Adaptive Server. Legal "
7856  "floating-point lengths are 4 and 8 bytes\0" }
7857  , { SYBEIFNB, EXPROGRAM, "Illegal field number passed to bcp_control\0" }
7858  , { SYBEIICL, EXCONSISTENCY, "Illegal integer column length returned by Adaptive Server. Legal integer lengths "
7859  "are 1, 2, and 4 bytes\0" }
7860  , { SYBEIMCL, EXCONSISTENCY, "Illegal money column length returned by Adaptive Server. Legal money lengths are 4 "
7861  "and 8 bytes\0" }
7862  , { SYBEINLN, EXUSER, "Interface file: unexpected end-of-line\0" }
7863  , { SYBEINTF, EXUSER, "Server name not found in configuration files\0" }
7864  , { SYBEINUMCL, EXCONSISTENCY, "Invalid numeric column length returned by the server\0" }
7865  , { SYBEIPV, EXINFO, "%1! is an illegal value for the %2! parameter of %3!\0%d %s %s" }
7866  , { SYBEISOI, EXCONSISTENCY, "International Release: Invalid sort-order information found\0" }
7867  , { SYBEISRVPREC, EXCONSISTENCY, "Illegal precision value returned by the server\0" }
7868  , { SYBEISRVSCL, EXCONSISTENCY, "Illegal scale value returned by the server\0" }
7869  , { SYBEITIM, EXPROGRAM, "Illegal timeout value specified\0" }
7870  , { SYBEIVERS, EXPROGRAM, "Illegal version level specified\0" }
7871  , { SYBEKBCI, EXINFO, "1000 rows sent to the server\0" }
7872  , { SYBEKBCO, EXINFO, "1000 rows successfully bulk copied to host file\0" }
7873  , { SYBEMEM, EXRESOURCE, "Unable to allocate sufficient memory\0" }
7874  , { SYBEMOV, EXUSER, "Money arithmetic resulted in overflow in function %1!\0%s" }
7875  , { SYBEMPLL, EXUSER, "Attempt to set maximum number of DBPROCESSes lower than 1\0" }
7876  , { SYBEMVOR, EXPROGRAM, "Month values must be between 1 and 12\0" }
7877  , { SYBENBUF, EXINFO, "Called dbsendpassthru with a NULL buf parameter\0" }
7878  , { SYBENBVP, EXPROGRAM, "Cannot pass dbsetnull a NULL bindval pointer\0" }
7879  , { SYBENDC, EXPROGRAM, "Cannot have negative component in date in numeric form\0" }
7880  , { SYBENDTP, EXPROGRAM, "Called dbdatecrack with NULL datetime parameter\0" }
7881  , { SYBENEG, EXCOMM, "Negotiated login attempt failed\0" }
7882  , { SYBENHAN, EXINFO, "Called dbrecvpassthru with a NULL handle parameter\0" }
7883  , { SYBENMOB, EXPROGRAM, "No such member of order by clause\0" }
7884  , { SYBENOEV, EXINFO, "DBPOLL can not be called when registered procedure notifications have been disabled\0" }
7885  , { SYBENPRM, EXPROGRAM, "NULL parameter not allowed for this dboption\0" }
7886  , { SYBENSIP, EXPROGRAM, "Negative starting index passed to dbstrcpy\0" }
7887  , { SYBENTLL, EXUSER, "Name too long for LOGINREC field\0" }
7888  , { SYBENTTN, EXPROGRAM, "Attempt to use dbtxtsput to put a new text timestamp into a non-existent data row\0" }
7889  , { SYBENULL, EXINFO, "NULL DBPROCESS pointer passed to DB-Library\0" }
7890  , { SYBENULP, EXPROGRAM, "Called %1! with parameter %2! NULL\0%s %d" }
7891  , { SYBENXID, EXNONFATAL, "The Server did not grant us a distributed-transaction ID\0" }
7892  , { SYBEONCE, EXPROGRAM, "Function can be called only once\0" }
7893  , { SYBEOOB, EXCOMM, "Error in sending out-of-band data to the server\0" }
7894  , { SYBEOPIN, EXNONFATAL, "Could not open interface file\0" }
7895  , { SYBEOPNA, EXNONFATAL, "Option is not available with current server\0" }
7896  , { SYBEOREN, EXINFO, "International Release: Warning: an out-of-range error-number was encountered in "
7897  "dblib.loc. The maximum permissible error-number is defined as DBERRCOUNT in sybdb.h\0" }
7898  , { SYBEORPF, EXUSER, "Attempt to set remote password would overflow "
7899  "the login record's remote password field\0" }
7900  , { SYBEPOLL, EXINFO, "There is already an active dbpoll\0" }
7901  , { SYBEPRTF, EXINFO, "dbtracestring may only be called from a printfunc\0" }
7902  , { SYBEPWD, EXUSER, "Login incorrect\0" }
7903  , { SYBERDCN, EXCONVERSION, "Requested data conversion does not exist\0" }
7904  , { SYBERDNR, EXPROGRAM, "Attempt to retrieve data from a non-existent row\0" }
7905  , { SYBEREAD, EXCOMM, "Read from the server failed\0" }
7906  , { SYBERESP, EXPROGRAM, "Response function address passed to dbresponse must be non-NULL\0" }
7907  , { SYBERPCS, EXINFO, "Must call dbrpcinit before dbrpcparam or dbrpcsend\0" }
7908  , { SYBERPIL, EXPROGRAM, "It is illegal to pass -1 to dbrpcparam for the datalen of parameters which are of "
7909  "type SYBCHAR, SYBVARCHAR, SYBBINARY, or SYBVARBINARY\0" }
7910  , { SYBERPNA, EXNONFATAL, "The RPC facility is available only when using a server whose version number is 4.0 "
7911  "or later\0" }
7912  , { SYBERPND, EXPROGRAM, "Attempt to initiate a new Adaptive Server operation with results pending\0" }
7913  , { SYBERPNULL, EXPROGRAM, "value parameter for dbrpcparam can be NULL, only if the datalen parameter is 0\0" }
7914  , { SYBERPTXTIM, EXPROGRAM, "RPC parameters cannot be of type text or image\0" }
7915  , { SYBERPUL, EXPROGRAM, "When passing a SYBINTN, SYBDATETIMN, SYBMONEYN, or SYBFLTN parameter via "
7916  "dbrpcparam, it is necessary to specify the parameter's maximum or actual length so "
7917  "that DB-Library can recognize it as a SYINT1, SYBINT2, SYBINT4, SYBMONEY, SYBMONEY4, "
7918  "and so on\0" }
7919  , { SYBERTCC, EXPROGRAM, "dbreadtext may not be used to receive the results of a query that contains a "
7920  "COMPUTE clause\0" }
7921  , { SYBERTSC, EXPROGRAM, "dbreadtext may be used only to receive the results of a query that contains a "
7922  "single result column\0" }
7923  , { SYBERXID, EXNONFATAL, "The Server did not recognize our distributed-transaction ID\0" }
7924  , { SYBESECURE, EXPROGRAM, "Secure SQL Server function not supported in this version\0" }
7925  , { SYBESEFA, EXPROGRAM, "DBSETNOTIFS cannot be called if connections are present\0" }
7926  , { SYBESEOF, EXCOMM, "Unexpected EOF from the server\0" }
7927  , { SYBESFOV, EXPROGRAM, "International Release: dbsafestr overflowed its destination buffer\0" }
7928  , { SYBESMSG, EXSERVER, "General Adaptive Server error: Check messages from the server\0" }
7929  , { SYBESOCK, EXCOMM, "Unable to open socket\0" }
7930  , { SYBESPID, EXPROGRAM, "Called dbspid with a NULL dbproc\0" }
7931  , { SYBESYNC, EXCOMM, "Read attempted while out of synchronization with Adaptive Server\0" }
7932  , { SYBETEXS, EXINFO, "Called dbmoretext with a bad size parameter\0" }
7933  , { SYBETIME, EXTIME, "Adaptive Server connection timed out\0" }
7934  , { SYBETMCF, EXPROGRAM, "Attempt to install too many custom formats via dbfmtinstall\0" }
7935  , { SYBETMTD, EXPROGRAM, "Attempt to send too much TEXT data via the dbmoretext call\0" }
7936  , { SYBETPAR, EXPROGRAM, "No SYBTEXT or SYBIMAGE parameters were defined\0" }
7937  , { SYBETPTN, EXUSER, "Syntax error: only two periods are permitted in table names\0" }
7938  , { SYBETRAC, EXINFO, "Attempted to turn off a trace flag that was not on\0" }
7939  , { SYBETRAN, EXINFO, "DBPROCESS is being used for another transaction\0" }
7940  , { SYBETRAS, EXINFO, "DB-Library internal error - trace structure not found\0" }
7941  , { SYBETRSN, EXINFO, "Bad numbytes parameter passed to dbtracestring\0" }
7942  , { SYBETSIT, EXINFO, "Attempt to call dbtsput with an invalid timestamp\0" }
7943  , { SYBETTS, EXUSER, "The table which bulk copy is attempting to copy to a host file is shorter than the "
7944  "number of rows which bulk copy was instructed to skip\0" }
7945  , { SYBETYPE, EXINFO, "Invalid argument type given to Hyper/DB-Library\0" }
7946  , { SYBEUCPT, EXUSER, "Unrecognized custom-format parameter-type encountered in dbstrbuild\0" }
7947  , { SYBEUCRR, EXCONSISTENCY, "Internal software error: Unknown connection result reported by dbpasswd\0" }
7948  , { SYBEUDTY, EXCONSISTENCY, "Unknown datatype encountered\0" }
7949  , { SYBEUFDS, EXUSER, "Unrecognized format encountered in dbstrbuild\0" }
7950  , { SYBEUFDT, EXCONSISTENCY, "Unknown fixed-length datatype encountered\0" }
7951  , { SYBEUHST, EXUSER, "Unknown host machine name\0" }
7952  , { SYBEUMSG, EXCOMM, "Unknown message-id in MSG datastream\0" }
7953  , { SYBEUNAM, EXFATAL, "Unable to get current user name from operating system\0" }
7954  , { SYBEUNOP, EXNONFATAL, "Unknown option passed to dbsetopt\0" }
7955  , { SYBEUNT, EXUSER, "Unknown network type found in interface file\0" }
7956  , { SYBEURCI, EXRESOURCE, "International Release: Unable to read copyright information from the DB-Library "
7957  "localization file\0" }
7958  , { SYBEUREI, EXRESOURCE, "International Release: Unable to read error information from the DB-Library "
7959  "localization file\0" }
7960  , { SYBEUREM, EXRESOURCE, "International Release: Unable to read error mnemonic from the DB-Library "
7961  "localization file\0" }
7962  , { SYBEURES, EXRESOURCE, "International Release: Unable to read error string from the DB-Library "
7963  "localization file. 401 Error severities\0" }
7964  , { SYBEURMI, EXRESOURCE, "International Release: Unable to read money-format information from the DB-Library "
7965  "localization file\0" }
7966  , { SYBEUSCT, EXCOMM, "Unable to set communications timer\0" }
7967  , { SYBEUTDS, EXCOMM, "Unrecognized TDS version received from the server\0" }
7968  , { SYBEUVBF, EXPROGRAM, "Attempt to read an unknown version of bcp format file\0" }
7969  , { SYBEUVDT, EXCONSISTENCY, "Unknown variable-length datatype encountered\0" }
7970  , { SYBEVDPT, EXUSER, "For bulk copy, all variable-length data must have either a length-prefix or a "
7971  "terminator specified\0" }
7972  , { SYBEWAID, EXCONSISTENCY, "DB-Library internal error: ALTFMT following ALTNAME has wrong id\0" }
7973  , { SYBEWRIT, EXCOMM, "Write to the server failed\0" }
7974  , { SYBEXOCI, EXNONFATAL, "International Release: A character-set translation overflowed its destination "
7975  "buffer while using bcp to copy data from a host-file to the server\0" }
7976  , { SYBEXTDN, EXPROGRAM, "Warning: the xlt_todisp parameter to dbfree_xlate was NULL. The space associated "
7977  "with the xlt_tosrv parameter has been freed\0" }
7978  , { SYBEXTN, EXPROGRAM, "The xlt_tosrv and xlt_todisp parameters to dbfree_xlate were NULL\0" }
7979  , { SYBEXTSN, EXPROGRAM, "Warning: the xlt_tosrv parameter to dbfree_xlate was NULL. The space associated "
7980  "with the xlt_todisp parameter has been freed\0" }
7981  , { SYBEZTXT, EXINFO, "Attempt to send zero length TEXT or IMAGE to dataserver via dbwritetext\0" }
7982  , { SYBECOLSIZE, EXINFO, "Invalid column information structure size\0" }
7983  , { 50000, EXCONVERSION, "Data is truncated during conversion\0" }
7984  , { 50001, EXPROGRAM, "Max connections reached, increase value of TDS_MAX_CONN\0" }
7985  };
7986 
7987 /** \internal
7988  * \ingroup dblib_internal
7989  * \brief Call client-installed error handler
7990  *
7991  * \param dbproc contains all information needed by db-lib to manage communications with the server.
7992  * \param msgno identifies the error message to be passed to the client's handler.
7993  * \param errnum identifies the OS error (errno), if any. Use 0 if not applicable.
7994  * \returns the handler's return code, subject to correction and adjustment for vendor style:
7995  * - INT_CANCEL The db-lib function that encountered the error will return FAIL.
7996  * - INT_TIMEOUT The db-lib function will cancel the operation and return FAIL. \a dbproc remains useable.
7997  * - INT_CONTINUE The db-lib function will retry the operation.
7998  * \remarks
7999  * The client-installed handler may also return INT_EXIT. If Sybase semantics are used, this function notifies
8000  * the user and calls exit(3). If Microsoft semantics are used, this function returns INT_CANCEL.
8001  *
8002  * If the client-installed handler returns something other than these four INT_* values, or returns timeout-related
8003  * value for anything but SYBETIME, it's treated here as INT_EXIT (see above).
8004  *
8005  * Instead of sprinkling error text all over db-lib, we consolidate it here,
8006  * where it can be translated (one day), and where it can be mapped to the TDS error number.
8007  * The libraries don't use consistent error numbers or messages, so when libtds has to emit
8008  * an error message, it can't include the text. It can pass its error number to a client-library
8009  * function, which will interpret it, add the text, call the application's installed handler
8010  * (if any) and return the handler's return code back to the caller.
8011  *
8012  * The call stack may look something like this:
8013  *
8014  * -# application
8015  * -# db-lib function (encounters error)
8016  * -# dbperror
8017  * -# error handler (installed by application)
8018  *
8019  * The error handling in this case is unambiguous: the caller invokes this function, the client's handler returns its
8020  * instruction, which the caller receives. Quite often the caller will get INT_CANCEL, in which case it should put its
8021  * house in order and return FAIL.
8022  *
8023  * The call stack may otherwise look something like this:
8024  *
8025  * -# application
8026  * -# db-lib function
8027  * -# libtds function (encounters error)
8028  * -# _dblib_handle_err_message
8029  * -# dbperror
8030  * -# error handler (installed by application)
8031  *
8032  * Because different client libraries specify their handler semantics differently,
8033  * and because libtds doesn't know which client library is in charge of any given connection, it cannot interpret the
8034  * raw return code from a db-lib error handler. For these reasons,
8035  * libtds calls _dblib_handle_err_message, which translates between libtds and db-lib semantics.
8036  * \sa dberrhandle(), _dblib_handle_err_message().
8037  */
8038 int
8039 dbperror (DBPROCESS *dbproc, DBINT msgno, long errnum, ...)
8040 {
8041  static const char int_exit_text[] = "FreeTDS: db-lib: exiting because client error handler returned %s for msgno %d\n";
8042  static const char int_invalid_text[] = "%s (%d) received from client-installed error handler for nontimeout for error %d."
8043  " Treating as INT_EXIT\n";
8044  static const DBLIB_ERROR_MESSAGE default_message = { 0, EXCONSISTENCY, "unrecognized msgno" };
8045  DBLIB_ERROR_MESSAGE constructed_message = { 0, EXCONSISTENCY, NULL };
8046  const DBLIB_ERROR_MESSAGE *msg = &default_message;
8047 
8048  int i, rc = INT_CANCEL;
8049  const char *os_msgtext = strerror((int)errnum),
8050  *rc_name = "logic error";
8051  char rc_buf[16];
8052 
8053  tdsdump_log(TDS_DBG_FUNC, "dbperror(%p, %d, %ld)\n", dbproc, msgno, errnum); /* dbproc can be NULL */
8054 
8055 #ifdef _WIN32
8056  /*
8057  * Unfortunately MingW uses the "old" msvcrt.dll (Visual C++ 2005 uses
8058  * a newer version) which does not set errno when allocation functions
8059  * cannot allocate memory, so we do it for them.
8060  */
8061  if (msgno == SYBEMEM)
8062  errnum = ENOMEM;
8063 #endif
8064 
8065  if (os_msgtext == NULL)
8066  os_msgtext = "no OS error";
8067 
8068  assert(_dblib_err_handler != NULL); /* always installed by dbinit() or dberrhandle() */
8069 
8070  /* look up the error message */
8071  for (i=0; i < TDS_VECTOR_SIZE(dblib_error_messages); i++ ) {
8072  if (dblib_error_messages[i].msgno == msgno) {
8073 
8074  /*
8075  * See if the message has placeholders. If so, build a message string on the heap.
8076  * The presence of placeholders is indicated by the existence of a "string after the string",
8077  * i.e., a format string (for dbstrbuild) after a null "terminator" in the message.
8078  * On error -- can't allocate, can't build the string -- give up and call the client handler anyway.
8079  */
8080  const char * ptext = dblib_error_messages[i].msgtext;
8081  const char * pformats = ptext + strlen(ptext) + 1;
8082  msg = &dblib_error_messages[i];
8083  assert(*(pformats - 1) == '\0');
8084  if(*pformats != '\0') {
8085  va_list ap;
8086  int result_len, len = 2 * (int)strlen(ptext);
8087  char * buffer = tds_new0(char, len);
8088 
8089  if (buffer == NULL)
8090  break;
8091  va_start(ap, errnum);
8092  rc = tds_vstrbuild(buffer, len, &result_len, ptext, TDS_NULLTERM, pformats, TDS_NULLTERM, ap);
8093  buffer[result_len] = '\0';
8094  va_end(ap);
8095  if (TDS_FAILED(rc)) {
8096  free(buffer);
8097  break;
8098  }
8099  constructed_message.msgtext = buffer;
8100  constructed_message.severity = msg->severity;
8101  msg = &constructed_message;
8102  }
8103  break;
8104  }
8105  }
8106 
8107  if (dbproc && dbproc->tds_socket && dbproc->tds_socket->login) {
8108  DSTR server_name_dstr = dbproc->tds_socket->login->server_name;
8109  if (!tds_dstr_isempty(&server_name_dstr)) {
8110  char * buffer = NULL;
8111  if (asprintf(&buffer, "%s (%s)", msg->msgtext,
8112  tds_dstr_cstr(&server_name_dstr)) >= 0) {
8113  free((char*) constructed_message.msgtext);
8114  constructed_message.msgtext = buffer;
8115  constructed_message.severity = msg->severity;
8116  msg = &constructed_message;
8117  }
8118  }
8119  }
8120 
8121  tdsdump_log(TDS_DBG_FUNC, "dbperror: Calling dblib_err_handler with msgno = %d; msg->msgtext = \"%s\"\n",
8122  msgno, msg->msgtext);
8123 
8124  /* call the error handler */
8125  rc = (*_dblib_err_handler)(dbproc, msg->severity, msgno, (int) errnum,
8126  (char*) msg->msgtext, (char*) os_msgtext);
8127  switch (rc) {
8128  case INT_EXIT:
8129  rc_name = "INT_EXIT";
8130  break;
8131  case INT_CONTINUE:
8132  rc_name = "INT_CONTINUE";
8133  break;
8134  case INT_CANCEL:
8135  rc_name = "INT_CANCEL";
8136  break;
8137  case INT_TIMEOUT:
8138  rc_name = "INT_TIMEOUT";
8139  break;
8140  default:
8141  rc_name = "invalid";
8142  break;
8143  }
8144  tdsdump_log(TDS_DBG_FUNC, "dbperror: dblib_err_handler for msgno = %d; msg->msgtext = \"%s\" -- returns %d (%s)\n",
8145  msgno, msg->msgtext, rc, rc_name);
8146 
8147  /* we're done with the dynamic string now. */
8148  free((char*) constructed_message.msgtext);
8149 
8150  /* Timeout return codes are errors for non-timeout conditions. */
8151  if (msgno != SYBETIME) {
8152  switch (rc) {
8153  case INT_CONTINUE:
8154  tdsdump_log(TDS_DBG_SEVERE, int_invalid_text, "INT_CONTINUE", rc, msgno);
8155  rc = INT_EXIT;
8156  break;
8157  case INT_TIMEOUT:
8158  tdsdump_log(TDS_DBG_SEVERE, int_invalid_text, "INT_TIMEOUT", rc, msgno);
8159  rc = INT_EXIT;
8160  break;
8161  default:
8162  break;
8163  }
8164  }
8165 
8166  /*
8167  * Sybase exits on INT_EXIT; Microsoft converts to INT_CANCEL.
8168  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dblibc/dbc_pdc04c_6v39.asp
8169  */
8170  switch (rc) {
8171  case INT_CONTINUE:
8172  /* Microsoft does not define INT_TIMEOUT. Instead, two consecutive INT_CONTINUEs yield INT_CANCEL. */
8173  if (dbproc && dbproc->msdblib && ++dbproc->ntimeouts >=2) {
8174  dbproc->ntimeouts = 0;
8175  rc = INT_CANCEL;
8176  } /* fall through */
8177  case INT_CANCEL:
8178  case INT_TIMEOUT:
8179  return rc; /* normal case */
8180  break;
8181  default:
8182  sprintf(rc_buf, "%d", rc);
8183  rc_name = rc_buf;
8184  tdsdump_log(TDS_DBG_SEVERE, int_invalid_text, "Invalid return code", rc, msgno);
8185  /* fall through */
8186  case INT_EXIT:
8187  if (dbproc && dbproc->msdblib) {
8188  /* Microsoft behavior */
8189  return INT_CANCEL;
8190  }
8191  /* fprintf(stderr, int_exit_text, rc_name, msgno); */
8192  tdsdump_log(TDS_DBG_SEVERE, int_exit_text, rc_name, msgno);
8193  break;
8194  }
8195  exit(EXIT_FAILURE);
8196  return rc; /* not reached */
8197 }
8198 
ncbi::TMaskedQueryRegions mask
void(*)(CSeq_entry_Handle seh, IWorkbench *wb, const CSerialObject &obj) handler
#define EXIT_FAILURE
Definition: fastme.h:73
static CS_COMMAND * cmd
Definition: ct_dynamic.c:26
#define strcat(s, k)
CS_CONTEXT * ctx
Definition: t0006.c:12
static void buffer_alloc(DBPROCESS *dbproc)
Definition: buffering.h:459
static void buffer_delete_rows(DBPROC_ROWBUF *buf, int count)
Deleting a row from the buffer doesn't affect memory allocation.
Definition: buffering.h:274
static int buffer_is_full(const DBPROC_ROWBUF *buf)
Can the buffer be written to?
Definition: buffering.h:123
static int buffer_count(const DBPROC_ROWBUF *buf)
A few words on the buffering design.
Definition: buffering.h:111
static DBINT buffer_idx2row(const DBPROC_ROWBUF *buf, int idx)
Convert an index to a row number.
Definition: buffering.h:230
static void buffer_set_capacity(DBPROCESS *dbproc, int nrows)
Definition: buffering.h:430
static int buffer_add_row(DBPROCESS *dbproc, TDSRESULTINFO *resinfo)
Called by dbnextrow Returns a row buffer index, or -1 to indicate the buffer is full.
Definition: buffering.h:483
static void buffer_free(DBPROC_ROWBUF *buf)
Definition: buffering.h:176
static void buffer_transfer_bound_data(DBPROC_ROWBUF *buf, TDS_INT res_type, TDS_INT compute_id, DBPROCESS *dbproc, int idx)
Definition: buffering.h:303
static int buffer_row2idx(const DBPROC_ROWBUF *buf, int row_number)
Convert a row number to an index.
Definition: buffering.h:240
static RETCODE buffer_save_row(DBPROCESS *dbproc)
Definition: buffering.h:526
static int buffer_current_index(const DBPROCESS *dbproc)
Return the current row buffer index.
Definition: buffering.h:401
int dbcurcmd(DBPROCESS *dbproc)
Definition: dblib.c:6133
static const DBSMALLINT null_SMALLINT
Definition: dblib.c:427
RETCODE dbsetlbool(LOGINREC *login, int value, int which)
Definition: dblib.c:907
static TDSCOLUMN * dbcolptr(DBPROCESS *dbproc, int column)
Definition: dblib.c:345
static const DBTINYINT null_TINYINT
Definition: dblib.c:426
DBINT dblastrow(DBPROCESS *dbproc)
Definition: dblib.c:7130
RETCODE dbcmdrow(DBPROCESS *dbproc)
Definition: dblib.c:4158
EHANDLEFUNC _dblib_err_handler
Definition: dblib.c:165
static TDSCOLUMN * dbacolptr(DBPROCESS *dbproc, int computeid, int column, int is_bind)
Definition: dblib.c:366
DBPROCESS * tdsdbopen(LOGINREC *login, const char *server, int msdblib)
Definition: dblib.c:1174
static char * dbstring_get(DBSTRING *dbstr)
Definition: dblib.c:1069
STATUS dbnextrow(DBPROCESS *dbproc)
Definition: dblib.c:2076
static int _get_printable_size(TDSCOLUMN *colinfo)
Definition: dblib.c:3670
int dbperror(DBPROCESS *dbproc, DBINT msgno, long errnum,...)
Definition: dblib.c:8039
static const char * prresult_type(int result_type, prbuf_t buf)
Definition: dblib.c:1650
static BYTE * _dbcoldata(TDSCOLUMN *colinfo)
Definition: dblib.c:3253
static const DBINT null_INT
Definition: dblib.c:428
static RETCODE dbstring_concat(DBSTRING **dbstrp, const char *p)
Definition: dblib.c:1003
static const DBLIB_ERROR_MESSAGE dblib_error_messages[]
Definition: dblib.c:7659
void copy_data_to_host_var(DBPROCESS *, TDS_SERVER_TYPE, const BYTE *, int, BYTE *, DBINT, int, DBINT *)
static const DBREAL null_REAL
Definition: dblib.c:431
RETCODE dbrows(DBPROCESS *dbproc)
Definition: dblib.c:3929
static const char * prretcode(int retcode, prbuf_t buf)
Definition: dblib.c:1636
static int _dbnullable(DBPROCESS *dbproc, int column)
Definition: dblib.c:7255
void dbsetavail(DBPROCESS *dbproc)
Definition: dblib.c:7198
static const char * prdbresults_state(int retcode, prbuf_t buf)
Definition: dblib.c:1604
static const DBFLT8 null_FLT8
Definition: dblib.c:430
int dbiowdesc(DBPROCESS *dbproc)
Definition: dblib.c:7170
static const DBMONEY4 null_SMALLMONEY
Definition: dblib.c:440
static DBOPTION * init_dboptions(void)
Definition: dblib.c:1135
static const DBBIT null_BIT
Definition: dblib.c:425
static int g_dblib_version
Definition: dblib.c:197
static const DBBIGINT null_BIGINT
Definition: dblib.c:429
static const DBCHAR null_CHAR
Definition: dblib.c:433
static TDS_SERVER_TYPE dblib_bound_type(int bindtype)
Definition: dblib.c:2186
static const DBNUMERIC null_NUMERIC
Definition: dblib.c:441
static NULLREP default_null_representations[MAXBINDTYPES]
Definition: dblib.c:444
int dbtds(DBPROCESS *dbproc)
Definition: dblib.c:6723
struct _dblib_error_message DBLIB_ERROR_MESSAGE
struct dblib_context DBLIBCONTEXT
static int dbbindtype(int datatype)
Definition: dblib.c:481
RETCODE dbcolinfo(DBPROCESS *dbproc, CI_TYPE type, DBINT column, DBINT computeid, DBCOL *pdbcol)
Get a bunch of column attributes with a single call (Microsoft-compatibility feature).
Definition: dblib.c:2985
DBINT dbcurrow(DBPROCESS *dbproc)
Definition: dblib.c:6099
static const char * dbcoltablename(DBPROCESS *dbproc, int column)
Definition: dblib.c:1899
static char * _dbprdate(char *timestr)
Definition: dblib.c:7242
STATUS dbrowtype(DBPROCESS *dbproc)
Definition: dblib.c:6116
static const char * prdbretcode(RETCODE retcode, prbuf_t buf)
Definition: dblib.c:1620
static void dbstring_free(DBSTRING **dbstrp)
Definition: dblib.c:984
static int g_dbsetversion_called
Definition: dblib.c:217
MHANDLEFUNC _dblib_msg_handler
Definition: dblib.c:164
int dbiordesc(DBPROCESS *dbproc)
Definition: dblib.c:7154
static const DBDATETIME4 null_SMALLDATETIME
Definition: dblib.c:438
static int dblib_add_connection(DBLIBCONTEXT *ctx, TDSSOCKET *tds)
Definition: dblib.c:221
static const DBVARYCHAR null_VARYCHAR
Definition: dblib.c:434
RETCODE dbsetllong(LOGINREC *login, long value, int which)
Definition: dblib.c:836
static void dblib_del_connection(DBLIBCONTEXT *ctx, TDSSOCKET *tds)
Definition: dblib.c:240
static const char * tds_prdatatype(int datatype_token)
Returns type in string.
Definition: dblib.c:7273
static void dblib_release_tds_ctx(int count)
Definition: dblib.c:290
static int default_err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
Definition: dblib.c:5001
static TDSCONTEXT * dblib_get_tds_ctx(void)
Definition: dblib.c:258
static DBLIBCONTEXT g_dblib_ctx
Definition: dblib.c:192
static const DBDATETIME null_DATETIME
Definition: dblib.c:437
static DBINT dbstring_length(DBSTRING *dbstr)
Definition: dblib.c:1037
static RETCODE dblib_datecrack(DBPROCESS *dbproc, BOOL nano_precision, DBDATEREC *output, int type, const void *data)
Definition: dblib.c:5702
static void db_env_chg(TDSSOCKET *tds, int type, char *oldval, char *newval)
Definition: dblib.c:306
RETCODE dbsetlname(LOGINREC *login, const char *value, int which)
Definition: dblib.c:773
static const char *const opttext[DBNUMOPTIONS]
Definition: dblib.c:1095
RETCODE dbgetnull(DBPROCESS *dbproc, int bindtype, int varlen, BYTE *varaddr)
Definition: dblib.c:543
char prbuf_t[24]
Definition: dblib.c:1601
DBBOOL dbdead(DBPROCESS *dbproc)
Definition: dblib.c:4967
static const DBMONEY null_MONEY
Definition: dblib.c:439
DBBOOL dbisavail(DBPROCESS *dbproc)
Definition: dblib.c:7179
static const TDS_DATETIMEALL null_DATETIMEALL
Definition: dblib.c:442
static RETCODE dbstring_assign(DBSTRING **dbstrp, const char *p)
Definition: dblib.c:1028
static int dbstring_getchar(DBSTRING *dbstr, ssize_t i)
Definition: dblib.c:1051
static DBPROCESS * dbproc
Definition: done_handling.c:29
static int msdblib
Definition: numeric.c:38
static int hndlintr(DBPROCESS *dbproc)
Definition: timeout.c:86
static int chkintr(DBPROCESS *dbproc)
Definition: timeout.c:79
@ dblib_msdblib
Definition: dblib.h:164
#define DBPERROR_RETURN(x, msg)
Definition: dblib.h:196
#define CHECK_PARAMETER_NOPROC(x, msg)
Definition: dblib.h:195
#define CHECK_NULP(x, func, param_num, ret)
Definition: dblib.h:194
@ _DB_RES_SUCCEED
Definition: dblib.h:39
@ _DB_RES_NO_MORE_RESULTS
Definition: dblib.h:38
@ _DB_RES_NEXT_RESULT
Definition: dblib.h:37
@ _DB_RES_INIT
Definition: dblib.h:34
@ _DB_RES_RESULTSET_EMPTY
Definition: dblib.h:35
@ _DB_RES_RESULTSET_ROWS
Definition: dblib.h:36
#define CHECK_PARAMETER(x, msg, ret)
Definition: dblib.h:193
#define CHECK_CONN(ret)
Definition: dblib.h:198
static DLIST_TYPE *DLIST_NAME() next(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
Definition: dlist.tmpl.h:56
#define TDS_ENV_DATABASE
Definition: proto.h:127
TDS_SERVER_TYPE
Definition: proto.h:161
@ SYBTIMEN
Definition: proto.h:226
@ SYBVARIANT
Definition: proto.h:200
@ SYB5INT8
Definition: proto.h:220
@ SYBINTERVAL
Definition: proto.h:221
@ SYBUINT8
Definition: proto.h:215
@ SYBLONGBINARY
Definition: proto.h:211
@ SYBUNIQUE
Definition: proto.h:199
@ SYBUINTN
Definition: proto.h:227
@ SYBXML
Definition: proto.h:229
@ XSYBNVARCHAR
Definition: proto.h:195
@ XSYBCHAR
Definition: proto.h:193
@ SYBLONGCHAR
Definition: proto.h:222
@ SYBUINT2
Definition: proto.h:213
@ SYBDATEN
Definition: proto.h:219
@ XSYBVARCHAR
Definition: proto.h:194
@ SYBUNITEXT
Definition: proto.h:228
@ SYBUINT4
Definition: proto.h:214
@ SYBSINT1
Definition: proto.h:224
@ XSYBVARBINARY
Definition: proto.h:197
@ XSYBNCHAR
Definition: proto.h:196
@ SYBMSUDT
Definition: proto.h:201
@ SYB5BIGTIME
Definition: proto.h:231
@ XSYBBINARY
Definition: proto.h:198
@ SYBMSXML
Definition: proto.h:202
@ SYB5BIGDATETIME
Definition: proto.h:230
@ SYBUINT1
Definition: proto.h:212
@ TDS_ODBC_ON
Definition: proto.h:413
#define TDS_ENV_CHARSET
Definition: proto.h:129
#define TDS_FAIL
Definition: tds.h:204
#define tds_new(type, n)
Definition: tds.h:1392
#define TDS_NO_COUNT
Definition: tds.h:214
#define is_numeric_type(x)
Definition: tds.h:454
#define TDS_DONEPROC_RESULT
Definition: tds.h:228
#define TDS_FAILED(rc)
Definition: tds.h:206
#define TDS_ROWFMT_RESULT
Definition: tds.h:224
tds_sysdep_int32_type TDS_INT
Definition: tds.h:149
#define tds_get_parent(tds)
Definition: tds.h:1296
@ TDS_STOPAT_DONE
Definition: tds.h:255
@ TDS_TOKEN_TRAILING
Definition: tds.h:262
@ 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 TDS_MSG_RESULT
Definition: tds.h:219
#define TDS_DONE_RESULT
Definition: tds.h:227
#define tdsdump_log
Definition: tds.h:1561
#define TDS_INVALID_TYPE
Definition: tds.h:160
#define TDS_DBG_INFO1
Definition: tds.h:900
#define TDS_NO_MORE_RESULTS
Definition: tds.h:202
#define TDS_COMPUTEFMT_RESULT
Definition: tds.h:225
#define TDS_DEF_BLKSZ
Definition: tds.h:476
#define is_datetime_type(x)
return true if type is a datetime (but not date or time)
Definition: tds.h:456
#define TDS_OTHERS_RESULT
Definition: tds.h:230
#define TDS_DBG_SEVERE
Definition: tds.h:904
#define TDS_CMD_FAIL
Definition: tds.h:223
static bool is_tds_type_valid(int type)
Definition: tds.h:463
#define tds_get_s(tds)
Definition: tds.h:1298
tds_sysdep_int64_type TDS_INT8
Definition: tds.h:153
#define TDS_DESCRIBE_RESULT
Definition: tds.h:226
#define is_blob_col(x)
Definition: tds.h:445
#define TDS_MAX_CONN
Definition: tds.h:471
#define TDS_COMPUTE_RESULT
Definition: tds.h:220
#define TDS_CMD_SUCCEED
Definition: tds.h:222
#define TDS_CMD_DONE
Definition: tds.h:221
#define TDS_PARAM_RESULT
Definition: tds.h:217
unsigned char TDS_TINYINT
Definition: tds.h:146
@ TDS_PENDING
cilent is waiting for data
Definition: tds.h:866
#define tdsdump_dump_buf
Definition: tds.h:1564
tds_sysdep_int16_type TDS_SMALLINT
Definition: tds.h:147
#define TDS_VECTOR_SIZE(x)
Definition: tds.h:360
#define TDS_CANCELLED
Definition: tds.h:205
#define IS_TDSDEAD(x)
Definition: tds.h:1717
#define tds_new0(type, n)
Definition: tds.h:1393
char TDS_CHAR
Definition: tds.h:144
#define is_nullable_type(x)
Definition: tds.h:439
#define TDS_ROW_RESULT
Definition: tds.h:216
@ TDS_DONE_MORE_RESULTS
more results follow
Definition: tds.h:271
@ TDS_DONE_ERROR
error occurred
Definition: tds.h:272
int TDSRET
Definition: tds.h:201
tds_sysdep_uint16_type TDS_USMALLINT
Definition: tds.h:148
#define TDS_DBG_ERROR
Definition: tds.h:903
#define TDS_SUCCESS
Definition: tds.h:203
#define TDS_STATUS_RESULT
Definition: tds.h:218
#define TDS_RESIZE(p, n_elem)
Definition: tds.h:1390
#define tds_set_parent(tds, val)
Definition: tds.h:1297
#define TDS_SUCCEED(rc)
Definition: tds.h:207
#define TDS_ZERO_FREE(x)
Definition: tds.h:359
#define TDS_MAX_LOGIN_STR_SZ
Definition: tds.h:582
tds_sysdep_uint32_type TDS_UINT
Definition: tds.h:150
#define is_similar_type(x, y)
Definition: tds.h:461
#define TDS_DONEINPROC_RESULT
Definition: tds.h:229
#define TDS_DBG_FUNC
Definition: tds.h:898
#define TDS_NULLTERM
Definition: tds.h:344
#define TDS_DBG_NETWORK
Definition: tds.h:901
#define tds_mutex_lock(x)
Definition: thread.h:421
#define tds_mutex_unlock(x)
Definition: thread.h:423
static SQLCHAR output[256]
Definition: print.c:5
static const char * str(char *buf, int n)
Definition: stats.c:84
static const char * column
Definition: stats.c:23
#define asprintf
Definition: replacements.h:54
#define strlcpy(d, s, l)
Definition: replacements.h:80
#define vasprintf
Definition: replacements.h:60
#define SYBESPID
Definition: sybdb.h:1082
#define SYBERPND
Definition: sybdb.h:947
#define SYBEBCHLEN
Definition: sybdb.h:1163
#define SYBEBPKS
Definition: sybdb.h:1121
#define SYBEALTT
Definition: sybdb.h:1057
#define DBSETCHARSET
Definition: sybdb.h:1280
#define SYBEIICL
Definition: sybdb.h:953
#define SYBEABNC
Definition: sybdb.h:960
#define SYBEAUTN
Definition: sybdb.h:990
#define DBQUOTEDIDENT
Definition: sybdb.h:435
#define SYBEBCIS
Definition: sybdb.h:1003
unsigned char DBBOOL
Definition: sybdb.h:250
#define DBOFFSET
Definition: sybdb.h:409
int BOOL
Definition: sybdb.h:150
#define SYBEBWEF
Definition: sybdb.h:1016
#define SYBEIFNB
Definition: sybdb.h:993
#define DBNOEXEC
Definition: sybdb.h:403
#define SYBMSDATE
Definition: sybdb.h:222
#define SYBEBCFO
Definition: sybdb.h:1010
#define SYBEUMSG
Definition: sybdb.h:1140
#define SYBEBRFF
Definition: sybdb.h:1028
#define SYBEMOV
Definition: sybdb.h:1123
#define SYBECRSSET
Definition: sybdb.h:1202
unsigned char DBBIT
Definition: sybdb.h:252
#define DBNUMOPTIONS
Definition: sybdb.h:437
#define SYBEUVBF
Definition: sybdb.h:1025
int STATUS
Definition: sybdb.h:148
#define SYBEASEC
Definition: sybdb.h:1019
#define SYBEEINI
Definition: sybdb.h:1110
#define SYBVOID
Definition: sybdb.h:198
#define DBTDS_7_4
Definition: sybdb.h:104
#define DBSTAT
Definition: sybdb.h:410
#define SYBINT4
Definition: sybdb.h:170
#define SYBECRSNORDER
Definition: sybdb.h:1214
#define SYBESFOV
Definition: sybdb.h:982
#define DBBOTH
Definition: sybdb.h:594
#define VARYBINBIND
Definition: sybdb.h:551
#define SYBECRSBROL
Definition: sybdb.h:1194
#define SYBECRSTAB
Definition: sybdb.h:1199
#define SYBENULP
Definition: sybdb.h:1104
#define SYBENPRM
Definition: sybdb.h:955
#define DBSETDBNAME
Definition: sybdb.h:1290
#define SYBEAAMT
Definition: sybdb.h:963
#define SYBEOOB
Definition: sybdb.h:950
#define REG_ROW
Definition: sybdb.h:580
#define SYBEMEM
Definition: sybdb.h:938
#define SYBENEG
Definition: sybdb.h:1138
#define DBCMDPEND
Definition: sybdb.h:118
Uint2 DBUSMALLINT
Definition: sybdb.h:260
#define DBDOUBLE
Definition: sybdb.h:593
#define SYBECRNC
Definition: sybdb.h:1044
#define SYBETDSVER
Definition: sybdb.h:927
#define SYBEFSHD
Definition: sybdb.h:1060
#define SYBENULL
Definition: sybdb.h:1037
#define BIGINTBIND
Definition: sybdb.h:571
#define DBTDS_7_0
Definition: sybdb.h:98
#define FLT8BIND
Definition: sybdb.h:555
#define SYBERESP
Definition: sybdb.h:1133
#define SYBEBCBPREF
Definition: sybdb.h:1164
#define SYBESYNC
Definition: sybdb.h:929
#define SYBEBCPCTYP
Definition: sybdb.h:1161
#define DBVERSION_70
Definition: sybdb.h:76
#define DBSINGLE
Definition: sybdb.h:592
RETCODE dbsetlshort(LOGINREC *login, int value, int which)
#define SYBEASNL
Definition: sybdb.h:969
#define SYBEUCPT
Definition: sybdb.h:1053
#define SYBEBADPK
Definition: sybdb.h:1129
#define SYBEBUDF
Definition: sybdb.h:1030
#define DBNATLANG
Definition: sybdb.h:418
#define MAXBINDTYPES
Definition: sybdb.h:573
#define SYBEARDL
Definition: sybdb.h:1064
#define DBSTORPROCID
Definition: sybdb.h:413
#define SYBEUDTY
Definition: sybdb.h:988
#define SYBEADST
Definition: sybdb.h:1056
#define SYBECUFL
Definition: sybdb.h:976
#define SYBEBTOK
Definition: sybdb.h:948
#define SYBEBCSET
Definition: sybdb.h:1149
#define SYBEBPRONODEF
Definition: sybdb.h:1173
#define DBTDS_4_2
Definition: sybdb.h:94
#define SYBEBCPI
Definition: sybdb.h:1004
#define SYBEUSCT
Definition: sybdb.h:986
#define SYBENTTN
Definition: sybdb.h:1021
#define SYBNUMERIC
Definition: sybdb.h:202
#define SYBEBCNT
Definition: sybdb.h:992
#define DBVERSION_71
Definition: sybdb.h:77
#define DBPRCOLSEP
Definition: sybdb.h:575
#define SYBECRSMROWS
Definition: sybdb.h:1210
#define SYBETMTD
Definition: sybdb.h:1020
#define DBNOAUTOFREE
Definition: sybdb.h:415
#define SYBENTLL
Definition: sybdb.h:970
#define SYBVARCHAR
Definition: sybdb.h:162
#define SRCNUMERICBIND
Definition: sybdb.h:565
#define SYBEUFDT
Definition: sybdb.h:957
#define SYBECRSVIIND
Definition: sybdb.h:1186
#define SYBEBCBC
Definition: sybdb.h:1009
#define TIMEBIND
Definition: sybdb.h:568
#define SYBEBDIO
Definition: sybdb.h:991
#define SYBETRAC
Definition: sybdb.h:1117
#define NUMERICBIND
Definition: sybdb.h:563
#define SYBEBNCR
Definition: sybdb.h:952
#define SYBEBPRONUMDEF
Definition: sybdb.h:1171
#define SYBERTSC
Definition: sybdb.h:1046
#define SYBEMVOR
Definition: sybdb.h:1079
#define SYBEPWD
Definition: sybdb.h:942
#define DBCHAINXACTS
Definition: sybdb.h:426
#define DATEBIND
Definition: sybdb.h:567
#define SYBEBCBNTYP
Definition: sybdb.h:1159
#define SYBEKBCO
Definition: sybdb.h:995
#define SYBEBNUM
Definition: sybdb.h:1142
#define INT_TIMEOUT
Definition: sybdb.h:63
int RETCODE
Definition: sybdb.h:121
#define SYBEBCRO
Definition: sybdb.h:1039
#define SYBEBCSA
Definition: sybdb.h:1036
#define BUF_FULL
Definition: sybdb.h:583
#define SYBECRSNOKEYS
Definition: sybdb.h:1206
#define SYBEBCWE
Definition: sybdb.h:1000
#define CHARBIND
Definition: sybdb.h:547
#define SYBETYPE
Definition: sybdb.h:1088
#define SYBEBCVH
Definition: sybdb.h:1011
#define SRCDECIMALBIND
Definition: sybdb.h:566
#define SYBEDVOR
Definition: sybdb.h:1080
#define SYBETPTN
Definition: sybdb.h:999
#define SYBEASTL
Definition: sybdb.h:1125
#define SYBEABNP
Definition: sybdb.h:962
#define SYBEIMCL
Definition: sybdb.h:1072
#define SYBTEXT
Definition: sybdb.h:182
#define SYBECRSBSKEY
Definition: sybdb.h:1196
#define SYBEPORT
Definition: sybdb.h:928
#define SYBECLPR
Definition: sybdb.h:979
#define SYBETEXS
Definition: sybdb.h:1116
#define SMALLBIND
Definition: sybdb.h:553
#define SYBETSIT
Definition: sybdb.h:989
#define SYBEBPROEXTDEF
Definition: sybdb.h:1175
#define SYBEUVDT
Definition: sybdb.h:956
#define SYBNVARCHAR
Definition: sybdb.h:212
#define DBSETPWD
Definition: sybdb.h:1258
#define SYBEIPV
Definition: sybdb.h:1122
#define SYBEBPROEXTRES
Definition: sybdb.h:1176
#define NTBSTRINGBIND
Definition: sybdb.h:549
#define SYBDATE
Definition: sybdb.h:214
#define SYBEBBL
Definition: sybdb.h:1143
#define SYBEABMT
Definition: sybdb.h:961
unsigned char BYTE
Definition: sybdb.h:334
#define DBSETHOST
Definition: sybdb.h:1252
#define SYBEWAID
Definition: sybdb.h:958
#define SYBEISOI
Definition: sybdb.h:1070
#define DBTDS_UNKNOWN
DBTDS_xxx are returned by DBTDS() The integer values of the constants are poorly chosen.
Definition: sybdb.h:90
#define SYBEBCBNPR
Definition: sybdb.h:1158
#define SYBEPRTF
Definition: sybdb.h:1119
#define NO_MORE_ROWS
Definition: sybdb.h:582
#define SYBEUFDS
Definition: sybdb.h:1052
#define SYBECRSFRAND
Definition: sybdb.h:1192
#define SYBERPUL
Definition: sybdb.h:1042
#define SYBINT8
Definition: sybdb.h:172
#define SYBECRSDIS
Definition: sybdb.h:1190
#define SYBEBUFF
Definition: sybdb.h:1075
#define SYBMONEYN
Definition: sybdb.h:208
#define SYBECDNS
Definition: sybdb.h:959
#define SYBECRSNOBIND
Definition: sybdb.h:1207
#define SYBEAICF
Definition: sybdb.h:1055
int(* DB_DBCHKINTR_FUNC)(void *dbproc)
Definition: sybdb.h:134
#define DBCMDNONE
Definition: sybdb.h:117
#define BIGTIMEBIND
Definition: sybdb.h:570
#define SYBETIME
Definition: sybdb.h:931
#define DBSETNATLANG
Definition: sybdb.h:1271
#define SYBENDC
Definition: sybdb.h:1078
#define SYBECRSUPDNB
Definition: sybdb.h:1200
#define SYBEPOLL
Definition: sybdb.h:1127
#define SYBEBCVLEN
Definition: sybdb.h:1162
#define DBPRLINESEP
Definition: sybdb.h:423
#define DBTEXTLIMIT
Definition: sybdb.h:407
#define SYBECSYN
Definition: sybdb.h:978
#define SYBECOFL
Definition: sybdb.h:977
#define SYBEONCE
Definition: sybdb.h:1135
#define SYBEINLN
Definition: sybdb.h:944
#define SYBEXTSN
Definition: sybdb.h:1086
#define DBDATEFIRST
Definition: sybdb.h:425
#define SYBEAPCT
Definition: sybdb.h:1058
#define DBAUTH
Definition: sybdb.h:429
#define SYBEBUFL
Definition: sybdb.h:933
#define SYBEDDNE
Definition: sybdb.h:975
#define SYBECAP
Definition: sybdb.h:1131
#define DBVERSION_72
Definition: sybdb.h:78
#define SYBMSDATETIME2
Definition: sybdb.h:226
#define SYBEAOLF
Definition: sybdb.h:1061
double DBFLT8
Definition: sybdb.h:259
#define SYBEBPROBADDEF
Definition: sybdb.h:1177
#define SYBNTEXT
Definition: sybdb.h:184
#define SYBECRSORD
Definition: sybdb.h:1187
#define SYBEORPF
Definition: sybdb.h:1024
#define SYBEURMI
Definition: sybdb.h:1065
#define SYBIMAGE
Definition: sybdb.h:186
#define SYBINTN
Definition: sybdb.h:164
#define SYBECRSUPDTAB
Definition: sybdb.h:1203
#define SYBECONN
Definition: sybdb.h:937
#define SYBECRSNOPTCC
Definition: sybdb.h:1213
Int2 DBSMALLINT
Definition: sybdb.h:254
#define DATETIMEBIND
Definition: sybdb.h:557
#define SYBEACNV
Definition: sybdb.h:1076
#define SYBEEVST
Definition: sybdb.h:1109
#define BIGDATETIMEBIND
Definition: sybdb.h:569
#define SYBEARDI
Definition: sybdb.h:1062
#define SYBENBVP
Definition: sybdb.h:1081
#define SYBEVERDOWN
Definition: sybdb.h:919
#define SYBERPNA
Definition: sybdb.h:1048
#define SYBEUNAM
Definition: sybdb.h:1038
#define SYBEICONVO
Definition: sybdb.h:922
#define DBFIPSFLAG
Definition: sybdb.h:427
#define SYBETRAN
Definition: sybdb.h:1108
#define SYBEIDCL
Definition: sybdb.h:1071
#define SYBMSDATETIMEOFFSET
Definition: sybdb.h:228
#define SYBEBPRODEFID
Definition: sybdb.h:1172
#define SYBECRSNOIND
Definition: sybdb.h:1184
#define SYBEREAD
Definition: sybdb.h:932
#define SYBINT1
Definition: sybdb.h:166
#define DBVER42
Definition: sybdb.h:83
#define DBSHOWPLAN
Definition: sybdb.h:402
#define SYBECRSINVALID
Definition: sybdb.h:1209
#define SYBEBCSNDROW
Definition: sybdb.h:1168
#define MONEYBIND
Definition: sybdb.h:559
#define SYBERPIL
Definition: sybdb.h:1041
#define SYBDATETIME4
Definition: sybdb.h:192
#define SYBDECIMAL
Definition: sybdb.h:204
#define INTBIND
Definition: sybdb.h:554
#define SYBENXID
Definition: sybdb.h:964
#define DBVERSION_100
Definition: sybdb.h:74
#define SYBEECAN
Definition: sybdb.h:1112
#define DBSETREADONLY
Definition: sybdb.h:1298
#define SYBEBIVI
Definition: sybdb.h:1008
#define DBSETBCP
Definition: sybdb.h:1268
#define SYBETTS
Definition: sybdb.h:994
char DBCHAR
Definition: sybdb.h:251
#define DBTXPLEN
Definition: sybdb.h:106
#define SUCCEED
Definition: sybdb.h:585
#define SYBEABNV
Definition: sybdb.h:974
#define SYBCHAR
Definition: sybdb.h:160
#define SYBEISRVPREC
Definition: sybdb.h:1152
#define SYBECRSNORES
Definition: sybdb.h:1183
#define BINARYBIND
Definition: sybdb.h:561
#define DBTDS_4_6
Definition: sybdb.h:95
#define SYBEEVOP
Definition: sybdb.h:1106
#define SYBEDPOR
Definition: sybdb.h:1077
#define DECIMALBIND
Definition: sybdb.h:564
#define SYBETPAR
Definition: sybdb.h:1115
#define SYBEBCSNTYP
Definition: sybdb.h:1160
#define SYBEOPIN
Definition: sybdb.h:943
#define DBTDS_5_0
Definition: sybdb.h:97
#define DBBUFFER
Definition: sybdb.h:414
#define SYBEBTYPSRV
Definition: sybdb.h:1148
#define SYBEDNTI
Definition: sybdb.h:1022
#define SYBEBUCF
Definition: sybdb.h:1027
#define SYBEBSCALE
Definition: sybdb.h:1145
#define DBSETTIME
Definition: sybdb.h:434
#define SYBEBCPB
Definition: sybdb.h:1006
#define SYBECRSVIEW
Definition: sybdb.h:1185
#define SYBEVDPT
Definition: sybdb.h:1007
RETCODE dbmnysub(DBPROCESS *dbproc, DBMONEY *m1, DBMONEY *m2, DBMONEY *diff)
#define DBSETENCRYPT
Definition: sybdb.h:1285
#define SYBREAL
Definition: sybdb.h:194
#define SYBECRSNOWHERE
Definition: sybdb.h:1201
#define SYBEBUCE
Definition: sybdb.h:1015
#define SYBECRSNOFREE
Definition: sybdb.h:1189
#define DBVERSION_74
Definition: sybdb.h:80
#define SYBEFCON
Definition: sybdb.h:930
#define SYBENSIP
Definition: sybdb.h:973
#define SYBERPTXTIM
Definition: sybdb.h:1137
#define SYBERPCS
Definition: sybdb.h:1114
#define SYBDATETIMN
Definition: sybdb.h:210
#define DBVER60
Definition: sybdb.h:84
#define SYBEUCRR
Definition: sybdb.h:1047
#define DBTDS_7_1
Definition: sybdb.h:101
#define DBROWCOUNT
Definition: sybdb.h:416
#define SYBETRSN
Definition: sybdb.h:1120
CI_TYPE
Definition: sybdb.h:354
@ CI_REGULAR
Definition: sybdb.h:354
@ CI_ALTERNATE
Definition: sybdb.h:354
#define SYBEUREI
Definition: sybdb.h:1068
#define SYBEBCPN
Definition: sybdb.h:1005
#define SYBBITN
Definition: sybdb.h:180
#define SYBEIDECCL
Definition: sybdb.h:1155
#define SYBEUNT
Definition: sybdb.h:983
unsigned char DBBINARY
Definition: sybdb.h:257
#define DBVERSION_73
Definition: sybdb.h:79
#define SYBECNOV
Definition: sybdb.h:980
#define SYBEOREN
Definition: sybdb.h:1069
#define SYBEOPNA
Definition: sybdb.h:1049
#define SYBECDOMAIN
Definition: sybdb.h:1146
#define SYBESMSG
Definition: sybdb.h:946
#define SYBEBPRODEFTYP
Definition: sybdb.h:1174
#define SYBECRSNOCOUNT
Definition: sybdb.h:1198
#define SMALLMONEYBIND
Definition: sybdb.h:560
#define SYBETMCF
Definition: sybdb.h:1054
#define SYBBINARY
Definition: sybdb.h:196
#define DBSETPACKET
Definition: sybdb.h:1282
#define SYBEETD
Definition: sybdb.h:1092
#define DBARITHIGNORE
Definition: sybdb.h:404
int(* EHANDLEFUNC)(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
Definition: sybdb.h:532
#define SYBEURCI
Definition: sybdb.h:1063
#define DBVERSION_42
Definition: sybdb.h:75
#define SYBEBCUC
Definition: sybdb.h:1013
Int8 DBBIGINT
Definition: sybdb.h:256
#define DBNOCOUNT
Definition: sybdb.h:405
#define SMALLDATETIMEBIND
Definition: sybdb.h:558
#define SYBECRSINV
Definition: sybdb.h:1205
#define SYBERTCC
Definition: sybdb.h:1045
#define SYBEBCITBNM
Definition: sybdb.h:1166
#define SYBEBTYP
Definition: sybdb.h:951
#define SYBECRSVAR
Definition: sybdb.h:1217
#define SYBEBTMT
Definition: sybdb.h:1023
#define DBISOLATION
Definition: sybdb.h:428
#define SYBEBCPREC
Definition: sybdb.h:1157
#define DBSETUSER
Definition: sybdb.h:1255
#define SYBEXTDN
Definition: sybdb.h:1085
#define SYBEZTXT
Definition: sybdb.h:1097
#define SYBEICONV2BIG
Definition: sybdb.h:924
#define SYBEBCRE
Definition: sybdb.h:998
#define SYBECRSNOTABLE
Definition: sybdb.h:1215
#define DBTEXTSIZE
Definition: sybdb.h:417
#define SYBEITIM
Definition: sybdb.h:949
#define SYBEBCIT
Definition: sybdb.h:1035
#define SYBEWRIT
Definition: sybdb.h:934
#define REALBIND
Definition: sybdb.h:556
#define DBCLIENTCURSORS
Definition: sybdb.h:433
#define SYBEURES
Definition: sybdb.h:1067
#define SYBEUTDS
Definition: sybdb.h:1074
#define DBSETUTF16
Definition: sybdb.h:1294
#define VARYCHARBIND
Definition: sybdb.h:550
#define SYBEBEOF
Definition: sybdb.h:1032
#define DBPRLINELEN
Definition: sybdb.h:576
#define SYBTIME
Definition: sybdb.h:216
unsigned char DBTINYINT
Definition: sybdb.h:253
#define DBPRPAD
Definition: sybdb.h:420
#define SYBENMOB
Definition: sybdb.h:967
#define SYBEDIVZ
Definition: sybdb.h:1124
#define SYBECRSAGR
Definition: sybdb.h:1191
#define SYBEXTN
Definition: sybdb.h:1084
#define FAIL
Definition: sybdb.h:586
#define SYBERXID
Definition: sybdb.h:965
#define SYBESEFA
Definition: sybdb.h:1126
#define SYBENBUF
Definition: sybdb.h:1103
#define SYBECWLL
Definition: sybdb.h:1051
float DBREAL
Definition: sybdb.h:258
#define SYBEMPLL
Definition: sybdb.h:1040
#define SYBEIFCL
Definition: sybdb.h:1073
#define SYBEBCNN
Definition: sybdb.h:1001
#define SYBESECURE
Definition: sybdb.h:1130
#define SYBECINTERNAL
Definition: sybdb.h:1147
#define SYBECLOS
Definition: sybdb.h:984
#define BITBIND
Definition: sybdb.h:562
#define SYBEICN
Definition: sybdb.h:966
#define SYBECRSBUFR
Definition: sybdb.h:1188
#define SYBEBIHC
Definition: sybdb.h:1031
#define SYBEFRES
Definition: sybdb.h:1151
#define SYBEEUNR
Definition: sybdb.h:1113
#define SYBMSTIME
Definition: sybdb.h:224
#define SYBECRSNUNIQUE
Definition: sybdb.h:1216
#define SYBDATETIME
Definition: sybdb.h:176
#define SYBEICONVI
Definition: sybdb.h:923
#define INT_CONTINUE
Definition: sybdb.h:61
#define SYBVARBINARY
Definition: sybdb.h:200
#define SYBEBPRODEF
Definition: sybdb.h:1170
#define SYBERPNULL
Definition: sybdb.h:1136
#define SYBECRSNROWS
Definition: sybdb.h:1211
#define SYBEIVERS
Definition: sybdb.h:1134
#define SYBESOCK
Definition: sybdb.h:936
#define SYBMONEY
Definition: sybdb.h:190
#define SYBEINTF
Definition: sybdb.h:940
#define SYBMONEY4
Definition: sybdb.h:188
#define SYBEASUL
Definition: sybdb.h:971
#define STRINGBIND
Definition: sybdb.h:548
int(* DB_DBHNDLINTR_FUNC)(void *dbproc)
Definition: sybdb.h:135
#define DBVERSION_UNKNOWN
DBVERSION_xxx are used with dbsetversion()
Definition: sybdb.h:72
#define SYBENOEV
Definition: sybdb.h:1128
int(* MHANDLEFUNC)(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *proc, int line)
Definition: sybdb.h:534
#define SYBENDTP
Definition: sybdb.h:1083
#define SYBFLT8
Definition: sybdb.h:174
#define SYBEBPREC
Definition: sybdb.h:1144
#define SYBEBCMTXT
Definition: sybdb.h:1156
#define SYBECOLSIZE
Definition: sybdb.h:1229
#define SYBEBBCI
Definition: sybdb.h:996
#define SYBEBCNL
Definition: sybdb.h:1033
#define SYBEDBPS
Definition: sybdb.h:939
#define SYBEICONVAVAIL
Definition: sybdb.h:921
#define SYBEINUMCL
Definition: sybdb.h:1154
#define DBPARSEONLY
Definition: sybdb.h:400
#define DBCMDSENT
Definition: sybdb.h:119
#define DATETIME2BIND
Definition: sybdb.h:572
#define SYBEBUOF
Definition: sybdb.h:1026
#define SYBEUHST
Definition: sybdb.h:941
#define SYBESEOF
Definition: sybdb.h:945
#define SYBENHAN
Definition: sybdb.h:1102
#define SYBERDNR
Definition: sybdb.h:972
#define SYBFLTN
Definition: sybdb.h:206
#define DBSETNTLMV2
Definition: sybdb.h:1296
#define SYBECRSFTYPE
Definition: sybdb.h:1208
#define SYBEXOCI
Definition: sybdb.h:1059
#define SYBECNOR
Definition: sybdb.h:954
Int4 DBINT
Definition: sybdb.h:255
#define DBARITHABORT
Definition: sybdb.h:406
#define SYBEBCOR
Definition: sybdb.h:1002
#define DBVERSION_46
Definition: sybdb.h:73
#define SYBEBWFF
Definition: sybdb.h:1029
#define SYBECRSFROWN
Definition: sybdb.h:1195
#define SYBETRAS
Definition: sybdb.h:1118
#define DBDATEFORMAT
Definition: sybdb.h:419
#define SYBEBCUO
Definition: sybdb.h:1012
#define DBSETLABELED
Definition: sybdb.h:1287
#define SYBEBCSI
Definition: sybdb.h:1034
#define SYBEUNOP
Definition: sybdb.h:1043
#define TINYBIND
Definition: sybdb.h:552
#define SYBERDCN
Definition: sybdb.h:981
#define INT_CANCEL
Definition: sybdb.h:62
#define SYBEISRVSCL
Definition: sybdb.h:1153
#define SYBEKBCI
Definition: sybdb.h:997
RETCODE dbsetdefcharset(char *charset)
#define SYBECAPTYP
Definition: sybdb.h:1141
#define SYBEFUNC
Definition: sybdb.h:1132
#define SYBEAPUT
Definition: sybdb.h:968
#define NO_MORE_RESULTS
Definition: sybdb.h:584
#define SYBEICONVIU
Definition: sybdb.h:920
#define SYBEBCPREF
Definition: sybdb.h:1165
#define SYBEBUOE
Definition: sybdb.h:1014
#define SYBEBCITBLEN
Definition: sybdb.h:1167
#define DBTDS_7_2
Definition: sybdb.h:102
#define SYBEUREM
Definition: sybdb.h:1066
#define DBTDS_7_3
Definition: sybdb.h:103
#define DBSETAPP
Definition: sybdb.h:1265
#define SYBINT2
Definition: sybdb.h:168
#define SYBECRSRO
Definition: sybdb.h:1197
#define INT_EXIT
Definition: sybdb.h:60
#define SYBECRSNOLEN
Definition: sybdb.h:1212
#define SYBECRSNOUPD
Definition: sybdb.h:1204
#define SYBECRSFLAST
Definition: sybdb.h:1193
#define SYBBIT
Definition: sybdb.h:178
#define SYBEBPROCOL
Definition: sybdb.h:1169
#define EXCONSISTENCY
Definition: syberror.h:45
#define EXNONFATAL
Definition: syberror.h:37
#define EXINFO
Definition: syberror.h:35
#define EXCONVERSION
Definition: syberror.h:38
#define EXFATAL
Definition: syberror.h:44
#define EXCOMM
Definition: syberror.h:43
#define EXTIME
Definition: syberror.h:40
#define EXPROGRAM
Definition: syberror.h:41
#define EXSERVER
Definition: syberror.h:39
#define EXUSER
Definition: syberror.h:36
#define EXRESOURCE
Definition: syberror.h:42
#define option
static TDSSOCKET * tds
Definition: collations.c:37
static TDSLOGIN * login
Definition: dataread.c:31
#define _dblib_handle_info_message
#define _dblib_check_and_handle_interrupt
#define dbrows_pivoted
#define _dblib_handle_err_message
#define dbnextrow_pivoted
#define tds_fix_login
#define tds_send_cancel
#define tds_set_version
#define tds_read_config_info
#define tds_free_login
#define tds_writetext_end
#define tds_set_app
#define tds_set_user
#define tds_close_socket
#define tds_alloc_login
#define STD_DATETIME_FMT
#define tds_set_bulk
#define tds_get_size_by_type
#define tds_strftime
#define tds_writetext_continue
#define tds_prtype
#define tds_connect_and_login
#define tds_quote_id
#define tds_set_interfaces_file_loc
#define tdsdump_open
#define tds_get_column_declaration
#define tds_flush_packet
#define tds_free_bcpinfo
#define tds_set_language
#define tds_submit_query
#define tds_set_host
#define tds_alloc_context
#define tds_vstrbuild
#define tds_free_socket
#define tds_alloc_socket
#define tds_datecrack
#define tds_process_cancel
#define tds_set_server
#define tds_set_passwd
#define tds_set_client_charset
#define tds_willconvert
#define tds_get_conversion_type
#define tds_set_packet
#define tds_free_context
#define tds_convert
#define tds_writetext_start
#define tds_set_library
#define tds_process_tokens
static tds_mutex dblib_mutex
Definition: dblib.c:193
#define TDS_MUTEX_INITIALIZER
Definition: thread.h:335
#define tds_mutex
Definition: thread.h:336
char data[12]
Definition: iconv.c:80
#define _dblib_convert_err
#define NULL
Definition: ncbistd.hpp:225
void dbclrbuf(DBPROCESS *dbproc, DBINT n)
Clear n rows from the row buffer.
Definition: dblib.c:2855
LOGINREC * dblogin(void)
Allocate a LOGINREC structure.
Definition: dblib.c:719
DBTYPEINFO * dbcoltypeinfo(DBPROCESS *dbproc, int column)
Get precision and scale information for a regular result column.
Definition: dblib.c:2956
void dbfreebuf(DBPROCESS *dbproc)
Erase the command buffer, in case DBNOAUTOFREE was set with dbsetopt().
Definition: dblib.c:5973
BYTE * dbdata(DBPROCESS *dbproc, int column)
Get address of data in a regular result column.
Definition: dblib.c:3237
int dbstrlen(DBPROCESS *dbproc)
Get size of the command buffer, in bytes.
Definition: dblib.c:6206
BYTE * dbadata(DBPROCESS *dbproc, int computeid, int column)
Get address of compute column data.
Definition: dblib.c:4325
int dbspid(DBPROCESS *dbproc)
Get server process ID for a DBPROCESS.
Definition: dblib.c:5829
DBBINARY * dbtxtimestamp(DBPROCESS *dbproc, int column)
Get text timestamp for a column in the current row.
Definition: dblib.c:6442
BYTE * dbbylist(DBPROCESS *dbproc, int computeid, int *size)
Get bylist for a compute row.
Definition: dblib.c:4908
#define DBDEAD(x)
Sybase macro mapping to the Microsoft (lower-case) function.
Definition: sybdb.h:762
char * dbservcharset(DBPROCESS *dbproc)
Get syscharset name of the server character set.
Definition: dblib.c:6945
DBINT dbspr1rowlen(DBPROCESS *dbproc)
Determine size buffer required to hold the results returned by dbsprhead(), dbsprline(),...
Definition: dblib.c:3304
DBINT dbconvert(DBPROCESS *dbproc, int srctype, const BYTE *src, DBINT srclen, int desttype, BYTE *dest, DBINT destlen)
cf.
Definition: dblib.c:2604
DBINT dbadlen(DBPROCESS *dbproc, int computeid, int column)
Get size of data in a compute column.
Definition: dblib.c:4209
void dbsetinterrupt(DBPROCESS *dbproc, DB_DBCHKINTR_FUNC chkintr, DB_DBHNDLINTR_FUNC hndlintr)
Set interrupt handler for db-lib to use while blocked against a read from the server.
Definition: dblib.c:4539
RETCODE dbsetnull(DBPROCESS *dbproc, int bindtype, int bindlen, BYTE *bindval)
Define substitution values to be used when binding null values.
Definition: dblib.c:1964
char * dbcolname(DBPROCESS *dbproc, int column)
Return name of a regular result column.
Definition: dblib.c:1884
RETCODE dbfcmd(DBPROCESS *dbproc, const char *fmt,...)
printf-like way to form SQL to send to the server.
Definition: dblib.c:1338
RETCODE dbdatecrack(DBPROCESS *dbproc, DBDATEREC *di, DBDATETIME *datetime)
Break a DBDATETIME value into useful pieces.
Definition: dblib.c:5756
RETCODE dbresults(DBPROCESS *dbproc)
Set up query results.
Definition: dblib.c:1706
RETCODE dbwritetext(DBPROCESS *dbproc, char *objname, DBBINARY *textptr, DBTINYINT textptrlen, DBBINARY *timestamp, DBBOOL log, DBINT size, BYTE *text)
Send text or image data to the server.
Definition: dblib.c:6509
RETCODE dbcanquery(DBPROCESS *dbproc)
Cancel the query currently being retrieved, discarding all pending rows.
Definition: dblib.c:5941
RETCODE dbinit(void)
Initialize db-lib.
Definition: dblib.c:674
DBINT dbvarylen(DBPROCESS *dbproc, int column)
Determine whether a column can vary in size.
Definition: dblib.c:3158
RETCODE dbcancel(DBPROCESS *dbproc)
Cancel the current command batch.
Definition: dblib.c:3279
RETCODE dbsetlogintime(int seconds)
Set maximum seconds db-lib waits for a server response to a login attempt.
Definition: dblib.c:4137
RETCODE dbgetrow(DBPROCESS *dbproc, DBINT row)
Read a row from the row buffer.
Definition: dblib.c:1932
int dbcoltype(DBPROCESS *dbproc, int column)
Get the datatype of a regular result set column.
Definition: dblib.c:2902
void dbsetifile(char *filename)
set name and location of the interfaces file FreeTDS should use to look up a servername.
Definition: dblib.c:2722
const char * dbversion()
See which version of db-lib is in use.
Definition: dblib.c:6762
RETCODE dbuse(DBPROCESS *dbproc, const char *name)
Change current database.
Definition: dblib.c:1449
int dbnumalts(DBPROCESS *dbproc, int computeid)
Get count of columns in a compute row.
Definition: dblib.c:4849
BOOL dbiscount(DBPROCESS *dbproc)
Indicates whether or not the count returned by dbcount is real (Microsoft-compatibility feature).
Definition: dblib.c:2815
int dbgettime(void)
Get maximum seconds db-lib waits for a server response to query.
Definition: dblib.c:4121
RETCODE dbmoretext(DBPROCESS *dbproc, DBINT size, const BYTE text[])
Send chunk of a text/image value to the server.
Definition: dblib.c:6654
const char * dbprtype(int token)
Print a token value's name to a buffer.
Definition: dblib.c:6363
char * dbcolsource(DBPROCESS *dbproc, int column)
Get base database column name for a result set column.
Definition: dblib.c:3084
char * dbchange(DBPROCESS *dbproc)
See if a command caused the current database to change.
Definition: dblib.c:6909
RETCODE dbnullbind(DBPROCESS *dbproc, int column, DBINT *indicator)
Tie a null-indicator to a regular result column.
Definition: dblib.c:2751
RETCODE dbbind(DBPROCESS *dbproc, int column, int vartype, DBINT varlen, BYTE *varaddr)
Tie a host variable to a resultset column.
Definition: dblib.c:2645
RETCODE dbcmd(DBPROCESS *dbproc, const char cmdstring[])
Append SQL to the command buffer.
Definition: dblib.c:1377
DBINT dbcollen(DBPROCESS *dbproc, int column)
Get size of a regular result column.
Definition: dblib.c:3109
DBINT dbconvert_ps(DBPROCESS *dbproc, int db_srctype, const BYTE *src, DBINT srclen, int db_desttype, BYTE *dest, DBINT destlen, DBTYPEINFO *typeinfo)
Convert one datatype to another.
Definition: dblib.c:2303
char * dbgetchar(DBPROCESS *dbproc, int pos)
Get address of a position in the command buffer.
Definition: dblib.c:6225
RETCODE dbanullbind(DBPROCESS *dbproc, int computeid, int column, DBINT *indicator)
Tie a null-indicator to a compute result column.
Definition: dblib.c:2787
RETCODE dbclropt(DBPROCESS *dbproc, int option, const char param[])
Reset an option.
Definition: dblib.c:6008
DBINT dbcount(DBPROCESS *dbproc)
Get count of rows processed.
Definition: dblib.c:2835
int dbaltop(DBPROCESS *dbproc, int computeid, int column)
Get aggregation operator for a compute column.
Definition: dblib.c:4355
RETCODE dbtablecolinfo(DBPROCESS *dbproc, DBINT column, DBCOL *pdbcol)
describe table column attributes with a single call (Freetds-only API function modelled on dbcolinfo)
Definition: dblib.c:6380
DBINT dbaltlen(DBPROCESS *dbproc, int computeid, int column)
Get size of data in compute column.
Definition: dblib.c:7060
RETCODE dbsetopt(DBPROCESS *dbproc, int option, const char *char_param, int int_param)
Set db-lib or server option.
Definition: dblib.c:4383
void dbprhead(DBPROCESS *dbproc)
Print result set headings to stdout.
Definition: dblib.c:3854
RETCODE dbsetlversion(LOGINREC *login, BYTE version)
Set TDS version for future connections.
Definition: dblib.c:945
RETCODE dbprrow(DBPROCESS *dbproc)
Print a result set to stdout.
Definition: dblib.c:3425
char * dbname(DBPROCESS *dbproc)
Get name of current database.
Definition: dblib.c:6929
int dbalttype(DBPROCESS *dbproc, int computeid, int column)
Get datatype for a compute column.
Definition: dblib.c:4240
RETCODE dbsprhead(DBPROCESS *dbproc, char *buffer, DBINT buf_len)
Print result set headings to a buffer.
Definition: dblib.c:3789
RETCODE dbsqlexec(DBPROCESS *dbproc)
send the SQL command to the server and wait for an answer.
Definition: dblib.c:1423
DBBOOL dbwillconvert(int srctype, int desttype)
Test whether or not a datatype can be converted to another datatype.
Definition: dblib.c:2885
int dbcolutype(DBPROCESS *dbproc, int column)
Get user-defined datatype of a regular result column.
Definition: dblib.c:2933
RETCODE dbstrbuild(DBPROCESS *dbproc, char *charbuf, int bufsize, char *text, char *formats,...)
Build a printable string from text containing placeholders for variables.
Definition: dblib.c:7223
EHANDLEFUNC dberrhandle(EHANDLEFUNC handler)
Set an error handler, for messages from db-lib.
Definition: dblib.c:5030
RETCODE dbsetversion(DBINT version)
Specify a db-lib version level.
Definition: dblib.c:5885
int dbgetpacket(DBPROCESS *dbproc)
Get TDS packet size for the connection.
Definition: dblib.c:3970
void dbrecftos(const char filename[])
Record to a file all SQL commands sent to the server.
Definition: dblib.c:6689
BYTE * dbgetuserdata(DBPROCESS *dbproc)
Get address of user-allocated data from a DBPROCESS.
Definition: dblib.c:5867
void dbsetuserdata(DBPROCESS *dbproc, BYTE *ptr)
Associate client-allocated (and defined) data with a DBPROCESS.
Definition: dblib.c:5849
DBINT dbprcollen(DBPROCESS *dbproc, int column)
Get size of a result column needed to print column.
Definition: dblib.c:3132
void dbloginfree(LOGINREC *login)
free the LOGINREC
Definition: dblib.c:751
RETCODE dbmorecmds(DBPROCESS *dbproc)
See if more commands are to be processed.
Definition: dblib.c:6150
DBBOOL dbisopt(DBPROCESS *dbproc, int option, const char param[])
Get value of an option.
Definition: dblib.c:6076
int dbnumcompute(DBPROCESS *dbproc)
Get count of COMPUTE clauses for a result set.
Definition: dblib.c:4882
RETCODE dbsqlsend(DBPROCESS *dbproc)
Transmit the command buffer to the server.
Definition: dblib.c:6965
RETCODE dbsprline(DBPROCESS *dbproc, char *buffer, DBINT buf_len, DBCHAR line_char)
Get formatted string for underlining dbsprhead() column names.
Definition: dblib.c:3731
void dbexit()
Close server connections and free all related structures.
Definition: dblib.c:1559
RETCODE dbsafestr(DBPROCESS *dbproc, const char *src, DBINT srclen, char *dest, DBINT destlen, int quotetype)
safely quotes character values in SQL text.
Definition: dblib.c:6302
int dbaltcolid(DBPROCESS *dbproc, int computeid, int column)
Get column ID of a compute column.
Definition: dblib.c:4182
RETCODE dbanydatecrack(DBPROCESS *dbproc, DBDATEREC2 *di, int type, const void *data)
Break any kind of date or time value into useful pieces.
Definition: dblib.c:5777
RETCODE dbsettime(int seconds)
Set maximum seconds db-lib waits for a server response to query.
Definition: dblib.c:4090
int dbnumcols(DBPROCESS *dbproc)
Return number of regular columns in a result set.
Definition: dblib.c:1860
int dbgetmaxprocs(void)
get maximum simultaneous connections db-lib will open to the server.
Definition: dblib.c:4069
DBBINARY * dbtxptr(DBPROCESS *dbproc, int column)
Get text pointer for a column in the current row.
Definition: dblib.c:6472
MHANDLEFUNC dbmsghandle(MHANDLEFUNC handler)
Set a message handler, for messages from the server.
Definition: dblib.c:5049
STATUS dbreadtext(DBPROCESS *dbproc, void *buf, DBINT bufsize)
Fetch part of a text or image value from the server.
Definition: dblib.c:6585
RETCODE dbsqlok(DBPROCESS *dbproc)
Wait for results of a query from the server.
Definition: dblib.c:4722
DBINT dbdatlen(DBPROCESS *dbproc, int column)
Get size of current row's data in a regular result column.
Definition: dblib.c:3209
STATUS dbsetrow(DBPROCESS *dbproc, DBINT row)
Make a buffered row "current" without fetching it into bound variables.
Definition: dblib.c:2047
void dbclose(DBPROCESS *dbproc)
Close a connection to the server and free associated resources.
Definition: dblib.c:1492
RETCODE dbstrcpy(DBPROCESS *dbproc, int start, int numbytes, char *dest)
Get a copy of a chunk of the command buffer.
Definition: dblib.c:6258
static RETCODE _dbresults(DBPROCESS *dbproc)
Definition: dblib.c:1716
DBINT dbaltutype(DBPROCESS *dbproc, int computeid, int column)
Get user-defined datatype of a compute column.
Definition: dblib.c:7036
RETCODE dbsetmaxprocs(int maxprocs)
Set maximum simultaneous connections db-lib will open to the server.
Definition: dblib.c:3994
DBINT dbfirstrow(DBPROCESS *dbproc)
See if a server response has arrived.
Definition: dblib.c:7115
RETCODE dbspr1row(DBPROCESS *dbproc, char *buffer, DBINT buf_len)
Print a regular result row to a buffer.
Definition: dblib.c:3342
RETCODE dbaltbind(DBPROCESS *dbproc, int computeid, int column, int vartype, DBINT varlen, BYTE *varaddr)
Bind a compute column to a program variable.
Definition: dblib.c:4278
int dbdatecmp(DBPROCESS *dbproc, DBDATETIME *d1, DBDATETIME *d2)
Compare DBDATETIME values, similar to strcmp(3).
Definition: dblib.c:5674
const char * dbmonthname(DBPROCESS *dbproc, char *language, int monthnum, DBBOOL shortform)
Get name of a month, in some human language.
Definition: dblib.c:6880
RETCODE dbmny4zero(DBPROCESS *dbproc, DBMONEY4 *dest)
Zero a DBMONEY4 value.
Definition: dblib.c:5479
RETCODE dbmny4add(DBPROCESS *dbproc, DBMONEY4 *m1, DBMONEY4 *m2, DBMONEY4 *sum)
Add two DBMONEY4 values.
Definition: dblib.c:5502
int dbmny4cmp(DBPROCESS *dbproc, DBMONEY4 *m1, DBMONEY4 *m2)
Compare two DBMONEY4 values.
Definition: dblib.c:5621
RETCODE dbmnymaxpos(DBPROCESS *dbproc, DBMONEY *amount)
Get maximum positive DBMONEY value supported.
Definition: dblib.c:5254
RETCODE dbmny4minus(DBPROCESS *dbproc, DBMONEY4 *src, DBMONEY4 *dest)
Negate a DBMONEY4 value.
Definition: dblib.c:5455
RETCODE dbmnyminus(DBPROCESS *dbproc, DBMONEY *src, DBMONEY *dest)
Negate a DBMONEY value.
Definition: dblib.c:5428
RETCODE dbmny4sub(DBPROCESS *dbproc, DBMONEY4 *m1, DBMONEY4 *m2, DBMONEY4 *diff)
Subtract two DBMONEY4 values.
Definition: dblib.c:5533
RETCODE dbmnyzero(DBPROCESS *dbproc, DBMONEY *dest)
Set a DBMONEY value to zero.
Definition: dblib.c:5233
RETCODE dbmnycopy(DBPROCESS *dbproc, DBMONEY *src, DBMONEY *dest)
Copy a DBMONEY value.
Definition: dblib.c:5920
RETCODE dbmny4copy(DBPROCESS *dbproc, DBMONEY4 *src, DBMONEY4 *dest)
Copy a DBMONEY4 value.
Definition: dblib.c:5649
RETCODE dbmnymaxneg(DBPROCESS *dbproc, DBMONEY *amount)
Get maximum negative DBMONEY value supported.
Definition: dblib.c:5275
RETCODE dbmnydec(DBPROCESS *dbproc, DBMONEY *amount)
Subtract $0.0001 from a DBMONEY value.
Definition: dblib.c:5400
RETCODE dbmnyinc(DBPROCESS *dbproc, DBMONEY *amount)
Add $0.0001 to a DBMONEY value.
Definition: dblib.c:5372
int dbmnycmp(DBPROCESS *dbproc, DBMONEY *m1, DBMONEY *m2)
Compare two DBMONEY values.
Definition: dblib.c:5175
DBINT dbretstatus(DBPROCESS *dbproc)
Fetch status value returned by query or remote procedure call.
Definition: dblib.c:4582
BYTE * dbretdata(DBPROCESS *dbproc, int retnum)
Get value of an output parameter filled by a stored procedure.
Definition: dblib.c:4661
char * dbretname(DBPROCESS *dbproc, int retnum)
Get name of an output parameter filled by a stored procedure.
Definition: dblib.c:4632
DBBOOL dbhasretstat(DBPROCESS *dbproc)
Determine if query generated a return status number.
Definition: dblib.c:4558
int dbrettype(DBPROCESS *dbproc, int retnum)
Get datatype of a stored procedure's return parameter.
Definition: dblib.c:6181
int dbretlen(DBPROCESS *dbproc, int retnum)
Get size of an output parameter filled by a stored procedure.
Definition: dblib.c:4687
int dbnumrets(DBPROCESS *dbproc)
Get count of output parameters filled by a stored procedure.
Definition: dblib.c:4600
static const char * tds_dstr_cstr(DSTR *s)
Returns a C version (NUL terminated string) of dstr.
Definition: string.h:66
static char * tds_dstr_buf(DSTR *s)
Returns a buffer to edit the string.
Definition: string.h:59
DSTR * tds_dstr_copy(DSTR *s, const char *src) TDS_WUR
copy a string from another
Definition: tdsstring.c:123
static int tds_dstr_isempty(DSTR *s)
test if string is empty
Definition: string.h:48
static size_t tds_dstr_len(DSTR *s)
Returns the length of the string in bytes.
Definition: string.h:73
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
#define TDS_VERSION_NO
Definition: version.h:25
exit(2)
char * buf
int i
if(yy_accept[yy_current_state])
yy_size_t n
int len
static CS_INT result_len
Definition: long_binary.c:21
static void text(MDB_val *v)
Definition: mdb_dump.c:62
static MDB_envinfo info
Definition: mdb_load.c:37
static int version
Definition: mdb_load.c:29
constexpr bool empty(list< Ts... >) noexcept
const struct ncbi::grid::netcache::search::fields::SIZE size
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
#define strdup
Definition: ncbi_ansi_ext.h:70
#define TRUE
bool replacment for C indicating true.
Definition: ncbi_std.h:97
#define FALSE
bool replacment for C indicating false.
Definition: ncbi_std.h:101
int ssize_t
Definition: ncbiconf_msvc.h:93
T negative(T x_)
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
double f(double x_, const double &y_)
Definition: njn_root.hpp:188
static int bufsize
Definition: pcregrep.c:162
char * strerror(int n)
Definition: pcregrep.c:835
static pcre_uint8 * buffer
Definition: pcretest.c:1051
#define assert(x)
Definition: srv_diag.hpp:58
#define row(bind, expected)
Definition: string_bind.c:73
BYTE * terminator
Definition: dblib.h:65
BCP_HOSTCOLINFO ** host_columns
Definition: dblib.h:77
TDS_CHAR * hostfile
Definition: dblib.h:73
TDS_CHAR * errorfile
Definition: dblib.h:74
TDS_INT host_colcount
Definition: dblib.h:76
Definition: sybdb.h:376
SHORT ServerType
Definition: sybdb.h:391
DBCHAR ServerTypeDeclaration[256]
Definition: sybdb.h:393
DBINT ServerMaxLength
Definition: sybdb.h:392
Definition: sybdb.h:357
BYTE Scale
Definition: sybdb.h:366
DBINT UserType
Definition: sybdb.h:363
DBCHAR TableName[MAXCOLNAMELEN+2]
Definition: sybdb.h:361
BYTE Null
Definition: sybdb.h:368
DBCHAR ActualName[MAXCOLNAMELEN+2]
Definition: sybdb.h:360
BYTE Precision
Definition: sybdb.h:365
DBCHAR Name[MAXCOLNAMELEN+2]
Definition: sybdb.h:359
BOOL Identity
Definition: sybdb.h:371
DBINT MaxLength
Definition: sybdb.h:364
BYTE Updatable
Definition: sybdb.h:370
SHORT Type
Definition: sybdb.h:362
BOOL VarLength
Definition: sybdb.h:367
DBINT SizeOfStruct
Definition: sybdb.h:358
DBINT dtdays
Definition: sybdb.h:298
DBINT dttime
Definition: sybdb.h:299
DBINT mny4
Definition: sybdb.h:293
Definition: sybdb.h:286
DBUINT mnylow
Definition: sybdb.h:288
DBINT mnyhigh
Definition: sybdb.h:287
unsigned char scale
Definition: sybdb.h:279
unsigned char precision
Definition: sybdb.h:278
int tail
Definition: dblib.h:55
int head
Definition: dblib.h:54
int current
Definition: dblib.h:56
int capacity
Definition: dblib.h:57
Definition: dblib.h:117
const BYTE * bindval
Definition: dblib.h:118
unsigned int len
Definition: dblib.h:119
this structure is not directed connected to a TDS protocol but keeps any DATE/TIME information.
Definition: tds.h:167
const char * msgtext
Definition: dblib.c:7651
static string query
int login_timeout
not used unless positive
Definition: dblib.c:187
int ref_count
reference count, time dbinit called
Definition: dblib.c:174
int recftos_filenum
Definition: dblib.c:186
TDSCONTEXT * tds_ctx
libTDS context
Definition: dblib.c:177
char * recftos_filename
Definition: dblib.c:185
int query_timeout
not used unless positive
Definition: dblib.c:188
TDSSOCKET ** connection_list
Definition: dblib.c:182
int connection_list_size_represented
Definition: dblib.c:184
int connection_list_size
Definition: dblib.c:183
int tds_ctx_ref_count
libTDS context reference counter
Definition: dblib.c:179
const char * text
Definition: dblib.h:109
DBSTRING * param
Definition: dblib.h:110
DBBOOL factive
Definition: dblib.h:111
DBINT strtotlen
Definition: sybdb.h:346
BYTE * strtext
Definition: sybdb.h:345
struct dbstring * strnext
Definition: sybdb.h:347
DBINT precision
Definition: sybdb.h:339
DBINT scale
Definition: sybdb.h:340
STATUS status
Definition: dbpivot.c:778
Information about blobs (e.g.
Definition: tds.h:658
unsigned char valid_ptr
Definition: tds.h:662
TDS_CHAR textptr[16]
Definition: tds.h:660
TDS_CHAR timestamp[8]
Definition: tds.h:661
Metadata about columns in regular and compute rows.
Definition: tds.h:761
TDS_TINYINT column_operator
Definition: tds.h:806
TDS_INT column_textpos
Definition: tds.h:821
TDS_INT column_size
maximun size of data.
Definition: tds.h:766
TDS_SMALLINT column_operand
Definition: tds.h:807
TDS_SMALLINT * column_nullbind
Definition: tds.h:818
DSTR column_name
Definition: tds.h:787
TDS_UINT column_bindlen
Definition: tds.h:817
TDS_SMALLINT column_bindtype
Definition: tds.h:815
unsigned int column_writeable
Definition: tds.h:796
DSTR table_column_name
Definition: tds.h:788
TDS_TINYINT column_prec
precision for decimal/numeric
Definition: tds.h:775
TDS_SERVER_TYPE column_type
This type can be different from wire type because conversion (e.g.
Definition: tds.h:768
unsigned int column_identity
Definition: tds.h:797
DSTR table_name
Definition: tds.h:786
unsigned int column_nullable
Definition: tds.h:795
TDS_TINYINT column_scale
scale for decimal/numeric
Definition: tds.h:776
unsigned char * column_data
Definition: tds.h:793
struct tds_column::@124 on_server
TDS_CHAR * column_varaddr
Definition: tds.h:819
TDS_INT column_cur_size
size written in variable (ie: char, text, binary).
Definition: tds.h:811
TDS_INT column_usertype
Definition: tds.h:763
TDSENV env
environment is shared between all sessions
Definition: tds.h:1147
int spid
Definition: tds.h:1192
TDS_USMALLINT tds_version
Definition: tds.h:1138
TDSLOCALE * locale
Definition: tds.h:1099
int(* msg_handler)(const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *)
Definition: tds.h:1102
int(* err_handler)(const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *)
Definition: tds.h:1103
int(* int_handler)(void *)
Definition: tds.h:1104
NULLREP nullreps[MAXBINDTYPES]
default null values
Definition: dblib.h:157
TDSBCPINFO * bcpinfo
Definition: dblib.h:142
char dbcurdb[DBMAXNAME+1]
Definition: dblib.h:145
TDS_INT text_size
Definition: dblib.h:135
STATUS row_type
Definition: dblib.h:124
DBSTRING * dboptcmd
Definition: dblib.h:140
DBPROC_ROWBUF row_buf
Definition: dblib.h:125
BCP_HOSTFILEINFO * hostfileinfo
Definition: dblib.h:141
DBTYPEINFO typeinfo
Definition: dblib.h:137
DB_DBCHKINTR_FUNC chkintr
Definition: dblib.h:148
TDSSOCKET * tds_socket
Definition: dblib.h:122
DB_DBHNDLINTR_FUNC hndlintr
Definition: dblib.h:149
char servcharset[DBMAXNAME+1]
Definition: dblib.h:146
unsigned char * dbbuf
Definition: dblib.h:132
DB_RESULT_STATE dbresults_state
Definition: dblib.h:129
DBUSMALLINT envchange_rcv
Definition: dblib.h:144
TDS_INT text_sent
Definition: dblib.h:136
BYTE * user_data
Definition: dblib.h:131
int msdblib
boolean use ms behaviour
Definition: dblib.h:152
unsigned char avail_flag
Definition: dblib.h:138
DBOPTION * dbopts
Definition: dblib.h:139
TDSLOGIN * tds_login
Definition: dblib.h:44
Structure to hold a string.
Definition: tds.h:116
int block_size
packet size (512-65535)
Definition: tds.h:1035
char * date_fmt
Definition: tds.h:650
Definition: tds.h:584
unsigned int use_ntlmv2
Definition: tds.h:628
TDS_INT query_timeout
Definition: tds.h:608
DSTR database
Definition: tds.h:611
TDS_INT connect_timeout
Definition: tds.h:591
unsigned int readonly_intent
Definition: tds.h:635
unsigned char option_flag2
Definition: tds.h:622
DSTR server_name
server name (in freetds.conf)
Definition: tds.h:585
TDS_USMALLINT tds_version
TDS version.
Definition: tds.h:587
unsigned int use_utf16
Definition: tds.h:631
int block_size
Definition: tds.h:588
Hold information for any results.
Definition: tds.h:842
TDS_TINYINT rows_exist
Definition: tds.h:855
TDS_USMALLINT computeid
Definition: tds.h:846
TDSCOLUMN ** columns
Definition: tds.h:844
TDS_USMALLINT num_cols
Definition: tds.h:845
TDS_TINYINT more_results
Definition: tds.h:857
TDS_USMALLINT by_cols
Definition: tds.h:854
Information for a server connection.
Definition: tds.h:1211
void(* env_chg_func)(TDSSOCKET *tds, int type, char *oldval, char *newval)
Definition: tds.h:1285
TDSCOMPUTEINFO ** comp_info
Definition: tds.h:1266
TDS_INT ret_status
return status from store procedure
Definition: tds.h:1272
TDSLOGIN * login
config for login stuff.
Definition: tds.h:1283
TDS_TINYINT has_status
true is ret_status is valid
Definition: tds.h:1270
TDS_INT8 rows_affected
rows updated/deleted/inserted/selected, TDS_NO_COUNT if not valid
Definition: tds.h:1278
TDS_STATE state
Definition: tds.h:1273
TDSCONNECTION conn[1]
Definition: tds.h:1215
TDSRESULTINFO * current_results
Current query information.
Definition: tds.h:1263
TDSRESULTINFO * res_info
Definition: tds.h:1264
TDS_UINT num_comp_info
Definition: tds.h:1265
TDS_INT query_timeout
Definition: tds.h:1279
TDSPARAMINFO * param_info
Definition: tds.h:1267
Used by tds_datecrack.
Definition: tds.h:180
unsigned char scale
Definition: proto.h:28
unsigned char precision
Definition: proto.h:27
Definition: type.c:6
else result
Definition: token2.c:20
TDS_TINYINT ti
Definition: convert.h:36
TDS_CHAR * ib
Definition: convert.h:59
TDS_NUMERIC n
Definition: convert.h:54
TDS_CHAR * c
Definition: convert.h:58
void free(voidpf ptr)
voidp malloc(uInt size)
Modified on Tue May 14 16:23:13 2024 by modify_doxy.py rev. 669887