common.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : common support for db apps.                                       *
00004 *  Author : Chris Koeritz                                                     *
00005 *  Author : freetds team for some support definitions                         *
00006 *                                                                             *
00007 *******************************************************************************
00008 * Copyright (c) 2008-$now By Author.  This program is free software; you can  *
00009 * redistribute it and/or modify it under the terms of the GNU General Public  *
00010 * License as published by the Free Software Foundation; either version 2 of   *
00011 * the License or (at your option) any later version.  This is online at:      *
00012 *     http://www.fsf.org/copyleft/gpl.html                                    *
00013 * Please send any updates to: fred@gruntose.com                               *
00014 \*****************************************************************************/
00015 
00016 #include "common.h"
00017 
00018 #include <basis/istring.h>
00019 #include <basis/log_base.h>
00020 #include <basis/program_wide_logger.h>
00021 
00022 #if HAVE_UNISTD_H
00023   #include <unistd.h>
00024 #endif
00025 
00026 #if HAVE_LIBGEN_H
00027   #include <libgen.h>
00028 #endif /* HAVE_LIBGEN_H */
00029 
00030 #if HAVE_SYS_PARAM_H
00031   #include <sys/param.h>
00032 #endif /* HAVE_SYS_PARAM_H */
00033 
00034 #include <stdlib.h>
00035 #include <string.h>
00036 
00037 bool common_database_support::_error_was_seen = false;
00038   // starts out healthy anyway.
00039 
00040 int common_database_support::syb_msg_handler(DBPROCESS * dbproc, DBINT msgno,
00041     int msgstate, int severity, char *msgtext, char *srvname, char *procname,
00042     int line)
00043 {
00044   char var_value[31];
00045   int i;
00046   char *c;
00047   int *pexpected_msgno;
00048   
00049   /*
00050    * Check for "database changed", or "language changed" messages from
00051    * the client.  If we get one of these, then we need to pull the
00052    * name of the database or charset from the message and set the
00053    * appropriate variable.
00054    */
00055   if (msgno == 5701 ||  /* database context change */
00056       msgno == 5703 ||  /* language changed */
00057       msgno == 5704) {  /* charset changed */
00058 
00059     /* program_wide_logger().log(isprintf("msgno = %d: %s", msgno, msgtext)) ; */
00060 
00061     if (msgtext != NULL && (c = strchr(msgtext, '\'')) != NULL) {
00062       i = 0;
00063       for (++c; i <= 30 && *c != '\0' && *c != '\''; ++c)
00064         var_value[i++] = *c;
00065       var_value[i] = '\0';
00066     }
00067     // this condition is not considered an error, apparently.
00068     return 0;
00069   }
00070 
00071   /*
00072    * If the user data indicates this is an expected error message (because we're testing the 
00073    * error propogation, say) then indicate this message was anticipated.
00074    */
00075   if (dbproc != NULL) {
00076     pexpected_msgno = (int *) dbgetuserdata(dbproc);
00077     if (pexpected_msgno && *pexpected_msgno == msgno) {
00078       program_wide_logger().log(isprintf("OK: anticipated message arrived: %d %s", msgno, msgtext));
00079       *pexpected_msgno = 0;
00080       return 0;
00081     }
00082   }
00083   /*
00084    * If the severity is something other than 0 or the msg number is
00085    * 0 (user informational messages).
00086    */
00087   if (severity >= 0 || msgno == 0) {
00088     /*
00089      * If the message was something other than informational, and
00090      * the severity was greater than 0, then print information to
00091      * stderr with a little pre-amble information.
00092      */
00093     if (msgno > 0 && severity > 0) {
00094       istring err_msg;
00095       err_msg += isprintf("ERROR: Msg %d, Level %d, State %d\n", (int) msgno, (int) severity, (int) msgstate);
00096       err_msg += isprintf("Server '%s'", srvname);
00097       if (procname != NULL && *procname != '\0')
00098         err_msg += isprintf(", Procedure '%s'", procname);
00099       if (line > 0)
00100         err_msg += isprintf(", Line %d", line);
00101       err_msg += isprintf("\n");
00102       err_msg += isprintf("%s", msgtext);
00103       program_wide_logger().log(err_msg);
00104       // this is actually considered an error; first and only case here.
00105       _error_was_seen = true;
00106     } else {
00107       /*
00108        * Otherwise, it is just an informational (e.g. print) message
00109        * from the server, so send it to stdout.
00110        */
00111       program_wide_logger().log(msgtext);
00112     }
00113   }
00114   return 0;
00115 }
00116 
00117 int common_database_support::syb_err_handler(DBPROCESS * dbproc, int severity,
00118     int dberr, int oserr, char *dberrstr, char *oserrstr)
00119 {
00120   int *pexpected_dberr;
00121 
00122   /*
00123    * For server messages, cancel the query and rely on the
00124    * message handler to spew the appropriate error messages out.
00125    */
00126   if (dberr == SYBESMSG) {
00127     // we think this is a real error case.
00128     _error_was_seen = true;
00129     return INT_CANCEL;
00130   }
00131 
00132   /*
00133    * If the user data indicates this is an expected error message (because we're testing the 
00134    * error propogation, say) then indicate this message was anticipated.
00135    */
00136   if (dbproc != NULL) {
00137     pexpected_dberr = (int *) dbgetuserdata(dbproc);
00138     if (pexpected_dberr && *pexpected_dberr == dberr) {
00139       program_wide_logger().log(isprintf("OK: anticipated error %d (%s) arrived", dberr, dberrstr));
00140       *pexpected_dberr = 0;
00141       return INT_CANCEL;
00142     }
00143   }
00144 
00145   program_wide_logger().log(isprintf("ERROR: in db-library (severity %d, dberr %d, oserr %d, dberrstr %s, oserrstr %s):",
00146     severity, dberr, oserr, dberrstr ? dberrstr : "(null)", oserrstr ? oserrstr : "(null)"));
00147   // we also think that anything after here is a real error.
00148   _error_was_seen = true;
00149 
00150   /*
00151    * If the dbprocess is dead or the dbproc is a NULL pointer and
00152    * we are not in the middle of logging in, then we need to exit.
00153    * We can't do anything from here on out anyway.
00154    * It's OK to end up here in response to a dbconvert() that
00155    * resulted in overflow, so don't exit in that case.
00156    */
00157   if ((dbproc == NULL) || DBDEAD(dbproc)) {
00158     if (dberr != SYBECOFL) {
00159       // we cannot allow this to exit, even with a bad database pointer.
00160       // instead, pass through to return bad value.
00161     }
00162   }
00163   return INT_CANCEL;
00164 }
00165 
00166 void common_database_support::nerf_special_characters(istring &to_nerf,
00167     char escape_char)
00168 {
00169   for (int i = 0; i < to_nerf.length(); i++) {
00170     const char current = to_nerf[i];
00171     switch (current) {
00172       // the first bank of cases are all handled identically.
00173 //      case '%':  // sql wildcard character (matches any number of chars).
00174 //      case '_':  // sql wildcard for one character match.
00175 //      case '*':  // sql wildcard for any column (may not be needed, but safer).
00176 //      case '&':  // sql special character for variable substitutions.
00177 //      case '[':  // sql special character starts literal phrases.
00178 //      {
00179 //        // put an escape before this character.
00180 //        to_nerf.insert(i, istring(escape_char, 1));
00181 //        i++;  // skip the next position, since we have offset the string.
00182 //        break;
00183 //      }
00184       case '\'': {
00185         // handle a single quote the sql way--add another single quote.
00186         to_nerf.insert(i, istring('\'', 1));  // put a new single quote in.
00187         i++;  // skip the next position, since we have offset the string.
00188         break;
00189       }
00190       default:
00191         // don't bother doing anything here.
00192         break;
00193     }
00194   }  
00195 }
00196 

Generated on Fri Nov 28 04:29:13 2008 for HOOPLE Libraries by  doxygen 1.5.1