1 #include "otsdaq/TableCore/TableBase.h"
6 #include "otsdaq/TableCore/TableInfoReader.h"
11 #define __MF_SUBJECT__ "TableBase"
13 #define __COUT_HDR__ ("TableBase-" + getTableName() + "\t<> ")
15 const std::string TableBase::GROUP_CACHE_PREPEND =
"GroupCache_";
16 const std::string TableBase::JSON_DOC_PREPEND =
"JSONDoc_";
17 const std::string TableBase::GROUP_METADATA_TABLE_NAME =
"TableGroupMetadata";
26 std::string* accumulatedExceptions)
27 : MAX_VIEWS_IN_CACHE(20)
29 , tableName_(tableName)
31 , mockupTableView_(tableName)
40 std::cout <<
"TableBase Before traceTID=" << traceTID << __E__;
42 traceInit(trace_name(TRACE_NAME, __TRACE_FILE__, buf,
sizeof(buf)), 0);
43 std::cout <<
"TableBase After traceTID=" << traceTID << __E__;
44 __COUT__ <<
"TableBase TRACE reinit and Constructed." << __E__;
49 __SS__ <<
"Do not allow anonymous table view construction!" << __E__;
55 if(tableName_ == TableBase::GROUP_METADATA_TABLE_NAME)
62 if(tableName.substr(0, TableBase::GROUP_CACHE_PREPEND.length()) ==
63 TableBase::GROUP_CACHE_PREPEND ||
64 tableName.substr(0, TableBase::JSON_DOC_PREPEND.length()) ==
65 TableBase::JSON_DOC_PREPEND)
67 __COUTT__ <<
"TableBase for special table '" << tableName <<
"' constructed."
78 __COUT__ <<
"Reading..." << __E__;
81 std::string returnedExceptions = tableInfoReader.read(
this);
84 if(returnedExceptions !=
"")
85 __COUT_ERR__ << returnedExceptions << __E__;
87 if(accumulatedExceptions)
88 *accumulatedExceptions += std::string(
"\n") + returnedExceptions;
92 __SS__ <<
"Failure reading table schema info for table '" << tableName <<
"!' "
94 "table definition has moved or been corrupted? Check your "
101 catch(
const std::runtime_error& e)
103 ss <<
"Here was the error:\n" << e.what() << __E__;
109 __COUT_ERR__ <<
"\n" << ss.str();
110 if(accumulatedExceptions)
111 *accumulatedExceptions += std::string(
"\n") + ss.str();
117 __COUT__ <<
"Initializing..." << __E__;
121 getMockupViewP()->
init();
123 __COUT__ <<
"Init." << __E__;
125 catch(std::runtime_error&
128 if(accumulatedExceptions)
129 *accumulatedExceptions += std::string(
"\n") + e.what();
141 : MAX_VIEWS_IN_CACHE(1)
143 , tableName_(specialTableName)
144 , activeTableView_(0)
145 , mockupTableView_(specialTableName)
154 std::cout <<
"TableBase Before traceTID=" << traceTID << __E__;
156 traceInit(trace_name(TRACE_NAME, __TRACE_FILE__, buf,
sizeof(buf)), 0);
157 std::cout <<
"TableBase After traceTID=" << traceTID << __E__;
158 __COUT__ <<
"TableBase TRACE reinit and Constructed." << __E__;
161 __COUTT__ <<
"Special table '" << tableName_ <<
"' constructed. " << specialTable
165 if(tableName_ == TableBase::GROUP_METADATA_TABLE_NAME)
174 __COUTT__ <<
"Special table '" << tableName_ <<
"' constructing..." << __E__;
187 std::vector<TableViewColumnInfo>* colInfo = getMockupViewP()->getColumnsInfoP();
201 TableViewColumnInfo::DATATYPE_STRING,
208 TableViewColumnInfo::TYPE_COMMENT,
209 TableViewColumnInfo::COL_NAME_COMMENT,
210 "COMMENT_DESCRIPTION",
211 TableViewColumnInfo::DATATYPE_STRING,
218 TableViewColumnInfo::TYPE_AUTHOR,
221 TableViewColumnInfo::DATATYPE_STRING,
229 "GROUP_CREATION_TIME",
230 TableViewColumnInfo::DATATYPE_TIME,
237 setActiveView(tmpVersion);
241 __COUTT__ <<
"Special table '" << tableName_ <<
"' constructed." << __E__;
257 std::string TableBase::getTypeId() {
return typeid(
this).name(); }
266 void TableBase::reset(
bool keepTemporaryVersions)
270 if(keepTemporaryVersions)
281 if(!activeTableView_)
283 __COUT_ERR__ <<
"ERROR: No active view set" << __E__;
286 activeTableView_->print(out);
294 if(!isStored(version))
298 mockupTableView_, version, mockupTableView_.getAuthor());
300 if(!isStored(version))
302 __SS__ <<
"IMPOSSIBLE ERROR: trimCache() is deleting the "
303 "latest view version "
304 << version <<
"!" << __E__;
310 __SS__ <<
"View to fill with mockup already exists: " << version
311 <<
". Cannot overwrite!" << __E__;
326 if(trimSize == (
unsigned int)-1)
333 time_t stalestTime = -1;
336 if(!viewPair.first.isTemporaryVersion())
338 if(stalestTime == -1 || viewPair.second.getLastAccessTime() < stalestTime)
340 versionToDelete = viewPair.first;
341 stalestTime = viewPair.second.getLastAccessTime();
349 __SS__ <<
"Can NOT have a stored view with an invalid version!" << __E__;
353 eraseView(versionToDelete);
368 if(it->first.isTemporaryVersion())
371 if(activeTableView_ &&
384 eraseView(targetVersion);
389 __SS__ <<
"Temporary trim target was a persistent version: " << targetVersion
411 __SS__ <<
"needleVersion does not exist: " << needleVersion << __E__;
415 const TableView* needleView = &(needleIt->second);
416 unsigned int rows = needleView->getNumberOfRows();
417 unsigned int cols = needleView->getNumberOfColumns();
420 unsigned int potentialMatchCount = 0;
425 __COUTTV__(needleVersion);
426 __COUTTV__(ignoreVersion);
432 auto viewPairReverseIterator =
tableViews_.rbegin();
433 for(; viewPairReverseIterator !=
tableViews_.rend(); ++viewPairReverseIterator)
435 __COUTTV__(viewPairReverseIterator->first);
436 if(viewPairReverseIterator->first == needleVersion)
438 __COUTVS__(2, viewPairReverseIterator->first);
439 if(viewPairReverseIterator->first == ignoreVersion)
441 __COUTVS__(2, viewPairReverseIterator->first);
442 if(viewPairReverseIterator->first.isTemporaryVersion())
444 __COUTVS__(2, viewPairReverseIterator->first);
445 if(viewPairReverseIterator->second.getNumberOfRows() != rows)
447 __COUTVS__(2, viewPairReverseIterator->first);
448 if(viewPairReverseIterator->second.getDataColumnSize() != cols ||
449 viewPairReverseIterator->second.getSourceColumnMismatch() != 0)
452 ++potentialMatchCount;
453 __COUTT__ <<
"Checking version... " << viewPairReverseIterator->first << __E__;
461 match = viewPairReverseIterator->second.getSourceColumnNames().size() ==
462 needleView->getSourceColumnNames().size();
463 __COUTTV__(viewPairReverseIterator->second.getSourceColumnNames().size());
464 __COUTTV__(needleView->getSourceColumnNames().size());
467 for(
auto& haystackColName :
468 viewPairReverseIterator->second.getSourceColumnNames())
469 if(needleView->getSourceColumnNames().find(haystackColName) ==
470 needleView->getSourceColumnNames().end())
472 __COUT__ <<
"Found column name mismatch for '" << haystackColName
473 <<
"'... So allowing same data!" << __E__;
482 for(
auto& srcCol : viewPairReverseIterator->second.getSourceColumnNames())
483 __COUTT__ <<
"compare Col #" << i++ <<
" " << srcCol << __E__;
485 for(
auto& srcCol : needleView->getSourceColumnNames())
486 __COUTT__ <<
"source Col #" << i++ <<
" " << srcCol << __E__;
506 for(
unsigned int row = 0; match && row < rows; ++row)
508 for(
unsigned int col = 0; col < cols - 2;
510 if(viewPairReverseIterator->second.getDataView()[row][col] !=
511 needleView->getDataView()[row][col])
516 <<
"Value name mismatch " << col <<
":"
517 << viewPairReverseIterator->second.getDataView()[row][col] <<
"["
518 << viewPairReverseIterator->second.getDataView()[row][col].size()
520 <<
" vs " << needleView->getDataView()[row][col] <<
"["
521 << needleView->getDataView()[row][col].size() <<
"]" << __E__;
528 __COUT_INFO__ <<
"Duplicate version found: " << viewPairReverseIterator->first
530 return viewPairReverseIterator->first;
534 __COUT__ <<
"No duplicates found in " << potentialMatchCount <<
" potential matches."
545 std::stringstream* diffReport ,
546 std::map<std::string , std::vector<std::string /* colName */>>*
547 v1ModifiedRecords )
const
549 __COUTT__ <<
"Diffing version... " << v1 <<
" vs " << v2 << __E__;
554 __SS__ <<
"Version v" << v1 <<
" does not exist." << __E__;
561 __SS__ <<
"Version v" << v2 <<
" does not exist." << __E__;
565 const TableView* view1 = &(v1It->second);
566 const TableView* view2 = &(v2It->second);
567 unsigned int rows1 = view1->getNumberOfRows();
568 unsigned int cols1 = view1->getNumberOfColumns();
570 bool noDifference =
true;
578 if(view1->getSourceColumnNames().size() != view2->getSourceColumnNames().size())
580 __COUT__ <<
"Found column count mismatch for '"
581 << view1->getSourceColumnNames().size() <<
" vs "
582 << view2->getSourceColumnNames().size() << __E__;
585 *diffReport <<
"<li>Found column count mismatch. The v" << v1
586 <<
" column count is <b>'" << view1->getSourceColumnNames().size()
587 <<
"'</b> and the v" << v2 <<
" column count is <b>'"
588 << view2->getSourceColumnNames().size() <<
"'</b>." << __E__;
590 noDifference =
false;
595 for(
auto& colName1 : view1->getSourceColumnNames())
596 if(view2->getSourceColumnNames().find(colName1) ==
597 view2->getSourceColumnNames().end())
599 __COUT__ <<
"Found column name mismatch for '" << colName1 << __E__;
602 *diffReport <<
"<li>Found column name mismatch. The v" << v1
603 <<
" column <b>'" << colName1 <<
"'</b> was not found in v"
604 << v2 <<
"." << __E__;
606 noDifference =
false;
610 for(
auto& colName2 : view2->getSourceColumnNames())
611 if(view1->getSourceColumnNames().find(colName2) ==
612 view1->getSourceColumnNames().end())
614 __COUT__ <<
"Found column name mismatch for '" << colName2 << __E__;
617 *diffReport <<
"<li>Found column name mismatch. The v" << v1
618 <<
" does not have column <b>'" << colName2
619 <<
"'</b> that was found in v" << v2 <<
"." << __E__;
621 noDifference =
false;
626 if(rows1 != view2->getNumberOfRows())
628 __COUT__ <<
"Found row count mismatch for '" << rows1 <<
" vs "
629 << view2->getNumberOfRows() << __E__;
632 *diffReport <<
"<li>Found row count mismatch. The v" << v1
633 <<
" row count is <b>'" << rows1 <<
"'</b> and the v" << v2
634 <<
" row count is <b>'" << view2->getNumberOfRows() <<
"'</b>."
637 noDifference =
false;
643 std::set<std::string > uidSet1, uidSet2;
644 for(
unsigned int row = 0; row < rows1; ++row)
645 uidSet1.insert(view1->getDataView()[row][view1->
getColUID()]);
646 for(
unsigned int row = 0; row < view2->getNumberOfRows(); ++row)
647 uidSet2.insert(view2->getDataView()[row][view2->
getColUID()]);
649 for(
auto& uid1 : uidSet1)
650 if(uidSet2.find(uid1) == uidSet2.end())
652 __COUT__ <<
"Found record name mismatch for '" << uid1 << __E__;
655 *diffReport <<
"<li>Found record name mismatch. The v" << v1
656 <<
" record <b>'" << uid1 <<
"'</b> was not found in v" << v2
659 noDifference =
false;
663 for(
auto& uid2 : uidSet2)
664 if(uidSet1.find(uid2) == uidSet1.end())
666 __COUT__ <<
"Found record name mismatch for '" << uid2 << __E__;
669 *diffReport <<
"<li>Found record name mismatch. v" << v1
670 <<
" does not have record <b>'" << uid2
671 <<
"'</b> that was found in v" << v2 <<
"." << __E__;
673 noDifference =
false;
678 unsigned int row2, col2;
679 for(
unsigned int row = 0; row < rows1 && row < view2->getNumberOfRows(); ++row)
683 if(view1->getDataView()[row][view1->
getColUID()] !=
684 view2->getDataView()[row2][view2->
getColUID()])
686 bool foundUid2 =
false;
688 for(row2 = 0; row2 < view2->getNumberOfRows(); ++row2)
689 if(view1->getDataView()[row][view1->
getColUID()] ==
690 view2->getDataView()[row2][view2->
getColUID()])
695 __COUTT__ <<
"Found row ? '" << foundUid2 <<
" " << row <<
"," << row2
701 __COUTT__ <<
"Found row "
702 <<
" " << row <<
"," << row2 << __E__;
703 for(
unsigned int col = 0;
704 col < cols1 - 2 && col < view2->getNumberOfColumns() - 2;
709 if(view1->getColumnInfo(col).getName() !=
710 view2->getColumnInfo(col2).getName())
712 bool foundCol2 =
false;
714 for(col2 = 0; col2 < view2->getNumberOfColumns() - 2; ++col2)
715 if(view1->getColumnInfo(col).getName() ==
716 view2->getColumnInfo(col2).getName())
722 __COUTT__ <<
"Found column ? '" << foundCol2 <<
" " << col <<
"," << col2
728 __COUTT__ <<
"Found column "
729 <<
" " << col <<
"," << col2 << __E__;
730 if(view1->getDataView()[row][col] != view2->getDataView()[row2][col2])
732 __COUT__ <<
"Found column value mismatch for '" << row <<
"," << col
733 <<
" " << view1->getDataView()[row][col] << __E__;
736 *diffReport <<
"<li><b>" << view1->getColumnInfo(col).getName()
737 <<
"</b> value mismatch at v" << v1 <<
" {UID,r,c}:{<b>"
738 << view1->getDataView()[row][view1->
getColUID()]
739 <<
"</b>," << row <<
"," << col <<
"}: <b>'"
740 << view1->getDataView()[row][col] <<
"'</b> vs value in v"
741 << v2 <<
": <b>'" << view2->getDataView()[row2][col2]
742 <<
"'</b>." << __E__;
744 noDifference =
false;
748 if(v1ModifiedRecords)
749 (*v1ModifiedRecords)[view1->getDataView()[row][view1->
getColUID()]]
750 .push_back(view1->getColumnInfo(col).getName());
755 if(noDifference && diffReport)
756 *diffReport <<
"<li>No difference found between v" << v1 <<
" and v" << v2 <<
"."
763 void TableBase::changeVersionAndActivateView(
TableVersion temporaryVersion,
769 __SS__ <<
"ERROR: Temporary view version " << temporaryVersion
770 <<
" doesn't exists!" << __E__;
775 __SS__ <<
"ERROR: Attempting to create an invalid version " << version
776 <<
"! Did you really run out of versions? (this should never happen)"
782 __COUT_WARN__ <<
"WARNING: View version " << version
783 <<
" already exists! Overwriting." << __E__;
787 emplacePair.first->second.copy(tmpIt->second, version, tmpIt->second.getAuthor());
788 setActiveView(version);
789 eraseView(temporaryVersion);
793 bool TableBase::isStored(
const TableVersion& version)
const
801 if(!isStored(version))
804 if(activeTableView_ &&
817 const std::string& TableBase::getTableDescription(
void)
const
819 return tableDescription_;
825 return getView().getVersion();
833 std::set<TableVersion> retSet = getStoredVersions();
834 if(retSet.size() && !retSet.rbegin()->isTemporaryVersion())
836 return tableViews_.find(*(retSet.rbegin()))->second.getNumberOfColumns() !=
837 mockupTableView_.getNumberOfColumns();
844 std::set<TableVersion> TableBase::getStoredVersions(
void)
const
846 std::set<TableVersion> retSet;
848 retSet.emplace(configs.first);
860 if(viewPair.first.isTemporaryVersion())
862 else if(viewPair.first.isInvalid())
872 __COUT__ <<
"There is an invalid version now!.. where did it come from?"
886 if(version != TableVersion::INVALID)
891 __SS__ <<
"Table '" << tableName_ <<
"' does not have version v" << version
892 <<
" in the cache." << __E__;
896 if(!activeTableView_)
898 __SS__ <<
"There is no active table view setup! Please check your system "
903 return *activeTableView_;
911 if(version != TableVersion::INVALID)
916 __SS__ <<
"Table '" << tableName_ <<
"' does not have version v" << version
917 <<
" in the cache." << __E__;
921 if(!activeTableView_)
923 __SS__ <<
"There is no active table view setup! Please check your system "
928 return activeTableView_;
932 TableView* TableBase::getMockupViewP(
void) {
return &mockupTableView_; }
938 void TableBase::setTableDescription(
const std::string& tableDescription)
940 tableDescription_ = tableDescription;
955 if(!isStored(version))
960 __SS__ <<
"\nsetActiveView() ERROR: View with version " << version
961 <<
" has never been stored before!" << __E__;
967 if(
tableViews_.at(version).getVersion() != version)
969 __SS__ <<
"Something has gone very wrong with the version handling!" << __E__;
988 const std::string& author,
990 std::map<std::pair<std::string /*original table*/, std::string /*original uidB*/>,
991 std::string >& uidConversionMap,
993 std::pair<std::string ,
994 std::pair<std::string /*group linkid*/, std::string /*original gidB*/>>,
995 std::string >& groupidConversionMap,
996 bool fillRecordConversionMaps,
997 bool applyRecordConversionMaps,
998 bool generateUniqueDataColumns ,
999 std::stringstream* mergeReport )
1001 __COUT__ <<
"mergeViews starting..." << __E__;
1013 if(!(mergeApproach == MergeApproach::RENAME ||
1014 mergeApproach == MergeApproach::REPLACE || mergeApproach == MergeApproach::SKIP))
1016 __SS__ <<
"Error! Invalid merge approach." << __E__;
1021 if(sourceViewA.getNumberOfColumns() != mockupTableView_.getNumberOfColumns())
1023 __SS__ <<
"Error! Number of Columns of source view A must match destination "
1025 <<
"Dimension of source is [" << sourceViewA.getNumberOfColumns()
1026 <<
"] and of destination mockup is ["
1027 << mockupTableView_.getNumberOfColumns() <<
"]." << __E__;
1031 if(sourceViewB.getNumberOfColumns() != mockupTableView_.getNumberOfColumns())
1033 __SS__ <<
"Error! Number of Columns of source view B must match destination "
1035 <<
"Dimension of source is [" << sourceViewB.getNumberOfColumns()
1036 <<
"] and of destination mockup is ["
1037 << mockupTableView_.getNumberOfColumns() <<
"]." << __E__;
1046 std::stringstream ss;
1047 sourceViewA.print(ss);
1048 __COUTT__ <<
"mergeViews() sourceViewA:\n" << ss.str() << __E__;
1051 std::stringstream ss;
1052 sourceViewB.print(ss);
1053 __COUTT__ <<
"mergeViews() sourceViewB:\n" << ss.str() << __E__;
1058 (*mergeReport) <<
"\n'"
1059 << (mergeApproach == MergeApproach::RENAME
1061 : (mergeApproach == MergeApproach::REPLACE ?
"REPLACE"
1064 << sourceViewA.getVersion() <<
" with B=v"
1065 << sourceViewB.getVersion() << __E__;
1067 if(fillRecordConversionMaps && mergeApproach == MergeApproach::RENAME)
1069 __COUT__ <<
"Filling record conversion map." << __E__;
1079 unsigned int uniqueId;
1080 std::string uniqueIdString, uniqueIdBase;
1081 char indexString[1000];
1083 unsigned int numericStartIndex;
1086 for(
unsigned int cb = 0; cb < sourceViewB.getNumberOfColumns(); ++cb)
1089 if(!(sourceViewA.getColumnInfo(cb).
isUID() ||
1090 sourceViewA.getColumnInfo(cb).
isGroupID()))
1093 __COUT__ <<
"Have an ID column: " << cb <<
" "
1094 << sourceViewA.getColumnInfo(cb).getType() << __E__;
1097 if(sourceViewA.getColumnInfo(cb).getType() !=
1098 sourceViewB.getColumnInfo(cb).getType() ||
1099 sourceViewA.getColumnInfo(cb).getType() !=
1100 mockupTableView_.getColumnInfo(cb).getType())
1102 __SS__ <<
"Error! " << sourceViewA.getColumnInfo(cb).getType()
1104 <<
" of source view A must match source B and destination mock-up "
1106 <<
" Column of source B is ["
1107 << sourceViewA.getColumnInfo(cb).getType()
1108 <<
"] and of destination mockup is ["
1109 << mockupTableView_.getColumnInfo(cb).getType() <<
"]." << __E__;
1115 std::vector<std::string >
1118 if(sourceViewA.getColumnInfo(cb).
isGroupID())
1123 for(
const auto& bGroupid : bGroupids)
1125 if(aGroupids.find(bGroupid) == aGroupids.end())
1129 __COUT__ <<
"found conflict: " <<
getTableName() <<
"/" << bGroupid
1134 const std::string& str = bGroupid;
1135 numericStartIndex = str.size();
1138 while(numericStartIndex - 1 < str.size() &&
1139 str[numericStartIndex - 1] >=
'0' &&
1140 str[numericStartIndex - 1] <=
'9')
1141 --numericStartIndex;
1143 if(numericStartIndex < str.size())
1145 uniqueId = atoi(str.substr(numericStartIndex).c_str()) + 1;
1146 uniqueIdBase = str.substr(0, numericStartIndex);
1154 __COUTV__(uniqueIdBase);
1155 __COUTV__(uniqueId);
1160 sprintf(indexString,
"%u", uniqueId);
1161 uniqueIdString = uniqueIdBase + indexString;
1162 __COUTV__(uniqueIdString);
1166 if(aGroupids.find(uniqueIdString) != aGroupids.end())
1168 if(!found && bGroupids.find(uniqueIdString) != bGroupids.end())
1170 if(!found && bGroupids.find(uniqueIdString) != bGroupids.end())
1172 for(ra = 0; !found && ra < localConvertedIds.size(); ++ra)
1173 if(localConvertedIds[ra] == uniqueIdString)
1179 sprintf(indexString,
"%u", uniqueId);
1180 uniqueIdString = uniqueIdBase + indexString;
1181 __COUTV__(uniqueIdString);
1185 if(aGroupids.find(uniqueIdString) != aGroupids.end())
1188 bGroupids.find(uniqueIdString) != bGroupids.end())
1191 bGroupids.find(uniqueIdString) != bGroupids.end())
1193 for(ra = 0; !found && ra < localConvertedIds.size(); ++ra)
1194 if(localConvertedIds[ra] == uniqueIdString)
1200 __COUTV__(uniqueIdString);
1202 groupidConversionMap
1203 [std::pair<std::string ,
1204 std::pair<std::string ,
1207 std::pair<std::string ,
1210 bGroupid))] = uniqueIdString;
1211 localConvertedIds.push_back(uniqueIdString);
1218 <<
"Found conflicting B groupID for linkIndex '"
1220 <<
"' and renamed '" << bGroupid <<
"' to '" << uniqueIdString
1231 for(
unsigned int rb = 0; rb < sourceViewB.getNumberOfRows(); ++rb)
1235 for(ra = 0; ra < sourceViewA.getDataView().size(); ++ra)
1247 __COUT__ <<
"found conflict: " <<
getTableName() <<
"/"
1248 << sourceViewB.getDataView()[rb][cb] << __E__;
1252 const std::string& str = sourceViewB.getDataView()[rb][cb];
1253 numericStartIndex = str.size();
1256 while(numericStartIndex - 1 < str.size() &&
1257 str[numericStartIndex - 1] >=
'0' &&
1258 str[numericStartIndex - 1] <=
'9')
1259 --numericStartIndex;
1261 if(numericStartIndex < str.size())
1263 uniqueId = atoi(str.substr(numericStartIndex).c_str()) + 1;
1264 uniqueIdBase = str.substr(0, numericStartIndex);
1272 __COUTV__(uniqueIdBase);
1273 __COUTV__(uniqueId);
1278 sprintf(indexString,
"%u", uniqueId);
1279 uniqueIdString = uniqueIdBase + indexString;
1280 __COUTV__(uniqueIdString);
1284 for(ra = 0; !found && ra < sourceViewA.getDataView().size(); ++ra)
1287 for(ra = 0; !found && ra < sourceViewB.getDataView().size(); ++ra)
1293 for(ra = 0; !found && ra < localConvertedIds.size(); ++ra)
1294 if(localConvertedIds[ra] == uniqueIdString)
1300 sprintf(indexString,
"%u", uniqueId);
1301 uniqueIdString = uniqueIdBase + indexString;
1302 __COUTV__(uniqueIdString);
1306 for(ra = 0; !found && ra < sourceViewA.getDataView().size();
1310 for(ra = 0; !found && ra < sourceViewB.getDataView().size();
1317 for(ra = 0; !found && ra < localConvertedIds.size(); ++ra)
1318 if(localConvertedIds[ra] == uniqueIdString)
1324 __COUTV__(uniqueIdString);
1326 uidConversionMap[std::pair<std::string ,
1330 localConvertedIds.push_back(uniqueIdString);
1335 (*mergeReport) <<
"\t"
1336 <<
"Found conflicting B UID and renamed '"
1338 << uniqueIdString <<
"'" << __E__;
1349 __COUT__ <<
"Not filling record conversion map." << __E__;
1351 if(!applyRecordConversionMaps)
1353 __COUT__ <<
"Not applying record conversion map." << __E__;
1358 __COUT__ <<
"Applying record conversion map." << __E__;
1366 __COUT__ <<
"Merging from (A) " << sourceViewA.getTableName() <<
"_v"
1367 << sourceViewA.getVersion() <<
" and (B) " << sourceViewB.getTableName()
1368 <<
"_v" << sourceViewB.getVersion() <<
" to " <<
getTableName() <<
"_v"
1369 << destinationVersion <<
" with approach '"
1370 << (mergeApproach == MergeApproach::RENAME
1372 : (mergeApproach == MergeApproach::REPLACE ?
"REPLACE" :
"SKIP"))
1384 .copy(sourceViewA, destinationVersion, author));
1386 unsigned int destRow, destSize = destinationView->getDataView().size();
1389 std::map<std::pair<std::string , std::string >,
1390 std::string >::iterator uidConversionIt;
1391 std::map<std::pair<std::string ,
1392 std::pair<std::string ,
1394 std::string >::iterator groupidConversionIt;
1397 std::pair<
unsigned int ,
unsigned int > linkPair;
1401 unsigned int colUID = mockupTableView_.
getColUID();
1404 for(
unsigned int rb = 0; rb < sourceViewB.getNumberOfRows(); ++rb)
1406 if(mergeApproach == MergeApproach::RENAME)
1416 destRow = destinationView->
copyRows(
1422 generateUniqueDataColumns );
1426 for(cb = 0; cb < sourceViewB.getNumberOfColumns(); ++cb)
1432 __COUT__ <<
"Checking UID link... col=" << cb << __E__;
1436 if((uidConversionIt = uidConversionMap.find(
1437 std::pair<std::string ,
1441 rb, linkPair.second)))) != uidConversionMap.end())
1443 __COUT__ <<
"Found entry to remap: "
1444 << sourceViewB.getDataView()[rb][linkPair.second]
1445 <<
" ==> " << uidConversionIt->second << __E__;
1450 <<
"Found entry to remap [r,c]=[" << rb <<
"," << cb
1453 << sourceViewB.getDataView()[rb][linkPair.second]
1454 <<
" ==> [" << destRow <<
"," << linkPair.second
1455 << uidConversionIt->second << __E__;
1457 uidConversionIt->second, destRow, linkPair.second);
1462 __COUT__ <<
"Checking GroupID link... col=" << cb << __E__;
1466 if((groupidConversionIt = groupidConversionMap.find(
1467 std::pair<std::string ,
1468 std::pair<std::string ,
1471 std::pair<std::string ,
1475 rb, linkPair.second))))) !=
1476 groupidConversionMap.end())
1478 __COUT__ <<
"Found entry to remap: "
1479 << sourceViewB.getDataView()[rb][linkPair.second]
1480 <<
" ==> " << groupidConversionIt->second << __E__;
1485 <<
"Found entry to remap [r,c]=[" << rb <<
"," << cb
1488 << sourceViewB.getDataView()[rb][linkPair.second]
1489 <<
" ==> [" << destRow <<
"," << linkPair.second
1490 <<
"] " << groupidConversionIt->second << __E__;
1492 groupidConversionIt->second, destRow, linkPair.second);
1495 else if(sourceViewB.getColumnInfo(cb).
isUID())
1497 __COUT__ <<
"Checking UID... col=" << cb << __E__;
1498 if((uidConversionIt = uidConversionMap.find(
1499 std::pair<std::string ,
1503 uidConversionMap.end())
1505 __COUT__ <<
"Found entry to remap: "
1506 << sourceViewB.getDataView()[rb][cb] <<
" ==> "
1507 << uidConversionIt->second << __E__;
1512 <<
"Found entry to remap [r,c]=[" << rb <<
"," << cb
1514 <<
": " << sourceViewB.getDataView()[rb][cb]
1515 <<
" ==> [" << destRow <<
"," << cb <<
"] "
1516 << uidConversionIt->second << __E__;
1518 uidConversionIt->second, destRow, cb);
1521 else if(sourceViewB.getColumnInfo(cb).
isGroupID())
1523 __COUT__ <<
"Checking GroupID... col=" << cb << __E__;
1524 if((groupidConversionIt = groupidConversionMap.find(
1525 std::pair<std::string ,
1526 std::pair<std::string ,
1529 std::pair<std::string ,
1533 groupidConversionMap.end())
1535 __COUT__ <<
"Found entry to remap: "
1536 << sourceViewB.getDataView()[rb][cb] <<
" ==> "
1537 << groupidConversionIt->second << __E__;
1542 <<
"Found entry to remap [r,c]=[" << rb <<
"," << cb
1543 <<
"]" << sourceViewB.getDataView()[rb][cb]
1544 <<
" ==> [" << destRow <<
"," << cb <<
"] "
1545 << groupidConversionIt->second << __E__;
1547 groupidConversionIt->second, destRow, cb);
1554 if(strb.size() >
getTableName().size() + 2 && strb[0] ==
'/')
1557 __COUT__ <<
"Checking col" << cb <<
" " << strb << __E__;
1560 for(
const auto& mapPairToPair : uidConversionMap)
1562 if((stri = strb.find(mapPairToPair.first.first +
"/" +
1563 mapPairToPair.first.second)) !=
1566 __COUT__ <<
"Found a text link match (stri=" << stri
1568 << (mapPairToPair.first.first +
"/" +
1569 mapPairToPair.first.second)
1570 <<
" ==> " << mapPairToPair.second << __E__;
1574 strb.substr(0, stri) +
1575 (mapPairToPair.first.first +
"/" +
1576 mapPairToPair.first.second) +
1578 (mapPairToPair.first.first +
"/" +
1579 mapPairToPair.first.second)
1585 <<
"Found entry to remap: "
1586 << sourceViewB.getDataView()[rb][cb] <<
" ==> "
1587 << destinationView->getDataView()[destRow][cb]
1593 <<
"Found entry to remap [r,c]=[" << rb <<
","
1595 << sourceViewB.getDataView()[rb][cb]
1596 <<
" ==> [" << destRow <<
"," << cb <<
"] "
1597 << destinationView->getDataView()[destRow][cb]
1613 for(destRow = 0; destRow < destSize; ++destRow)
1623 << (mergeApproach == MergeApproach::RENAME
1625 : (mergeApproach == MergeApproach::REPLACE ?
"REPLACE"
1627 <<
" conflict: " << __E__;
1629 if(mergeApproach == MergeApproach::REPLACE ||
1630 mergeApproach == MergeApproach::SKIP)
1635 author, sourceViewB, rb, 1 );
1644 __COUT__ <<
"found "
1645 << (mergeApproach == MergeApproach::RENAME
1647 : (mergeApproach == MergeApproach::REPLACE ?
"REPLACE"
1649 <<
" conflict: " << sourceViewB.getDataView()[rb][colUID] << __E__;
1651 if(mergeApproach == MergeApproach::REPLACE)
1656 <<
"Found UID conflict, replacing A with B record row=" << rb
1657 <<
" " << sourceViewB.getDataView()[rb][colUID] << __E__;
1667 destinationView->
copyRows(author, sourceViewB, rb, 1 );
1669 else if(mergeApproach ==
1670 MergeApproach::SKIP)
1675 <<
"Found UID conflict, skipping B record row=" << rb <<
" "
1676 << sourceViewB.getDataView()[rb][colUID] << __E__;
1682 std::stringstream ss;
1683 destinationView->print(ss);
1684 __COUTT__ <<
"mergeViews() destinationView:\n" << ss.str() << __E__;
1689 __COUT_ERR__ <<
"Failed to merge " << sourceViewA.getTableName() <<
"_v"
1690 << sourceViewA.getVersion() <<
" and " << sourceViewB.getTableName()
1691 <<
"_v" << sourceViewB.getVersion() <<
" into " <<
getTableName()
1692 <<
"_v" << destinationVersion << __E__;
1693 __COUT_WARN__ <<
"Deleting the failed destination version " << destinationVersion
1695 eraseView(destinationVersion);
1699 return destinationVersion;
1712 const std::string& author,
1713 bool looseColumnMatching )
1716 if(!looseColumnMatching &&
1717 sourceView.getNumberOfColumns() != mockupTableView_.getNumberOfColumns())
1719 __SS__ <<
"Error! Number of Columns of source view must match destination "
1721 <<
"Dimension of source is [" << sourceView.getNumberOfColumns()
1722 <<
"] and of destination mockup is ["
1723 << mockupTableView_.getNumberOfColumns() <<
"]." << __E__;
1731 __SS__ <<
"Error! Asked to copy a view with a conflicting version: "
1732 << destinationVersion << __E__;
1739 __COUT__ <<
"Copying from " << sourceView.getTableName() <<
"_v"
1740 << sourceView.getVersion() <<
" to " <<
getTableName() <<
"_v"
1741 << destinationVersion << __E__;
1746 tableViews_.at(destinationVersion).copy(sourceView, destinationVersion, author);
1750 __COUT_ERR__ <<
"Failed to copy from " << sourceView.getTableName() <<
"_v"
1751 << sourceView.getVersion() <<
" to " <<
getTableName() <<
"_v"
1752 << destinationVersion << __E__;
1753 __COUT_WARN__ <<
"Deleting the failed destination version " << destinationVersion
1755 eraseView(destinationVersion);
1759 return destinationVersion;
1780 while(isStored(tmpVersion) &&
1783 if(isStored(tmpVersion) || tmpVersion.
isInvalid())
1785 __SS__ <<
"Invalid destination temporary version: " << destTemporaryViewVersion
1786 <<
". Expected next temporary version < " << tmpVersion << __E__;
1790 if(sourceViewVersion ==
1791 TableVersion::INVALID ||
1794 if(sourceViewVersion != -1)
1796 __SS__ <<
"ERROR: sourceViewVersion " << sourceViewVersion <<
" not found. "
1797 <<
"Invalid source version. Version requested is not stored (yet?) or "
1802 __COUTT__ <<
"Using Mock-up view" << __E__;
1805 .copy(mockupTableView_, tmpVersion, mockupTableView_.getAuthor());
1820 <<
"createTemporaryView() Source view failed init(). "
1821 <<
"This is being ignored (hopefully the new copy is being fixed)."
1846 __SS__ <<
"Invalid destination temporary version: " << tmpVersion << __E__;
1869 __SS__ <<
"Invalid destination next version: " << tmpVersion << __E__;
1884 __SS__ <<
getTableName() <<
":: Error! Temporary version not found!" << __E__;
1897 unsigned int tablePos = (
unsigned int)std::string::npos;
1899 ((tablePos = str.find(
"Table")) != str.size() - strlen(
"Table") ||
1901 (
unsigned int)std::string::npos))
1906 std::string capsStr =
"";
1907 for(
unsigned int c = 0; c < str.size(); ++c)
1908 if(str[c] >=
'A' && str[c] <=
'Z')
1912 (c && str[c - 1] >=
'a' &&
1913 str[c - 1] <=
'z') ||
1914 (c && str[c - 1] >=
'A' &&
1915 str[c - 1] <=
'Z' &&
1916 c + 1 < str.size() && str[c + 1] >=
'a' && str[c + 1] <=
'z') ||
1917 (c && str[c - 1] >=
'0' &&
1918 str[c - 1] <=
'9' &&
1919 c + 1 < str.size() && str[c + 1] >=
'a' && str[c + 1] <=
'z'))
1923 else if(str[c] >=
'a' && str[c] <=
'z')
1924 capsStr += char(str[c] - 32);
1925 else if(str[c] >=
'0' && str[c] <=
'9')
1930 if((str.substr(0, TableBase::GROUP_CACHE_PREPEND.length()) ==
1931 TableBase::GROUP_CACHE_PREPEND ||
1932 str.substr(0, TableBase::JSON_DOC_PREPEND.length()) ==
1933 TableBase::JSON_DOC_PREPEND) &&
1940 std::stringstream ss;
1941 ss << __COUT_HDR_FL__
1942 <<
"TableBase::convertToCaps: Invalid character found in name (allowed: "
1944 << str <<
"'" << __E__;
1945 TLOG(TLVL_ERROR) << ss.str();
const std::string & getTableName(void) const
Getters.
std::map< TableVersion, TableView > tableViews_
TableVersion createTemporaryView(TableVersion sourceViewVersion=TableVersion(), TableVersion destTemporaryViewVersion=TableVersion::getNextTemporaryVersion())
source of -1, from MockUp, else from valid view version
void setupMockupView(TableVersion version)
bool diffTwoVersions(TableVersion v1, TableVersion v2, std::stringstream *diffReport=0, std::map< std::string, std::vector< std::string >> *v1ModifiedRecords=0) const
MergeApproach
Merge approach enumeration for mergeViews function.
TableBase(bool specialTable, const std::string &specialTableName)
void trimTemporary(TableVersion targetVersion=TableVersion())
unsigned int getNumberOfStoredViews(void) const
TableVersion checkForDuplicate(TableVersion needleVersion, TableVersion ignoreVersion=TableVersion()) const
bool isActive(void)
isActive
TableVersion mergeViews(const TableView &sourceViewA, const TableView &sourceViewB, TableVersion destinationVersion, const std::string &author, MergeApproach mergeApproach, std::map< std::pair< std::string, std::string >, std::string > &uidConversionMap, std::map< std::pair< std::string, std::pair< std::string, std::string > >, std::string > &groupidConversionMap, bool fillRecordConversionMaps, bool applyRecordConversionMaps, bool generateUniqueDataColumns=false, std::stringstream *mergeRepoert=nullptr)
static std::string convertToCaps(std::string &str, bool isConfigName=false)
TableView * getTemporaryView(TableVersion temporaryVersion)
const unsigned int MAX_VIEWS_IN_CACHE
TableVersion getNextVersion(void) const
const TableVersion & getViewVersion(void) const
always the active one
TableVersion copyView(const TableView &sourceView, TableVersion destinationVersion, const std::string &author, bool looseColumnMatching=false)
bool latestAndMockupColumnNumberMismatch(void) const
void setTableName(const std::string &tableName)
Setters.
void print(std::ostream &out=std::cout) const
always prints active view
void specialMetaTableConstructor(void)
Methods.
TableVersion getNextTemporaryVersion(void) const
void trimCache(unsigned int trimSize=-1)
bool isInvalid(void) const
isInvalid
static TableVersion getNextVersion(const TableVersion &version=TableVersion())
bool isTemporaryVersion(void) const
static TableVersion getNextTemporaryVersion(const TableVersion &version=TableVersion())
bool isChildLinkUID(void) const
static const std::string DATATYPE_NUMBER
std::string getChildLinkIndex(void) const
getChildLinkIndex
bool isChildLink(void) const
bool isUID(void) const
isUID
bool isGroupID(void) const
static const std::string TYPE_UID
NOTE: Do NOT put '-' in static const TYPEs because it will mess up javascript handling in the web gui...
bool isChildLinkGroupID(void) const
void setValueAsString(const std::string &value, unsigned int row, unsigned int col)
bool getChildLink(const unsigned int &col, bool &isGroup, std::pair< unsigned int, unsigned int > &linkPair) const
unsigned int copyRows(const std::string &author, const TableView &src, unsigned int srcOffsetRow=0, unsigned int srcRowsToCopy=(unsigned int) -1, unsigned int destOffsetRow=(unsigned int) -1, unsigned char generateUniqueDataColumns=false, const std::string &baseNameAutoUID="")
std::string getValueAsString(unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const
std::set< std::string > getSetOfGroupIDs(const std::string &childLinkIndex, unsigned int row=-1) const
unsigned int getColUID(void) const
unsigned int addRow(const std::string &author="", unsigned char incrementUniqueData=false, const std::string &baseNameAutoUID="", unsigned int rowToAdd=(unsigned int) -1, std::string childLinkIndex="", std::string groupId="")
defines used also by OtsConfigurationWizardSupervisor
static std::string mapToString(const std::map< std::string, T > &mapToReturn, const std::string &primaryDelimeter=", ", const std::string &secondaryDelimeter=": ")
static std::string stackTrace(void)