gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-2191-ga4742ac
a Global And Modular Bsm Inference Tool
sqlitereader.hpp
Go to the documentation of this file.
1 // GAMBIT: Global and Modular BSM Inference Tool
2 // *********************************************
19 
20 #include <sqlite3.h> // SQLite3 C interface
21 
25 
26 #include <boost/preprocessor/seq/for_each_i.hpp>
27 
28 #ifndef __sqlite_reader_hpp__
29 #define __sqlite_reader_hpp__
30 
31 namespace Gambit
32 {
33  namespace Printers
34  {
35 
36  class SQLiteReader : public BaseReader, public SQLiteBase
37  {
38  public:
39  SQLiteReader(const Options& options);
40  ~SQLiteReader();
41 
43  virtual void reset(); // Reset 'read head' position to first entry
44  virtual ulong get_dataset_length(); // Get length of input dataset
45  virtual PPIDpair get_next_point(); // Get next rank/ptID pair in data file
46  virtual PPIDpair get_current_point(); // Get current rank/ptID pair in data file
47  virtual ulong get_current_index(); // Get a linear index which corresponds to the current rank/ptID pair in the iterative sense
48  virtual bool eoi(); // Check if 'current point' is past the end of the data file (and thus invalid!)
51  virtual std::size_t get_type(const std::string& label);
52  virtual std::set<std::string> get_all_labels(); // Get all dataset labels
54 
56  using BaseReader::_retrieve; // Tell compiler we are using some of the base class overloads of this on purpose.
57  #define DECLARE_RETRIEVE(r,data,i,elem) bool _retrieve(elem&, const std::string&, const uint, const ulong);
59  #ifndef SCANNER_STANDALONE
61  #endif
62  #undef DECLARE_RETRIEVE
63 
64  private:
65 
66  // Flag that will be set to false when the end of the input table selection is reached
67  bool eoi_flag;
68 
69  // SQL statement variable used to access current row of table iteration
70  sqlite3_stmt *stmt;
71 
72  // Variables needed by e.g. postprocessor to track where we are in the database
73  ulong current_dataset_index; // index in input dataset of the current read-head position
74  PPIDpair current_point; // PPID of the point at the current read-head position
75 
76  // Map from column name to column position
77  std::map<std::string, std::size_t, Utils::ci_less> column_map;
78 
79  // Map from column name to column type
80  std::map<std::string, std::string, Utils::ci_less> column_types;
81 
82  // Move the SQL loop ahead one position
83  void move_to_next_point();
84 
85  // Build map from column name to column position
86  void build_column_map();
87 
88  // Safely access the column_map and throw informative error when column is missing
89  std::size_t get_col_i(const std::string& col_name);
90 
91  // Template function for retrieving SQLite column data as various types
92  // Need specialisations for each type in SQLITE_CPP_TYPES
93  template<typename T> T get_sql_col(const std::string& col_name);
94 
97  template<class T>
98  bool _retrieve_template(T& out, const std::string& label, int /*aux_id*/, const uint rank, const ulong pointID)
99  {
100  bool valid(false);
101  // The assumption made here is that we are iterating through the database, rather
102  // than attempting to access various random table entries constantly. So this reader object
103  // steps through the database. This means that most of the time, our sql cursor will already
104  // be pointing at the correct rank/pointID pair.
105  // In fact, for now at least, I think I will make it an ERROR if the correct rank/pointID is not
106  // at this cursor location. TODO: Consider whether more general access will be useful in the future.
107  if(not eoi())
108  {
109  if(current_point != PPIDpair(pointID,rank))
110  {
111  std::stringstream err;
112  err<<"Attempted to retrieve '"<<label<<"' from point ("<<rank<<", "<<pointID<<"), however the SQLiteReader object is not presently accessing this point (the 'current_point' is ("<<current_point.rank<<", "<<current_point.pointID<<")). At present this object is only really designed for use by the postprocessor scanner, if you have created another scanner that requires more general reader access then please make a feature request.";
113  printer_error().raise(LOCAL_INFO, err.str());
114  }
115  // Otherwise we are good to go!
116 
117  // First need to check if the result is 'null' for this entry
118  int typecode = sqlite3_column_type(stmt, get_col_i(label));
119  auto it = typecode2sql.find(typecode);
120  if( it == typecode2sql.end() )
121  {
122  std::stringstream err;
123  err<<"Received unrecognised type code from sqlite_column_type! (typecode="<<typecode<<")";
124  printer_error().raise(LOCAL_INFO, err.str());
125  }
126  else if( it->second=="NULL" )
127  {
128  // No data in this column.
129  valid = false;
130  }
131  else if(not SQLite_equaltypes(cpp2sql<T>(),it->second) )
132  {
133  // Seems to be data in the column, but type is not correct!
134  // Retrieve could still work since SQLite can do conversions,
135  // but this probably indicates a bug somewhere in this printer.
136  std::stringstream err;
137  err<<"Attempted to retrieve data from table column '"<<label<<"' as type "<<cpp2sql<T>()<<", but SQLite says that the data has type '"<<it->second<<"'. These must map to the same basic column affinity (these were "<<SQLtype_to_basic.at(cpp2sql<T>())<<" and "<<SQLtype_to_basic.at(it->second)<<" respectively)! This is probably a bug in the SQLiteReader 'retrieve' routines, please report it.";
138  printer_error().raise(LOCAL_INFO, err.str());
139  }
140  else
141  {
142  // Do the retrieval!
143  out = get_sql_col<T>(label);
144  valid = true;
145  }
146  }
147  return valid;
148  }
149 
150  };
151 
152  // Template function specialisations for retrieving SQLite column data as various types
153  // Need one for each type in SQLITE_CPP_TYPES
154  template<> long long int SQLiteReader::get_sql_col<long long int>(const std::string&);
155  template<> double SQLiteReader::get_sql_col<double> (const std::string&);
156  template<> std::string SQLiteReader::get_sql_col<std::string> (const std::string&);
157 
158  // Register reader so it can be constructed via inifile instructions
159  // First argument is string label for inifile access, second is class from which to construct printer
160  LOAD_READER(sqlite, SQLiteReader)
161 
162  }
163 }
164 
165 #endif
bool SQLite_equaltypes(const std::string &type1, const std::string &type2)
Definition: sqlitebase.cpp:125
bool _retrieve(T &, const std::string &label, const uint, const ulong)
Default _retrieve function.
unsigned long long int pointID
EXPORT_SYMBOLS error & printer_error()
Printer errors.
#define SQL_BACKEND_TYPES
Definition: sqlitetypes.hpp:38
BOOST_PP_SEQ_FOR_EACH_I(DECLARE_RETRIEVE,, SQL_TYPES) BOOST_PP_SEQ_FOR_EACH_I(DECLARE_RETRIEVE
std::map< std::string, std::size_t, Utils::ci_less > column_map
SQLite printer/reader base class declaration.
#define LOCAL_INFO
Definition: local_info.hpp:34
virtual std::set< std::string > get_all_labels()
Get labels of all datasets in the linked group.
#define LOAD_READER(tag,...)
Definition: baseprinter.hpp:60
#define SQL_TYPES
Definition: sqlitetypes.hpp:21
bool _retrieve_template(T &out, const std::string &label, int, const uint rank, const ulong pointID)
"Master" templated retrieve function.
virtual bool eoi()
Check if &#39;current point&#39; is past the end of the datasets (and thus invalid!)
virtual ulong get_dataset_length()
Get length of input dataset.
void move_to_next_point()
Move the SQL loop ahead one.
virtual std::size_t get_type(const std::string &label)
Get type information for a data entry, i.e.
SQLiteReader(const Options &options)
Declaration and definition of printer base class.
T get_sql_col(const std::string &col_name)
BASE PRINTER CLASS.
const std::map< std::string, std::string, Utils::ci_less > SQLtype_to_basic
unsigned long int ulong
virtual PPIDpair get_current_point()
Get current rank/ptID pair in data file.
#define DECLARE_RETRIEVE(r, data, i, elem)
virtual void reset()
Base class virtual interface functions.
std::size_t get_col_i(const std::string &col_name)
Safely access the column_map and throw informative error when column is missing.
virtual PPIDpair get_next_point()
Get next rank/ptID pair in data file.
Sequence of all types printable by the HDF5 printer.
SQLite base class for both reader and writer.
Definition: sqlitebase.hpp:93
pointID / process number pair Used to identify a single parameter space point
TODO: see if we can use this one:
Definition: Analysis.hpp:33
A small wrapper object for &#39;options&#39; nodes.
std::map< std::string, std::string, Utils::ci_less > column_types
const std::map< unsigned int, std::string > typecode2sql