BOSS 6.6.4.p01
BESIII Offline Software System
Loading...
Searching...
No Matches
MysqlConnection.cxx
Go to the documentation of this file.
1// $Header: /bes/bes/BossCvs/Calibration/rdbModel/src/Db/MysqlConnection.cxx,v 1.11 2011/02/22 06:16:29 maqm Exp $
2#ifdef WIN32
3#include <windows.h>
4#endif
5
7#include "rdbModel/Rdb.h"
14#include "facilities/Util.h"
15
16#include "xmlBase/XmlParser.h"
17#include "xmlBase/Dom.h"
18
19#include "mysql.h"
20#include <iostream>
21#include <unistd.h>
22#include "facilities/Util.h"
23namespace {
24
25 // Size specification is of form (m) or (m,d) If no size specification
26 // return 0; else return value of m.
27 int extractSize(const std::string& sqlString) {
28 std::string::size_type leftLoc = sqlString.find("(");
29 if (leftLoc == std::string::npos) return 0;
30 leftLoc++; // now is at start of m
31 std::string::size_type rightLoc = sqlString.find(",");
32 if (rightLoc == std::string::npos) {
33 rightLoc = sqlString.find(")");
34 }
35 std::string numString =
36 sqlString.substr(leftLoc, rightLoc - leftLoc);
37 return facilities::Util::stringToInt(numString);
38 }
39
40 void addArg(bool literal, const std::string arg, std::string& sqlString) {
41 if (literal) sqlString += '"';
42 sqlString += arg;
43 if (literal) sqlString += '"';
44 return;
45 }
46
47 bool compareEnumList(const std::vector<std::string>& choices,
48 std::string sqlType) {
49 // Number has to be the same.
50 std::string::size_type locComma = sqlType.find(",");
51 unsigned nComma = 0;
52 while (locComma != std::string::npos) {
53 nComma++;
54 locComma = sqlType.find(",", locComma+1);
55 }
56 unsigned nChoice = choices.size();
57 if (nChoice != (nComma + 1)) return false;
58 for (unsigned iChoice = 0; iChoice < nChoice; iChoice++) {
59 std::string::size_type loc = sqlType.find(choices[iChoice]);
60 if (loc == std::string::npos) return false;
61 }
62 return true;
63 }
64}
65
66namespace rdbModel {
67 bool MysqlConnection::m_compileInit = false;
68
70 std::ostream* errOut) :
71 m_mysql(0), m_connected(0), m_out(out), m_err(errOut),
72 m_visitorType(VISITORundefined), m_rdb(0), m_tempRes(0),
73 m_writeDisabled(false) {
74 if (m_out == 0) m_out = &std::cout;
75 if (m_err == 0) m_err = &std::cerr;
76 }
77
79 if (m_tempRes) {
80 mysql_free_result(m_tempRes);
81 m_tempRes = 0;
82 }
83 std::cout<<"close connection ================================"<<std::endl;
84 mysql_close(m_mysql);
85 m_mysql = 0;
86 m_connected = false;
87 return true;
88 }
89
91 close();
92 delete m_mysql;
93 return;
94 }
95
96 bool MysqlConnection::open(const std::string& host,
97 const std::string& user,
98 const std::string& password,
99 const std::string& dbName) {
100 // , unsigned int port) {
101 if (dbName.size() == 0) {
102 (*m_err) <<
103 "rdbModel::MysqlConnection::open : null db name not allowed!" <<
104 std::endl;
105 m_err->flush();
106 return false;
107 }
108 //huangb add
109 m_host = host;
110 m_user = user;
111 m_password = password;
112
113 m_mysql = new MYSQL;
114 mysql_init(m_mysql);
115
116 // 'host' argument is of the form hostname[:port]
117 // That is, port section is optional. If not supplied, use
118 // default port.
119 std::string hostOnly;
120 int port = 0;
121 std::string::size_type colonLoc = host.find(":");
122 if (colonLoc == std::string::npos) {
123 hostOnly = host;
124 }
125 else {
126 hostOnly = host.substr(0, colonLoc);
127 std::string portString = host.substr(colonLoc+1);
128 try {
129 port = facilities::Util::stringToInt(portString);
130 }
131 catch (facilities::WrongType ex) {
132 (*m_err) << "From MysqlConnection::connect. Bad port: "
133 << ex.getMsg() << std::endl;
134 m_err->flush();
135 return false;
136 }
137
138 }
139 // mysql_init(m_mysql);
140 std::cout<<"host is:"<<hostOnly.c_str()<<"::use is:: "<<user.c_str()<<":pass is::"<<password.c_str()<<":db is::"<<dbName.c_str()<<std::endl;
141 MYSQL *connected = mysql_real_connect(m_mysql, hostOnly.c_str(),
142 user.c_str(),
143 password.c_str(), dbName.c_str(),
144 3306, NULL, 0);
145
146 if (connected != 0) { // Everything is fine. Put out an info message
147 (*m_out) << "Successfully connected to MySQL host " <<
148 host << ", database " << dbName << std::endl;
149 m_out->flush();
150 m_connected = true;
151 m_dbName = dbName;
152 }
153 else {
154 (*m_err) << "Failed to connect to MySQL host " << host <<
155 "with error:::: " << mysql_error(m_mysql) << std::endl;
156 m_err->flush();
157 m_connected = false;
158 }
159 return m_connected;
160 }
161
162 bool MysqlConnection::open(const std::string& parms) {
163 using XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument;
164 using XERCES_CPP_NAMESPACE_QUALIFIER DOMElement;
165 xmlBase::XmlParser parser;
166 DOMDocument* doc = parser.parse(parms.c_str(), "mysqlConnection");
167 if (doc == 0) {
168 (*m_err) << "parse of connection parameters failed" << std::endl;
169 m_err->flush();
170 return false;
171 }
172 DOMElement* conn = doc->getDocumentElement();
173
174 std::string host = xmlBase::Dom::getAttribute(conn, "host");
175 std::string user = xmlBase::Dom::getAttribute(conn, "user");
176 std::string password = xmlBase::Dom::getAttribute(conn, "password");
177 std::string dbname = xmlBase::Dom::getAttribute(conn, "dbname");
178
179 if (password.size() == 0 ) { // prompt for password?
180 (*m_out) << "interactive login NYI " << std::endl;
181 m_out->flush();
182 return false;
183 }
184
185 return this->open(host, user, password, dbname);
186 }
187
188
189
190 MATCH MysqlConnection::matchSchema(Rdb *rdb, bool matchDbName) {
191 if (!m_connected) return MATCHnoConnection;
192
193 m_matchDbName = matchDbName;
194
195 // Check global characteristics;
196 // Could do this via Manager; seems a bit artificial, bypass for now
197 m_visitorType = VISITORmatch;
198 m_matchReturn = MATCHequivalent;
199 unsigned int ret = rdb->accept(this);
200
201 if ((ret == Visitor::VERROR) || (ret == Visitor::VERRORABORT)) {
202 return MATCHfail;
203 }
204 else return m_matchReturn;
205 }
206
207
208
209 // For each table
210 // compare # of columns
211 // compare datatype description, other attributes of column
212 // compare indices
213
214
215 bool MysqlConnection::insertRow(const std::string& tableName,
216 const StringVector& colNames,
217 const StringVector& values,
218 int* auto_value,
219 const StringVector* nullCols) {
220 std::string ins;
221 if (auto_value) *auto_value = 0;
222
223 // check that sizes of vectors match
224 unsigned nCol = colNames.size();
225 if (!nCol || (nCol != values.size() ) ) {
226 (*m_err) << " MysqlConnection::insertRow: vector lengths incompatible"
227 << std::endl;
228 m_err->flush();
229 return false;
230 }
231
232 // caller should already have checked for validity and should
233 // have supplied all necessary columns
234
235 ins += "insert into " + tableName;
236 ins += " set " + colNames[0] + "='" + values[0] + "' ";
237 for (unsigned iCol = 1; iCol < nCol; iCol++) {
238 ins += ", " + colNames[iCol] + "='" + values[iCol] + "' ";
239 }
240 if (nullCols) {
241 if (nullCols->size() > 0) {
242 unsigned nNull = nullCols->size();
243 for (unsigned iNull = 0; iNull < nNull; iNull++) {
244 ins += ", " + (*nullCols)[iNull] + "= NULL ";
245 }
246 }
247 }
248
249 (*m_out) << std::endl << "# INSERT string is:" << std::endl;
250 (*m_out) << ins << std::endl;
251 m_out->flush();
252
253 if (m_writeDisabled) {
254 (*m_out) << "write to Db previously disabled; INSERT not sent"
255 << std::endl;
256 m_out->flush();
257 return true;
258 }
259
260 int mysqlRet = mysql_query(m_mysql, ins.c_str());
261
262 if (mysqlRet) {
263 (*m_out) << "MySQL error during INSERT, code " << mysqlRet << std::endl;
264 m_out->flush();
265 return false;
266 }
267 if (auto_value) {
268 *auto_value = mysql_insert_id(m_mysql);
269 }
270 return true;
271 }
272
273
274 unsigned int MysqlConnection::update(const std::string& tableName,
275 const StringVector& colNames,
276 const StringVector& values,
277 const Assertion* where,
278 const StringVector* nullCols) {
279
280 unsigned int nCol = colNames.size();
281 if (nCol != values.size()) {
282 (*m_err) << "rdbModel::mysqlConnection::update: ";
283 (*m_err) << "Incompatible vector arguments " << std::endl;
284 m_err->flush();
285 return 0;
286 }
287 std::string sqlString = "UPDATE " + tableName + " SET ";
288 sqlString += colNames[0] + " = '" + values[0] + "'";
289 for (unsigned int iCol = 1; iCol < nCol; iCol++) {
290 sqlString += "," + colNames[iCol] + " = '" + values[iCol] + "'";
291 }
292 if (nullCols) {
293 unsigned nNull = nullCols->size();
294 for (unsigned iNull = 0; iNull < nNull; iNull++) {
295 sqlString += ", " + (*nullCols)[iNull] + "= NULL ";
296 }
297 }
298
299 if (where) {
300 sqlString += " WHERE ";
301 bool ret = compileAssertion(where, sqlString);
302 if (!ret) return 0;
303 }
304 (*m_out) << std::endl << "# UPDATE to be issued:" << std::endl;
305 (*m_out) << sqlString << std::endl;
306 m_out->flush();
307 if (m_writeDisabled) {
308 (*m_out) << "write to Db previously disabled; UPDATE not sent"
309 << std::endl;
310 m_out->flush();
311 return 0;
312 }
313 int mysqlRet = mysql_query(m_mysql, sqlString.c_str());
314
315 if (mysqlRet) {
316 (*m_out) << "rdbModel::MysqlConnection::update: ";
317 (*m_out) << "MySQL error during UPDATE, code " << mysqlRet << std::endl;
318 m_out->flush();
319 return 0;
320 }
321 my_ulonglong nModLong = mysql_affected_rows(m_mysql);
322 // Not much chance that we'll change more rows than will fit in just long
323 unsigned nMod = nModLong;
324 return nMod;
325
326
327 }
328
329 ResultHandle* MysqlConnection::select(const std::string& tableName,
330 const StringVector& getCols,
331 const StringVector& orderCols,
332 const Assertion* where,
333 int rowLimit,
334 int rowOffset) {
335 std::string sqlString = "SELECT ";
336 unsigned nGet = getCols.size();
337 unsigned nOrder = orderCols.size();
338
339 std::cout<<"tableName is:"<<tableName<<std::endl;
340
341// tableName="metadata_v2r1";
342
343 sqlString += getCols[0];
344 for (unsigned iGet = 1; iGet < nGet; iGet++) {
345 sqlString += ",";
346 sqlString += getCols[iGet];
347 }
348 sqlString += " FROM " + tableName + " ";
349 std::cout<<"sqlString is11:"<<sqlString<<std::endl;
350 if (where != 0) {
351 sqlString += " WHERE ";
352 bool ret = compileAssertion(where, sqlString);
353 if (!ret) return 0;
354 }
355
356 std::cout<<"sqlString is22:"<<sqlString<<std::endl;
357
358 /*maqm if (nOrder > 0 ) {
359 sqlString += " ORDER BY " + orderCols[0];
360 for (unsigned iOrder = 1; iOrder < nOrder; iOrder++) {
361 sqlString += ",";
362 sqlString += orderCols[iOrder];
363 }
364 }
365 */
366// sqlString ="SELECT ser_no FROM metadata_v2r1 WHERE ((completion='OK') AND (instrument='LAT') AND (calib_type='MDC_t0') AND (flavor='vanilla'))";
367 if (rowLimit > 0) {
368 // SQL format is LIMIT offset,limit or
369 // LIMIT limit or
370 // LIMIT limit OFFSET offset [don't use this one]
371 sqlString += " LIMIT ";
372 std::string limitStr;
373 if (rowOffset > 0) {
374 facilities::Util::itoa(rowOffset, limitStr);
375 sqlString += limitStr + ",";
376 }
377 limitStr.clear();
378 facilities::Util::itoa(rowLimit, limitStr);
379 std::cout<<"limitStr is:"<<limitStr<<std::endl;
380 sqlString += limitStr;
381 }
382
383 (*m_out) << std::endl << " # About to issue SELECT:" << std::endl;
384 (*m_out) << sqlString << std::endl;
385 m_out->flush();
386 //maqm add
387// sqlString="SELECT ser_no FROM metadata_v2r1";
388
389
390 int mysqlRet = mysql_query(m_mysql, sqlString.c_str());
391 if (mysqlRet) {
392 std::string msg =
393 "rdbModel::MysqlConnection::select: mysql_query error, code ";
394 std::string codeString;
395 facilities::Util::itoa(mysqlRet, codeString);
396 msg += codeString;
397 (*m_out) << std::endl << msg << std::endl;
398 m_out->flush();
399 throw RdbException(msg, mysqlRet);
400 return 0;
401 }
402
403 MYSQL_RES *myres = mysql_store_result(m_mysql);
404 MysqlResults* results = new MysqlResults(myres);
405 return results;
406 }
407
408 ResultHandle* MysqlConnection::dbRequest(const std::string& request) {
409
410 (*m_out) << std::endl << "# About to issue SQL request:" << std::endl;
411 (*m_out) << request << std::endl;
412 m_out->flush();
413
414 int i=0;
415 int mysqlRet = mysql_query(m_mysql, request.c_str());
416 for (i=0;i<10;i++) {
417 // int mysqlRet = mysql_query(m_mysql, request.c_str());
418 if (mysqlRet) {
419 //not connected
420 std::string msg =
421 "rdbModel::MysqlConnection::dbRequest: mysql_query error, code ";
422 std::string codeString;
423 facilities::Util::itoa(mysqlRet, codeString);
424 msg += codeString;
425 (*m_out) << std::endl <<i<<"times not connected++++ "<< msg << std::endl;
426 m_out->flush();
427 fprintf(stderr, "mysql_query error %d: %s\n",mysql_errno(m_mysql),mysql_error(m_mysql));
428 if (i>=9){
429 throw RdbException(msg, mysqlRet);
430 return 0;
431 }
432 mysql_close(m_mysql);
433 m_mysql = 0;
434 sleep(100);
435 bool st = open(m_host,m_user,m_password,m_dbName);
436 if(st==false) continue;
437 mysqlRet = mysql_query(m_mysql, request.c_str());
438 }else{
439 break;
440 }
441 }
442
443
444 MYSQL_RES *myres = mysql_store_result(m_mysql);
445 if (!myres) {
446 // Was it supposed to return data?
447 if (mysql_field_count(m_mysql) == 0) { // no data expected
448 return 0;
449 }
450 else {
451 std::string msg =
452 "rdbModel::MysqlConnection::dbRequest: expected data; none returned";
453 (*m_out) << std::endl << msg << std::endl;
454 m_out->flush();
455 throw RdbException(msg);
456 return 0;
457 }
458 }
459 return new MysqlResults(myres);
460 }
461
463 std::string& sqlString) const {
464 if (!m_compileInit) {
465 compileInit();
466 m_compileInit = true;
467 }
468 try {
469 return compileOperator(a->getOperator(), sqlString);
470 }
471 catch (RdbException ex) {
472 (*m_out) << std::endl << ex.getMsg() << std::endl;
473 m_out->flush();
474 return false;
475 }
476 }
477
478 std::string opSymbols[OPTYPElast];
479
480 void MysqlConnection::compileInit() {
481 opSymbols[OPTYPEor] = " OR ";
482 opSymbols[OPTYPEand] = " AND ";
483 opSymbols[OPTYPEnot] = " NOT ";
484 opSymbols[OPTYPEexists] = "EXISTS ";
485 opSymbols[OPTYPEisNull] = " IS NULL";
486 opSymbols[OPTYPEequal] = "=";
492 return;
493 }
494
495
496
497 /*
498 Need significant changes here to deal with which="toBe" case
499 In that case, the output isn't going to be SQL; in fact, it's
500 not clear what it should be, exactly!
501 */
502
503 /** Result is appended to caller-supplied string
504 Convention is to use " " around literal values
505 Note no verification is done here; that operator is in fact a comparison
506 or isNull operator. This is called internally only and that check will
507 have been done before invoking this routine.
508 */
509 bool MysqlConnection::compileComparison(Assertion::Operator* op,
510 std::string& sqlString) {
511 if (op->getToBe()) return false; // can't compile
512
513 OPTYPE opType = op->getOpType();
514 if (opType == OPTYPEisNull) {
515 sqlString +="(";
516 sqlString += op->getCompareArgs()[0];
517 sqlString += opSymbols[opType];
518 sqlString += ")";
519 return true;
520 }
521 sqlString += "(";
522
523 bool literal0 = (op->getCompareArgTypes()[0] == FIELDTYPElit);
524 bool literal1 = (op->getCompareArgTypes()[1] == FIELDTYPElit);
525
526 addArg(literal0, op->getCompareArgs()[0], sqlString);
527 sqlString += opSymbols[opType];
528 addArg(literal1, op->getCompareArgs()[1], sqlString);
529 sqlString += ")";
530
531 return true;
532 }
533
534 bool MysqlConnection::compileOperator(Assertion::Operator* op,
535 std::string &sqlString) {
536
537 //maqm std::cout<<"in compileOperator() sqlString is00:"<<sqlString<<std::endl;
538 if (op->isCompareOp() ) return compileComparison(op, sqlString);
539 if (op->getToBe()) return false; // can't compile in this case
540 bool ret = true;
541
542 const std::vector<Assertion::Operator*>& children = op->getChildren();
543 unsigned nChild = children.size();
544
545 // For single-child operators NOT, exists, operator symbol
546 // goes 1st, then operand
547 if (nChild <= 1) { // operator goes first
548 sqlString += opSymbols[op->getOpType()];
549
550 // more special handling for EXISTS
551 if (op->getOpType() == OPTYPEexists) {
552 sqlString += "(SELECT * FROM " + op->getTableName();
553 if (!nChild) { // done
554 sqlString += ")";
555 return ret;
556 }
557 // else EXISTS child is object of a WHERE clause
558 sqlString += " WHERE(";
559 }
560 ret = compileOperator(children[0], sqlString);
561 if (!ret) {
562 std::string msg =
563 "rdbModel::MysqlConnection::compileOperator failed for operator "
564 + opSymbols[op->getOpType()];
565 throw RdbException(msg);
566 }
567
568 // Have an extra closing ")" for EXISTS with WHERE clause
569 if (op->getOpType() == OPTYPEexists) sqlString += ")";
570
571
572 return ret;
573 }
574
575 // Otherwise put operator symbols between adjacent children.
576
577 // First open parentheses
578 sqlString += "(";
579
580 std::string symbol = opSymbols[op->getOpType()];
581
582 ret = compileOperator(children[0], sqlString);
583 if (!ret) {
584 std::string msg =
585 "rdbModel::MysqlConnection::compileOperator failed for operator "
586 + symbol;
587 throw RdbException(msg);
588 }
589 for (unsigned int iChild = 1; iChild < nChild; iChild++) {
590 sqlString += symbol;
591
592 ret = compileOperator(children[iChild], sqlString);
593 if (!ret) {
594 std::string msg =
595 "rdbModel::MysqlConnection::compileOperator failed for operator "
596 + symbol;
597 throw RdbException(msg);
598 }
599 }
600 // Finally close paren.
601 sqlString += ")";
602 return ret;
603 }
604
605 // Satisfy Visitor interface. For now the only visitor is the
606 // one to check whether remote and local db descriptions match or
607 // are at least compatible enough to be used.
609
610 if (m_matchDbName) {
611 if (m_dbName != rdb->getDbName()) {
612 m_matchReturn = MATCHfail;
613 return Visitor::VDONE;
614 }
615 }
616
617 unsigned int nLocal = rdb->getNTable();
618
619 // Null pointer for 2nd argument means "list all tables"
620
621 MYSQL_RES* res = mysql_list_tables(m_mysql, 0);
622 if (!res) {
623 m_matchReturn = MATCHfail;
625 }
626 unsigned int nRemote = mysql_num_rows(res);
627 mysql_free_result(res);
628
629 if (nRemote < nLocal) {
630 m_matchReturn = MATCHfail;
631 return Visitor::VDONE;
632 }
633 else if (nRemote > nLocal) m_matchReturn = MATCHcompatible;
634
635 // Tell Rdb about this
636 rdb->setConnection(this);
637
638 return Visitor::VCONTINUE;
639 }
640
642 const std::string& tName = table->getName();
643
644 // Result set will have all fields for the table
645 if (m_tempRes) {
646 mysql_free_result(m_tempRes);
647 m_tempRes = 0;
648 }
649 m_primColName.clear();
650
651 std::string query = "SHOW COLUMNS FROM " + tName;
652
653 (*m_out) << std::endl << "# About to issue SHOW COLUMNS request :"
654 << std::endl;
655 (*m_out) << query << std::endl;
656 m_out->flush();
657
658 int ret = mysql_query(m_mysql, query.c_str());
659 if (ret) {
660 m_matchReturn = MATCHfail;
662 }
663
664 m_tempRes = mysql_store_result(m_mysql);
665 if (!m_tempRes) {
666 m_matchReturn = MATCHfail;
668 }
669 // Result set is a table with fields "Field"(the name) "Type" "Null"(yes
670 // or no) "Key" "Default", "Extra"
671 // Make it easier for accept(Column* ) to find relevant information
672 unsigned int nRow = mysql_num_rows(m_tempRes);
673 m_colIx.clear();
674 for (unsigned iRow = 0; iRow < nRow; iRow++) {
675 MYSQL_ROW colDescrip = mysql_fetch_row(m_tempRes);
676 std::string name = std::string(colDescrip[0]);
677 std::cout<<"name is:"<<name<<std::endl;
678 m_colIx[name] = iRow;
679 }
680 return Visitor::VCONTINUE;
681
682 }
683
685 std::string myName = col->getName();
686 if (m_colIx.find(myName) == m_colIx.end()) {
687 m_matchReturn = MATCHfail;
689 }
690 unsigned int ix = m_colIx[myName];
691 mysql_data_seek(m_tempRes, ix);
692 MYSQL_ROW colDescrip = mysql_fetch_row(m_tempRes);
693
694 // Type
695 std::string sqlDtype = std::string(colDescrip[1]);
696 Datatype* dtype = col->getDatatype();
697 if (!checkDType(dtype, sqlDtype)) {
698 m_matchReturn = MATCHfail;
699 (*m_out) << "Failed dtype match of col " << myName << std::endl;
701 }
702
703 // Null
704 bool nullable = (std::string(colDescrip[2]) == std::string("YES"));
705 if (nullable != col->nullAllowed()) {
706 m_matchReturn = MATCHfail;
707 (*m_out) << "Failed null/not null match of col " << myName << std::endl;
709 }
710 // Key (PRI for primary, MUL if first in a multiple-field key
711 // Save primary key info, if any
712 if (std::string(colDescrip[3]) == std::string("PRI")) {
713 m_primColName = myName;
714 }
715
716 // Field 4 is default
717 // Extra (may say auto_increment)
718 bool autoInc =
719 (std::string(colDescrip[5]) == std::string("auto_increment"));
720 if (autoInc != col->isAutoIncrement()) {
721 m_matchReturn = MATCHfail;
722 (*m_out) << "Failed isAutoIncrement match of col " << myName << std::endl;
724 }
725 return Visitor::VCONTINUE;
726 }
727
728 bool MysqlConnection::checkDType(Datatype* dtype,
729 const std::string& sqlType) {
730 std::string base;
731 int sqlSize;
732 if (dtype->getType() != Datatype::TYPEenum) {
733 sqlSize = extractSize(sqlType);
734 }
735
736 // Cases char, varchar, enum and datetime are handled entirely within
737 // the switch statement, but most do the bulk of the work in
738 // common, after the switch.
739 switch (dtype->getType()) {
740 case Datatype::TYPEenum: {
741 base = "enum";
742 if (sqlType.find(base) != 0) {
743 m_matchReturn = MATCHfail;
744 return false;
745 }
746 Enum* ourEnum = dtype->getEnum();
747 // Finally compare local list of choices to those listed in sqlType
748 // Local list is a vector; in sqlType they're quoted, comma separated
749 return compareEnumList(ourEnum->getChoices(), sqlType);
750 }
752 base = "varchar";
753 if (sqlType.find(base) != 0) {
754 m_matchReturn = MATCHfail;
755 return false;
756 }
757 // size in db must be at least as large as size in Col.
758 if (sqlSize < dtype->getOutputSize()) {
759 m_matchReturn = MATCHfail;
760 return false;
761 }
762 else if (sqlSize > dtype->getOutputSize()) {
763 m_matchReturn = MATCHcompatible;
764 }
765 return true;
766 }
767 case Datatype::TYPEchar: {
768 base = "char";
769 if (sqlType.find(base) != 0) {
770 m_matchReturn = MATCHfail;
771 return false;
772 }
773 // For char datatype unspecified size is equivalent to size=1
774 if (!sqlSize) sqlSize = 1;
775 // size in db must be at least as large as size in Col.
776 if (sqlSize < dtype->getOutputSize()) {
777 m_matchReturn = MATCHfail;
778 return false;
779 }
780 else if (sqlSize > dtype->getOutputSize()) {
781 m_matchReturn = MATCHcompatible;
782 }
783 return true;
784 }
786 if (sqlType != "datetime") {
787 m_matchReturn = MATCHfail;
788 return false;
789 }
790 return true;
791 }
792
793
795 base = "timestamp";
796 break;
797 }
798 case Datatype::TYPEint: {
799 base = "int";
800 break;
801 }
803 base = "mediumint";
804 break;
805 }
807 base = "smallint";
808 break;
809 }
810 case Datatype::TYPEreal:
812 base = "double";
813 break;
814 }
815 default: { // Indicates bad xml file input. Applications
816 //should have exited already
817 m_matchReturn = MATCHfail;
818 return false;
819 }
820 } // end switch
821 if (sqlType.find(base) != 0) {
822 m_matchReturn = MATCHfail;
823 return false;
824 }
825 // Now check size. It's only for display, so mismatch is not failure
826 if (sqlSize != dtype->getOutputSize()) {
827 m_matchReturn = MATCHcompatible;
828 }
829
830 return true;
831 }
832
833
834
836 return Visitor::VCONTINUE;
837 // might put something real here later
838 }
839
841 return Visitor::VCONTINUE;
842 }
843
845 return Visitor::VCONTINUE;
846 }
847
849 return Visitor::VCONTINUE;
850 }
851
853 return Visitor::VCONTINUE;
854 }
855
857 return Visitor::VCONTINUE;
858 }
859
861 return Visitor::VCONTINUE;
862 }
863
864
865 } // end namespace rdbModel
*******DOUBLE PRECISION m_EGridB INTEGER m_out
Definition: BStra.h:10
double arg(const EvtComplex &c)
Definition: EvtComplex.hh:227
struct st_mysql_res MYSQL_RES
struct st_mysql MYSQL
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.
Datatype * getDatatype() const
Definition: Column.h:63
bool isAutoIncrement() const
Definition: Column.cxx:37
const std::string & getName() const
Definition: Column.h:56
bool nullAllowed() const
Returns true if column may take on value NULL.
Definition: Column.h:80
TYPES getType() const
Definition: Datatype.h:59
int getOutputSize() const
Definition: Datatype.h:60
Enum * getEnum() const
Definition: Datatype.h:64
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 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()
Definition: RdbException.h:14
const std::string & getDbName()
Definition: Rdb.h:56
unsigned int getNTable() const
Definition: Rdb.h:68
void setConnection(Connection *connection)
Definition: Rdb.cxx:43
unsigned int accept(Visitor *v)
This is the recursive accept for the visitor pattern.
Definition: Rdb.cxx:98
const std::string & getName() const
Definition: Table.h:40
static std::string getAttribute(const DOMElement *elt, const char *attName)
Definition: Dom.cxx:222
DOMDocument * parse(const char *const filename, const std::string &docType=std::string(""))
Parse an xml file, returning document node if successful.
Definition: XmlParser.cxx:108
@ FIELDTYPElit
Definition: Rdb.h:22
@ MATCHequivalent
Definition: Connection.h:26
@ MATCHnoConnection
Definition: Connection.h:29
@ MATCHfail
Definition: Connection.h:28
@ MATCHcompatible
Definition: Connection.h:27
std::string opSymbols[OPTYPElast]
std::vector< std::string > StringVector
Definition: Connection.h:52