LCOV - code coverage report
Current view: top level - src/dblib - dbutil.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 31 76 40.8 %
Date: 2024-04-18 20:40:06 Functions: 3 5 60.0 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004  Brian Bruns
       3             :  *
       4             :  * This library is free software; you can redistribute it and/or
       5             :  * modify it under the terms of the GNU Library General Public
       6             :  * License as published by the Free Software Foundation; either
       7             :  * version 2 of the License, or (at your option) any later version.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :  * Library General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU Library General Public
      15             :  * License along with this library; if not, write to the
      16             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      17             :  * Boston, MA 02111-1307, USA.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : 
      22             : #include <stdarg.h>
      23             : #include <stdio.h>
      24             : #include <assert.h>
      25             : 
      26             : #if HAVE_STDLIB_H
      27             : #include <stdlib.h>
      28             : #endif /* HAVE_STDLIB_H */
      29             : 
      30             : #if HAVE_ERRNO_H
      31             : # include <errno.h>
      32             : #endif /* HAVE_ERRNO_H */
      33             : 
      34             : #include <freetds/utils.h>
      35             : #include <freetds/tds.h>
      36             : #include <freetds/convert.h>
      37             : #include <sybdb.h>
      38             : #include <syberror.h>
      39             : #include <dblib.h>
      40             : 
      41             : /*
      42             :  * test include consistency 
      43             :  * I don't think all compiler are able to compile this code... if not comment it
      44             :  */
      45             : #if ENABLE_EXTRA_CHECKS
      46             : 
      47             : /* TODO test SYBxxx consistency */
      48             : 
      49             : #define TEST_ATTRIBUTE(t,sa,fa,sb,fb) \
      50             :         TDS_COMPILE_CHECK(t,sizeof(((sa*)0)->fa) == sizeof(((sb*)0)->fb) && TDS_OFFSET(sa,fa) == TDS_OFFSET(sb,fb))
      51             : 
      52             : TEST_ATTRIBUTE(t21,TDS_MONEY4,mny4,DBMONEY4,mny4);
      53             : TEST_ATTRIBUTE(t22,TDS_OLD_MONEY,mnyhigh,DBMONEY,mnyhigh);
      54             : TEST_ATTRIBUTE(t23,TDS_OLD_MONEY,mnylow,DBMONEY,mnylow);
      55             : TEST_ATTRIBUTE(t24,TDS_DATETIME,dtdays,DBDATETIME,dtdays);
      56             : TEST_ATTRIBUTE(t25,TDS_DATETIME,dttime,DBDATETIME,dttime);
      57             : TEST_ATTRIBUTE(t26,TDS_DATETIME4,days,DBDATETIME4,days);
      58             : TEST_ATTRIBUTE(t27,TDS_DATETIME4,minutes,DBDATETIME4,minutes);
      59             : TEST_ATTRIBUTE(t28,TDS_NUMERIC,precision,DBNUMERIC,precision);
      60             : TEST_ATTRIBUTE(t29,TDS_NUMERIC,scale,DBNUMERIC,scale);
      61             : TEST_ATTRIBUTE(t30,TDS_NUMERIC,array,DBNUMERIC,array);
      62             : #endif
      63             : 
      64             : /* 
      65             :  * The next 2 functions receive the info and error messages that come from the TDS layer.  
      66             :  * The address of this function is passed to the TDS layer in dbinit().  
      67             :  * It takes a pointer to a DBPROCESS, it's just that the TDS layer didn't 
      68             :  * know what it really was.  
      69             :  */
      70             : int
      71        2240 : _dblib_handle_info_message(const TDSCONTEXT * tds_ctx, TDSSOCKET * tds, TDSMESSAGE * msg)
      72             : {
      73        2240 :         DBPROCESS *dbproc = (tds && tds_get_parent(tds))? (DBPROCESS *) tds_get_parent(tds) : NULL;
      74             : 
      75        2240 :         tdsdump_log(TDS_DBG_FUNC, "_dblib_handle_info_message(%p, %p, %p)\n", tds_ctx, tds, msg);
      76        2240 :         tdsdump_log(TDS_DBG_FUNC, "msgno %d: \"%s\"\n", msg->msgno, msg->message);
      77             : 
      78             :         /* 
      79             :          * Check to see if the user supplied a function, else ignore the message. 
      80             :          */
      81        2240 :         if (_dblib_msg_handler) {
      82        5046 :                 _dblib_msg_handler(dbproc,
      83             :                                    msg->msgno,
      84        1682 :                                    msg->state,
      85        1682 :                                    msg->severity, msg->message, msg->server, msg->proc_name, msg->line_number);
      86             :         }
      87             : 
      88        2240 :         if (msg->severity > 10 && _dblib_err_handler) {   /* call the application's error handler, if installed. */
      89             :                 /*
      90             :                  * Sybase docs say SYBESMSG is generated only in specific
      91             :                  * cases (severity greater than 16, or deadlock occurred, or
      92             :                  * a syntax error occurred.)  However, actual observed
      93             :                  * behavior is that SYBESMSG is always generated for
      94             :                  * server messages with severity greater than 10.
      95             :                  */
      96             :                 /* Cannot call dbperror() here because server messsage numbers (and text) are not in its lookup table. */
      97             :                 static const char message[] = "General SQL Server error: Check messages from the SQL Server";
      98          94 :                 (*_dblib_err_handler)(dbproc, msg->severity, SYBESMSG, DBNOERR, (char *) message, NULL);
      99             :         }
     100        2240 :         return TDS_SUCCESS;
     101             : }
     102             : 
     103             : /** \internal
     104             :  *  \dblib_internal
     105             :  *  \brief handle errors generated by libtds
     106             :  *  \param tds_ctx actually a dbproc: contains all information needed by db-lib to manage communications with the server.
     107             :  *  \param tds contains all information needed by libtds to manage communications with the server.
     108             :  *  \param msg the message to send
     109             :  *  \returns 
     110             :  *  \remarks This function is called by libtds via tds_ctx->err_handler.  It exists to convert the db-lib 
     111             :  *      error handler's return code into one that libtds will know  how to handle.  
     112             :  *      libtds conveniently issues msgno's with the same values and meanings as db-lib and ODBC use.  
     113             :  *      (N.B. ODBC actually uses db-lib msgno numbers for its driver-specific "server errors".    
     114             :  */
     115             : /* 
     116             :  * Stack:
     117             :  *              libtds
     118             :  *                      tds_ctx->err_handler (pointer to _dblib_handle_err_message)
     119             :  *                      _dblib_handle_err_message
     120             :  *                              dbperror
     121             :  *                                      client (or default) error handler
     122             :  *                                      returns db-lib defined return code INT_something.
     123             :  *                              returns db-lib return code with Sybase semantics (adjusting client's code if need be)
     124             :  *                      returns libtds return code
     125             :  *              decides what to do based on the universal libtds return code, thank you. 
     126             :  */     
     127             : int
     128          64 : _dblib_handle_err_message(const TDSCONTEXT * tds_ctx TDS_UNUSED, TDSSOCKET * tds, TDSMESSAGE * msg)
     129             : {
     130          64 :         DBPROCESS *dbproc = (tds && tds_get_parent(tds))? (DBPROCESS *) tds_get_parent(tds) : NULL;
     131          64 :         int rc = INT_CANCEL;
     132             : 
     133          64 :         assert(_dblib_err_handler);
     134          64 :         assert(msg);
     135             : 
     136          64 :         rc = dbperror(dbproc, msg->msgno, msg->oserr, 0, 0, 0, 0);
     137             : 
     138             :         /*
     139             :          * Preprocess the return code to handle INT_TIMEOUT/INT_CONTINUE
     140             :          * for non-SYBETIME errors in the strange and different ways as
     141             :          * specified by Sybase and Microsoft.
     142             :          */
     143          64 :         if (msg->msgno != SYBETIME) {
     144           8 :                 switch (rc) {
     145             :                 case INT_TIMEOUT:
     146             :                         rc = INT_EXIT;
     147             :                         break;
     148           0 :                 case INT_CONTINUE:
     149           0 :                         if (!dbproc || !dbproc->msdblib) {
     150             :                                 /* Sybase behavior */
     151           0 :                                 assert(0);  /* dbperror() should prevent */
     152             :                                 rc = INT_EXIT;
     153             :                         } else {
     154             :                                 /* Microsoft behavior */
     155             :                                 rc = INT_CANCEL;
     156             :                         }
     157             :                         break;
     158             :                 default:
     159             :                         break;
     160             :                 }
     161          56 :         }
     162             : 
     163             :         /*
     164             :          * Convert db-lib return code to libtds return code, and return.
     165             :          */
     166          64 :         switch (rc) {
     167             :         case INT_CANCEL:        return TDS_INT_CANCEL;
     168          16 :         case INT_TIMEOUT:       return TDS_INT_TIMEOUT;
     169          32 :         case INT_CONTINUE:      return TDS_INT_CONTINUE;
     170             :         
     171             :         case INT_EXIT:
     172           0 :                 assert(0);  /* dbperror() should prevent */
     173             :         default:
     174             :                 /* unknown return code from error handler */
     175           0 :                 exit(EXIT_FAILURE);
     176             :                 break;
     177             :         }
     178             : 
     179             :         /* not reached */
     180             :         assert(0);
     181             :         return TDS_INT_CANCEL;
     182             : }
     183             : 
     184             : /**
     185             :  * \ingroup dblib_internal
     186             :  * \brief check interrupts for libtds.
     187             :  * 
     188             :  * \param vdbproc a DBPROCESS pointer, contains all information needed by db-lib to manage communications with the server.
     189             :  * \sa DBDEAD(), dbsetinterrupt().
     190             :  */
     191             : int
     192         216 : _dblib_check_and_handle_interrupt(void * vdbproc)
     193             : {
     194         216 :         DBPROCESS * dbproc = (DBPROCESS*) vdbproc;
     195         216 :         int ret = INT_CONTINUE;
     196             : 
     197         216 :         assert( dbproc != NULL );
     198             : 
     199         216 :         if (dbproc->chkintr == NULL || dbproc->hndlintr == NULL)
     200             :                 return INT_CONTINUE;
     201             :                 
     202          96 :         tdsdump_log(TDS_DBG_FUNC, "_dblib_check_and_handle_interrupt %p [%p, %p]\n", dbproc, dbproc->chkintr, dbproc->hndlintr);
     203             : 
     204          96 :         if (dbproc->chkintr(dbproc)){
     205           0 :                 switch (ret = dbproc->hndlintr(dbproc)) {
     206           0 :                 case INT_EXIT:
     207           0 :                         tdsdump_log(TDS_DBG_FUNC, "dbproc->hndlintr returned INT_EXIT, goodbye!\n");
     208           0 :                         exit(1);
     209           0 :                 case INT_CANCEL:
     210           0 :                         tdsdump_log(TDS_DBG_FUNC, "dbproc->hndlintr returned INT_CANCEL\n");
     211             :                         break;
     212           0 :                 case INT_CONTINUE:
     213           0 :                         tdsdump_log(TDS_DBG_FUNC, "dbproc->hndlintr returned INT_CONTINUE\n");
     214             :                         break;
     215           0 :                 default:
     216           0 :                         tdsdump_log(TDS_DBG_FUNC, "dbproc->hndlintr returned an invalid value (%d), returning INT_CONTINUE\n", ret);
     217             :                         ret = INT_CONTINUE;
     218             :                         break;
     219             :                 }
     220          96 :         }
     221             :         return ret;
     222             : }
     223             : 
     224             : 
     225             : void
     226           0 : _dblib_setTDS_version(TDSLOGIN * tds_login, DBINT version)
     227             : {
     228           0 :         switch (version) {
     229           0 :         case DBVERSION_42:
     230           0 :                 tds_set_version(tds_login, 4, 2);
     231           0 :                 break;
     232           0 :         case DBVERSION_46:
     233           0 :                 tds_set_version(tds_login, 4, 6);
     234           0 :                 break;
     235           0 :         case DBVERSION_100:
     236           0 :                 tds_set_version(tds_login, 5, 0);
     237           0 :                 break;
     238             :         }
     239           0 : }
     240             : 
     241             : void
     242           0 : _dblib_convert_err(DBPROCESS * dbproc, TDS_INT len)
     243             : {
     244           0 :         switch (len) {
     245           0 :         case TDS_CONVERT_NOAVAIL:
     246           0 :                 dbperror(dbproc, SYBERDCN, 0);
     247           0 :                 break;
     248           0 :         case TDS_CONVERT_SYNTAX:
     249           0 :                 dbperror(dbproc, SYBECSYN, 0);
     250           0 :                 break;
     251           0 :         case TDS_CONVERT_NOMEM:
     252           0 :                 dbperror(dbproc, SYBEMEM, ENOMEM);
     253           0 :                 break;
     254           0 :         case TDS_CONVERT_OVERFLOW:
     255           0 :                 dbperror(dbproc, SYBECOFL, 0);
     256           0 :                 break;
     257           0 :         default:
     258             :         case TDS_CONVERT_FAIL:
     259           0 :                 dbperror(dbproc, SYBECINTERNAL, 0);
     260           0 :                 break;
     261             :         }
     262           0 : }
     263             : 

Generated by: LCOV version 1.13