/home/bes3soft/bes3soft/Boss/7.0.2/dist/7.0.2/Calibration/rdbModel/rdbModel-00-01-01/src/Tables/Table.cxx

Go to the documentation of this file.
00001 // $Header: /bes/bes/BossCvs/Calibration/rdbModel/src/Tables/Table.cxx,v 1.1.1.1 2005/10/17 06:10:53 maqm Exp $
00002 
00003 #include "rdbModel/Tables/Table.h"
00004 #include "rdbModel/Tables/Column.h"
00005 #include "rdbModel/Tables/Index.h"
00006 #include "rdbModel/Tables/Assertion.h"
00007 #include "rdbModel/Db/Connection.h"
00008 #include "rdbModel/Db/ResultHandle.h"
00009 #include "rdbModel/RdbException.h"
00010 #include "rdbModel/Tables/InsertNew.h"
00011 #include "rdbModel/Tables/InterRow.h"
00012 #include "rdbModel/Tables/Query.h"
00013 #include "rdbModel/Tables/Set.h"
00014 #include "rdbModel/Tables/Supersede.h"
00015 #include "facilities/Util.h"
00016 #include "facilities/Timestamp.h"
00017 #include <algorithm>
00018 
00019 namespace rdbModel {
00020   Table::Table() : m_primaryKeyCol(""), m_sorted(false), m_nEndUser(0), 
00021                    m_validRow(0), m_iNew(0), m_sup(0), m_connect(0)    {
00022     m_sortedCols.clear(); m_programCols.clear(); 
00023     m_userCols.clear(); m_mayDefault.clear();
00024     m_out = &std::cout;    m_err = &std::cerr;
00025   }
00026 
00027 
00028   Table::~Table() {
00029     while (m_cols.size() ) {
00030       Column* c = m_cols.back();
00031       m_cols.pop_back();
00032       delete c;
00033     }
00034 
00035     while (m_asserts.size() ) {
00036       Assertion* a = m_asserts.back();
00037       m_asserts.pop_back();
00038       delete a;
00039     }
00040 
00041     while (m_indices.size() ) {
00042       Index* i = m_indices.back();
00043       m_indices.pop_back();
00044       delete i;
00045     }
00046   }
00047 
00048 
00049   void Table::setConnection(Connection* connect) {
00050     m_connect = connect;
00051     m_out = connect->getOut();
00052     m_err = connect->getErrOut();
00053   }
00054   // Columns are stored in order; binary cuts should do better than
00055   // just dumb compare one by one.
00056   Column* Table::getColumnByName(const std::string& name) const {
00057     unsigned nCol = m_sortedCols.size();
00058     unsigned minI = 0;
00059     unsigned maxI = nCol;
00060 
00061     unsigned guess = maxI/2;
00062     unsigned oldGuess = nCol;
00063 
00064     int cmp = name.compare(m_sortedCols[guess]->getName());
00065 
00066     while (cmp != 0)  {
00067       if (guess == oldGuess) return 0;        // not found
00068 
00069       if (cmp < 0 ) {    // thing we tried is > colName, so decrease maxI
00070         maxI = guess;
00071       }  else {   // thing we tried is > colName, so increase minI
00072         minI =  guess;
00073       }
00074       oldGuess = guess;
00075       guess = (minI + maxI)/2;
00076       cmp = name.compare(m_sortedCols[guess]->getName());
00077     }
00078     return m_sortedCols[guess];
00079 
00080   }
00081 
00082   Index* Table::getIndexByName(const std::string& name) const {
00083     unsigned nIx = m_indices.size();
00084     for (unsigned iIx = 0; iIx < nIx; iIx++) {
00085       Index* index = m_indices[iIx];
00086       if (index->getName() == name) return index;
00087     }
00088     return 0;
00089   }
00090 
00091   Assertion* Table::getAssertionByName(const std::string& name) const {
00092     unsigned nAssert = m_asserts.size();
00093     for (unsigned i = 0; i < nAssert; i++) {
00094       Assertion* a = m_asserts[i];
00095       if (a->getName() == name) return a;
00096     }
00097     return 0;
00098 
00099   }
00100 
00101   // Traversal order is self, columns, indices, asserts
00102   Visitor::VisitorState Table::accept(Visitor* v) {
00103     
00104     Visitor::VisitorState state = v->visitTable(this);
00105     if (state == Visitor::VBRANCHDONE) return Visitor::VCONTINUE;
00106     if (state != Visitor::VCONTINUE)       return state;
00107 
00108     unsigned n = m_cols.size();
00109 
00110     for (unsigned i = 0; i < n; i++) {
00111       state = m_cols[i]->accept(v);
00112       if (state != Visitor::VCONTINUE) return state;
00113     }
00114 
00115     n = m_indices.size();
00116     for (unsigned i = 0; i < n; i++) {
00117       state = m_indices[i]->accept(v);
00118       if (state != Visitor::VCONTINUE) return state;
00119     }
00120 
00121     n = m_asserts.size();
00122     for (unsigned i = 0; i < n; i++) {
00123       state = m_asserts[i]->accept(v);
00124       if (state != Visitor::VCONTINUE) return state;
00125     }
00126     return state;
00127   }
00128 
00129   void  Table::sortColumns() {
00130     if (m_sorted) return;
00131     m_sortedCols = m_cols;
00132 
00133     ColCompare  cmpObject;
00134 
00135     // Keep around original set so that rdbGUI will display them in
00136     // this order
00137     std::sort (m_sortedCols.begin(), m_sortedCols.end(), cmpObject); 
00138     m_sorted = true;
00139 
00140   }
00141 
00142   void Table::addColumn(Column* c) {
00143     m_cols.push_back(c);
00144     if (c->getSourceType() == Column::FROMendUser) {
00145       m_nEndUser++;
00146       // if not nullable and no default, user must supply it
00147       if (!(c->nullAllowed()) && ((c->getDefault()).size() == 0)) {
00148         m_userCols.push_back(c);
00149       }
00150       else {
00151         m_mayDefault.push_back(c);
00152       }
00153     }
00154     else if (c->getSourceType() == Column::FROMdefault) {
00155       m_mayDefault.push_back(c);
00156     }
00157     else if (c->getSourceType() == Column::FROMprogram) {
00158       m_programCols.push_back(c);
00159     }
00160   }
00161 
00162   int Table::insertLatest(Row& row, int* serial) const {
00163 
00164     if (!m_connect) {
00165       throw RdbException("Table::insertLatest Need matching connection");
00166     }
00167     row.rowSort();
00168 
00169     // Fill in columns in m_programCols list
00170     fillProgramCols(row, true);
00171 
00172     // Check that all required columns are there and not null
00173     for (unsigned i = 0; i < m_userCols.size(); i++) {
00174       FieldVal* f = row.find(m_userCols[i]->getName());
00175       if ((!f) || (f->m_null)) {
00176         std::string 
00177           msg("Table::insertLatest Row to be inserted missing req'd field ");
00178         msg = msg + m_userCols[i]->getName();
00179         throw RdbException(msg);
00180       }
00181     }
00182     // Fill in defaults
00183     fillDefaults(row);
00184 
00185     // Check against consistency conditions specified by <insertNew>
00186     const Assertion* cond = m_iNew->getInternal();
00187     bool satisfied;
00188 
00189     try {
00190       satisfied = cond->verify(row, row);
00191     }
00192     catch (RdbException ex) {
00193       (*m_out) << ex.getMsg() << std::endl;
00194       return -1;
00195     }
00196 
00197     if (!satisfied) return -1;   // or maybe throw exception here?
00198 
00199     // Check against official conditions specified by <insertNew>
00200     const Assertion* condO = m_iNew->getOfficial();
00201     Row empty;
00202     std::vector<std::string> colNames;
00203     std::vector<std::string> colValues;
00204     std::vector<std::string> nullCols;
00205 
00206     row.regroup(colNames, colValues, nullCols);
00207 
00208     satisfied = condO->verify(empty, row);
00209 
00210     // If not official, do insert and exit
00211     if (!satisfied) {
00212       bool ok = m_connect->insertRow(m_name, colNames, colValues,
00213                                      serial, &nullCols);
00214       return (ok) ?  0 : -1;
00215     }
00216 
00217     const std::vector<InterRow* >& inter = m_iNew->getInterRow();
00218 
00219     unsigned nInter = inter.size();
00220     Assertion* subsAssert;
00221     for (unsigned iInter = 0; iInter < nInter; iInter++) {
00222       const Query* q = inter[iInter]->getQuery();
00223       const std::vector<std::string>& toSelect = q->getToSelect();
00224 
00225       // Need to make a new Assertion which substitues our proposed row
00226       // values for all "toBe" entries
00227       subsAssert = new Assertion(q->getAssertion(), &row);
00228 
00229       std::vector<std::string> orderCols;
00230       orderCols.clear();
00231       ResultHandle* r = m_connect->select(m_name, toSelect, orderCols, 
00232                                           subsAssert);
00233 
00234       if (r->getNRows() == 0) {    // no conflicts found
00235         delete subsAssert;
00236         continue;   // go on to next InterRow, if any.  
00237       }
00238 
00239       // otherwise
00240       //    if quit  go ahead and quit
00241       if (inter[iInter]->getQuit()) {
00242         delete subsAssert;
00243         (*m_out) << "insert latest not done because of irreconcilable " 
00244                  << std::endl << "conflict with existing rows" << std::endl;
00245         return -1;
00246       }
00247       //    else modify conflicting rows as specified in <interRow>.
00248       //    (i.e., do an update with where clause = subsAssert
00249 
00250       std::vector<Set> sets = inter[iInter]->getSets();
00251 
00252       bool iu = doInterUpdate(sets, subsAssert, row);
00253       if (!iu) return -1;
00254     }
00255     // Insert and exit
00256     bool ok = m_connect->insertRow(m_name, colNames, colValues,
00257                                    serial, &nullCols);
00258     return (ok) ?  0 : -1;
00259   }
00260 
00261   int Table::insertRow(Row& row, int* serial) const {
00262 
00263     if (!m_connect) {
00264       throw RdbException("Table::insertRow Need matching connection");
00265     }
00266     row.rowSort();
00267 
00268     // Fill in columns in m_programCols list
00269     fillProgramCols(row, true);
00270 
00271 
00272     // Check that all required columns are there and not null
00273     for (unsigned i = 0; i < m_userCols.size(); i++) {
00274       FieldVal* f = row.find(m_userCols[i]->getName());
00275       if ((!f) || (f->m_null)) {
00276         std::string 
00277           msg("Table::insertRow Row to be inserted missing req'd field ");
00278         msg = msg + m_userCols[i]->getName();
00279         throw RdbException(msg);
00280       }
00281     }
00282 
00283     // Fill in defaults
00284     fillDefaults(row);
00285 
00286     // Check standard valid row condition if there is one
00287     if (m_validRow) {
00288       bool satisfied;
00289       try {
00290         satisfied = m_validRow->verify(row, row);
00291       }
00292       catch (RdbException ex) {
00293         (*m_out) << ex.getMsg() << std::endl;
00294         return -1;
00295       }
00296       if (!satisfied) {
00297         // throw RdbException("Table::insertRow Row to be inserted is not valid");
00298         (*m_out) << "Table::insertRow Row to be inserted is not valid " 
00299                   << std::endl;
00300         m_out->flush();
00301         return -1;
00302       }
00303     }
00304     // Insert and exit
00305     std::vector<std::string> colNames;
00306     std::vector<std::string> colValues;
00307     std::vector<std::string> nullCols;
00308 
00309     row.regroup(colNames, colValues, nullCols);
00310     bool ok = m_connect->insertRow(m_name, colNames, colValues,
00311                                    serial, &nullCols);
00312     return (ok) ?  0 : -1;
00313   }    
00314 
00315   int Table::supersedeRow(Row& row, int oldKey, int* serial) const {
00316     std::string oldKeyStr;
00317     facilities::Util::itoa(oldKey, oldKeyStr);
00318 
00319     if (m_primaryKeyCol.size() == 0) {
00320       throw RdbException("Table::supersedeRow No primary key column!");
00321     }
00322 
00323     // Confirm that row does not contain any of the fixed or oldForced columns
00324     row.rowSort();
00325     const std::vector<std::string>& forced = m_sup->getForced();
00326     for (unsigned i = 0; i < forced.size(); i++) {
00327       if (row.find(forced[i])) {
00328         //        throw RdbException
00329         //          (std::string("Table::supersedeRow bad column in input row ") +
00330         // forced[i]);
00331         (*m_out) << "Table::supersedeRow bad column in input row '"
00332                  << forced[i] << "'" << std::endl;
00333         m_out->flush();
00334         return -1;
00335       }
00336     }
00337     const std::vector<FieldVal>& fixed = m_sup->getFixed();
00338     for (unsigned i = 0; i < fixed.size(); i++) {
00339       if (row.find(fixed[i].m_colname)) {
00340         //        throw RdbException
00341         //          (std::string("Table::supersedeRow bad column in input row ") +
00342         //           fixed[i].m_colname);
00343         (*m_out) << "Table::supersedeRow bad column in input row " <<
00344           fixed[i].m_colname;
00345         m_out->flush();
00346         return -1;
00347       }
00348     }
00349 
00350     // Check that old row is supersedable
00351     if (!isSupersedable(oldKeyStr)) {
00352       *m_out << "Row " << oldKey << " is not supersedable" << std::endl;
00353       m_out->flush();
00354       return -1;
00355     }
00356     
00357     // Fill in fixed fields
00358     const std::vector<std::string>& fixedInterp = m_sup->getFixedInterp();
00359     for (unsigned i = 0; i < fixed.size(); i++) {
00360 
00361       FieldVal fv = fixed[i];
00362       if (fixedInterp[i].size() > 0) {
00363         Column* c = getColumnByName(fixed[i].m_colname);
00364         c->interpret(fixedInterp[i], fv.m_val);
00365       }
00366       row.addField(fv);
00367     }
00368     row.rowSort();
00369 
00370     // Fetch needed fields from row to be superseded (oldKey)
00371     Assertion::Operator* whereOp = 
00372       new Assertion::Operator(OPTYPEequal, m_primaryKeyCol,
00373                               oldKeyStr, FIELDTYPEold, FIELDTYPElit);
00374     Assertion* where = new Assertion(whereOp);
00375 
00376     std::vector<std::string> noCols;
00377     const std::vector<std::string>& fromOld = m_sup->getFromOld();
00378     noCols.clear();
00379     ResultHandle* results = m_connect->select(m_name, fromOld, 
00380                                               noCols, where);
00381     //    std::vector<std::string> vals;
00382     //    results->getRow(vals);
00383     std::vector<std::string*> vals;
00384     results->getRowPtrs(vals);
00385     // Merge as needed into our row.  First bunch may already be in the row
00386     unsigned nDef = m_sup->getOldDefaulted().size();
00387     for (unsigned i = 0; i < nDef; i++) {
00388       if (!(row.find(fromOld[i])) ) {
00389         if (vals[i] == 0) {
00390           row.addField(FieldVal(fromOld[i], "", true));
00391         }
00392         else {
00393           row.addField(FieldVal(fromOld[i], *vals[i]));
00394         }
00395         row.rowSort();
00396       }
00397     }
00398     // Remainder definitely have to be merged in
00399     for (unsigned i = nDef; i < fromOld.size(); i++) {
00400       if (vals[i] == 0) {
00401         row.addField(FieldVal(fromOld[i], "", true));
00402       }
00403       else {
00404         row.addField(FieldVal(fromOld[i], *vals[i]));
00405       }
00406     }
00407     results->cleanFieldPtrs(vals);
00408     
00409     // Insert the row and update old row
00410     int insRet;
00411     try {
00412       insRet = insertRow(row, serial);
00413     }
00414     catch (RdbException ex) {
00415       (*m_out) << ex.getMsg() << std::endl;
00416       insRet = -1;
00417     }
00418 
00419     if (insRet) { // something went wrong
00420       delete where;
00421       return insRet;
00422     }
00423 
00424     // Do the update of old row
00425     const std::vector<Set*>& setOld = m_sup->getSetOld();
00426     std::vector<FieldVal> oldFields;
00427     oldFields.reserve(setOld.size());
00428     for (unsigned i = 0; i < setOld.size(); i++) {
00429       std::string src = setOld[i]->getSrcValue();
00430       std::string col = setOld[i]->getDestColName();
00431       if (setOld[i]->hasInterp() ) {
00432         Column* c = getColumnByName(col);
00433         c->interpret(setOld[i]->getInterp(), src);
00434       }
00435       oldFields.push_back(FieldVal(col, src));
00436     }
00437     Row updateArg(oldFields);
00438     try {
00439       int iUpdated = updateRows(updateArg, where);
00440       if (iUpdated == 1) return 0;
00441       return -1;
00442     }
00443     catch (RdbException uEx) {
00444       (*m_out) << uEx.getMsg() << std::endl;
00445       return -1;
00446     }
00447   }
00448 
00449   int Table::updateRows(Row &row, Assertion* where) const {
00450 
00451     if (!m_connect) {
00452       throw RdbException("Table::insertLatest Need matching connection");
00453     }
00454     row.rowSort();
00455 
00456     // Fill in columns in m_programCols list
00457     fillProgramCols(row, false);
00458 
00459     std::vector<std::string> colNames;
00460     std::vector<std::string> colValues;
00461     std::vector<std::string> nullCols;
00462 
00463     row.regroup(colNames, colValues, nullCols);
00464 
00465     return m_connect->update(m_name, colNames, colValues, where, &nullCols);
00466   }
00467 
00468   bool Table::fillProgramCols(Row& row, bool newRow) const {
00469     std::string val;
00470 
00471     for (unsigned i = 0; i < m_programCols.size(); i++) {
00472       Column* col = m_programCols[i];
00473       switch (col->getContentsType() ) {
00474       case Column::CONTENTSserviceName: 
00475         val="rdbModel";
00476         break;
00477       case Column::CONTENTSusername: {
00478 #ifdef    __GNUG__ 
00479         val = std::string("$(USER)");
00480 #else
00481         val = std::string("$(USERNAME)");
00482 #endif
00483 
00484         int nsub = facilities::Util::expandEnvVar(&val);
00485         if (nsub != 1) {
00486           val="no username";
00487         }
00488         break;
00489       }
00490 
00491       case Column::CONTENTSinsertTime:
00492         if (!newRow) continue;   // otherwise, same as updateTime case
00493       case Column::CONTENTSupdateTime: {
00494         facilities::Timestamp curTime;
00495         val = curTime.getString();
00496         break;
00497       }
00498       default:
00499         return false;    // unrecognized type
00500       }
00501       // look for this field in Row input. If there, overwrite value
00502       FieldVal* f = row.find(col->getName());
00503       if (f) {
00504         f->m_val = val;
00505         f->m_null = false;
00506       } 
00507       else {
00508         FieldVal g(col->getName(), val, false);
00509         row.addField(g);
00510         row.rowSort();
00511       }
00512     }
00513     return true;
00514   }
00515 
00516   void Table::fillDefaults(Row& row) const {
00517     for (unsigned i = 0; i < m_mayDefault.size(); i++) {
00518       Column* hasDef = m_mayDefault[i];
00519       FieldVal* f = row.find(hasDef->getName());
00520       if (f) continue;  
00521       // otherwise add it it
00522       if ((hasDef->getDefault()).size() > 0) {
00523         FieldVal g(hasDef->getName(), hasDef->getDefault());
00524         row.addField(g);
00525       }
00526       else {   // null
00527         FieldVal g(hasDef->getName(), "", true);
00528         row.addField(g);
00529       }
00530       row.rowSort();
00531     }
00532   }
00533 
00534       
00535   //  Source in <set>
00536   // should either be FIELDTYPElit or FIELDTYPEtoBe.   In latter
00537   // case, substitute from row argument.
00538   bool Table::doInterUpdate(const std::vector<Set>& sets, 
00539                             Assertion* subsAssert, Row& toBe)  const     {
00540     unsigned nSets = sets.size();
00541     std::vector<FieldVal> fields;
00542     fields.reserve(nSets);
00543 
00544     for (unsigned iSet = 0; iSet < sets.size(); iSet++) {
00545       std::string col = sets[iSet].getDestColName();
00546       std::string src;
00547       //      updateCols.push_back(sets[iSet].getDestColName());
00548       FIELDTYPE srcType = sets[iSet].getSrcType();
00549       if ((srcType == FIELDTYPElit) || (srcType == FIELDTYPElitDef)) {
00550         src = sets[iSet].getSrcValue();
00551         // May require special handling
00552         if (sets[iSet].hasInterp()) {
00553           Column* c = getColumnByName(col);
00554           c->interpret(sets[iSet].getInterp(), src);
00555           /*  should know how to substitute, e.g. val="NOW" should
00556            be transformed into a timestamp           */
00557         }
00558       }
00559       else {   // must be toBe
00560         std::string toBeCol = sets[iSet].getSrcValue();
00561         FieldVal* f = toBe.find(toBeCol);
00562         if (f == 0) {
00563           delete subsAssert;
00564           (*m_out) << "Table::InsertNew Row argument missing needed field"
00565                    << toBeCol << std::endl;
00566           m_out->flush();
00567           return false;
00568           //          throw RdbException
00569           //            ("Table::InsertNew Row argument missing needed field");
00570         }
00571         src = f->m_val;
00572         //        updateVals.push_back(f->m_val);
00573       }
00574       FieldVal g(col, src);
00575       fields.push_back(g);
00576     }
00577     Row row(fields);
00578 
00579     fillProgramCols(row, false);
00580 
00581     std::vector<std::string> updateCols;
00582     std::vector<std::string> updateVals;
00583     std::vector<std::string> nullCols;
00584 
00585     row.regroup(updateCols, updateVals, nullCols);
00586 
00587     // Make specified changes (update)
00588     m_connect->update(m_name, updateCols, updateVals, subsAssert);
00589     
00590     delete subsAssert;
00591     return true;
00592   }
00593 
00594   const std::string& Table::setPrimaryKeyCol() {
00595     static const std::string empty("");
00596     if (m_primaryKeyCol.size() > 0) return m_primaryKeyCol;
00597 
00598     for (unsigned iCol = 0; iCol < m_cols.size(); iCol++) {
00599       if (m_cols[iCol]->isPrimaryKey()) {
00600         m_primaryKeyCol = m_cols[iCol]->getName();
00601         return m_primaryKeyCol;
00602       }
00603     }
00604     return empty;
00605   }
00606 
00607   bool Table::isSupersedable(std::string oldKeyStr) const {
00608     // Make a copy of supersedable condition
00609     Row emptyRow;
00610     Assertion::Operator* onlyIf = 
00611       new Assertion::Operator((m_sup->getOnlyIf())->getOperator(), 
00612                               &emptyRow);
00613     // Make operator for key == oldKey
00614     Assertion::Operator* ser =
00615       new Assertion::Operator(OPTYPEequal,  m_primaryKeyCol,
00616                               oldKeyStr, FIELDTYPEold, FIELDTYPElit);
00617     std::vector<Assertion::Operator*> children;
00618     children.push_back(onlyIf);
00619     children.push_back(ser);
00620     Assertion::Operator* whereOp = 
00621       new Assertion::Operator(OPTYPEand, children);
00622 
00623     std::vector<std::string> queryCols;
00624     queryCols.push_back(m_primaryKeyCol);
00625     Assertion* where = new Assertion(whereOp);
00626     ResultHandle* results = m_connect->select(m_name, queryCols, queryCols,
00627                                               where);
00628     delete where;
00629 
00630     return (results->getNRows() > 0);
00631   }
00632 
00633 }

Generated on Tue Nov 29 22:57:57 2016 for BOSS_7.0.2 by  doxygen 1.4.7