rdbModel::MysqlConnection Class Reference

#include <MysqlConnection.h>

Inheritance diagram for rdbModel::MysqlConnection:

rdbModel::Connection rdbModel::Visitor List of all members.

Public Types

 VCONTINUE = 0
 VDONE
 VBRANCHDONE
 VERROR
 VERRORABORT
enum  VisitorState {
  VCONTINUE = 0, VDONE, VBRANCHDONE, VERROR,
  VERRORABORT
}

Public Member Functions

 MysqlConnection (std::ostream *out=0, std::ostream *errOut=0)
virtual ~MysqlConnection ()
virtual bool open (const std::string &host, const std::string &userid, const std::string &password, const std::string &dbName)
virtual bool open (const std::string &parms)
virtual bool close ()
virtual bool isConnected ()
 Return true iff open has been done with no matching close.
std::ostreamgetOut () const
std::ostreamgetErrOut () const
virtual MATCH matchSchema (Rdb *rdb, bool matchDbName=true)
virtual bool insertRow (const std::string &tableName, const StringVector &colNames, const StringVector &values, int *auto_value=0, const StringVector *nullCols=0)
virtual unsigned int update (const std::string &tableName, const StringVector &colNames, const StringVector &values, const Assertion *where=0, const StringVector *nullCols=0)
virtual ResultHandleselect (const std::string &tableName, const StringVector &getCols, const StringVector &orderCols, const Assertion *where=0, int rowLimit=0, int rowOffset=0)
virtual ResultHandledbRequest (const std::string &request)
virtual bool compileAssertion (const Assertion *a, std::string &sqlString) const
virtual void disableModify (bool disable)
virtual Visitor::VisitorState visitRdb (Rdb *)
 This method sets if the visitor is recursive or not.
virtual Visitor::VisitorState visitTable (Table *)
virtual Visitor::VisitorState visitColumn (Column *)
virtual Visitor::VisitorState visitIndex (Index *)
virtual Visitor::VisitorState visitAssertion (Assertion *)
virtual VisitorState visitInsertNew (InsertNew *)
virtual VisitorState visitSupersede (Supersede *)
virtual VisitorState visitQuery (Query *)
virtual VisitorState visitSet (Set *)
virtual VisitorState visitInterRow (InterRow *)

Private Types

 VISITORundefined
 VISITORmatch
enum  VISITOR { VISITORundefined, VISITORmatch }

Private Member Functions

bool checkDType (Datatype *dtype, const std::string &sqlType)

Static Private Member Functions

static void compileInit ()
static bool compileComparison (Assertion::Operator *op, std::string &sqlString)
static bool compileOperator (Assertion::Operator *op, std::string &sqlString)

Private Attributes

MYSQLm_mysql
bool m_connected
std::string m_dbName
std::ostreamm_out
std::ostreamm_err
VISITOR m_visitorType
bool m_matchDbName
MATCH m_matchReturn
 Keep track of status during matching process.
Rdbm_rdb
 If successful match, save pointer to schema for use with smart insert.
std::vector< Column * > m_ourCols
MYSQL_RESm_tempRes
 For query results while visiting.
std::map< std::string, unsigned
int > 
m_colIx
 Index by colname; data is row number with "SHOW COLUMNS.." result set.
std::string m_primColName
bool m_writeDisabled
std::string m_host
std::string m_user
std::string m_password

Static Private Attributes

static bool m_compileInit = false

Detailed Description

Class to handle connection to a MySQL database

Initial design will just use host, password, userid passed in. Will be up to caller to insure that the userid has the right privilages for the operations caller intends to do.

Definition at line 32 of file MysqlConnection.h.


Member Enumeration Documentation

enum rdbModel::MysqlConnection::VISITOR [private]

Someday we may want more than one kind of visitor; for example, might want one to create dbs

Enumerator:
VISITORundefined 
VISITORmatch 

Definition at line 158 of file MysqlConnection.h.

00158                  {
00159       VISITORundefined,
00160       VISITORmatch
00161     };

enum rdbModel::Visitor::VisitorState [inherited]

Enumerator:
VCONTINUE 
VDONE 
VBRANCHDONE 
VERROR 
VERRORABORT 

Definition at line 34 of file Visitor.h.

00034                        {
00035       VCONTINUE = 0,
00036       VDONE,         // visitor has had its fill of visiting
00037       VBRANCHDONE,   // don't descend further; go to next sibling, if any
00038       VERROR,        // error during visit; perhaps can continue, though
00039       VERRORABORT    // error during visit; can't handle more
00040     };


Constructor & Destructor Documentation

rdbModel::MysqlConnection::MysqlConnection ( std::ostream out = 0,
std::ostream errOut = 0 
)

Open a connection Allowed operations will depend on userid, etc., specified return true if successful

Definition at line 70 of file MysqlConnection.cxx.

References m_err, and m_out.

00071                                                        :
00072     m_mysql(0), m_connected(0), m_out(out), m_err(errOut),
00073     m_visitorType(VISITORundefined), m_rdb(0), m_tempRes(0),
00074     m_writeDisabled(false)                                   {
00075     if (m_out == 0) m_out = &std::cout;
00076     if (m_err == 0) m_err = &std::cerr;
00077   }

rdbModel::MysqlConnection::~MysqlConnection (  )  [virtual]

Definition at line 91 of file MysqlConnection.cxx.

References close(), and m_mysql.

00091                                     {
00092     close();
00093     delete m_mysql;
00094     return;
00095   }


Member Function Documentation

bool rdbModel::MysqlConnection::checkDType ( Datatype dtype,
const std::string sqlType 
) [private]

Definition at line 729 of file MysqlConnection.cxx.

References compareEnumList(), extractSize(), rdbModel::Enum::getChoices(), rdbModel::Datatype::getEnum(), rdbModel::Datatype::getOutputSize(), rdbModel::Datatype::getType(), m_matchReturn, rdbModel::MATCHcompatible, rdbModel::MATCHfail, deljobs::string, rdbModel::Datatype::TYPEchar, rdbModel::Datatype::TYPEdatetime, rdbModel::Datatype::TYPEdouble, rdbModel::Datatype::TYPEenum, rdbModel::Datatype::TYPEint, rdbModel::Datatype::TYPEmediumint, rdbModel::Datatype::TYPEreal, rdbModel::Datatype::TYPEsmallint, rdbModel::Datatype::TYPEtimestamp, and rdbModel::Datatype::TYPEvarchar.

