Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:50:23

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 : public std::iterator<std::input_iterator_tag, std::tuple<Types...> > {
0408     public:
0409       QueryIterator() {}
0410 
0411       QueryIterator(const QueryIterator& rhs) : m_query(rhs.m_query), m_currentRow(rhs.m_currentRow) {}
0412 
0413       explicit QueryIterator(Query<Types...>* parent) : m_query(parent) {}
0414 
0415       QueryIterator& operator=(const QueryIterator& rhs) {
0416         m_query = rhs.m_query;
0417         m_currentRow = rhs.m_currentRow;
0418         return *this;
0419       }
0420 
0421       template <typename T>
0422       typename T::type get() const {
0423         return GetFromRow<typename T::type>()(*m_currentRow, T::fullyQualifiedName());
0424       }
0425 
0426       auto operator*() -> decltype(std::make_tuple(this->get<Types>()...)) { return std::make_tuple(get<Types>()...); }
0427 
0428       QueryIterator& operator++() {
0429         m_currentRow = m_query->next() ? &m_query->currentRow() : nullptr;
0430         return *this;
0431       }
0432 
0433       QueryIterator operator++(int) {
0434         QueryIterator tmp(*this);
0435         operator++();
0436         return tmp;
0437       }
0438 
0439       bool operator==(const QueryIterator& rhs) const {
0440         if (rhs.m_query == nullptr && m_query == nullptr)
0441           return true;
0442         return m_query == rhs.m_query && m_currentRow == rhs.m_currentRow;
0443       }
0444       bool operator!=(const QueryIterator& rhs) const { return !operator==(rhs); }
0445 
0446       operator bool() const { return m_currentRow; }
0447 
0448     private:
0449       Query<Types...>* m_query = nullptr;
0450       const coral::AttributeList* m_currentRow = nullptr;
0451     };
0452 
0453     template <typename T>
0454     struct DefineQueryOutput {
0455       static void make(coral::IQuery& query, const std::string& fullyQualifiedName) {
0456         query.addToOutputList(fullyQualifiedName);
0457         query.defineOutputType(fullyQualifiedName, coral::AttributeSpecification::typeNameForType<T>());
0458       }
0459     };
0460     template <>
0461     struct DefineQueryOutput<cond::Binary> {
0462       static void make(coral::IQuery& query, const std::string& fullyQualifiedName) {
0463         query.addToOutputList(fullyQualifiedName);
0464         query.defineOutputType(fullyQualifiedName, coral::AttributeSpecification::typeNameForType<coral::Blob>());
0465       }
0466     };
0467     template <>
0468     struct DefineQueryOutput<boost::posix_time::ptime> {
0469       static void make(coral::IQuery& query, const std::string& fullyQualifiedName) {
0470         query.addToOutputList(fullyQualifiedName);
0471         query.defineOutputType(fullyQualifiedName, coral::AttributeSpecification::typeNameForType<coral::TimeStamp>());
0472       }
0473     };
0474     template <>
0475     struct DefineQueryOutput<cond::TimeType> {
0476       static void make(coral::IQuery& query, const std::string& fullyQualifiedName) {
0477         query.addToOutputList(fullyQualifiedName);
0478         query.defineOutputType(fullyQualifiedName, coral::AttributeSpecification::typeNameForType<std::string>());
0479       }
0480     };
0481     template <>
0482     struct DefineQueryOutput<cond::SynchronizationType> {
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 <std::size_t n>
0489     struct DefineQueryOutput<std::array<char, n> > {
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 
0496     template <typename... Types>
0497     class Query {
0498     public:
0499       Query(const coral::ISchema& schema, bool distinct = false)
0500           : m_coralQuery(schema.newQuery()), m_whereData(), m_whereClause(""), m_tables() {
0501         _Query<0, Types...>();
0502         if (distinct)
0503           m_coralQuery->setDistinct();
0504       }
0505 
0506       ~Query() {}
0507 
0508       template <typename Col>
0509       Query& addTable() {
0510         if (m_tables.find(Col::tableName()) == m_tables.end()) {
0511           m_coralQuery->addToTableList(Col::tableName());
0512           m_tables.insert(Col::tableName());
0513         }
0514         return *this;
0515       }
0516 
0517       template <int n>
0518       void _Query() {}
0519 
0520       template <int n, typename Arg1, typename... Args>
0521       void _Query() {
0522         addTable<Arg1>();
0523         DefineQueryOutput<typename Arg1::type>::make(*m_coralQuery, Arg1::fullyQualifiedName());
0524         _Query<n + 1, Args...>();
0525       }
0526 
0527       template <typename C, typename T>
0528       Query& addCondition(const T& value, const std::string condition = "=") {
0529         addTable<C>();
0530         f_add_condition_data<C>(m_whereData, m_whereClause, value, condition);
0531         return *this;
0532       }
0533 
0534       template <typename C1, typename C2>
0535       Query& addCondition(const std::string condition = "=") {
0536         addTable<C1>();
0537         addTable<C2>();
0538         f_add_condition<C1, C2>(m_whereClause, condition);
0539         return *this;
0540       }
0541 
0542       template <typename C>
0543       Query& addOrderClause(bool ascending = true) {
0544         std::string orderClause(C::fullyQualifiedName());
0545         if (!ascending)
0546           orderClause += " DESC";
0547         m_coralQuery->addToOrderList(orderClause);
0548         return *this;
0549       }
0550 
0551       Query& groupBy(const std::string& expression) {
0552         m_coralQuery->groupBy(expression);
0553         return *this;
0554       }
0555 
0556       Query& setForUpdate() {
0557         m_coralQuery->setForUpdate();
0558         return *this;
0559       }
0560 
0561       Query& limitReturnedRows(size_t nrows) {
0562         m_coralQuery->limitReturnedRows(nrows);
0563         return *this;
0564       }
0565 
0566       bool next() {
0567         if (!m_cursor)
0568           throwException("The query has not been executed.", "Query::currentRow");
0569         bool ret = m_cursor->next();
0570         if (ret)
0571           m_retrievedRows++;
0572         return ret;
0573       }
0574 
0575       const coral::AttributeList& currentRow() const {
0576         if (!m_cursor)
0577           throwException("The query has not been executed.", "Query::currentRow");
0578         return m_cursor->currentRow();
0579       }
0580 
0581       const QueryIterator<Types...> begin() {
0582         m_coralQuery->setCondition(m_whereClause, m_whereData);
0583         m_cursor = &m_coralQuery->execute();
0584         m_retrievedRows = 0;
0585         QueryIterator<Types...> ret(this);
0586         return ++ret;
0587       }
0588 
0589       const QueryIterator<Types...> end() { return QueryIterator<Types...>(this); }
0590 
0591       size_t retrievedRows() const { return m_retrievedRows; }
0592 
0593     private:
0594       std::unique_ptr<coral::IQuery> m_coralQuery;
0595       coral::ICursor* m_cursor = nullptr;
0596       size_t m_retrievedRows = 0;
0597       coral::AttributeList m_whereData;
0598       std::string m_whereClause;
0599       std::set<std::string> m_tables;
0600     };
0601 
0602     class UpdateBuffer {
0603     private:
0604       template <typename Params, int n, typename C1, typename... Cs>
0605       void _set(const Params& params) {
0606         f_add_column_data<C1>(m_data, std::get<n>(params));
0607         if (!m_setClause.empty())
0608           m_setClause += ", ";
0609         m_setClause += std::string(C1::name) + " = :" + std::string(C1::name);
0610         _set<Params, n + 1, Cs...>(params);
0611       }
0612 
0613       template <typename Params, int n>
0614       void _set(const Params&) {}
0615 
0616     public:
0617       UpdateBuffer() : m_data(), m_setClause(""), m_whereClause("") {}
0618 
0619       template <typename... Columns, typename Params>
0620       void setColumnData(const Params& params) {
0621         _set<Params, 0, Columns...>(params);
0622       }
0623 
0624       template <typename Column1, typename Column2>
0625       void setColumnMatch() {
0626         if (!m_setClause.empty())
0627           m_setClause += ", ";
0628         m_setClause += std::string(Column1::name) + " = " + std::string(Column2::name);
0629       }
0630 
0631       template <typename Column, typename P>
0632       void addWhereCondition(const P& param, const std::string condition = "=") {
0633         f_add_condition_data<Column>(m_data, m_whereClause, param, condition);
0634       }
0635 
0636       template <typename Column1, typename Column2>
0637       void addWhereCondition(const std::string condition = "=") {
0638         f_add_condition<Column1, Column2>(m_whereClause, condition);
0639       }
0640 
0641       const coral::AttributeList& get() const { return m_data; }
0642 
0643       const std::string& setClause() const { return m_setClause; }
0644 
0645       const std::string& whereClause() const { return m_whereClause; }
0646 
0647     private:
0648       coral::AttributeList m_data;
0649       std::string m_setClause;
0650       std::string m_whereClause;
0651     };
0652 
0653     class DeleteBuffer {
0654     public:
0655       DeleteBuffer() : m_data(), m_whereClause("") {}
0656 
0657       template <typename Column, typename P>
0658       void addWhereCondition(const P& param, const std::string condition = "=") {
0659         f_add_condition_data<Column>(m_data, m_whereClause, param, condition);
0660       }
0661 
0662       template <typename Column1, typename Column2>
0663       void addWhereCondition(const std::string condition = "=") {
0664         f_add_condition<Column1, Column2>(m_whereClause, condition);
0665       }
0666 
0667       const coral::AttributeList& get() const { return m_data; }
0668 
0669       const std::string& whereClause() const { return m_whereClause; }
0670 
0671     private:
0672       coral::AttributeList m_data;
0673       std::string m_whereClause;
0674     };
0675 
0676     template <typename... Types>
0677     class BulkInserter {
0678     public:
0679       static constexpr size_t cacheSize = 1000;
0680       BulkInserter(coral::ISchema& schema, const char* tableName)
0681           : m_schema(schema), m_tableName(tableName), m_buffer(), m_coralInserter() {
0682         //fix me: maybe with
0683         //m_coralInserter.reset(  schema.tableHandle( std::string(tableName ) ).dataEditor().bulkInsert( m_buffer.get(), cacheSize ) );
0684       }
0685 
0686       template <typename P>
0687       void insert(const P& params) {
0688         m_buffer.set(params);
0689         if (!m_coralInserter.get())
0690           m_coralInserter.reset(m_schema.tableHandle(m_tableName).dataEditor().bulkInsert(m_buffer.get(), cacheSize));
0691         m_coralInserter->processNextIteration();
0692       }
0693 
0694       void flush() {
0695         if (m_coralInserter.get())
0696           m_coralInserter->flush();
0697       }
0698 
0699     private:
0700       // fixme
0701       coral::ISchema& m_schema;
0702       std::string m_tableName;
0703       //
0704       RowBuffer<Types...> m_buffer;
0705       std::unique_ptr<coral::IBulkOperation> m_coralInserter;
0706     };
0707 
0708     template <typename... Types>
0709     class BulkDeleter {
0710     public:
0711       static constexpr size_t cacheSize = 1000;
0712       explicit BulkDeleter(coral::ISchema& schema, const char* tableName)
0713           : m_schema(schema), m_tableName(tableName), m_buffer(), m_coralDeleter() {
0714         //fix me: maybe with
0715         //m_coralInserter.reset(  schema.tableHandle( std::string(tableName ) ).dataEditor().bulkInsert( m_buffer.get(), cacheSize ) );
0716       }
0717 
0718       void addStaticCondition(const std::string& condition) { m_buffer.addStaticCondition(condition); }
0719 
0720       template <typename P>
0721       void erase(const P& params) {
0722         m_buffer.set(params);
0723         if (!m_coralDeleter.get())
0724           m_coralDeleter.reset(m_schema.tableHandle(m_tableName)
0725                                    .dataEditor()
0726                                    .bulkDeleteRows(m_buffer.getClause(), m_buffer.get(), cacheSize));
0727         m_coralDeleter->processNextIteration();
0728       }
0729 
0730       void flush() {
0731         if (m_coralDeleter.get())
0732           m_coralDeleter->flush();
0733       }
0734 
0735     private:
0736       // fixme
0737       coral::ISchema& m_schema;
0738       std::string m_tableName;
0739       //
0740       ConditionBuffer<Types...> m_buffer;
0741       std::unique_ptr<coral::IBulkOperation> m_coralDeleter;
0742     };
0743 
0744     namespace {
0745 
0746       inline bool existsTable(coral::ISchema& schema, const char* tableName) {
0747         return schema.existsTable(std::string(tableName));
0748       }
0749 
0750       inline void createTable(coral::ISchema& schema, const coral::TableDescription& descr) {
0751         schema.createTable(descr);
0752       }
0753 
0754       inline bool insertInTable(coral::ISchema& schema,
0755                                 const char* tableName,
0756                                 const coral::AttributeList& row,
0757                                 bool failOnDuplicate = true) {
0758         bool ret = false;
0759         try {
0760           schema.tableHandle(std::string(tableName)).dataEditor().insertRow(row);
0761           ret = true;
0762         } catch (const coral::DuplicateEntryInUniqueKeyException&) {
0763           if (failOnDuplicate)
0764             throw;
0765         }
0766         return ret;
0767       }
0768 
0769       inline void updateTable(coral::ISchema& schema, const char* tableName, const UpdateBuffer& data) {
0770         schema.tableHandle(std::string(tableName))
0771             .dataEditor()
0772             .updateRows(data.setClause(), data.whereClause(), data.get());
0773       }
0774 
0775       inline void deleteFromTable(coral::ISchema& schema, const char* tableName, const DeleteBuffer& data) {
0776         schema.tableHandle(std::string(tableName)).dataEditor().deleteRows(data.whereClause(), data.get());
0777       }
0778     }  // namespace
0779 
0780   }  // namespace persistency
0781 
0782 }  // namespace cond
0783 
0784 #endif