ATLAS Offline Software
Loading...
Searching...
No Matches
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
11
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
25void 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) {
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
136unsigned int SqliteRecordset::size() const
137{
138 return m_records.size();
139}
140
141std::string SqliteRecordset::nodeName() const
142{
143 return m_nodeName;
144}
145
147{
148 return m_records[index].get();
149}
154
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
std::unique_ptr< IRDBRecord > IRDBRecord_ptr
static Double_t rc
std::variant< int, long, float, double, std::string > SqliteInp
std::map< std::string, SqliteInpType > SqliteInpDef
SqliteInpType
@ SQLITEINP_UNDEF
@ SQLITEINP_STRING
@ SQLITEINP_DOUBLE
@ SQLITEINP_INT
Declaration of the SqliteRecordset class.
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
IRDBRecord is one record in the IRDBRecordset object.
Definition IRDBRecord.h:27
RecordsVector::const_iterator const_iterator
SqliteRecord is one record in the SqliteRecordset object.
void addValue(const std::string &field, SqliteInp value)
unsigned int size() const override
RecordsVector m_records
const IRDBRecord * operator[](unsigned int index) const override
IRDBRecordset::const_iterator begin() const override
void getData(sqlite3 *db, const std::string &nodeName)
Constructs SQL query and retrieves data from the DB.
SqliteInpDef_ptr m_def
IRDBRecordset::const_iterator end() const override
SqliteRecordset()
Construct empty recordset.
std::string nodeName() const override
std::string m_nodeName
Definition index.py:1
STL namespace.