Referenced by visitColumn().

00730                                 {
00731     std::string base;
00732     int sqlSize;
00733     if (dtype->getType() != Datatype::TYPEenum) {
00734       sqlSize = extractSize(sqlType);
00735     }
00736 
00737     // Cases  char, varchar, enum and datetime are handled entirely within
00738     // the switch statement, but most do the bulk of the work in
00739     // common, after the switch.
00740     switch (dtype->getType()) {
00741       case Datatype::TYPEenum: {
00742                                  base = "enum";
00743                                  if (sqlType.find(base) != 0) {
00744                                    m_matchReturn = MATCHfail;
00745                                    return false;
00746                                  }
00747                                  Enum* ourEnum = dtype->getEnum();
00748                                  // Finally compare local list of choices to those listed in sqlType
00749                                  // Local list is a vector; in sqlType they're quoted, comma separated
00750                                  return compareEnumList(ourEnum->getChoices(), sqlType);
00751                                }
00752       case Datatype::TYPEvarchar: {
00753                                     base = "varchar";
00754                                     if (sqlType.find(base) != 0) {
00755                                       m_matchReturn = MATCHfail;
00756                                       return false;
00757                                     }
00758                                     // size in db must be at least as large as size in Col.
00759                                     if (sqlSize < dtype->getOutputSize()) {
00760                                       m_matchReturn = MATCHfail;
00761                                       return false;
00762                                     }
00763                                     else if (sqlSize > dtype->getOutputSize()) {
00764                                       m_matchReturn = MATCHcompatible;
00765                                     }
00766                                     return true;
00767                                   }
00768       case Datatype::TYPEchar: {
00769                                  base = "char";
00770                                  if (sqlType.find(base) != 0) {
00771                                    m_matchReturn = MATCHfail;
00772                                    return false;
00773                                  }
00774                                  //  For char datatype unspecified size is equivalent to size=1
00775                                  if (!sqlSize) sqlSize = 1;
00776                                  // size in db must be at least as large as size in Col.
00777                                  if (sqlSize < dtype->getOutputSize()) {
00778                                    m_matchReturn = MATCHfail;
00779                                    return false;
00780                                  }
00781                                  else if (sqlSize > dtype->getOutputSize()) {
00782                                    m_matchReturn = MATCHcompatible;
00783                                  }
00784                                  return true;
00785                                }
00786       case Datatype::TYPEdatetime: {
00787                                      if (sqlType != "datetime") {
00788                                        m_matchReturn = MATCHfail;
00789                                        return false;
00790                                      }
00791                                      return true;
00792                                    }
00793 
00794 
00795       case Datatype::TYPEtimestamp: {
00796                                       base = "timestamp";
00797                                       break;
00798                                     }
00799       case Datatype::TYPEint: {
00800                                 base = "int";
00801                                 break;
00802                               }
00803       case Datatype::TYPEmediumint: {
00804                                       base = "mediumint";
00805                                       break;
00806                                     }
00807       case Datatype::TYPEsmallint: {
00808                                      base = "smallint";
00809                                      break;
00810                                    }
00811       case Datatype::TYPEreal: 
00812       case Datatype::TYPEdouble: {
00813                                    base = "double";
00814                                    break;
00815                                  }
00816       default: {  // Indicates bad xml file input.  Applications
00817                  //should have exited already
00818                  m_matchReturn = MATCHfail;
00819                  return false;
00820                }
00821     }     // end switch
00822     if (sqlType.find(base) != 0) {
00823       m_matchReturn = MATCHfail;
00824       return false;
00825     }
00826     // Now check size.  It's only for display, so mismatch is not failure
00827     if (sqlSize != dtype->getOutputSize()) {
00828       m_matchReturn = MATCHcompatible;
00829     }
00830 
00831     return true;
00832   }

bool rdbModel::MysqlConnection::close (  )  [virtual]

Close the current open connection , if any. Return true if there was a connection to close and it was closed successfully

Implements rdbModel::Connection.

Definition at line 79 of file MysqlConnection.cxx.

References m_connected, m_mysql, and m_tempRes.

Referenced by main(), and ~MysqlConnection().

00079                               {
00080     if (m_tempRes) {
00081       mysql_free_result(m_tempRes);
00082       m_tempRes = 0;
00083     }
00084  std::cout<<"close connection ================================"<<std::endl;
00085     mysql_close(m_mysql);
00086     m_mysql = 0;
00087     m_connected = false;
00088     return true;
00089   }

bool rdbModel::MysqlConnection::compileAssertion ( const Assertion a,
std::string sqlString 
) const [virtual]

compile method for assertions. Use it internally, but also make it publicly available so assertions belonging to a table can save the compiled version.

Implements rdbModel::Connection.

Definition at line 463 of file MysqlConnection.cxx.

References compileInit(), compileOperator(), rdbModel::RdbException::getMsg(), rdbModel::Assertion::getOperator(), m_compileInit, and m_out.

Referenced by select(), and update().

00464                                   {
00465     if (!m_compileInit) {
00466       compileInit();
00467       m_compileInit = true;
00468     }
00469     try {
00470       return compileOperator(a->getOperator(), sqlString);
00471     }
00472     catch (RdbException ex) {
00473       (*m_out) << std::endl << ex.getMsg() << std::endl;
00474       m_out->flush();
00475       return false;
00476     }
00477   }

bool rdbModel::MysqlConnection::compileComparison ( Assertion::Operator op,
std::string sqlString 
) [static, private]

Result is appended to caller-supplied string Convention is to use " " around literal values Note no verification is done here; that operator is in fact a comparison or isNull operator. This is called internally only and that check will have been done before invoking this routine.

Definition at line 510 of file MysqlConnection.cxx.

