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