Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-02-11 03:07:42

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