References addArg(), rdbModel::FIELDTYPElit, rdbModel::Assertion::Operator::getCompareArgs(), rdbModel::Assertion::Operator::getCompareArgTypes(), rdbModel::Assertion::Operator::getOpType(), rdbModel::Assertion::Operator::getToBe(), rdbModel::opSymbols, and rdbModel::OPTYPEisNull.

Referenced by compileOperator().

00511                             {
00512     if (op->getToBe()) return false;  // can't compile
00513 
00514     OPTYPE opType = op->getOpType();
00515     if (opType == OPTYPEisNull) {
00516       sqlString +="(";
00517       sqlString += op->getCompareArgs()[0];
00518       sqlString += opSymbols[opType];
00519       sqlString += ")";
00520       return true;
00521     }
00522     sqlString += "(";
00523 
00524     bool literal0 = (op->getCompareArgTypes()[0] == FIELDTYPElit);
00525     bool literal1 = (op->getCompareArgTypes()[1] == FIELDTYPElit);
00526 
00527     addArg(literal0, op->getCompareArgs()[0], sqlString);
00528     sqlString += opSymbols[opType];
00529     addArg(literal1, op->getCompareArgs()[1], sqlString);
00530     sqlString += ")";
00531 
00532     return true;
00533   }

void rdbModel::MysqlConnection::compileInit (  )  [static, private]

Definition at line 481 of file MysqlConnection.cxx.

References rdbModel::opSymbols, rdbModel::OPTYPEand, rdbModel::OPTYPEequal, rdbModel::OPTYPEexists, rdbModel::OPTYPEgreaterOrEqual, rdbModel::OPTYPEgreaterThan, rdbModel::OPTYPEisNull, rdbModel::OPTYPElessOrEqual, rdbModel::OPTYPElessThan, rdbModel::OPTYPEnot, rdbModel::OPTYPEnotEqual, and rdbModel::OPTYPEor.

Referenced by compileAssertion().

00481                                     {
00482     opSymbols[OPTYPEor] = " OR ";
00483     opSymbols[OPTYPEand] = " AND ";
00484     opSymbols[OPTYPEnot] = " NOT ";
00485     opSymbols[OPTYPEexists] = "EXISTS ";
00486     opSymbols[OPTYPEisNull] = " IS NULL";
00487     opSymbols[OPTYPEequal] = "=";
00488     opSymbols[OPTYPEnotEqual] = "<>";
00489     opSymbols[OPTYPElessThan] = "<";
00490     opSymbols[OPTYPEgreaterThan] = ">";
00491     opSymbols[OPTYPElessOrEqual] = "<=";
00492     opSymbols[OPTYPEgreaterOrEqual] = ">=";
00493     return;
00494   }

bool rdbModel::MysqlConnection::compileOperator ( Assertion::Operator op,
std::string sqlString 
) [static, private]

Definition at line 535 of file MysqlConnection.cxx.

References compileComparison(), rdbModel::Assertion::Operator::isCompareOp(), rdbModel::opSymbols, rdbModel::OPTYPEexists, and deljobs::string.

Referenced by compileAssertion().

00536                             {
00537 
00538     //maqm     std::cout<<"in compileOperator() sqlString is00:"<<sqlString<<std::endl;
00539     if (op->isCompareOp() ) return compileComparison(op, sqlString);
00540     if (op->getToBe()) return false;  // can't compile in this case
00541     bool ret = true;
00542 
00543     const std::vector<Assertion::Operator*>& children = op->getChildren();
00544     unsigned nChild = children.size();
00545 
00546     // For single-child operators NOT,  exists, operator symbol
00547     // goes 1st, then operand
00548     if (nChild <= 1) { // operator goes first
00549       sqlString += opSymbols[op->getOpType()];
00550 
00551       // more special handling for EXISTS
00552       if (op->getOpType() == OPTYPEexists) {
00553         sqlString += "(SELECT * FROM " + op->getTableName();
00554         if (!nChild) {     // done
00555           sqlString += ")";
00556           return ret;
00557         }
00558         // else EXISTS child is object of a WHERE clause 
00559         sqlString += " WHERE(";
00560       }
00561       ret = compileOperator(children[0], sqlString);
00562       if (!ret) {
00563         std::string msg = 
00564           "rdbModel::MysqlConnection::compileOperator failed for operator "
00565           + opSymbols[op->getOpType()];
00566         throw RdbException(msg);
00567       }
00568 
00569       // Have an extra closing ")" for EXISTS with WHERE clause
00570       if (op->getOpType() == OPTYPEexists)       sqlString += ")";
00571 
00572 
00573       return ret;
00574     }
00575 
00576     // Otherwise put operator symbols between adjacent children.
00577 
00578     // First open parentheses
00579     sqlString += "(";
00580 
00581     std::string symbol = opSymbols[op->getOpType()];
00582 
00583     ret = compileOperator(children[0], sqlString);
00584     if (!ret) {
00585       std::string msg = 
00586         "rdbModel::MysqlConnection::compileOperator failed for operator "
00587         + symbol;
00588       throw RdbException(msg);
00589     }
00590     for (unsigned int iChild = 1; iChild < nChild; iChild++) {
00591       sqlString += symbol;
00592 
00593       ret = compileOperator(children[iChild], sqlString);
00594       if (!ret) {
00595         std::string msg = 
00596           "rdbModel::MysqlConnection::compileOperator failed for operator "
00597           + symbol;
00598         throw RdbException(msg);
00599       }
00600     }
00601     // Finally close paren.
00602     sqlString += ")";
00603     return ret;
00604   }

ResultHandle * rdbModel::MysqlConnection::dbRequest ( const std::string request  )  [virtual]

Transmit raw request of any form to our other end. If it is a request that returns results, those results will be stored in a newly-allocated ResultHandle and dbRequest will return a pointer to it. Otherwise dbRequest will return a null pointer. Throw an exception if request fails for any reason.

Implements rdbModel::Connection.

Definition at line 409 of file MysqlConnection.cxx.

