Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

StDbSql.cc

Go to the documentation of this file.
00001 /*************************************************************************** 00002 * 00003 * $Id: StDbSql.cc,v 1.28 2005/11/28 19:09:55 deph Exp $ 00004 * 00005 * Author: R. Jeff Porter 00006 *************************************************************************** 00007 * 00008 * Description: Implementation class of StDataBaseI in (My)SQL 00009 * 00010 *************************************************************************** 00011 * 00012 * $Log: StDbSql.cc,v $ 00013 * Revision 1.28 2005/11/28 19:09:55 deph 00014 * small bug fix for a rare condition. 00015 * 00016 * Revision 1.27 2005/11/07 14:45:44 deph 00017 * Changed the SQL operator IN to one of the following: = if row =1 ; between if block of element IDs are contiguous; or IN if they are not 00018 * 00019 * Revision 1.26 2004/01/15 00:02:25 fisyak 00020 * Replace ostringstream => StString, add option for alpha 00021 * 00022 * Revision 1.25 2003/12/16 01:30:32 porter 00023 * additional fixes for change from ostrstream to StString that were not exposed until 00024 * running in online 00025 * 00026 * Revision 1.24 2003/09/26 20:40:37 deph 00027 * *** empty log message *** 00028 * 00029 * Revision 1.23 2003/09/23 04:37:16 porter 00030 * fixed leak of timeValues array 00031 * 00032 * Revision 1.22 2003/09/16 22:44:17 porter 00033 * got rid of all ostrstream objects; replaced with StString+string. 00034 * modified rules.make and added file stdb_streams.h for standalone compilation 00035 * 00036 * Revision 1.21 2003/09/02 17:57:49 perev 00037 * gcc 3.2 updates + WarnOff 00038 * 00039 * Revision 1.20 2003/04/11 22:47:36 porter 00040 * Added a fast multi-row write model specifically needed by the daqEventTag 00041 * writer. Speed increased from about 100Hz to ~3000Hz. It is only invoked if 00042 * the table is marked as Non-Indexed (daqTags & scalers). For non-indexed tables 00043 * which include binary stored data (we don't have any yet), the fast writer has 00044 * to invoke a slower buffer so that the rates are a bit slower (~500Hz at 50 rows/insert). 00045 * 00046 * Revision 1.19 2003/01/29 03:44:54 porter 00047 * added setRowNumber in QueryDbFunction method to simplify codes that use 00048 * this when plotting directly from the database 00049 * 00050 * Revision 1.18 2003/01/10 04:19:20 porter 00051 * added feature of getting timestamp list (but no data) for a table. 00052 * fixed 2 features sometimes used in online in query-by-whereclause. 00053 * removed a stray 'cout' in a routine that is rarely accessed 00054 * 00055 * Revision 1.17 2002/01/30 15:40:48 porter 00056 * changed limits on flavor tag & made defaults retrieving more readable 00057 * 00058 * Revision 1.16 2001/12/21 22:47:33 porter 00059 * added DbRelease for new endtime checks - this caused problems with tpcGas 00060 * 00061 * Revision 1.15 2001/12/21 04:54:46 porter 00062 * sped up table definition for emc and changed some ostrstream usage for 00063 * insure tests 00064 * 00065 * Revision 1.14 2001/12/19 20:44:52 porter 00066 * fixed endTime for run-level queries 00067 * 00068 * Revision 1.13 2001/12/05 17:16:35 porter 00069 * stand-alone make file no longer had "DLINUX" in compile but this is still needed 00070 * and returned. Also retrieve elementID list in query by whereClause for plotting 00071 * many row instances. 00072 * 00073 * Revision 1.12 2001/10/26 20:59:46 porter 00074 * fixed new endtime flag from previous checkin. made StDataBaseI available 00075 * at root-cli. 00076 * 00077 * Revision 1.11 2001/10/24 04:05:20 porter 00078 * added long long type to I/O and got rid of obsolete dataIndex table 00079 * 00080 * Revision 1.10 2001/08/02 17:37:19 porter 00081 * fixed problem in fetch by where-clause used in online in StDbSql.cc. 00082 * also got rid of warning comparing unsigned int to int. 00083 * 00084 * Revision 1.9 2001/07/23 16:39:30 porter 00085 * removed an extraneous "cout" left in by mistake 00086 * 00087 * Revision 1.8 2001/04/23 19:24:31 porter 00088 * fixed row limit & initial buffer contents for query by where clause 00089 * 00090 * Revision 1.7 2001/03/30 18:48:26 porter 00091 * modified code to keep Insure from wigging-out on ostrstream functions. 00092 * moved some messaging into a StDbSql method. 00093 * 00094 * Revision 1.6 2001/02/23 18:35:47 porter 00095 * cleaned up a warning messages when compiled under HP's aCC 00096 * 00097 * Revision 1.5 2001/02/22 23:01:56 porter 00098 * Re-introduced many-to-one name-to-table capability 00099 * & robustness for query errors 00100 * 00101 * Revision 1.4 2001/02/09 23:06:25 porter 00102 * replaced ostrstream into a buffer with ostrstream creating the 00103 * buffer. The former somehow clashed on Solaris with CC5 iostream (current .dev) 00104 * 00105 * Revision 1.3 2001/02/08 23:23:56 porter 00106 * fixed initialization of schemaID in table & fixed some warnings when 00107 * compiled with NODEBUG 00108 * 00109 * Revision 1.2 2001/01/23 14:38:16 porter 00110 * fixed bug in parsing flavor string where string contains a list of flavors. 00111 * 00112 * Revision 1.1 2001/01/22 18:37:59 porter 00113 * Update of code needed in next year running. This update has little 00114 * effect on the interface (only 1 method has been changed in the interface). 00115 * Code also preserves backwards compatibility so that old versions of 00116 * StDbLib can read new table structures. 00117 * -Important features: 00118 * a. more efficient low-level table structure (see StDbSql.cc) 00119 * b. more flexible indexing for new systems (see StDbElememtIndex.cc) 00120 * c. environment variable override KEYS for each database 00121 * d. StMessage support & clock-time logging diagnostics 00122 * -Cosmetic features 00123 * e. hid stl behind interfaces (see new *Impl.* files) to again allow rootcint access 00124 * f. removed codes that have been obsolete for awhile (e.g. db factories) 00125 * & renamed some classes for clarity (e.g. tableQuery became StDataBaseI 00126 * and mysqlAccessor became StDbSql) 00127 * 00128 * 00129 **************************************************************************/ 00130 #include "StDbSql.hh" 00131 #include "StDbManager.hh" 00132 #include "StDbDefaults.hh" 00133 #include "StDbConfigNodeImpl.hh" 00134 #include "StDbTableIter.hh" 00135 #include "StDbTable.h" 00136 #include "StDbFastSqlWriter.h" 00137 00138 #include "stdb_streams.h" 00139 00140 #define __CLASS__ "StDbSql" 00141 00142 static const char* DbQFailed = "Query Failed = "; 00143 static const char* DbQInfo = " Query = "; 00144 static const char* DbQResult = " Query Result = "; 00145 00147 00148 StDbSql::StDbSql(MysqlDb &db, StDbBuffer& buffer) : StDataBaseI(),Db(db), buff(buffer) { mgr=StDbManager::Instance(); init(); } 00149 00151 00152 StDbSql::StDbSql(MysqlDb &db, StDbBuffer& buffer, StDbType tpe, StDbDomain dom) : StDataBaseI(tpe, dom), Db(db), buff(buffer) { 00153 mgr=StDbManager::Instance(); init(); 00154 } 00155 00157 00158 StDbSql::StDbSql(MysqlDb &db, StDbBuffer& buffer, const char* tpe, const char* dom) : StDataBaseI(tpe, dom), Db(db), buff(buffer){ 00159 mgr=StDbManager::Instance(); init(); 00160 } 00161 00163 00164 StDbSql::~StDbSql() { 00165 if(mretString) delete [] mretString; 00166 if(mdefaultEndDateTime) delete [] mdefaultEndDateTime; 00167 deleteDescriptors(); 00168 } 00169 00171 // 00172 // Real Work Begins here 00173 // 00175 00176 int 00177 StDbSql::QueryDb(StDbConfigNode* node) { 00178 00179 #define __METHOD__ "QueryDb(StDbConfigNode*)" 00180 00181 StDbNode curNode; 00182 curNode.setDbName(mdbName); 00183 curNode.setDbType(mdbType); 00184 curNode.setDbDomain(mdbDomain); 00185 int NodeID; 00186 int branchID=node->getBranchID(); 00187 00188 if(!((NodeID)=prepareNode(node)))return 0; 00189 00190 // Build node query string 00191 00192 Db<<"Select subNode.*, NodeRelation.ID as branchID from Nodes "; 00193 Db<<"LEFT JOIN NodeRelation ON Nodes.ID=NodeRelation.ParentID "; 00194 Db<<"LEFT JOIN Nodes as subNode ON NodeRelation.NodeID=subNode.ID "; 00195 Db<<" Where Nodes.ID="<<NodeID; 00196 Db<<" and NodeRelation.BranchID="<<branchID<<endsql; 00197 00198 if(!Db.QueryStatus()) 00199 return sendMess(DbQFailed,Db.printQuery(),dbMWarn,__LINE__,__CLASS__,__METHOD__); 00200 00201 if(!Db.NbRows()) 00202 sendMess(node->printName()," Node has no subnodes",dbMDebug,__LINE__,__CLASS__,__METHOD__); 00203 00204 sendMess(DbQInfo,Db.printQuery(),dbMDebug,__LINE__,__CLASS__,__METHOD__); 00205 00206 // 00207 // Loop over rows in Configuration 00208 00209 while(Db.Output(&buff)){ 00210 curNode.setConfigured(false); 00211 if(readNodeInfo(&curNode)){ 00212 00213 StString fs; 00214 fs<<"Found "<<curNode.printNodeType()<<" Node "<<curNode.printName(); 00215 fs<<" of parent "<<node->printName(); 00216 sendMess(DbQResult,(fs.str()).c_str(),dbMDebug,__LINE__,__CLASS__,__METHOD__); 00217 00218 00219 if(strcmp(curNode.printNodeType(),"table")!=0){ // it is a ConfigNode 00220 00221 StDbConfigNode* child= new StDbConfigNodeImpl(node,curNode); 00222 if(!child->isDbNode())readConfigNodeInfo(child); 00223 00224 } else { 00225 00226 StDbTable* table = node->addTable(&curNode); 00227 readTableInfo(table); 00228 } 00229 } 00230 buff.Raz(); 00231 } 00232 Db.Release(); 00233 return 1; 00234 #undef __METHOD__ 00235 } 00236 00238 int 00239 StDbSql::QueryDb(StDbNode* node){ 00240 #define __METHOD__ "QueryDb(StDbNode*)" 00241 00242 if(!prepareNode(node)) return 0; 00243 if(node->IsTable()){ 00244 readTableInfo((StDbTable*) node); 00245 } else { 00246 readConfigNodeInfo((StDbConfigNode*)node); 00247 } 00248 00249 return node->getNodeID(); 00250 #undef __METHOD__ 00251 } 00252 00254 int 00255 StDbSql::QueryDb(StDbTable* table, unsigned int reqTime){ 00256 00257 #define __METHOD__ "QueryDb(table,time)" 00258 00259 // Using name & version information in StDbTable + request timestamp 00260 // fill data from the database into the StDbTable pointer. 00261 // 00262 int retVal=1; 00263 if(!table) return 0; 00264 char* tName = table->printName(); 00265 table->clearStoreInfo(); 00266 int nodeID; 00267 if(!((nodeID)=table->getNodeID())){ 00268 if(!(prepareNode((StDbNode*)table))) 00269 return sendMess(tName," Table not found in DB",dbMErr,__LINE__,__CLASS__,__METHOD__); 00270 00271 readTableInfo(table); 00272 clear(); 00273 } 00274 00275 char* checkString=checkTablePrepForQuery(table,true); // returns null if ok 00276 if(checkString) 00277 return sendMess(tName,checkString,dbMErr,__LINE__,__CLASS__,__METHOD__); 00278 00279 // start preparing the queries 00280 00281 // common where clause 00282 StString bs; 00283 bs<<" Where nodeID="<<nodeID; 00284 // prepare "flavor" part of query 00285 bs<<" AND "<<getFlavorQuery(table->printFlavor()); 00286 // prepare for production time 00287 bs<<" AND "<<getProdTimeQuery(table->getProdTime()); 00288 // terminate the baseString 00289 bs<<" "; 00290 00291 string baseString = bs.str(); 00292 00293 00294 //--> add element ID list part of query 00295 int numRows; 00296 int* elementID=table->getElementID(numRows); 00297 if(!elementID) 00298 return sendMess(tName,"doesn't have an Element List",dbMErr,__LINE__,__CLASS__,__METHOD__); 00299 00300 char* elementString=getElementList(elementID,numRows); 00301 char* dataTable=getDataTable(table,reqTime); 00302 00303 // Query DB for the endtime -> earliest time of next row 00304 Db << " select beginTime + 0 as mendDateTime, "; 00305 Db << " unix_timestamp(beginTime) as mendTime from "<<dataTable; 00306 Db << baseString <<" AND beginTime>from_unixtime("<<reqTime<<")"; 00307 // Db << " And elementID In("<<elementString<<")"; 00308 Db << " And elementID "<<elementString; 00309 Db << " Order by beginTime limit 1"<<endsql; 00310 00311 sendMess(DbQInfo,Db.printQuery(),dbMDebug,__LINE__,__CLASS__,__METHOD__); 00312 00313 if(!Db.QueryStatus()) 00314 return sendMess(DbQFailed,Db.printQuery(),dbMWarn,__LINE__,__CLASS__,__METHOD__); 00315 00316 if(Db.NbRows()==1 && Db.Output(&buff)){ 00317 char* edTime=0; 00318 int eTime; 00319 buff.ReadScalar(edTime,"mendDateTime"); 00320 buff.ReadScalar(eTime,"mendTime"); 00321 table->setEndTime(eTime); 00322 table->setEndTime(edTime); 00323 if(edTime) delete [] edTime; 00324 clear(); 00325 } else { 00326 setDefaultEndTime(table); 00327 } 00328 00329 int eID; 00330 00331 // --> prep for data query which can be 1 or more queries 00332 int maxID=1; 00333 int i; 00334 for(i=0;i<numRows;i++)if(elementID[i]>maxID)maxID=elementID[i]; 00335 int* idMap = new int[maxID+1]; 00336 int* dataIDList = new int[numRows]; 00337 unsigned int* timeValues = new unsigned int[numRows]; 00338 for(i=0;i<numRows;i++){ 00339 idMap[elementID[i]]=i; 00340 dataIDList[i]=0; 00341 timeValues[i]=0; 00342 } 00343 00344 // --> end of prep <-- 00345 // query is done where elementID is not necessarily distinct. 00346 // yet the in the query we set limit=numRows. 00347 // - we take 1st of instance of each elementID returned. 00348 // - we make a new list of those not yet found 00349 // - redo query with limit="rowsLeft" 00350 // continue until we're done 00351 00352 int rowsLeft=numRows; 00353 bool done=false; 00354 while(!done){ //done if all elementIDs are found or (break) if null 00355 00356 Db <<" select unix_timestamp(beginTime) as bTime,"<<dataTable<<".* from "; 00357 Db << dataTable << baseString; 00358 Db <<" AND beginTime<=from_unixtime("<<reqTime<<")"; 00359 //Db <<" AND elementID In("<<elementString<<") "; 00360 Db <<" AND elementID "<<elementString; 00361 Db <<" Order by beginTime desc limit "<< rowsLeft <<endsql; 00362 00363 sendMess(DbQInfo,Db.printQuery(),dbMDebug,__LINE__,__CLASS__,__METHOD__); 00364 00365 if(!Db.QueryStatus()){ 00366 sendMess(DbQFailed,Db.printQuery(),dbMWarn,__LINE__,__CLASS__,__METHOD__); 00367 break; 00368 } 00369 00370 if(Db.NbRows()==0)break; 00371 00372 int numRowsFound=0; 00373 while(Db.Output(&buff)){ 00374 buff.ReadScalar(eID,"elementID"); 00375 // check to see if this eID is already returned & don't use if so 00376 if(!dataIDList[idMap[eID]]){ 00377 buff.ReadScalar(dataIDList[idMap[eID]],"dataID"); 00378 buff.ReadScalar(timeValues[idMap[eID]],"bTime"); 00379 table->setRowNumber(idMap[eID]); 00380 table->dbStreamer(&buff,true); // stream data into table 00381 numRowsFound++; 00382 } 00383 buff.Raz(); 00384 } 00385 00386 rowsLeft=rowsLeft-numRowsFound; 00387 // Check for left overs & modify query for repeat 00388 if(!done && (rowsLeft>0)){ 00389 int* elementsLeft = new int[rowsLeft]; 00390 int j=0; 00391 for(i=0;i<numRows;i++){ 00392 if(!dataIDList[i]){ 00393 elementsLeft[j]=elementID[i]; 00394 j++; 00395 } 00396 } 00397 elementString = getElementListIN(elementsLeft,rowsLeft); 00398 delete [] elementsLeft; 00399 } else { 00400 done=true; 00401 } 00402 00403 } // --> end of while loop 00404 00405 if(rowsLeft==numRows){ 00406 sendMess(tName," has No data for query",dbMWarn,__LINE__,__CLASS__,__METHOD__); 00407 setDefaultBeginTime(table,reqTime); 00408 retVal=0; 00409 } else if(rowsLeft>0){ 00410 StString tp; 00411 tp<<" Not all rows filled from DB, Requested="<<numRows; 00412 tp<<" Returned="<<numRows-rowsLeft<<" for Table="<<tName; 00413 mgr->printInfo((tp.str()).c_str(),dbMWarn,__LINE__,__CLASS__,__METHOD__); 00414 // numRows-=rowsLeft; 00415 // table->resizeNumRows(numRows); 00416 } 00417 00418 if(retVal){ 00419 table->addWrittenRows(dataIDList,numRows); 00420 table->setTimeValues(timeValues); 00421 unsigned int t1=table->getMaxTime(); 00422 table->setBeginTime(t1); 00423 char* dt=getDateTime(t1); 00424 table->setBeginTime(dt); delete [] dt; 00425 table->setRowNumber(); // reset current row to 0 00426 } else { 00427 delete [] timeValues; 00428 } 00429 00430 Db.Release(); 00431 if(retVal) retVal=(int)updateEndTime(table,dataTable,reqTime); 00432 00433 delete [] idMap; 00434 delete [] dataIDList; 00435 delete [] dataTable; 00436 00437 return retVal; 00438 #undef __METHOD__ 00439 } 00440 00442 bool StDbSql::checkColumn(const char* tableName, const char* columnName){ 00443 00444 bool retVal=false; 00445 Db<<"show columns from "<<tableName<<" like '"<<columnName<<"'"<<endsql; 00446 if(Db.NbRows()==1)retVal=true; 00447 Db.Release(); 00448 return retVal; 00449 } 00450 00452 bool StDbSql::updateEndTime(StDbTable* table, const char* dataTable, unsigned int requestTime){ 00453 00454 /******************************** 00455 resets the table's endtime based on set endTime (if table has this column) 00456 instead of the running beginTime timestamp. Returns False if endTime is 00457 earlier than requestTime 00458 ********************************/ 00459 00460 bool retVal = true; 00461 if(!checkColumn(dataTable,"endTime")) return retVal; 00462 int nrows; 00463 int* wrows = table->getWrittenRows(nrows); 00464 00465 Db<<" select unix_timestamp(Min(endTime)) as mendTime from "<<dataTable; 00466 // Db<<" where dataID In("<<getElementList(wrows,nrows)<<")"<<endsql; 00467 Db<<" where dataID "<<getElementList(wrows,nrows)<<endsql; 00468 00469 if( (Db.NbRows()>0) && Db.Output(&buff)){ 00470 unsigned int t1 = table->getEndTime(); 00471 unsigned int t2; 00472 buff.ReadScalar(t2,"mendTime"); 00473 if(t2<t1)table->setEndTime(t2); 00474 if(t2<requestTime) retVal=false; 00475 buff.Raz(); 00476 } 00477 00478 Db.Release(); 00479 return retVal; 00480 } 00481 00483 int 00484 StDbSql::QueryDb(StDbTable* table, const char* whereClause){ 00485 00486 #define __METHOD__ "QueryDb(StDbTable*, const char* where)" 00487 00488 unsigned int* timeSet=QueryDbTimes(table,whereClause); 00489 if(!timeSet)return 0; 00490 delete [] timeSet; 00491 return table->GetNRows(); 00492 #undef __METHOD__ 00493 } 00494 00496 unsigned int* 00497 StDbSql::QueryDbTimes(StDbTable* table, const char* whereClause, int opt){ 00498 00499 #define __METHOD__ "QueryDb(StDbTable*, const char* where)" 00500 00501 /* 00502 rules for # of rows returned (by user request via setRowLimit(int nrows);) 00503 1. table->GetNRows()= 0 or N means no limit or limit N 00504 2. returned table->GetNRows()=M where M is how many returned 00505 00506 rules for beginTime & endTime 00507 1. Non-indexed tables have arbitrary returned times 00508 2. beginTime="lastest" begin time of returned rows 00509 3. endTime="earliest" begin time of set of "next" rows 00510 */ 00511 00512 unsigned int* retVal=0; 00513 char* tName=table->printName(); 00514 00515 char* checkString=checkTablePrepForQuery(table); 00516 if(checkString){ // then error message 00517 sendMess(tName,checkString,dbMErr,__LINE__,__CLASS__,__METHOD__); 00518 return retVal; 00519 } 00520 00521 setDefaultReturnValues(table,0); 00522 int numRows = table->getRowLimit(); 00523 int numTables; 00524 int numRowsReturned=0; 00525 unsigned int t1=0; 00526 00527 00528 table->setElementID((int*)retVal,0); // no rows to begin with 00529 table->setRowNumber(); 00530 00531 char** dataTables=getDataTables(table,numTables); 00532 int i; 00533 for(i=0;i<numTables;i++){ 00534 00535 char* columnList=0; 00536 if(!opt)columnList=getColumnList(table,dataTables[i]); 00537 if(!opt && !columnList){ 00538 sendMess(tName," has no elements?",dbMErr,__LINE__,__CLASS__,__METHOD__); 00539 return retVal; 00540 } 00541 00542 Db<<" select unix_timestamp("<<dataTables[i]<<".beginTime) as bTime,"; 00543 Db<<" elementID "; 00544 if(!opt)Db<<","<<columnList; 00545 Db<<" from "<<dataTables[i]<<" "<<whereClause; 00546 if(numRows)Db<<" limit "<<numRows; 00547 Db<<endsql; 00548 sendMess(DbQInfo,Db.printQuery(),dbMDebug,__LINE__,__CLASS__,__METHOD__); 00549 if(!Db.QueryStatus()){ 00550 sendMess(DbQFailed,Db.printQuery(),dbMWarn,__LINE__,__CLASS__,__METHOD__); 00551 return retVal; 00552 } 00553 00554 int retRows=Db.NbRows(); 00555 if(retRows==0) continue; 00556 00557 int* elements = new int[retRows]; 00558 int* dataIDList = new int[retRows]; 00559 unsigned int* timeList = new unsigned int[retRows]; 00560 if(!opt){ 00561 table->addNRows(retRows); 00562 } else { 00563 table->resizeElementID(retRows+table->GetNRows()); 00564 } 00565 // table->setRowNumber(); 00566 00567 int j=0; 00568 while(Db.Output(&buff)){ 00569 buff.ReadScalar(timeList[j],"bTime"); 00570 buff.ReadScalar(elements[j],"elementID"); 00571 buff.ReadScalar(dataIDList[j],"dataID"); 00572 if(!opt)table->dbStreamer(&buff,true); 00573 if(timeList[j]>t1)t1=timeList[j]; 00574 j++; 00575 buff.Raz(); 00576 } 00577 table->addNElements(elements,retRows); 00578 table->addWrittenRows(dataIDList,retRows); 00579 table->setBeginTime(t1); 00580 00581 unsigned int* tmpRet=new unsigned int[numRowsReturned+retRows]; 00582 if(retVal){ 00583 memcpy(tmpRet,retVal,numRowsReturned*sizeof(int)); 00584 delete [] retVal; 00585 } 00586 tmpRet+=numRowsReturned; 00587 memcpy(tmpRet,timeList,retRows*sizeof(int)); 00588 retVal=tmpRet; 00589 numRowsReturned+=retRows; 00590 Db.Release(); 00591 00592 if(table->IsIndexed() && t1>0 && !opt){ 00593 Db<<" select unix_timestamp(beginTime) as eTime from "<<dataTables[i]; 00594 Db<<" where beginTime>from_unixtime("<<t1<<")"; 00595 //Db<<" and elementID In("<<getElementList(elements,retRows)<<")"; 00596 Db<<" and elementID "<<getElementList(elements,retRows); 00597 Db<<" Order by beginTime limit 1"<<endsql; 00598 00599 sendMess(DbQInfo,Db.printQuery(),dbMDebug,__LINE__,__CLASS__,__METHOD__); 00600 00601 if(Db.Output(&buff)){ 00602 unsigned int eTime=0; 00603 if(buff.ReadScalar(eTime,"eTime") && eTime && eTime<table->getEndTime())table->setEndTime(eTime); 00604 buff.Raz(); 00605 } 00606 Db.Release(); 00607 } 00608 delete [] elements; 00609 delete [] dataIDList; 00610 delete [] timeList; 00611 }// loop over tables 00612 00613 for(i=0;i<numTables;i++) delete [] dataTables[i]; 00614 delete [] dataTables; 00615 if(retVal){ 00616 char* dateTime=getDateTime(table->getBeginTime()); 00617 table->setBeginTime(dateTime); if(dateTime) delete [] dateTime; 00618 dateTime=getDateTime(table->getEndTime()); 00619 table->setEndTime(dateTime); if(dateTime) delete [] dateTime; 00620 table->setRowNumber(); 00621 } 00622 return retVal; 00623 #undef __METHOD__ 00624 } 00625 00627 int 00628 StDbSql::QueryDbFunction(StDbTable* table, const char* whereClause, char* funcName) { 00629 #define __METHOD__ "QueryDbFunction(table,whereClause,functionName)" 00630 /* 00631 Method to provide access to Max, Min, Ave,... functions where 00632 the result per storage table is put in a row in the StDbTable. 00633 This only works for those columns stored in basic Mysql types 00634 */ 00635 00636 char* checkString=checkTablePrepForQuery(table); // null is good 00637 if(checkString) 00638 return sendMess(table->printName(),checkString,dbMErr,__LINE__,__CLASS__,__METHOD__); 00639 00640 int numTables; 00641 int numRowsReturned=0; 00642 00643 char** dataTables=getDataTables(table,numTables); 00644 int i; 00645 for(i=0;i<numTables;i++){ 00646 00647 char* columnList=getColumnList(table,dataTables[i],funcName); 00648 if(!columnList)return 0; 00649 00650 Db<<" select "<<columnList<<" from "<<dataTables[i]; 00651 Db<<" "<<whereClause<<endsql; 00652 00653 sendMess(DbQInfo,Db.printQuery(),dbMDebug,__LINE__,__CLASS__,__METHOD__); 00654 00655 if(!Db.QueryStatus()) 00656 return sendMess(DbQFailed,Db.printQuery(),dbMWarn,__LINE__,__CLASS__,__METHOD__); 00657 00658 int retRows=Db.NbRows(); 00659 if(retRows==0) continue; 00660 numRowsReturned+=retRows; 00661 00662 while(Db.Output(&buff)){ table->dbStreamer(&buff,true); buff.Raz(); } 00663 Db.Release(); 00664 } 00665 00666 for(i=0;i<numTables;i++) delete [] dataTables[i]; 00667 delete [] dataTables; 00668 table->setRowNumber(); 00669 00670 return numRowsReturned; 00671 #undef __METHOD__ 00672 }; 00673 00675 int 00676 StDbSql::WriteDb(StDbTable* table, unsigned int storeTime){ 00677 00678 #define __METHOD__ "WriteDb(StDbTable*,uint storeTime)" 00679 00680 int retVal=1; 00681 char* tName=table->printName(); 00682 00683 if(!table->hasData()) 00684 return sendMess(tName," has no data to store",dbMWarn,__LINE__,__CLASS__,__METHOD__)+1; 00685 00686 int nodeID; 00687 if(!((nodeID)=table->getNodeID())) 00688 if(!(prepareNode((StDbNode*)table))) 00689 return sendMess(tName," Not found in DB",dbMErr,__LINE__,__CLASS__,__METHOD__); 00690 00691 readTableInfo(table); 00692 clear(); 00693 00694 00695 if(table->IsBaseLine() && hasInstance(table)) 00696 return sendMess("BaseLine instance already exists",tName,dbMErr,__LINE__,__CLASS__,__METHOD__); 00697 00698 if(!QueryDescriptor(table)) 00699 return sendMess(tName," doesn't have a descriptor",dbMErr,__LINE__,__CLASS__,__METHOD__); 00700 00701 00702 table->setRowNumber(); // set to 0 00703 if(!table->IsIndexed())return WriteDbNoIndex(table,storeTime); 00704 00705 char* dataTable; 00706 if(!((dataTable)=getDataTable(table,storeTime))) 00707 return sendMess(tName," has no storage table",dbMErr,__LINE__,__CLASS__,__METHOD__); 00708 00709 int numRows; 00710 int* elements = table->getElementID(numRows); 00711 00712 if(!elements) 00713 return sendMess(tName,"doesn't have an Element List",dbMErr,__LINE__,__CLASS__,__METHOD__); 00714 00715 int* storedData = new int[numRows]; 00716 memset(storedData,0,numRows*sizeof(int)); 00717 char* sTime = getDateTime(storeTime); 00718 int rowsWritten = 0; 00719 00720 // write each row & roll back full writes if any fail. 00721 // - Also, for the time being, write to the old index 00722 // so that one can read with older versions of the code 00723 00724 table->commitData(); 00725 table->clearStoreInfo(); 00726 table->setDataTable(dataTable); 00727 00728 char* eTime=0; 00729 if( table->getEndStoreTime() && checkColumn(dataTable,"endTime")) 00730 eTime=getDateTime(table->getEndStoreTime()); 00731 00732 for(int i=0;i<numRows;i++){ 00733 clear(); 00734 buff.WriteScalar(nodeID,"nodeID"); 00735 buff.WriteScalar(table->getSchemaID(),"schemaID"); 00736 buff.WriteScalar(sTime,"beginTime"); 00737 buff.WriteScalar(elements[i],"elementID"); 00738 if(eTime)buff.WriteScalar(eTime,"endTime"); 00739 if(!table->defaultFlavor())buff.WriteScalar(table->printFlavor(),"flavor"); 00740 table->dbStreamer(&buff,false); 00741 00742 if(!Db.Input(dataTable,&buff)){ 00743 deleteRows(dataTable,storedData,i); 00744 retVal=0; 00745 break; 00746 } else { 00747 storedData[i]=Db.GetLastInsertID(); 00748 } 00749 clear(); 00750 rowsWritten++; 00751 } 00752 if(rowsWritten==numRows)table->addWrittenRows(storedData,numRows,true); 00753 00754 delete [] storedData; 00755 delete [] sTime; 00756 if(eTime) delete [] eTime; 00757 00758 table->setRowNumber(); 00759 delete [] dataTable; 00760 00761 if(!retVal)sendMess(" Write failed for table=",tName,dbMWarn,__LINE__,__CLASS__,__METHOD__); 00762 return retVal; 00763 #undef __METHOD__ 00764 } 00765 00767 int 00768 StDbSql::WriteDbNoIndex(StDbTable* table, unsigned int storeTime){ 00769 #define __METHOD__ "WriteDbNoIndex(table,storeTime)" 00770 00771 int retVal=0; 00772 char* dataTable; 00773 if(!((dataTable)=getDataTable(table,storeTime))) 00774 return sendMess(table->printName()," has no storage table",dbMErr,__LINE__,__CLASS__,__METHOD__); 00775 00776 StString cList; 00777 cList<<"beginTime,"<<getColumnList(table); 00778 00779 char* sTime=getDateTime(storeTime); 00780 00781 int numRows=table->GetNRows(); 00782 char* colList = new char[strlen((cList.str()).c_str())+1]; 00783 strcpy(colList,(cList.str()).c_str()); 00784 00785 int i; 00786 bool hasBinary=false; 00787 if(Db.InputStart(dataTable,&buff,colList,numRows,hasBinary)){ 00788 00789 if(hasBinary){ // got to go through the buffer 00790 00791 cout<<" In Binary write???"<<endl; 00792 00793 for(i=0;i<numRows;i++){ 00794 buff.WriteScalar(sTime,"beginTime"); 00795 table->dbStreamerWrite(&buff); //,false); 00796 if(!Db.InputRow(&buff,i)) break; 00797 } 00798 if( i==numRows && Db.InputEnd() ){ 00799 retVal=1; 00800 table->commitData(); 00801 } 00802 } else { 00803 00804 table->setBeginTime(storeTime); 00805 StString fsql; 00806 StDbFastSqlWriter writer(fsql); 00807 writer.ioTable(table); 00808 Db<<fsql.str(); 00809 if(Db.InputEnd()){ 00810 retVal=1; 00811 table->commitData(); 00812 } 00813 } 00814 00815 } 00816 00817 clear(); 00818 00819 table->setRowNumber(); 00820 delete [] colList; 00821 delete [] sTime; 00822 00823 delete [] dataTable; 00824 00825 if(!retVal)sendMess(" Write failed for Non-Indexed table=",table->printName(),dbMWarn,__LINE__,__CLASS__,__METHOD__); 00826 return retVal; 00827 00828 #undef __METHOD__ 00829 } 00830 00832 int 00833 StDbSql::QueryDescriptor(StDbTable* table){ 00834 #define __METHOD__ "QueryDescriptor(StDbTable*)" 00835 00836 // Query the database for the elements associated with this 00837 // tableName and with the schemaID that is added at the 00838 // constructure or over-written by an input file ... e.g. requested SchemaID 00839 00840 if(table->hasDescriptor())return 1; 00841 00842 clear(); 00843 00844 Db<<" SELECT structure.lastSchemaID, structure.ID from structure left join Nodes on structure.name=Nodes.structName"; 00845 Db<<" WHERE Nodes.name='"<<table->printName() <<"'"<<endsql; 00846 00847 if(!Db.Output(&buff))return 0; 00848 00849 int schemaID; 00850 int structID; 00851 buff.ReadScalar(schemaID,"lastSchemaID"); 00852 buff.ReadScalar(structID,"ID"); 00853 clear(); 00854 00855 int requestSchemaID; 00856 if(!(requestSchemaID=table->getSchemaID())){ 00857 requestSchemaID=schemaID; 00858 table->setSchemaID(schemaID); 00859 } 00860 00861 StDbTableDescriptor* descriptor = getDescriptor(structID,requestSchemaID); 00862 table->setDescriptor(descriptor); 00863 00864 if(descriptor->IsValid())return 1; 00865 00866 Db<<"SELECT schema.schemaID, schema.name, schema.type, schema.length, "; 00867 Db<<"schema.position from schema WHERE schema.structID="<<structID; 00868 Db<<" AND schema.schemaID="<<requestSchemaID; 00869 Db<<" ORDER by schema.position"<<endsql; 00870 00871 sendMess(DbQInfo,Db.printQuery(),dbMDebug,__LINE__,__CLASS__,__METHOD__); 00872 00873 if(!Db.QueryStatus()) 00874 return sendMess(DbQFailed,Db.printQuery(),dbMWarn,__LINE__,__CLASS__,__METHOD__); 00875 00876 00877 if(Db.NbRows()==0) { 00878 deleteDescriptor(structID,requestSchemaID); 00879 return 0; 00880 } 00881 00882 while(Db.Output(&buff)){ 00883 descriptor->fillElement(&buff,requestSchemaID); 00884 buff.Raz(); 00885 } 00886 Db.Release(); 00887 descriptor->endRowPadding(); 00888 00889 addDescriptor(descriptor); 00890 00891 return 1; 00892 #undef __METHOD__ 00893 } 00894 00896 int 00897 StDbSql::WriteDb(StDbConfigNode* node, int parentID, int& configID){ 00898 #define __METHOD__ "WriteDb(node,parentID,configID)" 00899 00900 if(!node) return 0; 00901 00902 char* nName = node->printName(); 00903 00904 if(!parentID){ 00905 00906 if(strcmp(node->printNodeType(),"Config")!=0) 00907 return sendMess("No Config tag for new config=",nName,dbMErr,__LINE__,__CLASS__,__METHOD__); 00908 00909 if(!node->printVersion()) 00910 return sendMess("No version label for new config=",nName,dbMErr,__LINE__,__CLASS__,__METHOD__); 00911 00912 } else { 00913 node->setNodeType("directory"); 00914 } 00915 00916 int nodeID; 00917 if(!((nodeID)=storeConfigNode(node))) 00918 return sendMess(" Could not store ",nName,dbMErr,__LINE__,__CLASS__,__METHOD__); 00919 00920 // write this node 00921 if(parentID) { 00922 insertNodeRelation(configID,parentID,nodeID); 00923 } else { 00924 configID=node->getNodeID(); 00925 } 00926 00927 // do this node's tables 00928 if(node->hasData()){ 00929 StDbTableIter* itr=node->getStDbTableIter(); 00930 while(!itr->done()){ 00931 int childID=0; 00932 StDbTable* table= itr->next(); 00933 table->setNodeType("table"); 00934 if(!((childID)=storeTableNode(table))) 00935 return sendMess(" Could not store table in Node=",nName,dbMErr,__LINE__,__CLASS__,__METHOD__); 00936 insertNodeRelation(configID,nodeID,childID); 00937 } 00938 } 00939 00940 return nodeID; 00941 } 00942 00944 void 00945 StDbSql::deleteRows(const char* tableName, int* rowID, int nrows){ 00946 00947 if(!rowID || nrows==0)return; 00948 Db<<" delete from "<<tableName; 00949 Db<<" where dataID In("<<getElementList(rowID,nrows)<<")"<<endsql; 00950 } 00951 00953 bool 00954 StDbSql::rollBack(StDbNode* node){ 00955 00956 if(!(node->canRollBack()) || !(node->getNodeID())) return false; 00957 Db<<"delete from Nodes where ID="<<node->getNodeID()<<endsql; 00958 return Db.QueryStatus(); 00959 } 00960 00962 bool 00963 StDbSql::rollBack(StDbTable* table){ 00964 00965 int numRows; 00966 int* numWrittenRows = table->getWrittenRows(numRows); 00967 char* dataTable = table->getDataTable(); 00968 char* elementList = getElementList(numWrittenRows,numRows); 00969 00970 Db<<"delete from "<<dataTable<<" where dataID In("<<elementList<<")"<<endsql; 00971 Db.Release(); 00972 00973 bool retVal=Db.QueryStatus(); 00974 Db.Release(); 00975 delete [] dataTable; 00976 00977 return retVal; 00978 } 00979 00981 int* 00982 StDbSql::selectElements(const char* elementName, StDbElementIndex* inval, int& numElements){ 00983 // if table does not have element rows (elementName=="None") 00984 // then will return default elementID=0, numElements=1 00985 // if table does not have elements based on StDbElementIndex, 00986 // then will return null pointer & numElements=0 --> NO DATA CAN BE Gotten 00987 // else, will return element list & numElements based on query 00988 00989 int* retElements = 0; 00990 numElements=1; 00991 if(!elementName) return retElements; 00992 if(strcmp(elementName,"None")==0){ 00993 retElements = new int[1]; retElements[0]=0; 00994 return retElements; 00995 } 00996 00997 int numIndeces = inval->getNumIndeces(); 00998 clear(); 00999 01000 Db<<" select elementID from "<<elementName<<"IDs"; 01001 if(numIndeces>0){ 01002 Db<<" where "<<inval->printIndexName(0)<<"="<<inval->getIndexVal(0); 01003 for(int i=1; i<numIndeces; i++) 01004 Db<<" AND "<<inval->printIndexName(i)<<"="<<inval->getIndexVal(i); 01005 } 01006 Db<<endsql; 01007 numElements=Db.NbRows(); 01008 if(numElements<=0) return retElements; 01009 retElements = new int[numElements]; 01010 int j=0; 01011 while(Db.Output(&buff)){ 01012 buff.ReadScalar(retElements[j],"elementID"); 01013 j++; 01014 buff.Raz(); 01015 } 01016 clear(); 01017 return retElements; 01018 } 01019 01021 char** 01022 StDbSql::getIndexNames( const char* elementName, int& numIndexes){ 01023 01024 Db<<"select * from elementIndexes "; 01025 Db<<" where elementName='"<<elementName<<"'"<<endsql; 01026 01027 char** indexNames = 0; 01028 if(!((numIndexes)=Db.NbRows())) return indexNames; 01029 01030 indexNames = new char*[numIndexes]; 01031 int i = 0; 01032 while(Db.Output(&buff)){ 01033 buff.ReadScalar(indexNames[i],"indexName"); 01034 i++; 01035 buff.Raz(); 01036 } 01037 01038 clear(); 01039 return indexNames; 01040 } 01041 01043 StDbTableDescriptor* 01044 StDbSql::findDescriptor(int structID, int schemaID){ 01045 01046 StDbTableDescriptor* td = 0; 01047 for(DescList::iterator itr = mdescriptors.begin(); 01048 itr != mdescriptors.end(); ++itr){ 01049 if( ((*itr)->getSchemaID()==schemaID) && ((*itr)->getStructID()==structID)){ 01050 td = *itr; 01051 break; 01052 } 01053 } 01054 return td; 01055 } 01056 01058 StDbTableDescriptor* 01059 StDbSql::getDescriptor(int structID, int schemaID){ 01060 StDbTableDescriptor* retVal=findDescriptor(structID,schemaID); 01061 if(retVal) return new StDbTableDescriptor(*retVal); // make copy 01062 retVal=new StDbTableDescriptor(structID,schemaID); // -else- make new 01063 return retVal; 01064 } 01065 01067 void 01068 StDbSql::addDescriptor(StDbTableDescriptor* td){ 01069 mdescriptors.push_back( new StDbTableDescriptor((*td)) ); // add a copy 01070 }; 01071 01073 void 01074 StDbSql::deleteDescriptors(){ 01075 DescList::iterator itr; 01076 StDbTableDescriptor* desc; 01077 01078 do { 01079 for(itr=mdescriptors.begin(); itr != mdescriptors.end(); ++itr){ 01080 desc=*itr; 01081 mdescriptors.erase(itr); 01082 if(desc)delete desc; 01083 break; 01084 } 01085 } while (mdescriptors.begin() != mdescriptors.end() ); 01086 01087 } 01088 01090 void 01091 StDbSql::deleteDescriptor(int structID, int schemaID) { 01092 01093 StDbTableDescriptor* desc; 01094 for(DescList::iterator itr = mdescriptors.begin(); 01095 itr != mdescriptors.end(); ++itr){ 01096 if(structID==(*itr)->getStructID() && schemaID==(*itr)->getSchemaID()){ 01097 desc=(*itr); 01098 mdescriptors.erase(itr); 01099 delete [] desc; 01100 break; 01101 } 01102 } 01103 } 01104 01106 void 01107 StDbSql::setDefaultReturnValues(StDbTable* table, unsigned int reqTime){ 01108 if(!table)return; 01109 setDefaultBeginTime(table,reqTime); 01110 setDefaultEndTime(table); 01111 table->clearStoreInfo(); 01112 } 01113 01115 void StDbSql::setDefaultBeginTime(StDbTable* table, unsigned int reqTime){ 01116 // set default return times 01117 char* stime=getDateTime(reqTime); 01118 table->setBeginTime(reqTime); // uint version 01119 table->setBeginTime(stime); // char* version 01120 if(stime) delete [] stime; 01121 } 01122 01124 void StDbSql::setDefaultEndTime(StDbTable* table){ 01125 if(!mdefaultEndDateTime)initEndTime(); 01126 table->setEndTime(mdefaultEndDateTime); 01127 table->setEndTime(mdefaultEndTime); 01128 } 01129 01131 void StDbSql::initEndTime(){ 01132 mdefaultEndTime=StDbDefaults::Instance()->getEndTime(); 01133 mdefaultEndDateTime=getDateTime(mdefaultEndTime); 01134 } 01135 01137 int 01138 StDbSql::prepareNode(StDbNode* dbNode){ 01139 01140 //-> takes the input dbNode's name & version and calls the db 01141 // (via method queryNode()) for the other information 01142 // and sets into dbNode 01143 01144 if( (strcmp(dbNode->printNodeType(),"DB")!=0) && 01145 (dbNode->IsConfigured())) return dbNode->getNodeID(); 01146 01147 dbNode->setDbName(mdbName); 01148 dbNode->setDbType(mdbType); 01149 dbNode->setDbDomain(mdbDomain); 01150 01151 return queryNode(dbNode);; 01152 } 01153 01155 int 01156 StDbSql::queryNode(StDbNode* node){ 01157 01158 int retVal=0; 01159 01160 Db<< "Select * from Nodes where Nodes.name='"<<node->printName()<<"'"; 01161 Db<<" AND Nodes.versionKey='"<<node->printVersion()<<"'"<<endsql; 01162 01163 if(Db.Output(&buff) && readNodeInfo(node))retVal=node->getNodeID(); 01164 if(!retVal) clear(); 01165 01166 return retVal; 01167 } 01168 01170 bool 01171 StDbSql::readNodeInfo(StDbNode* node){ 01172 01173 int nodeID; 01174 char* tmpString; 01175 01176 if(!buff.ReadScalar(nodeID,"ID")) return false; 01177 if(!buff.ReadScalar(tmpString,"nodeType"))return false; 01178 node->setNodeType(tmpString); 01179 delete [] tmpString; 01180 01181 if(!buff.ReadScalar(tmpString,"name"))return false; 01182 node->setName(tmpString); delete [] tmpString; 01183 01184 if(!buff.ReadScalar(tmpString,"versionKey"))return false; 01185 node->setVersion(tmpString); delete [] tmpString; 01186 01187 node->setNodeID(nodeID); 01188 node->setConfigured(true); 01189 01190 return true; 01191 } 01192 01194 bool 01195 StDbSql::readConfigNodeInfo(StDbConfigNode* node){ 01196 01197 char* iname; 01198 if(!buff.ReadScalar(iname,"indexName")) return false; 01199 if(strcmp(iname,"None")!=0){ 01200 int id; 01201 buff.ReadScalar(id,"indexVal"); 01202 node->setElementIndexInfo(iname,id); 01203 } 01204 delete [] iname; 01205 01206 int branchID; 01207 buff.ReadScalar(branchID,"branchID"); 01208 node->setBranchID(branchID); 01209 01210 return true; 01211 } 01212 01214 bool 01215 StDbSql::readTableInfo(StDbTable* table){ 01216 01217 char* tmpString; 01218 01219 if(!buff.ReadScalar(tmpString,"structName"))return false; 01220 table->setCstructName(tmpString); delete [] tmpString; 01221 01222 tmpString=0; 01223 char* hy=0; 01224 if(buff.ReadScalar(tmpString,"elementID")){ 01225 hy=strstr(tmpString,"-"); 01226 if(hy){ 01227 *hy='\0'; 01228 hy++; 01229 int first=atoi(tmpString); 01230 int last = atoi(hy); 01231 hy--; 01232 *hy='-'; 01233 int len = last-first+1; 01234 int * tmpElements = new int[len]; 01235 int j=0; 01236 int k; 01237 for(k=first; k<=last;k++){ 01238 tmpElements[j]=k; 01239 j++; 01240 } 01241 table->setElementID(tmpElements,len); 01242 delete [] tmpElements; 01243 } else { 01244 delete [] tmpString; 01245 if(!buff.ReadScalar(tmpString,"indexName")) return false; 01246 table->setElementName(tmpString); 01247 } 01248 delete [] tmpString; 01249 } 01250 01251 01252 table->setBaseLine(checkValue("baseLine","Y")); 01253 table->setBinary(checkValue("isBinary","Y")); 01254 table->setIndexed(checkValue("isIndexed","Y")); 01255 01256 table->setDbName(mdbName); 01257 table->setDbType(mdbType); 01258 table->setDbDomain(mdbDomain); 01259 01260 return true; 01261 }; 01262 01264 char* 01265 StDbSql::insertNodeString(StDbNode* node){ 01266 01267 StString dqs; 01268 dqs<<"insert into Nodes set name='"<<node->printName()<<"' "; 01269 if(!StDbDefaults::Instance()->IsDefaultVersion(node->printVersion())) 01270 dqs<<", versionKey='"<<node->printVersion()<<"' "; 01271 01272 dqs<<", nodeType='"<<node->printNodeType()<<"'"; 01273 01274 return mRetString(dqs); 01275 } 01276 01278 int 01279 StDbSql::storeConfigNode(StDbConfigNode* node){ 01280 01281 int retVal=0; 01282 01283 Db<<insertNodeString((StDbNode*) node); 01284 01285 if(node->getNumIndeces()){ 01286 char* ename=0; int eid; 01287 node->getElementIndexInfo(ename,eid); 01288 Db<<", indexName='"<<ename<<"'"; 01289 Db<<", indexVal="<<eid; 01290 if(ename) delete [] ename; 01291 } 01292 Db<<endsql; 01293 01294 if(Db.QueryStatus())retVal=Db.GetLastInsertID(); 01295 clear(); 01296 01297 return retVal; 01298 } 01299 01301 int 01302 StDbSql::storeTableNode(StDbTable* table){ 01303 01304 int retVal=0; 01305 if(!table->printCstructName()) return retVal; 01306 01307 Db<<insertNodeString((StDbNode*) table); 01308 Db<<", structName='"<<table->printCstructName()<<"'"; 01309 01310 if(table->IsBaseLine())Db<<", baseLine='Y'"; 01311 if(table->IsBinary())Db<<", isBinary='Y'"; 01312 if(!table->IsIndexed())Db<<", isIndexed='N'"; 01313 01314 Db<<endsql; 01315 01316 if(Db.QueryStatus())retVal=Db.GetLastInsertID(); 01317 clear(); 01318 01319 return retVal; 01320 } 01321 01323 bool 01324 StDbSql::insertNodeRelation(int configID, int parent, int child){ 01325 01326 Db<<" insert into NodeRelation set ParentID="<<parent; 01327 Db<<", NodeID="<<child<<", ConfigID="<<configID<<endsql; 01328 01329 bool retVal=Db.QueryStatus(); 01330 Db.Release(); 01331 01332 return retVal; 01333 } 01334 01336 unsigned int 01337 StDbSql::getUnixTime(const char* time){ 01338 01339 unsigned int retVal = 0; 01340 clear(); 01341 Db<<"select unix_timestamp('"<<time<<"') as requestTime"<<endsql; 01342 if(Db.Output(&buff)) buff.ReadScalar(retVal,"requestTime"); 01343 clear(); 01344 01345 return retVal; 01346 } 01347 01349 char* 01350 StDbSql::getDateTime(unsigned int time){ 01351 01352 char* retVal=0; 01353 // note the " + 0" part formats result without delimiters 01354 // e.g. 1999-01-01 00:12:20 becomes 19990101001220 01355 01356 clear(); 01357 Db<<"select from_unixtime("<<time<<") + 0 as requestTime"<<endsql; 01358 if(Db.Output(&buff)) buff.ReadScalar(retVal,"requestTime"); 01359 clear(); 01360 01361 return retVal; 01362 } 01363 01365 bool 01366 StDbSql::checkValue(const char* colName, const char* colValue){ 01367 01368 bool retVal = false; 01369 char* tmpS=0; 01370 if(buff.ReadScalar(tmpS,colName) && strcmp(tmpS,colValue)==0)retVal=true; 01371 if(tmpS) delete [] tmpS; 01372 01373 return retVal; 01374 } 01375 01377 char* 01378 StDbSql::getFlavorQuery(const char* flavor){ 01379 01380 // prepares SQL of " flavor In('flav1','flav2',...)" 01381 01382 char *id1,*id2,*id3; 01383 id1 = new char[strlen(flavor)+1]; 01384 strcpy(id1,flavor); 01385 id3=id1; 01386 01387 StString fs; 01388 fs<<" flavor In("; 01389 while(( (id2)=strstr(id3,"+")) ){ 01390 *id2='\0'; 01391 fs<<"'"<<id3<<"',"; 01392 *id2='+'; 01393 id2++; 01394 id3=id2; 01395 } 01396 fs<<"'"<<id3<<"')"; 01397 delete [] id1; 01398 01399 return mRetString(fs); 01400 } 01401 01403 char* 01404 StDbSql::getProdTimeQuery(unsigned int prodTime){ 01405 01406 // prepares SQL of " entryTime<=" 01407 StString pt; 01408 if(prodTime==0){ 01409 pt<<" deactive=0 "; 01410 } else { 01411 pt<<" (deactive=0 OR deactive>="<<prodTime<<")"; 01412 pt<<" AND unix_timestamp(entryTime)<="<<prodTime; 01413 } 01414 return mRetString(pt); 01415 } 01416 01418 char* 01419 StDbSql::getElementList(int* e, int num){ 01420 01421 // prepares comma separated list of integers 01422 // using the between operator 01423 01424 StString es; 01425 if(!e){ 01426 es<<0; 01427 } else { 01428 // for(int i=0;i<num-1;i++)//es<<e[i]<<","; 01429 { 01430 //MPD 01431 // if (e[0] == 0){ 01432 if (num == 1){ 01433 es<<"= "<<e[0]; 01434 } else if(e[0]< num) { 01435 es<<"between "<<e[0]<<" and "<<num; 01436 } else { 01437 es<<"between "<<num <<" and "<<e[0]; 01438 } 01439 } 01440 // es<<e[num-1]; 01441 } 01442 01443 return mRetString(es); 01444 } 01446 char* 01447 StDbSql::getElementListIN(int* e, int num){ 01448 // prepares comma separated list of integers 01449 // using the IN operator 01450 01451 01452 StString es; 01453 if(!e){ 01454 es<<0; 01455 } else { 01456 es<<"In ("; 01457 for(int i=0;i<num-1;i++) es<<e[i]<<","; 01458 es<<e[num-1]; 01459 } 01460 es<<")"; 01461 return mRetString(es); 01462 } 01463 01465 char* 01466 StDbSql::getColumnList(StDbTable* table,char* tableName,char* funcName){ 01467 01468 StTableDescriptorI* desc=table->getDescriptor(); 01469 int numElements=desc->getNumElements(); 01470 01471 StString es; es<<" "; 01472 01473 int icount=0; 01474 for(int i=0;i<numElements;i++){ 01475 if(funcName && (desc->getElementLength(i)>1))continue; 01476 char* name=desc->getElementName(i); 01477 if(funcName)es<<funcName<<"("; 01478 if(tableName)es<<tableName<<"."; 01479 es<<name; 01480 if(funcName)es<<") as "<<name; 01481 if(i<(numElements-1))es<<", "; 01482 delete [] name; 01483 icount++; 01484 } 01485 01486 if(icount) return mRetString(es); 01487 return (char*) 0; 01488 } 01489 01491 char* 01492 StDbSql::getEmptyString(){ 01493 01494 StString es; es<<" "; 01495 return mRetString(es); 01496 01497 }; 01498 01500 char* 01501 StDbSql::checkTablePrepForQuery(StDbTable* table, bool checkIndexed){ 01502 01503 if(mretString){ 01504 delete [] mretString; 01505 mretString=new char[256]; 01506 }else{mretString=new char[256];} 01507 01508 if(!QueryDescriptor(table)) 01509 return strcpy(mretString," doesn't have a descriptor "); 01510 01511 if(table->IsBinary()) 01512 return strcpy(mretString," Binary Store is currently disabled "); 01513 01514 if(checkIndexed && !table->IsIndexed()) 01515 return strcpy(mretString," Table is not time indexed"); 01516 01517 delete [] mretString; 01518 return mretString=0; 01519 } 01520 01522 bool 01523 StDbSql::checkForNull(const char* src){ 01524 return (strstr(src,"null")) ? true : false; 01525 } 01526 01528 char* 01529 StDbSql::getDataTable(StDbTable* table, unsigned int time){ 01530 01531 if(mtableCatalog==0) checkTableCatalog(); 01532 if(mtableCatalog==1) return table->getCstructName(); 01533 char* retVal=0; 01534 clear(); 01535 01536 // as of now, just use name... later maybe more so I've sent in StDbTable* 01537 char* tableName=table->printName(); 01538 01539 Db<<" select * from tableCatalog where nodeName='"<<tableName<<"'"; 01540 Db<<" AND unix_timestamp(beginTime)<="<<time; 01541 Db<<" Order by beginTime desc limit 1"<<endsql; 01542 01543 if(Db.Output(&buff))buff.ReadScalar(retVal,"tableName"); 01544 clear(); 01545 01546 return (retVal) ? retVal : table->getCstructName(); 01547 } 01548 01550 char** 01551 StDbSql::getDataTables(StDbTable* table,int& numTables){ 01552 01553 char** retVal; 01554 if(mtableCatalog==0) checkTableCatalog(); 01555 if(mtableCatalog==1){ 01556 numTables=1; 01557 retVal=new char*[1]; 01558 retVal[0]=table->getCstructName(); 01559 return retVal; 01560 } 01561 clear(); 01562 01563 // as of now, just use name... later maybe more so I've sent in StDbTable* 01564 char* tableName=table->printName(); 01565 Db<<" select * from tableCatalog where nodeName='"<<tableName<<"'"<<endsql; 01566 01567 if(!((numTables)=Db.NbRows()) ){ // use tableName as the 1 01568 numTables++; 01569 retVal= new char*[numTables]; 01570 retVal[0]=new char[strlen(tableName)+1]; 01571 strcpy(retVal[0],tableName); 01572 return retVal; 01573 } 01574 01575 retVal=new char*[numTables]; 01576 int i=0; 01577 while(Db.Output(&buff)) if(buff.ReadScalar(retVal[i],"tableName"))i++; 01578 01579 numTables=i; 01580 return retVal; 01581 } 01582 01584 bool 01585 StDbSql::hasInstance(StDbTable* table){ 01586 01587 // try and find a data instance of this table 01588 // for use in keeping track of baseline instances 01589 bool retVal=false; 01590 clear(); 01591 01592 int numTables; 01593 char** dataTables=getDataTables(table,numTables); 01594 if(numTables==0) return retVal; 01595 01596 for(int i=0; i<numTables;i++){ 01597 01598 Db<<" select * from "<<dataTables[i]; 01599 Db<<" where "<<getFlavorQuery(table->printFlavor()); 01600 Db<<" AND "<<getProdTimeQuery(table->getProdTime())<<endsql; 01601 01602 if(Db.NbRows() !=0 ){ 01603 retVal=true; 01604 break; 01605 } 01606 } 01607 for(int k=0;k<numTables;k++) delete [] dataTables[k]; 01608 delete [] dataTables; 01609 return retVal; 01610 } 01611 01613 void 01614 StDbSql::checkTableCatalog(){ 01615 01616 // if(Db.checkForTable("tableCatalog"))mtableCatalog=1 01617 Db<<"show tables like 'tableCatalog'"<<endsql; 01618 if(Db.NbRows()==0){ 01619 mtableCatalog=1; 01620 } else { 01621 mtableCatalog=2; 01622 } 01623 Db.Release(); 01624 } 01625 01627 void StDbSql::setDbUtils(MysqlDb& db, StDbBuffer& buffer){ 01628 Db=db; 01629 buff=buffer; 01630 }; 01631 01632 #undef __CLASS__

Generated on Thu Aug 24 14:45:27 2006 for Doxygen by doxygen 1.3.7