00001
00002 #ifdef WIN32
00003 #include <windows.h>
00004 #endif
00005
00006 #include "rdbModel/Db/MysqlConnection.h"
00007 #include "rdbModel/Rdb.h"
00008 #include "rdbModel/Tables/Table.h"
00009 #include "rdbModel/Tables/Assertion.h"
00010 #include "rdbModel/Tables/Column.h"
00011 #include "rdbModel/Tables/Datatype.h"
00012 #include "rdbModel/Db/MysqlResults.h"
00013 #include "rdbModel/RdbException.h"
00014 #include "facilities/Util.h"
00015
00016 #include "xmlBase/XmlParser.h"
00017 #include "xmlBase/Dom.h"
00018
00019 #include "mysql.h"
00020 #include <iostream>
00021 #include <stdio.h>
00022 #include <unistd.h>
00023 #include "facilities/Util.h"
00024 namespace {
00025
00026
00027
00028 int extractSize(const std::string& sqlString) {
00029 std::string::size_type leftLoc = sqlString.find("(");
00030 if (leftLoc == std::string::npos) return 0;
00031 leftLoc++;
00032 std::string::size_type rightLoc = sqlString.find(",");
00033 if (rightLoc == std::string::npos) {
00034 rightLoc = sqlString.find(")");
00035 }
00036 std::string numString =
00037 sqlString.substr(leftLoc, rightLoc - leftLoc);
00038 return facilities::Util::stringToInt(numString);
00039 }
00040
00041 void addArg(bool literal, const std::string arg, std::string& sqlString) {
00042 if (literal) sqlString += '"';
00043 sqlString += arg;
00044 if (literal) sqlString += '"';
00045 return;
00046 }
00047
00048 bool compareEnumList(const std::vector<std::string>& choices,
00049 std::string sqlType) {
00050
00051 std::string::size_type locComma = sqlType.find(",");
00052 unsigned nComma = 0;
00053 while (locComma != std::string::npos) {
00054 nComma++;
00055 locComma = sqlType.find(",", locComma+1);
00056 }
00057 unsigned nChoice = choices.size();
00058 if (nChoice != (nComma + 1)) return false;
00059 for (unsigned iChoice = 0; iChoice < nChoice; iChoice++) {
00060 std::string::size_type loc = sqlType.find(choices[iChoice]);
00061 if (loc == std::string::npos) return false;
00062 }
00063 return true;
00064 }
00065 }
00066
00067 namespace rdbModel {
00068 bool MysqlConnection::m_compileInit = false;
00069
00070 MysqlConnection::MysqlConnection(std::ostream* out,
00071 std::ostream* errOut) :
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 }
00078
00079 bool MysqlConnection::close() {
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 }
00090
00091 MysqlConnection::~MysqlConnection() {
00092 close();
00093 delete m_mysql;
00094 return;
00095 }
00096
00097 bool MysqlConnection::open(const std::string& host,
00098 const std::string& user,
00099 const std::string& password,
00100 const std::string& dbName) {
00101
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
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
00118
00119
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
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) {
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 }
00162
00163 bool MysqlConnection::open(const std::string& parms) {
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 ) {
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 }
00188
00189
00190
00191 MATCH MysqlConnection::matchSchema(Rdb *rdb, bool matchDbName) {
00192 if (!m_connected) return MATCHnoConnection;
00193
00194 m_matchDbName = matchDbName;
00195
00196
00197
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 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 bool MysqlConnection::insertRow(const std::string& tableName,
00217 const StringVector& colNames,
00218 const StringVector& values,
00219 int* auto_value,
00220 const StringVector* nullCols) {
00221 std::string ins;
00222 if (auto_value) *auto_value = 0;
00223
00224
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
00234
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 }
00273
00274
00275 unsigned int MysqlConnection::update(const std::string& tableName,
00276 const StringVector& colNames,
00277 const StringVector& values,
00278 const Assertion* where,
00279 const StringVector* nullCols) {
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
00324 unsigned nMod = nModLong;
00325 return nMod;
00326
00327
00328 }
00329
00330 ResultHandle* MysqlConnection::select(const std::string& tableName,
00331 const StringVector& getCols,
00332 const StringVector& orderCols,
00333 const Assertion* where,
00334 int rowLimit,
00335 int rowOffset) {
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
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
00360
00361
00362
00363
00364
00365
00366
00367
00368 if (rowLimit > 0) {
00369
00370
00371
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
00388
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 }
00408
00409 ResultHandle* MysqlConnection::dbRequest(const std::string& request) {
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
00419 if (mysqlRet) {
00420
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
00448 if (mysql_field_count(m_mysql) == 0) {
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 }
00462
00463 bool MysqlConnection::compileAssertion(const Assertion* a,
00464 std::string& sqlString) const {
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 }
00478
00479 std::string opSymbols[OPTYPElast];
00480
00481 void MysqlConnection::compileInit() {
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 }
00495
00496
00497
00498
00499
00500
00501
00502
00503
00510 bool MysqlConnection::compileComparison(Assertion::Operator* op,
00511 std::string& sqlString) {
00512 if (op->getToBe()) return false;
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 }
00534
00535 bool MysqlConnection::compileOperator(Assertion::Operator* op,
00536 std::string &sqlString) {
00537
00538
00539 if (op->isCompareOp() ) return compileComparison(op, sqlString);
00540 if (op->getToBe()) return false;
00541 bool ret = true;
00542
00543 const std::vector<Assertion::Operator*>& children = op->getChildren();
00544 unsigned nChild = children.size();
00545
00546
00547
00548 if (nChild <= 1) {
00549 sqlString += opSymbols[op->getOpType()];
00550
00551
00552 if (op->getOpType() == OPTYPEexists) {
00553 sqlString += "(SELECT * FROM " + op->getTableName();
00554 if (!nChild) {
00555 sqlString += ")";
00556 return ret;
00557 }
00558
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
00570 if (op->getOpType() == OPTYPEexists) sqlString += ")";
00571
00572
00573 return ret;
00574 }
00575
00576
00577
00578
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
00602 sqlString += ")";
00603 return ret;
00604 }
00605
00606
00607
00608
00609 Visitor::VisitorState MysqlConnection::visitRdb(Rdb *rdb) {
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
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
00637 rdb->setConnection(this);
00638
00639 return Visitor::VCONTINUE;
00640 }
00641
00642 Visitor::VisitorState MysqlConnection::visitTable(Table* table) {
00643 const std::string& tName = table->getName();
00644
00645
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
00671
00672
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 }
00684
00685 Visitor::VisitorState MysqlConnection::visitColumn(Column* col) {
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
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
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
00712
00713 if (std::string(colDescrip[3]) == std::string("PRI")) {
00714 m_primColName = myName;
00715 }
00716
00717
00718
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 }
00728
00729 bool MysqlConnection::checkDType(Datatype* dtype,
00730 const std::string& sqlType) {
00731 std::string base;
00732 int sqlSize;
00733 if (dtype->getType() != Datatype::TYPEenum) {
00734 sqlSize = extractSize(sqlType);
00735 }
00736
00737
00738
00739
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
00749
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
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
00775 if (!sqlSize) sqlSize = 1;
00776
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: {
00817
00818 m_matchReturn = MATCHfail;
00819 return false;
00820 }
00821 }
00822 if (sqlType.find(base) != 0) {
00823 m_matchReturn = MATCHfail;
00824 return false;
00825 }
00826
00827 if (sqlSize != dtype->getOutputSize()) {
00828 m_matchReturn = MATCHcompatible;
00829 }
00830
00831 return true;
00832 }
00833
00834
00835
00836 Visitor::VisitorState MysqlConnection::visitIndex(Index* ) {
00837 return Visitor::VCONTINUE;
00838
00839 }
00840
00841 Visitor::VisitorState MysqlConnection::visitAssertion(Assertion*) {
00842 return Visitor::VCONTINUE;
00843 }
00844
00845 Visitor::VisitorState MysqlConnection::visitInsertNew(InsertNew*) {
00846 return Visitor::VCONTINUE;
00847 }
00848
00849 Visitor::VisitorState MysqlConnection::visitSupersede(Supersede*) {
00850 return Visitor::VCONTINUE;
00851 }
00852
00853 Visitor::VisitorState MysqlConnection::visitQuery(Query*) {
00854 return Visitor::VCONTINUE;
00855 }
00856
00857 Visitor::VisitorState MysqlConnection::visitSet(Set*) {
00858 return Visitor::VCONTINUE;
00859 }
00860
00861 Visitor::VisitorState MysqlConnection::visitInterRow(InterRow*) {
00862 return Visitor::VCONTINUE;
00863 }
00864
00865
00866 }