References genRecEmupikp::i, RawFileTools::itoa(), m_dbName, m_host, m_mysql, m_out, m_password, m_user, open(), and deljobs::string.

Referenced by main().

00409                                                                    {
00410 
00411     (*m_out) << std::endl << "# About to issue SQL request:" << std::endl;
00412     (*m_out) << request << std::endl;
00413     m_out->flush();
00414     
00415     int i=0;
00416     int mysqlRet = mysql_query(m_mysql, request.c_str());
00417     for (i=0;i<10;i++) {
00418     //  int mysqlRet = mysql_query(m_mysql, request.c_str());
00419       if (mysqlRet) {  
00420         //not connected
00421         std::string msg = 
00422           "rdbModel::MysqlConnection::dbRequest: mysql_query error, code ";
00423         std::string codeString;
00424         facilities::Util::itoa(mysqlRet, codeString);
00425         msg += codeString;
00426         (*m_out) << std::endl <<i<<"times not connected++++ "<< msg << std::endl;
00427         m_out->flush();
00428         fprintf(stderr, "mysql_query error %d: %s\n",mysql_errno(m_mysql),mysql_error(m_mysql));
00429         if (i>=9){
00430          throw RdbException(msg, mysqlRet);
00431           return 0;
00432         }
00433          mysql_close(m_mysql);
00434          m_mysql = 0;
00435          sleep(100);
00436          bool st = open(m_host,m_user,m_password,m_dbName);
00437          if(st==false) continue;
00438         mysqlRet = mysql_query(m_mysql, request.c_str());
00439       }else{
00440         break;
00441       }
00442     }
00443    
00444 
00445     MYSQL_RES *myres = mysql_store_result(m_mysql);
00446     if (!myres) {
00447       // Was it supposed to return data?
00448       if (mysql_field_count(m_mysql) == 0) { // no data expected
00449         return 0;
00450       }
00451       else {
00452         std::string msg =
00453           "rdbModel::MysqlConnection::dbRequest: expected data; none returned";
00454         (*m_out) << std::endl << msg << std::endl;
00455         m_out->flush();
00456         throw RdbException(msg);
00457         return 0;
00458       }
00459     }
00460     return new MysqlResults(myres);
00461   }

virtual void rdbModel::MysqlConnection::disableModify ( bool  disable  )  [inline, virtual]

Turn select and update into no-ops: output SQL string for debugging but don't change db

Implements rdbModel::Connection.

Definition at line 137 of file MysqlConnection.h.

References m_writeDisabled.

Referenced by main().

00137 {m_writeDisabled=disable;}

std::ostream* rdbModel::MysqlConnection::getErrOut (  )  const [inline, virtual]

Implements rdbModel::Connection.

Definition at line 57 of file MysqlConnection.h.

References m_err.

00057 {return m_err;}

std::ostream* rdbModel::MysqlConnection::getOut (  )  const [inline, virtual]

Implements rdbModel::Connection.

Definition at line 56 of file MysqlConnection.h.

References m_out.

00056 {return m_out;}

bool rdbModel::MysqlConnection::insertRow ( const std::string tableName,
const StringVector colNames,
const StringVector values,
int *  auto_value = 0,
const StringVector nullCols = 0 
) [virtual]

Typical derived class will form a syntactically correct INSERT statement from the input arguments and issue it to the dbms. Return true if row was inserted successfully If auto_value is non-zero and the table has an auto-increment column, its value will be returned. If nullCols is non-zero, insertRow will treat each string in the vector as a column name whose value should be set to NULL

Might also want to add a routine for INSERT ... SELECT

Implements rdbModel::Connection.

Definition at line 216 of file MysqlConnection.cxx.

References m_err, m_mysql, m_out, m_writeDisabled, and deljobs::string.

00220                                                                 {
00221     std::string ins;
00222     if (auto_value) *auto_value = 0;
00223 
00224     // check that sizes of vectors match
00225     unsigned  nCol = colNames.size();    
00226     if (!nCol || (nCol != values.size()  ) ) {
00227       (*m_err) << " MysqlConnection::insertRow: vector lengths incompatible"
00228                 << std::endl;
00229       m_err->flush();
00230       return false;
00231     }
00232 
00233     // caller should already have checked for validity and should
00234     // have supplied all necessary columns
00235 
00236     ins += "insert into " + tableName;
00237     ins += " set " + colNames[0] + "='" + values[0] + "' ";
00238     for (unsigned iCol = 1; iCol < nCol; iCol++) {
00239       ins += ", " + colNames[iCol] + "='" + values[iCol] + "' ";
00240     }
00241     if (nullCols) {
00242       if (nullCols->size() > 0) {
00243         unsigned nNull = nullCols->size();
00244         for (unsigned iNull = 0; iNull < nNull; iNull++) {
00245           ins += ", " + (*nullCols)[iNull] + "= NULL ";
00246         }
00247       }
00248     }
00249 
00250     (*m_out) << std::endl << "# INSERT string is:" << std::endl;
00251     (*m_out) << ins << std::endl;
00252     m_out->flush();
00253 
00254     if (m_writeDisabled) {
00255       (*m_out) << "write to Db previously disabled; INSERT not sent"
00256                << std::endl;
00257       m_out->flush();
00258       return true;
00259     }
00260 
00261     int mysqlRet = mysql_query(m_mysql, ins.c_str());
00262 
00263     if (mysqlRet) {
00264       (*m_out) << "MySQL error during INSERT, code " << mysqlRet << std::endl;
00265       m_out->flush();
00266       return false;
00267     }
00268     if (auto_value) {
00269       *auto_value = mysql_insert_id(m_mysql);
00270     }
00271     return true;
00272   }

virtual bool rdbModel::MysqlConnection::isConnected (  )  [inline, virtual]

Return true iff open has been done with no matching close.

Implements rdbModel::Connection.

Definition at line 54 of file MysqlConnection.h.

References m_connected.

00054 {return m_connected;}

MATCH rdbModel::MysqlConnection::matchSchema ( Rdb rdb,
bool  matchDbName = true 
) [virtual]

Check to what degree local schema definition is compatible with remote db accessed via this connection. By default check db names match, but this may be disabled.

