ATLAS Offline Software
SqliteRecordset.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
12 #include "SqliteRecordset.h"
13 
14 #include <sqlite3.h>
15 #include <stdexcept>
16 #include <sstream>
17 #include <set>
18 
20  : AthMessaging("SqliteRecordset")
21  , m_def(std::make_shared<SqliteInpDef>())
22 {
23 }
24 
25 void SqliteRecordset::getData(sqlite3* db, const std::string& nodeName)
26 {
27  //the following should already be checked by the calling code and should never happen
28  if (db == nullptr){
29  throw std::runtime_error("SqliteRecordset::getData : db pointer is null");
30  }
31  if (nodeName.empty()){
32  throw std::runtime_error("SqliteRecordset::getData : nodeName is empty");
33  }
34  ATH_MSG_DEBUG("getData for " << nodeName);
36 
37  std::ostringstream sql;
38 
39  // First check if the table exists in the database
40  sql << "select * from " << m_nodeName;
41  sqlite3_stmt* stTable{nullptr};
42  int rc = sqlite3_prepare_v2(db, sql.str().c_str(), -1, &stTable, NULL);
43  if(rc!=SQLITE_OK) {
44  ATH_MSG_INFO(m_nodeName << " table is not found in the database");
45  return;
46  }
47 
48  sql << " order by " << m_nodeName << "_data_id";
49  sqlite3_stmt* st{nullptr};
50  rc = sqlite3_prepare_v2(db, sql.str().c_str(), -1, &st, NULL);
51  if(rc!=SQLITE_OK) {
52  ATH_MSG_ERROR("Error occurred when preparing to fetch data for " << m_nodeName);
53  ATH_MSG_ERROR("SQLite Error: " << sqlite3_errmsg(db));
54  return;
55  }
56  int ctotal = sqlite3_column_count(st);
57 
58  bool all_ok{true};
59 
60  while(true) {
61  rc = sqlite3_step(st);
62 
63  if(rc == SQLITE_ROW) {
64  SqliteRecord* rec = new SqliteRecord(m_def);
65  IRDBRecord_ptr record{rec};
66 
67  // Loop throug the fields of the retrieved record
68  for(int i=0; i<ctotal; ++i) {
69 
70  // The feature of SQLite: if in the given record some fields have NULL values,
71  // then the data type of the corresponding columns is reported as NULL.
72  // This means that we need to be able to build the Def gradually, as we read
73  // in new records of the table
74 
75  // Do we need to extend Def?
76  std::string columnName = sqlite3_column_name(st,i);
77  bool extendDef = (m_def->find(columnName)==m_def->end());
78 
79  auto columnType = sqlite3_column_type(st,i);
81  SqliteInp val;
82 
83  switch(columnType) {
84  case SQLITE_INTEGER:
85  inpType = SQLITEINP_INT;
86  val = sqlite3_column_int(st,i);
87  break;
88  case SQLITE_FLOAT:
89  inpType = SQLITEINP_DOUBLE;
90  val = sqlite3_column_double(st,i);
91  break;
92  case SQLITE_TEXT:
93  inpType = SQLITEINP_STRING;
94  val = std::string((char*)(sqlite3_column_text(st,i)));
95  break;
96  case SQLITE_BLOB:
97  inpType = SQLITEINP_STRING;
98  val = std::string((char*)(sqlite3_column_blob(st,i)));
99  break;
100  case SQLITE_NULL:
101  continue;
102  default:
103  break;
104  }
105 
106  if(inpType==SQLITEINP_UNDEF) {
107  all_ok = false;
108  ATH_MSG_ERROR("Unexpected data type in column " << columnName << " of the table " << m_nodeName);
109  break;
110  }
111 
112  if(extendDef) {
113  (*m_def)[columnName] = inpType;
114  }
115  rec->addValue(columnName,val);
116  }
117  m_records.push_back(std::move(record));
118  }
119  else if(rc == SQLITE_DONE) {
120  break;
121  }
122  else {
123  ATH_MSG_ERROR("Error occurred when fetching data for " << m_nodeName);
124  ATH_MSG_ERROR("SQLite Error: " << sqlite3_errmsg(db));
125  all_ok = false;
126  break;
127  }
128  }
129 
130  if(!all_ok) {
131  // Do memory cleanup
132  m_records.clear();
133  }
134 }
135 
136 unsigned int SqliteRecordset::size() const
137 {
138  return m_records.size();
139 }
140 
141 std::string SqliteRecordset::nodeName() const
142 {
143  return m_nodeName;
144 }
145 
146 const IRDBRecord* SqliteRecordset::operator[](unsigned int index) const
147 {
148  return m_records[index].get();
149 }
151 {
152  return m_records.begin();
153 }
154 
156 {
157  return m_records.end();
158 }
SqliteInp
std::variant< int, long, float, double, std::string > SqliteInp
Definition: SqliteRecord.h:37
SqliteRecordset.h
Declaration of the SqliteRecordset class.
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
index
Definition: index.py:1
CaloCondBlobAlgs_fillNoiseFromASCII.db
db
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:42
SqliteRecordset::m_records
RecordsVector m_records
Definition: SqliteRecordset.h:62
SqliteRecordset::getData
void getData(sqlite3 *db, const std::string &nodeName)
Constructs SQL query and retrieves data from the DB.
Definition: SqliteRecordset.cxx:25
SqliteRecordset::m_nodeName
std::string m_nodeName
Definition: SqliteRecordset.h:60
SQLITEINP_UNDEF
@ SQLITEINP_UNDEF
Definition: SqliteRecord.h:30
SQLITEINP_INT
@ SQLITEINP_INT
Definition: SqliteRecord.h:25
SqliteInpDef
std::map< std::string, SqliteInpType > SqliteInpDef
Definition: SqliteRecord.h:39
SqliteRecordset::nodeName
std::string nodeName() const override
Definition: SqliteRecordset.cxx:141
beamspotman.sql
sql
Definition: beamspotman.py:672
SqliteRecordset::begin
IRDBRecordset::const_iterator begin() const override
Definition: SqliteRecordset.cxx:150
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
SQLITEINP_DOUBLE
@ SQLITEINP_DOUBLE
Definition: SqliteRecord.h:28
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
SQLITEINP_STRING
@ SQLITEINP_STRING
Definition: SqliteRecord.h:29
SqliteRecord::addValue
void addValue(const std::string &field, SqliteInp value)
Definition: SqliteRecord.cxx:102
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
SqliteRecordset::end
IRDBRecordset::const_iterator end() const override
Definition: SqliteRecordset.cxx:155
SqliteRecord
SqliteRecord is one record in the SqliteRecordset object.
Definition: SqliteRecord.h:49
SqliteInpType
SqliteInpType
Definition: SqliteRecord.h:24
DeMoScan.index
string index
Definition: DeMoScan.py:362
Pythia8_RapidityOrderMPI.val
val
Definition: Pythia8_RapidityOrderMPI.py:14
IRDBRecord
IRDBRecord is one record in the IRDBRecordset object.
Definition: IRDBRecord.h:27
SqliteRecordset::m_def
SqliteInpDef_ptr m_def
Definition: SqliteRecordset.h:61
IRDBRecord_ptr
std::unique_ptr< IRDBRecord > IRDBRecord_ptr
Definition: IRDBRecordset.h:23
SqliteRecordset::size
unsigned int size() const override
Definition: SqliteRecordset.cxx:136
SqliteRecordset::operator[]
const IRDBRecord * operator[](unsigned int index) const override
Definition: SqliteRecordset.cxx:146
SqliteRecordset::SqliteRecordset
SqliteRecordset()
Construct empty recordset.
Definition: SqliteRecordset.cxx:19
IRDBRecordset::const_iterator
RecordsVector::const_iterator const_iterator
Definition: IRDBRecordset.h:52