#include <MysqlConnection.h>
Inheritance diagram for rdbModel::MysqlConnection:
Public Types | |
enum | VisitorState { VCONTINUE = 0, VDONE, VBRANCHDONE, VERROR, VERRORABORT } |
enum | VisitorState { VCONTINUE = 0, VDONE, VBRANCHDONE, VERROR, VERRORABORT } |
Public Member Functions | |
virtual bool | close () |
virtual bool | close () |
virtual bool | compileAssertion (const Assertion *a, std::string &sqlString) const |
virtual bool | compileAssertion (const Assertion *a, std::string &sqlString) const |
virtual ResultHandle * | dbRequest (const std::string &request) |
virtual ResultHandle * | dbRequest (const std::string &request) |
virtual void | disableModify (bool disable) |
virtual void | disableModify (bool disable) |
std::ostream * | getErrOut () const |
std::ostream * | getErrOut () const |
std::ostream * | getOut () const |
std::ostream * | getOut () const |
virtual bool | insertRow (const std::string &tableName, const StringVector &colNames, const StringVector &values, int *auto_value=0, const StringVector *nullCols=0) |
virtual bool | insertRow (const std::string &tableName, const StringVector &colNames, const StringVector &values, int *auto_value=0, const StringVector *nullCols=0) |
virtual bool | isConnected () |
Return true iff open has been done with no matching close. | |
virtual bool | isConnected () |
Return true iff open has been done with no matching close. | |
virtual MATCH | matchSchema (Rdb *rdb, bool matchDbName=true) |
virtual MATCH | matchSchema (Rdb *rdb, bool matchDbName=true) |
MysqlConnection (std::ostream *out=0, std::ostream *errOut=0) | |
MysqlConnection (std::ostream *out=0, std::ostream *errOut=0) | |
virtual bool | open (const std::string &parms) |
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 | open (const std::string &host, const std::string &userid, const std::string &password, const std::string &dbName) |
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 * | select (const std::string &tableName, const StringVector &getCols, const StringVector &orderCols, const Assertion *where=0, int rowLimit=0, int rowOffset=0) |
virtual unsigned int | update (const std::string &tableName, const StringVector &colNames, const StringVector &values, const Assertion *where=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 Visitor::VisitorState | visitAssertion (Assertion *) |
virtual Visitor::VisitorState | visitAssertion (Assertion *) |
virtual Visitor::VisitorState | visitColumn (Column *) |
virtual Visitor::VisitorState | visitColumn (Column *) |
virtual Visitor::VisitorState | visitIndex (Index *) |
virtual Visitor::VisitorState | visitIndex (Index *) |
virtual VisitorState | visitInsertNew (InsertNew *) |
virtual VisitorState | visitInsertNew (InsertNew *) |
virtual VisitorState | visitInterRow (InterRow *) |
virtual VisitorState | visitInterRow (InterRow *) |
virtual VisitorState | visitQuery (Query *) |
virtual VisitorState | visitQuery (Query *) |
virtual Visitor::VisitorState | visitRdb (Rdb *) |
This method sets if the visitor is recursive or not. | |
virtual Visitor::VisitorState | visitRdb (Rdb *) |
This method sets if the visitor is recursive or not. | |
virtual VisitorState | visitSet (Set *) |
virtual VisitorState | visitSet (Set *) |
virtual VisitorState | visitSupersede (Supersede *) |
virtual VisitorState | visitSupersede (Supersede *) |
virtual Visitor::VisitorState | visitTable (Table *) |
virtual Visitor::VisitorState | visitTable (Table *) |
virtual | ~MysqlConnection () |
virtual | ~MysqlConnection () |
Private Types | |
enum | VISITOR { VISITORundefined, VISITORmatch } |
enum | VISITOR { VISITORundefined, VISITORmatch } |
Private Member Functions | |
bool | checkDType (Datatype *dtype, const std::string &sqlType) |
bool | checkDType (Datatype *dtype, const std::string &sqlType) |
Static Private Member Functions | |
bool | compileComparison (Assertion::Operator *op, std::string &sqlString) |
bool | compileComparison (Assertion::Operator *op, std::string &sqlString) |
void | compileInit () |
void | compileInit () |
bool | compileOperator (Assertion::Operator *op, std::string &sqlString) |
bool | compileOperator (Assertion::Operator *op, std::string &sqlString) |
Private Attributes | |
std::map< std::string, unsigned int > | m_colIx |
Index by colname; data is row number with "SHOW COLUMNS.." result set. | |
std::map< std::string, unsigned int > | m_colIx |
Index by colname; data is row number with "SHOW COLUMNS.." result set. | |
bool | m_connected |
std::string | m_dbName |
std::ostream * | m_err |
std::ostream * | m_err |
std::string | m_host |
bool | m_matchDbName |
MATCH | m_matchReturn |
Keep track of status during matching process. | |
MYSQL * | m_mysql |
MYSQL * | m_mysql |
std::vector< Column * > | m_ourCols |
std::vector< Column * > | m_ourCols |
std::ostream * | m_out |
std::ostream * | m_out |
std::string | m_password |
std::string | m_primColName |
Rdb * | m_rdb |
If successful match, save pointer to schema for use with smart insert. | |
Rdb * | m_rdb |
If successful match, save pointer to schema for use with smart insert. | |
MYSQL_RES * | m_tempRes |
For query results while visiting. | |
MYSQL_RES * | m_tempRes |
For query results while visiting. | |
std::string | m_user |
VISITOR | m_visitorType |
bool | m_writeDisabled |
Static Private Attributes | |
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.
|
Someday we may want more than one kind of visitor; for example, might want one to create dbs 00158 { 00159 VISITORundefined, 00160 VISITORmatch 00161 };
|
|
Someday we may want more than one kind of visitor; for example, might want one to create dbs 00158 { 00159 VISITORundefined, 00160 VISITORmatch 00161 };
|
|
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 };
|
|
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 };
|
|
Open a connection Allowed operations will depend on userid, etc., specified return true if successful 00070 : 00071 m_mysql(0), m_connected(0), m_out(out), m_err(errOut), 00072 m_visitorType(VISITORundefined), m_rdb(0), m_tempRes(0), 00073 m_writeDisabled(false) { 00074 if (m_out == 0) m_out = &std::cout; 00075 if (m_err == 0) m_err = &std::cerr; 00076 }
|
|
00090 { 00091 close(); 00092 delete m_mysql; 00093 return; 00094 }
|
|
Open a connection Allowed operations will depend on userid, etc., specified return true if successful |
|
|
|
|
|
00729 { 00730 std::string base; 00731 int sqlSize; 00732 if (dtype->getType() != Datatype::TYPEenum) { 00733 sqlSize = extractSize(sqlType); 00734 } 00735 00736 // Cases char, varchar, enum and datetime are handled entirely within 00737 // the switch statement, but most do the bulk of the work in 00738 // common, after the switch. 00739 switch (dtype->getType()) { 00740 case Datatype::TYPEenum: { 00741 base = "enum"; 00742 if (sqlType.find(base) != 0) { 00743 m_matchReturn = MATCHfail; 00744 return false; 00745 } 00746 Enum* ourEnum = dtype->getEnum(); 00747 // Finally compare local list of choices to those listed in sqlType 00748 // Local list is a vector; in sqlType they're quoted, comma separated 00749 return compareEnumList(ourEnum->getChoices(), sqlType); 00750 } 00751 case Datatype::TYPEvarchar: { 00752 base = "varchar"; 00753 if (sqlType.find(base) != 0) { 00754 m_matchReturn = MATCHfail; 00755 return false; 00756 } 00757 // size in db must be at least as large as size in Col. 00758 if (sqlSize < dtype->getOutputSize()) { 00759 m_matchReturn = MATCHfail; 00760 return false; 00761 } 00762 else if (sqlSize > dtype->getOutputSize()) { 00763 m_matchReturn = MATCHcompatible; 00764 } 00765 return true; 00766 } 00767 case Datatype::TYPEchar: { 00768 base = "char"; 00769 if (sqlType.find(base) != 0) { 00770 m_matchReturn = MATCHfail; 00771 return false; 00772 } 00773 // For char datatype unspecified size is equivalent to size=1 00774 if (!sqlSize) sqlSize = 1; 00775 // size in db must be at least as large as size in Col. 00776 if (sqlSize < dtype->getOutputSize()) { 00777 m_matchReturn = MATCHfail; 00778 return false; 00779 } 00780 else if (sqlSize > dtype->getOutputSize()) { 00781 m_matchReturn = MATCHcompatible; 00782 } 00783 return true; 00784 } 00785 case Datatype::TYPEdatetime: { 00786 if (sqlType != "datetime") { 00787 m_matchReturn = MATCHfail; 00788 return false; 00789 } 00790 return true; 00791 } 00792 00793 00794 case Datatype::TYPEtimestamp: { 00795 base = "timestamp"; 00796 break; 00797 } 00798 case Datatype::TYPEint: { 00799 base = "int"; 00800 break; 00801 } 00802 case Datatype::TYPEmediumint: { 00803 base = "mediumint"; 00804 break; 00805 } 00806 case Datatype::TYPEsmallint: { 00807 base = "smallint"; 00808 break; 00809 } 00810 case Datatype::TYPEreal: 00811 case Datatype::TYPEdouble: { 00812 base = "double"; 00813 break; 00814 } 00815 default: { // Indicates bad xml file input. Applications 00816 //should have exited already 00817 m_matchReturn = MATCHfail; 00818 return false; 00819 } 00820 } // end switch 00821 if (sqlType.find(base) != 0) { 00822 m_matchReturn = MATCHfail; 00823 return false; 00824 } 00825 // Now check size. It's only for display, so mismatch is not failure 00826 if (sqlSize != dtype->getOutputSize()) { 00827 m_matchReturn = MATCHcompatible; 00828 } 00829 00830 return true; 00831 }
|
|
Close the current open connection , if any. Return true if there was a connection to close and it was closed successfully Implements rdbModel::Connection. |
|
Close the current open connection , if any. Return true if there was a connection to close and it was closed successfully Implements rdbModel::Connection. 00078 { 00079 if (m_tempRes) { 00080 mysql_free_result(m_tempRes); 00081 m_tempRes = 0; 00082 } 00083 std::cout<<"close connection ================================"<<std::endl; 00084 mysql_close(m_mysql); 00085 m_mysql = 0; 00086 m_connected = false; 00087 return true; 00088 }
|
|
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. |
|
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. 00463 { 00464 if (!m_compileInit) { 00465 compileInit(); 00466 m_compileInit = true; 00467 } 00468 try { 00469 return compileOperator(a->getOperator(), sqlString); 00470 } 00471 catch (RdbException ex) { 00472 (*m_out) << std::endl << ex.getMsg() << std::endl; 00473 m_out->flush(); 00474 return false; 00475 } 00476 }
|
|
|
|
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. 00510 { 00511 if (op->getToBe()) return false; // can't compile 00512 00513 OPTYPE opType = op->getOpType(); 00514 if (opType == OPTYPEisNull) { 00515 sqlString +="("; 00516 sqlString += op->getCompareArgs()[0]; 00517 sqlString += opSymbols[opType]; 00518 sqlString += ")"; 00519 return true; 00520 } 00521 sqlString += "("; 00522 00523 bool literal0 = (op->getCompareArgTypes()[0] == FIELDTYPElit); 00524 bool literal1 = (op->getCompareArgTypes()[1] == FIELDTYPElit); 00525 00526 addArg(literal0, op->getCompareArgs()[0], sqlString); 00527 sqlString += opSymbols[opType]; 00528 addArg(literal1, op->getCompareArgs()[1], sqlString); 00529 sqlString += ")"; 00530 00531 return true; 00532 }
|
|
|
|
00480 { 00481 opSymbols[OPTYPEor] = " OR "; 00482 opSymbols[OPTYPEand] = " AND "; 00483 opSymbols[OPTYPEnot] = " NOT "; 00484 opSymbols[OPTYPEexists] = "EXISTS "; 00485 opSymbols[OPTYPEisNull] = " IS NULL"; 00486 opSymbols[OPTYPEequal] = "="; 00487 opSymbols[OPTYPEnotEqual] = "<>"; 00488 opSymbols[OPTYPElessThan] = "<"; 00489 opSymbols[OPTYPEgreaterThan] = ">"; 00490 opSymbols[OPTYPElessOrEqual] = "<="; 00491 opSymbols[OPTYPEgreaterOrEqual] = ">="; 00492 return; 00493 }
|
|
|
|
00535 { 00536 00537 //maqm std::cout<<"in compileOperator() sqlString is00:"<<sqlString<<std::endl; 00538 if (op->isCompareOp() ) return compileComparison(op, sqlString); 00539 if (op->getToBe()) return false; // can't compile in this case 00540 bool ret = true; 00541 00542 const std::vector<Assertion::Operator*>& children = op->getChildren(); 00543 unsigned nChild = children.size(); 00544 00545 // For single-child operators NOT, exists, operator symbol 00546 // goes 1st, then operand 00547 if (nChild <= 1) { // operator goes first 00548 sqlString += opSymbols[op->getOpType()]; 00549 00550 // more special handling for EXISTS 00551 if (op->getOpType() == OPTYPEexists) { 00552 sqlString += "(SELECT * FROM " + op->getTableName(); 00553 if (!nChild) { // done 00554 sqlString += ")"; 00555 return ret; 00556 } 00557 // else EXISTS child is object of a WHERE clause 00558 sqlString += " WHERE("; 00559 } 00560 ret = compileOperator(children[0], sqlString); 00561 if (!ret) { 00562 std::string msg = 00563 "rdbModel::MysqlConnection::compileOperator failed for operator " 00564 + opSymbols[op->getOpType()]; 00565 throw RdbException(msg); 00566 } 00567 00568 // Have an extra closing ")" for EXISTS with WHERE clause 00569 if (op->getOpType() == OPTYPEexists) sqlString += ")"; 00570 00571 00572 return ret; 00573 } 00574 00575 // Otherwise put operator symbols between adjacent children. 00576 00577 // First open parentheses 00578 sqlString += "("; 00579 00580 std::string symbol = opSymbols[op->getOpType()]; 00581 00582 ret = compileOperator(children[0], sqlString); 00583 if (!ret) { 00584 std::string msg = 00585 "rdbModel::MysqlConnection::compileOperator failed for operator " 00586 + symbol; 00587 throw RdbException(msg); 00588 } 00589 for (unsigned int iChild = 1; iChild < nChild; iChild++) { 00590 sqlString += symbol; 00591 00592 ret = compileOperator(children[iChild], sqlString); 00593 if (!ret) { 00594 std::string msg = 00595 "rdbModel::MysqlConnection::compileOperator failed for operator " 00596 + symbol; 00597 throw RdbException(msg); 00598 } 00599 } 00600 // Finally close paren. 00601 sqlString += ")"; 00602 return ret; 00603 }
|
|
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. |
|
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. 00408 { 00409 00410 (*m_out) << std::endl << "# About to issue SQL request:" << std::endl; 00411 (*m_out) << request << std::endl; 00412 m_out->flush(); 00413 00414 int i=0; 00415 int mysqlRet = mysql_query(m_mysql, request.c_str()); 00416 for (i=0;i<10;i++) { 00417 // int mysqlRet = mysql_query(m_mysql, request.c_str()); 00418 if (mysqlRet) { 00419 //not connected 00420 std::string msg = 00421 "rdbModel::MysqlConnection::dbRequest: mysql_query error, code "; 00422 std::string codeString; 00423 facilities::Util::itoa(mysqlRet, codeString); 00424 msg += codeString; 00425 (*m_out) << std::endl <<i<<"times not connected++++ "<< msg << std::endl; 00426 m_out->flush(); 00427 fprintf(stderr, "mysql_query error %d: %s\n",mysql_errno(m_mysql),mysql_error(m_mysql)); 00428 if (i>=9){ 00429 throw RdbException(msg, mysqlRet); 00430 return 0; 00431 } 00432 mysql_close(m_mysql); 00433 m_mysql = 0; 00434 sleep(100); 00435 bool st = open(m_host,m_user,m_password,m_dbName); 00436 if(st==false) continue; 00437 mysqlRet = mysql_query(m_mysql, request.c_str()); 00438 }else{ 00439 break; 00440 } 00441 } 00442 00443 00444 MYSQL_RES *myres = mysql_store_result(m_mysql); 00445 if (!myres) { 00446 // Was it supposed to return data? 00447 if (mysql_field_count(m_mysql) == 0) { // no data expected 00448 return 0; 00449 } 00450 else { 00451 std::string msg = 00452 "rdbModel::MysqlConnection::dbRequest: expected data; none returned"; 00453 (*m_out) << std::endl << msg << std::endl; 00454 m_out->flush(); 00455 throw RdbException(msg); 00456 return 0; 00457 } 00458 } 00459 return new MysqlResults(myres); 00460 }
|
|
Turn select and update into no-ops: output SQL string for debugging but don't change db Implements rdbModel::Connection. 00137 {m_writeDisabled=disable;}
|
|
Turn select and update into no-ops: output SQL string for debugging but don't change db Implements rdbModel::Connection. 00137 {m_writeDisabled=disable;}
|
|
Implements rdbModel::Connection. 00057 {return m_err;}
|
|
Implements rdbModel::Connection. 00057 {return m_err;}
|
|
Implements rdbModel::Connection. 00056 {return m_out;}
|
|
Implements rdbModel::Connection. 00056 {return m_out;}
|
|
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. |
|
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. 00219 { 00220 std::string ins; 00221 if (auto_value) *auto_value = 0; 00222 00223 // check that sizes of vectors match 00224 unsigned nCol = colNames.size(); 00225 if (!nCol || (nCol != values.size() ) ) { 00226 (*m_err) << " MysqlConnection::insertRow: vector lengths incompatible" 00227 << std::endl; 00228 m_err->flush(); 00229 return false; 00230 } 00231 00232 // caller should already have checked for validity and should 00233 // have supplied all necessary columns 00234 00235 ins += "insert into " + tableName; 00236 ins += " set " + colNames[0] + "='" + values[0] + "' "; 00237 for (unsigned iCol = 1; iCol < nCol; iCol++) { 00238 ins += ", " + colNames[iCol] + "='" + values[iCol] + "' "; 00239 } 00240 if (nullCols) { 00241 if (nullCols->size() > 0) { 00242 unsigned nNull = nullCols->size(); 00243 for (unsigned iNull = 0; iNull < nNull; iNull++) { 00244 ins += ", " + (*nullCols)[iNull] + "= NULL "; 00245 } 00246 } 00247 } 00248 00249 (*m_out) << std::endl << "# INSERT string is:" << std::endl; 00250 (*m_out) << ins << std::endl; 00251 m_out->flush(); 00252 00253 if (m_writeDisabled) { 00254 (*m_out) << "write to Db previously disabled; INSERT not sent" 00255 << std::endl; 00256 m_out->flush(); 00257 return true; 00258 } 00259 00260 int mysqlRet = mysql_query(m_mysql, ins.c_str()); 00261 00262 if (mysqlRet) { 00263 (*m_out) << "MySQL error during INSERT, code " << mysqlRet << std::endl; 00264 m_out->flush(); 00265 return false; 00266 } 00267 if (auto_value) { 00268 *auto_value = mysql_insert_id(m_mysql); 00269 } 00270 return true; 00271 }
|
|
Return true iff open has been done with no matching close.
Implements rdbModel::Connection. 00054 {return m_connected;}
|
|
Return true iff open has been done with no matching close.
Implements rdbModel::Connection. 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. |
|
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. 00190 { 00191 if (!m_connected) return MATCHnoConnection; 00192 00193 m_matchDbName = matchDbName; 00194 00195 // Check global characteristics; 00196 // Could do this via Manager; seems a bit artificial, bypass for now 00197 m_visitorType = VISITORmatch; 00198 m_matchReturn = MATCHequivalent; 00199 unsigned int ret = rdb->accept(this); 00200 00201 if ((ret == Visitor::VERROR) || (ret == Visitor::VERRORABORT)) { 00202 return MATCHfail; 00203 } 00204 else return m_matchReturn; 00205 }
|
|
Parameter is normally path for an xml file descrbing the connection parameters Implements rdbModel::Connection. |
|
Implements rdbModel::Connection. |
|
Parameter is normally path for an xml file descrbing the connection parameters Implements rdbModel::Connection. 00162 { 00163 using XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument; 00164 using XERCES_CPP_NAMESPACE_QUALIFIER DOMElement; 00165 xmlBase::XmlParser parser; 00166 DOMDocument* doc = parser.parse(parms.c_str(), "mysqlConnection"); 00167 if (doc == 0) { 00168 (*m_err) << "parse of connection parameters failed" << std::endl; 00169 m_err->flush(); 00170 return false; 00171 } 00172 DOMElement* conn = doc->getDocumentElement(); 00173 00174 std::string host = xmlBase::Dom::getAttribute(conn, "host"); 00175 std::string user = xmlBase::Dom::getAttribute(conn, "user"); 00176 std::string password = xmlBase::Dom::getAttribute(conn, "password"); 00177 std::string dbname = xmlBase::Dom::getAttribute(conn, "dbname"); 00178 00179 if (password.size() == 0 ) { // prompt for password? 00180 (*m_out) << "interactive login NYI " << std::endl; 00181 m_out->flush(); 00182 return false; 00183 } 00184 00185 return this->open(host, user, password, dbname); 00186 }
|
|
Implements rdbModel::Connection. 00099 { 00100 // , unsigned int port) { 00101 if (dbName.size() == 0) { 00102 (*m_err) << 00103 "rdbModel::MysqlConnection::open : null db name not allowed!" << 00104 std::endl; 00105 m_err->flush(); 00106 return false; 00107 } 00108 //huangb add 00109 m_host = host; 00110 m_user = user; 00111 m_password = password; 00112 00113 m_mysql = new MYSQL; 00114 mysql_init(m_mysql); 00115 00116 // 'host' argument is of the form hostname[:port] 00117 // That is, port section is optional. If not supplied, use 00118 // default port. 00119 std::string hostOnly; 00120 int port = 0; 00121 unsigned int colonLoc = host.find(":"); 00122 if (colonLoc == std::string::npos) { 00123 hostOnly = host; 00124 } 00125 else { 00126 hostOnly = host.substr(0, colonLoc); 00127 std::string portString = host.substr(colonLoc+1); 00128 try { 00129 port = facilities::Util::stringToInt(portString); 00130 } 00131 catch (facilities::WrongType ex) { 00132 (*m_err) << "From MysqlConnection::connect. Bad port: " 00133 << ex.getMsg() << std::endl; 00134 m_err->flush(); 00135 return false; 00136 } 00137 00138 } 00139 // mysql_init(m_mysql); 00140 std::cout<<"host is:"<<hostOnly.c_str()<<"::use is:: "<<user.c_str()<<":pass is::"<<password.c_str()<<":db is::"<<dbName.c_str()<<std::endl; 00141 MYSQL *connected = mysql_real_connect(m_mysql, hostOnly.c_str(), 00142 user.c_str(), 00143 password.c_str(), dbName.c_str(), 00144 3306, NULL, 0); 00145 00146 if (connected != 0) { // Everything is fine. Put out an info message 00147 (*m_out) << "Successfully connected to MySQL host " << 00148 host << ", database " << dbName << std::endl; 00149 m_out->flush(); 00150 m_connected = true; 00151 m_dbName = dbName; 00152 } 00153 else { 00154 (*m_err) << "Failed to connect to MySQL host " << host << 00155 "with error:::: " << mysql_error(m_mysql) << std::endl; 00156 m_err->flush(); 00157 m_connected = false; 00158 } 00159 return m_connected; 00160 }
|
|
Support only for relatively simple SELECT, involving just one table.
Implements rdbModel::Connection. |
|
Support only for relatively simple SELECT, involving just one table.
Implements rdbModel::Connection. 00334 { 00335 std::string sqlString = "SELECT "; 00336 unsigned nGet = getCols.size(); 00337 unsigned nOrder = orderCols.size(); 00338 00339 std::cout<<"tableName is:"<<tableName<<std::endl; 00340 00341 // tableName="metadata_v2r1"; 00342 00343 sqlString += getCols[0]; 00344 for (unsigned iGet = 1; iGet < nGet; iGet++) { 00345 sqlString += ","; 00346 sqlString += getCols[iGet]; 00347 } 00348 sqlString += " FROM " + tableName + " "; 00349 std::cout<<"sqlString is11:"<<sqlString<<std::endl; 00350 if (where != 0) { 00351 sqlString += " WHERE "; 00352 bool ret = compileAssertion(where, sqlString); 00353 if (!ret) return 0; 00354 } 00355 00356 std::cout<<"sqlString is22:"<<sqlString<<std::endl; 00357 00358 /*maqm if (nOrder > 0 ) { 00359 sqlString += " ORDER BY " + orderCols[0]; 00360 for (unsigned iOrder = 1; iOrder < nOrder; iOrder++) { 00361 sqlString += ","; 00362 sqlString += orderCols[iOrder]; 00363 } 00364 } 00365 */ 00366 // sqlString ="SELECT ser_no FROM metadata_v2r1 WHERE ((completion='OK') AND (instrument='LAT') AND (calib_type='MDC_t0') AND (flavor='vanilla'))"; 00367 if (rowLimit > 0) { 00368 // SQL format is LIMIT offset,limit or 00369 // LIMIT limit or 00370 // LIMIT limit OFFSET offset [don't use this one] 00371 sqlString += " LIMIT "; 00372 std::string limitStr; 00373 if (rowOffset > 0) { 00374 facilities::Util::itoa(rowOffset, limitStr); 00375 sqlString += limitStr + ","; 00376 } 00377 limitStr.clear(); 00378 facilities::Util::itoa(rowLimit, limitStr); 00379 std::cout<<"limitStr is:"<<limitStr<<std::endl; 00380 sqlString += limitStr; 00381 } 00382 00383 (*m_out) << std::endl << " # About to issue SELECT:" << std::endl; 00384 (*m_out) << sqlString << std::endl; 00385 m_out->flush(); 00386 //maqm add 00387 // sqlString="SELECT ser_no FROM metadata_v2r1"; 00388 00389 00390 int mysqlRet = mysql_query(m_mysql, sqlString.c_str()); 00391 if (mysqlRet) { 00392 std::string msg = 00393 "rdbModel::MysqlConnection::select: mysql_query error, code "; 00394 std::string codeString; 00395 facilities::Util::itoa(mysqlRet, codeString); 00396 msg += codeString; 00397 (*m_out) << std::endl << msg << std::endl; 00398 m_out->flush(); 00399 throw RdbException(msg, mysqlRet); 00400 return 0; 00401 } 00402 00403 MYSQL_RES *myres = mysql_store_result(m_mysql); 00404 MysqlResults* results = new MysqlResults(myres); 00405 return results; 00406 }
|
|
Generic UPDATE. Return value is number of rows changed. Implements rdbModel::Connection. |
|
Generic UPDATE. Return value is number of rows changed. Implements rdbModel::Connection. 00278 { 00279 00280 unsigned int nCol = colNames.size(); 00281 if (nCol != values.size()) { 00282 (*m_err) << "rdbModel::mysqlConnection::update: "; 00283 (*m_err) << "Incompatible vector arguments " << std::endl; 00284 m_err->flush(); 00285 return 0; 00286 } 00287 std::string sqlString = "UPDATE " + tableName + " SET "; 00288 sqlString += colNames[0] + " = '" + values[0] + "'"; 00289 for (unsigned int iCol = 1; iCol < nCol; iCol++) { 00290 sqlString += "," + colNames[iCol] + " = '" + values[iCol] + "'"; 00291 } 00292 if (nullCols) { 00293 unsigned nNull = nullCols->size(); 00294 for (unsigned iNull = 0; iNull < nNull; iNull++) { 00295 sqlString += ", " + (*nullCols)[iNull] + "= NULL "; 00296 } 00297 } 00298 00299 if (where) { 00300 sqlString += " WHERE "; 00301 bool ret = compileAssertion(where, sqlString); 00302 if (!ret) return 0; 00303 } 00304 (*m_out) << std::endl << "# UPDATE to be issued:" << std::endl; 00305 (*m_out) << sqlString << std::endl; 00306 m_out->flush(); 00307 if (m_writeDisabled) { 00308 (*m_out) << "write to Db previously disabled; UPDATE not sent" 00309 << std::endl; 00310 m_out->flush(); 00311 return 0; 00312 } 00313 int mysqlRet = mysql_query(m_mysql, sqlString.c_str()); 00314 00315 if (mysqlRet) { 00316 (*m_out) << "rdbModel::MysqlConnection::update: "; 00317 (*m_out) << "MySQL error during UPDATE, code " << mysqlRet << std::endl; 00318 m_out->flush(); 00319 return 0; 00320 } 00321 my_ulonglong nModLong = mysql_affected_rows(m_mysql); 00322 // Not much chance that we'll change more rows than will fit in just long 00323 unsigned nMod = nModLong; 00324 return nMod; 00325 00326 00327 }
|
|
Implements rdbModel::Visitor. |
|
Implements rdbModel::Visitor. 00840 {
00841 return Visitor::VCONTINUE;
00842 }
|
|
Implements rdbModel::Visitor. |
|
Implements rdbModel::Visitor. 00684 { 00685 std::string myName = col->getName(); 00686 if (m_colIx.find(myName) == m_colIx.end()) { 00687 m_matchReturn = MATCHfail; 00688 return Visitor::VERRORABORT; 00689 } 00690 unsigned int ix = m_colIx[myName]; 00691 mysql_data_seek(m_tempRes, ix); 00692 MYSQL_ROW colDescrip = mysql_fetch_row(m_tempRes); 00693 00694 // Type 00695 std::string sqlDtype = std::string(colDescrip[1]); 00696 Datatype* dtype = col->getDatatype(); 00697 if (!checkDType(dtype, sqlDtype)) { 00698 m_matchReturn = MATCHfail; 00699 (*m_out) << "Failed dtype match of col " << myName << std::endl; 00700 return Visitor::VERRORABORT; 00701 } 00702 00703 // Null 00704 bool nullable = (std::string(colDescrip[2]) == std::string("YES")); 00705 if (nullable != col->nullAllowed()) { 00706 m_matchReturn = MATCHfail; 00707 (*m_out) << "Failed null/not null match of col " << myName << std::endl; 00708 return Visitor::VERRORABORT; 00709 } 00710 // Key (PRI for primary, MUL if first in a multiple-field key 00711 // Save primary key info, if any 00712 if (std::string(colDescrip[3]) == std::string("PRI")) { 00713 m_primColName = myName; 00714 } 00715 00716 // Field 4 is default 00717 // Extra (may say auto_increment) 00718 bool autoInc = 00719 (std::string(colDescrip[5]) == std::string("auto_increment")); 00720 if (autoInc != col->isAutoIncrement()) { 00721 m_matchReturn = MATCHfail; 00722 (*m_out) << "Failed isAutoIncrement match of col " << myName << std::endl; 00723 return Visitor::VERRORABORT; 00724 } 00725 return Visitor::VCONTINUE; 00726 }
|
|
Implements rdbModel::Visitor. |
|
Implements rdbModel::Visitor. 00835 { 00836 return Visitor::VCONTINUE; 00837 // might put something real here later 00838 }
|
|
Implements rdbModel::Visitor. |
|
Implements rdbModel::Visitor. 00844 {
00845 return Visitor::VCONTINUE;
00846 }
|
|
Implements rdbModel::Visitor. |
|
Implements rdbModel::Visitor. 00860 {
00861 return Visitor::VCONTINUE;
00862 }
|
|
Implements rdbModel::Visitor. |
|
Implements rdbModel::Visitor. 00852 {
00853 return Visitor::VCONTINUE;
00854 }
|
|
This method sets if the visitor is recursive or not.
Implements rdbModel::Visitor. |
|
This method sets if the visitor is recursive or not.
Implements rdbModel::Visitor. 00608 { 00609 00610 if (m_matchDbName) { 00611 if (m_dbName != rdb->getDbName()) { 00612 m_matchReturn = MATCHfail; 00613 return Visitor::VDONE; 00614 } 00615 } 00616 00617 unsigned int nLocal = rdb->getNTable(); 00618 00619 // Null pointer for 2nd argument means "list all tables" 00620 00621 MYSQL_RES* res = mysql_list_tables(m_mysql, 0); 00622 if (!res) { 00623 m_matchReturn = MATCHfail; 00624 return Visitor::VERRORABORT; 00625 } 00626 unsigned int nRemote = mysql_num_rows(res); 00627 mysql_free_result(res); 00628 00629 if (nRemote < nLocal) { 00630 m_matchReturn = MATCHfail; 00631 return Visitor::VDONE; 00632 } 00633 else if (nRemote > nLocal) m_matchReturn = MATCHcompatible; 00634 00635 // Tell Rdb about this 00636 rdb->setConnection(this); 00637 00638 return Visitor::VCONTINUE; 00639 }
|
|
Implements rdbModel::Visitor. |
|
Implements rdbModel::Visitor. 00856 {
00857 return Visitor::VCONTINUE;
00858 }
|
|
Implements rdbModel::Visitor. |
|
Implements rdbModel::Visitor. 00848 {
00849 return Visitor::VCONTINUE;
00850 }
|
|
Implements rdbModel::Visitor. |
|
Implements rdbModel::Visitor. 00641 { 00642 const std::string& tName = table->getName(); 00643 00644 // Result set will have all fields for the table 00645 if (m_tempRes) { 00646 mysql_free_result(m_tempRes); 00647 m_tempRes = 0; 00648 } 00649 m_primColName.clear(); 00650 00651 std::string query = "SHOW COLUMNS FROM " + tName; 00652 00653 (*m_out) << std::endl << "# About to issue SHOW COLUMNS request :" 00654 << std::endl; 00655 (*m_out) << query << std::endl; 00656 m_out->flush(); 00657 00658 int ret = mysql_query(m_mysql, query.c_str()); 00659 if (ret) { 00660 m_matchReturn = MATCHfail; 00661 return Visitor::VERRORABORT; 00662 } 00663 00664 m_tempRes = mysql_store_result(m_mysql); 00665 if (!m_tempRes) { 00666 m_matchReturn = MATCHfail; 00667 return Visitor::VERRORABORT; 00668 } 00669 // Result set is a table with fields "Field"(the name) "Type" "Null"(yes 00670 // or no) "Key" "Default", "Extra" 00671 // Make it easier for accept(Column* ) to find relevant information 00672 unsigned int nRow = mysql_num_rows(m_tempRes); 00673 m_colIx.clear(); 00674 for (unsigned iRow = 0; iRow < nRow; iRow++) { 00675 MYSQL_ROW colDescrip = mysql_fetch_row(m_tempRes); 00676 std::string name = std::string(colDescrip[0]); 00677 std::cout<<"name is:"<<name<<std::endl; 00678 m_colIx[name] = iRow; 00679 } 00680 return Visitor::VCONTINUE; 00681 00682 }
|
|
Index by colname; data is row number with "SHOW COLUMNS.." result set.
|
|
Index by colname; data is row number with "SHOW COLUMNS.." result set.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Keep track of status during matching process.
|
|
|
|
|
|
Also save list of columns we ("service") are responsible for Could organize this by table, or just use Column::getTableName() |
|
Also save list of columns we ("service") are responsible for Could organize this by table, or just use Column::getTableName() |
|
|
|
|
|
|
|
|
|
If successful match, save pointer to schema for use with smart insert.
|
|
If successful match, save pointer to schema for use with smart insert.
|
|
For query results while visiting.
|
|
For query results while visiting.
|
|
|
|
|
|
|