ATLAS Offline Software
RDBRecordset.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
15 #include "RDBAccessSvc.h"
16 #include "RDBRecordset.h"
17 #include "RDBRecord.h"
18 
19 #include "RelationalAccess/ISessionProxy.h"
20 #include "RelationalAccess/ICursor.h"
21 #include "RelationalAccess/ITableDescription.h"
22 #include "RelationalAccess/IQuery.h"
23 #include "RelationalAccess/ISchema.h"
24 #include "RelationalAccess/ITable.h"
25 #include "RelationalAccess/IColumn.h"
26 #include "RelationalAccess/SchemaException.h"
27 
29 
30 #include "CoralBase/Attribute.h"
31 #include "CoralBase/AttributeList.h"
32 
33 #include "GaudiKernel/MsgStream.h"
34 
35 #include <stdexcept>
36 #include <iostream>
37 #include <set>
38 
39 void RDBRecordset::getData(coral::ISessionProxy* session
40  , const std::string& nodeName
41  , const std::string& tagName
42  , const std::string& tagId)
43 {
44  if(m_accessSvc->msg().level() <= MSG::DEBUG) {
45  m_accessSvc->msg() << MSG::DEBUG << "Recordset get data " << nodeName << ", "
46  << tagName << ", "
47  << tagId << endmsg;
48  }
49 
50  if(session==0) {
51  m_accessSvc->msg() << MSG::ERROR << "RT: No connection to database!" << endmsg;
52  return;
53  }
54 
55  try
56  {
58 
59  if(tagId.empty()) {
60  if(m_accessSvc->msg().level() <= MSG::DEBUG)
61  m_accessSvc->msg() << MSG::DEBUG << "RT: Could not get the tag for " << m_tableName
62  << " node. Returning empty recordset" << endmsg;
63  return;
64  }
65 
67 
68  // change table name to upper case
69  std::string upperName = m_tableName;
70  for (char& ch : upperName) {
71  ch = std::toupper (static_cast<unsigned int>(ch));
72  }
73 
74  coral::IQuery* queryStructure = session->nominalSchema().newQuery();
75 
76  // Compose the list of output fields for queryStructure
77  const coral::ITableDescription& dataTableDesc = session->nominalSchema().tableHandle(upperName + "_DATA").description();
78  for(int i=0; i<dataTableDesc.numberOfColumns(); i++) {
79  queryStructure->addToOutputList(upperName + "_DATA." + dataTableDesc.columnDescription(i).name());
80  }
81 
82  // Create table list for query >> data and data2vers tables
83  queryStructure->addToTableList(upperName + "_DATA");
84  queryStructure->addToTableList(upperName + "_DATA2TAG");
85 
87  bindsData.extend<std::string>("tagID");
88 
89  // Compose condition for structure query
90  std::string queryStructCondition = upperName +"_DATA2TAG." + upperName + "_TAG_ID =:tagID";
91  queryStructCondition += " AND " + upperName +"_DATA." + upperName + "_DATA_ID=" + upperName + "_DATA2TAG." + upperName + "_DATA_ID";
92 
93  queryStructure->setCondition(queryStructCondition , bindsData);
94  bindsData[0].data<std::string>() = tagId;
95 
96  queryStructure->addToOrderList(upperName + "_DATA." + upperName + "_DATA_ID");
97  queryStructure->setMemoryCacheSize(1);
98 
99  coral::ICursor& cursorStructure = queryStructure->execute();
100 
101  // Process Query results
102  while(cursorStructure.next()) {
103  const coral::AttributeList& row = cursorStructure.currentRow();
104  m_records.push_back(IRDBRecord_ptr(new RDBRecord(row,upperName + "_DATA")));
105  }
106 
107  delete queryStructure;
108  }
109  catch(coral::SchemaException& se) {
110  m_accessSvc->msg() << MSG::ERROR<< "RT: Schema Exception : " << se.what() << endmsg;
111  }
112  catch(std::exception& e) {
113  m_accessSvc->msg() << MSG::ERROR << e.what() << endmsg;
114  }
115  catch(...) {
116  m_accessSvc->msg() << MSG::ERROR << "RT: Exception caught(...)" << endmsg;
117  }
118 
119 }
120 
121 unsigned int RDBRecordset::size() const
122 {
123  return m_records.size();
124 }
125 
126 std::string RDBRecordset::nodeName() const
127 {
128  return m_tableName;
129 }
130 
131 std::string RDBRecordset::tagName() const
132 {
133  return m_tagName;
134 }
135 
136 const IRDBRecord* RDBRecordset::operator[](unsigned int index) const
137 {
138  return m_records[index].get();
139 }
141 {
142  return m_records.begin();
143 }
144 
146 {
147  return m_records.end();
148 }
149 
151 {
152  if(m_records.size()!=rhs.m_records.size()) return true;
153 
154  for(size_t i=0; i<m_records.size(); ++i) {
155  RDBRecord* rec1 = dynamic_cast<RDBRecord*>(m_records[i].get());
156  RDBRecord* rec2 = dynamic_cast<RDBRecord*>(rhs.m_records[i].get());
157  if(rec1!=0
158  && rec2!=0
159  && *rec1!=*rec2) return true;
160  }
161 
162  return false;
163 }
164 
165 void RDBRecordset::compare(const RDBRecordset& rec, std::ostream& os) const
166 {
167  if(m_tableName!=rec.m_tableName) {
168  os << "Recordsets correspond to different nodes" << std::endl;
169  return;
170  }
171 
172  if(m_tagName!=rec.m_tagName) {
173  os << "Recordsets correspond to different tags" << std::endl;
174  return;
175  }
176 
177  std::set<size_t> uniq0, uniq1;
178  std::vector<long> dataId0, dataId1;
179 
180  // change table name to upper case
181  std::string upperName = m_tableName;
182  for (char& ch : upperName) {
183  ch = std::toupper (static_cast<unsigned int>(ch));
184  }
185 
186  // Collect data_id's for both recordsets
187  for(size_t i=0; i<m_records.size(); ++i) {
188  dataId0.push_back(m_records[i]->getLong(upperName+"_DATA_ID"));
189  }
190 
191  for(size_t i=0; i<rec.m_records.size(); ++i) {
192  dataId1.push_back(rec.m_records[i]->getLong(upperName+"_DATA_ID"));
193  }
194 
195  // print out possible diffs of recordsets with same data id's
196  // collect indices of records with data_id's unique to rec0 (this)
197  bool diffFound = false;
198  for(size_t i=0; i<dataId0.size(); ++i) {
199  long id0 = dataId0[i];
200  bool found = false;
201  size_t i1(0);
202  for(size_t ii=0; ii<dataId1.size(); ++ii) {
203  if(id0==dataId1[ii]) {
204  found = true;
205  i1 = ii;
206  break;
207  }
208  }
209  if(found) {
210  RDBRecord* record0 = dynamic_cast<RDBRecord*>(m_records[i].get());
211  RDBRecord* record1 = dynamic_cast<RDBRecord*>(rec.m_records[i1].get());
212  if(record0!=0
213  && record1!=0
214  && *record0!=*record1) {
215  if(!diffFound) {
216  os << "Records with the same data id and different contents:" << std::endl;
217  diffFound = true;
218  }
219  os << "< " << *record0 << std::endl;
220  os << "> " << *record1 << std::endl;
221  os << "--" << std::endl;
222  }
223  }
224  else
225  uniq0.insert(i);
226  }
227 
228  // collect indices of records with data_id's unique to rec1
229  for(size_t i=0; i<dataId1.size(); ++i) {
230  long id1 = dataId1[i];
231  bool found = false;
232  for(size_t ii=0; ii<dataId0.size(); ++ii) {
233  if(id1==dataId0[ii]) {
234  found = true;
235  break;
236  }
237  }
238  if(!found) {
239  uniq1.insert(i);
240  }
241  }
242 
243  // print out results
244  if(uniq0.size()>0) {
245  os << "Records with the following data ids are present in recordset 0 and missing in recordset 1: " << std::endl;
246  std::set<size_t>::const_iterator it = uniq0.begin();
247  for(; it!=uniq0.end(); ++it) {
248  os << m_records[*it]->getLong(upperName+"_DATA_ID") << " ";
249  }
250  os << std::endl;
251  }
252  if(uniq1.size()>0) {
253  os << "Records with the following data ids are present in recordset 1 and missing in recordset 0: " << std::endl;
254  std::set<size_t>::const_iterator it = uniq1.begin();
255  for(; it!=uniq1.end(); ++it) {
256  os << rec.m_records[*it]->getLong(upperName+"_DATA_ID") << " ";
257  }
258  os << std::endl;
259  }
260 
261 }
262 
263 void RDBRecordset::setNodeName(const std::string& nodeName)
264 {
265  if(m_tableName.empty()) m_tableName = nodeName;
266 }
query_example.row
row
Definition: query_example.py:24
RDBRecord.h
Definition of RDBRecord class.
RDBRecordset::tagName
std::string tagName() const override
Definition: RDBRecordset.cxx:131
sendEI_SPB.ch
ch
Definition: sendEI_SPB.py:35
RDBRecordset::m_accessSvc
RDBAccessSvc * m_accessSvc
Definition: RDBRecordset.h:86
RDBAccessSvc.h
Definition of RDBAccessSvc class.
index
Definition: index.py:1
skel.it
it
Definition: skel.GENtoEVGEN.py:423
RDBRecord
RDBRecord is one record in the RDBRecordset object.
Definition: RDBRecord.h:35
python.PyKernel.AttributeList
AttributeList
Definition: PyKernel.py:36
RDBRecordset::end
IRDBRecordset::const_iterator end() const override
Definition: RDBRecordset.cxx:145
keylayer_zslicemap.se
se
Definition: keylayer_zslicemap.py:194
lumiFormat.i
int i
Definition: lumiFormat.py:92
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
calibdata.exception
exception
Definition: calibdata.py:496
RDBRecordset::operator!=
bool operator!=(const RDBRecordset &rhs) const
Definition: RDBRecordset.cxx:150
RDBRecordset::nodeName
std::string nodeName() const override
Definition: RDBRecordset.cxx:126
RDBRecordset::size
unsigned int size() const override
Definition: RDBRecordset.cxx:121
ReadFromCoolCompare.os
os
Definition: ReadFromCoolCompare.py:231
RDBRecordset::m_tagName
std::string m_tagName
Definition: RDBRecordset.h:84
RDBRecordset::m_records
RecordsVector m_records
Definition: RDBRecordset.h:85
RDBRecordset::begin
IRDBRecordset::const_iterator begin() const override
Definition: RDBRecordset.cxx:140
RDBRecordset::m_tableName
std::string m_tableName
Definition: RDBRecordset.h:83
RDBRecordset::getData
void getData(coral::ISessionProxy *session, const std::string &nodeName, const std::string &tagName, const std::string &tagId)
Constructs SQL query and retrieves the data from DB.
Definition: RDBRecordset.cxx:39
DeMoScan.index
string index
Definition: DeMoScan.py:362
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
CondAlgsOpts.found
int found
Definition: CondAlgsOpts.py:101
RDBRecordset.h
Definition of RDBRecordset class.
IRDBRecord
IRDBRecord is one record in the IRDBRecordset object.
Definition: IRDBRecord.h:27
DEBUG
#define DEBUG
Definition: page_access.h:11
IRDBRecord_ptr
std::unique_ptr< IRDBRecord > IRDBRecord_ptr
Definition: IRDBRecordset.h:23
AthCommonMsg::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
RDBRecordset::setNodeName
void setNodeName(const std::string &nodeName)
Definition: RDBRecordset.cxx:263
RDBRecordset::operator[]
const IRDBRecord * operator[](unsigned int index) const override
Definition: RDBRecordset.cxx:136
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
checker_macros.h
Define macros for attributes used to control the static checker.
IRDBRecordset::const_iterator
RecordsVector::const_iterator const_iterator
Definition: IRDBRecordset.h:52
RDBRecordset
RDBRecordset is an implementation of IRDBRecordset interface.
Definition: RDBRecordset.h:39
RDBRecordset::compare
void compare(const RDBRecordset &rec, std::ostream &os) const
Definition: RDBRecordset.cxx:165