If match is successful, may also want to cache information about some things; for example, rows for which agent = "service"

Implements rdbModel::Connection.

Definition at line 191 of file MysqlConnection.cxx.

References rdbModel::Rdb::accept(), m_connected, m_matchDbName, m_matchReturn, m_visitorType, rdbModel::MATCHequivalent, rdbModel::MATCHfail, rdbModel::MATCHnoConnection, rdbModel::Visitor::VERROR, rdbModel::Visitor::VERRORABORT, and VISITORmatch.

Referenced by main().

00191                                                                {
00192     if (!m_connected) return MATCHnoConnection;
00193 
00194     m_matchDbName = matchDbName;
00195 
00196     // Check global characteristics; 
00197     // Could do this via Manager; seems a bit artificial, bypass for now
00198     m_visitorType = VISITORmatch;
00199     m_matchReturn = MATCHequivalent;
00200     unsigned int ret = rdb->accept(this);
00201 
00202     if ((ret == Visitor::VERROR) || (ret == Visitor::VERRORABORT)) {
00203       return MATCHfail;
00204     }
00205     else return m_matchReturn;
00206   }

bool rdbModel::MysqlConnection::open ( const std::string parms  )  [virtual]

Parameter is normally path for an xml file descrbing the connection parameters

Implements rdbModel::Connection.

Definition at line 163 of file MysqlConnection.cxx.

References xmlBase::Dom::getAttribute(), m_err, m_out, open(), xmlBase::XmlParser::parse(), and deljobs::string.

00163                                                    {
00164     using XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument;
00165     using XERCES_CPP_NAMESPACE_QUALIFIER DOMElement;
00166     xmlBase::XmlParser parser;
00167     DOMDocument* doc = parser.parse(parms.c_str(), "mysqlConnection");
00168     if (doc == 0) {
00169       (*m_err) << "parse of connection parameters failed" << std::endl;
00170       m_err->flush();
00171       return false;
00172     }
00173     DOMElement*  conn = doc->getDocumentElement();
00174     
00175     std::string host = xmlBase::Dom::getAttribute(conn, "host");
00176     std::string user = xmlBase::Dom::getAttribute(conn, "user");
00177     std::string password = xmlBase::Dom::getAttribute(conn, "password");
00178     std::string dbname = xmlBase::Dom::getAttribute(conn, "dbname");
00179 
00180     if (password.size() == 0 ) { // prompt for password?
00181       (*m_out) << "interactive login NYI " << std::endl;
00182       m_out->flush();
00183       return false;
00184     }
00185 
00186     return this->open(host, user, password, dbname);
00187   }

bool rdbModel::MysqlConnection::open ( const std::string host,
const std::string userid,
const std::string password,
const std::string dbName 
) [virtual]

Implements rdbModel::Connection.

Definition at line 97 of file MysqlConnection.cxx.

References m_connected, m_dbName, m_err, m_host, m_mysql, m_out, m_password, m_user, RealDBUtil::npos, and deljobs::string.

Referenced by dbRequest(), main(), and open().

00100                                                       {
00101                              //     , unsigned int       port) {
00102     if (dbName.size() == 0) {
00103       (*m_err) << 
00104         "rdbModel::MysqlConnection::open : null db name not allowed!" <<
00105         std::endl;
00106       m_err->flush();
00107       return false;
00108     } 
00109    //huangb add
00110     m_host = host;
00111     m_user = user;
00112     m_password = password;
00113 
00114     m_mysql = new MYSQL;
00115     mysql_init(m_mysql);
00116 
00117     // 'host' argument is of the form hostname[:port]
00118     //  That is, port section is optional.  If not supplied, use
00119     // default port.
00120     std::string hostOnly;
00121     int port = 0;
00122     std::string::size_type colonLoc = host.find(":");
00123     if (colonLoc == std::string::npos) {
00124       hostOnly = host;
00125     }
00126     else {
00127       hostOnly = host.substr(0, colonLoc);
00128       std::string portString = host.substr(colonLoc+1);
00129       try {
00130         port = facilities::Util::stringToInt(portString);
00131       }
00132       catch (facilities::WrongType ex) {
00133         (*m_err) << "From MysqlConnection::connect.  Bad port: "
00134                  << ex.getMsg() << std::endl;
00135         m_err->flush();
00136         return false;
00137       }
00138 
00139     }
00140     //    mysql_init(m_mysql);
00141     std::cout<<"host is:"<<hostOnly.c_str()<<"::use is:: "<<user.c_str()<<":pass is::"<<password.c_str()<<":db is::"<<dbName.c_str()<<std::endl;
00142     MYSQL *connected = mysql_real_connect(m_mysql, hostOnly.c_str(),  
00143                                           user.c_str(),
00144                                           password.c_str(), dbName.c_str(),
00145                                           3306, NULL, 0);
00146 
00147     if (connected != 0) {  // Everything is fine.  Put out an info message
00148       (*m_out) << "Successfully connected to MySQL host " << 
00149         host << ", database " << dbName << std::endl;
00150       m_out->flush();
00151       m_connected = true;
00152       m_dbName = dbName;
00153     }
00154     else {
00155       (*m_err) <<  "Failed to connect to MySQL host " << host <<
00156         "with error:::: " << mysql_error(m_mysql) << std::endl;
00157       m_err->flush();
00158       m_connected = false;
00159     }
00160     return m_connected;
00161   }

ResultHandle * rdbModel::MysqlConnection::select ( const std::string tableName,
const StringVector getCols,
const StringVector orderCols,
const Assertion where = 0,
int  rowLimit = 0,
int  rowOffset = 0 
) [virtual]

Support only for relatively simple SELECT, involving just one table.

Parameters:
tableName 
getCols vector of columns to be retrieved
where ptr to an Assertion object
rowLimit max number of rows to return
rowOffset offset for first row returned among those satisfying conditions; ignored if 0.
Returns:
If the SELECT succeeds, a pointer to an object which manages the returned data; else 0. Caller is responsible for deleting the ResultHandle object.

Implements rdbModel::Connection.

