Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:01:27

0001 #ifndef CondCore_ConditionDatabase_DbCore_h
0002 #define CondCore_ConditionDatabase_DbCore_h
0003 //
0004 // Package:     CondDB
0005 // Class  :     DbCore
0006 //
0007 /**\class DbCore DbCore.h CondCore/CondDB/interface/DbCore.h
0008    Description: an interface wrapper for CORAL.  
0009 */
0010 //
0011 // Author:      Miguel Ojeda, Giacomo Govi
0012 // Created:     May 2013
0013 //
0014 //
0015 
0016 #include "CondCore/CondDB/interface/Exception.h"
0017 #include "CondCore/CondDB/interface/Binary.h"
0018 #include "CondCore/CondDB/interface/Time.h"
0019 #include "CondCore/CondDB/interface/Types.h"
0020 // coral includes
0021 #include "CoralBase/AttributeList.h"
0022 #include "CoralBase/Attribute.h"
0023 #include "CoralBase/AttributeSpecification.h"
0024 #include "CoralBase/Blob.h"
0025 #include "CoralBase/TimeStamp.h"
0026 #include "RelationalAccess/ICursor.h"
0027 #include "RelationalAccess/ISchema.h"
0028 #include "RelationalAccess/ISessionProxy.h"
0029 #include "RelationalAccess/IQuery.h"
0030 #include "RelationalAccess/TableDescription.h"
0031 #include "RelationalAccess/ITable.h"
0032 #include "RelationalAccess/IColumn.h"
0033 #include "RelationalAccess/ITableDataEditor.h"
0034 #include "RelationalAccess/IBulkOperation.h"
0035 #include "RelationalAccess/IBulkOperation.h"
0036 #include "RelationalAccess/SchemaException.h"
0037 //
0038 #include <tuple>
0039 #include <cstring>
0040 #include <set>
0041 #include <map>
0042 #include <memory>
0043 //
0044 #include <boost/date_time/posix_time/posix_time.hpp>
0045 
0046 // macros for the schema definition
0047 
0048 // table definition
0049 #define conddb_table(NAME)                      \
0050   namespace NAME {                              \
0051     static constexpr char const* tname = #NAME; \
0052   }                                             \
0053   namespace NAME
0054 
0055 // implementation for the column definition:
0056 
0057 // case with 3 params
0058 #define FIXSIZE_COLUMN(NAME, TYPE, SIZE)                                                \
0059   struct NAME {                                                                         \
0060     static constexpr char const* name = #NAME;                                          \
0061     typedef TYPE type;                                                                  \
0062     static constexpr size_t size = SIZE;                                                \
0063     static std::string tableName() { return std::string(tname); }                       \
0064     static std::string fullyQualifiedName() { return std::string(tname) + "." + name; } \
0065   };
0066 
0067 // case with 2 params
0068 #define VARSIZE_COLUMN(NAME, TYPE) FIXSIZE_COLUMN(NAME, TYPE, 0)
0069 
0070 // trick to select the case
0071 #define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4
0072 #define WRONG_PAR_NUMBER_ERROR(...) static_assert(false, "\"column\" macro accepts exactly 2 or 3 parameters")
0073 #define SELECT_COLUMN_MACRO(...) GET_4TH_ARG(__VA_ARGS__, FIXSIZE_COLUMN, VARSIZE_COLUMN, WRONG_PAR_NUMBER_ERROR)
0074 
0075 // the final column definition macro
0076 #define conddb_column(...) SELECT_COLUMN_MACRO(__VA_ARGS__)(__VA_ARGS__)
0077 
0078 namespace cond {
0079 
0080   namespace persistency {
0081 
0082     // helper function to asses the equality of the underlying types, regardless if they are references and their constness
0083     template <typename T, typename P>
0084     inline void static_assert_is_same_decayed() {
0085       static_assert(std::is_same<typename std::decay<T>::type, typename std::decay<P>::type>::value,
0086                     "Parameter types don't match with the RowBuffer types");
0087     };
0088 
0089     // functions ( specilized for specific types ) for adding data in AttributeList buffers
0090     template <typename T>
0091     inline void f_add_attribute(coral::AttributeList& data,
0092                                 const std::string& attributeName,
0093                                 const T& param,
0094                                 bool init = true) {
0095       if (init)
0096         data.extend<T>(attributeName);
0097       data[attributeName].data<T>() = param;
0098     }
0099 
0100     template <>
0101     inline void f_add_attribute(coral::AttributeList& data,
0102                                 const std::string& attributeName,
0103                                 const cond::Binary& param,
0104                                 bool init) {
0105       if (init)
0106         data.extend<coral::Blob>(attributeName);
0107       data[attributeName].bind(param.get());
0108     }
0109 
0110     template <>
0111     inline void f_add_attribute(coral::AttributeList& data,
0112                                 const std::string& attributeName,
0113                                 const boost::posix_time::ptime& param,
0114                                 bool init) {
0115       if (init)
0116         data.extend<coral::TimeStamp>(attributeName);
0117       data[attributeName].data<coral::TimeStamp>() = coral::TimeStamp(param);
0118     }
0119 
0120     template <>
0121     inline void f_add_attribute(coral::AttributeList& data,
0122                                 const std::string& attributeName,
0123                                 const cond::TimeType& param,
0124                                 bool init) {
0125       if (init)
0126         data.extend<std::string>(attributeName);
0127       data[attributeName].data<std::string>() = cond::time::timeTypeName(param);
0128     }
0129 
0130     template <>
0131     inline void f_add_attribute(coral::AttributeList& data,
0132                                 const std::string& attributeName,
0133                                 const cond::SynchronizationType& param,
0134                                 bool init) {
0135       if (init)
0136         data.extend<std::string>(attributeName);
0137       data[attributeName].data<std::string>() = synchronizationTypeNames(param);
0138     }
0139 
0140     // function for adding into an AttributeList buffer data for a specified column. Performs type checking.
0141     template <typename Column, typename P>
0142     inline void f_add_column_data(coral::AttributeList& data, const P& param, bool init = true) {
0143       static_assert_is_same_decayed<typename Column::type, P>();
0144       f_add_attribute(data, Column::name, param, init);
0145     }
0146 
0147     // function for adding into an AttributeList buffer data for a specified condition. Performs type checking.
0148     template <typename Column, typename P>
0149     inline void f_add_condition_data(coral::AttributeList& data,
0150                                      std::string& whereClause,
0151                                      const P& value,
0152                                      const std::string condition = "=") {
0153       static_assert_is_same_decayed<typename Column::type, P>();
0154       std::stringstream varId;
0155       unsigned int id = data.size();
0156       varId << Column::name << "_" << id;
0157       if (!whereClause.empty())
0158         whereClause += " AND ";
0159       whereClause += Column::fullyQualifiedName() + " " + condition + " :" + varId.str() + " ";
0160       //bool init = (id == 0);
0161       f_add_attribute(data, varId.str(), value);
0162     }
0163 
0164     // function for appending conditions to a where clause
0165     template <typename C1, typename C2>
0166     inline void f_add_condition(std::string& whereClause, const std::string condition = "=") {
0167       if (!whereClause.empty())
0168         whereClause += " AND ";
0169       whereClause += C1::fullyQualifiedName() + " " + condition + " " + C2::fullyQualifiedName() + " ";
0170     }
0171 
0172     // buffer for data to be inserted into a table
0173     // maybe better only leave the template set methods ( no class template )
0174     template <typename... Columns>
0175     class RowBuffer {
0176     private:
0177       template <typename Params, int n, typename T1, typename... Ts>
0178       void _set(const Params& params, bool init = true) {
0179         f_add_column_data<T1>(m_data, std::get<n>(params), init);
0180         _set<Params, n + 1, Ts...>(params, init);
0181       }
0182 
0183       template <typename Params, int n>
0184       void _set(const Params&, bool) {}
0185 
0186     public:
0187       RowBuffer() : m_data() {}
0188 
0189       template <typename P>
0190       explicit RowBuffer(const P& params) : m_data() {
0191         _set<P, 0, Columns...>(params);
0192       }
0193 
0194       template <typename P>
0195       void set(const P& params) {
0196         bool init = (m_data.size() == 0);
0197         // if RowBuffer becames a single type, we need to run either the equivalent of _RowBuffer ( having addAttribute ) when m_data.size()=0, or _set in all other cases
0198         _set<P, 0, Columns...>(params, init);
0199       }
0200 
0201       const coral::AttributeList& get() const { return m_data; }
0202 
0203     protected:
0204       coral::AttributeList m_data;
0205     };
0206 
0207     template <typename... Columns>
0208     class ConditionBuffer {
0209     private:
0210       template <typename Params, int n, typename T1, typename... Ts>
0211       void _set(const Params& params) {
0212         f_add_condition_data<T1>(m_data, m_clause, std::get<n>(params));
0213         _set<Params, n + 1, Ts...>(params);
0214       }
0215 
0216       template <typename Params, int n>
0217       void _set(const Params&) {}
0218 
0219     public:
0220       ConditionBuffer() : m_data(), m_clause() {}
0221 
0222       template <typename P>
0223       void set(const P& params) {
0224         // if RowBuffer becames a single type, we need to run either the equivalent of _RowBuffer ( having addAttribute ) when m_data.size()=0, or _set in all other cases
0225         _set<P, 0, Columns...>(params);
0226       }
0227 
0228       void addStaticCondition(const std::string& condition) {
0229         if (!m_clause.empty()) {
0230           m_clause += " AND ";
0231         }
0232         m_clause += condition;
0233       }
0234 
0235       const coral::AttributeList& get() const { return m_data; }
0236 
0237       const std::string& getClause() const { return m_clause; }
0238 
0239     protected:
0240       coral::AttributeList m_data;
0241       std::string m_clause;
0242     };
0243 
0244     template <typename T>
0245     struct AttributeTypeName {
0246       std::string operator()() { return coral::AttributeSpecification::typeNameForType<T>(); }
0247     };
0248     template <>
0249     struct AttributeTypeName<cond::Binary> {
0250       std::string operator()() { return coral::AttributeSpecification::typeNameForType<coral::Blob>(); }
0251     };
0252     template <>
0253     struct AttributeTypeName<boost::posix_time::ptime> {
0254       std::string operator()() { return coral::AttributeSpecification::typeNameForType<coral::TimeStamp>(); }
0255     };
0256     template <>
0257     struct AttributeTypeName<cond::TimeType> {
0258       std::string operator()() { return coral::AttributeSpecification::typeNameForType<std::string>(); }
0259     };
0260     template <>
0261     struct AttributeTypeName<cond::SynchronizationType> {
0262       std::string operator()() { return coral::AttributeSpecification::typeNameForType<std::string>(); }
0263     };
0264 
0265     template <typename T>
0266     void f_add_column_description(coral::TableDescription& table,
0267                                   const std::string& columnName,
0268                                   size_t size = 0,
0269                                   bool notNull = true) {
0270       table.insertColumn(columnName, AttributeTypeName<T>()(), size);
0271       if (notNull)
0272         table.setNotNullConstraint(columnName);
0273     }
0274 
0275     template <typename T, typename Arg1>
0276     constexpr bool is_same_any() {
0277       return std::is_same<T, Arg1>::value;
0278     };
0279 
0280     template <typename T, typename Arg1, typename Arg2, typename... Args>
0281     constexpr bool is_same_any() {
0282       return is_same_any<T, Arg1>() || is_same_any<T, Arg2, Args...>();
0283     };
0284 
0285     template <typename... Types>
0286     class TableDescription {
0287     private:
0288       template <int n>
0289       void addColumn(coral::TableDescription&) {}
0290 
0291       template <int n, typename Arg1, typename... Args>
0292       void addColumn(coral::TableDescription& tableDescription) {
0293         std::string columnName(Arg1::name);
0294         f_add_column_description<typename Arg1::type>(m_description, columnName, Arg1::size);
0295         addColumn<n + 1, Args...>(m_description);
0296       }
0297 
0298       template <int, typename Col1, typename... Cols>
0299       void checkColumns() {
0300         static_assert(is_same_any<Col1, Types...>(), "Specified Column has not been found in the table.");
0301         checkColumns<0, Cols...>();
0302       }
0303 
0304       template <int>
0305       void checkColumns() {}
0306 
0307     public:
0308       explicit TableDescription(const char* name) : m_description("ConditionDatabase") {
0309         m_description.setName(name);
0310         addColumn<0, Types...>(m_description);
0311       }
0312 
0313       // for all these methods, we should check that the specified columns belongs to the table columns...
0314       template <typename... ColumnTypes>
0315       void setPrimaryKey() {
0316         checkColumns<0, ColumnTypes...>();
0317         m_description.setPrimaryKey(makeList<ColumnTypes...>());
0318       }
0319 
0320       template <typename... ColumnTypes>
0321       void setUniqueConstraint(const std::string& name) {
0322         checkColumns<0, ColumnTypes...>();
0323         m_description.setUniqueConstraint(makeList<ColumnTypes...>(), name);
0324       }
0325 
0326       template <typename... ColumnTypes>
0327       void createIndex(const std::string& name) {
0328         checkColumns<0, ColumnTypes...>();
0329         m_description.createIndex(name, makeList<ColumnTypes...>());
0330       }
0331 
0332       template <typename Column, typename ReferencedColumn>
0333       void setForeignKey(const std::string& name) {
0334         checkColumns<0, Column>();
0335         m_description.createForeignKey(name, Column::name, ReferencedColumn::tableName(), ReferencedColumn::name);
0336       }
0337 
0338       const coral::TableDescription& get() { return m_description; }
0339 
0340     private:
0341       template <int n>
0342       void _makeList(std::vector<std::string>&) {}
0343 
0344       template <int n, typename Arg1, typename... Args>
0345       void _makeList(std::vector<std::string>& columnNames) {
0346         columnNames.push_back(Arg1::name);
0347         _makeList<n + 1, Args...>(columnNames);
0348       }
0349 
0350       template <typename... ColumnTypes>
0351       std::vector<std::string> makeList() {
0352         std::vector<std::string> columnList;
0353         _makeList<0, ColumnTypes...>(columnList);
0354         return columnList;
0355       }
0356 
0357     private:
0358       coral::TableDescription m_description;
0359     };
0360 
0361     template <typename T>
0362     struct GetFromRow {
0363       T operator()(const coral::AttributeList& row, const std::string& fullyQualifiedName) {
0364         return row[fullyQualifiedName].data<T>();
0365       }
0366     };
0367     template <>
0368     struct GetFromRow<cond::Binary> {
0369       cond::Binary operator()(const coral::AttributeList& row, const std::string& fullyQualifiedName) {
0370         return cond::Binary(row[fullyQualifiedName].data<coral::Blob>());
0371       }
0372     };
0373     template <>
0374     struct GetFromRow<boost::posix_time::ptime> {
0375       boost::posix_time::ptime operator()(const coral::AttributeList& row, const std::string& fullyQualifiedName) {
0376         return row[fullyQualifiedName].data<coral::TimeStamp>().time();
0377       }
0378     };
0379     template <>
0380     struct GetFromRow<cond::TimeType> {
0381       cond::TimeType operator()(const coral::AttributeList& row, const std::string& fullyQualifiedName) {
0382         return cond::time::timeTypeFromName(row[fullyQualifiedName].data<std::string>());
0383       }
0384     };
0385     template <>
0386     struct GetFromRow<cond::SynchronizationType> {
0387       cond::SynchronizationType operator()(const coral::AttributeList& row, const std::string& fullyQualifiedName) {
0388         return cond::synchronizationTypeFromName(row[fullyQualifiedName].data<std::string>());
0389       }
0390     };
0391     template <std::size_t n>
0392     struct GetFromRow<std::array<char, n> > {
0393       std::string operator()(const coral::AttributeList& row, const std::string& fullyQualifiedName) {
0394         std::string val = row[fullyQualifiedName].data<std::string>();
0395         if (val.size() != n)
0396           throwException("Retrieved string size does not match with the expected string size.", "getFromRow");
0397         std::array<char, n> ret;
0398         ::memcpy(ret.data(), val.c_str(), n);
0399         return ret;
0400       }
0401     };
0402 
0403     template <typename... Types>
0404     class Query;
0405 
0406     template <typename... Types>
0407     class QueryIterator {
0408     public:
0409       // C++17 compliant iterator definition
0410       using iterator_category = std::input_iterator_tag;
0411       using value_type = std::tuple<Types...>;
0412       using difference_type = void;  // Not used
0413       using pointer = void;          // Not used
0414       using reference = void;        // Not used
0415 
0416       QueryIterator() {}
0417 
0418       QueryIterator(const QueryIterator& rhs) : m_query(rhs.m_query), m_currentRow(rhs.m_currentRow) {}
0419 
0420       explicit QueryIterator(Query<Types...>* parent) : m_query(parent) {}
0421 
0422       QueryIterator& operator=(const QueryIterator& rhs) {
0423         m_query = rhs.m_query;
0424         m_currentRow = rhs.m_currentRow;
0425         return *this;
0426       }
0427 
0428       template <typename T>
0429       typename T::type get() const {
0430         return GetFromRow<typename T::type>()(*m_currentRow, T::fullyQualifiedName());
0431       }
0432 
0433       auto operator*() -> decltype(std::make_tuple(this->get<Types>()...)) { return std::make_tuple(get<Types>()...); }
0434 
0435       QueryIterator& operator++() {
0436         m_currentRow = m_query->next() ? &m_query->currentRow() : nullptr;
0437         return *this;
0438       }
0439 
0440       QueryIterator operator++(int) {
0441         QueryIterator tmp(*this);
0442         operator++();
0443         return tmp;
0444       }
0445 
0446       bool operator==(const QueryIterator& rhs) const {
0447         if (rhs.m_query == nullptr && m_query == nullptr)
0448           return true;
0449         return m_query == rhs.m_query && m_currentRow == rhs.m_currentRow;
0450       }
0451       bool operator!=(const QueryIterator& rhs) const { return !operator==(rhs); }
0452 
0453       operator bool() const { return m_currentRow; }
0454 
0455     private:
0456       Query<Types...>* m_query = nullptr;
0457       const coral::AttributeList* m_currentRow = nullptr;
0458     };
0459 
0460     template <typename T>
0461     struct DefineQueryOutput {
0462       static void make(coral::IQuery& query, const std::string& fullyQualifiedName) {
0463         query.addToOutputList(fullyQualifiedName);
0464         query.defineOutputType(fullyQualifiedName, coral::AttributeSpecification::typeNameForType<T>());
0465       }
0466     };
0467     template <>
0468     struct DefineQueryOutput<cond::Binary> {
0469       static void make(coral::IQuery& query, const std::string& fullyQualifiedName) {
0470         query.addToOutputList(fullyQualifiedName);
0471         query.defineOutputType(fullyQualifiedName, coral::AttributeSpecification::typeNameForType<coral::Blob>());
0472       }
0473     };
0474     template <>
0475     struct DefineQueryOutput<boost::posix_time::ptime> {
0476       static void make(coral::IQuery& query, const std::string& fullyQualifiedName) {
0477         query.addToOutputList(fullyQualifiedName);
0478         query.defineOutputType(fullyQualifiedName, coral::AttributeSpecification::typeNameForType<coral::TimeStamp>());
0479       }
0480     };
0481     template <>
0482     struct DefineQueryOutput<cond::TimeType> {
0483       static void make(coral::IQuery& query, const std::string& fullyQualifiedName) {
0484         query.addToOutputList(fullyQualifiedName);
0485         query.defineOutputType(fullyQualifiedName, coral::AttributeSpecification::typeNameForType<std::string>());
0486       }
0487     };
0488     template <>
0489     struct DefineQueryOutput<cond::SynchronizationType> {
0490       static void make(coral::IQuery& query, const std::string& fullyQualifiedName) {
0491         query.addToOutputList(fullyQualifiedName);
0492         query.defineOutputType(fullyQualifiedName, coral::AttributeSpecification::typeNameForType<std::string>());
0493       }
0494     };
0495     template <std::size_t n>
0496     struct DefineQueryOutput<std::array<char, n> > {
0497       static void make(coral::IQuery& query, const std::string& fullyQualifiedName) {
0498         query.addToOutputList(fullyQualifiedName);
0499         query.defineOutputType(fullyQualifiedName, coral::AttributeSpecification::typeNameForType<std::string>());
0500       }
0501     };
0502 
0503     template <typename... Types>
0504     class Query {
0505     public:
0506       Query(const coral::ISchema& schema, bool distinct = false)
0507           : m_coralQuery(schema.newQuery()), m_whereData(), m_whereClause(""), m_tables() {
0508         _Query<0, Types...>();
0509         if (distinct)
0510           m_coralQuery->setDistinct();
0511       }
0512 
0513       ~Query() {}
0514 
0515       template <typename Col>
0516       Query& addTable() {
0517         if (m_tables.find(Col::tableName()) == m_tables.end()) {
0518           m_coralQuery->addToTableList(Col::tableName());
0519           m_tables.insert(Col::tableName());
0520         }
0521         return *this;
0522       }
0523 
0524       template <int n>
0525       void _Query() {}
0526 
0527       template <int n, typename Arg1, typename... Args>
0528       void _Query() {
0529         addTable<Arg1>();
0530         DefineQueryOutput<typename Arg1::type>::make(*m_coralQuery, Arg1::fullyQualifiedName());
0531         _Query<n + 1, Args...>();
0532       }
0533 
0534       template <typename C, typename T>
0535       Query& addCondition(const T& value, const std::string condition = "=") {
0536         addTable<C>();
0537         f_add_condition_data<C>(m_whereData, m_whereClause, value, condition);
0538         return *this;
0539       }
0540 
0541       template <typename C1, typename C2>
0542       Query& addCondition(const std::string condition = "=") {
0543         addTable<C1>();
0544         addTable<C2>();
0545         f_add_condition<C1, C2>(m_whereClause, condition);
0546         return *this;
0547       }
0548 
0549       template <typename C>
0550       Query& addOrderClause(bool ascending = true) {
0551         std::string orderClause(C::fullyQualifiedName());
0552         if (!ascending)
0553           orderClause += " DESC";
0554         m_coralQuery->addToOrderList(orderClause);
0555         return *this;
0556       }
0557 
0558       Query& groupBy(const std::string& expression) {
0559         m_coralQuery->groupBy(expression);
0560         return *this;
0561       }
0562 
0563       Query& setForUpdate() {
0564         m_coralQuery->setForUpdate();
0565         return *this;
0566       }
0567 
0568       Query& limitReturnedRows(size_t nrows) {
0569         m_coralQuery->limitReturnedRows(nrows);
0570         return *this;
0571       }
0572 
0573       bool next() {
0574         if (!m_cursor)
0575           throwException("The query has not been executed.", "Query::currentRow");
0576         bool ret = m_cursor->next();
0577         if (ret)
0578           m_retrievedRows++;
0579         return ret;
0580       }
0581 
0582       const coral::AttributeList& currentRow() const {
0583         if (!m_cursor)
0584           throwException("The query has not been executed.", "Query::currentRow");
0585         return m_cursor->currentRow();
0586       }
0587 
0588       const QueryIterator<Types...> begin() {
0589         m_coralQuery->setCondition(m_whereClause, m_whereData);
0590         m_cursor = &m_coralQuery->execute();
0591         m_retrievedRows = 0;
0592         QueryIterator<Types...> ret(this);
0593         return ++ret;
0594       }
0595 
0596       const QueryIterator<Types...> end() { return QueryIterator<Types...>(this); }
0597 
0598       size_t retrievedRows() const { return m_retrievedRows; }
0599 
0600     private:
0601       std::unique_ptr<coral::IQuery> m_coralQuery;
0602       coral::ICursor* m_cursor = nullptr;
0603       size_t m_retrievedRows = 0;
0604       coral::AttributeList m_whereData;
0605       std::string m_whereClause;
0606       std::set<std::string> m_tables;
0607     };
0608 
0609     class UpdateBuffer {
0610     private:
0611       template <typename Params, int n, typename C1, typename... Cs>
0612       void _set(const Params& params) {
0613         f_add_column_data<C1>(m_data, std::get<n>(params));
0614         if (!m_setClause.empty())
0615           m_setClause += ", ";
0616         m_setClause += std::string(C1::name) + " = :" + std::string(C1::name);
0617         _set<Params, n + 1, Cs...>(params);
0618       }
0619 
0620       template <typename Params, int n>
0621       void _set(const Params&) {}
0622 
0623     public:
0624       UpdateBuffer() : m_data(), m_setClause(""), m_whereClause("") {}
0625 
0626       template <typename... Columns, typename Params>
0627       void setColumnData(const Params& params) {
0628         _set<Params, 0, Columns...>(params);
0629       }
0630 
0631       template <typename Column1, typename Column2>
0632       void setColumnMatch() {
0633         if (!m_setClause.empty())
0634           m_setClause += ", ";
0635         m_setClause += std::string(Column1::name) + " = " + std::string(Column2::name);
0636       }
0637 
0638       template <typename Column, typename P>
0639       void addWhereCondition(const P& param, const std::string condition = "=") {
0640         f_add_condition_data<Column>(m_data, m_whereClause, param, condition);
0641       }
0642 
0643       template <typename Column1, typename Column2>
0644       void addWhereCondition(const std::string condition = "=") {
0645         f_add_condition<Column1, Column2>(m_whereClause, condition);
0646       }
0647 
0648       const coral::AttributeList& get() const { return m_data; }
0649 
0650       const std::string& setClause() const { return m_setClause; }
0651 
0652       const std::string& whereClause() const { return m_whereClause; }
0653 
0654     private:
0655       coral::AttributeList m_data;
0656       std::string m_setClause;
0657       std::string m_whereClause;
0658     };
0659 
0660     class DeleteBuffer {
0661     public:
0662       DeleteBuffer() : m_data(), m_whereClause("") {}
0663 
0664       template <typename Column, typename P>
0665       void addWhereCondition(const P& param, const std::string condition = "=") {
0666         f_add_condition_data<Column>(m_data, m_whereClause, param, condition);
0667       }
0668 
0669       template <typename Column1, typename Column2>
0670       void addWhereCondition(const std::string condition = "=") {
0671         f_add_condition<Column1, Column2>(m_whereClause, condition);
0672       }
0673 
0674       const coral::AttributeList& get() const { return m_data; }
0675 
0676       const std::string& whereClause() const { return m_whereClause; }
0677 
0678     private:
0679       coral::AttributeList m_data;
0680       std::string m_whereClause;
0681     };
0682 
0683     template <typename... Types>
0684     class BulkInserter {
0685     public:
0686       static constexpr size_t cacheSize = 1000;
0687       BulkInserter(coral::ISchema& schema, const char* tableName)
0688           : m_schema(schema), m_tableName(tableName), m_buffer(), m_coralInserter() {
0689         //fix me: maybe with
0690         //m_coralInserter.reset(  schema.tableHandle( std::string(tableName ) ).dataEditor().bulkInsert( m_buffer.get(), cacheSize ) );
0691       }
0692 
0693       template <typename P>
0694       void insert(const P& params) {
0695         m_buffer.set(params);
0696         if (!m_coralInserter.get())
0697           m_coralInserter.reset(m_schema.tableHandle(m_tableName).dataEditor().bulkInsert(m_buffer.get(), cacheSize));
0698         m_coralInserter->processNextIteration();
0699       }
0700 
0701       void flush() {
0702         if (m_coralInserter.get())
0703           m_coralInserter->flush();
0704       }
0705 
0706     private:
0707       // fixme
0708       coral::ISchema& m_schema;
0709       std::string m_tableName;
0710       //
0711       RowBuffer<Types...> m_buffer;
0712       std::unique_ptr<coral::IBulkOperation> m_coralInserter;
0713     };
0714 
0715     template <typename... Types>
0716     class BulkDeleter {
0717     public:
0718       static constexpr size_t cacheSize = 1000;
0719       explicit BulkDeleter(coral::ISchema& schema, const char* tableName)
0720           : m_schema(schema), m_tableName(tableName), m_buffer(), m_coralDeleter() {
0721         //fix me: maybe with
0722         //m_coralInserter.reset(  schema.tableHandle( std::string(tableName ) ).dataEditor().bulkInsert( m_buffer.get(), cacheSize ) );
0723       }
0724 
0725       void addStaticCondition(const std::string& condition) { m_buffer.addStaticCondition(condition); }
0726 
0727       template <typename P>
0728       void erase(const P& params) {
0729         m_buffer.set(params);
0730         if (!m_coralDeleter.get())
0731           m_coralDeleter.reset(m_schema.tableHandle(m_tableName)
0732                                    .dataEditor()
0733                                    .bulkDeleteRows(m_buffer.getClause(), m_buffer.get(), cacheSize));
0734         m_coralDeleter->processNextIteration();
0735       }
0736 
0737       void flush() {
0738         if (m_coralDeleter.get())
0739           m_coralDeleter->flush();
0740       }
0741 
0742     private:
0743       // fixme
0744       coral::ISchema& m_schema;
0745       std::string m_tableName;
0746       //
0747       ConditionBuffer<Types...> m_buffer;
0748       std::unique_ptr<coral::IBulkOperation> m_coralDeleter;
0749     };
0750 
0751     namespace {
0752 
0753       inline bool existsTable(coral::ISchema& schema, const char* tableName) {
0754         return schema.existsTable(std::string(tableName));
0755       }
0756 
0757       inline void createTable(coral::ISchema& schema, const coral::TableDescription& descr) {
0758         schema.createTable(descr);
0759       }
0760 
0761       inline bool insertInTable(coral::ISchema& schema,
0762                                 const char* tableName,
0763                                 const coral::AttributeList& row,
0764                                 bool failOnDuplicate = true) {
0765         bool ret = false;
0766         try {
0767           schema.tableHandle(std::string(tableName)).dataEditor().insertRow(row);
0768           ret = true;
0769         } catch (const coral::DuplicateEntryInUniqueKeyException&) {
0770           if (failOnDuplicate)
0771             throw;
0772         }
0773         return ret;
0774       }
0775 
0776       inline void updateTable(coral::ISchema& schema, const char* tableName, const UpdateBuffer& data) {
0777         schema.tableHandle(std::string(tableName))
0778             .dataEditor()
0779             .updateRows(data.setClause(), data.whereClause(), data.get());
0780       }
0781 
0782       inline void deleteFromTable(coral::ISchema& schema, const char* tableName, const DeleteBuffer& data) {
0783         schema.tableHandle(std::string(tableName)).dataEditor().deleteRows(data.whereClause(), data.get());
0784       }
0785     }  // namespace
0786 
0787   }  // namespace persistency
0788 
0789 }  // namespace cond
0790 
0791 #endif