00001
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
00055
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;
00068
00069 if (cmp < 0 ) {
00070 maxI = guess;
00071 } else {
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
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
00136
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
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
00170 fillProgramCols(row, true);
00171
00172
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
00183 fillDefaults(row);
00184
00185
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;
00198
00199
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
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
00226
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) {
00235 delete subsAssert;
00236 continue;
00237 }
00238
00239
00240
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
00248
00249
00250 std::vector<Set> sets = inter[iInter]->getSets();
00251
00252 bool iu = doInterUpdate(sets, subsAssert, row);
00253 if (!iu) return -1;
00254 }
00255
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
00269 fillProgramCols(row, true);
00270
00271
00272
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
00284 fillDefaults(row);
00285
00286
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
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
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
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
00329
00330
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
00341
00342
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
00351 if (!isSupersedable(oldKeyStr)) {
00352 *m_out << "Row " << oldKey << " is not supersedable" << std::endl;
00353 m_out->flush();
00354 return -1;
00355 }
00356
00357
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
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
00382
00383 std::vector<std::string*> vals;
00384 results->getRowPtrs(vals);
00385
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
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
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) {
00420 delete where;
00421 return insRet;
00422 }
00423
00424
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
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;
00493 case Column::CONTENTSupdateTime: {
00494 facilities::Timestamp curTime;
00495 val = curTime.getString();
00496 break;
00497 }
00498 default:
00499 return false;
00500 }
00501
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
00522 if ((hasDef->getDefault()).size() > 0) {
00523 FieldVal g(hasDef->getName(), hasDef->getDefault());
00524 row.addField(g);
00525 }
00526 else {
00527 FieldVal g(hasDef->getName(), "", true);
00528 row.addField(g);
00529 }
00530 row.rowSort();
00531 }
00532 }
00533
00534
00535
00536
00537
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
00548 FIELDTYPE srcType = sets[iSet].getSrcType();
00549 if ((srcType == FIELDTYPElit) || (srcType == FIELDTYPElitDef)) {
00550 src = sets[iSet].getSrcValue();
00551
00552 if (sets[iSet].hasInterp()) {
00553 Column* c = getColumnByName(col);
00554 c->interpret(sets[iSet].getInterp(), src);
00555
00556
00557 }
00558 }
00559 else {
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
00569
00570 }
00571 src = f->m_val;
00572
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
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
00609 Row emptyRow;
00610 Assertion::Operator* onlyIf =
00611 new Assertion::Operator((m_sup->getOnlyIf())->getOperator(),
00612 &emptyRow);
00613
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 }