Definition at line 330 of file MysqlConnection.cxx.

References compileAssertion(), RawFileTools::itoa(), m_mysql, m_out, deljobs::string, and boss::where().

00335                                                          {
00336     std::string sqlString = "SELECT ";
00337     unsigned nGet = getCols.size();
00338     unsigned nOrder = orderCols.size();
00339 
00340      std::cout<<"tableName is:"<<tableName<<std::endl;
00341 
00342 //     tableName="metadata_v2r1";
00343        
00344     sqlString += getCols[0];
00345     for (unsigned iGet = 1; iGet < nGet; iGet++) {
00346       sqlString += ",";
00347       sqlString += getCols[iGet];
00348     }
00349     sqlString +=  " FROM " + tableName +  " ";
00350      std::cout<<"sqlString is11:"<<sqlString<<std::endl;
00351    if (where != 0) {
00352       sqlString += " WHERE ";
00353       bool ret = compileAssertion(where, sqlString);
00354       if (!ret) return 0;
00355     }
00356    
00357     std::cout<<"sqlString is22:"<<sqlString<<std::endl;
00358   
00359     /*maqm  if (nOrder > 0 ) {
00360       sqlString += " ORDER BY " + orderCols[0]; 
00361       for (unsigned iOrder = 1; iOrder < nOrder; iOrder++) {
00362         sqlString += ",";
00363         sqlString += orderCols[iOrder];
00364       }
00365     }
00366    */ 
00367 //     sqlString ="SELECT ser_no FROM metadata_v2r1  WHERE ((completion='OK') AND (instrument='LAT') AND (calib_type='MDC_t0') AND (flavor='vanilla'))";
00368     if (rowLimit > 0) {
00369       // SQL format is LIMIT offset,limit      or
00370       //               LIMIT limit             or
00371       //               LIMIT limit   OFFSET offset  [don't use this one]
00372       sqlString += " LIMIT ";
00373       std::string limitStr;
00374       if (rowOffset > 0) {
00375         facilities::Util::itoa(rowOffset, limitStr);
00376         sqlString += limitStr + ",";
00377       }
00378       limitStr.clear();
00379       facilities::Util::itoa(rowLimit, limitStr);
00380        std::cout<<"limitStr is:"<<limitStr<<std::endl;
00381       sqlString += limitStr;
00382     }
00383 
00384     (*m_out) << std::endl << " # About to issue SELECT:" << std::endl;
00385     (*m_out) << sqlString << std::endl;
00386     m_out->flush();
00387    //maqm add
00388 //     sqlString="SELECT ser_no FROM metadata_v2r1";
00389 
00390      
00391     int mysqlRet = mysql_query(m_mysql, sqlString.c_str());
00392     if (mysqlRet) {
00393       std::string msg = 
00394         "rdbModel::MysqlConnection::select: mysql_query error, code ";
00395       std::string codeString;
00396       facilities::Util::itoa(mysqlRet, codeString);
00397       msg += codeString;
00398       (*m_out) << std::endl << msg << std::endl;
00399       m_out->flush();
00400       throw RdbException(msg, mysqlRet);
00401       return 0;
00402     }
00403 
00404     MYSQL_RES *myres = mysql_store_result(m_mysql);
00405     MysqlResults* results = new MysqlResults(myres);
00406     return results;
00407   }

unsigned int rdbModel::MysqlConnection::update ( const std::string tableName,
const StringVector colNames,
const StringVector values,
const Assertion where = 0,
const StringVector nullCols = 0 
) [virtual]

Generic UPDATE. Return value is number of rows changed.

Implements rdbModel::Connection.

Definition at line 275 of file MysqlConnection.cxx.

References compileAssertion(), m_err, m_mysql, m_out, m_writeDisabled, deljobs::string, and boss::where().

00279                                                                      {
00280 
00281     unsigned int nCol = colNames.size();
00282     if (nCol != values.size()) {
00283       (*m_err) << "rdbModel::mysqlConnection::update: ";
00284       (*m_err) << "Incompatible vector arguments " << std::endl;
00285       m_err->flush();
00286       return 0;
00287     }
00288     std::string sqlString = "UPDATE " + tableName + " SET ";
00289     sqlString += colNames[0] + " = '" + values[0] + "'";
00290     for (unsigned int iCol = 1; iCol < nCol; iCol++) {
00291       sqlString += "," + colNames[iCol] + " = '" + values[iCol] + "'";
00292     }
00293     if (nullCols) {
00294       unsigned nNull = nullCols->size();
00295       for (unsigned iNull = 0; iNull < nNull; iNull++) {
00296         sqlString += ", " + (*nullCols)[iNull] + "= NULL ";
00297       }
00298     }
00299 
00300     if (where) {
00301       sqlString += " WHERE ";
00302       bool ret = compileAssertion(where, sqlString);
00303       if (!ret) return 0;
00304     }
00305     (*m_out) << std::endl << "#  UPDATE to be issued:" << std::endl;
00306     (*m_out) << sqlString << std::endl;
00307     m_out->flush();
00308     if (m_writeDisabled) {
00309       (*m_out) << "write to Db previously disabled; UPDATE not sent"
00310                << std::endl;
00311       m_out->flush();
00312       return 0;
00313     }
00314     int mysqlRet = mysql_query(m_mysql, sqlString.c_str());
00315 
00316     if (mysqlRet) {
00317       (*m_out) << "rdbModel::MysqlConnection::update: ";
00318       (*m_out) << "MySQL error during UPDATE, code " << mysqlRet << std::endl;
00319       m_out->flush();
00320       return 0;
00321     }
00322     my_ulonglong nModLong = mysql_affected_rows(m_mysql);
00323     // Not much chance that we'll change more rows than will fit in just long
00324     unsigned nMod = nModLong;
00325     return nMod;
00326 
00327 
00328   }

Visitor::VisitorState rdbModel::MysqlConnection::visitAssertion ( Assertion  )  [virtual]

Implements rdbModel::Visitor.

Definition at line 841 of file MysqlConnection.cxx.

References rdbModel::Visitor::VCONTINUE.

