6#include "rdbModel/Db/MysqlConnection.h"
7#include "rdbModel/Rdb.h"
8#include "rdbModel/Tables/Table.h"
9#include "rdbModel/Tables/Assertion.h"
10#include "rdbModel/Tables/Column.h"
11#include "rdbModel/Tables/Datatype.h"
12#include "rdbModel/Db/MysqlResults.h"
13#include "rdbModel/RdbException.h"
14#include "facilities/Util.h"
16#include "xmlBase/XmlParser.h"
17#include "xmlBase/Dom.h"
23#include "facilities/Util.h"
28 int extractSize(
const std::string& sqlString) {
29 std::string::size_type leftLoc = sqlString.find(
"(");
30 if (leftLoc == std::string::npos)
return 0;
32 std::string::size_type rightLoc = sqlString.find(
",");
33 if (rightLoc == std::string::npos) {
34 rightLoc = sqlString.find(
")");
36 std::string numString =
37 sqlString.substr(leftLoc, rightLoc - leftLoc);
41 void addArg(
bool literal,
const std::string
arg, std::string& sqlString) {
42 if (literal) sqlString +=
'"';
44 if (literal) sqlString +=
'"';
48 bool compareEnumList(
const std::vector<std::string>& choices,
49 std::string sqlType) {
51 std::string::size_type locComma = sqlType.find(
",");
53 while (locComma != std::string::npos) {
55 locComma = sqlType.find(
",", locComma+1);
57 unsigned nChoice = choices.size();
58 if (nChoice != (nComma + 1))
return false;
59 for (
unsigned iChoice = 0; iChoice < nChoice; iChoice++) {
60 std::string::size_type loc = sqlType.find(choices[iChoice]);
61 if (loc == std::string::npos)
return false;
68 bool MysqlConnection::m_compileInit =
false;
71 std::ostream* errOut) :
72 m_mysql(0), m_connected(0),
m_out(out), m_err(errOut),
73 m_visitorType(VISITORundefined), m_rdb(0), m_tempRes(0),
74 m_writeDisabled(
false) {
75 if (m_out == 0) m_out = &std::cout;
76 if (m_err == 0) m_err = &std::cerr;
81 mysql_free_result(m_tempRes);
84 std::cout<<
"close connection ================================"<<std::endl;
98 const std::string& user,
99 const std::string& password,
100 const std::string& dbName) {
102 if (dbName.size() == 0) {
104 "rdbModel::MysqlConnection::open : null db name not allowed!" <<
112 m_password = password;
120 std::string hostOnly;
122 std::string::size_type colonLoc = host.find(
":");
123 if (colonLoc == std::string::npos) {
127 hostOnly = host.substr(0, colonLoc);
128 std::string portString = host.substr(colonLoc+1);
133 (*m_err) <<
"From MysqlConnection::connect. Bad port: "
134 << ex.
getMsg() << std::endl;
141 std::cout<<
"host is:"<<hostOnly.c_str()<<
"::use is:: "<<user.c_str()<<
":pass is::"<<password.c_str()<<
":db is::"<<dbName.c_str()<<std::endl;
142 MYSQL *connected = mysql_real_connect(m_mysql, hostOnly.c_str(),
144 password.c_str(), dbName.c_str(),
147 if (connected != 0) {
148 (*m_out) <<
"Successfully connected to MySQL host " <<
149 host <<
", database " << dbName << std::endl;
155 (*m_err) <<
"Failed to connect to MySQL host " << host <<
156 "with error:::: " << mysql_error(m_mysql) << std::endl;
164 using XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument;
165 using XERCES_CPP_NAMESPACE_QUALIFIER DOMElement;
167 DOMDocument* doc = parser.
parse(parms.c_str(),
"mysqlConnection");
169 (*m_err) <<
"parse of connection parameters failed" << std::endl;
173 DOMElement* conn = doc->getDocumentElement();
180 if (password.size() == 0 ) {
181 (*m_out) <<
"interactive login NYI " << std::endl;
186 return this->
open(host, user, password, dbname);
194 m_matchDbName = matchDbName;
198 m_visitorType = VISITORmatch;
200 unsigned int ret = rdb->
accept(
this);
205 else return m_matchReturn;
222 if (auto_value) *auto_value = 0;
225 unsigned nCol = colNames.size();
226 if (!nCol || (nCol != values.size() ) ) {
227 (*m_err) <<
" MysqlConnection::insertRow: vector lengths incompatible"
236 ins +=
"insert into " + tableName;
237 ins +=
" set " + colNames[0] +
"='" + values[0] +
"' ";
238 for (
unsigned iCol = 1; iCol < nCol; iCol++) {
239 ins +=
", " + colNames[iCol] +
"='" + values[iCol] +
"' ";
242 if (nullCols->size() > 0) {
243 unsigned nNull = nullCols->size();
244 for (
unsigned iNull = 0; iNull < nNull; iNull++) {
245 ins +=
", " + (*nullCols)[iNull] +
"= NULL ";
250 (*m_out) << std::endl <<
"# INSERT string is:" << std::endl;
251 (*m_out) << ins << std::endl;
254 if (m_writeDisabled) {
255 (*m_out) <<
"write to Db previously disabled; INSERT not sent"
261 int mysqlRet = mysql_query(m_mysql, ins.c_str());
264 (*m_out) <<
"MySQL error during INSERT, code " << mysqlRet << std::endl;
269 *auto_value = mysql_insert_id(m_mysql);
281 unsigned int nCol = colNames.size();
282 if (nCol != values.size()) {
283 (*m_err) <<
"rdbModel::mysqlConnection::update: ";
284 (*m_err) <<
"Incompatible vector arguments " << std::endl;
288 std::string sqlString =
"UPDATE " + tableName +
" SET ";
289 sqlString += colNames[0] +
" = '" + values[0] +
"'";
290 for (
unsigned int iCol = 1; iCol < nCol; iCol++) {
291 sqlString +=
"," + colNames[iCol] +
" = '" + values[iCol] +
"'";
294 unsigned nNull = nullCols->size();
295 for (
unsigned iNull = 0; iNull < nNull; iNull++) {
296 sqlString +=
", " + (*nullCols)[iNull] +
"= NULL ";
301 sqlString +=
" WHERE ";
305 (*m_out) << std::endl <<
"# UPDATE to be issued:" << std::endl;
306 (*m_out) << sqlString << std::endl;
308 if (m_writeDisabled) {
309 (*m_out) <<
"write to Db previously disabled; UPDATE not sent"
314 int mysqlRet = mysql_query(m_mysql, sqlString.c_str());
317 (*m_out) <<
"rdbModel::MysqlConnection::update: ";
318 (*m_out) <<
"MySQL error during UPDATE, code " << mysqlRet << std::endl;
322 my_ulonglong nModLong = mysql_affected_rows(m_mysql);
324 unsigned nMod = nModLong;
336 std::string sqlString =
"SELECT ";
337 unsigned nGet = getCols.size();
338 unsigned nOrder = orderCols.size();
340 std::cout<<
"tableName is:"<<tableName<<std::endl;
344 sqlString += getCols[0];
345 for (
unsigned iGet = 1; iGet < nGet; iGet++) {
347 sqlString += getCols[iGet];
349 sqlString +=
" FROM " + tableName +
" ";
350 std::cout<<
"sqlString is11:"<<sqlString<<std::endl;
352 sqlString +=
" WHERE ";
357 std::cout<<
"sqlString is22:"<<sqlString<<std::endl;
372 sqlString +=
" LIMIT ";
373 std::string limitStr;
376 sqlString += limitStr +
",";
380 std::cout<<
"limitStr is:"<<limitStr<<std::endl;
381 sqlString += limitStr;
384 (*m_out) << std::endl <<
" # About to issue SELECT:" << std::endl;
385 (*m_out) << sqlString << std::endl;
391 int mysqlRet = mysql_query(m_mysql, sqlString.c_str());
394 "rdbModel::MysqlConnection::select: mysql_query error, code ";
395 std::string codeString;
398 (*m_out) << std::endl << msg << std::endl;
404 MYSQL_RES *myres = mysql_store_result(m_mysql);
411 (*m_out) << std::endl <<
"# About to issue SQL request:" << std::endl;
412 (*m_out) << request << std::endl;
416 int mysqlRet = mysql_query(m_mysql, request.c_str());
422 "rdbModel::MysqlConnection::dbRequest: mysql_query error, code ";
423 std::string codeString;
426 (*m_out) << std::endl <<i<<
"times not connected++++ "<< msg << std::endl;
428 fprintf(stderr,
"mysql_query error %d: %s\n",mysql_errno(m_mysql),mysql_error(m_mysql));
433 mysql_close(m_mysql);
436 bool st =
open(m_host,m_user,m_password,m_dbName);
437 if(st==
false)
continue;
438 mysqlRet = mysql_query(m_mysql, request.c_str());
445 MYSQL_RES *myres = mysql_store_result(m_mysql);
448 if (mysql_field_count(m_mysql) == 0) {
453 "rdbModel::MysqlConnection::dbRequest: expected data; none returned";
454 (*m_out) << std::endl << msg << std::endl;
464 std::string& sqlString)
const {
465 if (!m_compileInit) {
467 m_compileInit =
true;
470 return compileOperator(a->
getOperator(), sqlString);
473 (*m_out) << std::endl << ex.
getMsg() << std::endl;
481 void MysqlConnection::compileInit() {
510 bool MysqlConnection::compileComparison(Assertion::Operator* op,
511 std::string& sqlString) {
512 if (op->getToBe())
return false;
514 OPTYPE opType = op->getOpType();
517 sqlString += op->getCompareArgs()[0];
524 bool literal0 = (op->getCompareArgTypes()[0] ==
FIELDTYPElit);
525 bool literal1 = (op->getCompareArgTypes()[1] ==
FIELDTYPElit);
527 addArg(literal0, op->getCompareArgs()[0], sqlString);
529 addArg(literal1, op->getCompareArgs()[1], sqlString);
535 bool MysqlConnection::compileOperator(Assertion::Operator* op,
536 std::string &sqlString) {
539 if (op->isCompareOp() )
return compileComparison(op, sqlString);
540 if (op->getToBe())
return false;
543 const std::vector<Assertion::Operator*>& children = op->getChildren();
544 unsigned nChild = children.size();
553 sqlString +=
"(SELECT * FROM " + op->getTableName();
559 sqlString +=
" WHERE(";
561 ret = compileOperator(children[0], sqlString);
564 "rdbModel::MysqlConnection::compileOperator failed for operator "
566 throw RdbException(msg);
581 std::string symbol =
opSymbols[op->getOpType()];
583 ret = compileOperator(children[0], sqlString);
586 "rdbModel::MysqlConnection::compileOperator failed for operator "
588 throw RdbException(msg);
590 for (
unsigned int iChild = 1; iChild < nChild; iChild++) {
593 ret = compileOperator(children[iChild], sqlString);
596 "rdbModel::MysqlConnection::compileOperator failed for operator "
598 throw RdbException(msg);
622 MYSQL_RES* res = mysql_list_tables(m_mysql, 0);
627 unsigned int nRemote = mysql_num_rows(res);
628 mysql_free_result(res);
630 if (nRemote < nLocal) {
643 const std::string& tName = table->
getName();
647 mysql_free_result(m_tempRes);
650 m_primColName.clear();
652 std::string query =
"SHOW COLUMNS FROM " + tName;
654 (*m_out) << std::endl <<
"# About to issue SHOW COLUMNS request :"
656 (*m_out) << query << std::endl;
659 int ret = mysql_query(m_mysql, query.c_str());
665 m_tempRes = mysql_store_result(m_mysql);
673 unsigned int nRow = mysql_num_rows(m_tempRes);
675 for (
unsigned iRow = 0; iRow < nRow; iRow++) {
676 MYSQL_ROW colDescrip = mysql_fetch_row(m_tempRes);
677 std::string name = std::string(colDescrip[0]);
678 std::cout<<
"name is:"<<name<<std::endl;
679 m_colIx[name] = iRow;
686 std::string myName = col->
getName();
687 if (m_colIx.find(myName) == m_colIx.end()) {
691 unsigned int ix = m_colIx[myName];
692 mysql_data_seek(m_tempRes,
ix);
693 MYSQL_ROW colDescrip = mysql_fetch_row(m_tempRes);
696 std::string sqlDtype = std::string(colDescrip[1]);
698 if (!checkDType(dtype, sqlDtype)) {
700 (*m_out) <<
"Failed dtype match of col " << myName << std::endl;
705 bool nullable = (std::string(colDescrip[2]) == std::string(
"YES"));
708 (*m_out) <<
"Failed null/not null match of col " << myName << std::endl;
713 if (std::string(colDescrip[3]) == std::string(
"PRI")) {
714 m_primColName = myName;
720 (std::string(colDescrip[5]) == std::string(
"auto_increment"));
723 (*m_out) <<
"Failed isAutoIncrement match of col " << myName << std::endl;
729 bool MysqlConnection::checkDType(
Datatype* dtype,
730 const std::string& sqlType) {
734 sqlSize = extractSize(sqlType);
743 if (sqlType.find(base) != 0) {
747 Enum* ourEnum = dtype->
getEnum();
750 return compareEnumList(ourEnum->getChoices(), sqlType);
754 if (sqlType.find(base) != 0) {
759 if (sqlSize < dtype->getOutputSize()) {
770 if (sqlType.find(base) != 0) {
775 if (!sqlSize) sqlSize = 1;
777 if (sqlSize < dtype->getOutputSize()) {
787 if (sqlType !=
"datetime") {
822 if (sqlType.find(base) != 0) {
*******DOUBLE PRECISION m_EGridB INTEGER m_out
struct st_mysql_res MYSQL_RES
double arg(const EvtComplex &c)
static int stringToInt(const std::string &InStr)
static const char * itoa(int val, std::string &outStr)
Exception class used when converting from string to numeric type.
Operator * getOperator() const
Datatype * getDatatype() const
bool isAutoIncrement() const
const std::string & getName() const
bool nullAllowed() const
Returns true if column may take on value NULL.
int getOutputSize() const
virtual VisitorState visitInterRow(InterRow *)
virtual Visitor::VisitorState visitRdb(Rdb *)
This method says if the visitor is recursive or not.
virtual Visitor::VisitorState visitAssertion(Assertion *)
virtual VisitorState visitQuery(Query *)
virtual VisitorState visitSet(Set *)
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 Visitor::VisitorState visitTable(Table *)
virtual Visitor::VisitorState visitIndex(Index *)
virtual bool compileAssertion(const Assertion *a, std::string &sqlString) const
virtual VisitorState visitSupersede(Supersede *)
virtual ResultHandle * dbRequest(const std::string &request)
virtual VisitorState visitInsertNew(InsertNew *)
virtual ~MysqlConnection()
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 Visitor::VisitorState visitColumn(Column *)
virtual unsigned int update(const std::string &tableName, const StringVector &colNames, const StringVector &values, const Assertion *where=0, const StringVector *nullCols=0)
MysqlConnection(std::ostream *out=0, std::ostream *errOut=0)
virtual std::string getMsg()
const std::string & getDbName()
unsigned int getNTable() const
void setConnection(Connection *connection)
unsigned int accept(Visitor *v)
This is the recursive accept for the visitor pattern.
const std::string & getName() const
static std::string getAttribute(const DOMElement *elt, const char *attName)
DOMDocument * parse(const char *const filename, const std::string &docType=std::string(""))
Parse an xml file, returning document node if successful.
std::vector< std::string > StringVector
std::string opSymbols[OPTYPElast]