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