00841                                                                 {
00842     return Visitor::VCONTINUE;
00843   }

Visitor::VisitorState rdbModel::MysqlConnection::visitColumn ( Column  )  [virtual]

Implements rdbModel::Visitor.

Definition at line 685 of file MysqlConnection.cxx.

References checkDType(), rdbModel::Column::getDatatype(), rdbModel::Column::getName(), rdbModel::Column::isAutoIncrement(), m_colIx, m_matchReturn, m_primColName, m_tempRes, rdbModel::MATCHfail, rdbModel::Column::nullAllowed(), deljobs::string, rdbModel::Visitor::VCONTINUE, and rdbModel::Visitor::VERRORABORT.

00685                                                               {
00686     std::string myName = col->getName();
00687     if (m_colIx.find(myName) == m_colIx.end()) {
00688       m_matchReturn = MATCHfail;
00689       return Visitor::VERRORABORT;
00690     }
00691     unsigned int ix = m_colIx[myName];
00692     mysql_data_seek(m_tempRes, ix);
00693     MYSQL_ROW colDescrip = mysql_fetch_row(m_tempRes);
00694 
00695     // Type
00696     std::string sqlDtype = std::string(colDescrip[1]);
00697     Datatype* dtype = col->getDatatype();
00698     if (!checkDType(dtype, sqlDtype)) {
00699       m_matchReturn = MATCHfail;
00700       (*m_out) << "Failed dtype match of col " << myName << std::endl;
00701       return Visitor::VERRORABORT;
00702     }
00703 
00704     // Null
00705     bool nullable = (std::string(colDescrip[2]) == std::string("YES"));
00706     if (nullable != col->nullAllowed()) {
00707       m_matchReturn = MATCHfail;
00708       (*m_out) << "Failed null/not null match of col " << myName << std::endl;
00709       return Visitor::VERRORABORT;
00710     }
00711     // Key (PRI for primary, MUL if first in a multiple-field key
00712     // Save primary key info, if any
00713     if (std::string(colDescrip[3]) == std::string("PRI")) {
00714       m_primColName = myName;
00715     }
00716 
00717     // Field 4 is default
00718     // Extra (may say auto_increment)
00719     bool autoInc = 
00720       (std::string(colDescrip[5]) == std::string("auto_increment"));
00721     if (autoInc != col->isAutoIncrement()) {
00722       m_matchReturn = MATCHfail;
00723       (*m_out) << "Failed isAutoIncrement match of col " << myName << std::endl;
00724       return Visitor::VERRORABORT;
00725     }
00726     return Visitor::VCONTINUE;
00727   }

Visitor::VisitorState rdbModel::MysqlConnection::visitIndex ( Index  )  [virtual]

Implements rdbModel::Visitor.

Definition at line 836 of file MysqlConnection.cxx.

References rdbModel::Visitor::VCONTINUE.

00836                                                          {
00837     return Visitor::VCONTINUE;
00838     // might put something real here later
00839   }

Visitor::VisitorState rdbModel::MysqlConnection::visitInsertNew ( InsertNew  )  [virtual]

Implements rdbModel::Visitor.

Definition at line 845 of file MysqlConnection.cxx.

References rdbModel::Visitor::VCONTINUE.

00845                                                                 {
00846     return Visitor::VCONTINUE;
00847   }

Visitor::VisitorState rdbModel::MysqlConnection::visitInterRow ( InterRow  )  [virtual]

Implements rdbModel::Visitor.

Definition at line 861 of file MysqlConnection.cxx.

References rdbModel::Visitor::VCONTINUE.

00861                                                               {
00862     return Visitor::VCONTINUE;
00863   }

Visitor::VisitorState rdbModel::MysqlConnection::visitQuery ( Query  )  [virtual]

Implements rdbModel::Visitor.

Definition at line 853 of file MysqlConnection.cxx.

References rdbModel::Visitor::VCONTINUE.

00853                                                         {
00854     return Visitor::VCONTINUE;
00855   }

Visitor::VisitorState rdbModel::MysqlConnection::visitRdb ( Rdb  )  [virtual]

This method sets if the visitor is recursive or not.

Implements rdbModel::Visitor.

Definition at line 609 of file MysqlConnection.cxx.

References rdbModel::Rdb::getDbName(), rdbModel::Rdb::getNTable(), m_dbName, m_matchDbName, m_matchReturn, m_mysql, rdbModel::MATCHcompatible, rdbModel::MATCHfail, rdbModel::Rdb::setConnection(), rdbModel::Visitor::VCONTINUE, rdbModel::Visitor::VDONE, and rdbModel::Visitor::VERRORABORT.

00609                                                         {
00610 
00611     if (m_matchDbName) {
00612       if (m_dbName != rdb->getDbName()) {
00613         m_matchReturn = MATCHfail;
00614         return Visitor::VDONE;
00615       }
00616     }
00617 
00618     unsigned int nLocal = rdb->getNTable();
00619 
00620     // Null pointer for 2nd argument means "list all tables"
00621 
00622     MYSQL_RES* res = mysql_list_tables(m_mysql, 0);
00623     if (!res) {
00624       m_matchReturn = MATCHfail;
00625       return Visitor::VERRORABORT;
00626     }
00627     unsigned int nRemote = mysql_num_rows(res);
00628     mysql_free_result(res);
00629 
00630     if (nRemote < nLocal) {
00631       m_matchReturn = MATCHfail;
00632       return Visitor::VDONE;
00633     }
00634     else if (nRemote > nLocal) m_matchReturn = MATCHcompatible;
00635 
00636     // Tell Rdb about this 
00637     rdb->setConnection(this);
00638 
00639     return Visitor::VCONTINUE;
00640   }

Visitor::VisitorState rdbModel::MysqlConnection::visitSet ( Set  )  [virtual]

Implements rdbModel::Visitor.

Definition at line 857 of file MysqlConnection.cxx.

References rdbModel::Visitor::VCONTINUE.

00857                                                     {
00858     return Visitor::VCONTINUE;
00859   }

