#include <MysqlConnection.h>
Inheritance diagram for rdbModel::MysqlConnection:
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::ostream * | getOut () const |
std::ostream * | getErrOut () 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 ResultHandle * | select (const std::string &tableName, const StringVector &getCols, const StringVector &orderCols, const Assertion *where=0, int rowLimit=0, int rowOffset=0) |
virtual ResultHandle * | dbRequest (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 | |
MYSQL * | m_mysql |
bool | m_connected |
std::string | m_dbName |
std::ostream * | m_out |
std::ostream * | m_err |
VISITOR | m_visitorType |
bool | m_matchDbName |
MATCH | m_matchReturn |
Keep track of status during matching process. | |
Rdb * | m_rdb |
If successful match, save pointer to schema for use with smart insert. | |
std::vector< Column * > | m_ourCols |
MYSQL_RES * | m_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 |
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.
enum rdbModel::MysqlConnection::VISITOR [private] |
Someday we may want more than one kind of visitor; for example, might want one to create dbs
Definition at line 158 of file MysqlConnection.h.
00158 { 00159 VISITORundefined, 00160 VISITORmatch 00161 };
enum rdbModel::Visitor::VisitorState [inherited] |
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 };
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.
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] |
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;}
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.
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. |
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 }
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] |
bool rdbModel::MysqlConnection::m_connected [private] |
Definition at line 164 of file MysqlConnection.h.
Referenced by close(), isConnected(), matchSchema(), and open().
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] |
bool rdbModel::MysqlConnection::m_matchDbName [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().
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 195 of file MysqlConnection.h.
Referenced by disableModify(), insertRow(), and update().