Visitor::VisitorState rdbModel::MysqlConnection::visitSupersede ( Supersede  )  [virtual]

Implements rdbModel::Visitor.

Definition at line 849 of file MysqlConnection.cxx.

References rdbModel::Visitor::VCONTINUE.

00849                                                                 {
00850     return Visitor::VCONTINUE;
00851   }

Visitor::VisitorState rdbModel::MysqlConnection::visitTable ( Table  )  [virtual]

Implements rdbModel::Visitor.

Definition at line 642 of file MysqlConnection.cxx.

References rdbModel::Table::getName(), m_colIx, m_matchReturn, m_mysql, m_out, m_primColName, m_tempRes, rdbModel::MATCHfail, deljobs::string, rdbModel::Visitor::VCONTINUE, and rdbModel::Visitor::VERRORABORT.

00642                                                               {
00643     const std::string& tName = table->getName();
00644 
00645     // Result set will have all fields for the table
00646     if (m_tempRes) {
00647       mysql_free_result(m_tempRes);
00648       m_tempRes = 0;
00649     }
00650     m_primColName.clear();
00651 
00652     std::string query = "SHOW COLUMNS FROM " + tName;
00653 
00654     (*m_out) << std::endl << "# About to issue SHOW COLUMNS request :" 
00655       << std::endl;
00656     (*m_out) << query << std::endl;
00657     m_out->flush();
00658 
00659     int ret = mysql_query(m_mysql, query.c_str());
00660     if (ret) {
00661       m_matchReturn = MATCHfail;
00662       return Visitor::VERRORABORT;
00663     }
00664 
00665     m_tempRes = mysql_store_result(m_mysql);
00666     if (!m_tempRes) {
00667       m_matchReturn = MATCHfail;
00668       return Visitor::VERRORABORT;
00669     }
00670     // Result set is a table with fields "Field"(the name) "Type" "Null"(yes
00671     // or no) "Key" "Default", "Extra"  
00672     // Make it easier for accept(Column* ) to find relevant information
00673     unsigned int nRow = mysql_num_rows(m_tempRes);
00674     m_colIx.clear();
00675     for (unsigned iRow = 0; iRow < nRow; iRow++) {
00676       MYSQL_ROW colDescrip = mysql_fetch_row(m_tempRes);
00677       std::string name = std::string(colDescrip[0]);
00678       std::cout<<"name is:"<<name<<std::endl;
00679       m_colIx[name] = iRow;
00680     }
00681     return Visitor::VCONTINUE;
00682 
00683   }


Member Data Documentation

std::map<std::string, unsigned int> rdbModel::MysqlConnection::m_colIx [private]

Index by colname; data is row number with "SHOW COLUMNS.." result set.

Definition at line 190 of file MysqlConnection.h.

Referenced by visitColumn(), and visitTable().

bool rdbModel::MysqlConnection::m_compileInit = false [static, private]

Definition at line 194 of file MysqlConnection.h.

Referenced by compileAssertion().

bool rdbModel::MysqlConnection::m_connected [private]

Definition at line 164 of file MysqlConnection.h.

Referenced by close(), isConnected(), matchSchema(), and open().

std::string rdbModel::MysqlConnection::m_dbName [private]

Definition at line 166 of file MysqlConnection.h.

Referenced by dbRequest(), open(), and visitRdb().

std::ostream* rdbModel::MysqlConnection::m_err [private]

Definition at line 168 of file MysqlConnection.h.

Referenced by getErrOut(), insertRow(), MysqlConnection(), open(), and update().

std::string rdbModel::MysqlConnection::m_host [private]

Definition at line 206 of file MysqlConnection.h.

Referenced by dbRequest(), and open().

bool rdbModel::MysqlConnection::m_matchDbName [private]

Definition at line 174 of file MysqlConnection.h.

Referenced by matchSchema(), and visitRdb().

MATCH rdbModel::MysqlConnection::m_matchReturn [private]

Keep track of status during matching process.

Definition at line 177 of file MysqlConnection.h.

Referenced by checkDType(), matchSchema(), visitColumn(), visitRdb(), and visitTable().

MYSQL* rdbModel::MysqlConnection::m_mysql [private]

Definition at line 163 of file MysqlConnection.h.

Referenced by close(), dbRequest(), insertRow(), open(), select(), update(), visitRdb(), visitTable(), and ~MysqlConnection().

std::vector<Column* > rdbModel::MysqlConnection::m_ourCols [private]

Also save list of columns we ("service") are responsible for Could organize this by table, or just use Column::getTableName()

Definition at line 184 of file MysqlConnection.h.

std::ostream* rdbModel::MysqlConnection::m_out [private]

Definition at line 167 of file MysqlConnection.h.

Referenced by compileAssertion(), dbRequest(), getOut(), insertRow(), MysqlConnection(), open(), select(), update(), and visitTable().

std::string rdbModel::MysqlConnection::m_password [private]

Definition at line 208 of file MysqlConnection.h.

Referenced by dbRequest(), and open().

std::string rdbModel::MysqlConnection::m_primColName [private]

Definition at line 192 of file MysqlConnection.h.

Referenced by visitColumn(), and visitTable().

Rdb* rdbModel::MysqlConnection::m_rdb [private]

If successful match, save pointer to schema for use with smart insert.

Definition at line 180 of file MysqlConnection.h.

MYSQL_RES* rdbModel::MysqlConnection::m_tempRes [private]

For query results while visiting.

Definition at line 187 of file MysqlConnection.h.

Referenced by close(), visitColumn(), and visitTable().

std::string rdbModel::MysqlConnection::m_user [private]

Definition at line 207 of file MysqlConnection.h.

Referenced by dbRequest(), and open().

VISITOR rdbModel::MysqlConnection::m_visitorType [private]

Definition at line 173 of file MysqlConnection.h.

Referenced by matchSchema().

bool rdbModel::MysqlConnection::m_writeDisabled [private]

Definition at line 195 of file MysqlConnection.h.

Referenced by disableModify(), insertRow(), and update().


Generated on Tue Nov 29 23:36:35 2016 for BOSS_7.0.2 by  doxygen 1.4.7